/** Internal function to add IO write opcode to the table. @param Marker The variable argument list to get the opcode and associated attributes. @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. @retval EFI_SUCCESS Opcode is added. **/ EFI_STATUS BootScriptWriteIoWrite ( IN VA_LIST Marker ) { S3_BOOT_SCRIPT_LIB_WIDTH Width; UINT64 Address; UINTN Count; UINT8 *Buffer; Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); Address = VA_ARG (Marker, UINT64); Count = VA_ARG (Marker, UINTN); Buffer = VA_ARG (Marker, UINT8 *); return S3BootScriptSaveIoWrite (Width, Address, Count, Buffer); }
EFI_STATUS SaveRuntimeScriptTable ( VOID ) { SMM_PCI_IO_ADDRESS PciAddress; UINT32 Data32; UINT16 Data16; UINT8 Data8; UINT8 Mask; UINTN Index; UINTN Offset; UINT8 RegTable[] = { // //Bus , Dev, Func, DMI // 0x00 , 0x00, 0x00, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x00 , 0x08, 0x00, 0x00, 0x30, 0x00, 0x00, 0xa0, // //Bus , Dev, Func, LPC device // 0x00 , 0x1F, 0x00, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x00 , 0x08, 0x00, 0x07, 0x00, 0x00, 0x90, 0x00, // //Bus , Dev, Func, PCIE device // 0x00 , 0x1C, 0x00, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0xC0 , 0x83, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, // //Bus , Dev, Func, PCIE device // 0x00 , 0x1C, 0x00, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x03 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // //Bus , Dev, Func, SATA device // 0x00 , 0x13, 0x00, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0xf4 , 0xab, 0x27, 0x10, 0xf1, 0x1d, 0x00, 0x40, // //Bus , Dev, Func, EHCI device // 0x00 , 0x1D, 0x00, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x10 , 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, // //Bus , Dev, Func, SMBUS device // 0x00 , 0x1f, 0x03, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x10 , 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // //Bus , Dev, Func, SMBUS device // 0x00 , 0x1f, 0x03, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x02 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // //Bus , Dev, Func, VGA bus1 // 0x01 , 0x00, 0x00, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x58 , 0x81, 0x18, 0x01, 0xb0, 0x00, 0x00, 0x00, // //Bus , Dev, Func, VGA bus1 // 0x01 , 0x00, 0x00, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x02 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // //Bus , Dev, Func, VGA bus1 function 1 // 0x01 , 0x00, 0x01, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x51 , 0x80, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, // //Bus , Dev, Func, VGA bus1 function 1 // 0x01 , 0x00, 0x01, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x02 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // //Bus , Dev, Func, IGD bus0 function 0 // 0x00 , 0x02, 0x00, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x42 , 0x81, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, // //Bus , Dev, Func, USB bus0 function 0 // 0x00 , 0x16, 0x00, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x32 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // //Bus , Dev, Func, HD Audio bus0 function 0 // 0x00 , 0x1B, 0x00, // //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF // 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, // //0xFF indicates the end of the table // 0xFF }; // // These registers have to set in byte order // UINT8 ExtReg[] = { 0x9E, 0x9D }; // SMRAM settings // // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM // and vital to S3 resume. That's why we put save code here // PciAddress.Bus = 0; PciAddress.Device = 0; PciAddress.Function = 0; PciAddress.ExtendedRegister = 0; for (Index = 0; Index < 2; Index++) { // // Read SRAM setting from Pci(0, 0, 0) // PciAddress.Register = ExtReg[Index]; Data8 = MmioRead8 ( MmPciAddress (0, PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register ) ); // // Save latest settings to runtime script table // S3BootScriptSavePciCfgWrite( S3BootScriptWidthUint8, *(UINT64*)&PciAddress, 1, &Data8 ); } // // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM // and vital to S3 resume. That's why we put save code here // Index = 0; while (RegTable[Index] != 0xFF) { PciAddress.Bus = RegTable[Index++]; PciAddress.Device = RegTable[Index++]; PciAddress.Function = RegTable[Index++]; PciAddress.Register = 0; PciAddress.ExtendedRegister = 0; Data16 = MmioRead16 ( MmPciAddress (0, PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register ) ); if (Data16 == 0xFFFF) { Index+=8; continue; } for (Offset = 0, Mask = 0x01; Offset < 256; Offset+=4, Mask<<=1) { if (Mask == 0x00) { Mask = 0x01; } if (RegTable[Index + Offset/32] & Mask ) { PciAddress.Register = (UINT8)Offset; Data32 = MmioRead32 (MmPciAddress (0, PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)); // // Save latest settings to runtime script table // S3BootScriptSavePciCfgWrite ( S3BootScriptWidthUint32, *(UINT64*)&PciAddress, 1, &Data32 ); } } Index += 8; } // // Save I/O ports to S3 script table // // // Selftest KBC // Data8 = 0xAA; S3BootScriptSaveIoWrite ( S3BootScriptWidthUint8, 0x64, (UINTN)1, &Data8 ); Data32 = IoRead32(mAcpiBaseAddr + R_PCH_SMI_EN); S3BootScriptSaveIoWrite ( S3BootScriptWidthUint32, (mAcpiBaseAddr + R_PCH_SMI_EN), 1, &Data32 ); // // Save B_ICH_TCO_CNT_LOCK so it will be done on S3 resume path. // Data16 = IoRead16(mAcpiBaseAddr + R_PCH_TCO_CNT); S3BootScriptSaveIoWrite ( S3BootScriptWidthUint16, mAcpiBaseAddr + R_PCH_TCO_CNT, 1, &Data16 ); return EFI_SUCCESS; }
EFI_STATUS SaveRuntimeScriptTable ( IN EFI_SMM_SYSTEM_TABLE2 *Smst ) { EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress; UINT32 Data32; UINT16 Data16; UINT8 Mask; UINTN Index; UINTN Offset; UINT16 DeviceId; // // Check what Soc we are running on (read Host bridge DeviceId) // DeviceId = QncGetSocDeviceId(); // // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM // and vital to S3 resume. That's why we put save code here // Index = 0; while (mPciCfgRegTable[Index] != PCI_DEVICE_END) { PciAddress.Bus = mPciCfgRegTable[Index++]; PciAddress.Device = mPciCfgRegTable[Index++]; PciAddress.Function = mPciCfgRegTable[Index++]; PciAddress.Register = 0; PciAddress.ExtendedRegister = 0; Data16 = PciRead16 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)); if (Data16 == 0xFFFF) { Index += 8; continue; } for (Offset = 0, Mask = 0x01; Offset < 256; Offset += 4, Mask <<= 1) { if (Mask == 0x00) { Mask = 0x01; } if (mPciCfgRegTable[Index + Offset / 32] & Mask) { PciAddress.Register = (UINT8) Offset; Data32 = PciRead32 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)); // // Save latest settings to runtime script table // S3BootScriptSavePciCfgWrite ( S3BootScriptWidthUint32, PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)), 1, &Data32 ); } } Index += 8; } // // Save message bus registers // Index = 0; while (QNCS3SaveExtReg[Index] != 0xFF) { Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]); // // Save IMR settings with IMR protection disabled initially // HMBOUND and IMRs will be locked just before jumping to the OS waking vector // if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) { if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) == QUARK_NC_MEMORY_MANAGER_IMRXL)) { Data32 &= ~IMR_LOCK; if (DeviceId == QUARK2_MC_DEVICE_ID) { Data32 &= ~IMR_EN; } } if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) >= QUARK_NC_MEMORY_MANAGER_IMRXRM)) { Data32 = (UINT32)IMRX_ALL_ACCESS; } } // // Save latest settings to runtime script table // S3BootScriptSavePciCfgWrite ( S3BootScriptWidthUint32, PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)), 1, &Data32 ); Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]); S3BootScriptSavePciCfgWrite ( S3BootScriptWidthUint32, PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)), 1, &Data32 ); Index += 2; } Index = 0; while (QNCS3SaveExtReg[Index] != 0xFF) { // // Save IMR settings with IMR protection enabled (above script was to handle restoring all settings first - now we want to enable) // if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) { if (DeviceId == QUARK2_MC_DEVICE_ID) { if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) == QUARK_NC_MEMORY_MANAGER_IMRXL)) { Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]); Data32 &= ~IMR_LOCK; // // Save latest settings to runtime script table // S3BootScriptSavePciCfgWrite ( S3BootScriptWidthUint32, PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)), 1, &Data32 ); Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]); S3BootScriptSavePciCfgWrite ( S3BootScriptWidthUint32, PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)), 1, &Data32 ); } } else { if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) >= QUARK_NC_MEMORY_MANAGER_IMRXRM)) { Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]); // // Save latest settings to runtime script table // S3BootScriptSavePciCfgWrite ( S3BootScriptWidthUint32, PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)), 1, &Data32 ); Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]); S3BootScriptSavePciCfgWrite ( S3BootScriptWidthUint32, PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)), 1, &Data32 ); } } } Index += 2; } // Check if ECC scrub enabled and need re-enabling on resume // All scrub related configuration registers are saved on suspend // as part of QNCS3SaveExtReg configuration table script. // The code below extends the S3 resume script with scrub reactivation // message (if needed only) Data32 = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG); if( 0 != (Data32 & SCRUB_CFG_ACTIVE)) { Data32 = SCRUB_RESUME_MSG(); S3BootScriptSavePciCfgWrite ( S3BootScriptWidthUint32, PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)), 1, &Data32 ); } // // Save I/O ports to S3 script table // // // Important to trap Sx for SMM // Data32 = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE); S3BootScriptSaveIoWrite(S3BootScriptWidthUint32, (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE), 1, &Data32); return EFI_SUCCESS; }