/** Saves a PCI configuration value to the boot script. This internal worker function saves a PCI configuration value in the S3 script to be replayed on S3 resume. If the saving process fails, then ASSERT(). @param Width The width of PCI configuration. @param Address Address that encodes the PCI Bus, Device, Function and Register. @param Buffer The buffer containing value. **/ VOID InternalSavePciWriteValueToBootScript ( IN S3_BOOT_SCRIPT_LIB_WIDTH Width, IN UINTN Address, IN VOID *Buffer ) { RETURN_STATUS Status; Status = S3BootScriptSavePciCfgWrite ( Width, PCILIB_TO_COMMON_ADDRESS(Address), 1, Buffer ); ASSERT (Status == RETURN_SUCCESS); }
/** Copies the data in a caller supplied buffer to a specified range of PCI configuration space and saves the value in the S3 script to be replayed on S3 resume. Writes the range of PCI configuration registers specified by StartAddress and Size from the buffer specified by Buffer. This function only allows the PCI configuration registers from a single PCI function to be written. Size is returned. When possible 32-bit PCI configuration write cycles are used to write from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit and 16-bit PCI configuration write cycles may be used at the beginning and the end of the range. If StartAddress > 0x0FFFFFFF, then ASSERT(). If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). If Size > 0 and Buffer is NULL, then ASSERT(). @param StartAddress Starting address that encodes the PCI Bus, Device, Function and Register. @param Size Size in bytes of the transfer. @param Buffer Pointer to a buffer containing the data to write. @return Size **/ UINTN EFIAPI S3PciWriteBuffer ( IN UINTN StartAddress, IN UINTN Size, IN VOID *Buffer ) { RETURN_STATUS Status; Status = S3BootScriptSavePciCfgWrite ( S3BootScriptWidthUint8, PCILIB_TO_COMMON_ADDRESS (StartAddress), PciWriteBuffer (StartAddress, Size, Buffer), Buffer ); ASSERT (Status == RETURN_SUCCESS); return Size; }
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; }