Newer
Older
AMI-Aptio-BIOS-Reversed / CpPlatPkg / Whea / WheaSupport / WheaSupport.c
@Ajax Dong Ajax Dong 2 days ago 28 KB Restructure the repo
//-------------------------------------------------------------------------
// WheaSupport.c - WHEA Support DXE Driver for Lenovo HR650X BIOS
// Module: CpPlatPkg/Whea/WheaSupport/WheaSupport.c
// PE file: 0309_WheaSupport_95b18380d0d5 (from HR650X_3647_AJAX_BIOS)
//
// Build info:
//   Source: e:\hs\CpPlatPkg\Whea\WheaSupport\WheaSupport.c
//   Build:  DEBUG_VS2015 X64
//   Image:  HR6N0XMLK
//   GUID:   {36232936-0E76-31C8-A13A-3AF2FC1C3932}
//
// This DXE driver implements Windows Hardware Error Architecture (WHEA)
// support. It constructs ACPI WHEA tables in memory and installs them
// via SMM communication at ReadyToBoot:
//   - HEST (Hardware Error Source Table)  - 0x8000 bytes
//   - ERST (Error Record Serialization)   - 0x2000 bytes
//   - BERT (Boot Error Record Table)      - 0x8000 bytes
//   - EINJ (Error Injection Table)        - 0x2000 bytes
//
// The driver also allocates a shared communication buffer (0xE000 bytes)
// at 0x4000 offset for HEST+ERST data, 0x6000 offset for BERT.
//-------------------------------------------------------------------------

#include "WheaSupport.h"

//-------------------------------------------------------------------------
// Global Variables (from IDA - .data section, imagebase 0x0)
//-------------------------------------------------------------------------

// Module globals (set during WheaSupportEntry)
EFI_HANDLE                gImageHandle      = NULL;    // 0x1FF0
EFI_SYSTEM_TABLE         *gSystemTable      = NULL;    // 0x1FE0
EFI_BOOT_SERVICES        *gBootServices     = NULL;    // 0x1FE8
EFI_RUNTIME_SERVICES     *gRuntimeServices  = NULL;    // 0x1FF8

// WHEA instance allocations (from WheaDriverInit)
VOID                     *gHest             = NULL;    // 0x1F38: 0x8000
VOID                     *gErst             = NULL;    // 0x1F40: 0x2000
VOID                     *gEinj             = NULL;    // 0x1F50: 0x2000
VOID                     *gBert             = NULL;    // 0x1F48: 0x8000

// Shared SMM communication buffer
VOID                     *gCommBuffer       = NULL;    // 0x1F68: 0xE000

// Pointers into comm buffer
VOID                     *gSharedData       = NULL;    // 0x1F58
VOID                     *gHestErstData     = NULL;    // 0x1F78: at +0x4000
VOID                     *gBertData         = NULL;    // 0x1F88: at +0x6000

UINT8                    gEinjEntryCount    = 8;       // 0x1FD8: 8 or 9 entries
UINT32                   gSize0x4000        = 0x4000;  // 0x1F60
UINT32                   gSize0x2000        = 0x2000;  // 0x1F70
UINT32                   gSize0x8000        = 0x8000;  // 0x1F80
CHAR8                    gWheaStr[]         = "WHEA";  // 0x1F30

// Protocol handles
VOID                     *gSmmCommProtocol  = NULL;    // 0x1FD0
VOID                     *gDebugPort        = NULL;    // 0x2000
VOID                     *gPcdProtocol      = NULL;    // 0x2020
VOID                     *gDS               = NULL;    // 0x2008
VOID                     *gPciUsra          = NULL;    // 0x2010
VOID                     *gHobList          = NULL;    // 0x2018

// Function table for WHEA protocol
VOID                     *gFnCreateHest     = NULL;    // 0x1FA0
VOID                     *gFnGetErst        = NULL;    // 0x1FA8
VOID                     *gFnSetEinj        = NULL;    // 0x1FB0
VOID                     *gFnGetEinjCtx     = NULL;    // 0x1FB8
VOID                     *gFnGetBert        = NULL;    // 0x1FC0
VOID                     *gFnSetErst        = NULL;    // 0x1FC8

//-------------------------------------------------------------------------
// CR (CONTAINING_RECORD) macros
//
// The WHEA instance uses signature 0x41424344 ("ABCD") at offset -112 bytes
// from the checked field pointer.
//-------------------------------------------------------------------------
#define WHEA_INSTANCE_SIG  0x41424344ULL
#define WHEA_CR_OFFSET     0x70

#define WHEA_CR_FROM_FIELD(Ptr, Field)                                 \
  ((Ptr) != NULL &&                                                     \
   *((UINT64 *)(Ptr) - (WHEA_CR_OFFSET / sizeof(UINT64))) ==           \
       WHEA_INSTANCE_SIG                                                \
   ? ((VOID *)((UINT64 *)(Ptr) - (WHEA_CR_OFFSET / sizeof(UINT64))))   \
   : NULL)

//-------------------------------------------------------------------------
// InternalCopyMem (0x2A0)
//
// memmove with overlap handling.
//-------------------------------------------------------------------------
char *
InternalCopyMem (char *dst, char *src, UINT64 count)
{
  char *orig_dst = dst;

  if (src < dst && &src[count - 1] >= dst) {
    // Backward copy for overlapping regions
    src = &src[count - 1];
    dst = &dst[count - 1];
    goto DO_COPY;
  }

  // Forward copy in 8-byte chunks
  {
    UINT64 count_8 = count >> 3;
    count &= 7;
    qmemcpy(dst, src, 8 * count_8);
    src += 8 * count_8;
    dst += 8 * count_8;
  }

DO_COPY:
  qmemcpy(dst, src, count);
  return orig_dst;
}

//-------------------------------------------------------------------------
// InternalZeroMem (0x2F0)
//
//-------------------------------------------------------------------------
char *
InternalZeroMem (char *buf, UINT64 size)
{
  memset(buf, 0, 8 * (size >> 3));
  memset(&buf[8 * (size >> 3)], 0, size & 7);
  return buf;
}

//-------------------------------------------------------------------------
// _ModuleEntryPoint / WheaSupportEntry / WheaDriverInit
//
// Entry: standard UEFI DXE entry, chains into driver init.
//-------------------------------------------------------------------------
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  WheaSupportEntry(ImageHandle, SystemTable);
  return WheaDriverInit();
}

//-------------------------------------------------------------------------
// WheaSupportEntry (0x358)
//
// Initializes UEFI boot services / runtime services globals,
// locates DxeServicesTable, PCI USRA protocol, HOB list, PCD protocol.
//-------------------------------------------------------------------------
__int64
WheaSupportEntry (__int64 ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
  __int64 Status;

  // Save globals
  gImageHandle = (EFI_HANDLE)ImageHandle;
  if (!ImageHandle)
    DebugAssert("e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
      51, "gImageHandle != ((void *) 0)");

  gSystemTable = SystemTable;
  if (!SystemTable)
    DebugAssert("e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
      57, "gST != ((void *) 0)");

  gBootServices = SystemTable->BootServices;
  if (!gBootServices)
    DebugAssert("e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
      63, "gBS != ((void *) 0)");

  gRuntimeServices = SystemTable->RuntimeServices;
  if (!gRuntimeServices)
    DebugAssert(
      "e:\\hs\\MdePkg\\Library\\UefiRuntimeServicesTableLib\\UefiRuntimeServicesTableLib.c",
      47, "gRT != ((void *) 0)");

  // Locate DxeServicesTable
  Status = EfiGetSystemConfigurationTable(&gEfiDxeServicesTableGuid, &gDS);
  if (Status < 0) {
    DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
    DebugAssert("e:\\hs\\MdePkg\\Library\\DxeServicesTableLib\\DxeServicesTableLib.c",
      64, "!EFI_ERROR (Status)");
  }
  if (!gDS)
    DebugAssert("e:\\hs\\MdePkg\\Library\\DxeServicesTableLib\\DxeServicesTableLib.c",
      65, "gDS != ((void *) 0)");

  if (Status < 0) {
    DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
    DebugAssert(
      "e:\\hs\\Build\\HR6N0XMLK\\DEBUG_VS2015\\X64\\CpPlatPkg\\Whea\\WheaSupport\\WheaSupport\\DEBUG\\AutoGen.c",
      300, "!EFI_ERROR (Status)");
  }

  // Locate PCI USRA protocol (for MM PCI config access)
  if (!gPciUsra) {
    Status = gBootServices->LocateProtocol(&gEfiMmPciBaseProtocolGuid, NULL, &gPciUsra);
    if (Status < 0) {
      DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
      DebugAssert("e:\\hs\\CpRcPkg\\Library\\DxeMmPciBaseLib\\DxeMmPciBaseLib.c",
        52, "!EFI_ERROR (Status)");
    }
    if (!gPciUsra)
      DebugAssert("e:\\hs\\CpRcPkg\\Library\\DxeMmPciBaseLib\\DxeMmPciBaseLib.c",
        53, "mPciUsra != ((void *) 0)");
  }

  GetHobList();
  return ((__int64 (*)(UINTN))(((UINT8 *)GetPcdProtocol()) + 32))(5);
}

//-------------------------------------------------------------------------
// WheaCreateHestErrorSrcDescriptor (0x524)
//
// Creates a HEST error source descriptor in the HEST table area.
//
// Types:
//   0 = IA-32 Machine Check (standard)     -- 656 bytes
//   1 = IPMI                              -- 664 bytes
//   6 = PCIe Root Port AER                -- 48 bytes (16+32)
//   7 = PCIe Device AER                   -- 44 bytes (16+28)
//   8 = PCIe Bridge AER                   -- 56 bytes (16+40)
//   9 = Generic Hardware Error Source     -- variable
//-------------------------------------------------------------------------
UINT64
WheaCreateHestErrorSrcDescriptor (
  _QWORD *a1, INT32 n6, CHAR8 a3, CHAR8 a4,
  UINT16 *a5, INT32 a6, INT32 a7, __int64 a8
  )
{
  _QWORD *Instance;
  __int64 HestBase;
  __int64 Dst;
  INT32   DescSize;
  INT32   DataSize;

  Instance = a1;
  if (!a1)
    return EFI_INVALID_PARAMETER;

  // CR: find containing struct (-14 qwords = -112 bytes)
  if (*(a1 - 14) == WHEA_INSTANCE_SIG)
    Instance = a1 - 14;
  else
    DebugAssert("e:\\hs\\CpPlatPkg\\Whea\\WheaSupport\\WheaSupport.c",
      86, "CR has Bad Signature");

  HestBase = Instance[1];                          // HEST table ptr
  Dst = HestBase + *(UINT32 *)(HestBase + 4);     // current end offset

  if (n6 == 0) {
    *(UINT16 *)Dst = 0;
    DescSize = 656;
    DataSize = 640;
    goto COMMON;
  }
  if (n6 == 1) {
    *(UINT16 *)Dst = 1;
    DescSize = 664;
    DataSize = 648;
    goto COMMON;
  }
  if (n6 < 6 || n6 > 9)
    return EFI_UNSUPPORTED;

  if (n6 == 9) {
    // Type 9: Generic Hardware Error Source
    UINT64 maxLen;

    DescSize = 64;
    maxLen = MAX(*(UINT32 *)(a8 + 2), *(UINT32 *)(a8 + 46));
    if (Instance[5] + maxLen + 8 > 0x4000)
      return EFI_OUT_OF_RESOURCES;
    *(UINT64 *)(a8 + 10) = Instance[7];
    *(UINT64 *)Instance[7] = Instance[7] + 8;
    *(UINT8 *)(a8 + 6) = 0;
    *(UINT16 *)(a8 + 7) = 64;
    *(UINT8 *)(a8 + 9) = 4;
    Instance[7] += maxLen + 8;
    Instance[5] += maxLen + 8;

    *(UINT16 *)Dst = 9;
    *a5 = *(UINT16 *)(HestBase + 36);
    *(UINT16 *)(Dst + 2) = *(UINT16 *)(HestBase + 36);
    *(UINT16 *)(Dst + 4) = *(UINT16 *)a8;
    *(UINT8 *)(Dst + 7) = (a4 == 1);
    *(UINT32 *)(Dst + 8) = a6;
    *(UINT32 *)(Dst + 12) = a7;
    *(UINT8 *)(Dst + 6) = a3;
    *(UINT32 *)(Dst + 16) = *(UINT32 *)(a8 + 2);
    gBootServices->CopyMem((VOID *)(Dst + 20), (VOID *)(a8 + 6), 12);
    gBootServices->CopyMem((VOID *)(Dst + 32), (VOID *)(a8 + 18), 28);
    *(UINT32 *)(Dst + 60) = *(UINT32 *)(a8 + 46);
    goto DONE;
  }

  // Types 6, 7, 8 (PCIe AER)
  *(UINT16 *)Dst = n6;
  *a5 = *(UINT16 *)(HestBase + 36);
  *(UINT16 *)(Dst + 2) = *(UINT16 *)(HestBase + 36);
  *(UINT8 *)(Dst + 7) = (a4 == 1);
  *(UINT32 *)(Dst + 8) = a6;
  *(UINT32 *)(Dst + 12) = a7;
  *(UINT16 *)(Dst + 4) = 0;
  *(UINT8 *)(Dst + 6) = a3;

  switch (n6 - 6) {
  case 0: DataSize = 32; break;
  case 1: DataSize = 28; break;
  default:DataSize = 40; break;
  }
  gBootServices->CopyMem((VOID *)(Dst + 16), (VOID *)a8, DataSize);
  DescSize = DataSize + 16;
  goto DONE;

COMMON:
  *a5 = *(UINT16 *)(HestBase + 36);
  *(UINT16 *)(Dst + 2) = *(UINT16 *)(HestBase + 36);
  *(UINT8 *)(Dst + 7) = (a4 == 1);
  *(UINT32 *)(Dst + 8) = a6;
  *(UINT32 *)(Dst + 12) = a7;
  *(UINT16 *)(Dst + 4) = 0;
  *(UINT8 *)(Dst + 6) = a3;
  gBootServices->CopyMem((VOID *)(Dst + 16), (VOID *)a8, DataSize);

DONE:
  *(UINT32 *)(HestBase + 4) += DescSize;
  ++*(UINT32 *)(HestBase + 36);
  return 0;
}

//-------------------------------------------------------------------------
// WheaGetErstRecordCount (0x7DC)
//
// Dummy: returns 0 (no ERST records).
//-------------------------------------------------------------------------
UINT64 WheaGetErstRecordCount (VOID) { return 0; }

//-------------------------------------------------------------------------
// WheaSetEinjConfig (0x7E0)
//
// Configure EINJ table error injection entries.
// CR offset: -0x70 (112 bytes)
//-------------------------------------------------------------------------
UINT64
WheaSetEinjConfig (__int64 a1, __int64 Context, __int64 a3, __int64 EntryData)
{
  __int64 Instance;

  Instance = a1;
  if (!a1) return EFI_INVALID_PARAMETER;
  if (*(UINT64 *)(a1 - 112) == WHEA_INSTANCE_SIG)
    Instance = a1 - 112;
  else
    DebugAssert(SOURCE_FILE, 250, "CR has Bad Signature");

  if (gEinjEntryCount > 10)
    DebugAssert(SOURCE_FILE, 252, "mEinjEntries <= 10");

  // Set EinjContext at Instance+0x68, EinjEntryCount in table
  *(UINT64 *)(Instance + 0x68) = Context;
  *(UINT32 *)(*(UINT64 *)(Instance + 0x20) + 0x2C) = gEinjEntryCount;
  gBootServices->CopyMem(
    (VOID *)(*(UINT64 *)(Instance + 0x20) + 0x30),
    (VOID *)EntryData,
    32 * gEinjEntryCount);

  // EINJ table length based on entries
  if (gEinjEntryCount == 9)
    *(UINT32 *)(*(UINT64 *)(Instance + 0x20) + 4) = 336;
  else
    *(UINT32 *)(*(UINT64 *)(Instance + 0x20) + 4) = 304;
  return 0;
}

//-------------------------------------------------------------------------
// WheaGetEinjContext (0x8BC)
//-------------------------------------------------------------------------
UINT64
WheaGetEinjContext (__int64 a1, UINT64 *Context)
{
  __int64 Instance;

  Instance = a1;
  if (!a1) return EFI_INVALID_PARAMETER;
  if (*(UINT64 *)(a1 - 112) == WHEA_INSTANCE_SIG)
    Instance = a1 - 112;
  else
    DebugAssert(SOURCE_FILE, 283, "CR has Bad Signature");
  *Context = *(UINT64 *)(Instance + 0x68);
  return 0;
}

//-------------------------------------------------------------------------
// WheaGetBertContext (0x91C)
//-------------------------------------------------------------------------
UINT64
WheaGetBertContext (__int64 a1, UINT64 *BertRegion, UINT64 *BertRegionSize)
{
  __int64 Instance;

  Instance = a1;
  if (!a1) return EFI_INVALID_PARAMETER;
  if (*(UINT64 *)(a1 - 112) == WHEA_INSTANCE_SIG)
    Instance = a1 - 112;
  else
    DebugAssert(SOURCE_FILE, 309, "CR has Bad Signature");

  *BertRegion     = *(UINT64 *)(Instance + 0x40);
  *BertRegionSize = *(UINT64 *)(Instance + 0x48);

  return (*BertRegion && *BertRegionSize) ? 0 : EFI_NOT_FOUND;
}

//-------------------------------------------------------------------------
// WheaSetErstConfig (0x9A8)
//-------------------------------------------------------------------------
UINT64
WheaSetErstConfig (__int64 a1, UINT64 EntryCount, __int64 EntryData)
{
  __int64 Instance;

  Instance = a1;
  if (!a1) return EFI_INVALID_PARAMETER;
  if (*(UINT64 *)(a1 - 112) == WHEA_INSTANCE_SIG)
    Instance = a1 - 112;
  else
    DebugAssert(SOURCE_FILE, 341, "CR has Bad Signature");

  if (EntryCount > 16)
    DebugAssert(SOURCE_FILE, 343, "InstCount <= 16");

  *(UINT32 *)(*(UINT64 *)(Instance + 0x10) + 0x2C) = (UINT32)EntryCount;
  gBootServices->CopyMem(
    (VOID *)(*(UINT64 *)(Instance + 0x10) + 0x30),
    (VOID *)EntryData,
    32 * EntryCount);

  *(UINT32 *)(*(UINT64 *)(Instance + 0x10) + 4) = 560;
  return 0;
}

//-------------------------------------------------------------------------
// WheaInstallTables (0xA5C)
//
// Installs HEST, ERST, BERT, EINJ tables via SMM communication protocol.
// Calls ->Communicate() for each table, then frees buffers.
//-------------------------------------------------------------------------
UINT64
WheaInstallTables (__int64 Instance)
{
  UINT64 Status;
  UINT64 v15;

  if (!Instance) return EFI_INVALID_PARAMETER;
  if (*(UINT8 *)(Instance + 0x60))               // already installed
    return EFI_ALREADY_STARTED;

  if (gSmmCommProtocol) {
    DebugPrint(0x80000000, "WheaSupport. Install Whea Tables \n");

    // HEST
    v15 = 0;
    Status = ((UINT64 (*)(UINT64, UINT64, UINT32, UINT64 *))gSmmCommProtocol)(
      (UINT64)gSmmCommProtocol,
      *(UINT64 *)(Instance + 0x08),
      *(UINT32 *)(*(UINT64 *)(Instance + 0x08) + 4),
      &v15);

    // ERST
    v15 = 0;
    Status |= ((UINT64 (*)(UINT64, UINT64, UINT32, UINT64 *))gSmmCommProtocol)(
      (UINT64)gSmmCommProtocol,
      *(UINT64 *)(Instance + 0x18),
      *(UINT32 *)(*(UINT64 *)(Instance + 0x18) + 4),
      &v15);

    // BERT
    v15 = 0;
    Status |= ((UINT64 (*)(UINT64, UINT64, UINT32, UINT64 *))gSmmCommProtocol)(
      (UINT64)gSmmCommProtocol,
      *(UINT64 *)(Instance + 0x10),
      *(UINT32 *)(*(UINT64 *)(Instance + 0x10) + 4),
      &v15);

    // EINJ
    v15 = 0;
    Status |= ((UINT64 (*)(UINT64, UINT64, UINT32, UINT64 *))gSmmCommProtocol)(
      (UINT64)gSmmCommProtocol,
      *(UINT64 *)(Instance + 0x20),
      *(UINT32 *)(*(UINT64 *)(Instance + 0x20) + 4),
      &v15);

    if (Status < 0) {
      DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
      DebugAssert(SOURCE_FILE, 378, "!EFI_ERROR (Status)");
    }

    // Mark installed and free tables
    *(UINT8 *)(Instance + 0x60) = 1;
    gBootServices->FreePool((VOID *)*(UINT64 *)(Instance + 0x08));
    gBootServices->FreePool((VOID *)*(UINT64 *)(Instance + 0x18));
    gBootServices->FreePool((VOID *)*(UINT64 *)(Instance + 0x10));
    gBootServices->FreePool((VOID *)*(UINT64 *)(Instance + 0x20));
  }
  return 0;
}

//-------------------------------------------------------------------------
// WheaReadyToBootNotify (0xBBC)
//
// ReadyToBoot callback: calls WheaInstallTables.
// Tolerates EFI_ALREADY_STARTED (0x8000000000000014).
//-------------------------------------------------------------------------
EFI_STATUS
EFIAPI
WheaReadyToBootNotify (IN EFI_EVENT Event, IN VOID *Context)
{
  EFI_STATUS Status;

  Status = WheaInstallTables((__int64)Context);
  if (Status < 0 && Status != EFI_ALREADY_STARTED) {
    DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
    return DebugAssert(SOURCE_FILE, 402, "!EFI_ERROR (Status)");
  }
  return Status;
}

//-------------------------------------------------------------------------
// WheaDriverInit (0xC10) - Main init function
//
// 1. Locate WHEA protocol (skip if already)
// 2. Allocate HEST (0x8000), ERST (0x2000), EINJ (0x2000), BERT (0x8000)
// 3. Fill ACPI table headers with sig/revision/OEM data
//    HEST: 0x54534548, ERST: 0x54535245, EINJ: 0x4A4E4945, BERT: 0x54524542
// 4. Allocate comm buffer (0xE000) and partition it
// 5. Register WHEA protocol interface
// 6. Locate SMM Communication protocol
// 7. Register ReadyToBoot callback
//-------------------------------------------------------------------------
EFI_STATUS
WheaDriverInit (VOID)
{
  UINT8          n9;
  UINT64         v4, v5, v8, v9;
  UINT64         v10;
  __int64        v11;
  __int64        v15;

  v10 = (__int64)&v15;                             // ImageHandle capture
  v11 = 0;

  // Locate WHEA protocol - if found, skip init (already registered)
  if (gBootServices->LocateProtocol(&gWheaProtocolGuid, NULL, &v11) < 0
      || !((UINT8 (*)(__int64))(v11 + 8))(v11))
    return EFI_UNSUPPORTED;

  // Allocate tables
  gHest = AllocateZeroPool(0x8000);
  if (!gHest) DebugAssert(SOURCE_FILE, 476, "mWheaInst.Hest != NULL");
  gErst = AllocateZeroPool(0x2000);
  if (!gErst) DebugAssert(SOURCE_FILE, 478, "mWheaInst.Erst != NULL");
  gEinj = AllocateZeroPool(0x2000);
  if (!gEinj) DebugAssert(SOURCE_FILE, 480, "mWheaInst.Einj != NULL");
  gBert = AllocateZeroPool(0x8000);
  if (!gBert) DebugAssert(SOURCE_FILE, 482, "mWheaInst.Bert != NULL");

  // HEST header
  if (gHest) {
    *(UINT32 *)gHest = 0x54534548;                // "HEST"
    *(UINT32 *)((UINT8 *)gHest + 4) = 40;
    *(UINT32 *)((UINT8 *)gHest + 36) = 0;
    *(UINT8 *)((UINT8 *)gHest + 8) = 1;
    *(UINT8 *)((UINT8 *)gHest + 9) = 0;
    InitAcpiTableHeader((__int64)gHest);
  }

  // ERST header
  if (gErst) {
    *(UINT32 *)gErst = 0x54535245;                // "ERST"
    *(UINT32 *)((UINT8 *)gErst + 4) = 560;
    *(UINT32 *)((UINT8 *)gErst + 36) = 48;
    *(UINT32 *)((UINT8 *)gErst + 44) = 0;
    *(UINT8 *)((UINT8 *)gErst + 8) = 1;
    *(UINT8 *)((UINT8 *)gErst + 9) = 0;
    InitAcpiTableHeader((__int64)gErst);
  }

  // BERT header
  if (gBert) {
    *(UINT32 *)gBert = 0x54524542;                // "BERT"
    *(UINT32 *)((UINT8 *)gBert + 4) = 48;
    *(UINT8 *)((UINT8 *)gBert + 8) = 1;
    *(UINT8 *)((UINT8 *)gBert + 9) = 0;
    InitAcpiTableHeader((__int64)gBert);
  }

  // EINJ header (determine entries from HW-reduced flag)
  if (gEinj) {
    *(UINT32 *)gEinj = 0x4A4E4945;                // "EINJ"
    if (*(UINT8 *)(v11 + 4) == 1) {               // HW-reduced ACPI?
      *(UINT32 *)((UINT8 *)gEinj + 4) = 336;
      n9 = 9;
    } else {
      *(UINT32 *)((UINT8 *)gEinj + 4) = 304;
      n9 = 8;
    }
    gEinjEntryCount = n9;
    *(UINT32 *)((UINT8 *)gEinj + 36) = 12;
    *(UINT32 *)((UINT8 *)gEinj + 44) = n9;
    *(UINT8 *)((UINT8 *)gEinj + 8) = 1;
    *(UINT8 *)((UINT8 *)gEinj + 9) = 0;
    InitAcpiTableHeader((__int64)gEinj);
  }

  // Allocate SMM communication buffer (0xE000)
  v4 = gBootServices->AllocatePool(EfiBootServicesData, 57344, &gCommBuffer);
  if (v4 < 0) {
    DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", v4);
    DebugAssert(SOURCE_FILE, 535, "!EFI_ERROR (Status)");
  }
  gBootServices->SetMem(gCommBuffer, 57344, 0);

  // Partition: [0x0000-reserved][0x4000-HEST/ERST data][0x6000-BERT region]
  gSharedData   = NULL;                            // placeholder
  gHestErstData = (UINT8 *)gCommBuffer + 0x4000;
  gBertData     = (UINT8 *)gCommBuffer + 0x6000;

  // BERT error region
  *(UINT32 *)((UINT8 *)gBert + 36) = 0x8000;
  *(UINT64 *)((UINT8 *)gBert + 40) = (UINT64)gBertData;

  // Function table for protocol
  v10 = 0;
  gFnCreateHest = (VOID *)WheaCreateHestErrorSrcDescriptor;
  gFnGetErst    = (VOID *)WheaGetErstRecordCount;
  gFnSetEinj    = (VOID *)WheaSetEinjConfig;
  gFnGetEinjCtx = (VOID *)WheaGetEinjContext;
  gFnGetBert    = (VOID *)WheaGetBertContext;
  gFnSetErst    = (VOID *)WheaSetErstConfig;

  v5 = gBootServices->InstallProtocolInterface(
         &v10, &gWheaProtocolGuid,
         EFI_NATIVE_INTERFACE,
         &gFnCreateHest);
  if (v5 < 0) {
    DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", v5);
    DebugAssert(SOURCE_FILE, 567, "!EFI_ERROR (Status)");
  }

  // Locate SMM Communication protocol
  gSmmCommProtocol = NULL;
  gBootServices->LocateProtocol(&gSmmCommunicationProtocolGuid, NULL, &gSmmCommProtocol);

  // Register ReadyToBoot event
  v8 = RegisterWheaReadyToBoot();
  v9 = v8;
  if (v8 < 0) {
    DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", v8);
    DebugAssert(SOURCE_FILE, 584, "!EFI_ERROR (Status)");
  }
  return v9;
}

//-------------------------------------------------------------------------
// DebugLibConstructor (0x1068)
// DebugPrint (0x10E8)
// DebugAssert (0x1170)
//
// Standard UEFI debug library functions used by MDE modules.
// See edk2/MdePkg/Library/UefiDebugLibStdErr/
//-------------------------------------------------------------------------

__int64 DebugLibConstructor (VOID)
{
  UINT64 result = (UINT64)gDebugPort;
  if (!gDebugPort) {
    UINT64 tsc;
    tsc = gBootServices->GetTimerValue(31);
    gBootServices->RestoreTimerValue(tsc);
    if (tsc <= 0x10) {
      if (gBootServices->LocateProtocol(&gEfiDebugPortProtocolGuid, NULL, &gDebugPort) >= 0)
        return (__int64)gDebugPort;
      gDebugPort = NULL;
    }
    return 0;
  }
  return result;
}

CHAR8 DebugPrint(__int64 ErrorLevel, const CHAR8 *Format, ...)
{
  va_list va;
  UINT64  DebugPort;
  UINT64  FilterMask;
  UINT8   n3;

  va_start(va, Format);

  DebugPort = DebugLibConstructor();
  FilterMask = 0;
  if (DebugPort) {
    // Read debug level from CMOS reg 0x4B
    __outbyte(0x70, __inbyte(0x70) & 0x80 | 0x4B);
    n3 = __inbyte(0x71);

    if ((UINT8)n3 > 3)
      if (!n3)
        n3 = (UINT8)(MEMORY[0xFDAF0490] & 2) | 1;

    if ((UINT8)(n3 - 1) <= 0xFD)
      FilterMask = (n3 == 1) ? 0x80000004 : 0x80000006;

    if ((FilterMask & ErrorLevel) != 0)
      ((__int64 (*)(__int64, const CHAR8 *, va_list))DebugPort)(ErrorLevel, Format, va);
  }
  return 0;
}

__int64 DebugAssert(__int64 FileName, __int64 LineNumber, __int64 Description)
{
  __int64 result = DebugLibConstructor();
  if (result)
    return (*(__int64 (__fastcall **)(__int64, __int64, __int64))(result + 8))(
      FileName, LineNumber, Description);
  return result;
}

//-------------------------------------------------------------------------
// Memory allocation helpers
//-------------------------------------------------------------------------

VOID *AllocatePool(UINTN PoolType, UINTN AllocationSize)
{
  VOID *Buf = NULL;
  if (gBootServices->AllocatePool(PoolType, AllocationSize, &Buf) < 0)
    return NULL;
  return Buf;
}

VOID *AllocateZeroPool(UINTN Size)
{
  VOID *Buf = AllocatePool(EfiBootServicesData, Size);
  if (Buf) Buf = ZeroMem(Buf, Size);
  return Buf;
}

//-------------------------------------------------------------------------
// EfiGetSystemConfigurationTable (0x1208)
//-------------------------------------------------------------------------
EFI_STATUS
EfiGetSystemConfigurationTable (IN EFI_GUID *TableGuid, OUT VOID **Table)
{
  UINT64 i, count;

  if (!TableGuid) DebugAssert(STR_LIB_UEFI_C, 97, "TableGuid != NULL");
  if (!Table)    DebugAssert(STR_LIB_UEFI_C, 98, "Table != NULL");

  *Table = NULL;
  count = *(UINT64 *)((UINT8 *)gSystemTable + 0x68);
  if (!count) return EFI_NOT_FOUND;

  for (i = 0; ; i += 24) {
    if (CompareGuid(TableGuid,
          *(EFI_GUID **)((UINT8 *)gSystemTable + 0x70) + i / sizeof(EFI_GUID)))
      break;
    if (i / 24 + 1 >= count)
      return EFI_NOT_FOUND;
  }

  *Table = *(VOID **)(*(UINT64 *)((UINT8 *)gSystemTable + 0x70) + i + 16);
  return 0;
}

//-------------------------------------------------------------------------
// RegisterWheaReadyToBoot (0x12CC)
//-------------------------------------------------------------------------
EFI_STATUS RegisterWheaReadyToBoot (VOID)
{
  if (*(UINT32 *)((UINT8 *)gSystemTable + 8) >= 0x20000) {
    return gBootServices->CreateEventEx(
             EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
             WheaReadyToBootNotify, (VOID *)"WHEA",
             &gEfiEventReadyToBootGuid,
             (EFI_EVENT *)&gEventBuffer);
  }
  DebugPrint(0x80000000, "EFI1.1 can't support ReadyToBootEvent!");
  DebugAssert("e:\\hs\\MdePkg\\Library\\UefiLib\\UefiNotTiano.c", 185, "((BOOLEAN)(0==1))");
  return EFI_UNSUPPORTED;
}

//-------------------------------------------------------------------------
// GetHobList (0x1354)
// GetPcdProtocol (0x15D0)
// InitAcpiTableHeader (0x13D8)
// CopyMem (0x1458)
// ZeroMem (0x14F8)
// CompareGuid (0x1568)
// ReadUnaligned64 (0x165C)
//-------------------------------------------------------------------------

VOID *GetHobList (VOID)
{
  if (!gHobList) {
    if (EfiGetSystemConfigurationTable(&gEfiHobListGuid, &gHobList) < 0) {
      DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", 0);
      DebugAssert("e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c", 54, "!EFI_ERROR (Status)");
    }
    if (!gHobList)
      DebugAssert("e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c", 55, "mHobList != NULL");
  }
  return gHobList;
}

VOID *GetPcdProtocol (VOID)
{
  if (!gPcdProtocol) {
    if (gBootServices->LocateProtocol(&gEfiPcdProtocolGuid, NULL, &gPcdProtocol) < 0) {
      DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", 0);
      DebugAssert("e:\\hs\\MdePkg\\Library\\DxePcdLib\\DxePcdLib.c", 78, "!EFI_ERROR (Status)");
    }
    if (!gPcdProtocol)
      DebugAssert("e:\\hs\\MdePkg\\Library\\DxePcdLib\\DxePcdLib.c", 79, "mPcd != NULL");
  }
  return gPcdProtocol;
}

UINT64 InitAcpiTableHeader (__int64 Table)
{
  __int64 Pcd1, Pcd2;
  CHAR8   OemId[6];
  CHAR8   OemTableId[8];

  // Set initial OEM placeholder
  *(UINT32 *)(Table + 10) = 0x454D4F49;           // "OEM "
  *(UINT16 *)(Table + 14) = 0x2020;               // "  "

  Pcd1 = GetPcdProtocol();
  Pcd2 = GetPcdProtocol();

  // Get OEM values from PCD protocol
  // PcdGet32(32) = OEM ID, PcdGet32(31) = OEM Table ID
  *(UINT64 *)&OemTableId = ((UINT64 (*)(UINT32))(((UINT8 *)Pcd1) + 32))(32);
  CopyMem((VOID *)OemId, (VOID *)((UINT8 *)Pcd2 + 40), 6);

  CopyMem((VOID *)(Table + 10), OemId, 6);
  CopyMem((VOID *)(Table + 16), &OemTableId, 8);

  *(UINT32 *)(Table + 24) = 1;                     // Creator ID
  *(UINT32 *)(Table + 28) = 1280593481;            // Creator Rev
  *(UINT32 *)(Table + 32) = 1;                     // OEM Revision
  return 1;
}

VOID *CopyMem (VOID *Dest, CONST VOID *Src, UINTN Len)
{
  if (!Len) return Dest;
  if ((UINTN)(Len - 1) > ~(UINTN)Dest)
    DebugAssert(STR_COPYMEM_C, 56, STR_OFFSET_CHECK);
  if ((UINTN)(Len - 1) > ~(UINTN)Src)
    DebugAssert(STR_COPYMEM_C, 57, STR_OFFSET_CHECK2);
  if (Dest != Src)
    return InternalCopyMem((char *)Dest, (char *)Src, Len);
  return Dest;
}

VOID *ZeroMem (VOID *Buf, UINTN Len)
{
  if (!Len) return Buf;
  if (!Buf) DebugAssert(STR_ZEROMEM_C, 53, "Buffer != NULL");
  if (Len > ~(UINTN)Buf)
    DebugAssert(STR_ZEROMEM_C, 54, STR_LENGTH_CHECK);
  return InternalZeroMem((char *)Buf, Len);
}

BOOLEAN CompareGuid (CONST EFI_GUID *g1, CONST EFI_GUID *g2)
{
  return ReadUnaligned64(g1) == ReadUnaligned64(g2)
      && ReadUnaligned64((UINT8 *)g1 + 8) == ReadUnaligned64((UINT8 *)g2 + 8);
}

UINT64 ReadUnaligned64 (CONST VOID *Buf)
{
  if (!Buf) DebugAssert("e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c", 192, "Buffer != NULL");
  return *(UINT64 *)Buf;
}