--- qemu/roms/seabios/src/dev-i440fx.c 2018/04/24 18:27:24 1.1 +++ qemu/roms/seabios/src/dev-i440fx.c 2018/04/24 18:36:41 1.1.1.2 @@ -13,9 +13,23 @@ #include "util.h" // dprintf #include "ioport.h" // outb #include "pci.h" // pci_config_writeb +#include "pci_ids.h" #include "pci_regs.h" // PCI_INTERRUPT_LINE +#include "acpi.h" #include "dev-i440fx.h" +#define I440FX_PAM0 0x59 + +void i440fx_bios_make_writable(u16 bdf, void *arg) +{ + make_bios_writable_intel(bdf, I440FX_PAM0); +} + +void i440fx_bios_make_readonly(u16 bdf, void *arg) +{ + make_bios_readonly_intel(bdf, I440FX_PAM0); +} + /* PIIX3/PIIX4 PCI to ISA bridge */ void piix_isa_bridge_init(u16 bdf, void *arg) { @@ -55,3 +69,48 @@ void piix4_pm_init(u16 bdf, void *arg) pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1); pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */ } + +#define PIIX4_ACPI_ENABLE 0xf1 +#define PIIX4_ACPI_DISABLE 0xf0 +#define PIIX4_GPE0_BLK 0xafe0 +#define PIIX4_GPE0_BLK_LEN 4 + +void piix4_fadt_init(u16 bdf, void *arg) +{ + struct fadt_descriptor_rev1 *fadt = arg; + fadt->acpi_enable = PIIX4_ACPI_ENABLE; + fadt->acpi_disable = PIIX4_ACPI_DISABLE; + fadt->gpe0_blk = cpu_to_le32(PIIX4_GPE0_BLK); + fadt->gpe0_blk_len = PIIX4_GPE0_BLK_LEN; +} + +#define I440FX_SMRAM 0x72 +#define PIIX_DEVACTB 0x58 +#define PIIX_APMC_EN (1 << 25) + +// This code is hardcoded for PIIX4 Power Management device. +void piix4_apmc_smm_init(u16 bdf, void *arg) +{ + int i440_bdf = pci_find_device(PCI_VENDOR_ID_INTEL + , PCI_DEVICE_ID_INTEL_82441); + if (i440_bdf < 0) + return; + + /* check if SMM init is already done */ + u32 value = pci_config_readl(bdf, PIIX_DEVACTB); + if (value & PIIX_APMC_EN) + return; + + /* enable the SMM memory window */ + pci_config_writeb(i440_bdf, I440FX_SMRAM, 0x02 | 0x48); + + smm_save_and_copy(); + + /* enable SMI generation when writing to the APMC register */ + pci_config_writel(bdf, PIIX_DEVACTB, value | PIIX_APMC_EN); + + smm_relocate_and_restore(); + + /* close the SMM memory window and enable normal SMM */ + pci_config_writeb(i440_bdf, I440FX_SMRAM, 0x02 | 0x08); +}