--- qemu/roms/seabios/src/smm.c 2018/04/24 18:36:35 1.1.1.3 +++ qemu/roms/seabios/src/smm.c 2018/04/24 19:23:49 1.1.1.4 @@ -10,7 +10,6 @@ #include "config.h" // CONFIG_* #include "ioport.h" // outb #include "pci_ids.h" // PCI_VENDOR_ID_INTEL -#include "dev-i440fx.h" ASM32FLAT( ".global smm_relocation_start\n" @@ -73,7 +72,7 @@ ASM32FLAT( extern u8 smm_relocation_start, smm_relocation_end; extern u8 smm_code_start, smm_code_end; -void +static void smm_save_and_copy(void) { /* save original memory content */ @@ -84,7 +83,7 @@ smm_save_and_copy(void) &smm_relocation_end - &smm_relocation_start); } -void +static void smm_relocate_and_restore(void) { /* init APM status port */ @@ -106,6 +105,37 @@ smm_relocate_and_restore(void) wbinvd(); } +#define I440FX_SMRAM 0x72 +#define PIIX_DEVACTB 0x58 +#define PIIX_APMC_EN (1 << 25) + +// This code is hardcoded for PIIX4 Power Management device. +static void piix4_apmc_smm_init(struct pci_device *pci, void *arg) +{ + struct pci_device *i440_pci = pci_find_device(PCI_VENDOR_ID_INTEL + , PCI_DEVICE_ID_INTEL_82441); + if (!i440_pci) + return; + + /* check if SMM init is already done */ + u32 value = pci_config_readl(pci->bdf, PIIX_DEVACTB); + if (value & PIIX_APMC_EN) + return; + + /* enable the SMM memory window */ + pci_config_writeb(i440_pci->bdf, I440FX_SMRAM, 0x02 | 0x48); + + smm_save_and_copy(); + + /* enable SMI generation when writing to the APMC register */ + pci_config_writel(pci->bdf, PIIX_DEVACTB, value | PIIX_APMC_EN); + + smm_relocate_and_restore(); + + /* close the SMM memory window and enable normal SMM */ + pci_config_writeb(i440_pci->bdf, I440FX_SMRAM, 0x02 | 0x08); +} + static const struct pci_device_id smm_init_tbl[] = { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, piix4_apmc_smm_init),