# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1173872306 0
# Node ID 4d7327502ba6e5776f22c80e541f9298ee0692d5
# Parent 2787228610af8b70114f60a302078797ab596b80
hvm: Add a revision 1 FADT in ACPI, and link the original revision-4
FADT only to XSDT. It avoids a buffer overflow in the initialization
of Window 2000 ACPI HAL (pre ACPI 2.0 OS), and thus enables the
installation and boot. This compatibility practice is also used in
hardware, please refer to:
http://www.acpi.info/presentations/S01USMOBS169_OS%20new.ppt
Signed-off-by: Qing He <qing.he@xxxxxxxxx>
---
tools/firmware/hvmloader/acpi/acpi2_0.h | 52 ++++++++++++++++++++++++++++++--
tools/firmware/hvmloader/acpi/build.c | 22 ++++++++++++-
2 files changed, 70 insertions(+), 4 deletions(-)
diff -r 2787228610af -r 4d7327502ba6 tools/firmware/hvmloader/acpi/acpi2_0.h
--- a/tools/firmware/hvmloader/acpi/acpi2_0.h Wed Mar 14 11:22:59 2007 +0000
+++ b/tools/firmware/hvmloader/acpi/acpi2_0.h Wed Mar 14 11:38:26 2007 +0000
@@ -143,9 +143,9 @@ struct acpi_20_tcpa {
#define ACPI_2_0_TCPA_LAML_SIZE (64*1024)
/*
- * Fixed ACPI Description Table Structure (FADT).
- */
-struct acpi_20_fadt {
+ * Fixed ACPI Description Table Structure (FADT) in ACPI 1.0.
+ */
+struct acpi_10_fadt {
struct acpi_header header;
uint32_t firmware_ctrl;
uint32_t dsdt;
@@ -185,6 +185,51 @@ struct acpi_20_fadt {
uint16_t iapc_boot_arch;
uint8_t reserved1;
uint32_t flags;
+};
+
+/*
+ * Fixed ACPI Description Table Structure (FADT).
+ */
+struct acpi_20_fadt {
+ struct acpi_header header;
+ uint32_t firmware_ctrl;
+ uint32_t dsdt;
+ uint8_t reserved0;
+ uint8_t preferred_pm_profile;
+ uint16_t sci_int;
+ uint32_t smi_cmd;
+ uint8_t acpi_enable;
+ uint8_t acpi_disable;
+ uint8_t s4bios_req;
+ uint8_t pstate_cnt;
+ uint32_t pm1a_evt_blk;
+ uint32_t pm1b_evt_blk;
+ uint32_t pm1a_cnt_blk;
+ uint32_t pm1b_cnt_blk;
+ uint32_t pm2_cnt_blk;
+ uint32_t pm_tmr_blk;
+ uint32_t gpe0_blk;
+ uint32_t gpe1_blk;
+ uint8_t pm1_evt_len;
+ uint8_t pm1_cnt_len;
+ uint8_t pm2_cnt_len;
+ uint8_t pm_tmr_len;
+ uint8_t gpe0_blk_len;
+ uint8_t gpe1_blk_len;
+ uint8_t gpe1_base;
+ uint8_t cst_cnt;
+ uint16_t p_lvl2_lat;
+ uint16_t p_lvl3_lat;
+ uint16_t flush_size;
+ uint16_t flush_stride;
+ uint8_t duty_offset;
+ uint8_t duty_width;
+ uint8_t day_alrm;
+ uint8_t mon_alrm;
+ uint8_t century;
+ uint16_t iapc_boot_arch;
+ uint8_t reserved1;
+ uint32_t flags;
struct acpi_20_generic_address reset_reg;
uint8_t reset_value;
uint8_t reserved2[3];
@@ -345,6 +390,7 @@ struct acpi_20_madt_intsrcovr {
#define ACPI_2_0_XSDT_REVISION 0x01
#define ACPI_2_0_TCPA_REVISION 0x02
#define ACPI_2_0_HPET_REVISION 0x01
+#define ACPI_1_0_FADT_REVISION 0x01
#pragma pack ()
diff -r 2787228610af -r 4d7327502ba6 tools/firmware/hvmloader/acpi/build.c
--- a/tools/firmware/hvmloader/acpi/build.c Wed Mar 14 11:22:59 2007 +0000
+++ b/tools/firmware/hvmloader/acpi/build.c Wed Mar 14 11:38:26 2007 +0000
@@ -293,6 +293,7 @@ int acpi_build_tables(uint8_t *buf)
struct acpi_20_rsdt *rsdt;
struct acpi_20_xsdt *xsdt;
struct acpi_20_fadt *fadt;
+ struct acpi_10_fadt *fadt_10;
struct acpi_20_facs *facs;
unsigned char *dsdt;
unsigned long secondary_tables[16];
@@ -305,6 +306,25 @@ int acpi_build_tables(uint8_t *buf)
dsdt = (unsigned char *)&buf[offset];
memcpy(dsdt, &AmlCode, DsdtLen);
offset += align16(DsdtLen);
+
+ /*
+ * N.B. ACPI 1.0 operating systems may not handle FADT with revision 2
+ * or above properly, notably Windows 2000, which tries to copy FADT
+ * into a 116 bytes buffer thus causing an overflow. The solution is to
+ * link the higher revision FADT with the XSDT only and introduce a
+ * compatible revision 1 FADT that is linked with the RSDT. Refer to:
+ * http://www.acpi.info/presentations/S01USMOBS169_OS%20new.ppt
+ */
+ fadt_10 = (struct acpi_10_fadt *)&buf[offset];
+ memcpy(fadt_10, &Fadt, sizeof(struct acpi_10_fadt));
+ offset += align16(sizeof(struct acpi_10_fadt));
+ fadt_10->header.length = sizeof(struct acpi_10_fadt);
+ fadt_10->header.revision = ACPI_1_0_FADT_REVISION;
+ fadt_10->dsdt = (unsigned long)dsdt;
+ fadt_10->firmware_ctrl = (unsigned long)facs;
+ set_checksum(fadt_10,
+ offsetof(struct acpi_header, checksum),
+ sizeof(struct acpi_10_fadt));
fadt = (struct acpi_20_fadt *)&buf[offset];
memcpy(fadt, &Fadt, sizeof(struct acpi_20_fadt));
@@ -332,7 +352,7 @@ int acpi_build_tables(uint8_t *buf)
rsdt = (struct acpi_20_rsdt *)&buf[offset];
memcpy(rsdt, &Rsdt, sizeof(struct acpi_header));
- rsdt->entry[0] = (unsigned long)fadt;
+ rsdt->entry[0] = (unsigned long)fadt_10;
for ( i = 0; secondary_tables[i]; i++ )
rsdt->entry[i+1] = secondary_tables[i];
rsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint32_t);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|