From e682cbc293d0bc6b37a80a2dadb3415d08a395cf Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sat, 6 Dec 2008 23:11:56 -0500 Subject: [PATCH] Don't overwrite memory on smm init. Save/restore memory changed during smm init - this is based on a patch committed to bochs bios. Also, clean up ioport and base memory address definitions for smm. --- src/acpi.c | 8 ++++---- src/config.h | 6 +++--- src/ioport.h | 4 ++++ src/pciinit.c | 6 ++---- src/smm.c | 37 ++++++++++++++++++++++--------------- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index 46aff4a..c85ddf5 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -365,12 +365,12 @@ void acpi_bios_init(void) fadt->reserved1 = 0; int pm_sci_int = pci_config_readb(bdf, PCI_INTERRUPT_LINE); fadt->sci_int = cpu_to_le16(pm_sci_int); - fadt->smi_cmd = cpu_to_le32(BUILD_SMI_CMD_IO_ADDR); + fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD); fadt->acpi_enable = 0xf1; fadt->acpi_disable = 0xf0; - fadt->pm1a_evt_blk = cpu_to_le32(BUILD_PM_IO_BASE); - fadt->pm1a_cnt_blk = cpu_to_le32(BUILD_PM_IO_BASE + 0x04); - fadt->pm_tmr_blk = cpu_to_le32(BUILD_PM_IO_BASE + 0x08); + fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE); + fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04); + fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08); fadt->pm1_evt_len = 4; fadt->pm1_cnt_len = 2; fadt->pm_tmr_len = 4; diff --git a/src/config.h b/src/config.h index fcfd085..968b1f3 100644 --- a/src/config.h +++ b/src/config.h @@ -93,9 +93,9 @@ // 64 KB used to copy the BIOS to shadow RAM #define BUILD_BIOS_TMP_ADDR 0x30000 -#define BUILD_PM_IO_BASE 0xb000 -#define BUILD_SMB_IO_BASE 0xb100 -#define BUILD_SMI_CMD_IO_ADDR 0xb2 +#define BUILD_SMM_INIT_ADDR 0x38000 +#define BUILD_SMM_ADDR 0xa8000 +#define BUILD_SMM_SIZE 0x8000 // Start of fixed addresses in 0xf0000 segment. #define BUILD_START_FIXED 0xe050 diff --git a/src/ioport.h b/src/ioport.h index 633ed0e..cb11a3d 100644 --- a/src/ioport.h +++ b/src/ioport.h @@ -28,6 +28,8 @@ #define PORT_A20 0x0092 #define PORT_PIC2_CMD 0x00a0 #define PORT_PIC2_DATA 0x00a1 +#define PORT_SMI_CMD 0x00b2 +#define PORT_SMI_STATUS 0x00b3 #define PORT_DMA2_MASK_REG 0x00d4 #define PORT_DMA2_MODE_REG 0x00d6 #define PORT_DMA2_MASTER_CLEAR 0x00da @@ -42,6 +44,8 @@ #define PORT_BIOS_DEBUG 0x0402 #define PORT_QEMU_CFG_CTL 0x0510 #define PORT_QEMU_CFG_DATA 0x0511 +#define PORT_ACPI_PM_BASE 0xb000 +#define PORT_SMB_BASE 0xb100 #define PORT_BIOS_APM 0x8900 // PORT_A20 bitdefs diff --git a/src/pciinit.c b/src/pciinit.c index 643e027..6f57d68 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -180,11 +180,9 @@ static void pci_bios_init_device(u16 bdf) if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) { /* PIIX4 Power Management device (for ACPI) */ - u32 pm_io_base = BUILD_PM_IO_BASE; - pci_config_writel(bdf, 0x40, pm_io_base | 1); + pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1); pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */ - u32 smb_io_base = BUILD_SMB_IO_BASE; - pci_config_writel(bdf, 0x90, smb_io_base | 1); + pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1); pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */ } } diff --git a/src/smm.c b/src/smm.c index dda8d5d..5a79269 100644 --- a/src/smm.c +++ b/src/smm.c @@ -21,33 +21,33 @@ asm( /* code to relocate SMBASE to 0xa0000 */ "smm_relocation_start:\n" - " mov $0x38000 + 0x7efc, %ebx\n" + " mov $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7efc, %ebx\n" " addr32 mov (%ebx), %al\n" /* revision ID to see if x86_64 or x86 */ " cmp $0x64, %al\n" " je 1f\n" - " mov $0x38000 + 0x7ef8, %ebx\n" + " mov $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7ef8, %ebx\n" " jmp 2f\n" "1:\n" - " mov $0x38000 + 0x7f00, %ebx\n" + " mov $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7f00, %ebx\n" "2:\n" - " movl $0xa0000, %eax\n" + " movl $" __stringify(BUILD_SMM_ADDR) " - 0x8000, %eax\n" " addr32 movl %eax, (%ebx)\n" /* indicate to the BIOS that the SMM code was executed */ " mov $0x00, %al\n" - " movw $0xb3, %dx\n" + " movw $" __stringify(PORT_SMI_STATUS) ", %dx\n" " outb %al, %dx\n" " rsm\n" "smm_relocation_end:\n" /* minimal SMM code to enable or disable ACPI */ "smm_code_start:\n" - " movw $0xb2, %dx\n" + " movw $" __stringify(PORT_SMI_CMD) ", %dx\n" " inb %dx, %al\n" " cmp $0xf0, %al\n" " jne 1f\n" /* ACPI disable */ - " mov $" __stringify(BUILD_PM_IO_BASE) " + 0x04, %dx\n" /* PMCNTRL */ + " mov $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */ " inw %dx, %ax\n" " andw $~1, %ax\n" " outw %ax, %dx\n" @@ -59,7 +59,7 @@ asm( " jne 2f\n" /* ACPI enable */ - " mov $" __stringify(BUILD_PM_IO_BASE) " + 0x04, %dx\n" /* PMCNTRL */ + " mov $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */ " inw %dx, %ax\n" " orw $1, %ax\n" " outw %ax, %dx\n" @@ -98,28 +98,35 @@ smm_init() if (value & (1 << 25)) return; + /* enable the SMM memory window */ + pci_config_writeb(i440_bdf, 0x72, 0x02 | 0x48); + + /* save original memory content */ + memcpy((void *)BUILD_SMM_ADDR, (void *)BUILD_SMM_INIT_ADDR, BUILD_SMM_SIZE); + /* copy the SMM relocation code */ - memcpy((void *)0x38000, &smm_relocation_start, + memcpy((void *)BUILD_SMM_INIT_ADDR, &smm_relocation_start, &smm_relocation_end - &smm_relocation_start); /* enable SMI generation when writing to the APMC register */ pci_config_writel(bdf, 0x58, value | (1 << 25)); /* init APM status port */ - outb(0x01, 0xb3); + outb(0x01, PORT_SMI_STATUS); /* raise an SMI interrupt */ - outb(0x00, 0xb2); + outb(0x00, PORT_SMI_CMD); /* wait until SMM code executed */ - while (inb(0xb3) != 0x00) + while (inb(PORT_SMI_STATUS) != 0x00) ; - /* enable the SMM memory window */ - pci_config_writeb(i440_bdf, 0x72, 0x02 | 0x48); + /* restore original memory content */ + memcpy((void *)BUILD_SMM_INIT_ADDR, (void *)BUILD_SMM_ADDR, BUILD_SMM_SIZE); /* copy the SMM code */ - memcpy((void *)0xa8000, &smm_code_start, &smm_code_end - &smm_code_start); + memcpy((void *)BUILD_SMM_ADDR, &smm_code_start + , &smm_code_end - &smm_code_start); wbinvd(); /* close the SMM memory window and enable normal SMM */ -- 2.25.1