Newer
Older
AMI-Aptio-BIOS-Reversed / StaticSkuDataDxeLightningRidgeEXECB1 / StaticSkuDataDxeLightningRidgeEXECB1.c
@Ajax Dong Ajax Dong 2 days ago 26 KB Init
/*++

StaticSkuDataDxeLightningRidgeEXECB1.c

UEFI DXE driver for static SKU data on the Intel Purley platform
(Lightning Ridge EXEC B1 revision).

This driver's purpose is to read platform SKU information from the
UEFI HOB list (handoff data from PEI phase) and register it as
multiple UBA (Universal BIOS Agent) sub-protocols.  The registered
protocols expose ACPI method outputs (_SB_.CCT0-CCT8, _SB_.CFH0,
FIX0, FIXX, FIXV, FIXY, FIXW etc.) to other DXE drivers and the
ACPI subsystem.

Build:
  PurleyRpPkg/Uba/UbaMain/Dxe/TypeLightningRidgeEXECB1/
    StaticSkuDataDxe/StaticSkuDataDxe/
      DEBUG_VS2015\StaticSkuDataDxeLightningRidgeEXECB1.pdb

References:
  - MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c
  - MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c
  - MdePkg/Library/DxeHobLib/HobLib.c
  - MdePkg/Library/BaseLib/Unaligned.c

--*/

#include "../uefi_headers/Uefi.h"
#include "StaticSkuDataDxeLightningRidgeEXECB1.h"


//
// GUID Definitions (instantiation)
//

EFI_GUID gSkuDataProtocolGuid   = SKU_DATA_PROTOCOL_GUID;
EFI_GUID gUbaProtocolGuid       = UBA_PROTOCOL_GUID;
EFI_GUID gSkuHobGuid            = SKU_HOB_GUID;
EFI_GUID gUmptProtocolGuid      = UMPT_PROTOCOL_GUID;
EFI_GUID gPirqProtocolGuid      = PIRQ_PROTOCOL_GUID;
EFI_GUID gAcpfProtocolGuid      = ACPF_PROTOCOL_GUID;

//
// Global Variables
//

//
// gImageHandle -- EFI_HANDLE for this driver image, set by
//   ModuleEntryPoint (sub_390).  Used primarily for assertions.
//
EFI_HANDLE  gImageHandle = NULL;

//
// gST -- Pointer to the UEFI System Table.
//   Set by ModuleEntryPoint (sub_390) at 0x396.
//
EFI_SYSTEM_TABLE  *gST = NULL;

//
// gBS -- Pointer to BootServices from the System Table.
//   Set by ModuleEntryPoint at 0x3E1.
//   Used for AllocatePool (offset 24) and LocateProtocol (offset 320).
//
EFI_BOOT_SERVICES  *gBS = NULL;

//
// gRT -- Pointer to RuntimeServices from the System Table.
//   Set by ModuleEntryPoint at 0x407.
//
EFI_RUNTIME_SERVICES  *gRT = NULL;

//
// gUbaProtocol -- Cached pointer to the UBA protocol interface.
//   Initialized by GetUbaProtocol() (sub_4C0).
//
UBA_PROTOCOL  *gUbaProtocol = NULL;

//
// gHobList -- Cached pointer to the start of the UEFI HOB list.
//   Initialized by GetHobList() (sub_608).
//
VOID  *gHobList = NULL;

//
// Data used for CMOS SKU check in UbaCheckCmosSku().
//
UINT8  gCmosSkuValue;  // Cached CMOS register 0x4B value


//
// External data tables (defined in the .data section of the binary).
//

extern volatile UINT8  gSkuDataProtocolGuidData[16];   // at 0x4080
extern volatile UINT8  gSkuHobGuidData[16];             // at 0x40A0

// SKU data protocol interfaces installed via UBA protocol:
extern SKU_DATA_INTERFACE_EXTENDED  gUmptProtocolData;   // at 0x40B0
extern SKU_DATA_INTERFACE           gPirqProtocolData;    // at 0x40D8
extern SKU_DATA_INTERFACE           gAcpfProtocolData;    // at 0x9020

// SKU configuration table (HOB data-derived entries):
extern SKU_CONFIG_TABLE  gSkuConfigTable;                // at 0x40F0


//
// CMOS/NVRAM Register Definitions
//

//
// CMOS register index 0x4B (decimal 75).
// On Intel Purley platforms, this register encodes the board SKU
// type:
//   < 4    -> Standard values (1 = type A, 2 = type B, 3 = type C)
//   >= 4   -> Must check memory-mapped I/O at 0xFDAF0490 bit 1.
//   0      -> Board uses MMIO-based SKU detection.
//
#define CMOS_INDEX_SKU_TYPE  0x4B

//
// RTC/CMOS I/O ports for indexed access.
//
#define RTC_INDEX_PORT   0x70
#define RTC_DATA_PORT    0x71

//
// RTC index port bits.
// Bit 7 is the NMI (Non-Maskable Interrupt) enable bit.
// When set, NMI is disabled; when clear, NMI is enabled.
//
#define RTC_INDEX_NMI_DISABLE  0x80

//
// Memory-mapped I/O address used for SKU type detection fallback.
// This is in the MMIO configuration space, typically an Intel
// platform register at:
//   ((Bus 0xFE, Dev 0xAF, Func 0x04) << 12) + register offset
//   = (0xFDAF << 12) + 0x490 = 0xFDAF0490
//
#define SKU_MMIO_DETECT_ADDR   0xFDAF0490
// Bit 1 of the MMIO register indicates the board variant.
#define SKU_MMIO_DETECT_BIT    2


//
// ACPI method name strings used in the SKU table.
// These are ASL method paths in the _SB_ (System Bus) scope.
//

#define ACPI_PATH_CCT(_N_)   "_SB_.CCT"  // Core Count Throttle (0-8)
#define ACPI_PATH_CFH        "_SB_.CFH0" // CPU Family/Health
#define ACPI_PATH_FIX(_N_)   "FIX"       // Platform SKU info (0, X, V, Y, W)


//
// ModuleEntryPoint (sub_390)
//

/**
  Entry point for the StaticSkuDataDxe Lightning Ridge EXECB1 driver.

  This is the standard UEFI DXE driver entry point.  It:
    1. Saves ImageHandle, SystemTable, BootServices, RuntimeServices
       to global variables (with NULL checks).
    2. Initializes the HOB list via GetHobList().
    3. Locates the UBA protocol handle using
       BootServices->LocateProtocol(UBA_PROTOCOL_GUID, NULL, &Handle).
    4. Registers three sub-protocols on the returned handle:
       a. UMPT_PROTOCOL_GUID  (24-byte interface at 0x40B0)
       b. PIRQ_PROTOCOL_GUID  (16-byte interface at 0x40D8)
       c. ACPF_PROTOCOL_GUID  (16-byte interface at 0x9020)

  The UBA protocol's method at offset 0x10 (UBA_PROTOCOL.RegisterProtocol)
  is used for each registration call.

  @param[in] ImageHandle  The firmware allocated handle for this driver.
  @param[in] SystemTable  A pointer to the EFI System Table.

  @return EFI_SUCCESS  The driver initialized and registered all SKU
                       data sub-protocols successfully.
  @return Other        Status from LocateProtocol or RegisterProtocol.
**/
EFI_STATUS
EFIAPI
ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS  Status;
  EFI_HANDLE  UbaHandle;

  //
  // Step 1: Save UEFI core pointers to globals.
  // These are used by the UBA ASSERT macros and protocol lookups.
  //

  gImageHandle = ImageHandle;
  if (gImageHandle == NULL) {
    //
    // ASSERT: gImageHandle != NULL.
    // File: MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c
    // Line: 51
    //
    UbaAssert (
      "e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
      51,
      "gImageHandle != ((void *) 0)"
      );
  }

  gST = SystemTable;
  if (gST == NULL) {
    //
    // ASSERT: gST != NULL.
    // Line: 57
    //
    UbaAssert (
      "e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
      57,
      "gST != ((void *) 0)"
      );
  }

  gBS = SystemTable->BootServices;
  if (gBS == NULL) {
    //
    // ASSERT: gBS != NULL.
    // Line: 63
    //
    UbaAssert (
      "e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
      63,
      "gBS != ((void *) 0)"
      );
  }

  gRT = SystemTable->RuntimeServices;
  if (gRT == NULL) {
    //
    // ASSERT: gRT != NULL.
    // File: UefiRuntimeServicesTableLib.c, line 47
    //
    UbaAssert (
      "e:\\hs\\MdePkg\\Library\\UefiRuntimeServicesTableLib\\UefiRuntimeServicesTableLib.c",
      47,
      "gRT != ((void *) 0)"
      );
  }

  //
  // Step 2: Initialize the HOB list.
  // This scans SystemTable->ConfigurationTable for the HOB list GUID.
  //
  GetHobList ();

  //
  // Step 3: Locate the UBA protocol handle.
  // BootServices->LocateProtocol (at BootServices offset 0x140 = 320
  // in the function table).  Returns a handle through which we
  // register sub-protocols.
  //
  UbaHandle = NULL;
  Status = gBS->LocateProtocol (
                  &gUbaProtocolGuid,
                  NULL,          // Registration (none)
                  &UbaHandle
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Step 4a: Register UMPT protocol.
  // Method at offset 0x10 of the UBA_PROTOCOL.
  //
  Status = ((UBA_PROTOCOL *)UbaHandle)->RegisterProtocol (
                                          &gUmptProtocolGuid,
                                          &gUmptProtocolData,
                                          sizeof (SKU_DATA_INTERFACE_EXTENDED)
                                          );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Step 4b: Register PIRQ protocol.
  //
  Status = ((UBA_PROTOCOL *)UbaHandle)->RegisterProtocol (
                                          &gPirqProtocolGuid,
                                          &gPirqProtocolData,
                                          sizeof (SKU_DATA_INTERFACE)
                                          );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Step 4c: Register ACPF protocol.
  //
  Status = ((UBA_PROTOCOL *)UbaHandle)->RegisterProtocol (
                                          &gAcpfProtocolGuid,
                                          &gAcpfProtocolData,
                                          sizeof (SKU_DATA_INTERFACE)
                                          );
  return Status;
}


//
// GetUbaProtocol (sub_4C0 at 0x4C0)
//

/**
  Retrieves the UBA (Universal BIOS Agent) protocol interface pointer.

  Uses BootServices->AllocatePool (offset 24 = slot 3) with pool type
  EfiBootServicesData (value 31) to allocate a pool buffer.  If the
  allocation succeeds with buffer size <= 0x10 (16 bytes), the function
  attempts to locate the UBA protocol via BootServices->LocateProtocol
  (offset 320 = slot 40).

  On success, the protocol pointer is cached in the global gUbaProtocol
  and returned.  On failure (protocol not found, or pool too small),
  returns NULL.

  The pool allocation size of 31 (0x1F) is a probing allocation used
  to check whether the BootServices pointer is valid before performing
  the LocateProtocol call.

  NOTE: The "<= 16" check on the allocated pool size is unusual.
  It may indicate that:
    - The AllocatePool function returns a buffer with metadata, and
      the effective data size must be >= 0x10 for the protocol header.
    - Or this is a debugging/validation check.

  @return  Pointer to the UBA_PROTOCOL interface, or NULL if not found.
**/
UBA_PROTOCOL *
GetUbaProtocol (
  VOID
  )
{
  UBA_PROTOCOL  *Protocol;
  VOID          *PoolBuffer;
  EFI_STATUS    Status;

  //
  // Return cached pointer if already located.
  //
  if (gUbaProtocol != NULL) {
    return gUbaProtocol;
  }

  //
  // Attempt a probing pool allocation.
  // Pool type 31 = EfiBootServicesData.
  //
  PoolBuffer = gBS->AllocatePool (31);
  gBS->FreePool (PoolBuffer);

  if (PoolBuffer != NULL && (UINTN)PoolBuffer <= 0x10) {
    //
    // Pool allocation succeeded and resulted in a low address
    // (indicating the Boot Services table is functional).
    // Now try to locate the UBA protocol.
    //
    Status = gBS->LocateProtocol (
                    &gUbaProtocolGuid,
                    NULL,
                    (VOID **)&Protocol
                    );
    if (!EFI_ERROR (Status)) {
      gUbaProtocol = Protocol;
      return Protocol;
    }

    //
    // LocateProtocol failed; clear the cached pointer.
    //
    gUbaProtocol = NULL;
    return NULL;
  }

  return NULL;
}


//
// UbaAssert (sub_5C8 at 0x5C8)
//

/**
  UBA assertion/debug helper function.

  If the UBA protocol is available (via GetUbaProtocol), this function
  calls the protocol's method at offset 0x08 (UBA_PROTOCOL->Method8),
  which takes three arguments: FileName, LineNumber, and Expression.

  The purpose of this method is to log/display an ASSERT failure
  message via the UBA protocol's debug infrastructure, rather than
  using the standard UEFI ASSERT macro.

  @param[in] FileName    Source file name string (e.g., path to .c file).
  @param[in] LineNumber  Line number in the source file where the ASSERT
                         condition failed.
  @param[in] Expression  The failed ASSERT expression as a string.
**/
VOID
UbaAssert (
  IN CHAR8   *FileName,
  IN UINTN   LineNumber,
  IN CHAR8   *Expression
  )
{
  UBA_PROTOCOL  *Protocol;

  Protocol = GetUbaProtocol ();
  if (Protocol != NULL) {
    //
    // Call the ASSERT/debug method at protocol offset 0x08.
    // This is not the same as RegisterProtocol (offset 0x10).
    // The offset 0x08 method signature is:
    //   (CHAR8 *FileName, UINTN LineNumber, CHAR8 *Expression)
    //
    ((EFI_STATUS (EFIAPI *)(CHAR8 *, UINTN, CHAR8 *))
      (((UINT64 *)Protocol)[1])) (
      FileName,
      LineNumber,
      Expression
      );
  }
}


//
// UbaCheckCmosSku (sub_540 at 0x540)
//

/**
  Checks CMOS register 0x4B to determine the board SKU type, then
  tests whether a given assertion flag is set for this SKU.

  This function implements platform-specific SKU detection:
    1. Reads the current RTC index register (saving NMI bit).
    2. Selects CMOS index 0x4B.
    3. Reads the data byte from CMOS register 0x4B.
    4. Interprets the SKU type:
       - n3 > 3:        Use memory-mapped I/O at 0xFDAF0490
                         (bit 1 determines type: (value & 2) | 1)
       - n3 == 0:       (handled by the >3 check: both fall through
                         to MMIO path if n3 > 3 is true but 0 is not > 3;
                         only >3 and n3==0 cases lead to MMIO -- wait,
                         the logic is:
                         if (n3 > 3) {
                           if (!n3)   // impossible since n3>3 here, so
                             n3 = (MEMORY[0xFDAF0490] & 2) | 1;
                         }
                         Actually this means: if n3 > 3, we still keep
                         n3 as-is, AND if n3 were 0 (dead path) we'd
                         go MMIO.  The MMIO path is effectively dead
                         code in this '>3' branch.
                         REAL interpretation: the compiler generated
                         this structure from conditionals; the true
                         MMIO fallback happens for n3 > 3 || n3 == 0,
                         which is always true for n3 > 3.
                         In practice, n3 > 3 is rare.
       - n3 == 1:       Board type A, flags = 0x80000004
       - n3 == 2 or 3:  Board type B/C, flags = 0x80000006
       - default:        Returns 4 (no assertion, do nothing)

    5. If (Flags & AssertFlag) is non-zero, calls the UBA protocol's
       RegisterProtocol (offset 0x10) to register a data protocol.
    6. Returns the method result.

  Actually (re-analyzed from decompilation):

    n3 = ReadCmos(0x4B)
    v4 = 0
    if (n3 != 0) {
      // Check if n3 > 3 -> special case
      if (n3 > 3 || n3 == 0) {
        n3 = (ReadMmio(SKU_MMIO_DETECT_ADDR) & 2) | 1;
      }
      v3 = n3 - 1   // normalize to 0-based
      if (v3 <= 253) {  // i.e. n3 >= 1 and n3 <= 254
        v3 = 4;          // default result
        v4 = 0x80000006; // flags for SKU type B/C
        if (n3 == 1) {
          v4 = 0x80000004; // flags for SKU type A
        }
      }
    }

    if (v4 & a1) {
      // Call UBA protocol RegisterProtocol with ASSERT info
      return (*v5)(a1, _nASSERT..., va);
    }

  @param[in] AssertFlag  Bitmask to check against the platform flags.
                          Typically 0x80000000LL (EFI_ERROR check) or
                          0x80000004LL (type A) / 0x80000006LL (type
                          B/C).

  @return  The result of the UBA protocol call, or 4 if no action needed.
**/
UINT8
UbaCheckCmosSku (
  IN UINT64   AssertFlag
  )
{
  UBA_PROTOCOL  *Protocol;
  UINT64        Flags;
  UINT8         CmosValue;
  UINT8         Result;
  UINT8         RegIndex;

  Protocol = GetUbaProtocol ();
  Flags = 0;
  Result = 0;

  if (Protocol != NULL) {
    //
    // Read the current RTC index register to preserve NMI state.
    //
    RegIndex = IoRead8 (RTC_INDEX_PORT);

    //
    // Set RTC index to CMOS register 0x4B, preserving NMI bit.
    //
    IoWrite8 (RTC_INDEX_PORT, (RegIndex & RTC_INDEX_NMI_DISABLE) | CMOS_INDEX_SKU_TYPE);

    //
    // Read CMOS data byte.
    //
    CmosValue = IoRead8 (RTC_DATA_PORT);

    //
    // Apply SKU detection logic.
    //
    if ((UINT8)CmosValue > 3) {
      //
      // SKU value > 3 is unexpected.  Fall back to MMIO detection.
      // (In practice, this branch is rare for well-defined SKUs.)
      //
      if (CmosValue == 0) {
        CmosValue = (MmioRead8 (SKU_MMIO_DETECT_ADDR) & SKU_MMIO_DETECT_BIT) | 1;
      }
    }

    //
    // Normalize: result = n3 - 1
    // If n3 >= 1 and n3 <= 254, set default flags.
    //
    Result = CmosValue - 1;
    if ((UINT8)Result <= 0xFD) {
      //
      // Default result when no assertion fires.
      //
      Result = 4;
      Flags = 0x80000006;   // SKU type B/C flags
      if (CmosValue == 1) {
        Flags = 0x80000004; // SKU type A flags
      }
    }

    //
    // If the required assertion flag is set in the platform flags,
    // invoke the UBA protocol's RegisterProtocol (method @ +0x10)
    // to register an assert-like protocol entry.
    //
    if ((Flags & AssertFlag) != 0) {
      Result = (UINT8)Protocol->RegisterProtocol (
                                  (EFI_GUID *)AssertFlag,
                                  (VOID *)&CmosValue,
                                  (UINTN *)&Flags
                                  );
    }
  }

  return Result;
}


//
// GetHobList (sub_608 at 0x608)
//

/**
  Scans the UEFI configuration tables to find the HOB (Hand-Off Block)
  list pointer.

  The HOB list is produced in the PEI phase and passed to DXE via the
  UEFI System Table's configuration table array.  The configuration
  table entries have the format:
    struct {
      EFI_GUID  VendorGuid;    // +0: 16-byte GUID
      VOID      *VendorTable;  // +16: pointer to the table data
    };
  This function iterates through all entries in the array
  (SystemTable->ConfigurationTable) looking for a specific
  vendor table GUID.

  The GUID used for matching is EFI_HOB_LIST_GUID:
    { 0x7739F24C, 0x93D7, 0x11D4,
      { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }
  Actually it matches the GUID stored at 0x40A0 (gSkuHobGuid).

  @param[in] a1  The GUID to match against (used in CompareGuidQwords).
                  In the actual implementation the GUID is from a fixed
                  location in the data section.

  @return  Pointer to the HOB list base, or 0 if not found.
           Cached in gHobList.
**/
VOID *
GetHobList (
  VOID
  )
{
  UINTN   Index;
  UINTN   EntryCount;
  VOID    *ConfigTable;
  VOID    *HobList;

  //
  // Return cached pointer if already initialized.
  //
  if (gHobList != NULL) {
    return gHobList;
  }

  //
  // Assume no HOB list found initially.
  //
  gHobList = NULL;
  HobList = NULL;
  EntryCount = gST->NumberOfTableEntries;

  if (EntryCount != 0) {
    //
    // Iterate through configuration table entries.
    // Each entry is 24 bytes: 16-byte GUID + 8-byte pointer.
    //
    for (Index = 0; Index < EntryCount; Index++) {
      ConfigTable = (VOID *)((UINTN)gST->ConfigurationTable + (Index * 24));

      //
      // Compare GUIDs: check if the table entry's GUID matches.
      // The match checks two QWORDs (16 bytes):
      //   CompareGuidQwords reads 8 bytes from each GUID.
      //   If first 8 bytes AND second 8 bytes both match, we found it.
      //
      if (CompareGuidQwords (&gSkuHobGuid, ConfigTable)) {
        //
        // Found matching entry; extract the table pointer.
        // The pointer is at offset 16 = 0x10 within the entry.
        //
        HobList = *(VOID **)((UINTN)ConfigTable + 16);
        gHobList = HobList;
        break;
      }
    }

    //
    // If HOB list was not found, fire assertion.
    //
    if (HobList == NULL) {
      //
      // Print the EFI_ERROR status first.
      //
      UbaCheckCmosSku (
        0x80000000LL,
        "\nASSERT_EFI_ERROR (Status = %r)\n",
        0x800000000000000ELL
        );

      //
      // ASSERT: EFI_ERROR(Status) -- Status is EFI_NOT_FOUND.
      //
      UbaAssert (
        "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
        54,
        "!EFI_ERROR (Status)"
        );
    }

    //
    // Verify the HOB list pointer is not NULL.
    //
    if (HobList == NULL) {
      UbaAssert (
        "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
        55,
        "mHobList != ((void *) 0)"
        );
    }
  }

  return gHobList;
}


//
// CompareGuidQwords (sub_6E0 at 0x6E0)
//

/**
  Compares two GUIDs by comparing their first 8 bytes and second
  8 bytes independently as 64-bit values.

  This is a fast non-standard GUID comparison used by GetHobList.
  Instead of calling CompareGuid() from the UEFI spec, it compares
  two UINT64 halves of the GUID structure.  Because EFI_GUID is
  defined as:
    typedef struct {
      UINT32  Data1;  // 4 bytes at offset 0
      UINT16  Data2;  // 2 bytes at offset 4
      UINT16  Data3;  // 2 bytes at offset 6
      UINT8   Data4[8]; // 8 bytes at offset 8
    } EFI_GUID;
  The first QWORD (offset 0) contains Data1+Data2+Data3.
  The second QWORD (offset 8) contains Data4[0..7].
  Comparing these as two UINT64 values is equivalent to a full
  GUID comparison.

  @param[in]  Guid1  Pointer to the first GUID to compare.
  @param[in]  Guid2  Pointer to the second GUID (e.g., from the
                      SystemTable configuration table entry).

  @retval TRUE  All bytes of the two GUIDs match.
  @retval FALSE The GUIDs differ.
**/
BOOLEAN
EFIAPI
CompareGuidQwords (
  IN EFI_GUID  *Guid1,
  IN EFI_GUID  *Guid2
  )
{
  UINT64  FirstHalf1;
  UINT64  FirstHalf2;
  UINT64  SecondHalf1;
  UINT64  SecondHalf2;

  //
  // Read the first 8 bytes of each GUID as a UINT64.
  //
  FirstHalf1 = ReadUnaligned64 ((VOID *)Guid1);
  FirstHalf2 = ReadUnaligned64 ((VOID *)Guid2);

  //
  // Read the second 8 bytes of each GUID.
  //
  SecondHalf1 = ReadUnaligned64 ((VOID *)((UINTN)Guid1 + 8));
  SecondHalf2 = ReadUnaligned64 ((VOID *)((UINTN)Guid2 + 8));

  //
  // Both halves must match for the GUID to be equal.
  //
  return (FirstHalf1 == FirstHalf2) && (SecondHalf1 == SecondHalf2);
}


//
// ReadUnaligned64 (sub_750 at 0x750)
//

/**
  Reads a 64-bit value from an unaligned buffer pointer.

  This is a simple dereference of a UINT64*.  The function is named
  after the BaseLib UEFI library function ReadUnaligned64(), which is
  defined in MdePkg/Library/BaseLib/Unaligned.c.

  The function asserts if the Buffer pointer is NULL.

  @param[in]  Buffer  Pointer to the buffer to read (may be unaligned).
                       Must not be NULL.

  @return  The UINT64 value at the given address.
**/
UINT64
EFIAPI
ReadUnaligned64 (
  IN VOID  *Buffer
  )
{
  //
  // Assert if Buffer is NULL.
  //
  if (Buffer == NULL) {
    UbaAssert (
      "e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
      192,
      "Buffer != ((void *) 0)"
      );
  }

  return *(UINT64 *)Buffer;
}


//
// ReadUnaligned32 (helper wrapper, not in this binary but in standard BaseLib)
//

/**
  Reads a 32-bit value from an unaligned buffer pointer.

  @param[in]  Buffer  Pointer to the buffer to read.

  @return  The UINT32 value at the given address.
**/
UINT32
EFIAPI
ReadUnaligned32 (
  IN UINT32  *Buffer
  )
{
  if (Buffer == NULL) {
    UbaAssert (
      "e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
      192,
      "Buffer != ((void *) 0)"
      );
  }

  return *Buffer;
}


///
/// SKU Configuration Table
///
/// Starting at offset 0x40F0 from the image base, the SKU configuration
/// table is embedded in the .data section.  Its content is HOB-derived
/// platform configuration data organized as an array of 32-byte entries.
///
/// The table header is:
///   16 bytes: SKU table identifier (GUID-like, partially zero)
///
/// Each entry (32 bytes) describes a specific platform configuration
/// value.  The names referenced by the table include:
///
///   Entry 0:  "FIX0"    - FIX method 0
///   Entries 1-9: "FIXX" (with sub-id 01-08) - Extended FIX methods
///   Entries 10-18: "FIXV" (with sub-id 02-08) - Vendor FIX methods
///   Entries 19-25: unnamed (data_type=0x0A, ASCII strings)
///   Entries 26-27: "FIXY"/"FIXW" - More FIX variants
///   ... repeating pattern of FIXY/FIXW pairs ...
///
/// The data_type field determines interpretation:
///   0x0A: The data payload is an ASCII string.
///   0x0C: The data payload contains an ACPI method name (like "FIX0").
///   0x0E: The data payload contains 16-bit values / numeric data.
///
/// The ACPI method references _SB_.CCT0 through _SB_.CCT8 and _SB_.CFH0
/// are stored as ASCII strings in .rdata at 0x7C8-0x858 and referenced
/// by the SKU table entries via their offset fields.
///
/// The actual SKU data (the payloads for FIX0, FIXX, etc.) begins at
/// offset 0x5B80 in the image (0x5B80 + 0x4080 = 0x9C00 area), though
/// the precise layout depends on how the HOB data was produced by the
/// PEI phase via the PCD (Platform Configuration Database).
///


/*++
  Notes on the UBA Protocol Registration:

  The UBA protocol found via LocateProtocol at offset 0x140 in
  BootServices (slot 40) is:

    Protocol GUID: {E03E0D46-5263-4845-B0A4-58D57B3177E2}

  Its interface has three known methods at offsets 0x00, 0x08, 0x10:
    [0x00]: Some initialization/query method.
    [0x08]: Debug/assert handler.  Called by UbaAssert() with
            (FileName, LineNumber, Expression).
    [0x10]: RegisterProtocol.  Called with
            (ProtocolGuid, InterfaceData, InterfaceSize).
            This registers a sub-protocol on the UBA handle so that
            other DXE drivers can locate it via their own GUID.

  The three sub-protocols registered by this driver are:

    1. UMPT ({0FF8A1CF-A0AB-4AC0-BFC9-34A78F68DD8A})
       Interface (24 bytes, at 0x40B0):
         Tag     = 'UMPT'  (0x54504D55)
         Version = 1
         Data1   = 0x9060  (pointer to additional UMPT data)
         Data2   = 0x9040  (pointer to resource descriptors)

    2. PIRQ ({4C1F48A5-C976-4D90-9F03-8E9B1C327FCF})
       Interface (16 bytes, at 0x40D8):
         Tag     = 'PIRQ'  (0x51524950)
         Version = 1
         Data    = 0x90D8  (pointer to PIRQ data table)

    3. ACPF ({46504341-0001-0000-0041-000000000000})
       Interface (16 bytes, at 0x9020):
         Tag     = 'ACPF'  (0x46504341)
         Version = 1
         Data    = 0x4100  (ACPI platform flags/version)

  The data tables at 0x9040, 0x9060, and 0x90D8 contain pairs of
  (Offset, Size) entries describing ACPI resource descriptors or
  ACPI _CRS (Current Resource Settings) for the platform.

  CMOS Register 0x4B Encoding:
    0x01 = Board revision A (flags = 0x80000004)
    0x02 = Board revision B (flags = 0x80000006)
    0x03 = Board revision C (flags = 0x80000006)
    >3   = Fall back to MMIO detection
    0x00 = (invalid for production, MMIO fallback)
++*/