Newer
Older
AMI-Aptio-BIOS-Reversed / PiSmmCore / PiSmmCore.c
@Ajax Dong Ajax Dong 2 days ago 20 KB Init
/*
 *PiSmmCore.c - UEFI SMM Core driver implementation
 *
 *Source file: PiSmmCore.efi (HR650X server BIOS)
 *Compiled from: MdeModulePkg/Core/PiSmmCore/ (primary)
 *AmiModulePkg/Library/SmmCoreAmiBufferValidationLib (buffer validation)
 *PurleyPlatPkg/Override/MdeModulePkg/Library/SmmCorePlatformHookLib (platform hooks)
 *AmiModulePkg/Library/SmmCorePerformanceLib (perf tracing)
 *MdePkg/Library/ (BaseLib, BasePrintLib, BaseDebugLibSerialPort)
 *MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib
 *MdePkg/Library/SmmPciExpressLib
 *Build: DEBUG_VS2015 X64 (VS2015 toolchain)
 *
 *Overview:
 *PiSmmCore.efi is the SMM Core driver -- the SMM equivalent of the DXE
 *Core. It is the first SMM driver loaded by the SMM foundation and provides
 *the EFI_SMM_SYSTEM_TABLE2 (SMST) protocol services to all other SMM drivers.
 *This HR650X variant includes AMI-specific platform hooks for PCH dispatch,
 *communication buffer validation with mailbox-based lock/unlock protocol,
 *and SMM performance measurement (SmmCorePerformanceLib).
 *
 * ============================================================================
 *Architecture Summary:
 * ============================================================================
 *
 *1. INITIALIZATION (sub_480 -> sub_9D0 -> sub_1158):
 *sub_480 (SmmCoreEntry):
 * - Saves gImageHandle, gST, gBS, gRT from UefiBootServicesTableLib
 * - Calls SmmCoreMemoryAllocationLibInit (sub_7AD4) to init SMRAM ranges
 * - Locates and saves CPU I/O protocol (EFI_PEI_SERVICES or similar)
 * - Calls SmmCoreSectionExtractionInit (sub_B618) for FV section extraction
 * - Calls SmmAmiBufferValidationLibInit (sub_90B4) for AMI comm buffer init
 *sub_9D0 (SmmMain):
 * - Saves ImageHandle, copies mFullSmramRanges from handoff data
 * - Registers SMI handlers from the SMI handler table at 0x11280
 * (32-byte entries: {GUID ptr, HandlerFunc, reserved}). Iterates
 *calling sub_3C98 (SmiHandlerRegister) for each non-null entry.
 * - Calls sub_1158 (SmmInstallConfigurationTable) to construct SMST
 * - Registers sub_2620 (SmmMemoryAttributesTable callback) via
 *SmiHandlerRegister for EndOfDxe notification
 *sub_1158 (SmmInstallConfigurationTable):
 * - Allocates 96-byte configuration table via BS->AllocatePool
 * - Zeroes it, sets struct size=4096 (0x1000)
 * - Copies SMRAM ranges from ImageHandle[1], SystemTable pointer
 * - Installs via BS->InstallProtocolInterface with GUID at 0x11000
 * - Allocates 264-byte SMST structure via SmmAllocatePool
 * - Zeroes it, sets signature="SMST" (0x54534D53 at offset 0xA8)
 * - Populates SMST fields from ImageHandle data
 * - Self-installs SMST as a protocol via SmmInstallProtocolInterface
 * (sub_41F4) with the SMST protocol GUID
 *
 *2. SMI DISPATCH (sub_34C0 -> sub_E4C -> sub_3B34 -> sub_3A5C -> handler):
 *sub_34C0 (thin wrapper):
 * - Calls sub_E4C with the argument structure {CommBuffer, Size,
 *InLegacyBoot, CommBufferSizeReturned}
 *sub_E4C (SmmEntryPoint core):
 * - Saves CommBuffer/Size to globals (qword_113F0/qword_113F8)
 * - Saves InLegacyBoot and CommBufferSizeReturned to qword_11400/qword_11408
 * - Saves image handle extended fields to qword_11410
 * - Sets gInSmmEntryPoint flag (ImageHandle_0+41 = 1)
 * (unless byte_14020 is set, which skips this for special modes)
 * - Executes PRE-handler callbacks: iterates off_10BA0 to qword_10BB0
 *calling each function pointer with argument 1
 * - PCH-specific SMI dispatch (if qword_141C8 and qword_14218+8 set):
 * - Checks PCH TCO status via qword_14210+8 (EFI_PCH_SMM_IO or similar)
 *with command value 318783732 (= 0x13000074, TCO_STS check)
 * - If result != 1, iterates 4 threads x 2 cores for each active
 *PCH SMM source (qword_14208+6 bitmask), calls qword_14210+40
 *with 100679988 (= 0x06000034, SMI_STS clear)
 * - AMI buffer validation: if byte_14020 is NOT set:
 * - Loads CommBuffer from ImageHandle_0+56, verifies not overlapping
 *ImageHandle_0 region (SMRAM overflow check)
 * - Calls sub_853C (AmiBufferValidation->ValidateCommBuffer)
 * - If validation OK: calls sub_3B34 (SmiManage/SmiHandlerInvoke)
 *with the actual comm buffer (skipping 24-byte AMI mailbox header)
 * - Sets ImageHandle_0+72 to EFI_NOT_FOUND or EFI_INVALID_PARAMETER
 * - Even if no comm buffer: calls sub_3B34(0,0,0,0) for root handlers
 * - Executes POST-handler callbacks: iterates off_10BA8 down to off_10BA0
 * - Restores PCH TCO state (clears the interrupt bit via mask)
 * - Clears gInSmmEntryPoint flag
 * - DEBUG "SmmEntryPoint Exit"
 *sub_3B34 (SmiHandlerInvoke):
 * - If a1 (CommBuffer) is provided: calls sub_3A5C to find matching
 *SMI_HANDLER entry by GUID from gSmiHandlerList at 0x11508
 * (signature 0x65696D73 "smie"), walks per-GUID handler chain (offset +40)
 * - If no a1: uses root "smie" handler (global at 0x114D0)
 * - For each SMHC_ENTRY (signature 0x68634D53 "SMHC") on the handler's
 *per-GUID list:
 * - Prints "Calling SMI Handler %p; Handle = 0x%X"
 * - Calls handler function with (SMHC_ENTRY*, Context, CommBuffer, Size)
 * - Processes return code:
 *0 (EFI_SUCCESS) -> returns 0 immediately if GUID match, else continues
 *0x2000000000000000 (SMI_INTERRUPT_PENDING) -> continues
 *0x2000000000000001 (SMI_INTERRUPT_PENDING_NEXT) -> sets flag, continues
 *0xA000000000000000 (SMI_NOT_HANDLED) -> continues if no GUID match
 *Other -> ASSERT(0)
 *sub_3A5C (SmiHandlerFindOrCreate - GUID lookup in gSmiHandlerList):
 * - Walks off_11508 linked list
 * - Each node is SMI_HANDLER (signature 0x65696D73 "smie") located at
 *list_entry - 8 bytes
 * - Uses sub_627C (64-bit comparison via two qword compares) to match GUID
 * - If not found and a2 (create_flag) is set: allocates 56-byte entry,
 *copies GUID, initializes per-GUID handler list, links into off_11508
 *
 *3. SMI HANDLER REGISTRATION / UNREGISTRATION:
 *sub_3C98 (SmiHandlerRegister):
 * - Params: (GUID *HandlerGuid, SMI_HANDLER_FUNC Handler,
 *EFI_HANDLE *DispatchHandle)
 * - Allocates 64-byte SMHC_ENTRY, sets signature=0x68634D53 "SMHC"
 * - Sets HandlerGuid pointer and handler function pointer
 * - If HandlerGuid is provided: calls sub_3A5C(Guid, 1) to find/create
 *the SMI_HANDLER entry in gSmiHandlerList
 * - If HandlerGuid is NULL: uses root "smie" handler (global at 0x114D0)
 *for handlers that match all SMIs
 * - Links SMHC_ENTRY onto the SMI_HANDLER's per-GUID list (offset +40)
 * - Returns SMHC_ENTRY pointer as the DispatchHandle
 *sub_3D70 (SmiHandlerUnRegister):
 * - Validates DispatchHandle signature = 0x68634D53 "SMHC"
 * - Unlinks SMHC_ENTRY from its list (sub_6464)
 * - Frees SMHC_ENTRY (sub_7A74)
 * - If the parent SMI_HANDLER's per-GUID list is now empty:
 *unlinks and frees the SMI_HANDLER entry too
 *
 *4. PROTOCOL DATABASE MANAGEMENT (Handle.c/Notify.c):
 *sub_41F4 (SmmInstallProtocolInterface):
 * - Params: (EFI_HANDLE *Handle, EFI_GUID *Protocol, VOID *Interface)
 * - Validates: Handle != NULL, Protocol != NULL, no third arg expected
 * - Debug prints: "%a %p" if name found, "%g %p" otherwise
 * - If *Handle is NULL or not found in database:
 * - Calls sub_4068 (SmmCreateProtocolEntry) to find/create PROTOCOL_ENTRY
 * - Allocates new SHND_ENTRY (0x30 bytes, signature 0x6C6E6F77 "wonk")
 *if *Handle is NULL, or validates existing handle via sub_4038
 * - Creates PRTI_ENTRY (0x40 bytes, signature 0x636C666E "nflc")
 * - Links: PRTI_ENTRY onto handle's protocol list and PROTOCOL_ENTRY's
 *protocol interface list
 * - Fires notifications: walks PROTOCOL_ENTRY's notify list (offset +56),
 *finds NOTIFY_ENTRY entries (signature 0x6E656F74 "toen" at
 *list_entry-16), calls each notify function with (Protocol, Interface, Handle)
 * - Returns *Handle (now populated)
 *sub_4598 (SmmFindProtocolInterface):
 * - Searches handle's protocol list for matching GUID+Interface
 *sub_4148 (SmmFindProtocolInterface):
 * - Searches handle's protocol list for matching GUID
 *sub_4038 (SmmValidateHandle):
 * - Validates SHND_ENTRY signature = 0x6C6E6F77 "wonk"
 *sub_4068 (SmmCreateProtocolEntry):
 * - Searches PROTOCOL_ENTRY database (off_13F60 list) for matching GUID
 * - Creates new PROTOCOL_ENTRY (signature 0x6E6F6874 "thon") if not found
 * - Links into off_13F60 global list
 *sub_4F80 (SmmLocateProtocol / SmmHandleProtocol):
 * - Locates a protocol by GUID on a given handle
 *sub_4C68 (SmmLocateHandle):
 * - Locates handles in database by protocol GUID or search type
 *
 *5. MEMORY MANAGEMENT (Page.c / Pool.c):
 *sub_4F80 (SmmAllocatePool):
 * - Params: (UINT32 PoolType, UINTN Size, VOID **Buffer)
 * - Validates PoolType is 5 (EfiRuntimeServicesCode) or 6
 * (EfiRuntimeServicesData), else ASSERT + return EFI_INVALID_PARAMETER
 * - Splits on Size+40 (header+data+tail) vs 0x800 boundary:
 *SMALL POOL PATH (<=0x800):
 * - Computes pool index: ((Size+40+63)>>6) -> next power of 2
 * - Calls sub_4C68 (SmmInternalAllocatePool) with PoolType, pool index
 * - sub_4C68: pools are indexed 0-6 per bucket. Bucket 6 uses
 *page allocator (falls through to sub_57AC for 1 page).
 *Buckets 0-5 use pool free list at unk_143A0 (96-byte stride,
 *16-byte per-index entries: unk_143A0+96*bucket+16*index).
 *If free list is empty, recursively calls with next index,
 *splits the larger block in half, marks as Available=1,
 *and links one half back into the free list.
 * - Sets POOL_HEADER signature="phd0" (0x30646870),
 *Available=0, Type=PoolType, Size=64<<index
 * - Sets POOL_TAIL signature="ptal" (0x6C617470), Size=header.Size
 * - Returns Buffer = POOL_HEADER + 0x18
 *LARGE POOL PATH (>0x800):
 * - Pages needed = (Size+40 + 0xFFF) >> 12
 * - Searches page free list (off_13F70 -> ::i linked list)
 *for a descriptor with enough pages
 * - If found: calls sub_57AC to split the allocation
 * - Calls sub_5554 to set pool type
 * - Calls sub_5260 to update free list accounting
 * - Sets POOL_PAGE header: signature="phd0", Type=PoolType,
 *Size=pages<<12
 *sub_5100 (SmmFreePool):
 * - Params: (VOID *Buffer)
 * - Computes header = Buffer - 0x18
 * - Validates POOL_HEADER: signature="phd0", Available=0
 * - Validates POOL_TAIL: signature="ptal", Size matches
 * - If total size <= 0x800: calls sub_4E64 (small free)
 *which returns the block to the pool free list
 * - If total size > 0x800: validates page alignment, calls
 *sub_59E8 (SmmFreePages) to return pages to page allocator
 *
 *6. IMAGE MANAGEMENT for MemoryAttributesTable (MemoryAttributesTable.c):
 *sub_2708 (SmmLoadImage):
 * - Loads SMM driver PE32+ image into SMRAM via firmware volume protocol
 * - Uses gBS->LoadImage and gBS->StartImage (BootServices at offset 0x60)
 * - Handles DEPEX evaluation before loading
 *sub_1E38 (SmmInsertImageRecord):
 * - Creates IMAGE_RECORD (0x40 bytes, signature "IPRD")
 * - Walks PE32+ section table, creates CODE_SECTION entries (0x28 bytes,
 *signature "SC\T") for each executable section
 * - Validates section alignment (must be 4K)
 * - Calls sub_1B7C, sub_1C40, sub_1D08 for validation and insertion
 * - Links into gImageRecordList at off_11490
 * - Updates qword_11480 (record count), qword_11488 (max code segments)
 *sub_2620 (SmmMemoryAttributesTable callback):
 * - Registered as EndOfDxe SMI handler
 * - Dumps gImageRecordList, builds memory attributes table
 * - If gMemoryProtectionAttribute & 1: sets NX on data pages
 *sub_1D08 (SmmUpdateMemoryAttributes):
 * - Applies page-level memory protection to SMRAM pages based on
 *image code segment records
 *
 *7. AMI BUFFER VALIDATION (SmmCoreAmiBufferValidationLib):
 *sub_853C (AmiBufferValidation_Validate):
 * - Entry point for SMI dispatch buffer validation
 * - Calls sub_8414 which runs the actual checks
 * - Prints "[%a]: SMM buffer security violation" on failure
 *sub_8414 (AmiBufferValidation_CheckBuffer):
 * - Checks against multiple exclusion/inclusion regions:
 *1. sub_8270(buffer, size, qword_14110, qword_14140):
 *Checks buffer is NOT in SMRAM ranges
 *2. If byte_14148 (RT check enabled):
 *a. sub_8270(buffer, size, qword_14130, qword_14150):
 *Checks buffer does NOT overlap RT driver code sections
 *b. sub_82E0(buffer, size, qword_140D8, n2):
 *Checks buffer IS in firmware-reserved RT access region
 *c. sub_834C: additional validation (MMIO ranges)
 *3. If byte_140E8 (MMIO check enabled):
 *sub_82E0(buffer, size, qword_13FA0, 2)
 *sub_8270 (AmiBufferValidation_CheckOverlap):
 * - Generic range overlap check against a region list
 *sub_82E0 (AmiBufferValidation_CheckInside):
 * - Checks buffer is inside a region list
 *sub_834C (AmiBufferValidation_CheckMmiO):
 * - Validates MMIO range permissions
 *sub_8BE8 (AmiBufferValidation_MailboxProtocol):
 * - AMI communication buffer mailbox lock/unlock protocol
 * - Params: (buffer, size, mailbox_ptr, mailbox_size_ptr)
 * - Lock flow:
 * - Validates qword_14118 (mailbox_addr) is set
 * - Validates qword_14108 (PciRootBridgeIo or similar) is set
 * - Reads CommBufferHeader_Size (offset 44) via MMIO read (function 4)
 * - Reads CommBufferHeader_Flags (offset 45) via MMIO read
 * - Checks if already locked (byte_14158 && !Flags.bit0)
 * - Checks size <= dword_14128 (supported max size, typically 0x20000)
 * - If OK: sets byte_14158=1, increments dword_14138 (session counter)
 * - Writes mailbox: {Command=1, Identifier=140F0, Sequence=counter}
 * - Writes back CommBufferHeader_Size and CommBufferHeader_Flags
 * - Unlock flow:
 * - Reads CommBufferHeader_Status (offset 40) from buffer
 * - If status == -1073741822 (EFI_ACCESS_DENIED):
 * - Checks mailbox state: Command==1, Identifier==140F0, counter matches
 * - Clears byte_14158=0, zeroes Session and Sequence
 * - Sets buffer status via sub_8B78
 *sub_90B4 (AmiBufferValidationLibInit):
 * - Initializes AMI buffer validation library
 * - Reads MMIO ranges, SMRAM ranges, RT regions from PCH config
 * - Sets up globals (qword_14108, qword_14110, qword_14118, etc.)
 *
 *8. AMI PLATFORM HOOKS (SmmCorePlatformHookLib):
 *sub_B158 (AmiSmmCorePlatformHookInit):
 * - Initializes pre/post SMI callback table at off_10BA0-0x10BA8
 * - Populates qword_10BB0 with end-of-table sentinel
 * - These callbacks are invoked on every SMI entry/exit
 *off_10BA0 (pre-SMI callbacks):
 * - Array of function pointers called at SMI entry before handler dispatch
 * - Each called with argument 1 by sub_E4C
 *off_10BA8 (post-SMI callbacks):
 * - Array of function pointers called at SMI exit after handler dispatch
 * - Each called with argument 0 by sub_E4C
 *
 *9. SMM PERFORMANCE (SmmCorePerformanceLib):
 *sub_9464 (SmmPerformanceStart):
 * - Called at SMI entry if byte_14228 (performance enabled) is set
 * - Logs "SMM" performance start marker
 *sub_9598 (SmmPerformanceEnd):
 * - Called at SMI exit if byte_14228 is set
 * - Logs "SMM" performance end marker
 *sub_9A18 (SmmPerformanceProtocolInstall):
 * - Installs SMM performance protocol
 *sub_98B8 (SmmPerformanceGetTimer):
 * - Reads hardware timer for performance measurement
 *
 * ============================================================================
 *DEBUG OUTPUT:
 * ============================================================================
 *sub_7834 - SMM debug output via serial port
 * - Checks CMOS 0x4C debug level against requested level
 * - Uses I/O ports 0x70/0x71 for CMOS access
 * - Serial output at 0x3F8 or 0x2F8 (115200 baud, 8N1)
 *sub_7908 - SMM assertion handler (calls sub_7834 then infinite loop)
 * - Format: "ASSERT [file](line): description\n"
 *
 * ============================================================================
 *KEY GLOBAL VARIABLES:
 * ============================================================================
 *0x14078: gST (SystemTable pointer)
 *0x14080: gBS (BootServices pointer)
 *0x14088: gImageHandle
 *0x14090: gRT (RuntimeServices pointer)
 *0x14098: SMST (SMM System Table pointer)
 *0x113F0: gCommBuffer (current SMI comm buffer address)
 *0x113F8: gCommBufferSize (current SMI comm buffer size)
 *0x11400: gInLegacyBoot (pointer to legacy boot flag)
 *0x11408: gCommBufferSizeReturned (pointer to size-returned field)
 *0x11410: gImageHandleExtended (extra image handle data)
 *0x11480: gImageRecordCount (number of loaded images)
 *0x11488: gMaxCodeSegmentCount (max code segments across all images)
 *0x11490: gImageRecordList (list head for IMAGE_RECORD entries)
 *0x114D0: gRootSmiHandler ("smie" root handler, matches all SMIs)
 *0x11508: gSmiHandlerList (list head for GUID-matching SMI_HANDLER entries)
 *0x11530: gGuidToNameTable (449-entry sorted table for debug name lookup)
 *0x13F60: gHandleList (list head for SHND_ENTRY global list)
 *0x13F70: gPageFreeList (list head for free page descriptors)
 *0x13F78: gPageDescriptor (::i iterator for page free list)
 *0x143A0: gPoolFreeLists (6 buckets x 7 sizes = 42 LIST_ENTRY heads)
 *0x14020: byte_14020 (flag to skip SMRAM check, possibly RAS recovery)
 *0x140D8: gCommBufferSafeRegion (list of safe comm buffer regions)
 *0x140E8: byte_140E8 (MMIO range check enable)
 *0x140F0: gMailboxIdentifier (AMI mailbox session identifier)
 *0x14108: gPciRootBridgeIo (protocol for MMIO accesses)
 *0x14110: gSmramRanges (list of SMRAM ranges for exclusion check)
 *0x14118: gMailboxAddr (AMI communication buffer mailbox address)
 *0x14128: gMaxCommBufferSize (typically 0x20000 = 128KB)
 *0x14130: gRtDriverCodeRanges (RT driver code section ranges)
 *0x14138: dword_14138 (mailbox session sequence counter)
 *0x14140: qword_14140 (SMRAM range count for exclusion)
 *0x14148: byte_14148 (RT code check enable)
 *0x14150: qword_14150 (RT code range count)
 *0x14158: byte_14158 (buffer lock state)
 *0x141C8: qword_141C8 (PCH SMM enable flag)
 *0x14208: qword_14208 (PCH SMM configuration data)
 *0x14210: qword_14210 (PCH SMM I/O protocol)
 *0x14218: qword_14218 (PCH SMM feature enable data)
 *0x14228: byte_14228 (SMM performance measurement enable)
 *0x14470: qword_14470 (memory protection attributes)
 *0x14478: qword_14478 (mFullSmramRanges backup)
 *0x14480: qword_14480 (SMST structure pointer)
 *0x14488: qword_14488 (mSmramRangeCount)
 *0x14490: qword_14490 (SMM configuration table pointer)
 *0x14498: ImageHandle_0 (global image handle reference)
 *0x10BA0: off_10BA0 (pre-SMI callback function table start)
 *0x10BA8: off_10BA8 (post-SMI callback function table start)
 *0x10BB0: qword_10BB0 (pre-callback end sentinel)
 *
 * ============================================================================
 *SMI HANDLER TABLE (at 0x11280):
 * ============================================================================
 *32-byte entries: {GUID_ptr (16 bytes?), HandlerFunc, NotifyFlag}
 *Iterated by sub_9D0 to register built-in SMI handlers via sub_3C98.
 *Terminated by null pointer at 0x11288 (first entry's handler field).
 *Known handlers:
 *0x111E0: GUID for SmmMemoryAttributesTable (sub_2620)
 *
 * ============================================================================
 *STRUCTURE SIGNATURES (validated by CR macros):
 * ============================================================================
 *0x68634D53 "SMHC" -> SMHC_ENTRY (SMI Handler Context, 64 bytes)
 *0x65696D73 "smie" -> SMI_HANDLER (per-GUID handler node, 56 bytes)
 *0x6C6E6F77 "wonk" -> SHND_ENTRY (SMM protocol handle, 48 bytes)
 *0x636C666E "nflc" -> PRTI_ENTRY (Protocol Interface, 64 bytes)
 *0x6E6F6874 "thon" -> PROTOCOL_ENTRY (Protocol Database Entry, 56 bytes)
 *0x6E656F74 "toen" -> NOTIFY_ENTRY (Protocol Notify, 48 bytes)
 *0x44525049 "IPRD" -> IMAGE_RECORD (64 bytes)
 *0x545C4353 "SC\T" -> CODE_SECTION (40 bytes)
 *0x30646870 "phd0" -> POOL_HEADER (allocated, 24 bytes)
 *0x30666870 "phf0" -> POOL_HEADER (free, 24 bytes)
 *0x6C617470 "ptal" -> POOL_TAIL (16 bytes)
 *
 * ============================================================================
 *CALLING CONVENTIONS:
 * ============================================================================
 *sub_61D0 (ZeroMem): (VOID *Buffer, UINTN Size)
 *sub_6134 (CopyMem): (VOID *Dst, VOID *Src, UINTN Size)
 *sub_6234 (CompareMem): (VOID *Buf1, VOID *Buf2, UINTN Size) -> INTN
 *sub_627C (GuidEqual): compares two qwords (GUID.Data1 + upper 4 bytes)
 * -> returns BOOLEAN
 *sub_6350 (InitializeListHead): (LIST_ENTRY *ListHead)
 *sub_6388 (InsertHeadList): (LIST_ENTRY *List, LIST_ENTRY *Entry)
 *sub_63D8 (InsertTailList): (LIST_ENTRY *List, LIST_ENTRY *Entry)
 *sub_642C (IsListEmpty): (LIST_ENTRY *List) -> BOOLEAN
 *sub_6464 (RemoveEntryList): (LIST_ENTRY *Entry)
 *sub_62E4 (IsNull): (LIST_ENTRY *List, LIST_ENTRY *Entry) -> BOOLEAN
 *sub_79A0 (AllocateZeroPool): (UINTN Size) -> VOID*
 *sub_79D0 (AllocatePool): (UINTN Size) -> VOID*
 *sub_7A74 (FreePool): (VOID *Buffer)
 *sub_7834 (DebugPrint): (UINTN ErrorLevel, CHAR8 *Format, ...)
 *sub_7908 (Assert): (CHAR8 *FileName, UINTN Line, CHAR8 *Desc)
 *
 * ============================================================================
 *SMI HANDLER RETURN CODES:
 * ============================================================================
 *0x0000000000000000: EFI_SUCCESS - handler claimed the SMI
 *0x2000000000000000: SMI_INTERRUPT_PENDING - handler needs re-dispatch
 *0x2000000000000001: SMI_INTERRUPT_PENDING_NEXT - re-dispatch requested
 *0xA000000000000000: SMI_NOT_HANDLED - handler does not claim this SMI
 */