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

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: 
                     14: ASM32(
                     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: 
                     75: void
                     76: smm_init()
                     77: {
                     78:     if (CONFIG_COREBOOT)
                     79:         // SMM only supported on emulators.
                     80:         return;
                     81:     if (!CONFIG_USE_SMM)
                     82:         return;
                     83: 
                     84:     dprintf(3, "init smm\n");
                     85: 
                     86:     // This code is hardcoded for PIIX4 Power Management device.
                     87:     int bdf = pci_find_device(PCI_VENDOR_ID_INTEL
                     88:                               , PCI_DEVICE_ID_INTEL_82371AB_3);
                     89:     if (bdf < 0)
                     90:         // Device not found
                     91:         return;
                     92:     int i440_bdf = pci_find_device(PCI_VENDOR_ID_INTEL
                     93:                                    , PCI_DEVICE_ID_INTEL_82441);
                     94:     if (i440_bdf < 0)
                     95:         return;
                     96: 
                     97:     /* check if SMM init is already done */
                     98:     u32 value = pci_config_readl(bdf, 0x58);
                     99:     if (value & (1 << 25))
                    100:         return;
                    101: 
                    102:     /* enable the SMM memory window */
                    103:     pci_config_writeb(i440_bdf, 0x72, 0x02 | 0x48);
                    104: 
                    105:     /* save original memory content */
                    106:     memcpy((void *)BUILD_SMM_ADDR, (void *)BUILD_SMM_INIT_ADDR, BUILD_SMM_SIZE);
                    107: 
                    108:     /* copy the SMM relocation code */
                    109:     memcpy((void *)BUILD_SMM_INIT_ADDR, &smm_relocation_start,
                    110:            &smm_relocation_end - &smm_relocation_start);
                    111: 
                    112:     /* enable SMI generation when writing to the APMC register */
                    113:     pci_config_writel(bdf, 0x58, value | (1 << 25));
                    114: 
                    115:     /* init APM status port */
                    116:     outb(0x01, PORT_SMI_STATUS);
                    117: 
                    118:     /* raise an SMI interrupt */
                    119:     outb(0x00, PORT_SMI_CMD);
                    120: 
                    121:     /* wait until SMM code executed */
                    122:     while (inb(PORT_SMI_STATUS) != 0x00)
                    123:         ;
                    124: 
                    125:     /* restore original memory content */
                    126:     memcpy((void *)BUILD_SMM_INIT_ADDR, (void *)BUILD_SMM_ADDR, BUILD_SMM_SIZE);
                    127: 
                    128:     /* copy the SMM code */
                    129:     memcpy((void *)BUILD_SMM_ADDR, &smm_code_start
                    130:            , &smm_code_end - &smm_code_start);
                    131:     wbinvd();
                    132: 
                    133:     /* close the SMM memory window and enable normal SMM */
                    134:     pci_config_writeb(i440_bdf, 0x72, 0x02 | 0x08);
                    135: }

unix.superglobalmegacorp.com

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