Annotation of qemu/roms/seabios/src/smm.c, revision 1.1.1.4

1.1       root        1: // System Management Mode support (on emulators)
                      2: //
                      3: // Copyright (C) 2008  Kevin O'Connor <[email protected]>
                      4: // Copyright (C) 2006 Fabrice Bellard
                      5: //
                      6: // This file may be distributed under the terms of the GNU LGPLv3 license.
                      7: 
                      8: #include "pci.h" // pci_config_writel
                      9: #include "util.h" // wbinvd
                     10: #include "config.h" // CONFIG_*
                     11: #include "ioport.h" // outb
                     12: #include "pci_ids.h" // PCI_VENDOR_ID_INTEL
                     13: 
1.1.1.2   root       14: ASM32FLAT(
1.1       root       15:     ".global smm_relocation_start\n"
                     16:     ".global smm_relocation_end\n"
                     17:     ".global smm_code_start\n"
                     18:     ".global smm_code_end\n"
                     19:     "  .code16\n"
                     20: 
                     21:     /* code to relocate SMBASE to 0xa0000 */
                     22:     "smm_relocation_start:\n"
                     23:     "  mov $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7efc, %ebx\n"
                     24:     "  addr32 mov (%ebx), %al\n"  /* revision ID to see if x86_64 or x86 */
                     25:     "  cmp $0x64, %al\n"
                     26:     "  je 1f\n"
                     27:     "  mov $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7ef8, %ebx\n"
                     28:     "  jmp 2f\n"
                     29:     "1:\n"
                     30:     "  mov $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7f00, %ebx\n"
                     31:     "2:\n"
                     32:     "  movl $" __stringify(BUILD_SMM_ADDR) " - 0x8000, %eax\n"
                     33:     "  addr32 movl %eax, (%ebx)\n"
                     34:     /* indicate to the BIOS that the SMM code was executed */
                     35:     "  mov $0x00, %al\n"
                     36:     "  movw $" __stringify(PORT_SMI_STATUS) ", %dx\n"
                     37:     "  outb %al, %dx\n"
                     38:     "  rsm\n"
                     39:     "smm_relocation_end:\n"
                     40: 
                     41:     /* minimal SMM code to enable or disable ACPI */
                     42:     "smm_code_start:\n"
                     43:     "  movw $" __stringify(PORT_SMI_CMD) ", %dx\n"
                     44:     "  inb %dx, %al\n"
                     45:     "  cmp $0xf0, %al\n"
                     46:     "  jne 1f\n"
                     47: 
                     48:     /* ACPI disable */
                     49:     "  mov $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */
                     50:     "  inw %dx, %ax\n"
                     51:     "  andw $~1, %ax\n"
                     52:     "  outw %ax, %dx\n"
                     53: 
                     54:     "  jmp 2f\n"
                     55: 
                     56:     "1:\n"
                     57:     "  cmp $0xf1, %al\n"
                     58:     "  jne 2f\n"
                     59: 
                     60:     /* ACPI enable */
                     61:     "  mov $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */
                     62:     "  inw %dx, %ax\n"
                     63:     "  orw $1, %ax\n"
                     64:     "  outw %ax, %dx\n"
                     65: 
                     66:     "2:\n"
                     67:     "  rsm\n"
                     68:     "smm_code_end:\n"
                     69:     "  .code32\n"
                     70:     );
                     71: 
                     72: extern u8 smm_relocation_start, smm_relocation_end;
                     73: extern u8 smm_code_start, smm_code_end;
                     74: 
1.1.1.4 ! root       75: static void
1.1.1.3   root       76: smm_save_and_copy(void)
1.1       root       77: {
                     78:     /* save original memory content */
                     79:     memcpy((void *)BUILD_SMM_ADDR, (void *)BUILD_SMM_INIT_ADDR, BUILD_SMM_SIZE);
                     80: 
                     81:     /* copy the SMM relocation code */
                     82:     memcpy((void *)BUILD_SMM_INIT_ADDR, &smm_relocation_start,
                     83:            &smm_relocation_end - &smm_relocation_start);
1.1.1.3   root       84: }
1.1       root       85: 
1.1.1.4 ! root       86: static void
1.1.1.3   root       87: smm_relocate_and_restore(void)
                     88: {
1.1       root       89:     /* init APM status port */
                     90:     outb(0x01, PORT_SMI_STATUS);
                     91: 
                     92:     /* raise an SMI interrupt */
                     93:     outb(0x00, PORT_SMI_CMD);
                     94: 
                     95:     /* wait until SMM code executed */
                     96:     while (inb(PORT_SMI_STATUS) != 0x00)
                     97:         ;
                     98: 
                     99:     /* restore original memory content */
                    100:     memcpy((void *)BUILD_SMM_INIT_ADDR, (void *)BUILD_SMM_ADDR, BUILD_SMM_SIZE);
                    101: 
                    102:     /* copy the SMM code */
                    103:     memcpy((void *)BUILD_SMM_ADDR, &smm_code_start
                    104:            , &smm_code_end - &smm_code_start);
                    105:     wbinvd();
1.1.1.3   root      106: }
                    107: 
1.1.1.4 ! root      108: #define I440FX_SMRAM    0x72
        !           109: #define PIIX_DEVACTB    0x58
        !           110: #define PIIX_APMC_EN    (1 << 25)
        !           111: 
        !           112: // This code is hardcoded for PIIX4 Power Management device.
        !           113: static void piix4_apmc_smm_init(struct pci_device *pci, void *arg)
        !           114: {
        !           115:     struct pci_device *i440_pci = pci_find_device(PCI_VENDOR_ID_INTEL
        !           116:                                                   , PCI_DEVICE_ID_INTEL_82441);
        !           117:     if (!i440_pci)
        !           118:         return;
        !           119: 
        !           120:     /* check if SMM init is already done */
        !           121:     u32 value = pci_config_readl(pci->bdf, PIIX_DEVACTB);
        !           122:     if (value & PIIX_APMC_EN)
        !           123:         return;
        !           124: 
        !           125:     /* enable the SMM memory window */
        !           126:     pci_config_writeb(i440_pci->bdf, I440FX_SMRAM, 0x02 | 0x48);
        !           127: 
        !           128:     smm_save_and_copy();
        !           129: 
        !           130:     /* enable SMI generation when writing to the APMC register */
        !           131:     pci_config_writel(pci->bdf, PIIX_DEVACTB, value | PIIX_APMC_EN);
        !           132: 
        !           133:     smm_relocate_and_restore();
        !           134: 
        !           135:     /* close the SMM memory window and enable normal SMM */
        !           136:     pci_config_writeb(i440_pci->bdf, I440FX_SMRAM, 0x02 | 0x08);
        !           137: }
        !           138: 
1.1.1.3   root      139: static const struct pci_device_id smm_init_tbl[] = {
                    140:     PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
                    141:                piix4_apmc_smm_init),
                    142: 
                    143:     PCI_DEVICE_END,
                    144: };
                    145: 
                    146: void
                    147: smm_init(void)
                    148: {
                    149:     if (CONFIG_COREBOOT)
                    150:         // SMM only supported on emulators.
                    151:         return;
                    152:     if (!CONFIG_USE_SMM)
                    153:         return;
1.1       root      154: 
1.1.1.3   root      155:     dprintf(3, "init smm\n");
                    156:     pci_find_init_device(smm_init_tbl, NULL);
1.1       root      157: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.