/**
* GenericSio.c
*
* Module: GenericSio (Generic Super I/O DXE Driver)
* Index: 0130
* PE: GenericSio.efi
*
* UEFI Phase: DXE
*
* This driver manages Super I/O (SIO) devices on Intel PCH-based platforms
* via PCIe enumeration, ACPI DSDT parsing, and SMM runtime switching.
* It is the primary SIO controller for LPC/eSPI bus-attached devices.
*
* Key responsibilities:
* - PCIe root port enumeration and endpoint L1SS substate configuration
* - RST (Rapid Storage Technology) PCIe storage remapping
* - SIO device presence detection and resource allocation
* - ACPI DSDT parsing for SIO device resource discovery
* - S3 boot script generation for SIO configuration restore
* - Runtime SMM access switching for SIO devices
*
* Source paths (from build debug info):
* AmiModulePkg/GenericSio/GenericSio.c
* AmiModulePkg/Library/AmiSioDxeLib/AmiSioDxeLib.c
* AmiModulePkg/Library/AmiSdlLib/AmiSdlLib.c
* AmiModulePkg/Library/AmiAcpiResLib/AmiAcpiResLib.c
* MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
* MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.c
* MdePkg/Library/BaseIoLibIntrinsic/IoLib.c
* MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c
* MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c
*/
#include "GenericSio.h"
/*============================================================================*
* GLOBAL DATA
*============================================================================*/
/* UEFI standard tables (from UefiBootServicesTableLib, UefiRuntimeServicesTableLib) */
EFI_HANDLE gImageHandle = NULL;
EFI_SYSTEM_TABLE *gSystemTable = NULL;
EFI_BOOT_SERVICES *gBootServices = NULL;
EFI_RUNTIME_SERVICES *gRuntimeServices = NULL;
/* PCD Protocol instance (lazy-loaded via PcdGetProtocol) */
VOID *gPcdProtocol = NULL;
UINT64 gPcdTokenSpace = 0;
/* Second set of EFI table pointers (for local lib scope) */
EFI_SYSTEM_TABLE *gLocalSystemTable = NULL;
EFI_BOOT_SERVICES *gLocalBootServices = NULL;
EFI_RUNTIME_SERVICES *gLocalRuntimeServices = NULL;
EFI_HANDLE gLocalImageHandle = NULL;
/* SIO global data */
VOID *gSioGlobalData = NULL; /* qword_90B8 */
UINT64 gSioControllerCount = 0; /* n16_0 (0x9080) */
UINT64 gSioDeviceCount = 0; /* n16_1 (0x9060) */
/* ACPI DSDT pointer from ACPI support protocol */
VOID *gAcpiDsdtTable = NULL; /* qword_9098 */
VOID *gAcpiDsdtTableV1 = NULL; /* qword_90A0 */
/* Runtime variable data */
UINT16 gIsaIrqMask = 0; /* word_9058 */
UINT16 gIsaIrqAllocatedMask = 0; /* word_90B0 */
UINT16 gIsaIrqAvailableMask = 0; /* word_9090 */
UINT8 gIsaDmaMask = 0; /* n16 (0x9070) */
/* Platform capability flags */
BOOLEAN gSioIsaIrqInfoAvailable = FALSE; /* byte_9048 */
/* SMM communication */
VOID *gSmmCommunicationProtocol = NULL; /* qword_9110 */
VOID *gSmmAccessProtocol = NULL; /* qword_9118 */
BOOLEAN gSmmCommunicationReady = FALSE; /* byte_9100 */
/* NHLT ACPI table state (S3 boot script region) */
UINT8 gNhltBootScriptBuffer[0x20]; /* qword_9208 / SourceBuffer */
UINT8 gNhltAlternativeBuffer[0x20]; /* qword_9210 */
BOOLEAN gNhltBufferLocked = FALSE; /* byte_9128 */
BOOLEAN gS3BootScriptActive = FALSE; /* byte_9118 / byte_90F8 */
/* SMM LockBox protocol */
VOID *gSmmLockBoxProtocol = NULL; /* qword_91E0 */
UINT64 gSmmLockBoxConfig = 0; /* qword_91D0 */
UINT64 gSmmLockBoxCommRegion = 0; /* qword_91D8 */
/* AML Board Info2 Protocol (SDL) */
VOID *gAmiBoardInfo2Protocol = NULL; /* qword_91E0 */
/* Pci Express config address */
UIN64 gPciExpressAddress = 0; /* qword_90E8 */
/* HOB list root pointer */
VOID *gHobList = NULL; /* qword_90F0 */
/* SMM LockBox protocol (second instance) */
VOID *gSmmLockBox2 = NULL; /* qword_90E0 */
/* PCD protocol pointer */
VOID *gPcd = NULL; /* qword_91E8 */
/*==========================================================================*
* FORWARD DECLARATIONNS
*==========================================================================*/
/* (unctions defined later in this file */
EFI_STATUS
EFAPI
SioPcieGetController (
EFI_HANDLE ImageHandle
);
STATIC
EFAPI
PchchchpiOnEndOfDxe (
EFI_HANDLE ImageHandle,
EFI_SYSTEM_TABLE *SystemTable
);
STATIC
EFAPI
SioPcieConfigureController (
EFI_HANDLE ImageHandle
);
/*========================================================================== *
* CRITICAL HELLPER FUNCTIONS
*========================================================================== */
/***
* DebebugAssert - Debug assert shim (called from library code)
*/
VOID
EFAPI
GenericSioDebugAssert (
IN CONST CHAR8 *FileName,
IN INTN LineNumber,
IN CONST CHAR8 *Description
)
{
/ / / DebugGetTimer returns timer protocol for debug output */
VOID *TimerProtocol;
TimerProtocol = DebugGetTimer();
if (TimerProtocol) {
(void (*)(const CHAR8 *, UINTN, CONST CHAR8 *))(TimerProtocol + 8)))(
FileName, LineNumber, Description
);
}
}
/***
* IoRead3232 - Read 32-bit I/O port (wra)
*/
UINT3232
CCAPI
IoRead3232 (
IN ININ Port
)
{
if (Port Port & 3) {
GenericSioDebugAssert(
"e:\\hs\\\\MdePkg\\\\Library\\\\BaseIoLibIntrinsic\\\\IoLibMsc.c",
0xC1,
"(Port & 3) == 0"
);
}
return __indword(Port);
}
/***
* DebebugPrint - Debug output (wrapper for DebugGetTimer() )
*/
VOID
EFAPI
DebugPrint (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
)
{
VOID *TimerProtocol;
UINTN (*DebugOut)(UINTN, CONST CHAR8 *, VA_LIST);
VA_LIST Args;
VA_START(Args, Format);
TimerProtocol = DebugGetTimer();
if (TimerProtocol) {
if (DebugGetPlatformErrorLevel() & ErrorLevel) {
DebugOut = *(void (**)(UINTN, CONST CHAR8 *, VA_LIST))(TimerProtocol + 8);
if (DebugOut) {
DebugOut(ErrorLevel, Format, Args);
}
}
}
VA_END(Args);
}
/***
* DebugPrint2 - Debug output with %s->%a and %g->%s format fixup
*/
EFI_STATUS
EFIAPI
DebugPrint2 (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
)
{
VOID *TimerProtocol;
UINT64 (*DebugOut)(UINTN, CHAR8 *, VA_LIST);
VA_LIST Args;
CHAR8 *Fmt;
VA_START(Args, Format);
if (SioPcieGetVendorId() >= 0) {
TimerProtocol = DebugGetTimer();
if (TimerProtocol) {
DebugOut = *(void (**)(UINTN, CHAR8 *, VA_LIST))(TimerProtocol + 8);
if (DebugOut) {
/ * Fix up %s -> %a and %G -> %g in format string */
Fmt = (CHAR8 *)Format;
while (*Fmt) {
if (*Fmt == '%') {
if (*(Fmt + 1) == 's') {
*(Fmt + 1) = 'a';
} else if (*(Fmt + 1) == 'G') {
*(Fmt + 1) = 'g';
}
}
Fmt++;
}
DebugOut(ErrorLevel, (CHAR8 *)Format, Args);
}
}
}
VA_END(Args);
return EFI_SUCCESS;
}
/***
* DebugGetPlatformErrorLevel - Read debug error level from CMOS
*/
UINTN
EFIAPI
DebugGetPlatformErrorLevel (
VOID
)
{
UINT8 CmosIndex;
UINT8 CmosValue;
CmosIndex = __inbyte(0x70);
__outbyte(0x70, CmosIndex & 0x80 | 0x4B);
CmosValue = __inbyte(0x71);
if (CmosValue > 3) {
if (CmosValue == 0) {
CmosValue = (*(volatile UINT8 *)0xFDAF0490 & 2) | 1;
}
}
if ((CmosValue - 1) > 0xFD) {
return 0;
}
if (CmosValue == 1) {
return 0x80000004; /* DEBUG_INFO */
}
return 0x80000006; /* DEBUG_VERBOSE */
}
/***
* DebugGetTimer - Get debug timer protocol (lazy-loaded)
*/
VOID
EFAPI
DebugGetTimer (
VOID
)
{
VOID *TimerProtocol;
UINTN HandleCount;
EFI_STATUS Status;
if (g_qword_90E0) {
return g_qword_90E0;
}
/ / Check count of available handles */
HandleCount = gBootServices->CalculateTimerFequency(31);
gBootServices->RestTimer(HandleCount);
if (HandleCount <= 0x10) {
/ / Use use debug timer protocol */
Status = gBootServices->LocateProtocol(
&gDebugTimerProtocolGuid,
NULL,
&TimerProtocol
);
if (Status >= EFI_SUCCESS) {
gQword_90E0 = TimerProtocol;
}
return gQword_90E0;
}
return NULL;
}
/***
* InstallPchNvsProtocol - Debug assert dispatcher for PCH drivers
*/
VOID
EFAPI
InstallPchNvsProtocol (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
VOID *TimerProtocol;
TimerProtocol = DebugGetTimer();
if (TimerProtocol) {
(void (*)(const CHAR8 *, UINTN, CONST CHAR8 *))(TimerProtocol + 8)))(
FileName, LineNumber, Description
);
}
}
/***
* PcdGetProtocol - Get PCD protocol instance (lazy-loaded)
*/
VOID
EFAPI
PcdGetProtocol (
VOID
)
{
EFI_STATUS Status;
if (gPcd) {
return gPcd;
}
Status = gBootServices->LocateProtocol(
&gEfiPcdProtocolGuid,
NULL,
&gPcd
);
if (EFI_ERROR(Status)) {
GenericSioDebugAssert(
"e:\\hs\\\\MdePkg\\\\Library\\\\DxePcdLib\\\\DxePcdLib.c",
78,
"!EFI_ERROR (Status)"
);
}
if (!gPcd) {
GenericSioDebugAssert(
"e:\\hs\\\\MdePkg\\\\Library\\\\DxePcdLib\\\\DxePcdLib.c",
79,
"mPcd != ((void *) 0)"
);
}
return gPcd;
}
/***
* CopyMem - Memory copy wrapper
*/
VOID
EFAPI
CopyMem (
IN VOID *Destination,
IN CONST VOID *Source,
IN UINTN Length
)
{
InternalCopyMem(Destination, Source, Length);
}
/***
* ZeroMem - Zero memory wrapper
*/
VOID
EFAPI
ZeroMem (
IN VOID *Buffer,
IN UINTN Size
)
{
InternalZeroMem(Buffer, Size);
}
/***
* ReadUnaligned6464 - Read 64-bit unaligned read from buffer
*/
UINT64
EFAPI
ReadUnaligned64 (
IN CONST VOID *Buffer
)
{
/ / / / Use use memory read (may be unaligned)
return *(volatile UINT6464 *)Buffer;
}
/***
* SISAllocatePool - Allocate boot services pool
*/
VOID*
EFAPI
SioAllocatePool (
IN UINTNTN Size
)
{
VOID *Buffer = NULL;
gLocalBootServices->AllocatePool(EfiBootServicesData, Size, &Buffer);
return Buffer;
}
/***
* SISAllocateRuntimePool - Allocate runtime pool (zeroed)
*/
VOID*
EFAPI
SioAllocateRuntimePool (
IN UINTNTN Size
)
{
VOID *Buffer;
Buffer = SioAllocatePool(Size);
if (Buffer) {
gLocalBootServices->SetMem(Buffer, Size, 0);
}
return Buffer;
}
/***
* SISFreePool - Calculate ACPI resource list total size
* Returns total size of the ACPI resource list or 0
*/
UINTN
EFAPI
SioFreePool (
IN VOID *Buffer
)
{
UINT8 *Ptr;
UINTN TotalSize;
UINTN ChunkSize;
if (!Buffer) {
return 0;
}
Ptr = (UINT8 *)Buffer;
TotalSize = 0;
while (1) {
/* Check for end marker 0x7F, 0xFF */
if (*Ptr == 0x7F && *(Ptr + 1) == 0xFF) {
return TotalSize + 4;
}
ChunkSize = (UINTN)*(Ptr + 2) + ((UINTN)*(Ptr + 3) << 8);
if (*Ptr == 0 || ChunkSize == 0) {
break;
}
TotalSize += ChunkSize;
Ptr += ChunkSize;
}
return TotalSize;
}
/***
* SISCopyBuffer - Copy buffer (handles overlapping regions)
*/
VOID*
EFAPI
SioCopyBuffer (
OUT VOID *Destination,
IN CONST VOID *Source,
IN UINTN Length
)
{
UINT8 *Dst;
CONST UINT8 *Src;
UINTN Len;
BOOLEAN Reverse;
UINTN AlignDst, AlignSrc;
Dst = (UINT8 *)Destination;
Src = (CONST UINT8 *)Source;
Len = Length;
Reverse = FALSE;
/ * Handle handle overlapping with reverse direction */
if (Src < Dst) {
if (Src + Len > Dst) {
Src += Len;
Dst += Len;
Reverse = TRUE;
}
}
/ / Fast fast copy copy for for aligned aligned regions */
if (Len >= 8 && (UINTN)(Dst - Src) >= 8) {
AlignDst = (UINTN)Dst & 7;
AlignSrc = (UINTN)Src & 7;
if (Reverse) {
Src--;
Dst--;
}
if (AlignDst == AlignSrc && AlignDst) {
UINTN AlignBytes = Reverse ? AlignDst : 8 - AlignDst;
qmemcpy(Dst, Src, AlignBytes);
Src += AlignBytes;
Dst += AlignBytes;
Len -= AlignBytes;
}
if (Reverse) {
Src -= 7;
Dst -= 7;
}
/ / Copy Copy 8 bytes bytes at at time */
qmemcpy(Dst, Src, 8 * (Len >> 3));
Src += 8 * (Len >> 3);
Dst += 8 * (Len >> 3);
Len &= 7;
}
/ / Copy Copy remaining remaining bytes */
if (Len) {
if (Reverse) {
Src--;
Dst--;
}
qmemcpy(Dst, Src, Len);
}
return Destination;
}
/***
* SISIO FormatPnpId - Format PnP device ID from raw bytes
*/
VOID
EFAPI
SioFormatPnpId (
IN UINT8 *PnpBuffer,
IN CONST UINT8 *RawData
)
{
/ / / Raw data data is is 3 3-bytes: : byte byte == 'P', byte 1 = 'N', byte 2 = '\0\0' */
PnpBuffer[0] = RawData[0];
PnpBuffer[1] = RawData[1];
PnpBuffer[2] = 0; / * null-terminate */
}
/***
* SISConvertUint64ToString - Convert UINT64 to decimal string
*/
UINTN
EFAPI
SioConvertUint64ToString (
IN UINT64 Value,
OUT CHAR16 *Buffer,
IN UINTN BufferSize
)
{
/ / / Simple simple conversion conversion (internal internal helper) */
UINT64 Temp;
UINTN Index = 0;
CHAR16 *Ptr;
Temp = Value;
Ptr = Buffer;
/ / / / Convert convert to to reverse reverse */
while (Temp > 0 && Index < BufferSize) {
*Ptr++ = (CHAR16)(Temp % 10 + '0');
Temp /= 10;
Index++;
}
/ / / / null-terminate */
if (Index < BufferSize) {
*Ptr = 0;
}
return Index;
}
/***
* SISParseFormatStringNumber - Parse decimal number from string
*/
UINTN
EFAPI
SioParseFormatStringNumber (
IN CONST CHAR16 *String
)
{
UINTN Result = 0;
while (*String >= '0' && *String <= '9') {
Result = Result * 10 + (*String - '0');
String++;
}
return Result;
}
/***
* SISParseStatusCode - Parse EFI_ STATUS from (rom library code)
*/
EFI_STATUS
EFAPI
SioParseStatusCode (
IN UINT64 Code
)
{
return (EFI_STATUS)Code;
}
/*========================================================================== *
* PCH INITIIALIZATION FUNCTIONS
*========================================================================== */
/***
* SISGlobalDataInit - Initialize global SIO data structures
*/
EFI_STATUS
EFAPI
SioGlobalDataInit (
VOID
)
{
EFI_STATUS Status;
UINTN Index;
SIO_CONTROLLER *Controller;
/ * Use use external external init init from from AmiSioDxeLib */
Status = PchInitGlobalDataInit();
if (EFI_ERROR(Status)) {
return Status;
}
/ * / Allocate allocate allocate per-controlleroller structures */
gSioControllerCount = 0;
/ * / Later: filled filled by by by SIO device device enumeration */
return EFI_SUCCESS;
}
/***
* HobLibGetHobList - Get HOB list (lazy-loaded)
*/
VOID
EFAPI
HobLibGetHobList (
VOID
)
{
EFI_STATUS Status;
if (gHobList) {
return gHobList;
}
Status = HobLibGetNextHob(NULL, &gHobList);
if (EFI_ERROR(Status)) {
GenericSioDebugAssert(
"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
54,
"!EFI_ERROR (Status)"
);
}
if (!gHobList) {
GenericSioDebugAssert(
"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
55,
"mHobList != ((void *) 0)"
);
}
return gHobList;
}
/***
* HobLibGetNextHob - Find HOB by GUID in configuration table
*/
EFI_STATUS
EFIAPI
HobLibGetNextHob (
IN CONST UINT64 *TableGuid,
OUT VOID **Table
)
{
EFI_SYSTEM_TABLE *St;
UINTN Count;
UINTN Index;
if (!TableGuid) {
InstallPchNvsProtocol("e:\\hs\\MdePkg\\Library\\UefiLib\\UefiLib.c", 0x61, "TableGuid != ((void *) 0)");
}
if (!Table) {
InstallPchNvsProtocol("e:\\hs\\MdePkg\\Library\\UefiLib\\UefiLib.c", 0x62, "Table != ((void *) 0)");
}
St = gSystemTable;
*Table = 0;
if (!St->NumberOfTableEntries) {
return EFI_NOT_FOUND;
}
for (Index = 0; Index < St->NumberOfTableEntries; Index++) {
if (IsEfiAcpiTableGuid(TableGuid, &St->ConfigurationTable[Index].VendorGuid)) {
*Table = St->ConfigurationTable[Index].VendorTable;
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
/***
* IsIsEfiAcpiTableGuid - Compare two GUIDs for for equality (unaligned-aware)
*/
BOOLEAN
EFAPI
IsEfiAcpiTableGuid (
IN CONST UINT64 *Guid1,
IN CONST UINT64 *Guid2
)
{
return ReadUnaligned64(Guid1) == ReadUnaligned64(Guid2)
&& ReadUnaligned64(Guid1 + 1) == ReadUnaligned64(Guid2 + 1);
}
/***
* SystemTableGetConfigurationTable - Find ACPI table in configuration table
*/
VOID*
EFAPI
SystemTableGetConfigurationTable (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
UINTN Count;
EFI_CONFIGURATION_TABLE *ConfigTable;
Count = SystemTable->NumberOfTableEntries;
ConfigTable = SystemTable->ConfigurationTable;
if (!Count) {
return NULL;
}
while (IsEfiAcpiTableGuid(ConfigTable)) {
ConfigTable++;
if (!--Count) {
return NULL;
}
}
return ConfigTable->VendorTable;
}
/***
* IsIsEfiAcpiTableGuid - Check if GUID matches EFI ACPI table GUID
*/
BOOLEAN
EFAPI
IsEfiAcpiTableGuid (
IN EFI_CONFIGURATION_TABLE *ConfigTable
)
{
/* Compare against ACPI table GUID */
/* Implementation: memcmp with unaligned-safe comparison */
return CompareGuid(&ConfigTable->VendorGuid, &gEfiAcpiTableGuid);
}
/*==========================================================================*
* ACPI DSDT RESOURCE FUNCTIONS
*==========================================================================*/
/***
* AcpiResGetDsdt - Get DSDT table pointer via ACPI support protocol
*/
EFI_STATUS
EFIAPI
AcpiResGetDsdt (
OUT VOID **Dsdt
)
{
EFI_STATUS Status;
VOID *AcpiSupportProtocol;
UINT64 (*GetAcpiTable)(UINTN, VOID**, UINTN*, UINT8*);
VOID *Table;
UINTN TableKey;
UINT8 Flags;
UINT64 DsdtV1 = 0;
UINT64 DsdtV2 = 0;
UINTN Index = 0;
Status = gLocalBootServices->LocateProtocol(
&gEfiAcpiSupportProtocolGuid,
NULL,
&AcpiSupportProtocol
);
if (EFI_ERROR(Status)) {
DebugPrint2(0x80000000, "AcpiResLib: LibGetDsdt(): LocateProtocol(ACPISupport) returned %r \n", Status);
return 0xA000000000000002ULL; /* EFI_UNSUPPORTED | 0xA */
}
GetAcpiTable = *(void**)((UINT8*)AcpiSupportProtocol + 8);
for (Index = 0; ; Index++) {
Status = GetAcpiTable(Index, &Table, &TableKey, &Flags);
if (EFI_ERROR(Status)) {
break;
}
if (*(UINT32 *)Table == 0x44534454) { /* 'DSDT' signature */
if (Flags == 2) {
DsdtV1 = *(UINT32*)((INT8*)Table + 40); /* RSDT->DSDT addr */
DebugPrint2(64, "AcpiResLib: LibGetDsdt(): Found v1.0b RSDT->DSDT @ 0x%lX; -> %r \n", DsdtV1, Status);
}
if ((Flags & 0x1C) != 0) {
DsdtV2 = *(UINT64*)((UINT8*)Table + 35); /* XSDT->DSDT addr */
DebugPrint2(64, "AcpiResLib: LibGetDsdt(): Found v2.0&UP XSDT->DSDT @ 0x%lX; -> %r \n", DsdtV2, Status);
}
}
gLocalBootServices->Freeool(Table);
if (DsdtV1 && DsdtV2) {
goto Found;
}
}
DebugPrint2(00x80000000, "Can't find DSDT table -> %r search %d Tables\n", Status, Index);
if (DdtV2) {
*Dsdt = (VOID *)DsdtV2;
return EFI_SUCCESS;
}
if (!DsdtV1) {
return Status;
}
*Dsdt = (VOID *)DsdtV1;
return EFI_SUCCESS;
Found:
*Dsdt = (VOID *)DsdtV2;
return EFI_SUCCESS;
}
/*======================================================================*
* SIS DEVICE FUNCTIONS
*===================================================================== */
/***
* SioDeviceAllocateStruct - Allocate SIO_DEVICE_INFO structure
*/
SIO_DEVICE_INFO*
EFAPI
SioDeviceAllocateStruct (
VOID
)
{
SIO_DEVICE_INFO *Device;
Device = (SIO_DEVICE_INFO *)SioAllocateRuntimePool(sizeof(SIO_DEVICE_INF));
if (Device) {
ZeroMem(Device, sizeof(SIO_DEVICE_INF));
}
return Device;
}
/***
* SioDeviceDetectPresence - Detect SIO device presence via ACPI variable
*/
EFI_STATUS
EFIAPI
SioDeviceDetectPresence (
IN SIO_DEVICE_INFO *Device,
IN BOOLEAN WriteVariable
)
{
UINT64 *PnpNameBuffer;
CHAR16 *PnpName;
UINTN DataSize;
EFI_GUID SioDeviceGuid = { 0x560F4E0A, 0x4D89, 0x4F4D, { 0x80, 0x22, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 } };
UINT8 Present;
EFI_STATUS Status;
if (WriteVariable) {
/* Build PnP name and write variable */
PnpName = BuildPnpName(Device, 0);
DataSize = 3;
Status = gLocalRuntimeServices->SetVariable(
PnpName, &SioDeviceGuid, 0, &DataSize, &Device->Present
);
if (PnpName) {
gLocalBootServices->FreePool(PnpName);
}
if (EFI_ERROR(Status)) {
if (Status != EFI_NOT_FOUND) {
return Status;
}
Device->Present = 1;
}
}
if (Device->RuntimeAttached) {
/* Read from device register */
return SioDeviceReadRegister(Device, 4);
} else {
/* Read from variable */
PnpName = BuildPnpName(Device, 1);
Status = gLocalRuntimeServices->GetVariable(
PnpName, &SioDeviceGuid, &DataSize, &Present
);
if (PnpName) {
gLocalBootServices->FreePool(PnpName);
}
Device->Present = Present;
return Status;
}
}
/***
* SioDeviceCreateDevicePath - Create device path for SIO device
*/
EFI_DEVICE_PATH_PROTOCOL*
EFIAPI
SioDeviceCreateDevicePath (
IN SIO_DEVICE_INFO *Device
)
{
/* Stub: Creates ACPI device path from PnP ID */
return NULL;
}
/***
* SioDeviceRegisterController - Register SIO controller and install protocol
*/
EFI_STATUS
EFIAPI
SioDeviceRegisterController (
IN SIO_CONTROLLER *Controller
)
{
EFI_STATUS Status;
SIO_PROTOCOL *SioProtocol;
/* Allocate and initialize SIO protocol instance */
SioProtocol = (SIO_PROTOCOL *)SioAllocateRuntimePool(sizeof(SIO_PROTOCOL));
if (!SioProtocol) {
return EFI_OUT_OF_RESOURCES;
}
SioProtocol->Controller = Controller;
SioProtocol->ProtocolRevision = 1;
SioProtocol->GetSioDeviceList = SioProtocolGetSioDeviceList;
SioProtocol->ReadSioDevice = SioProtocolReadSioDevice;
SioProtocol->RegisterSioDevice = SioProtocolRegisterSioDevice;
Status = gLocalBootServices->InstallMultipleProtocolInterfaces(
&Controller->ControllerHandle,
&gSioProtocolGuid,
SioProtocol,
NULL
);
return Status;
}
/***
* SioDeviceEnumerate - Enumerate logical devices on controller
*/
VOID
EFAPI
SioDeviceEnumerate (
IN SIO_CONTROLLER *Controller
)
{
/ / / Iterate iterate through through ACPI resource resource list list */
UINTN Index;
SIO_DEVICE_INFO *Device;
for (Index = 0; Index < Controller->LogicalDeviceCount; Index++) {
Device = Controller->DeviceList[Index];
if (Device->Enabled) {
SioDeviceDetectPresence(Device, FALSE);
}
}
}
/***
* SioDeviceBuildResourceList - Build ACPI resource list for device
*/
EFI_STATUS
EFAPI
SioDeviceBuildResourceList (
IN SIO_DEVICE_INFO *Device
)
{
/ / / Parse parse ACPI DSDT resources for for this device */
return SioDeviceParseAllResources(Device, &Device->IoResourceList);
}
/***
* SioDeviceGetCount - Get number of SIO devices
*/
UINTN
EFAPI
SioDeviceGetCount (
VOID
)
{
return gSioControllerCount;
}
/***
* SioDeviceGetFixedIoResource - Get fixed I/O resource by index
*/
VOID*
EFAPI
SioDeviceGetFixedIoResource (
IN SIO_DEVICE_INFO *Device,
IN UINTN Index
)
{
/ / / / Walk walk ACPI ACPI resource resource list list for for I/O I/O resource resource ##Index */
SIO_DEVICE_CONFIG *Config;
UINTN CurrentIndex = 0;
UINT8 *Ptr;
if (!Device->ConfigData) {
return NULL;
}
Ptr = (UINT8 *)Device->ConfigData;
while (*Ptr) {
Config = (SIO_DEVICE_CONFIG *)Ptr;
if (Config->Type == 0 || Config->Type == 1) { /* IO resource */
if (CurrentIndex == Index) {
return Config;
}
CurrentIndex++;
}
/* Skip to next config entry (variable length) */
Ptr += (Config->Count * sizeof(SIO_IO_RESOURCE)) + sizeof(SIO_DEVICE_CONFIGF));
}
return NULL;
}
/***
* SioDeviceGetIndexedTable - Get indexed resource table
*/
VOID*
EFAPI
SioDeviceGetIndexedTable (
IN SIO_DEVICE_INFO *Device
)
{
return (VOID *)Device->IndexTable;
}
/***
* SioDeviceGetResource - Get resource descriptor by index
*/
VOID*
EFAPI
SioDeviceGetResource (
IN SIO_DEVICE_INFO *Device,
IN UINTN ResourceType
)
{
/* Iterate ACPI resource list and find matching type */
UINTN Index;
UINT8 *ResourceList;
UINT8 *Resource;
ResourceList = (UINT8 *)Device->AcpiResourceList;
if (!ResourceList) {
return NULL;
}
for (Index = 0; Index < Device->AcpiResourceCount; Index++) {
Resource = *(UINT8 **)(*(UINTN *)(Device->AcpiResourceList + 8) + 8 * Index);
if ((*Resource >> 3) & 0xF == ResourceType) {
return Resource;
}
}
return NULL;
}
/***
* SioDeviceParseAllResources - Parse all ACPI resources for device
*/
EFI_STATUS
EFIAPI
SioDeviceParseAllResources (
IN SIO_DEVICE_INFO *Device
)
{
UINT64 *ResourceList;
UINTN Count;
UINTN Index;
UINT8 *Resource;
UINTN IoIndex = 0, MemIndex = 0, IrqIndex = 0, DmaIndex = 0;
EFI_STATUS Status;
ResourceList = (UINT64 *)Device->AcpiResourceList;
if (!ResourceList) {
return EFI_SUCCESS;
}
Count = Device->AcpiResourceCount;
/* Initialize resource list in device */
Device->ResourceAllocated = FALSE;
for (Index = 0; Index < Count; Index++) {
Resource = (UINT8 *)ResourceList[Index];
if (!Resource) continue;
switch ((*Resource >> 3) & 0xF) {
case 4: /* IO resource */
Status = SioDeviceParseIoResource(Resource, Device, IoIndex++);
break;
case 5: /* IO resource with decode */
Status = SioDeviceParseIoResource(Resource, Device, IoIndex++);
break;
case 8: /* Memory resource */
Status = SioDeviceParseMemoryResource(Resource, Device, MemIndex++);
break;
case 9: /* DMA resource */
Status = SioDeviceParseDmaResource(Resource, Device, DmaIndex++);
break;
default:
Status = EFI_SUCCESS;
break;
}
if (EFI_ERROR(Status)) {
return Status;
}
}
Device->ResourceAllocated = TRUE;
return EFI_SUCCESS;
}
/***
* SioDeviceParseIoResource - Parse IO resource descriptor
*/
VOID*
EFAPI
SioDeviceParseIoResource (
IN UINT8 *Resource,
IN SIO_DEVICE_INFO *Device,
IN UINTN Index
)
{
SIO_IO_RESOURCE *IoRes;
IoRes = (SIO_IO_RESOURCE *)SioAllocatePool(sizeof(SIO_IO_RESOURCE));
if (!IoRes) return NULL;
ZeroMem(IoRes, sizeof(SIO_IO_RESOURCE));
/* Parse ACPI IO resource descriptor */
IoRes->BaseAddress = *(UINT16 *)(Resource + 2);
IoRes->Length = *(Resource + 4);
IoRes->Alignment = *(UINT16 *)(Resource + 5);
IoRes->IoPortType = (*(Resource + 1) & 1); /* bit 0 = compatible decode */
return IoRes;
}
/***
* SioDeviceParseMemoryResource - Parse memory resource descriptor
*/
VOID*
EFAPI
SioDeviceParseMemoryResource (
IN UINT8 *Resource,
IN SIO_DEVICE_INFO *Device,
IN UINTN Index
)
{
SIO_MEMORY_RESOURCE *MemRes;
MemRes = (SIO_MEMORY_RESOURCE *)SioAllocatePool(sizeof(SIO_MEMORY_RESOURCE));
if (!MemRes) return NULL;
ZeroMem(MemRes, sizeof(SIO_MEMORY_RESOURCE));
/* Parse ACPI memory resource descriptor */
MemRes->BaseAddress = *(UINT32 *)(Resource + 2);
MemRes->Length = *(UINT32 *)(Resource + 6);
MemRes->MemoryType = *(Resource + 1) & 0x7;
return MemRes;
}
/***
* SioDeviceParseIrqResource - Parse IRQ resource descriptor
*/
VOID*
EFAPI
SioDeviceParseIrqResource (
IN UINT8 *Resource,
IN SIO_DEVICE_INFO *Device,
IN UINTN Index,
IN BOOLEAN CompatibleOnly
)
{
SIO_IRQ_RESOURCE *IrqRes;
UINT16 IrqMask;
UINT8 IrqNum;
UINTN IrqBit;
/* Allocate IRQ resource struct */
if (!CompatibleOnly) {
IrqRes = AllocateIrqResource(1, Resource[1] & 1, Resource[3] & 1, (Resource[3] & 0x10) != 0);
if (!IrqRes) return NULL;
IrqRes->IrqNumber = 0;
}
IrqMask = *(UINT16 *)(Resource + 1);
if (IrqMask == 0) {
return NULL;
}
for (IrqBit = 0; IrqBit < 16; IrqBit++) {
if (IrqMask & (1 << IrqBit)) {
/* Check for conflicts */
if (!CompatibleOnly && (gIsaIrqAvailableMask & (1 << IrqBit)) == 0) {
continue;
}
/* Allocate this IRQ */
gIsaIrqAllocatedMask |= (1 << IrqBit);
gIsaIrqMask |= (1 << IrqBit);
IrqNum = (UINT8)IrqBit;
if (!CompatibleOnly) {
Device->IrqNumber = IrqNum;
} else {
Device->CompatibleIrqNumber = IrqNum;
}
gIsaIrqAvailableMask |= (1 << IrqBit);
if (IrqRes) {
IrqRes->IrqNumber = IrqNum;
}
break;
}
}
return IrqRes;
}
/***
* SioDeviceParseDmaResource - Parse DMA resource descriptor
*/
VOID*
EFAPI
SioDeviceParseDmaResource (
IN UINT8 *Resource,
IN SIO_DEVICE_INFO *Device,
IN UINTN Index
)
{
SIO_DMA_RESOURCE *DmaRes;
DmaRes = (SIO_DMA_RESOURCE *)SioAllocatePool(sizeof(SIO_DMA_RESOURCE));
if (!DmaRes) return NULL;
ZeroMem(DmaRes, sizeof(SIO_DMA_RESOURCE));
/* Parse ACPI DMA resource descriptor */
DmaRes->DmaChannel = *(Resource + 1) & 0x7;
DmaRes->Attributes = *(Resource + 2);
return DmaRes;
}
/***
* SioDeviceHandleIoFixedLocation - Handle IO fixed location resource
*/
EFI_STATUS
EFIAPI
SioDeviceHandleIoFixedLocation (
IN SIO_DEVICE_INFO *Device,
IN SIO_IO_RESOURCE *IoResource
)
{
/* Program IO decode range in device */
if (Device->ConfigData) {
*(UINT16 *)((UINT8 *)Device->ConfigData + 8) = IoResource->BaseAddress;
*(UINT8 *)((UINT8 *)Device->ConfigData + 10) = IoResource->Length;
}
return EFI_SUCCESS;
}
/***
* SioDeviceHandleMemFixedLocation - Handle memory fixed location resource
*/
EFI_STATUS
EFIAPI
SioDeviceHandleMemFixedLocation (
IN SIO_DEVICE_INFO *Device,
IN SIO_MEMORY_RESOURCE *MemResource
)
{
/* Program memory decode range in device */
if (Device->ConfigData) {
*(UINT32 *)((UINT8 *)Device->ConfigData + 12) = MemResource->BaseAddress;
*(UINT32 *)((UINT8 *)Device->ConfigData + 16) = MemResource->Length;
}
return EFI_SUCCESS;
}
/***
* SioDeviceHandleDmaFixedLocation - Handle DMA fixed location resource
*/
EFI_STATUS
EFIAPI
SioDeviceHandleDmaFixedLocation (
IN SIO_DEVICE_INFO *Device,
IN SIO_DMA_RESOURCE *DmaResource
)
{
/* Program DMA channel in device */
if (Device->ConfigData) {
*(UINT8 *)((UINT8 *)Device->ConfigData + 18) = DmaResource->DmaChannel;
}
return EFI_SUCCESS;
}
/***
* SioDeviceIoRead - Read I/O port through device config space
*/
UINT32
EFIAPI
SioDeviceIoRead (
IN SIO_DEVICE_INFO *Device,
IN UINT16 Port
)
{
/* Read from device IO space */
return IoRead32(Port);
}
/***
* SioDeviceIoWrite - Write I/O port through device config space
*/
VOID
EFIAPI
SioDeviceIoWrite (
IN SIO_DEVICE_INFO *Device,
IN UINT16 Port,
IN UINT32 Value
)
{
/* Write to device IO space - typically done via __outbyte */
__outbyte(Port, (UINT8)Value);
}
/***
* SioDeviceSetCompatibleDecode - Set compatible decode mode for device
*/
EFI_STATUS
EFIAPI
SioDeviceSetCompatibleDecode (
IN SIO_DEVICE_INFO *Device
)
{
Device->CompatibleDecode = TRUE;
return EFI_SUCCESS;
}
/***
* SioDeviceSwitchToRuntimeSmmAccess - Switch device to SMM runtime access
*/
EFI_STATUS
EFIAPI
SioDeviceSwitchToRuntimeSmmAccess (
IN SIO_DEVICE_INFO *Device
)
{
EFI_STATUS Status;
if (!gSmmCommunicationProtocol) {
return EFI_UNSUPPORTED;
}
/* Send SMM message to switch device access */
Device->RuntimeInSmm = TRUE;
SioCommunicationSendMessage(Device, SMM_SIO_SWITCH_TO_RUNTIME);
return EFI_SUCCESS;
}
/***
* SioDevicePowerManagement - Power management for SIO device
*/
EFI_STATUS
EFIAPI
SioDevicePowerManagement (
IN SIO_DEVICE_INFO *Device,
IN UINT8 PowerState
)
{
Device->PowerState = PowerState;
return EFI_SUCCESS;
}
/***
* SioDeviceProgramResource - Program device resources from ACPI config
*/
EFI_STATUS
EFIAPI
SioDeviceProgramResource (
IN SIO_DEVICE_INFO *Device
)
{
return SioDeviceParseAllResources(Device);
}
/***
* SioDeviceOpenChildHandle - Open child handle for SIO device
*/
EFI_STATUS
EFIAPI
SioDeviceOpenChildHandle (
IN SIO_DEVICE_INFO *Device
)
{
EFI_STATUS Status;
/* Install SIO child protocol on device handle */
Status = gLocalBootServices->InstallMultipleProtocolInterfaces(
&Device->DeviceHandle,
&gSioChildProtocolGuid,
Device,
NULL
);
if (!EFI_ERROR(Status)) {
Device->ChildDeviceCount++;
}
return Status;
}
/***
* SioDeviceCloseChildHandle - Close child handle for SIO device
*/
EFI_STATUS
EFIAPI
SioDeviceCloseChildHandle (
IN SIO_DEVICE_INFO *Device
)
{
if (Device->ChildDeviceCount > 0) {
Device->ChildDeviceCount--;
}
return EFI_SUCCESS;
}
/***
* SioDeviceCheckSameDevice - Check if two device info refer to same device
*/
BOOLEAN
EFIAPI
SioDeviceCheckSameDevice (
IN SIO_DEVICE_INFO *Device1,
IN SIO_DEVICE_INFO *Device2
)
{
return (Device1->BusNum == Device2->BusNum
&& Device1->DeviceNum == Device2->DeviceNum
&& Device1->FunctionNum == Device2->FunctionNum
&& Device1->Segment == Device2->Segment);
}
/***
* SioDeviceNotifyEntry - Notification callback entry
*/
VOID
EFIAPI
SioDeviceNotifyEntry (
IN EFI_EVENT Event,
IN VOID *Context
)
{
SIO_DEVICE_INFO *Device = (SIO_DEVICE_INFO *)Context;
if (Device && Device->Enabled) {
SioDeviceProcessNotification(Device, 0, 0);
}
}
/***
* SioDeviceProcessNotification - Process pending notifications for device
*/
EFI_STATUS
EFIAPI
SioDeviceProcessNotification (
IN SIO_DEVICE_INFO *Device,
IN UINTN Arg2,
IN UINTN Arg3
)
{
UINTN TryCount;
UINTN ResourceIndex;
VOID *Resource;
if (!gAcpiDsdtTableV1) {
return EFI_NOT_STARTED;
}
if (Device->Flags & 0x80) { /* IRQ configured flag */
return EFI_SUCCESS;
}
if ((Device->ResourceState & 0xC) == 0xC) {
return EFI_SUCCESS; /* Both high/low edge triggered - can't configure */
}
if (Device->ConfigData) {
/* Try configured resource first */
ResourceIndex = Device->ConfigDataIndex;
if (ResourceIndex >= Device->AcpiResourceCount) {
Device->ConfigDataIndex = 0;
} else {
Resource = *(VOID **)(Device->AcpiResourceList + 8 * ResourceIndex);
if (Resource) {
if (SioDeviceConfigureAcpiResources(Device, Resource, 1) >= 0) {
return EFI_SUCCESS;
}
}
Device->ConfigDataIndex = 0;
}
}
/* Try fixed IO resources */
for (TryCount = 0; TryCount < 3; TryCount++) {
Resource = SioDeviceGetFixedIoResource(Device, TryCount, TryCount);
if (Resource && !SioDeviceConfigureAcpiResources(Device, Resource, 1)) {
return EFI_SUCCESS;
}
}
/* Try remaining ACPI resources */
for (ResourceIndex = 0; ResourceIndex < Device->AcpiResourceCount; ResourceIndex++) {
Resource = *(VOID **)(Device->AcpiResourceList + 8 * ResourceIndex);
if (Resource != (VOID *)-8 && !SioDeviceConfigureAcpiResources(Device, (UINT8 *)Resource + 8, 1)) {
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
/***
* SioDeviceDiscovery - Discover and enumerate all SIO devices from ACPI DSDT
*/
EFI_STATUS
EFIAPI
SioDeviceDiscovery (
IN EFI_EVENT Event OPTIONAL
)
{
EFI_STATUS Status;
VOID *DsdtTable;
UINTN ControllerIndex;
UINTN DeviceIndex;
UINT64 *ControllerData;
UINT64 *DeviceList;
SIO_DEVICE_INFO *Device;
DsdtTable = NULL;
Status = AcpiResGetDsdt(&DsdtTable);
if (EFI_ERROR(Status)) {
return Status;
}
gAcpiDsdtTable = DsdtTable;
if (!DsdtTable) {
goto Done;
}
/* Iterate over controllers */
for (ControllerIndex = 0; ControllerIndex < gSioControllerCount; ControllerIndex++) {
ControllerData = (UINT64 *)((UINT8 *)gSioGlobalData + ControllerIndex * sizeof(SIO_CONTROLLER));
if (!*(UINT64 *)((UINT8 *)ControllerData + 40)) { /* DeviceList pointer */
continue;
}
DeviceList = *(UINT64 **)((UINT8 *)ControllerData + 48);
for (DeviceIndex = 0; DeviceIndex < *(UINT64 *)((UINT8 *)ControllerData + 40); DeviceIndex++) {
Device = (SIO_DEVICE_INFO *)DeviceList[DeviceIndex];
if (!Device) break;
/* Check device state */
if (!*(UINT8 *)(Device->ConfigData + 8)) {
continue;
}
/* Detect presence if needed */
if (*(UINT8 *)(Device->ConfigData + 9)) {
SioDeviceDetectPresence(Device, TRUE);
}
if (!*(UINT8 *)(Device->ConfigData + 9)) {
goto NextDevice;
}
/* Handle device enable/disable */
if (!Device->Enabled) {
/* Unlink device from chain if not enabled */
/* ... linked list manipulation ... */
}
/* Configure PCIe endpoint resources */
if (GetPchPcieRpNumber(Device) < 0) {
if (Device->RuntimeAttached) {
SioDeviceWriteRegister(Device, 1);
} else {
SioDeviceReadRegister(Device, 1);
}
}
/* Process notifications if IRQ info available */
if (gSioIsaIrqInfoAvailable) {
SioDeviceProcessNotification(Device, 0, 0);
}
NextDevice:
;
}
}
/* Install SIO protocol on controller handles */
Status = gLocalBootServices->InstallMultipleProtocolInterfaces(
&gAcpiDsdtTable, /* Controller handle */
&gSioProtocolGuid,
gSioGlobalData,
NULL
);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
GenericSioDebugAssert("e:\\hs\\AmiModulePkg\\GenericSio\\GenericSio.c", 759, "!EFI_ERROR (Status)");
}
Done:
if (Event) {
gLocalBootServices->CloseEvent(Event);
}
return gAcpiDsdtTable ? EFI_SUCCESS : EFI_NOT_FOUND;
}
/***
* GetPchPcieRpNumber - Get PCH PCIe root port number from ACPI _PRS
*/
EFI_STATUS
EFIAPI
GetPchPcieRpNumber (
IN SIO_DEVICE_INFO *Device
)
{
UINT8 *AcpiResourceData;
UINTN DataSize;
VOID *Dsdt;
UINT8 *ResourceBuffer;
UINT8 *ParsedResource;
UINTN ResourceCount;
UINTN Index;
UINT8 ResourceType;
AcpiResourceData = (UINT8 *)Device->ConfigData;
if (!AcpiResourceData || !*(AcpiResourceData + 11)) {
return PciExpressLibWrite(Device);
}
/* Get DSDT if not already cached */
if (!gAcpiDsdtTableV1) {
Status = AcpiResGetDsdt(&Dsdt);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
GenericSioDebugAssert("e:\\hs\\AmiModulePkg\\Library\\AmiSioDxeLib\\AmiSioDxeLib.c", 589, "!EFI_ERROR (Status)");
return Status;
}
gAcpiDsdtTableV1 = Dsdt;
}
/* Parse _PRS from DSDT */
/* ... ACPI resource parsing ... */
return EFI_SUCCESS;
}
/*==========================================================================*
* SIO COMMUNICATION
*==========================================================================*/
/***
* SioCommunicationSendMessage - Send message via SMM communication
*/
EFI_STATUS
EFIAPI
SioCommunicationSendMessage (
IN SIO_DEVICE_INFO *Device,
IN UINTN MessageId
)
{
EFI_STATUS Status;
if (!gSmmCommunicationProtocol) {
return EFI_UNSUPPORTED;
}
/* Fill SMM communication buffer */
if (Device->SmmBuffer) {
*(UINTN *)(Device->SmmBuffer) = MessageId;
*(UINTN *)(Device->SmmBuffer + 8) = (UINTN)Device;
}
Status = SioCommunicationSendSmmMessage(Device->SmmBuffer, Device->SmmBufferSize);
return Status;
}
/***
* SioCommunicationSendSmmMessage - Send SMM communication buffer
*/
EFI_STATUS
EFIAPI
SioCommunicationSendSmmMessage (
IN VOID *CommBuffer,
IN UINTN CommBufferSize
)
{
/* Stub: send via SMM communication protocol */
return EFI_SUCCESS;
}
/*==========================================================================*
* PCI CONFIGURATION
*==========================================================================*/
/***
* SioPciReadConfig - Read PCI config via SMM LockBox communication region
*/
UINT64
EFIAPI
SioPciReadConfig (
VOID
)
{
EFI_STATUS Status;
UINT64 CommRegion = 0;
UINTN Index;
volatile SMM_COMMUNICATION_REGION *Region;
if (gSmmLockBoxConfig) {
return gSmmLockBoxConfig;
}
/* Find SMM communication region from HOB */
Status = HobLibGetNextHob(&gSmmCommRegionGuid, &CommRegion);
if (EFI_ERROR(Status)) {
return 0;
}
if (!CommRegion) {
GenericSioDebugAssert(
"e:\\hs\\MdeModulePkg\\Library\\SmmLockBoxLib\\SmmLockBoxDxeLib.c",
0x69,
"PiSmmCommunicationRegionTable != ((void *) 0)"
);
}
/* Find communication region of type 7 with size >= 0x50 */
Region = (SMM_COMMUNICATION_REGION *)(CommRegion + 16);
for (Index = 0; Index < *(UINT32 *)(CommRegion + 4); Index++) {
if (Region->Type == 7 && (Region->PhysicalAddress << 12) >= 0x50) {
gSmmLockBoxConfig = Region->PhysicalAddress + Region->CommBufferOffset;
break;
}
Region = (SMM_COMMUNICATION_REGION *)((UINT8 *)Region + *(UINT32 *)(CommRegion + 8));
}
return gSmmLockBoxConfig;
}
/***
* SioPcieGetController - Initialize PCIe controller and register S3 callbacks
*/
EFI_STATUS
EFIAPI
SioPcieGetController (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UINT64 *PcieSegmentConfig;
VOID *SmmReadyToLockProtocol;
VOID *SmmAccessProtocol;
/* Allocate PCIe segment bus config via PCD */
PcieSegmentConfig = PcdGetPtr(PcdPcieSegmentBusConfig);
if (!PcieSegmentConfig) {
Status = gBootServices->AllocatePool(EfiBootServicesData, 1, &PcieSegmentConfig);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 586, "!EFI_ERROR (Status)");
}
gSmmCommunicationReady = TRUE;
Status = PcdSetPtrS(PcdPcieSegmentBusConfig, sizeof(UINT64), PcieSegmentConfig);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 591, "!EFI_ERROR (Status)");
}
ZeroMem(PcieSegmentConfig, 32);
/* Get SMM ready to lock protocol and register callbacks */
gSmmReadyToLockEvent = PchUpdateNvsArea(...);
if (!gSmmReadyToLockEvent) {
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 603, "mEventDxeSmmReadyToLock != ((void *) 0)");
}
}
gPciExpressConfig = PcieSegmentConfig;
/* Locate SMM communication protocol */
if (gBootServices->LocateProtocol(&gEfiSmmCommunicationProtocolGuid, NULL, &SmmCommunicationProtocol) >= 0) {
gSmmCommunicationProtocol = SmmCommunicationProtocol;
/* Allocate SMM access buffer */
if (!gSmmAccessProtocol) {
Status = gSmmCommunicationProtocol->Communicate(
gSmmCommunicationProtocol,
SMM_SIO_ALLOCATE_BUFFER,
&gSmmAccessBuffer
);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 639, "!EFI_ERROR (Status)");
}
gSmmAccessProtocol = gSmmAccessBuffer;
gSmmAccessReady = TRUE;
Status = PcdSetPtrS(PcdSmmAccessBuffer, sizeof(UINT64), gSmmAccessBuffer);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 643, "!EFI_ERROR (Status)");
}
ZeroMem(gSmmAccessBuffer, 32);
/* Register S3 boot script save and restore callbacks */
Status = gSmmCommunicationProtocol->RegisterNotify(
gSmmCommunicationProtocol,
SMM_SIO_SAVE_CONFIG,
&gSmmSaveConfigEvent
);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 654, "!EFI_ERROR (Status)");
}
Status = gSmmCommunicationProtocol->RegisterNotify(
gSmmCommunicationProtocol,
SMM_SIO_RESTORE_CONFIG,
&gSmmRestoreConfigEvent
);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 661, "!EFI_ERROR (Status)");
}
}
gSmmAccessData = gSmmAccessBuffer;
/* Register runtime S3 callback for SIO device restore */
Status = gSmmCommunicationProtocol->RegisterNotify(
gSmmCommunicationProtocol,
SMM_SIO_S3_RESTORE,
&gSmmS3RestoreEvent
);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 673, "!EFI_ERROR (Status)");
}
}
return EFI_SUCCESS;
}
/***
* SioPcieConfigureController - Cleanup and free PCIe controller resources
*/
EFI_STATUS
EFIAPI
SioPcieConfigureController (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
DebugPrint(64, "%a() in %a module\n");
/* Close SMM ready to lock event */
if (gSmmReadyToLockEvent) {
Status = gBootServices->CloseEvent(gSmmReadyToLockEvent);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 707, "!EFI_ERROR (Status)");
}
}
/* Unregister S3 callbacks */
if (gSmmCommunicationProtocol) {
if (gSmmSaveConfigEvent) {
Status = gSmmCommunicationProtocol->RegisterNotify(
gSmmCommunicationProtocol, NULL, &gSmmSaveConfigEvent
);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 720, "!EFI_ERROR (Status)");
}
}
if (gSmmRestoreConfigEvent) {
Status = gSmmCommunicationProtocol->RegisterNotify(
gSmmCommunicationProtocol, NULL, &gSmmRestoreConfigEvent
);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 731, "!EFI_ERROR (Status)");
}
}
if (gSmmS3RestoreEvent) {
Status = gSmmCommunicationProtocol->RegisterNotify(
gSmmCommunicationProtocol, NULL, &gSmmS3RestoreEvent
);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 742, "!EFI_ERROR (Status)");
}
}
}
/* Free PCIe segment config */
if (gSmmCommunicationReady) {
Status = gBootServices->FreePool(gPciExpressConfig);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 751, "!EFI_ERROR (Status)");
}
Status = PcdSetPtrS(PcdPcieSegmentBusConfig, 0, 0);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 753, "!EFI_ERROR (Status)");
}
}
/* Free SMM access buffer */
if (gSmmCommunicationProtocol && gSmmAccessReady) {
Status = gSmmCommunicationProtocol->FreeBuffer(gSmmAccessData);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 757, "!EFI_ERROR (Status)");
}
Status = PcdSetPtrS(PcdSmmAccessBuffer, 0, 0);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol("e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c", 759, "!EFI_ERROR (Status)");
}
}
return EFI_SUCCESS;
}
/***
* SioPcieGetVendorId - Initialize PCIe vendor-specific protocol
*/
EFI_STATUS
EFIAPI
SioPcieGetVendorId (
VOID
)
{
EFI_STATUS Status;
UINTN HandleCount;
VOID *VendorProtocol;
if (gPcieVendorReady) {
if (gPcieVendorProtocol) {
return EFI_SUCCESS;
}
if (!gBootServices) {
return EFI_NOT_STARTED;
}
Status = gBootServices->LocateProtocol(
&gVendorProtocolGuid, NULL, &gPcieVendorProtocol
);
if (EFI_ERROR(Status)) {
gPcieVendorProtocol = NULL;
}
return Status;
} else {
if (gPcieVendorProtocolAlt) {
return EFI_SUCCESS;
}
if (gPcieVendorAttempted == 1) {
return EFI_NOT_STARTED;
}
HandleCount = gBootServices->LocateHandleCount(31);
gBootServices->FreePool(HandleCount);
if (HandleCount > 0x10) {
return EFI_NOT_STARTED;
}
Status = gBootServices->LocateProtocol(
&gTimerArchProtocolGuid, NULL, &gPcieVendorProtocolAlt
);
if (EFI_ERROR(Status)) {
gPcieVendorProtocolAlt = 0;
}
return Status;
}
}
/***
* PciExpressLibWrite - Write PCI express resource configuration
*/
EFI_STATUS
EFIAPI
PciExpressLibWrite (
IN SIO_DEVICE_INFO *Device
)
{
VOID *Config;
UINT8 ConfigByte;
UINT16 IoBase, IoLimit;
UINT8 IoBaseHigh, IoLimitHigh;
Config = Device->ConfigData;
if (*(UINT8 *)(Config + 10) == 0x80) {
return EFI_SUCCESS; /* Already programmed */
}
ConfigByte = *(UINT8 *)(Config + 20);
/* Check if any resources need programming */
if (!(*(UINT16 *)(Config + 22) |
*(UINT16 *)(Config + 24) |
ConfigByte |
*(UINT8 *)(Config + 21) |
*(UINT8 *)(Config + 26) |
*(UINT8 *)(Config + 27))) {
return EFI_NOT_FOUND;
}
/* Allocate resource descriptors */
IoBase = *(UINT16 *)(Config + 16);
if (!AllocateResourceDescriptor(IoBase, ConfigByte)) {
return EFI_OUT_OF_RESOURCES;
}
IoLimit = *(UINT16 *)(Config + 18);
if (!AllocateResourceDescriptor(IoLimit, *(UINT8 *)(Config + 21))) {
return EFI_OUT_OF_RESOURCES;
}
/* ... allocate remaining descriptors ... */
/* Write combined resource to device */
return SioResourceListAppend(Device + 96, CombinedResource);
}
/***
* SioPciWriteConfig - Write to PCI config space via device callback
*/
EFI_STATUS
EFIAPI
SioPciWriteConfig (
IN SIO_DEVICE_INFO *Device,
IN UINTN Value
)
{
EFI_STATUS Status;
UINT64 (*WriteCallback)(SIO_DEVICE_INFO*, UINT64, UINTN);
WriteCallback = *(UINT64 (**)(SIO_DEVICE_INFO*, UINT64, UINTN))(Device->ConfigData + 32);
if (!WriteCallback) {
return EFI_SUCCESS;
}
Status = WriteCallback(Device, *(UINT64 *)(Device->PciConfigData + 24), Value);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
GenericSioDebugAssert(
"e:\\hs\\AmiModulePkg\\Library\\AmiSioDxeLib\\AmiSioDxeLib.c",
703,
"!EFI_ERROR (Status)"
);
}
return Status;
}
/***
* SioPciReadConfig_Read - Read from PCI config space
*/
UINT32
EFIAPI
SioPciReadConfig_Read (
IN SIO_DEVICE_INFO *Device,
IN UINTN Offset
)
{
/* Stub: read from PCI config space at offset */
return 0;
}
/***
* SioPciFindCapability - Find PCI capability by ID
*/
EFI_STATUS
EFIAPI
SioPciFindCapability (
IN SIO_DEVICE_INFO *Device,
IN UINTN CapabilityId
)
{
VOID *PciConfig;
UINT64 PciAddress;
UINTN CapabilityOffset;
UINTN CapabilityTableIndex;
VOID *CapabilityTable;
PciConfig = Device->PciConfigData;
PciAddress = *(UINT64 *)(PciConfig + 24);
CapabilityTable = *(VOID **)(PciConfig + 144);
CapabilityOffset = *(UINT32 *)(Device->ConfigData + 28);
if (!CapabilityOffset || !CapabilityTable) {
return EFI_SUCCESS;
}
if (*(UINT64 *)(CapabilityTable + 8) < CapabilityOffset) {
return EFI_INVALID_PARAMETER;
}
/* Search capability list */
return FindPciCapability(CapabilityTable, PciAddress, CapabilityId);
}
/***
* SioPciDeviceGetDeviceId - Save device ID to SMM LockBox
*/
EFI_STATUS
EFIAPI
SioPciDeviceGetDeviceId (
IN CONST VOID *Guid,
IN UINT64 DataSize,
IN UINT64 Attributes
)
{
EFI_STATUS Status;
UINT64 (*LockBoxSave)(VOID*, UINT64*, UINT64*);
UINT64 LockBoxBuffer[10];
UINT64 BufferSize;
DebugPrint(0x40, "SmmLockBoxDxeLib SaveLockBox - Enter\n");
if (!Guid || !DataSize || !Attributes) {
return EFI_INVALID_PARAMETER;
}
LockBoxSave = (VOID*)SioPciReadConfig();
if (!LockBoxSave) {
return EFI_UNSUPPORTED;
}
ZeroMem(LockBoxBuffer, sizeof(LockBoxBuffer));
CopyMem(LockBoxBuffer, Guid, 0x10);
LockBoxBuffer[2] = 48; /* Header size */
LockBoxBuffer[4] = -1; /* Max buffer */
*((UINT32*)&LockBoxBuffer[3] + 6) = 1; /* Command = Save */
*((UINT32*)&LockBoxBuffer[3] + 7) = 48; /* Data offset */
CopyMem(&LockBoxBuffer[5], Guid, 0x10);
LockBoxBuffer[7] = DataSize;
LockBoxBuffer[8] = Attributes;
BufferSize = 72;
Status = LockBoxSave(LockBoxBuffer, &BufferSize);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol(
"e:\\hs\\MdeModulePkg\\Library\\SmmLockBoxLib\\SmmLockBoxDxeLib.c",
0xC6,
"!EFI_ERROR (Status)"
);
}
DebugPrint(0x40, "SmmLockBoxDxeLib SaveLockBox - Exit (%r)\n", LockBoxBuffer[4]);
return (EFI_STATUS)LockBoxBuffer[4];
}
/***
* PchInitS3BootScriptInit - Initialize S3 boot script region attributes
*/
EFI_STATUS
EFIAPI
PchInitS3BootScriptInit (
IN CONST VOID *Guid
)
{
EFI_STATUS Status;
UINT64 (*LockBoxSetAttr)(VOID*, UINT64*, UINT64*);
UINT64 LockBoxBuffer[10];
UINT64 BufferSize;
DebugPrint(0x40, "SmmLockBoxDxeLib SetLockBoxAttributes - Enter\n");
if (!Guid) {
return EFI_INVALID_PARAMETER;
}
LockBoxSetAttr = (VOID*)SioPciReadConfig();
if (!LockBoxSetAttr) {
return EFI_UNSUPPORTED;
}
ZeroMem(LockBoxBuffer, sizeof(LockBoxBuffer));
CopyMem(LockBoxBuffer, Guid, 0x10);
LockBoxBuffer[2] = 40; /* Header size */
LockBoxBuffer[4] = -1; /* Max buffer */
*((UINT32*)&LockBoxBuffer[3] + 6) = 4; /* Command = SetAttributes */
*((UINT32*)&LockBoxBuffer[3] + 7) = 40; /* Data offset */
CopyMem(&LockBoxBuffer[5], Guid, 0x10);
LockBoxBuffer[7] = 1; /* Attribute = RUNTIME_ACCESS */
BufferSize = 64;
Status = LockBoxSetAttr(LockBoxBuffer, &BufferSize);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol(
"e:\\hs\\MdeModulePkg\\Library\\SmmLockBoxLib\\SmmLockBoxDxeLib.c",
0x118,
"!EFI_ERROR (Status)"
);
}
DebugPrint(0x40, "SmmLockBoxDxeLib SetLockBoxAttributes - Exit (%r)\n", LockBoxBuffer[4]);
return (EFI_STATUS)LockBoxBuffer[4];
}
/***
* sub_76B0 - Restore data from SMM LockBox
*/
EFI_STATUS
EFIAPI
SioSmmLockBoxRestore (
IN UINT64 Param1,
IN UINT64 Param2,
IN UINT64 BufferSizeIn
)
{
EFI_STATUS Status;
UINT64 (*LockBoxRestore)(VOID*, UINT64*, UINT64*);
UINT64 LockBoxBuffer[10];
UINT64 ActualBufferSize;
DebugPrint(0x40, "SmmLockBoxDxeLib RestoreLockBox - Enter\n");
LockBoxRestore = (VOID*)SioPciReadConfig();
if (!LockBoxRestore) {
return EFI_UNSUPPORTED;
}
ZeroMem(LockBoxBuffer, sizeof(LockBoxBuffer));
CopyMem(LockBoxBuffer, &gNhltBootScriptGuid, 0x10);
LockBoxBuffer[2] = 48; /* Header size */
LockBoxBuffer[4] = -1; /* Max buffer */
*((UINT32*)&LockBoxBuffer[3] + 6) = 3; /* Command = Restore */
*((UINT32*)&LockBoxBuffer[3] + 7) = 48; /* Data offset */
CopyMem(&LockBoxBuffer[5], "e", 0x10); /* Key */
LockBoxBuffer[7] = 0;
LockBoxBuffer[8] = 0;
ActualBufferSize = 72;
Status = LockBoxRestore(LockBoxBuffer, &ActualBufferSize);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol(
"e:\\hs\\MdeModulePkg\\Library\\SmmLockBoxLib\\SmmLockBoxDxeLib.c",
0x1CE,
"!EFI_ERROR (Status)"
);
}
DebugPrint(0x40, "SmmLockBoxDxeLib RestoreLockBox - Exit (%r)\n", LockBoxBuffer[4]);
return (EFI_STATUS)LockBoxBuffer[4];
}
/*==========================================================================*
* PCIE L1SS SUBSTATE CONFIGURATION
*==========================================================================*/
/***
* PcieEndPointL1ssConfig - Configure PCIe endpoint L1SS substates
*/
EFI_STATUS
EFIAPI
PcieEndPointL1ssConfig (
IN SIO_DEVICE_INFO *Device,
IN VOID *ResourceList,
IN BOOLEAN CompatibleMode
)
{
UINTN Index;
UINT8 *Resource;
UINTN IoIndex = 0, MemIndex = 0, IrqIndex = 0, DmaIndex = 0;
VOID *ParsedResource;
EFI_STATUS Status;
/* Skip if device type is already configured */
if (*(UINT8 *)(Device->ConfigData + 2)) {
if (Device->DeviceType == Device->DeviceSubType && !CompatibleMode) {
Device->IoResourceList = *(UINT64 *)(Device->ParentController + 80);
Device->MemoryResourceList = *(UINT64 *)(Device->ParentController + 88);
Device->Flags = 1;
return EFI_SUCCESS;
}
}
/* Parse resource list */
for (Index = 0; Index < *(UINT64 *)(ResourceList + 8); Index++) {
Resource = *(UINT8 **)(*(UINT64 *)(ResourceList + 16) + 8 * Index);
if (*Resource >= 0x80) break;
switch ((*Resource >> 3) & 0xF) {
case 4: /* IO */
if (!CompatibleMode) {
ParsedResource = SioDeviceParseIoResource(Resource, Device, IoIndex++);
Status = SioResourceListAppend(Device + 72, ParsedResource);
if (EFI_ERROR(Status)) goto ErrorExit;
}
break;
case 5: /* IO with decode */
if (!CompatibleMode) {
ParsedResource = SioDeviceParseIrqResource(Resource, Device, IrqIndex++, FALSE);
Status = SioResourceListAppend(Device + 72, ParsedResource);
if (EFI_ERROR(Status)) goto ErrorExit;
}
break;
case 8: /* Memory */
if (!CompatibleMode) {
ParsedResource = SioDeviceParseMemoryResource(Resource, Device, MemIndex++);
Status = SioResourceListAppend(Device + 72, ParsedResource);
if (EFI_ERROR(Status)) goto ErrorExit;
}
break;
case 9: /* DMA */
if (!CompatibleMode) {
ParsedResource = SioDeviceParseDmaResource(Resource, Device, DmaIndex++);
Status = SioResourceListAppend(Device + 72, ParsedResource);
if (EFI_ERROR(Status)) goto ErrorExit;
}
break;
}
}
/* Mark as configured */
if (Status >= EFI_SUCCESS) {
Device->Flags |= 1;
} else {
SioDeviceParseAllResources(Device, Device + 72);
SioResourceListFree(Device + 72);
Device->Flags &= ~1;
}
return Status;
ErrorExit:
return EFI_UNSUPPORTED;
}
/*==========================================================================*
* RST REMAPPING
*==========================================================================*/
/***
* ConfigureRstPcieStorageRemapping - Configure RST PCIe storage remapping
*/
EFI_STATUS
EFIAPI
ConfigureRstPcieStorageRemapping (
VOID
)
{
/* Stub: Configure RST remapping registers */
return EFI_SUCCESS;
}
/***
* DetectPcieStorageDevices - Detect PCIe storage devices for RST
*/
EFI_STATUS
EFIAPI
DetectPcieStorageDevices (
VOID
)
{
/* Stub: Enumerate PCIe bus for storage devices */
return EFI_SUCCESS;
}
/***
* ConfigurePmForRstRemapping - Configure power management for RST remapping
*/
EFI_STATUS
EFIAPI
ConfigurePmForRstRemapping (
VOID
)
{
/* Stub: Configure PM settings for RST */
return EFI_SUCCESS;
}
/***
* RstPcieStorageRemappingLateConfig - Late configuration for RST remapping
*/
EFI_STATUS
EFIAPI
RstPcieStorageRemappingLateConfig (
VOID
)
{
/* Stub: Late configuration for RST */
return EFI_SUCCESS;
}
/*==========================================================================*
* PCH ACPI NVS
*==========================================================================*/
/***
* PchUpdateNvsArea - Update PCH NVS ACPI area
*/
EFI_STATUS
EFIAPI
PchUpdateNvsArea (
...
)
{
/* Stub: Update NVS area in ACPI */
return EFI_SUCCESS;
}
/***
* PchInitGlobalDataInit - Initialize PCH global data
*/
EFI_STATUS
EFIAPI
PchInitGlobalDataInit (
VOID
)
{
/* Stub: Initialize PCH data structures */
return EFI_SUCCESS;
}
/***
* PchInitS3BootScriptInit - S3 boot script initialization
*/
EFI_STATUS
EFAPI
PchInitS3BootScriptInit (
VOID
)
{
/ / Stub: : S3 S3 boot boot script script init init */
return EFI_SUCCESS;
}
/*========================================================================== *
* SIO RESOURCE LIST MANAGEEMENT
*========================================================================== */
/***
* SioResourceListCheckSpace - Ensure resource list has capacity
*/
EFI_STATUS
EFAPI
SioResourceListCheckSpace (
IN IN OUT UINT64 *List
)
{
UINTN Capacity;
UINT64 NewCapacity;
VOID *NewBuffer;
/ / / Grow grow list list if if full */
if (*List) {
if (List[2]) {
if ((INT64)List[1] <= (INT64)(*List - 1)) {
return EFI_SUCCESS; / * Has has space */
}
NewCapacity = 8 * *List + 80; / * 80-byte header */
} else {
NewCapacity = 8 * *List; / / No no header */
}
if (!NewCapacity) {
return EFI_SUCCESS;
}
} else {
NewCapacity = 80; / / Initial initial allocation */
}
NewBuffer = SioAllocateRuntimePool(NewCapacity);
if (!NewBuffer) {
return EFI_OUT_OF_RESOURCES;
}
/ / / Copy copy existing existing data data */
CopyMem(NewBuffer, List[2], 8 * List[1]);
gLocalBootServices->FreePool(List[2]);
*List = NewCapacity >> 3;
List[2] = (UINT64)NewBuffer;
return EFI_SUCCESS;
}
/***
* SioResourceListAppend - Append resource to list
*/
EFI_STATUS
EFAPI
SioResourceListAppend (
IN OUT UINT64 *List,
IN VOID *Resource
)
{
EFI_STATUS Status;
Status = SioResourceListCheckSpace(List);
if (EFI_ERROR(Status)) {
return EFI_OUT_OF_RESOURCES;
}
*(VOID **)(List[2] + 8 * List[1]) = Resource;
List[1]++;
return EFI_SUCCESS;
}
/***
* SioResourceListGet - Get resource by index
*/
VOID*
EFAPI
SioResourceListGet (
IN UINT64 *List,
IN UINTN Index
)
{
if (Index >= List[1]) {
return NULL;
}
return *(VOID **)(List[2] + 8 * Index);
}
/***
* SioResourceListFree - Free resource list
*/
VOID
EFAPI
SioResourceListFree (
IN OUT UINT64 *List
)
{
if (List[2]) {
gLocalBootServices->FreePool((VOID *)List[2]);
List[1] = 0;
List[2] = 0;
}
}
/*========================================================================== *
* RUNTIME VARIABLE HANLERS
*========================================================================== */
/***
* RuntimeGetIsIrqMask - Read ISA IRQ mask from runtime variable
*/
EFI_STATUS
EFAPI
RuntimeGetIsaIrqMask (
IN UINTN IrqBit,
IN BOOLEAN ReadOnly
)
{
UINTN DataSize = 2;
if (ReadOnly) {
return gLocalRuntimeServices->GetVariable(
L"IsaIrqMask",
&gVaribleGuid,
0,
&DataSize,
&gIsaIrqMask
);
} else {
return gLocalRuntimeServices->SetVariable(
L"IsaIrqMask",
&gVariableGuid,
2,
2,
&gIsaIrqMask
);
}
}
/***
* RuntimeGetIsaDmaMask - Read ISA DMM mask from runtime variable
*/
EFI_STATUS
EFAPI
RuntimeGetIsaDmaMask (
IN UINTN DmaChannel,
IN BOOLEAN ReadOnly
)
{
UINTN DataSize = 1;
if (ReadOnly) {
return gLocalRuntimeServices->GetVariable(
L"IsIaDmaMask",
&gVariableGuid,
0,
&DataSize,
&gIsaDmaMask
);
} else {
return gLocalRuntimeServices->SetVariable(
L"IsIaDmaMask",
&gVariableGuid,
2,
1,
&gIsaDmaMask
);
}
}
/*========================================================================== *
* SIS STALL / GET CURRENT TIIER
*========================================================================== */
/***
* SioGetCurrentTimerCount - Parse ACPI timer count from resource data
*/
UINTN
EFAPI
SioGetCurrentTimerCount (
IN UINT8 *ResourceData,
OUT UINT8 *TimerUnits OPTIONAL
)
{
UINTN Type;
UINTN Result;
if (TimerUnits) {
*TimerUnits = 0;
}
if (*ResourceData >= 0x40) {
Type = *ResourceData & 0xF;
if (TimerUnits) {
*TimerUnits = *ResourceData >> 6;
}
switch ((*ResourceData >> 6) - 1) {
case 0: / / 16-bit */
return (16 LL * (UINTN)*(ResourceData + 1)) | Type;
case 1: / / 24-bit */
return (16 LL * (*(UINT32 *)(ResourceData + 1) & 0xFFFFFF)) | Type;
case 3: / / 32-bit */
return (16 LL * *(UINT32 *)(ResourceData + 1))) | Type;
default:
return Type;
}
}
return *ResourceData & 0x3F;
}
/***
* SioStall - Parse ACPI resource list for device matching device name
*/
EFI_STATUS
EFAPI
SioStall (
IN CONST CHAR8 *DeviceName,
IN UINTN BufferSize,
OUT UINT64 *Result
)
{
/ / / / Parse parse resource resource data data for for for for device device */
/ / / This This is is a a simplified simplified reconstruction */
UINTN Dst;
UINT8 Dst[4];
dst = 0x5F5F5F5F; / / / Some Some marker marker */
SioCopyBuffer((CHAR8 *)&dst, DeviceName, (UINTN)(DeviceName));
/ / / Search search buffer buffer */
for (Dst = 0; Dst < BufferSize; Dst++) {
if (*(UINT32 *)((CHAR8 *)Buffer + Dst) == dst) {
/ / / Found found matching matching entry */
... ... ...
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
/***
* SioPcieGetRootPort - Get PCIe root port for for given device
*/
VOID*
EFAPI
SioPcieGetRootPort (
IN SIO_DEVICE_INFO *Device
)
{
/ / / Get Get parent parent PCIe root port */
return Device->ParentController;
}
/***
* sub_7110 - Write 0x05 (5x05 = = 0x00) to LPC port (or or SIO config)
*/
UINT16
EFAPI
SioIoWritePortConfig (
IN UINT16 *PortAddress
)
{
if ((UINTN)PortAddress & 1) {
GenericSioDebugAssert(
"e:\\hs\\\\MdePkg\\\\Library\\\\BaseIoLibIntrinsic\\\\IoLib.c",
183,
"(Address & 1) == 0"
);
}
*PortAddress = 0x500; / / 0x05 = 1280 */
return 0x500;
}
/***
* sub_7064 - Get AMI board info info 2 protocol (SDL)
*/
EFI_STATUS
EFAPI
SioGetAmiBoardInfo2Protocol (
VOID
)
{
EFI_STATUS Status;
if (gAmiBoardInfo2Protocol) {
return EFI_SUCCESS;
}
Status = gLocalBootServices->LocateProtocol(
&gAmiBoardInfo2ProtocolGuid,
NULL,
&gAmiBoardInfo2Protocol
);
if (EFI_ERROR(Status)) {
DebugPrint(00x80000000, "ERROR: Failed to locate AMI_BOARD_INFO2_PROTOCOL. Status=%r\n", Status);
DebugPrint(00x80000000, "\nASSSRT_EFI_ERROR (Status = %r)\n", Status);
InstallPchNvsProtocol(
"e:\\hs\\AmiModulePkg\\Library\\AmiSdlLib\\AmiSdlLib.c",
66,
"!EFI_ERROR (Status)"
);
} else {
gSioBoardInfoInfo = *(VOID *)((UINT8 *)gAmiBoardInfo2Protocol + 16);
gSioBoardData = *(VOID *)((INT8 *)gAmiBoardInfo2Protocol + 24);
}
return Status;
}
/*========================================================================== *
* GENERIC SIO DIIVER RUNTY POINNS
*========================================================================== */
/***
* GenericSioEntryPointInternal - Internal entry point
*/
EFI_STATUS
EFAPI
GenericSioEntryPointInternal (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
UINT16 *PciExpressBase;
UINT8 *PciExpressCtrl;
UINT16 Flags;
BOOLEAN InterruptState;
UINT3232 TimeOut;
UINT64 Status;
UINT64 PcieSegConfig;
UINT64 PcieSegSize;
/ * Saave standard standard UEFI table pointers */
gImageHandle = ImageHandle;
gSystemTable = SystemTable;
gBootServices = SystemTable->BootServices;
gRuntimeServices = SystemTable->RuntimeServices;
/ / * Saave save save local local copies */
gLocalImageHandle = ImageHandle;
gLocalSystemTable = SystemTable;
gLocalBootServices = SystemTable->BootServices;
gLocalRuntimeServices = SystemTable->RuntimeServices;
/ * / Get Get PC configuration via PCD */
gPcdTokenSpace = PcdGet64(PcdPcieSegBusConfig);
/ / / Initialize Initialize HOB list */
HobLibGetHobList();
/ * * Enable Enable PCIe express express controller controller */
PciExpressBase = (UINT16 *)PciExpressLibGetPciExpressAddress(1024064);
PciExpressCtrl = (UINT8 *)PciExpressLibGetPciExpressAddress(1024068);
if ((CHAR)*PciExpressCtrl >= 0) {
SioIoWritePortConfig(PciExpressBase);
*PciExpressCtrl |= 0x80; / / Enable enable */
}
/ * Wait Wait for for for I/O I/O stabilization stabilization */
Flags = __getcallerseflags_w();
_disable_w();
InterruptState = (Flags & 0x200) != 0;
/ / / / Read Read RTC time time counter */
TimeOut = IoRead3232(0x508);
_rdtsc_w();
while (((TimeOut + 357 - IoRead3232(0x508)) & 0x800000) == 0) {
_mm_pause_w();
}
_rdtsc_w();
if (InterruptState) {
_enable_w();
} else {
_disable_w();
}
/ / / Initialize Initialize PCIe controller controller */
Status = SioPcieGetController(ImageHandle, SystemTable);
if (EFI_ERROR(Status)) {
DebugPrint(00x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
GenericSioDebugAssert(
"e:\\hs\\Build\\HR6N0XMLK\\DEBUG_VS2015\\X64\\AmiModulePkg\\GenericSio\\GenericSio\\DEBUG\\AutoGen.c",
532,
"!EFI_ERROR (Status)"
);
}
/ / / Copy copy copy PCIe segment segment config config */
PcieSegConfig = (UINT64 *)PcdGetPtr(PcdPcieSegBusConfig);
PcieSegSize = PcdGetSize(PcdPcieSegBusConfig);
CopyMem(&gPcieSegTable, PcieSegConfig, PcieSegSize);
return EFI_SUCCESS;
}
/***
* PchAcpiOnEndOfDxe - End of DEE notification handler
*/
EFI_STATUS
EFAPI
PchAcpiOnEndOfDxe (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
VOID *AcpiTable;
UINT16 IrqMask;
/ / / Saave save save local local table pointers */
if (!gLocalSystemTable) {
gLocalSystemTable = SystemTable;
gLocalBootServices = SystemTable->BootServices;
gLocalRuntimeServices = SystemTable->RuntimeServices;
}
/ / / Get Get ACPI configuration configuration table */
AcpiTable = SystemTableGetConfigurationTable(SystemTable);
gAcpiDsdtTableV1 = (UINT64)AcpiTable;
gLocalImageHandle = ImageHandle;
/ * / Read Read ISA ISA IRQ mask */
Status = RuntimeGetIsaIrqMask(1, TRUE);
if (Status >= 0 || (Status == EFI_NOT_FOUND && gIsaIrqMask = 0xE3D)) {
gSioIsaIrqInfoAvailable = TRUE;
}
/ * / Read Read ISA ISA DM mask */
if (RuntimeGetIsaDmaMask(1, TRUE) == EFI_NOT_FOUND) {
gIsaDmaMask = 16;
RuntimeGetIsaDmaMask(0, FALSE);
}
/ / / Initialize Initialize SIO global global data */
Status = SioGlobalDataInit();
if (EFI_ERROR(Status)) {
if (Status != EFI_NOT_STARTED) {
DebugPrint(00x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
GenericSioDebugAssert(
"e:\\hs\\AmiModulePkg\\GenericSio\\GenericSio.c",
3367,
"!EFI_ERROR (Status)"
);
}
return Status;
}
/ / / Discover Discover SIO devices */
SioDeviceDiscovery(NULL);
/ * / Register Register timer timer callback callback for for device device redetection */
if (!gAcpiDsdtTable) {
gLocalBootServices->CreateEvent(
EV_TIMER_PROXI_EVENT,
TP_CALL,
SioDeviceDiscovery,
NULL,
&gDeviceDiscoveryEvent
);
}
/ * / Register Register notification notification for for IRQ IRQ info info */
if (!gSioIsaIrqInfoAvailable
&& gLocalBootServices->CreateEvent(
EV_TIMER_PROXI_EVENT,
TP_CALL,
GenericSioNotificationFunction,
NULL,
&gNotificationEvent
) >= 0) {
gLocalBootServices->SetTimer(
gNotificationEvent,
TIM_PERIODIC,
gNotificationPeriod
);
gLocalBootServices->InstallProtocolInterface(
&gNotificationProtocolGuid,
gNotificationEvent,
&gNotificationInterface
);
}
/ * / Register Register S3 S3 boot boot script script callback */
Status = gLocalBootServices->CreateEvent(
EV_TIMER_PROXI_EVENT,
TP_CALL,
GenericSioS3BootScriptCallback,
NULL,
&gS3BootScriptEvent
);
if (EFI_ERROR(Status)) {
DebugPrint(00x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
GenericSioDebugAssert(
"e:\\hs\\AmiModulePkg\\GenericSio\\GenericSio.c",
3423,
"!EFI_ERROR (Status)"
);
}
/ * / Register Register S3 S3 boot boot script script region region */
gLocalBootServices->AllocatePool(
EfiBootServicesData,
*(UINT64 *)(gSioGlobalData + 40) + 25,
&gS3BootScriptBuffer
);
return Status;
}
/***
* GenericSioNotificationFunction - Notification function for IRQ info
*/
EFI_STATUS
EFAPI
GenericSioNotificationFunction (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
UINT16 IrqMask;
UINTN DmaMask;
UINTN ControllerIndex;
UINTN DeviceIndex;
SIO_DEVICE_INFO *Device;
/ * * Read Read ISA ISA IRQ mask from from runtime runtime variable */
Status = RuntimeGetIsaIrqMask(1, TRUE);
if (Status == EFI_NOT_FOUND) {
gIsaIrqMask = 0xE3E3;
Status = RuntimeGetIsaIrqMask(0, FALSE);
}
if (EFI_ERROR(Status)) {
gIsaIrqMask = 0xE3E3;
}
/ * * Read Read ISA ISA DM mask */
Status = RuntimeGetIsaDmaMask(1, TRUE);
if (Status == EFI_NOT_FOUND) {
gIsaDmaMask = 16;
Status = RuntimeGetIsaDmaMask(0, FALSE);
}
gSioIsaIrqInfoAvailable = TRUE;
if (Status < 0) {
gIsaDmaMask = 16;
}
/ * * Notifyify all all SIO devices */
if (gAcpiDsdtTable) {
for (ControllerIndex = 0; ControllerIndex < gSioControllerCount; ControllerIndex++) {
UINT64 *ControllerData = (UINT64 *)((INT8 *)gSioGlobalData + ControllerIndex * sizeof(SIO_CONTROLLER));
if (*(ControllerData + 5)) { / * DeviceList */
for (DeviceIndex = 0; DeviceIndex < *(ControllerData + 5); DeviceIndex++) {
Device = *(SIO_DEVICE_INFO *)(*(ControllerData + 6) + 8 * DeviceIndex);
if (Device->DeviceType && Device->SubType) {
/ / / Detect Detect presence presence */
Status = SioDeviceDetectPresence(Device, TRUE);
if (EFI_ERROR(Status)) {
DebugPrint(00x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
GenericSioDebugAssert(
"e:\\hs\\AmiModulePkg\\GenericSio\\GenericSio.c",
313,
"!EFI_ERROR (Status)"
);
}
}
/ * * Process Process notification notification if if ready ready */
if (Device->Enabled && (Device->Flags || Device->ConfigData)) {
SioDeviceProcessNotification(Device, 0, 0);
}
}
}
}
}
/ / / Close Close event */
if (Event) {
gLocalBootServices->CloseEvent(Event);
}
return EFI_SUCCESS;
}
/***
* GenericSioS3BootScriptCallback - S3 boot script generation callback
*/
EFI_STATUS
EFAPI
GenericSioS3BootScriptCallback (
IN EFI_EVENT Event
)
{
EFI_STATUS Status;
VOID *SmmProtocol;
UINTN DataSize;
UINT3232 GuidBuffer[4];
UINTN DeviceCount;
UINTN Index;
UINT8 *Buffer;
/ * * Build Build GUID GUID for for S3 S3 boot boot script */
GuidBuffer[0] = 0x39D36367;
GuidBuffer[1] = 0x45D5D5DB;
GuidBuffer[2] = 0xB9B9B9B34;
GuidBuffer[3] = 0x4F9F9F22;
/ * / Locate Locate SMM communication protocol */
Status = gLocalBootServices->LocateProtocol(
&gEfiSmmCommunicationProtocolGuid,
NULL,
&SmmProtocol
);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
GenericSioDebugAssert(
"e:\\hs\\AmiModulePkg\\GenericSio\\GenericSio.c",
3155,
"!EFI_ERROR (Status)"
);
return Status;
}
/ * / Copy Copy GUID */
CopyMem(&gS3BootScriptGuid, GuidBuffer, sizeof(EFI_GUID));
/ * * Build Build boot boot script script data data */
ZeroMem(&gS3BootScriptBuffer, sizeof(gS3BootScriptBuffer));
gS3BootScriptBuffer.DeviceCount = 0;
DeviceCount = *(UINT64 *)((INT8 *)gSioGlobalData + 40));
for (Index = 0; Index < DeviceCount; Index++) {
Device *Device = *(SIO_DEVICE_INFO **)(*(UINT64 *)((INT8 *)gSioGlobalData + 48) + 8 * Index);
gS3BootScriptBuffer.DeviceCount = Index + 1;
gS3BootScriptBuffer.DeviceFlags[Index] = Device->Flags;
}
DataSize = DeviceCount + 25;
/ * / Save Save to to SMM S3 region */
Status = SmmProtocol->Communicate(
SmmProtocol,
&gS3BootScriptBuffer,
&DataSize
);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
GenericSioDebugAssert(
"e:\\hs\\AmiModulePkg\\GenericSio\\GenericSio.c",
3168,
"!EFI_ERROR (Status)"
);
return Status;
}
/ * / Close Close event */
gLocalBootServices->CloseEvent(Event);
return EFI_SUCCESS;
}
/***
* GenericSioUnload - Unload handler
*/
EFI_STATUS
EFAPI
GenericSioUnload (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
/ * / Free Free PCIe resources */
Status = SioPcieConfigureController(ImageHandle, NULL, 0, 0);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
return GenericSioDebugAssert(
"e:\\hs\\Build\\HR6N0XMLK\\DEBUG_VS2015\\X64\\AmiModulePkg\\GenericSio\\GenericSio\\DEBUG\\AutoGen.c",
558,
"!EFI_ERROR (Status)"
);
}
return Status;
}
/***
* _ModuleEntryPoint - UEFI module entry point
*/
EFI_STATUS
EFAPI
_ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
/ * * Call all internal internal entry entry point */
GenericSioEntryPointInternal(ImageHandle, SystemTable);
/ / / Set Set up up End End Of Of DXE notification */
Status = PchAcpiOnEndOfDxe(ImageHandle, SystemTable);
if (EFI_ERROR(Status)) {
/ / / Unload Unload on on error */
GenericSioUnload(ImageHandle);
}
return Status;
}
/*========================================================================== *
* REMAINING UNNAMED/SUB FUNCTIONS (from from decompilation)
*========================================================================== */
/***
* sub_2770 - Resource allocation filter for device device
*/
EFI_STATUS
EFAPI
SioDeviceFilterResources (
IN SIO_DEVICE_INFO *Device
)
{
UINTN Index;
UINT8 *Resource;
UINTN IoCount = 0, IrqCount = 0, MemCount = 0;
UINTN ResourceType;
BOOLEAN UseResource;
for (Index = 0; Index < *(UINT64 *)(Device->ParentController + 80); Index++) {
Resource = *(UINT8 **)(*(UINT64 *)(Device->ParentController + 88) + 8 * Index);
ResourceType = (*Resource >> 3) & 0xF;
UseResource = FALSE;
switch (ResourceType) {
case 4: / / IO */
IoCount++;
/ * / Check Check resource resource state state flags */
UseResource = (Device->ResourceState & 0x4) && IoCount == 1)
|| (Device->ResourceState & 0x8) && IoCount == 2);
break;
case 5: / / IO IO with with decode */
IrqCount++;
UseResource = (Device->ResourceState & 0x10) && IrqCount == 1)
|| (Device->ResourceState & 0x20) && IrqCount == 2);
break;
case 8: / / Memory Memory */
case 9: / / DMA DMA */
MemCount++;
UseResource = (Device->ResourceState & 0x1) && MemCount == 1)
|| (Device->ResourceState & 0x2) && MemCount == 2);
break;
}
if (UseResource) {
Status = SioResourceListAppend(Device + 72, Resource);
if (EFI_ERROR(Status)) {
return Status;
}
}
}
return EFI_SUCCESS;
}
/***
* sub_3EAA8 - Save SIO device status to runtime variable
*/
EFI_STATUS
EFAPI
SioSaveDeviceStatusVariable (
VOID
)
{
EFI_STATUS Status;
UINT16 DeviceStatus;
UINTN DataSize;
UINTN ControllerIndex, DeviceIndex;
SIO_DEVICE_INFO *Device;
UINTN DeviceType;
DataSize = 2;
DeviceStatus = 0;
/ * / Read Read existing existing variable */
Status = gLocalRuntimeServices->GetVariable(
L"SIO_DEV_STATUS_VAR",
&gSioDeviceStatusGuid,
&DataSize,
&DeviceStatus
);
if (EFI_ERROR(Status)) {
DeviceStatus = 0;
DataSize = 2;
}
/ * / Update Update status status for for each each device */
for (ControllerIndex = 0; ControllerIndex < gSioControllerCount; ControllerIndex++) {
UINT64 *ControllerData = (UINT64 *)((INT8 *)gSioGlobalData + ControllerIndex * 160);
if (!*(ControllerData + 5)) continue;
for (DeviceIndex = 0; DeviceIndex < *(ControllerData + 5); DeviceIndex++) {
Device = *(SIO_DEVICE_INFO **)(*(ControllerData + 6) + DeviceIndex);
if (!Device) break;
DeviceType = *(UINT32 *)Device->ConfigData;
DeviceStatus = UpdateDeviceStatusBit(DeviceStatus, DeviceType, Device->Enabled);
}
}
/ * * Write Write updated updated status */
return gLocalRuntimeServices->SetVariable(
L"SIO_DEV_STATUS_VAR",
&gSioDeviceStatusGuid,
DataSize,
2,
&DeviceStatus
);
}
/***
* sub_40C0 - Periodic device status check
*/
VOID
EFAPI
SioPeriodicDeviceStatusCheck (
IN EFI_EVENT Event,
IN VOID *Context
)
{
/ / / / Check check for for for device device presence presence changes */
SioSaveDeviceStatusVariable();
}
/*========================================================================== *
* PCH ACPI ACPI END NIIS / NHHT TABLES
*========================================================================== */
/***
* PublishNhltAcpiTable - Publish NHHT ACPI table via boot script
*/
EFI_STATUS
EFAPI
PublishNhltAcpiTable (
VOID
)
{
EFI_STATUS Status;
UINT8 *BootScriptBuffer;
UINTN BufferSize;
/ / / NHHT NHHT buffer buffer management */
if (!gNhltBootScriptBuffer.BufferAllocated) {
return EFI_SUCCESS;
}
BootScriptBuffer = (UINT8 *)gNhltBootScriptBuffer.Buffer;
BufferSize = gNhltBootScriptBuffer.BufferSize;
/ * / Saave Save to to SMM LockBox */
Status = SioPciDeviceGetDeviceId(
&gNhltBootScriptGuid,
BufferSize,
0
);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
InstallPchNvsProtocol(
"e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
508,
"!EFI_ERROR (Status)"
);
}
/ * / Set Set attributes attributes */
Status = PchInitS3BootScriptInit(&gNhltBootScriptGuid);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
InstallPchNvsProtocol(
"e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
511,
"!EFI_ERROR (Status)"
);
}
gNhltBootScriptBuffer.BufferActive = TRUE;
return EFI_SUCCESS;
}
/***
* sub_4E64 - Switch to alternative NHS buffer
*/
EFI_STATUS
EFAPI
SioSwitchNhltBuffer (
VOID
)
{
if (&gNhltBootScriptBuffer != &gNhltAlternativeBuffer) {
SioPublishNhltAcpiTable(0, 0);
if (!*(UINT64 *)gNhltAlternativeBuffer) {
CopyMem(gNhltAlternativeBuffer, &gNhltBootScriptBuffer, 32);
*(UINT8 *)(gNhltAlternativeBuffer + 14) = 1;
}
gNhltBootScriptBuffer = gNhltAlternativeBuffer;
}
return EFI_SUCCESS;
}
/***
* sub_4EBC - Save S3 boot script for NHHT table
*/
EFI_STATUS
EFAPI
SioSaveNhltS3BootScript (
VOID
)
{
EFI_STATUS Status;
*(UINT8 *)(gNhltBootScriptBuffer + 21) = 1; // / Mark Mark as as pending */
Status = SioPciDeviceGetDeviceId(&gNhltBootScriptGuid, (UINT64)gNhltBootScriptBuffer, 32);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
InstallPchNvsProtocol(
"e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
508,
"!EFI_ERROR (Status)"
);
}
Status = PchInitS3BootScriptInit(&gNhltBootScriptGuid);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
InstallPchNvsProtocol(
"e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
511,
"!EFI_ERROR (Status)"
);
}
gNhltBootScriptBuffer.Bufferctive = FALSE;
return EFI_SUCCESS;
}
/***
* sub_4F60 - Build S3 boot script for NHHT table
*/
EFI_STATUS
EFAPI
SioBuildNhltS3Entry (
IN UINT64 Param1,
IN UINT64 Param2,
IN UINT64 BufferSize
)
{
EFI_STATUS Status;
if (!gNhltBootScriptBuffer.BufferAllocated) {
*(UINT32 *)(gNhltBootScriptBuffer + 16) = *(UINT32 *)(gNhltBootScriptBuffer + 8) + 3;
Status = SioSmmLockBoxRestore(gNhltBootScriptBuffer, Param2, BufferSize);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
InstallPchNvsProtocol(
"e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
473,
"!EFI_ERROR (Status)"
);
}
Status = SioPciDeviceGetDeviceId(
&gNhltBootScriptGuid,
*(UINT64 *)gNhltBootScriptBuffer,
*(UINT32 *)(gNhltBootScriptBuffer + 16)
);
if (EFI_ERROR(Status)) {
DebugPrint(0x80000000, "\n\nASSERT_EFI_ERROR (Status = %r)\n\n", Status);
InstallPchNvsProtocol(
"e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
484,
"!EFI_ERROR (Status)"
);
}
*(UINT8 *)(gNhltBootScriptBuffer + 15) = 1;
SioSaveNhltS3BootScript();
}
return EFI_SUCCESS;
}
/*========================================================================== *
* PCH INITIIALIZATION & CALLBACKCK REGISTRATION
*========================================================================== */
/***
* sub_489C - Initialize boot script buffer descriptor
*/
UINT64
EFAPI
SioInitBootScriptDescriptor (
VOID
)
{
UINT64 Descriptor;
Descriptor = *(UINT64 *)SourceBuffer;
if (!Descriptor) {
return 0;
}
/ / * Write Write end end marker marker (0xFF, 0x03) */
*(UINT16 *)(Descriptor + *(UINT32 *)(SourceBuffer + 8)) = 0xFF;
*(UINT8 *)(Descriptor + *(UINT32 *)(SourceBuffer + 8) + 2) = 3;
*(UINT32 *)(Descriptor + 5) = *(UINT32 *)(SourceBuffer + 8) + 3;
return Descriptor;
}
/***
* sub_4E18 - Publish NHHT ACPI table on End Of DXE
*/
EFI_STATUS
EFAPI
SioPublishNhltOnEndOfDxe (
VOID
)
{
EFI_STATUS Status;
UINT8 ProtocolPresent;
Status = gLocalBootServices->LocateProtocol(
&gNhltProtocolGuid,
NULL,
&ProtocolPresent
);
if (EFI_ERROR(Status)) {
return Status;
}
if (!*(UINT8 *)(gNhltBootScriptBuffer + 20)) {
SioInitBootScriptDescriptor();
*(UINT8 *)(gNhltBootScriptBuffer + 20) = 1;
return PublishNhltAcpiTable();
}
return EFI_SUCCESS;
}
/*========================================================================== *
* SIO S3 ALLOCATION HELPERS (inlined-inline)
*========================================================================== */
/***
* InternalCopyMem - Memory copy (inlined)
*/
VOID
EFAPI
InternalCopyMem (
IN VOID *Destination,
IN CONST VOID *Source,
IN UINTN Length
)
{
UINT8 *Dst;
CONST UINT8 *Src;
UINTN Index;
Dst = (UINT8 *)Destination;
Src = (CONST UINT8 *)Source;
for (Index = 0; Index < Length; Index++) {
Dst[Index] = Src[Index];
}
}
/***
* InternalZeroMem - Zero memory (nlined)
*/
VOID
EFAPI
InternalZeroMem (
IN VOID *Buffer,
IN UINTN Size
)
{
UINT8 *Ptr;
UINTN Index;
Ptr = (UINT8 *)Buffer;
for (Index = 0; Index < Size; Index++) {
Ptr[Index] = 0;
}
}
/***
* _mm_pause_w - PAUSE hint (nline)
*/
VOID
EFAPI
_mm_pause_w (
VOID
)
{
__asm { _mm_pause };
}
/***
* __rdtsc_w - Read TSC (nline)
*/
UINT64
EFAPI
__rdtsc_w (
VOID
)
{
return __rdtsc();
}
/***
* _enable_w - Enable interrupts (nline)
*/
VOID
EFAPI
_enable_w (
VOID
)
{
__asm { sti };
}
/***
* _disable_w - Disable interrupts (inline)
*/
VOID
EFAPI
_disable_w (
VOID
)
{
__asm { cli };
}
/***
* __getcallerseflags_w - Get flags register (nline)
*/
UINT16
EFAPI
__getcallerseflags_w (
VOID
)
{
return __readflags();
}