ia64/xen-unstable

changeset 14393:4d7327502ba6

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@intel.com>
author kfraser@localhost.localdomain
date Wed Mar 14 11:38:26 2007 +0000 (2007-03-14)
parents 2787228610af
children 35c9a1939ae4
files tools/firmware/hvmloader/acpi/acpi2_0.h tools/firmware/hvmloader/acpi/build.c
line diff
     1.1 --- a/tools/firmware/hvmloader/acpi/acpi2_0.h	Wed Mar 14 11:22:59 2007 +0000
     1.2 +++ b/tools/firmware/hvmloader/acpi/acpi2_0.h	Wed Mar 14 11:38:26 2007 +0000
     1.3 @@ -143,6 +143,51 @@ struct acpi_20_tcpa {
     1.4  #define ACPI_2_0_TCPA_LAML_SIZE (64*1024)
     1.5  
     1.6  /*
     1.7 + * Fixed ACPI Description Table Structure (FADT) in ACPI 1.0.
     1.8 + */
     1.9 +struct acpi_10_fadt {
    1.10 +    struct acpi_header header;
    1.11 +    uint32_t firmware_ctrl;
    1.12 +    uint32_t dsdt;
    1.13 +    uint8_t  reserved0;
    1.14 +    uint8_t  preferred_pm_profile;
    1.15 +    uint16_t sci_int;
    1.16 +    uint32_t smi_cmd;
    1.17 +    uint8_t  acpi_enable;
    1.18 +    uint8_t  acpi_disable;
    1.19 +    uint8_t  s4bios_req;
    1.20 +    uint8_t  pstate_cnt;
    1.21 +    uint32_t pm1a_evt_blk;
    1.22 +    uint32_t pm1b_evt_blk;
    1.23 +    uint32_t pm1a_cnt_blk;
    1.24 +    uint32_t pm1b_cnt_blk;
    1.25 +    uint32_t pm2_cnt_blk;
    1.26 +    uint32_t pm_tmr_blk;
    1.27 +    uint32_t gpe0_blk;
    1.28 +    uint32_t gpe1_blk;
    1.29 +    uint8_t  pm1_evt_len;
    1.30 +    uint8_t  pm1_cnt_len;
    1.31 +    uint8_t  pm2_cnt_len;
    1.32 +    uint8_t  pm_tmr_len;
    1.33 +    uint8_t  gpe0_blk_len;
    1.34 +    uint8_t  gpe1_blk_len;
    1.35 +    uint8_t  gpe1_base;
    1.36 +    uint8_t  cst_cnt;
    1.37 +    uint16_t p_lvl2_lat;
    1.38 +    uint16_t p_lvl3_lat;
    1.39 +    uint16_t flush_size;
    1.40 +    uint16_t flush_stride;
    1.41 +    uint8_t  duty_offset;
    1.42 +    uint8_t  duty_width;
    1.43 +    uint8_t  day_alrm;
    1.44 +    uint8_t  mon_alrm;
    1.45 +    uint8_t  century;
    1.46 +    uint16_t iapc_boot_arch;
    1.47 +    uint8_t  reserved1;
    1.48 +    uint32_t flags;
    1.49 +};
    1.50 +
    1.51 +/*
    1.52   * Fixed ACPI Description Table Structure (FADT).
    1.53   */
    1.54  struct acpi_20_fadt {
    1.55 @@ -345,6 +390,7 @@ struct acpi_20_madt_intsrcovr {
    1.56  #define ACPI_2_0_XSDT_REVISION 0x01
    1.57  #define ACPI_2_0_TCPA_REVISION 0x02
    1.58  #define ACPI_2_0_HPET_REVISION 0x01
    1.59 +#define ACPI_1_0_FADT_REVISION 0x01
    1.60  
    1.61  #pragma pack ()
    1.62  
     2.1 --- a/tools/firmware/hvmloader/acpi/build.c	Wed Mar 14 11:22:59 2007 +0000
     2.2 +++ b/tools/firmware/hvmloader/acpi/build.c	Wed Mar 14 11:38:26 2007 +0000
     2.3 @@ -293,6 +293,7 @@ int acpi_build_tables(uint8_t *buf)
     2.4      struct acpi_20_rsdt *rsdt;
     2.5      struct acpi_20_xsdt *xsdt;
     2.6      struct acpi_20_fadt *fadt;
     2.7 +    struct acpi_10_fadt *fadt_10;
     2.8      struct acpi_20_facs *facs;
     2.9      unsigned char       *dsdt;
    2.10      unsigned long        secondary_tables[16];
    2.11 @@ -306,6 +307,25 @@ int acpi_build_tables(uint8_t *buf)
    2.12      memcpy(dsdt, &AmlCode, DsdtLen);
    2.13      offset += align16(DsdtLen);
    2.14  
    2.15 +    /*
    2.16 +     * N.B. ACPI 1.0 operating systems may not handle FADT with revision 2
    2.17 +     * or above properly, notably Windows 2000, which tries to copy FADT
    2.18 +     * into a 116 bytes buffer thus causing an overflow. The solution is to
    2.19 +     * link the higher revision FADT with the XSDT only and introduce a
    2.20 +     * compatible revision 1 FADT that is linked with the RSDT. Refer to:
    2.21 +     *     http://www.acpi.info/presentations/S01USMOBS169_OS%20new.ppt
    2.22 +     */
    2.23 +    fadt_10 = (struct acpi_10_fadt *)&buf[offset];
    2.24 +    memcpy(fadt_10, &Fadt, sizeof(struct acpi_10_fadt));
    2.25 +    offset += align16(sizeof(struct acpi_10_fadt));
    2.26 +    fadt_10->header.length = sizeof(struct acpi_10_fadt);
    2.27 +    fadt_10->header.revision = ACPI_1_0_FADT_REVISION;
    2.28 +    fadt_10->dsdt          = (unsigned long)dsdt;
    2.29 +    fadt_10->firmware_ctrl = (unsigned long)facs;
    2.30 +    set_checksum(fadt_10,
    2.31 +                 offsetof(struct acpi_header, checksum),
    2.32 +                 sizeof(struct acpi_10_fadt));
    2.33 +
    2.34      fadt = (struct acpi_20_fadt *)&buf[offset];
    2.35      memcpy(fadt, &Fadt, sizeof(struct acpi_20_fadt));
    2.36      offset += align16(sizeof(struct acpi_20_fadt));
    2.37 @@ -332,7 +352,7 @@ int acpi_build_tables(uint8_t *buf)
    2.38  
    2.39      rsdt = (struct acpi_20_rsdt *)&buf[offset];
    2.40      memcpy(rsdt, &Rsdt, sizeof(struct acpi_header));
    2.41 -    rsdt->entry[0] = (unsigned long)fadt;
    2.42 +    rsdt->entry[0] = (unsigned long)fadt_10;
    2.43      for ( i = 0; secondary_tables[i]; i++ )
    2.44          rsdt->entry[i+1] = secondary_tables[i];
    2.45      rsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint32_t);