diff options
author | sshwarts <sshwarts> | 2008-12-04 18:40:54 +0000 |
---|---|---|
committer | sshwarts <sshwarts> | 2008-12-04 18:40:54 +0000 |
commit | 13d71d42060e230ad60dfd9eaba618761ae66443 (patch) | |
tree | 716f1ebdbb726ad41112a248b213db41dcb9d144 /bios | |
parent | f93b12cb47f9fa40c2f758cbe2653c66bc2c77dc (diff) |
Add S3 state to DSDT. Handle resume event in the BIOS.
patch by Gleb Natapov
Diffstat (limited to 'bios')
-rw-r--r-- | bios/BIOS-bochs-latest | bin | 131042 -> 131042 bytes | |||
-rw-r--r-- | bios/BIOS-bochs-legacy | bin | 65506 -> 65506 bytes | |||
-rw-r--r-- | bios/acpi-dsdt.dsl | 30 | ||||
-rw-r--r-- | bios/acpi-dsdt.hex | 17 | ||||
-rw-r--r-- | bios/rombios.c | 51 | ||||
-rw-r--r-- | bios/rombios32.c | 111 |
6 files changed, 184 insertions, 25 deletions
diff --git a/bios/BIOS-bochs-latest b/bios/BIOS-bochs-latest Binary files differindex 1aa1d74b..abadd7ff 100644 --- a/bios/BIOS-bochs-latest +++ b/bios/BIOS-bochs-latest diff --git a/bios/BIOS-bochs-legacy b/bios/BIOS-bochs-legacy Binary files differindex e3c2d5c6..24a34d59 100644 --- a/bios/BIOS-bochs-legacy +++ b/bios/BIOS-bochs-legacy diff --git a/bios/acpi-dsdt.dsl b/bios/acpi-dsdt.dsl index 19ac2f9c..280a05e8 100644 --- a/bios/acpi-dsdt.dsl +++ b/bios/acpi-dsdt.dsl @@ -531,11 +531,29 @@ DefinitionBlock ( } } - /* S5 = power off state */ - Name (_S5, Package (4) { - 0x00, // PM1a_CNT.SLP_TYP - 0x00, // PM2a_CNT.SLP_TYP - 0x00, // reserved - 0x00, // reserved + /* + * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes: + * must match piix4 emulation. + */ + Name (\_S3, Package (0x04) + { + 0x01, /* PM1a_CNT.SLP_TYP */ + 0x01, /* PM1b_CNT.SLP_TYP */ + Zero, /* reserved */ + Zero /* reserved */ + }) + Name (\_S4, Package (0x04) + { + Zero, /* PM1a_CNT.SLP_TYP */ + Zero, /* PM1b_CNT.SLP_TYP */ + Zero, /* reserved */ + Zero /* reserved */ + }) + Name (\_S5, Package (0x04) + { + Zero, /* PM1a_CNT.SLP_TYP */ + Zero, /* PM1b_CNT.SLP_TYP */ + Zero, /* reserved */ + Zero /* reserved */ }) } diff --git a/bios/acpi-dsdt.hex b/bios/acpi-dsdt.hex index 6bc6268f..6088b187 100644 --- a/bios/acpi-dsdt.hex +++ b/bios/acpi-dsdt.hex @@ -1,22 +1,22 @@ /* * * Intel ACPI Component Architecture - * ASL Optimizing Compiler version 20060912 [Nov 25 2006] + * ASL Optimizing Compiler version 20061109 [May 15 2007] * Copyright (C) 2000 - 2006 Intel Corporation * Supports ACPI Specification Revision 3.0a * - * Compilation of "acpi-dsdt.dsl" - Sun Sep 14 10:27:40 2008 + * Compilation of "acpi-dsdt.dsl" - Mon Oct 27 10:37:05 2008 * * C source code output * */ -unsigned char AmlCode[] = +const unsigned char AmlCode[] = { - 0x44,0x53,0x44,0x54,0xC9,0x07,0x00,0x00, /* 00000000 "DSDT...." */ - 0x01,0x0E,0x42,0x58,0x50,0x43,0x00,0x00, /* 00000008 "..BXPC.." */ + 0x44,0x53,0x44,0x54,0xE1,0x07,0x00,0x00, /* 00000000 "DSDT...." */ + 0x01,0x24,0x42,0x58,0x50,0x43,0x00,0x00, /* 00000008 ".$BXPC.." */ 0x42,0x58,0x44,0x53,0x44,0x54,0x00,0x00, /* 00000010 "BXDSDT.." */ 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ - 0x12,0x09,0x06,0x20,0x10,0x1C,0x5C,0x00, /* 00000020 "... ..\." */ + 0x09,0x11,0x06,0x20,0x10,0x1C,0x5C,0x00, /* 00000020 "... ..\." */ 0x5B,0x80,0x44,0x42,0x47,0x5F,0x01,0x0B, /* 00000028 "[.DBG_.." */ 0x44,0xB0,0x0A,0x04,0x5B,0x81,0x0B,0x44, /* 00000030 "D...[..D" */ 0x42,0x47,0x5F,0x03,0x44,0x42,0x47,0x4C, /* 00000038 "BG_.DBGL" */ @@ -260,6 +260,9 @@ unsigned char AmlCode[] = 0x8B,0x68,0x01,0x54,0x4D,0x50,0x5F,0x82, /* 000007A8 ".h.TMP_." */ 0x54,0x4D,0x50,0x5F,0x60,0x76,0x60,0x70, /* 000007B0 "TMP_`v`p" */ 0x60,0x50,0x52,0x51,0x33,0x08,0x5F,0x53, /* 000007B8 "`PRQ3._S" */ - 0x35,0x5F,0x12,0x06,0x04,0x00,0x00,0x00, /* 000007C0 "5_......" */ + 0x33,0x5F,0x12,0x06,0x04,0x01,0x01,0x00, /* 000007C0 "3_......" */ + 0x00,0x08,0x5F,0x53,0x34,0x5F,0x12,0x06, /* 000007C8 ".._S4_.." */ + 0x04,0x00,0x00,0x00,0x00,0x08,0x5F,0x53, /* 000007D0 "......_S" */ + 0x35,0x5F,0x12,0x06,0x04,0x00,0x00,0x00, /* 000007D8 "5_......" */ 0x00, }; diff --git a/bios/rombios.c b/bios/rombios.c index f25ebf12..f8e70e36 100644 --- a/bios/rombios.c +++ b/bios/rombios.c @@ -1917,6 +1917,11 @@ shutdown_status_panic(status) BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status); } +void s3_resume_panic() +{ + BX_PANIC("Returned from s3_resume.\n"); +} + //-------------------------------------------------------------------------- // print_bios_banner // displays a the bios version @@ -2198,6 +2203,33 @@ debugger_off() outb(0xfedc, 0x00); } +int +s3_resume() +{ + Bit32u s3_wakeup_vector; + Bit8u s3_resume_flag; + + s3_resume_flag = read_byte(0x40, 0xb0); + s3_wakeup_vector = read_dword(0x40, 0xb2); + + BX_INFO("S3 resume called %x 0x%lx\n", s3_resume_flag, s3_wakeup_vector); + if (s3_resume_flag != 0xFE || !s3_wakeup_vector) + return 0; + + write_byte(0x40, 0xb0, 0); + + /* setup wakeup vector */ + write_word(0x40, 0xb6, (s3_wakeup_vector & 0xF)); /* IP */ + write_word(0x40, 0xb8, (s3_wakeup_vector >> 4)); /* CS */ + + BX_INFO("S3 resume jump to %x:%x\n", (s3_wakeup_vector >> 4), + (s3_wakeup_vector & 0xF)); +ASM_START + jmpf [0x04b6] +ASM_END + return 1; +} + #if BX_USE_ATADRV // --------------------------------------------------------------------------- @@ -9081,6 +9113,15 @@ retf_post_0x467: mov ss, [0x469] retf +s3_post: +#if BX_ROMBIOS32 + call rombios32_init +#endif + call _s3_resume + mov bl, #0x00 + and ax, ax + jz normal_post + call _s3_resume_panic ;-------------------- eoi_both_pics: @@ -10005,6 +10046,10 @@ rombios32_05: ;; init the stack pointer mov esp, #0x00080000 + ;; pass pointer to s3_resume_flag and s3_resume_vector to rombios32 + push #0x04b0 + push #0x04b2 + ;; call rombios32 code mov eax, #0x00040000 call eax @@ -10375,6 +10420,12 @@ normal_post: mov ds, ax mov ss, ax + ;; Save shutdown status + mov 0x04b0, bl + + cmp bl, #0xfe + jz s3_post + ;; zero out BIOS data area (40:00..40:ff) mov es, ax mov cx, #0x0080 ;; 128 words diff --git a/bios/rombios32.c b/bios/rombios32.c index 762becf6..19ee2166 100644 --- a/bios/rombios32.c +++ b/bios/rombios32.c @@ -180,6 +180,20 @@ void *memmove(void *d1, const void *s1, size_t len) return d1; } +int memcmp(const void *s1, const void *s2, size_t len) +{ + const int8_t *p1 = s1; + const int8_t *p2 = s2; + + while (len--) { + int r = *p1++ - *p2++; + if(r) + return r; + } + + return 0; +} + size_t strlen(const char *s) { const char *s1; @@ -625,7 +639,7 @@ static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) return (irq_num + slot_addend) & 3; } -static int find_bios_table_area(void) +static void find_bios_table_area(void) { unsigned long addr; for(addr = 0xf0000; addr < 0x100000; addr += 16) { @@ -634,17 +648,17 @@ static int find_bios_table_area(void) bios_table_end_addr = bios_table_cur_addr + *(uint32_t *)(addr + 4); BX_INFO("bios_table_addr: 0x%08lx end=0x%08lx\n", bios_table_cur_addr, bios_table_end_addr); - return 0; + return; } } - return -1; + return; } static void bios_shadow_init(PCIDevice *d) { int v; - if (find_bios_table_area() < 0) + if (bios_table_cur_addr == 0) return; /* remap the BIOS to shadow RAM an keep it read/write while we @@ -747,6 +761,18 @@ static void smm_init(PCIDevice *d) } #endif +static void piix4_pm_enable(PCIDevice *d) +{ + /* PIIX4 Power Management device (for ACPI) */ + pci_config_writel(d, 0x40, PM_IO_BASE | 1); + pci_config_writeb(d, 0x80, 0x01); /* enable PM io space */ + pci_config_writel(d, 0x90, SMB_IO_BASE | 1); + pci_config_writeb(d, 0xd2, 0x09); /* enable SMBus io space */ +#ifdef BX_USE_SMM + smm_init(d); +#endif +} + static void pci_bios_init_device(PCIDevice *d) { int class; @@ -837,15 +863,9 @@ static void pci_bios_init_device(PCIDevice *d) if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) { /* PIIX4 Power Management device (for ACPI) */ pm_io_base = PM_IO_BASE; - pci_config_writel(d, 0x40, pm_io_base | 1); - pci_config_writeb(d, 0x80, 0x01); /* enable PM io space */ smb_io_base = SMB_IO_BASE; - pci_config_writel(d, 0x90, smb_io_base | 1); - pci_config_writeb(d, 0xd2, 0x09); /* enable SMBus io space */ pm_sci_int = pci_config_readb(d, PCI_INTERRUPT_LINE); -#ifdef BX_USE_SMM - smm_init(d); -#endif + piix4_pm_enable(d); acpi_enabled = 1; } } @@ -1460,6 +1480,7 @@ void acpi_bios_init(void) memset(facs, 0, sizeof(*facs)); memcpy(facs->signature, "FACS", 4); facs->length = cpu_to_le32(sizeof(*facs)); + BX_INFO("Firmware waking vector %p\n", &facs->firmware_waking_vector); /* DSDT */ memcpy(dsdt, AmlCode, sizeof(AmlCode)); @@ -2010,9 +2031,59 @@ void smbios_init(void) BX_INFO("SMBIOS table addr=0x%08lx\n", (unsigned long)start); } -void rombios32_init(void) +static uint32_t find_resume_vector(void) +{ + unsigned long addr, start, end; + +#ifdef BX_USE_EBDA_TABLES + start = align(ebda_cur_addr, 16); + end = 0xa000 << 4; +#else + if (bios_table_cur_addr == 0) + return 0; + start = align(bios_table_cur_addr, 16); + end = bios_table_end_addr; +#endif + + for (addr = start; addr < end; addr += 16) { + if (!memcmp((void*)addr, "RSD PTR ", 8)) { + struct rsdp_descriptor *rsdp = (void*)addr; + struct rsdt_descriptor_rev1 *rsdt = (void*)rsdp->rsdt_physical_address; + struct fadt_descriptor_rev1 *fadt = (void*)rsdt->table_offset_entry[0]; + struct facs_descriptor_rev1 *facs = (void*)fadt->firmware_ctrl; + return facs->firmware_waking_vector; + } + } + + return 0; +} + +static void find_440fx(PCIDevice *d) +{ + uint16_t vendor_id, device_id; + + vendor_id = pci_config_readw(d, PCI_VENDOR_ID); + device_id = pci_config_readw(d, PCI_DEVICE_ID); + + if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82441) + i440_pcidev = *d; +} + +static void reinit_piix4_pm(PCIDevice *d) +{ + uint16_t vendor_id, device_id; + + vendor_id = pci_config_readw(d, PCI_VENDOR_ID); + device_id = pci_config_readw(d, PCI_DEVICE_ID); + + if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) + piix4_pm_enable(d); +} + +void rombios32_init(uint32_t *s3_resume_vector, uint8_t *shutdown_flag) { BX_INFO("Starting rombios32\n"); + BX_INFO("Shutdown flag %x\n", *shutdown_flag); #ifdef BX_QEMU qemu_cfg_port = qemu_cfg_port_probe(); @@ -2024,6 +2095,22 @@ void rombios32_init(void) smp_probe(); + find_bios_table_area(); + + if (*shutdown_flag == 0xfe) { + /* redirect bios read access to RAM */ + pci_for_each_device(find_440fx); + bios_lock_shadow_ram(); /* bios is already copied */ + *s3_resume_vector = find_resume_vector(); + if (!*s3_resume_vector) { + BX_INFO("This is S3 resume but wakeup vector is NULL\n"); + } else { + BX_INFO("S3 resume vector %p\n", *s3_resume_vector); + pci_for_each_device(reinit_piix4_pm); + } + return; + } + pci_bios_init(); if (bios_table_cur_addr != 0) { |