73
74
extern u8 smm_code_start, smm_code_end;
77
smm_save_and_copy(void)
79
// SMM only supported on emulators.
84
dprintf(3, "init smm\n");
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);
92
int i440_bdf = pci_find_device(PCI_VENDOR_ID_INTEL
93
, PCI_DEVICE_ID_INTEL_82441);
97
/* check if SMM init is already done */
98
u32 value = pci_config_readl(bdf, 0x58);
99
if (value & (1 << 25))
102
/* enable the SMM memory window */
103
pci_config_writeb(i440_bdf, 0x72, 0x02 | 0x48);
105
79
/* save original memory content */
106
80
memcpy((void *)BUILD_SMM_ADDR, (void *)BUILD_SMM_INIT_ADDR, BUILD_SMM_SIZE);
108
82
/* copy the SMM relocation code */
109
83
memcpy((void *)BUILD_SMM_INIT_ADDR, &smm_relocation_start,
110
84
&smm_relocation_end - &smm_relocation_start);
112
/* enable SMI generation when writing to the APMC register */
113
pci_config_writel(bdf, 0x58, value | (1 << 25));
88
smm_relocate_and_restore(void)
115
90
/* init APM status port */
116
91
outb(0x01, PORT_SMI_STATUS);
129
104
memcpy((void *)BUILD_SMM_ADDR, &smm_code_start
130
105
, &smm_code_end - &smm_code_start);
133
/* close the SMM memory window and enable normal SMM */
134
pci_config_writeb(i440_bdf, 0x72, 0x02 | 0x08);
109
static const struct pci_device_id smm_init_tbl[] = {
110
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
111
piix4_apmc_smm_init),
120
// SMM only supported on emulators.
125
dprintf(3, "init smm\n");
126
pci_find_init_device(smm_init_tbl, NULL);