Don't overwrite memory on smm init.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 7 Dec 2008 04:11:56 +0000 (23:11 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Sun, 7 Dec 2008 04:11:56 +0000 (23:11 -0500)
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
src/config.h
src/ioport.h
src/pciinit.c
src/smm.c

index 46aff4a8c695b1b47c68988fd5f2684d33796cea..c85ddf5a2ef07bc3f26fe5b643451b97b6fa6526 100644 (file)
@@ -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;
index fcfd0852d4c794120fabdeb0fc7e24bb194c622a..968b1f385e9047c1a26b149e2ed40af68af0f432 100644 (file)
@@ -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
index 633ed0ed2aefc77ac478efecabbe35a3b53565fc..cb11a3d6b2b40cee3accacdb2dc087d7be1d4eb9 100644 (file)
@@ -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
index 643e027f96e2b97899f64d9dfe8bc945c6bc45e5..6f57d688e31a5736881b36c1d0b0883605c70e9e 100644 (file)
@@ -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 */
     }
 }
index dda8d5d1374d9a943a4590a3b60b5d72a09c7940..5a79269fde74ae63fb97e3314df1b43cf0d37050 100644 (file)
--- 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 */