Newer
Older
AMI-Aptio-BIOS-Reversed / PcAtChipsetPkg / PcatRealTimeClockSmm / PcatRealTimeClockSmm / PcRtcSmm / PcRtcSmm.c
@Ajax Dong Ajax Dong 2 days ago 78 KB Restructure the repo
/** @file
  PcRtcSmm.c - PcAtChipsetPkg PcatRealTimeClockSmm UEFI SMM RTC driver

  Reconstructed decompilation of PcRtcSmm.efi (HR650X server, index 0171)
  Original source: e:\hs\PcAtChipsetPkg\PcatRealTimeClockSmm\PcRtcSmm.c
  Build:           e:\hs\Build\HR6N0XMLK\DEBUG_VS2015\X64\PcAtChipsetPkg\PcatRealTimeClockSmm\

  This SMM driver manages the MC146818-compatible RTC controller from SMM context.
  It registers four SMM Runtime Services Call (RSC) handlers via the SMM_RSC_HANDLER_PROTOCOL:
    handler[0] = GetTime      (sub_84C -> sub_C28)
    handler[1] = SetTime      (sub_854 -> sub_D20)
    handler[2] = GetWakeupTime (sub_870 -> sub_EC8)
    handler[3] = SetWakeupTime (sub_87C -> sub_1074)

  The driver is linked with the following libraries:
    - UefiBootServicesTableLib   (global gImageHandle, gST, gBS)
    - UefiRuntimeServicesTableLib (global gRT)
    - SmmServicesTableLib         (global gSmst)
    - SmmMemoryAllocationLib      (SMRAM range management)
    - BaseLib                     (SetJump/LongJump, BCD conversion, CompareGuid, unaligned)
    - BaseMemoryLibRepStr         (CopyMem, ZeroMem)
    - BaseIoLibIntrinsic          (IoRead8/IoWrite8 ports 0x70/0x71 and __indword port 0x508)
    - DebugLib                    (DebugPrint, DebugAssert)
    - DxePcdLib                   (PCD protocol access)
    - SmmPciExpressLib            (PCIe config space MMIO via PCD database base)
    - DxeHobLib                   (HOB list lookup via gEfiHobListGuid)

  RTC CMOS I/O ports:   0x74 (index, SMM alias), 0x75 (data, SMM alias)
  Standard PC CMOS:     0x70 (index), 0x71 (data)
**/

#include "PcRtcSmm.h"

//
// RTC Register Ports (SMM alias)
//
#define RTC_ADDRESS_PORT        0x74
#define RTC_DATA_PORT           0x75

//
// RTC Register Indices
//
#define RTC_SECONDS             0x00
#define RTC_SECONDS_ALARM       0x01
#define RTC_MINUTES             0x02
#define RTC_MINUTES_ALARM       0x03
#define RTC_HOURS               0x04
#define RTC_HOURS_ALARM         0x05
#define RTC_DAY_OF_WEEK         0x06
#define RTC_DAY_OF_MONTH        0x07
#define RTC_MONTH               0x08
#define RTC_YEAR                0x09
#define RTC_REGISTER_A          0x0A
#define RTC_REGISTER_B          0x0B
#define RTC_REGISTER_C          0x0C
#define RTC_REGISTER_D          0x0D

//
// Register A bits
//
#define RTC_A_UIP               BIT7   // Update In Progress

//
// Register B bits
//
#define RTC_B_DSE               BIT0   // Daylight Savings Enable
#define RTC_B_24HR              BIT1   // 0=12hr mode, 1=24hr mode
#define RTC_B_DM                BIT2   // 0=BCD, 1=binary
#define RTC_B_SQWE              BIT3   // Square Wave Enable
#define RTC_B_UIE               BIT4   // Update Ended Interrupt Enable
#define RTC_B_AIE               BIT5   // Alarm Interrupt Enable
#define RTC_B_PIE               BIT6   // Periodic Interrupt Enable
#define RTC_B_SET               BIT7   // SET=1 freezes updates to allow write

//
// Register D bits
//
#define RTC_D_VRT               BIT7   // Valid RAM and Time

//
// Helper macros for RTC register access via SMM I/O ports
//
#define RTC_READ8(reg)          (IoWrite8(RTC_ADDRESS_PORT, reg), IoRead8(RTC_DATA_PORT))
#define RTC_WRITE8(reg, val)    (IoWrite8(RTC_ADDRESS_PORT, reg), IoWrite8(RTC_DATA_PORT, val))

// ============================================================================
// Module Global Variables (mapped from .data section at 0x2A20-0x2C40)
// ============================================================================

//
// Standard EFI globals (set by UefiBootServicesTableLib / UefiRuntimeServicesTableLib)
//
EFI_HANDLE              gImageHandle      = NULL;     // 0x2AB8
EFI_SYSTEM_TABLE        *gST              = NULL;     // 0x2AA8
EFI_BOOT_SERVICES       *gBS              = NULL;     // 0x2AB0
EFI_RUNTIME_SERVICES    *gRT              = NULL;     // 0x2AC0

//
// SMM globals (resolved via SmmServicesTableLib)
//
EFI_SMM_SYSTEM_TABLE2   *gSmst            = NULL;     // 0x2AC8
EFI_SMM_BASE2_PROTOCOL  *gSmmBase2        = NULL;     // resolved from GUID at 0x2A60

//
// SMM Runtime RSC Handler Protocol
//   qword_2AA0: pointer to the SMM_RSC_HANDLER_PROTOCOL found by scanning
//   gSmst->ProtocolRegistry with gEfiSmmRscHandlerGuid
//   Layout: +0 Unknown  +8 Unknown  +16 Unknown  +24 Handler[0]  +32 Handler[1]
//           +40 Handler[2]  +48 Handler[3]  +56 SmmVariableRead  +64 SmmVariableWrite
//           +72 SmmGetVariable  +80 SmmSetVariable  +88 SmmDeleteVariable
//           96  SmmEndOfDxe  +104 SmmAllocatePages  +112 SmmFreePages +120 SmmAllocatePool
//
VOID                    *gSmmRuntimeRsc   = NULL;     // 0x2AA0 (qword_2AA0)
VOID                    *gSmmCpuProtocol  = NULL;     // 0x2AE8 (qword_2AE8, lazy-init from GUID 0x2A20)
VOID                    *gSmmCpuInterface = NULL;     // 0x2AF0 (qword_2AF0, SMM CPU I/O2 interface)

//
// SMM Variable Protocol (lazy-init)
//
VOID                    *gSmmVariable     = NULL;     // 0x2AD0 (qword_2AD0)

//
// Platform type from PCD protocol
//
UINT64                  gPcdDbValue       = 0;        // 0x2AD8: PcdGet32(PcdPlatformType) result
VOID                    *gPcdDb           = NULL;     // 0x2AF8 (PCD protocol pointer)

//
// HOB list (lazy-init via gEfiHobListGuid)
//
VOID                    *gHobList         = NULL;     // 0x2AE0 (qword_2AE0)

//
// SMRAM range tracking
//
UINT64                  *gSmramRanges     = NULL;     // 0x2C18
UINT64                  gSmramRangeCount  = 0;        // 0x2C10

//
// RTC state globals
//
UINT16                  gRtcTimeZone      = 2047;     // 0x2C38: EFI_UNSPECIFIED_TIMEZONE
UINT8                   gRtcDaylight      = 0;        // 0x2C3A
UINT8                   gRtcCenturyOffset = 0x32;     // 0x2C3B (n50): CMOS offset for century byte

//
// RTC Config Structure (28 bytes at 0x2C20: unk_2C20)
// Used by sub_D20 (SetTime) and sub_EC8 (GetWakeupTime) to save/restore
// configuration across operations.
//
PC_RTC_CONFIG           gRtcConfig;                   // 0x2C20

//
// EFI System Return Status for module entry
//
UINT64                  gModuleEntryStatus = 0x8000000000000001ULL; // 0x2C08

//
// SetJump/LongJump buffer
//
UINT8                   gJumpBuffer[320];             // 0x2B10 (unk_2B10)

//
// Debug port scratch (byte at 0x2B00)
//
UINT8                   gDebugPortScratch;            // 0x2B00

//
// Forward declarations for internal functions
//
STATIC
EFI_STATUS
PcRtcGetCentury (
  OUT UINT8  *Century
  );

// ============================================================================
// CPU intrinsic wrappers (sub_470, sub_480, sub_490, sub_4A0, sub_4B0)
// ============================================================================

/**
  CPU PAUSE instruction (sub_470 at 0x470)
**/
VOID
EFIAPI
CpuPause (
  VOID
  )
{
  _mm_pause ();
}

/**
  Read the CPU timestamp counter (sub_480 at 0x480)
**/
UINT64
EFIAPI
ReadTsc (
  VOID
  )
{
  return __rdtsc ();
}

/**
  Enable interrupts (sub_490 at 0x490)
**/
VOID
EFIAPI
EnableInterrupts (
  VOID
  )
{
  _enable ();
}

/**
  Disable interrupts (sub_4A0 at 0x4A0)
**/
VOID
EFIAPI
DisableInterrupts (
  VOID
  )
{
  _disable ();
}

/**
  Get caller's EFLAGS (sub_4B0 at 0x4B0)
**/
UINT64
EFIAPI
GetCallerEflags (
  VOID
  )
{
  return __getcallerseflags ();
}

// ============================================================================
// Library support functions
// ============================================================================

/**
  SetJump - save CPU context (sub_280 at 0x280)

  Saves all callee-saved registers (GPRs GPRs rbx, rbp, rdi, rsi, r12-r15),
  stack pointer (via retaddr), return address, MXCSR, and XMM6-15 to the
  jump buffer.

  @param[out] JumpBuffer  Aligned buffer (16-byte alignment required).

  @return  Non-zero when SetJump returns via a LongJump, zero on initial call.
**/
UINTN
EFIAPI
SetJump (
  OUT VOID  *JumpBuffer  // actually JUMP_BUFFER * (at least 320 bytes)
  )
{
  UINTN  Result;

  //
  // Validate the jump buffer pointer and alignment
  //
  PcRtcValidateJumpBuffer (JumpBuffer);

  //
  // Save registers: rbx, rbp, rdi, rsi, r12, r13, r14, r15
  // followed by return address and MXCSR
  //
  *(UINT64 *)(JumpBuffer + 0)   = rbx;
  *(UINT64 *)(JumpBuffer + 8)   = &Result;            // stack pointer proxy
  *(UINT64 *)(JumpBuffer + 16)  = rbp;
  *(UINT64 *)(JumpBuffer + 24)  = rdi;
  *(UINT64 *)(JumpBuffer + 32)  = rsi;
  *(UINT64 *)(JumpBuffer + 40)  = r12;
  *(UINT64 *)(JumpBuffer + 48)  = r13;
  *(UINT64 *)(JumpBuffer + 56)  = r14;
  *(UINT64 *)(JumpBuffer + 64)  = r15;
  *(UINT64 *)(JumpBuffer + 72)  = __builtin_return_address (0);
  * (UINT32 *)(JumpBuffer + 80) = _mm_getcsr ();      // MXCSR

  //
  // Save XMM6-XMM15 (128-bit each)
  //
  * (UINT128 *)(JumpBuffer + 88)  = xmm6;
  * (UINT128 *)(JumpBuffer + 104) = xmm7;
  * (UINT128 *)(JumpBuffer + 120) = xmm8;
  * (UINT128 *)(JumpBuffer + 136) = xmm9;
  * (UINT128 *)(JumpBuffer + 152) = xmm10;
  * (UINT128 *)(JumpBuffer + 168) = xmm11;
  * (UINT128 *)(JumpBuffer + 184) = xmm12;
  * (UINT128 *)(JumpBuffer + 200) = xmm13;
  * (UINT128 *)(JumpBuffer + 216) = xmm14;
  * (UINT128 *)(JumpBuffer + 232) = xmm15;

  return __builtin_return_address (0);
}

/**
  LongJump - restore CPU context (sub_320 at 0x320)

  Restores MXCSR and jumps to the saved return address.

  @param[in] JumpBuffer  Buffer previously filled by SetJump.
  @param[in] Value       Return value for the SetJump call site.
**/
VOID
EFIAPI
LongJump (
  IN VOID    *JumpBuffer,
  IN UINTN   Value
  )
{
  _mm_setcsr (* (UINT32 *)(JumpBuffer + 80));
  //
  // Jump through the saved return address (offset 72 in jump buffer)
  //
  ((VOID (*)(UINTN))(*(UINT64 *)(JumpBuffer + 72)))(Value);
}

/**
  CopyMem - copy buffer with overlap support (sub_3A0 at 0x3A0)

  Uses qmemcpy for aligned portions and handles overlapping destinations
  by copying backward.

  @param[out] Destination  Destination buffer.
  @param[in]  Source       Source buffer.
  @param[in]  Length       Number of bytes to copy.

  @return  Destination buffer.
**/
VOID *
EFIAPI
CopyMem (
  OUT VOID       *Destination,
  IN  VOID       *Source,
  IN  UINTN      Length
  )
{
  //
  // Handle overlap: if Source < Destination and Source + Length >= Destination,
  // copy backwards from end.
  //
  if (Source < Destination &&
      (UINT8 *)Source + Length - 1 >= (UINT8 *)Destination)
  {
    UINT8 *Dst = (UINT8 *)Destination + Length - 1;
    UINT8 *Src = (UINT8 *)Source + Length - 1;
    //
    // Copy in reverse 8-byte chunks
    //
    for (; Length >= 8; Length -= 8)
    {
      Dst -= 7;
      Src -= 7;
      *(UINT64 *)Dst = *(UINT64 *)Src;
    }
    //
    // Copy remaining bytes in reverse
    //
    for (; Length > 0; Length--)
    {
      *Dst-- = *Src--;
    }
  }
  else
  {
    //
    // Copy forward 8-byte chunks via qmemcpy
    //
    UINTN  Remaining = Length;
    if (Length >= 8)
    {
      UINTN  Chunks = Length >> 3;
      qmemcpy (Destination, Source, Chunks * 8);
      Dst += Chunks * 8;
      Src += Chunks * 8;
    }
    //
    // Copy remaining 1-7 bytes
    //
    for (; Length > 0; Length--)
    {
      *((UINT8 *)Destination + (Length - 1)) = *((UINT8 *)Source + (Length - 1));
    }
  }

  return Destination;
}

/**
  ZeroMem - fill buffer with 0 (sub_3F0 at 0x3F0)

  @param[out] Buffer  Buffer to zero.
  @param[in]  Length  Number of bytes to zero.

  @return  Buffer.
**/
VOID *
EFIAPI
ZeroMem (
  OUT VOID   *Buffer,
  IN  UINTN  Length
  )
{
  //
  // Zero 8-byte aligned chunks
  //
  UINTN  Chunks = Length >> 3;
  if (Chunks > 0)
  {
    memset (Buffer, 0, Chunks * 8);
  }

  //
  // Zero remaining bytes
  //
  UINTN  Remaining = Length & 7;
  if (Remaining > 0)
  {
    memset ((UINT8 *)Buffer + (Chunks * 8), 0, Remaining);
  }

  return Buffer;
}

// ============================================================================
// Validation helpers (sub_199C at 0x199C and sub_1ABC at 0x1ABC / sub_1A34 at 0x1A34)
// ============================================================================

/**
  Validate the SetJump buffer pointer (sub_199C at 0x199C)

  @param[in] JumpBuffer  Pointer to the jump buffer to validate.
**/
VOID
EFIAPI
PcRtcValidateJumpBuffer (
  IN VOID  *JumpBuffer
  )
{
  if (JumpBuffer == NULL)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\BaseLib\\SetJump.c",
      37,
      "JumpBuffer != ((void *) 0)"
      );
  }

  if (((UINTN)JumpBuffer & 7) != 0)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\BaseLib\\SetJump.c",
      39,
      "((UINTN)JumpBuffer & (8 - 1)) == 0"
      );
  }
}

/**
  Debug print with format (sub_1A34 at 0x1A34)

  Uses the SMM variable protocol for debug output. Also checks the debug
  level via CMOS port 0x70/0x71 register 0x4C (bit 7 preserved).

  @param[in] ErrorLevel  Debug error level.
  @param[in] Format      Print format string.
  @param[in] ...         Variable arguments.
**/
UINT8
EFIAPI
DebugPrint (
  IN UINTN        ErrorLevel,
  IN CONST CHAR8  *Format,
  ...
  )
{
  VA_LIST         Marker;
  UINT8           Result;
  EFI_STATUS      Status;
  UINTN           CmosDebugLevel;
  UINTN           FilterLevel;
  UINTN           TargetError;

  VA_START (Marker, Format);
  Result = 4;

  //
  // Fetch the SMM variable protocol if needed (lazy init)
  //
  if (gSmmVariable == NULL)
  {
    PcRtcGetSmmVariableProtocol ();
  }

  //
  // Read debug level from CMOS (port 0x70 index 0x4C, preserving NMI bit)
  //
  IoWrite8 (0x70, (IoRead8 (0x70) & 0x80) | 0x4C);
  CmosDebugLevel = IoRead8 (0x71);

  //
  // Determine the filter level from CMOS
  //
  if (CmosDebugLevel > 3)
  {
    if (CmosDebugLevel == 0)
    {
      CmosDebugLevel = 1;
    }
    FilterLevel = 4;
    TargetError = 2147483718;  // DEBUG_VERBOSE
    if (CmosDebugLevel == 1)
    {
      TargetError = 2147483652; // DEBUG_INFO
    }
  }
  else
  {
    FilterLevel = CmosDebugLevel;
    if (CmosDebugLevel == 1)
    {
      FilterLevel = 4;
    }
  }

  if ((TargetError & ErrorLevel) != 0)
  {
    if (gSmmVariable != NULL)
    {
      Result = ((EFI_SMM_VARIABLE_PROTOCOL *)gSmmVariable)->DebugPrint (
                                                               ErrorLevel,
                                                               Format,
                                                               Marker
                                                               );
    }
  }

  VA_END (Marker);
  return Result;
}

/**
  Debug assert / dead loop (sub_1ABC at 0x1ABC)

  @param[in] FileName     Assertion source file name.
  @param[in] LineNumber   Assertion source line number.
  @param[in] Description  Assertion description.
**/
VOID
EFIAPI
DebugAssert (
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Description
  )
{
  EFI_SMM_VARIABLE_PROTOCOL *VariableProtocol;

  VariableProtocol = (EFI_SMM_VARIABLE_PROTOCOL *)PcRtcGetSmmVariableProtocol ();
  if (VariableProtocol != NULL)
  {
    VariableProtocol->DebugAssert (FileName, LineNumber, Description);
  }
  //
  // Enter infinite loop (no return)
  //
  while (TRUE);
}

/**
  Compare two GUIDs by their first 8 bytes (sub_1AFC at 0x1AFC)

  @param[in] Guid1  Pointer to first GUID.
  @param[in] Guid2  Pointer to second GUID.

  @return TRUE if both qwords match.
**/
BOOLEAN
EFIAPI
CompareGuidPair (
  IN EFI_GUID  *Guid1,
  IN EFI_GUID  *Guid2
  )
{
  return ReadUnaligned64 ((UINT64 *)Guid1) == ReadUnaligned64 ((UINT64 *)Guid2) &&
         ReadUnaligned64 ((UINT64 *)&Guid1->Data4) == ReadUnaligned64 ((UINT64 *)&Guid2->Data4);
}

/**
  Read unaligned 64-bit value (sub_201C at 0x201C)

  @param[in] Buffer  Source buffer (must not be NULL).

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

  return * (UINT64 *)Buffer;
}

// ============================================================================
// Lazy-init protocol resolvers
// ============================================================================

/**
  Get the SMM Variable Protocol (lazy-init for sub_19E4 at 0x19E4)

  Scans gSmst->ProtocolRegistry for gEfiSmmVariableProtocolGuid (0x2A40).

  @return  Pointer to the EFI_SMM_VARIABLE_PROTOCOL, or NULL if not found.
**/
VOID *
EFIAPI
PcRtcGetSmmVariableProtocol (
  VOID
  )
{
  if (gSmmVariable == NULL)
  {
    EFI_STATUS  Status;
    VOID        *Interface;

    Status = gSmst->SmmLocateProtocol (
                     &gEfiSmmVariableProtocolGuid,
                     NULL,
                     &Interface
                     );
    if (EFI_ERROR (Status))
    {
      Interface = NULL;
    }

    gSmmVariable = Interface;
  }

  return gSmmVariable;
}

/**
  Get the HOB list pointer (lazy-init for sub_1DB0 at 0x1DB0)

  Scans the system table's configuration table for gEfiHobListGuid.

  @return  HOB list pointer, or NULL if not found.
**/
VOID *
EFIAPI
GeHobList (
  VOID
  )
{
  if (gHobList == NULL)
  {
    UINTN  Index;
    VOID   *Entry;

    gHobList = NULL;

    for (Index = 0; Index < gST->NumberOfTableEntries; Index++)
    {
      if (CompareGuidPair (
            &gEfiHobListGuid,
            gST->ConfigurationTable[Index].VendorGuid
            ))
      {
        gHobList = gST->ConfigurationTable[Index].VendorTable;
        break;
      }
    }

    if (Index >= gST->NumberOfTableEntries)
    {
      DebugPrint (
        0x80000000,
        "\nASSERT_EFI_ERROR (Status = %r)\n",
        0x800000000000000EULL
        );
      DebugAssert (
        "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
        54,
        "!EFI_ERROR (Status)"
        );
    }

    if (gHobList == NULL)
    {
      DebugAssert (
        "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
        55,
        "mHobList != ((void *) 0)"
        );
    }
  }

  return gHobList;
}

/**
  Get the PCD protocol pointer (lazy-init for sub_1F90 at 0x1F90)

  Locates gEfiPcdProtocolGuid via gBS->LocateProtocol.

  @return  Pointer to the PCD protocol, or NULL if not found.
**/
VOID *
EFIAPI
GetPcdProtocol (
  VOID
  )
{
  if (gPcdDb == NULL)
  {
    EFI_STATUS  Status;

    Status = gBS->LocateProtocol (
                   &gEfiPcdProtocolGuid,
                   NULL,
                   &gPcdDb
                   );
    if (EFI_ERROR (Status))
    {
      DebugPrint (
        0x80000000,
        "\nASSERT_EFI_ERROR (Status = %r)\n",
        Status
        );
      DebugAssert (
        "e:\\hs\\MdePkg\\Library\\DxePcdLib\\DxePcdLib.c",
        78,
        "!EFI_ERROR (Status)"
        );
    }

    if (gPcdDb == NULL)
    {
      DebugAssert (
        "e:\\hs\\MdePkg\\Library\\DxePcdLib\\DxePcdLib.c",
        79,
        "mPcd != ((void *) 0)"
        );
    }
  }

  return gPcdDb;
}

/**
  Get SMM CPU I/O2 Protocol (lazy-init for sub_1F04 at 0x1F04)

  Locates gEfiSmmCpuProtocolGuid (0x2A20) via gSmst->SmmLocateProtocol,
  then calls the SMM CPU protocol to write a register (function index
  1073741826 = 0x40000002, data = 50724874 = 0x0306000A).

  @return  EFI_SUCCESS or EFI_NOT_FOUND.
**/
EFI_STATUS
EFIAPI
PcRtcSmmCpuWrite (
  VOID
  )
{
  EFI_SMM_CPU_PROTOCOL  *CpuProtocol;

  if (gSmmCpuProtocol == NULL)
  {
    EFI_STATUS  Status;

    Status = gSmst->SmmLocateProtocol (
                     &gEfiSmmCpuProtocolGuid,
                     NULL,
                     &gSmmCpuInterface
                     );
    if (EFI_ERROR (Status) || gSmmCpuInterface == NULL)
    {
      gSmmCpuProtocol = NULL;
      return EFI_NOT_FOUND;
    }

    gSmmCpuProtocol = *(VOID **)gSmmCpuInterface;
    if (gSmmCpuProtocol == NULL)
    {
      return EFI_NOT_FOUND;
    }
  }

  //
  // Write register via SMM CPU protocol
  //    1073741826 = 0x40000002 (some CPU register write)
  //    50724874  = 0x0306000A
  //
  return ((EFI_SMM_CPU_PROTOCOL *)gSmmCpuProtocol)->WriteRegister (
                                                      gSmmCpuInterface,
                                                      0x40000002,
                                                      0x0306000A,
                                                      0,
                                                      &gEfiSmmVariableGuid,
                                                      0
                                                      );
}

/**
  PCD Get32 - reads a PCD value (sub_1F90 + callback at 0x1F90)

  @param[in] TokenNumber  PCD token number.

  @return  The 32-bit PCD value.
**/
UINT32
EFIAPI
PcdGet32 (
  UINTN  TokenNumber
  )
{
  VOID       *PcdProtocol;

  PcdProtocol = GetPcdProtocol ();
  return ((PCD_PROTOCOL *)PcdProtocol)->Get32 (TokenNumber);
}

/**
  PCI Express MMIO address resolution (sub_1D74 at 0x1D74)

  @param[in] Address  PCIe config address (must be within 0..0xFFFFFFF).

  @return  The MMIO address in PCIe config space.
**/
UINT64 *
EFIAPI
PciExpressReadAddress (
  IN UINT64  Address
  )
{
  if ((Address & 0xFFFFFFFFF0000000ULL) != 0)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\SmmPciExpressLib\\PciExpressLib.c",
      118,
      "((Address) & ~0xfffffff) == 0"
      );
  }

  return (UINT64 *)(gPcdDbValue + Address);
}

/**
  Write 0x500 to a word at a PCIe address (sub_204C at 0x204C)

  @param[in] Address  PCIe MMIO address (must be 16-bit aligned).

  @return  0x500.
**/
UINT16
EFIAPI
PciExpressWrite500 (
  IN UINT16  *Address
  )
{
  //
  // Check alignment
  //
  if (((UINTN)Address & 1) != 0)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLib.c",
      183,
      "(Address & 1) == 0"
      );
  }

  *Address = 0x500;
  return 0x500;
}

/**
  Read a 32-bit MMIO value from an aligned port (sub_1C68 at 0x1C68)

  @param[in] Port  Port to read from (must be 4-byte aligned).

  @return  The 32-bit value read.
**/
UINT32
EFIAPI
ReadMmio32 (
  IN UINT16  Port
  )
{
  if ((Port & 3) != 0)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLibMsc.c",
      193,
      "(Port & 3) == 0"
      );
  }

  return __indword (Port);
}

/**
  MicroSecondDelay - TSC-based delay (sub_1DB0 delay portion + sub_1E90 at 0x1E90)

  @param[in] MicroSeconds  Microseconds to delay.

  @return  0.
**/
UINT64
EFIAPI
MicroSecondDelay (
  IN UINTN  MicroSeconds
  )
{
  UINTN   Iterations;
  UINT32  TicksPerIter;
  UINT32  RemainderTicks;
  UINT32  TargetTsc;
  UINT32  CurrentTsc;

  //
  // Decompose microseconds into:
  //   - iterations: micro >> 22 (upper bits)
  //   - per-iteration ticks: micro & 0x3FFFFF (lower 22 bits)
  //
  Iterations = MicroSeconds >> 22;
  RemainderTicks = MicroSeconds & 0x3FFFFF;

  //
  // Wait for the initial TSC + per-iteration ticks to pass
  //
  do
  {
    TargetTsc = RemainderTicks + (__indword (1288) & 0xFFFFFF);

    //
    // Loop until TSC >= TargetTsc
    //
    while (((TargetTsc - (UINT32)__indword (1288)) & 0x800000) == 0)
    {
      CpuPause ();
    }

    RemainderTicks = 0x400000;  // next iteration uses full tick range
    Iterations--;
  }
  while ((INTN)Iterations > 0);

  return 0;
}

/**
  SmmCpuReadSaveState - read SMM CPU save state (sub_1C68 + sub_1E90 at 0x1E90)

  Uses __indword(0x508) for TSC-based timing, same as MicroSecondDelay.
**/
UINT64
EFIAPI
SmmCpuReadSaveState (
  VOID
  )
{
  //
  // TSC-based delay using port 0x508 (1288)
  //
  MicroSecondDelay (35);
  return 0;
}

// ============================================================================
// SMRAM helper functions
// ============================================================================

/**
  Check if an address is in SMRAM (sub_1C98 at 0x1C98)

  @param[in] Address  The address to check.

  @return  TRUE if the address falls inside one of the SMRAM ranges.
**/
BOOLEAN
EFIAPI
IsAddressInSmram (
  IN UINT64  Address
  )
{
  UINTN  Index;

  if (gSmramRangeCount == 0)
  {
    return FALSE;
  }

  for (Index = 0; Index < gSmramRangeCount; Index++)
  {
    UINT64  *Range = (UINT64 *)gSmramRanges + (Index * 4) + 1;

    if (Address >= *Range && Address < *Range + *(Range + 1))
    {
      return TRUE;
    }
  }

  return FALSE;
}

/**
  Allocate pool via Smst->SmmAllocatePool (sub_1CDC at 0x1CDC)

  @param[in] PoolType  Type of pool to allocate.
  @param[in] Size      Size of the allocation.

  @return  Pointer to allocated pool, or NULL on failure.
**/
VOID *
EFIAPI
AllocateSmramPool (
  IN EFI_MEMORY_TYPE  PoolType,
  IN UINTN            Size
  )
{
  VOID        *Buffer;
  EFI_STATUS  Status;

  Status = gSmst->SmmAllocatePool (
                   PoolType,
                   Size,
                   &Buffer
                   );
  if (EFI_ERROR (Status))
  {
    return NULL;
  }

  return Buffer;
}

/**
  Free SMRAM or boot-services pool depending on address (sub_1D0C at 0x1D0C)

  @param[in] Buffer  Pointer to the buffer to free.
**/
VOID
EFIAPI
FreePoolMmramAware (
  IN VOID  *Buffer
  )
{
  EFI_STATUS  Status;

  if (Buffer == NULL)
  {
    return;
  }

  //
  // Check if the address is within SMRAM -- use Smst to free inside SMRAM,
  // or BootServices to free outside.
  //
  if (IsAddressInSmram ((UINT64)Buffer))
  {
    Status = gSmst->SmmFreePool (Buffer);
  }
  else
  {
    Status = gBS->FreePool (Buffer);
  }

  if (EFI_ERROR (Status))
  {
    DebugPrint (
      0x80000000,
      "\nASSERT_EFI_ERROR (Status = %r)\n",
      Status
      );
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\SmmMemoryAllocationLib\\MemoryAllocationLib.c",
      981,
      "!EFI_ERROR (Status)"
      );
  }
}

// ============================================================================
// CopyMem wrapper (sub_1B64 at 0x1B64)
// ============================================================================

/**
  CopyMem with bounds checking wrapper (sub_1B64 at 0x1B64)

  @param[out] Destination  Destination buffer.
  @param[in]  Source       Source buffer.
  @param[in]  Length       Number of bytes to copy.

  @return  Destination buffer.
**/
VOID *
EFIAPI
CopyMemWrapper (
  OUT VOID       *Destination,
  IN  VOID       *Source,
  IN  UINTN      Length
  )
{
  if (Length - 1 > (UINT64)(-1LL - (UINT64)Destination))
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\CopyMemWrapper.c",
      56,
      "(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"
      );
  }

  if (Length - 1 > (UINT64)(-1LL - (UINT64)Source))
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\CopyMemWrapper.c",
      57,
      "(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"
      );
  }

  if (Destination == Source)
  {
    return Destination;
  }

  return CopyMem (Destination, Source, Length);
}

/**
  ZeroMem with bounds checking wrapper (sub_1C04 at 0x1C04)

  @param[out] Buffer  Buffer to zero.
  @param[in]  Length  Number of bytes to zero.

  @return  Buffer.
**/
VOID *
EFIAPI
ZeroMemWrapper (
  OUT VOID   *Buffer,
  IN  UINTN  Length
  )
{
  if (Buffer == NULL)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\ZeroMemWrapper.c",
      53,
      "Buffer != ((void *) 0)"
      );
  }

  if (Length > - (UINTN)Buffer)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\ZeroMemWrapper.c",
      54,
      "Length <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)Buffer + 1)"
      );
  }

  return ZeroMem (Buffer, Length);
}

// ============================================================================
// RTC Register Access
// ============================================================================

/**
  PcRtcReadReg - read a single RTC register (inlined as RTC_READ8)

  @param[in]  Register  RTC register index (0x00-0x3F).

  @return  The value read from RTC_DATA_PORT.
**/
UINT8
EFIAPI
PcRtcReadReg (
  IN UINT8  Register
  )
{
  IoWrite8 (RTC_ADDRESS_PORT, Register);
  return IoRead8 (RTC_DATA_PORT);
}

/**
  PcRtcWriteReg - write a single RTC register (inlined as RTC_WRITE8)

  @param[in]  Register  RTC register index (0x00-0x3F).
  @param[in]  Value     Value to write.
**/
VOID
EFIAPI
PcRtcWriteReg (
  IN UINT8  Register,
  IN UINT8  Value
  )
{
  IoWrite8 (RTC_ADDRESS_PORT, Register);
  IoWrite8 (RTC_DATA_PORT, Value);
}

// ============================================================================
// BCD conversion (DecimalToBcd = sub_18F4 at 0x18F4,
//                   BcdToDecimal = sub_1940 at 0x1940)
// ============================================================================

/**
  DecimalToBcd - Convert a decimal value to BCD (sub_18F4 at 0x18F4)

  @param[in] Value  Decimal value (must be < 100).

  @return  BCD-encoded value.
**/
UINT8
EFIAPI
DecimalToBcd (
  IN UINT8  Value
  )
{
  if (Value >= 100)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\BaseLib\\String.c",
      1785,
      "Value < 100"
      );
  }

  return (Value % 10) | (16 * (Value / 10));
}

/**
  BcdToDecimal - Convert a BCD value to decimal (sub_1940 at 0x1940)

  @param[in] Value  BCD value (must have valid nibbles < 0xA).

  @return  Decimal value.
**/
UINT8
EFIAPI
BcdToDecimal (
  IN UINT8  Value
  )
{
  if (Value >= 0xA0)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\BaseLib\\String.c",
      1809,
      "Value < 0xa0"
      );
  }

  if ((Value & 0x0F) >= 0x0A)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\BaseLib\\String.c",
      1810,
      "(Value & 0xf) < 0xa"
      );
  }

  return (Value & 0x0F) + 10 * (Value >> 4);
}

// ============================================================================
// PcRtcWaitForUpdateComplete (sub_1400 at 0x1400)
// ============================================================================

/**
  Wait for the RTC update to complete (UIP bit clears).

  Steps:
    1. Check Register D VRT bit -- if not valid, return error.
    2. Poll Register A UIP bit in a loop with up to 10001 iterations,
       waiting ~35 microseconds between polls.
    3. After UIP clears, verify Register D VRT again.

  @return  EFI_SUCCESS           RTC is ready.
  @return  EFI_DEVICE_ERROR      VRT invalid or timeout polling UIP.
**/
EFI_STATUS
EFIAPI
PcRtcWaitForUpdateComplete (
  VOID
  )
{
  UINTN      Index;
  UINT8      RegisterD;

  //
  // Check Register D VRT bit
  //
  RegisterD = PcRtcReadReg (RTC_REGISTER_D);
  if ((RegisterD & RTC_D_VRT) == 0)
  {
    return EFI_DEVICE_ERROR;
  }

  //
  // Poll Register A UIP with timeout
  //
  Index = 10001;

  while (Index > 0)
  {
    UINT8  RegisterA;

    //
    // Read Register A and check UIP
    //
    RegisterA = PcRtcReadReg (RTC_REGISTER_A);
    if ((RegisterA & RTC_A_UIP) == 0)
    {
      break;
    }

    MicroSecondDelay (35);
    Index--;
  }

  //
  // Verify VRT again after the update completes
  //
  RegisterD = PcRtcReadReg (RTC_REGISTER_D);

  if (Index > 0 && (RegisterD & RTC_D_VRT) != 0)
  {
    return EFI_SUCCESS;
  }
  else
  {
    return EFI_DEVICE_ERROR;
  }
}

// ============================================================================
// PcRtcDaysInMonth table (used by IsDayValid at sub_1500)
// ============================================================================

//
// Days in each month (non-leap year February = 28, leap February = 29)
// Stored as an array of 12 UINTN values for SIMD loading in sub_1500.
// xmmword_2870 = days for months 1-2
// xmmword_2880 = days for months 3-12 starting at 30
//
STATIC CONST UINT8 mDaysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

// ============================================================================
// PcRtcIsLeapYear
// ============================================================================

/**
  Check if a given year is a leap year.

  @param[in] Year  Year to check (e.g., 2000, 2024).

  @return  TRUE if the year is a leap year.
**/
BOOLEAN
EFIAPI
PcRtcIsLeapYear (
  IN UINT16  Year
  )
{
  //
  // Leap year: divisible by 4, and not (divisible by 100 unless divisible by 400)
  //
  if ((Year & 3) != 0)
  {
    return FALSE;
  }

  if (Year != 100 * (Year / 100))
  {
    return TRUE;
  }

  if (Year == 400 * (Year / 400))
  {
    return TRUE;
  }

  return FALSE;
}

// ============================================================================
// PcRtcIsDayValid (sub_1500 at 0x1500)
// ============================================================================

/**
  Validate the Day field of an EFI_TIME against the Month/Year.

  @param[in] Time  Pointer to EFI_TIME structure.

  @return  TRUE if Day is valid for the given Month/Year.
**/
BOOLEAN
EFIAPI
PcRtcIsDayValid (
  IN EFI_TIME  *Time
  )
{
  UINTN  DaysInMonth;

  if (Time->Month < 1)
  {
    DebugAssert (
      "e:\\hs\\PcAtChipsetPkg\\PcatRealTimeClockSmm\\PcRtcSmm.c",
      1163,
      "Time->Month >=1"
      );
  }

  if (Time->Month > 12)
  {
    DebugAssert (
      "e:\\hs\\PcAtChipsetPkg\\PcatRealTimeClockSmm\\PcRtcSmm.c",
      1164,
      "Time->Month <=12"
      );
  }

  if (Time->Day < 1)
  {
    return FALSE;
  }

  //
  // Look up days in this month
  //
  DaysInMonth = mDaysInMonth[Time->Month - 1];

  //
  // February special: check for leap year
  //
  if (Time->Month == 2)
  {
    if (PcRtcIsLeapYear (Time->Year))
    {
      DaysInMonth = 29;
    }
  }

  return Time->Day <= DaysInMonth;
}

// ============================================================================
// PcRtcValidateTime (sub_1478 at 0x1478)
// ============================================================================

/**
  Validate the entire EFI_TIME structure.

  @param[in] Time  Pointer to EFI_TIME structure.

  @return  EFI_SUCCESS           Time is valid.
  @return  EFI_INVALID_PARAMETER One or more fields are out of range.
**/
EFI_STATUS
EFIAPI
PcRtcValidateTime (
  IN EFI_TIME  *Time
  )
{
  if (Time->Year < 2000 ||
      Time->Year > 9999 ||
      Time->Month < 1 ||
      Time->Month > 12 ||
      !PcRtcIsDayValid (Time) ||
      Time->Hour > 23 ||
      Time->Minute > 59 ||
      Time->Second > 59 ||
      Time->Nanosecond > 999999999 ||
      (Time->TimeZone != 2047 && (UINT16)(Time->TimeZone + 1440) > 0xB40) ||
      (Time->Daylight & 0xFC) != 0)
  {
    return EFI_INVALID_PARAMETER;
  }

  return EFI_SUCCESS;
}

// ============================================================================
// PcRtcConvertFromRegisterFormat (sub_1260 at 0x1260)
// ============================================================================

/**
  Convert time values from RTC register format to EFI_TIME.

  Handles:
  - BCD-to-decimal conversion (if Register_B DM bit = 0)
  - 12-hour to 24-hour conversion (if Register_B 24HR bit = 0)
    (PM flag in Hour bit 7)
  - Century rollover using gRtcCenturyOffset from CMOS

  @param[in,out] Time       On input, raw register values.
                             On output, converted EFI_TIME.
  @param[in]     RegisterB  Current Register B value (bits for DM and 24HR).

  @return  EFI_SUCCESS           Conversion successful.
  @return  EFI_INVALID_PARAMETER BCD conversion resulted in invalid values.
**/
EFI_STATUS
EFIAPI
PcRtcConvertFromRegisterFormat (
  IN OUT EFI_TIME  *Time,
  IN     UINT8     RegisterB
  )
{
  UINT8    RawHour;
  UINT8    PmFlag;
  BOOLEAN  IsBinary;
  BOOLEAN  Is24Hour;
  UINT8    HourBcd;

  //
  // Extract PM flag from Hour bit 7 and clear it
  //
  RawHour = Time->Hour;
  PmFlag  = RawHour >> 7;
  Time->Hour = RawHour & 0x7F;

  IsBinary  = (RegisterB & RTC_B_DM) != 0;
  Is24Hour  = (RegisterB & RTC_B_24HR) != 0;

  if (!IsBinary)
  {
    //
    // Convert BCD to decimal for all time fields
    //
    Time->Year    = BcdToDecimal ((UINT8)Time->Year);
    Time->Month   = BcdToDecimal (Time->Month);
    Time->Day     = BcdToDecimal (Time->Day);
    Time->Hour    = BcdToDecimal (Time->Hour);
    Time->Minute  = BcdToDecimal (Time->Minute);
    Time->Second  = BcdToDecimal (Time->Second);
  }

  //
  // Check for invalid BCD conversion (0xFF indicates failure)
  //
  if (Time->Year == 0xFF ||
      Time->Month == 0xFF ||
      Time->Day == 0xFF ||
      Time->Hour == 0xFF ||
      Time->Minute == 0xFF ||
      Time->Second == 0xFF)
  {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Read century byte from RTC CMOS
  //
  if (gRtcCenturyOffset != 0)
  {
    Time->Year = Time->Year + (100 * BcdToDecimal (PcRtcReadReg (gRtcCenturyOffset & 0x7F)));
  }
  else
  {
    Time->Year = Time->Year + (100 * BcdToDecimal (PcRtcReadReg (0x32)));
  }

  //
  // Convert from 12-hour to 24-hour format
  //
  if (!Is24Hour)
  {
    if (PmFlag != 0)
    {
      //
      // PM: add 12 hours (but 12:00 PM = 12:00, not 24:00)
      //
      if (Time->Hour < 12)
      {
        Time->Hour = Time->Hour + 12;
      }
      else
      {
        Time->Hour = 12;
      }
    }
    else
    {
      //
      // AM: 12:00 AM = 00:00
      //
      if (Time->Hour == 12)
      {
        Time->Hour = 0;
      }
    }
  }

  //
  // Clear nanosecond (time register reads don't provide nanoseconds)
  //
  Time->Nanosecond = 0;

  return EFI_SUCCESS;
}

// ============================================================================
// PcRtcConvertToRegisterFormat (sub_1640 at 0x1640)
// ============================================================================

/**
  Convert time values from EFI_TIME to RTC register format.

  Handles:
  - 24-hour to 12-hour conversion (PM flag in Hour bit 7)
  - Decimal-to-BCD conversion
  - Century byte extraction (Year -> century byte)

  @param[in,out] Time       On input, EFI_TIME values.
                             On output, values ready to write to RTC registers.
  @param[in]     RegisterB  Current Register B value (controls DM and 24HR bits).

  @return  The last conversion result (BCD value of the Second field).
**/
UINT8
EFIAPI
PcRtcConvertToRegisterFormat (
  IN OUT EFI_TIME  *Time,
  IN     UINT8     RegisterB
  )
{
  BOOLEAN  Is24Hour;
  BOOLEAN  IsBinary;
  UINT16   Year;

  Is24Hour = (RegisterB & RTC_B_24HR) != 0;
  IsBinary = (RegisterB & RTC_B_DM) != 0;

  //
  // Convert Hour from 24-hour to 12-hour
  //
  if (!Is24Hour)
  {
    if (Time->Hour >= 12)
    {
      //
      // PM: set PM flag in bit 7
      //
      if (Time->Hour > 12)
      {
        Time->Hour = Time->Hour - 12;
      }
      //
      // 12:00 PM stays 12 with PM flag
      //
      Time->Hour |= 0x80;
    }
    else if (Time->Hour == 0)
    {
      //
      // 12:00 AM = 12 with no PM flag
      //
      Time->Hour = 12;
    }
  }

  //
  // Extract century: Year / 100
  //
  Year = Time->Year;
  Time->Year = Year % 100;

  if (!IsBinary)
  {
    //
    // Convert to BCD
    //
    Time->Year   = DecimalToBcd ((UINT8)Time->Year);
    Time->Month  = DecimalToBcd (Time->Month);
    Time->Day    = DecimalToBcd (Time->Day);
    Time->Hour   = DecimalToBcd (Time->Hour);
    Time->Minute = DecimalToBcd (Time->Minute);
  }

  //
  // Write century byte to CMOS
  //
  if (gRtcCenturyOffset != 0)
  {
    PcRtcWriteReg (gRtcCenturyOffset & 0x7F, DecimalToBcd ((UINT8)(Year / 100)));
  }
  else
  {
    PcRtcWriteReg (0x32, DecimalToBcd ((UINT8)(Year / 100)));
  }

  //
  // Convert Second to BCD (return value)
  //
  if (!IsBinary)
  {
    Time->Second = DecimalToBcd (Time->Second);
  }

  //
  // Set PM flag in Hour if in 12-hour mode and PM
  //
  if (!Is24Hour && RegisterB == 0)
  {
    //
    // Actually check if we need PM bit: the 12-hour conversion already set it.
    // Just make sure it's persistent.
    //
  }

  return Time->Second;
}

// ============================================================================
// PcRtcTimeCompare (sub_16F8 at 0x16F8)
// ============================================================================

/**
  Compare two EFI_TIME values by Hour/Minute/Second only.

  @param[in] Time1  First time to compare.
  @param[in] Time2  Second time to compare.

  @return  0  if Hour/Minute/Second match.
  @return  1  if Time1 > Time2.
  @return  -1 if Time1 < Time2.
**/
INTN
EFIAPI
PcRtcTimeCompare (
  IN EFI_TIME  *Time1,
  IN EFI_TIME  *Time2
  )
{
  if (Time1->Hour > Time2->Hour)
  {
    return 1;
  }

  if (Time1->Hour < Time2->Hour)
  {
    return -1;
  }

  //
  // Hours equal, check minutes
  //
  if (Time1->Minute > Time2->Minute)
  {
    return 1;
  }

  if (Time1->Minute < Time2->Minute)
  {
    return -1;
  }

  //
  // Minutes equal, check seconds
  //
  if (Time1->Second > Time2->Second)
  {
    return 1;
  }

  if (Time1->Second < Time2->Second)
  {
    return -1;
  }

  return 0;
}

// ============================================================================
// PcRtcIsTimeNearby (sub_1744 at 0x1744)
// ============================================================================

/**
  Check if "From" time is the same as or the day before "Target" time,
  and that the target time is within the same day boundary.

  This is used to validate that a SetWakeupTime alarm is within
  1 day of the current RTC time.

  @param[in] From    Current RTC time.
  @param[in] Target  Proposed alarm time.

  @return  TRUE if Target is within the same day (or adjacent day)
           and the alarm time is >= current time.
**/
BOOLEAN
EFIAPI
PcRtcIsTimeNearby (
  IN EFI_TIME  *From,
  IN EFI_TIME  *Target
  )
{
  if (From->Month < 1)
  {
    DebugAssert (
      "e:\\hs\\PcAtChipsetPkg\\PcatRealTimeClockSmm\\PcRtcSmm.c",
      1323,
      "From->Month >=1"
      );
  }

  if (From->Month > 12)
  {
    DebugAssert (
      "e:\\hs\\PcAtChipsetPkg\\PcatRealTimeClockSmm\\PcRtcSmm.c",
      1324,
      "From->Month <=12"
      );
  }

  if (From->Year != Target->Year)
  {
    //
    // Allow Dec 31 -> Jan 1 cross-year
    //
    if ((UINT16)From->Year + 1 != (UINT16)Target->Year ||
        From->Month != 12 ||
        From->Day != 31 ||
        Target->Month != 1 ||
        Target->Day != 1)
    {
      return FALSE;
    }

    return PcRtcTimeCompare (From, Target) >= 0;
  }

  if (From->Month != Target->Month)
  {
    UINTN  FromMonth = From->Month;

    //
    // Allow month rollover: From->Month + 1 == Target->Month and Target->Day == 1
    //
    if (FromMonth + 1 == (UINTN)Target->Month && Target->Day == 1)
    {
      BOOLEAN  IsValidEndOfMonth;

      if (From->Month == 2)
      {
        //
        // February: check if it's 28th or 29th (leap year)
        //
        if (PcRtcIsLeapYear (From->Year))
        {
          IsValidEndOfMonth = (From->Day == 29);
        }
        else
        {
          IsValidEndOfMonth = (From->Day == 28);
        }
      }
      else
      {
        //
        // For other months, check days-in-month
        //
        IsValidEndOfMonth = (From->Day == mDaysInMonth[FromMonth - 1]);
      }

      if (IsValidEndOfMonth && PcRtcTimeCompare (From, Target) >= 0)
      {
        return TRUE;
      }
    }

    return FALSE;
  }

  //
  // Same year, same month -- check day rollover
  //
  if (From->Day + 1 == Target->Day)
  {
    return PcRtcTimeCompare (From, Target) >= 0;
  }

  //
  // Same day -- alarm must be >= current time
  //
  if (From->Day == Target->Day && PcRtcTimeCompare (From, Target) <= 0)
  {
    return TRUE;
  }

  return FALSE;
}

// ============================================================================
// PcRtcGetTime - SMM GetTime handler (sub_84C -> sub_C28 at 0xC28)
// ============================================================================

/**
  Get the current RTC time from hardware.

  Steps:
    1. Wait for RTC update complete (UIP clear).
    2. Read Register B to determine binary/BCD and 12hr/24hr mode.
    3. Read all time registers (second, minute, hour, day, month, year).
    4. Convert from register format.
    5. Validate the time.

  @param[out] Time       Pointer to receive the current time.
  @param[out] Capabilities  Optional SMM capabilities descriptor.

  @return  EFI_SUCCESS           Time read successfully.
  @return  EFI_INVALID_PARAMETER Time pointer is NULL.
  @return  EFI_DEVICE_ERROR      RTC update failed, or converted time invalid.
**/
EFI_STATUS
EFIAPI
PcRtcGetTime (
  OUT EFI_TIME               *Time,
  OUT EFI_TIME_CAPABILITIES  *Capabilities OPTIONAL
  )
{
  EFI_STATUS  Status;
  UINT8       RegisterB;
  UINT8       Second;
  UINT8       Minute;
  UINT8       Hour;
  UINT8       Day;
  UINT8       Month;
  UINT8       Year;

  if (Time == NULL)
  {
    return EFI_INVALID_PARAMETER;
  }

  Status = PcRtcWaitForUpdateComplete ();
  if (EFI_ERROR (Status))
  {
    return Status;
  }

  //
  // Read Register B to determine format
  //
  RegisterB = PcRtcReadReg (RTC_REGISTER_B);

  //
  // Read all time registers
  //
  Time->Second = PcRtcReadReg (RTC_SECONDS);
  Time->Minute = PcRtcReadReg (RTC_MINUTES);
  Time->Hour   = PcRtcReadReg (RTC_HOURS);
  Time->Day    = PcRtcReadReg (RTC_DAY_OF_MONTH);
  Time->Month  = PcRtcReadReg (RTC_MONTH);
  Time->Year   = PcRtcReadReg (RTC_YEAR);

  //
  // Set TimeZone and Daylight from globals
  //
  Time->TimeZone  = gRtcTimeZone;
  Time->Daylight  = gRtcDaylight;

  //
  // Convert from register format (BCD->decimal, 12hr->24hr, add century)
  //
  Status = PcRtcConvertFromRegisterFormat (Time, RegisterB);
  if (EFI_ERROR (Status))
  {
    return EFI_DEVICE_ERROR;
  }

  //
  // Validate the converted time
  //
  Status = PcRtcValidateTime (Time);
  if (EFI_ERROR (Status))
  {
    return EFI_DEVICE_ERROR;
  }

  //
  // Report capabilities
  //
  if (Capabilities != NULL)
  {
    Capabilities->Resolution  = 1;           // 1 Hz
    Capabilities->Accuracy    = 50000000;    // 50,000,000 nanoseconds (50ms)
    Capabilities->SetsToZero  = FALSE;
  }

  return EFI_SUCCESS;
}

// ============================================================================
// PcRtcGetTime thunk (sub_84C at 0x84C)
// ============================================================================

/**
  Thunk function for PcRtcGetTime.
  Called via the RSC handler array at gSmmRuntimeRsc+24.
**/
EFI_STATUS
EFIAPI
PcRtcSmmGetTimeHandler (
  VOID
  )
{
  return PcRtcGetTime (NULL, NULL);
}

// ============================================================================
// PcRtcSetTime - SMM SetTime handler (sub_854 -> sub_D20 at 0xD20)
// ============================================================================

/**
  Set the RTC time on hardware.

  Steps:
    1. Validate the time.
    2. Copy time to config structure.
    3. Wait for RTC update complete.
    4. Delete the "RTC" SMM variable (to invalidate DXE-side cache).
    5. Set Register B SET bit to freeze updates.
    6. Write century byte.
    7. Convert time to register format (BCD, 12hr with PM flag).
    8. Write all time registers.
    9. Clear SET bit to resume updates.
   10. Save TimeZone and Daylight to config structure.

  @param[in,out] Time   Time to set (may be modified during format conversion).
  @param[in]     Config RTC configuration structure containing century register.

  @return  EFI_SUCCESS           Time set successfully.
  @return  EFI_INVALID_PARAMETER Time validation failed.
  @return  EFI_DEVICE_ERROR      RTC update failed to complete.
**/
EFI_STATUS
EFIAPI
PcRtcSetTime (
  IN OUT EFI_TIME  *Time,
  IN     PC_RTC_CONFIG *Config OPTIONAL
  )
{
  EFI_STATUS  Status;
  UINT8       RegisterB;
  EFI_TIME    LocalTime;

  //
  // Validate the time
  //
  Status = PcRtcValidateTime (Time);
  if (EFI_ERROR (Status))
  {
    return Status;
  }

  //
  // Copy time for internal manipulation
  //
  CopyMemWrapper (&LocalTime, Time, sizeof (EFI_TIME));

  //
  // Wait for update complete before writing
  //
  Status = PcRtcWaitForUpdateComplete ();
  if (EFI_ERROR (Status))
  {
    return Status;
  }

  //
  // Delete the "RTC" SMM variable to invalidate DXE-side cache
  //
  if (gSmmRuntimeRsc != NULL)
  {
    //
    // The RSC protocol has the SmmDeleteVariable at offset 88
    //
    ((SMM_RSC_HANDLER_PROTOCOL *)gSmmRuntimeRsc)->SmmDeleteVariable (
                                                    L"RTC",
                                                    &gEfiSmmVariableGuid,
                                                    7
                                                    );
  }

  //
  // Set SET bit in Register B to freeze RTC updates
  //
  RegisterB = PcRtcReadReg (RTC_REGISTER_B);
  PcRtcWriteReg (RTC_REGISTER_B, RegisterB | RTC_B_SET);

  //
  // Write century byte to CMOS (offset from Config or default 0x32)
  //
  if (Config != NULL && Config->CenturyRegister != 0)
  {
    PcRtcWriteReg (Config->CenturyRegister & 0x7F,
                   DecimalToBcd ((UINT8)(LocalTime.Year / 100)));
  }
  else
  {
    PcRtcWriteReg (0x32,
                   DecimalToBcd ((UINT8)(LocalTime.Year / 100)));
  }

  //
  // Convert time to register format
  //
  PcRtcConvertToRegisterFormat (&LocalTime, RegisterB);

  //
  // Write all time registers
  //
  PcRtcWriteReg (RTC_SECONDS,     LocalTime.Second);
  PcRtcWriteReg (RTC_MINUTES,     LocalTime.Minute);
  PcRtcWriteReg (RTC_HOURS,       LocalTime.Hour);
  PcRtcWriteReg (RTC_DAY_OF_MONTH, LocalTime.Day);
  PcRtcWriteReg (RTC_MONTH,       LocalTime.Month);
  PcRtcWriteReg (RTC_YEAR,        (UINT8)LocalTime.Year);

  //
  // Clear SET bit to resume RTC updates
  //
  PcRtcWriteReg (RTC_REGISTER_B, RegisterB & ~RTC_B_SET);

  //
  // Save TimeZone and Daylight to config structure
  //
  if (Config != NULL)
  {
    Config->TimeZone  = Time->TimeZone;
    Config->Daylight  = Time->Daylight;
  }

  return EFI_SUCCESS;
}

// ============================================================================
// PcRtcSetTime thunk (sub_854 at 0x854)
// ============================================================================

/**
  Thunk function for PcRtcSetTime.
  Called via the RSC handler array at gSmmRuntimeRsc+32.
**/
EFI_STATUS
EFIAPI
PcRtcSmmSetTimeHandler (
  IN PC_RTC_CONFIG *Config OPTIONAL
  )
{
  if (Config != NULL)
  {
    return PcRtcSetTime (NULL, &gRtcConfig);
  }

  return EFI_INVALID_PARAMETER;
}

// ============================================================================
// PcRtcGetWakeupTime - SMM GetWakeupTime handler (sub_870 -> sub_EC8 at 0xEC8)
// ============================================================================

/**
  Get the RTC wakeup alarm time.

  Steps:
    1. Wait for RTC update complete.
    2. Read Register B for AIE status (alarm enabled).
    3. Read Register C for AF bit (alarm fired).
    4. Read alarm time registers (seconds, minutes, hours).
    5. Read the "RTCALARM" SMM variable to get Year/Month (if stored).
    6. Restore TimeZone/Daylight from config structure.
    7. Convert/validate time.

  @param[out] Enabled   TRUE if alarm interrupt is enabled (AIE bit in Register B).
  @param[out] Pending   TRUE if alarm has fired (AF bit in Register C).
  @param[out] Time      Alarm time (from registers + RTCALARM variable).
  @param[in]  Config    RTC configuration structure.

  @return  EFI_SUCCESS           Alarm time read successfully.
  @return  EFI_INVALID_PARAMETER Any output pointer is NULL.
  @return  EFI_DEVICE_ERROR      RTC update failed or time conversion invalid.
**/
EFI_STATUS
EFIAPI
PcRtcGetWakeupTime (
  OUT BOOLEAN      *Enabled,
  OUT BOOLEAN      *Pending,
  OUT EFI_TIME     *Time,
  IN  PC_RTC_CONFIG *Config
  )
{
  EFI_STATUS  Status;
  UINT8       RegisterB;
  UINT8       RegisterC;
  UINT8       Century;
  UINTN       DataSize;

  if (Enabled == NULL || Pending == NULL || Time == NULL)
  {
    return EFI_INVALID_PARAMETER;
  }

  Status = PcRtcWaitForUpdateComplete ();
  if (EFI_ERROR (Status))
  {
    return EFI_DEVICE_ERROR;
  }

  //
  // Read Register B and C for alarm status
  //
  RegisterB = PcRtcReadReg (RTC_REGISTER_B);
  RegisterC = PcRtcReadReg (RTC_REGISTER_C);

  *Enabled = (RegisterB & RTC_B_AIE) != 0;
  *Pending = (RegisterC & RTC_B_AIE) != 0;

  //
  // Read alarm registers (seconds, minutes, hours)
  //
  Time->Second = PcRtcReadReg (RTC_SECONDS_ALARM);
  Time->Minute = PcRtcReadReg (RTC_MINUTES_ALARM);
  Time->Hour   = PcRtcReadReg (RTC_HOURS_ALARM);

  //
  // Read date registers (day, month, year)
  //
  Time->Day    = PcRtcReadReg (RTC_DAY_OF_MONTH);

  //
  // Check Register D for century storage
  //
  UINT8 RegisterD;

  RegisterD = PcRtcReadReg (RTC_REGISTER_D);
  Century = RegisterD & 0x3F;

  if (Century > 0 && Century - 1 <= 30)
  {
    Time->Day = DecimalToBcd (Century);
  }

  Time->Month  = PcRtcReadReg (RTC_MONTH);
  Time->Year   = PcRtcReadReg (RTC_YEAR);

  //
  // Apply TimeZone/Daylight from config structure
  //
  Time->TimeZone = Config->TimeZone;
  Time->Daylight = Config->Daylight;

  //
  // Try to read the "RTCALARM" SMM variable to get Year/Month
  //
  DataSize = sizeof (EFI_TIME);
  Status = ((SMM_RSC_HANDLER_PROTOCOL *)gSmmRuntimeRsc)->SmmGetVariable (
                                                           L"RTCALARM",
                                                           &gEfiSmmVariableGuid,
                                                           0,
                                                           &DataSize,
                                                           Time
                                                           );

  if (!EFI_ERROR (Status))
  {
    //
    // Update Year/Month/Day from the stored alarm variable
    //
    Time->Day   = Time->Day;
    Time->Month = Time->Month;
    Time->Year  = Time->Year;
  }

  //
  // Convert from register format
  //
  Status = PcRtcConvertFromRegisterFormat (Time, RegisterB);
  if (EFI_ERROR (Status))
  {
    return EFI_DEVICE_ERROR;
  }

  //
  // Validate the time
  //
  Status = PcRtcValidateTime (Time);
  if (EFI_ERROR (Status))
  {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

// ============================================================================
// PcRtcGetWakeupTime thunk (sub_870 at 0x870)
// ============================================================================

/**
  Thunk function for PcRtcGetWakeupTime.
  Called via the RSC handler array at gSmmRuntimeRsc+40.
**/
EFI_STATUS
EFIAPI
PcRtcSmmGetAlarmHandler (
  OUT BOOLEAN      *Enabled,
  OUT BOOLEAN      *Pending,
  OUT EFI_TIME     *Time
  )
{
  return PcRtcGetWakeupTime (Enabled, Pending, Time, &gRtcConfig);
}

// ============================================================================
// PcRtcSetWakeupTime - SMM SetWakeupTime handler (sub_87C -> sub_1074 at 0x1074)
// ============================================================================

/**
  Set or clear the RTC wakeup alarm.

  Steps:
    1. Zero the local time buffer.
    2. If Enabled:
       a. Validate the alarm time.
       b. Get current RTC time.
       c. Validate current time.
       d. Check alarm is within 24 hours of current time.
       e. Copy alarm time.
    3. Wait for RTC update complete.
    4. Read Register B.
    5. If Enabled:
       a. Convert time to register format.
    6. Else:
       a. Save current alarm register values.
    7. Write "RTCALARM" SMM variable.
    8. Set Register B SET bit.
    9. Write alarm registers (seconds, minutes, hours).
   10. Update Register D century.
   11. Write Month/Year.
   12. Toggle AIE bit: set if Enabled, clear if not.
   13. Clear SET bit.

  @param[in] Enabled     TRUE to set alarm, FALSE to clear.
  @param[in] Time        Alarm time (if Enabled is TRUE).

  @return  EFI_SUCCESS           Alarm set/cleared successfully.
  @return  EFI_INVALID_PARAMETER Invalid time (if enabled).
  @return  EFI_DEVICE_ERROR      RTC update failed.
**/
EFI_STATUS
EFIAPI
PcRtcSetWakeupTime (
  IN BOOLEAN       Enabled,
  IN EFI_TIME      *Time    OPTIONAL
  )
{
  EFI_STATUS  Status;
  UINT8       RegisterB;
  UINT8       RegisterBNew;
  UINT8       RegisterD;
  EFI_TIME    AlarmTime;
  EFI_TIME    CurrentTime;

  ZeroMemWrapper (&AlarmTime, sizeof (EFI_TIME));

  if (Enabled)
  {
    if (Time == NULL)
    {
      return EFI_INVALID_PARAMETER;
    }

    Status = PcRtcValidateTime (Time);
    if (EFI_ERROR (Status))
    {
      return EFI_INVALID_PARAMETER;
    }

    //
    // Get current RTC time to validate proximity (alarm must be within 24 hours)
    //
    Status = PcRtcGetTime (&CurrentTime, NULL);
    if (EFI_ERROR (Status))
    {
      return EFI_DEVICE_ERROR;
    }

    Status = PcRtcValidateTime (&CurrentTime);
    if (EFI_ERROR (Status))
    {
      return Status;
    }

    //
    // Check if alarm time is nearby (within 1 day)
    //
    if (!PcRtcIsTimeNearby (&CurrentTime, Time))
    {
      return EFI_INVALID_PARAMETER;
    }

    //
    // Copy alarm time
    //
    CopyMemWrapper (&AlarmTime, Time, sizeof (EFI_TIME));
  }

  Status = PcRtcWaitForUpdateComplete ();
  if (EFI_ERROR (Status))
  {
    return EFI_DEVICE_ERROR;
  }

  RegisterB = PcRtcReadReg (RTC_REGISTER_B);

  if (Enabled)
  {
    //
    // Convert alarm to register format
    //
    PcRtcConvertToRegisterFormat (&AlarmTime, RegisterB);
  }
  else
  {
    //
    // Save current alarm register values (for restoring previous alarm)
    //
    AlarmTime.Second = PcRtcReadReg (RTC_SECONDS_ALARM);
    AlarmTime.Minute = PcRtcReadReg (RTC_MINUTES_ALARM);
    AlarmTime.Hour   = PcRtcReadReg (RTC_HOURS_ALARM);

    //
    // Read Register D century
    //
    RegisterD = PcRtcReadReg (RTC_REGISTER_D) & 0x3F;

    AlarmTime.Month  = PcRtcReadReg (RTC_MONTH);
    AlarmTime.Year   = PcRtcReadReg (RTC_YEAR);

    //
    // Apply TimeZone/Daylight from globals
    //
    AlarmTime.TimeZone = gRtcTimeZone;
    AlarmTime.Daylight = gRtcDaylight;
  }

  //
  // Write "RTCALARM" SMM variable
  //
  Status = ((SMM_RSC_HANDLER_PROTOCOL *)gSmmRuntimeRsc)->SmmSetVariable (
                                                           L"RTCALARM",
                                                           &gEfiSmmVariableGuid,
                                                           7,
                                                           sizeof (EFI_TIME),
                                                           &AlarmTime
                                                           );
  if (EFI_ERROR (Status))
  {
    return EFI_DEVICE_ERROR;
  }

  //
  // Set Register B SET bit to freeze updates
  //
  RegisterBNew = RegisterB | RTC_B_SET;
  PcRtcWriteReg (RTC_REGISTER_B, RegisterBNew);

  if (Enabled)
  {
    //
    // Write alarm registers
    //
    PcRtcWriteReg (RTC_SECONDS_ALARM, AlarmTime.Second);
    PcRtcWriteReg (RTC_MINUTES_ALARM, AlarmTime.Minute);
    PcRtcWriteReg (RTC_HOURS_ALARM,   AlarmTime.Hour);

    //
    // Read and update Register D with the alarm day/century
    //
    PcRtcReadReg (RTC_REGISTER_C);        // Clear pending AF
    //
    // Write Register D century
    //
    PcRtcWriteReg (RTC_REGISTER_D, AlarmTime.Day & 0x3F);

    //
    // Clear pending interrupt by reading Register C
    //
    PcRtcReadReg (RTC_REGISTER_C);
  }
  else
  {
    //
    // Read existing alarm values and keep them (only clear AIE)
    //
    AlarmTime.Second = PcRtcReadReg (RTC_SECONDS_ALARM);
    AlarmTime.Minute = PcRtcReadReg (RTC_MINUTES_ALARM);
    AlarmTime.Hour   = PcRtcReadReg (RTC_HOURS_ALARM);

    //
    // Get date
    //
    RegisterD = PcRtcReadReg (RTC_REGISTER_D);
    AlarmTime.Day    = PcRtcReadReg (RTC_DAY_OF_MONTH);
    AlarmTime.Month  = PcRtcReadReg (RTC_MONTH);
    AlarmTime.Year   = PcRtcReadReg (RTC_YEAR);

    AlarmTime.TimeZone = gRtcTimeZone;
    AlarmTime.Daylight = gRtcDaylight;
  }

  //
  // Write alarm registers (redundant for Enabled, restores current for not)
  //
  PcRtcWriteReg (RTC_SECONDS_ALARM, AlarmTime.Second);
  PcRtcWriteReg (RTC_MINUTES_ALARM, AlarmTime.Minute);
  PcRtcWriteReg (RTC_HOURS_ALARM,   AlarmTime.Hour);

  //
  // Write Register D century
  //
  if (!Enabled)
  {
    PcRtcReadReg (RTC_REGISTER_D);        // Dummy read
  }
  PcRtcWriteReg (RTC_REGISTER_D, AlarmTime.Day & 0x3F);

  //
  // Write Month/Year
  //
  PcRtcWriteReg (RTC_MONTH, AlarmTime.Month);
  PcRtcWriteReg (RTC_YEAR,  (UINT8)AlarmTime.Year);

  //
  // Toggle AIE bit: set if enabled, clear if not
  //
  if (Enabled)
  {
    RegisterBNew = (RegisterBNew | RTC_B_AIE) & ~RTC_B_SET;
  }
  else
  {
    RegisterBNew = (RegisterBNew & ~RTC_B_AIE) & ~RTC_B_SET;
  }

  //
  // Write final Register B value (clear SET, optionally set AIE)
  //
  PcRtcWriteReg (RTC_REGISTER_B, RegisterBNew & 0x7F);

  return EFI_SUCCESS;
}

// ============================================================================
// PcRtcSetWakeupTime thunk (sub_87C at 0x87C)
// ============================================================================

/**
  Thunk function for PcRtcSetWakeupTime.
  Called via the RSC handler array at gSmmRuntimeRsc+48.
**/
EFI_STATUS
EFIAPI
PcRtcSmmSetAlarmHandler (
  VOID
  )
{
  return PcRtcSetWakeupTime (FALSE, NULL);
}

// ============================================================================
// PcRtcInitRtcHardware - RTC chip initialization (sub_984 at 0x984)
// ============================================================================

/**
  Initialize the MC146818 RTC hardware.

  Steps:
    1. Write Register A = 0x26 (divider reset + 32768 Hz rate select).
    2. Read Register B, save value.
    3. Read Register C to clear pending interrupt.
    4. Write Register D = 0 (clear VRT, will be set by hardware).
    5. Wait for UIP to clear.
    6. Read all time registers.
    7. Configure Register B: preserve bits 5 (AIE) and 2 (DM),
       force bit 1 (24HR) and clear bit 0 (DSE) -> value = (RegB & 0x24) | 0x02.
    8. Try to read "RTC" SMM variable for TimeZone.
    9. Convert/validate time.
   10. If time invalid: software reset, set defaults (Year=2000, Month=1, Day=1,
       Hour=0, Minute=0, Second=0, TimeZone=2047, Daylight=0).
   11. Write current time via PcRtcSetTime.
   12. Get wakeup alarm time.
   13. If no alarm pending: set default alarm (2000-01-01, clear AIE).

  @param[in] SmmRuntimeRsc  Pointer to SMM_RSC_HANDLER_PROTOCOL.

  @return  EFI_SUCCESS           RTC initialized successfully.
  @return  EFI_DEVICE_ERROR      RTC hardware init failed.
**/
EFI_STATUS
EFIAPI
PcRtcInitRtcHardware (
  IN VOID  *SmmRuntimeRsc
  )
{
  EFI_STATUS  Status;
  UINT8       RegisterB;
  UINT8       RegisterBNew;
  UINT16      AlarmYear;
  EFI_TIME    CurrentTime;
  EFI_TIME    AlarmTime;
  BOOLEAN     AlarmEnabled;
  BOOLEAN     AlarmPending;
  UINT8       Century;
  UINTN       DataSize;
  UINTN       TempTime;

  gRtcCenturyOffset = 0x32;

  //
  // Step 1: Initialize RTC hardware registers
  //
  PcRtcWriteReg (RTC_REGISTER_A, 0x26);           // 32768 Hz, divider reset

  RegisterB = PcRtcReadReg (RTC_REGISTER_B);
  PcRtcReadReg (RTC_REGISTER_C);                   // Clear pending interrupt
  PcRtcWriteReg (RTC_REGISTER_D, 0);               // Clear VRT (will be set by hardware)

  //
  // Wait for UIP to clear
  //
  Status = PcRtcWaitForUpdateComplete ();
  if (EFI_ERROR (Status))
  {
    gRtcDaylight = 0;
    return EFI_DEVICE_ERROR;
  }

  //
  // Step 2: Read the current RTC time from hardware
  //
  CurrentTime.Second = PcRtcReadReg (RTC_SECONDS);
  CurrentTime.Minute = PcRtcReadReg (RTC_MINUTES);
  CurrentTime.Hour   = PcRtcReadReg (RTC_HOURS);
  CurrentTime.Day    = PcRtcReadReg (RTC_DAY_OF_MONTH);
  CurrentTime.Month  = PcRtcReadReg (RTC_MONTH);
  CurrentTime.Year   = PcRtcReadReg (RTC_YEAR);

  //
  // Step 3: Configure Register B
  //   Preserve bits: AIE (5), DM (2) = 0x24
  //   Set:           24HR (1) = 0x02
  //   Clear:         DSE (0), SQWE (3), UIE (4), PIE (6), SET (7)
  //
  RegisterBNew = (RegisterB & 0x24) | 0x02;
  PcRtcWriteReg (RTC_REGISTER_B, RegisterBNew);

  //
  // Step 4: Try to read the "RTC" SMM variable for TimeZone
  //
  DataSize = sizeof (UINT64);
  if (((SMM_RSC_HANDLER_PROTOCOL *)gSmmRuntimeRsc)->SmmGetVariable (
                                                      L"RTC",
                                                      &gEfiSmmVariableGuid,
                                                      0,
                                                      &DataSize,
                                                      &TempTime
                                                      ) >= 0)
  {
    gRtcTimeZone = (INT16)(TempTime & 0xFFFF);
    gRtcDaylight = (UINT8)((TempTime >> 16) & 0xFF);
  }
  else
  {
    gRtcTimeZone = 2047;
    gRtcDaylight = 0;
  }

  //
  // Step 5: Try to convert and validate the current time
  //
  Status = PcRtcConvertFromRegisterFormat (&CurrentTime, RegisterBNew);
  if (EFI_ERROR (Status) || EFI_ERROR (PcRtcValidateTime (&CurrentTime)))
  {
    //
    // Time invalid -- reset to factory defaults
    //
    //
    // Software reset via SMM CPU protocol write
    //
    PcRtcSmmCpuWrite ();

    CurrentTime.Year   = 2000;
    CurrentTime.Month  = 1;
    CurrentTime.Day    = 1;
    CurrentTime.Hour   = 0;
    CurrentTime.Minute = 0;
    CurrentTime.Second = 0;
    gRtcTimeZone       = 2047;
    gRtcDaylight       = 0;

    //
    // Ensure SET (bit 7) is clear, AIE (bit 5) is set, 24HR (bit 1) is set
    //
    PcRtcWriteReg (RTC_REGISTER_B, RegisterBNew & 0xDF | 0x02);
  }

  //
  // Step 6: Write back the SMM variable with the current time + config
  //
  Status = PcRtcSetTime (&CurrentTime, &gRtcConfig);
  if (EFI_ERROR (Status))
  {
    return EFI_DEVICE_ERROR;
  }

  //
  // Step 7: Get wakeup alarm time
  //
  Status = PcRtcGetWakeupTime (&AlarmEnabled, &AlarmPending, &AlarmTime, &gRtcConfig);

  //
  // Step 8: If no alarm pending, set default alarm (2000-01-01, clear AIE)
  //
  if (!AlarmEnabled && EFI_ERROR (Status))
  {
    //
    // Read the current config timezone/daylight
    //
    gRtcTimeZone = gRtcConfig.TimeZone;
    gRtcDaylight = gRtcConfig.Daylight;

    //
    // Set default alarm time: 2000-01-01 00:00:00
    //
    CurrentTime.Year   = 2000;
    CurrentTime.Month  = 1;
    CurrentTime.Day    = 1;
    CurrentTime.Hour   = 0;
    CurrentTime.Minute = 0;
    CurrentTime.Second = 0;

    Status = PcRtcWaitForUpdateComplete ();
    if (EFI_ERROR (Status))
    {
      return EFI_DEVICE_ERROR;
    }

    RegisterB = PcRtcReadReg (RTC_REGISTER_B);

    //
    // Convert to register format
    //
    PcRtcConvertToRegisterFormat (&CurrentTime, RegisterB);

    //
    // Delete the "RTCALARM" variable
    //
    Status = ((SMM_RSC_HANDLER_PROTOCOL *)gSmmRuntimeRsc)->SmmSetVariable (
                                                             L"RTCALARM",
                                                             &gEfiSmmVariableGuid,
                                                             7,
                                                             sizeof (EFI_TIME),
                                                             &CurrentTime
                                                             );
    if (EFI_ERROR (Status))
    {
      return EFI_DEVICE_ERROR;
    }

    //
    // Set Register B SET bit, write alarm registers, clear SET bit
    //
    PcRtcWriteReg (RTC_REGISTER_B, RegisterB | RTC_B_SET);
    PcRtcWriteReg (RTC_SECONDS_ALARM, CurrentTime.Second);
    PcRtcWriteReg (RTC_MINUTES_ALARM, CurrentTime.Minute);
    PcRtcWriteReg (RTC_HOURS_ALARM,   CurrentTime.Hour);
    PcRtcWriteReg (RTC_REGISTER_D, CurrentTime.Day & 0x3F);
    PcRtcWriteReg (RTC_MONTH,  CurrentTime.Month);
    PcRtcWriteReg (RTC_YEAR,   (UINT8)CurrentTime.Year);
    PcRtcWriteReg (RTC_REGISTER_B, (RegisterB | RTC_B_AIE | 0x80) & 0x7F);
  }

  return EFI_SUCCESS;
}

// ============================================================================
// PcRtcInitialize - Protocol registration (sub_884 at 0x884)
// ============================================================================

/**
  Initialize the SMM Runtime RSC handler.

  Scans gSmst->SmmRegisterProtocol for registered protocols to find
  gEfiSmmRscHandlerGuid. Once found, stores the protocol interface
  and registers the four RTC handlers.

  @param[in] Smst  Pointer to EFI_SMM_SYSTEM_TABLE2 (gSmst).

  @return  EFI_SUCCESS           RSC handler installed.
  @return  EFI_UNSUPPORTED       SMM Runtime RSC protocol not found.
**/
EFI_STATUS
EFIAPI
PcRtcInitialize (
  IN EFI_SMM_SYSTEM_TABLE2  *Smst
  )
{
  UINTN       Index;
  UINTN       ProtocolCount;
  VOID        *Interface;
  EFI_STATUS  Status;

  //
  // Scan the protocol database for gEfiSmmRscHandlerGuid
  //
  ProtocolCount = Smst->NumberOfProtocols;

  for (Index = 0; Index < ProtocolCount; Index++)
  {
    //
    // Get protocol entry from Smst->ProtocolRegistry
    // Each entry is 24 bytes:
    //   +0: Protocol GUID pointer
    //   +8: Protocol Interface (if matching)
    //   +16: Not used for matching
    //
    EFI_GUID *EntryGuid = (EFI_GUID *)(*(UINT64 *)(Smst + 160) + (Index * 24));

    if (CompareGuidPair (EntryGuid, &gEfiSmmRscHandlerGuid))
    {
      gSmmRuntimeRsc = *(VOID **)(*(UINT64 *)(Smst + 160) + (Index * 24) + 16);
      break;
    }
  }

  if (gSmmRuntimeRsc == NULL)
  {
    //
    // Could not find SMM Runtime Services Protocol
    //
    DebugPrint (4, "Couldn't find SMM Runtime Services\n");
    return EFI_UNSUPPORTED;
  }

  //
  // Initialize RTC hardware
  //
  Status = PcRtcInitRtcHardware (gSmmRuntimeRsc);
  if (EFI_ERROR (Status))
  {
    DebugPrint (
      0x80000000,
      "\nASSERT_EFI_ERROR (Status = %r)\n",
      Status
      );
    DebugAssert (
      "e:\\hs\\PcAtChipsetPkg\\PcatRealTimeClockSmm\\PcRtcSmmEntry.c",
      159,
      "!EFI_ERROR (Status)"
      );
  }

  //
  // Register the four RTC handlers in the RSC protocol
  //
  ((SMM_RSC_HANDLER_PROTOCOL *)gSmmRuntimeRsc)->Handler[0] = PcRtcSmmGetTimeHandler;
  ((SMM_RSC_HANDLER_PROTOCOL *)gSmmRuntimeRsc)->Handler[1] = PcRtcSmmSetTimeHandler;
  ((SMM_RSC_HANDLER_PROTOCOL *)gSmmRuntimeRsc)->Handler[2] = PcRtcSmmGetAlarmHandler;
  ((SMM_RSC_HANDLER_PROTOCOL *)gSmmRuntimeRsc)->Handler[3] = PcRtcSmmSetAlarmHandler;

  return EFI_SUCCESS;
}

// ============================================================================
// PcRtcSmmDriverInit - Full driver entry (sub_560 at 0x560)
// ============================================================================

/**
  Full SMM driver initialization.

  Steps:
    1. Save ImageHandle, SystemTable, BootServices, RuntimeServices to globals.
    2. Locate SMM Base2 protocol (GUID at 0x2A60).
    3. Call GetSmstLocation to get gSmst.
    4. Locate SMM Access2 protocol (GUID at 0x2A90).
    5. Get SMRAM capabilities (buffer size).
    6. Allocate SmramRanges buffer via Smst->SmmAllocatePool.
    7. Re-read SMRAM capabilities into gSmramRanges.
    8. Set gSmramRangeCount = BufferSize >> 5 (divide by 32).
    9. Get PCD protocol and read PcdPlatformType (token 5).
   10. Initialize HOB list.
   11. Check PCI express MMIO at config address 0x500 (if bit 31 clear):
       Write 0x500 to the word at address (PcdDbValue + 1024064).
       Then set bit 7 on the byte at (PcdDbValue + 1024068).
   12. TSC-based delay: read EFLAGS, disable interrupts,
       read TSC, wait ~357 TSC cycles, restore interrupts.
   13. Return.

  @param[in] ImageHandle  EFI image handle for this driver.
  @param[in] SystemTable  EFI system table.

  @return  EFI_STATUS.
**/
EFI_STATUS
EFIAPI
PcRtcSmmDriverInit (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS                  Status;
  UINTN                       SmramRangeBufferSize;
  VOID                        *SmmBase2;
  EFI_SMM_ACCESS2_PROTOCOL    *SmmAccess2;
  SMM_SERVICES_TABLE          *Smst;
  UINTN                       Index;
  UINTN                       CpuIo2Handle;
  UINT64                      CmosDelayTsc;
  UINT64                      InitialTsc;
  UINT64                      TargetEflags;
  BOOLEAN                     InterruptsEnabled;

  //
  // Step 1: Save EFI table pointers to globals
  //
  gImageHandle = ImageHandle;
  gST          = SystemTable;
  gBS          = SystemTable->BootServices;
  gRT          = SystemTable->RuntimeServices;

  //
  // Step 2: Locate SMM Base2 protocol
  //
  SmmBase2 = NULL;
  Status = gBS->LocateProtocol (
                 &gEfiSmmBase2ProtocolGuid,
                 NULL,
                 &SmmBase2
                 );
  if (EFI_ERROR (Status))
  {
    DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\SmmServicesTableLib\\SmmServicesTableLib.c",
      52,
      "!EFI_ERROR (Status)"
      );
  }

  if (SmmBase2 == NULL)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\SmmServicesTableLib\\SmmServicesTableLib.c",
      53,
      "InternalSmmBase2 != ((void *) 0)"
      );
  }

  //
  // Step 3: Get Smst location
  //
  Smst = NULL;
  ((EFI_SMM_BASE2_PROTOCOL *)SmmBase2)->GetSmstLocation (SmmBase2, &Smst);

  if (Smst == NULL)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\SmmServicesTableLib\\SmmServicesTableLib.c",
      59,
      "gSmst != ((void *) 0)"
      );
  }
  gSmst = Smst;

  //
  // Step 4: Locate SMM Access2 protocol
  //
  CpuIo2Handle = 0;
  Status = gBS->LocateProtocol (
                 &gEfiSmmAccess2ProtocolGuid,
                 NULL,
                 &CpuIo2Handle
                 );
  if (EFI_ERROR (Status))
  {
    DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\SmmMemoryAllocationLib\\MemoryAllocationLib.c",
      71,
      "!EFI_ERROR (Status)"
      );
  }

  //
  // Step 5: Get SMRAM capabilities (query size first)
  //
  SmramRangeBufferSize = 0;
  Status = ((EFI_SMM_ACCESS2_PROTOCOL *)(UINTN)CpuIo2Handle)->GetCapabilities (
                                                                (EFI_SMM_ACCESS2_PROTOCOL *)(UINTN)CpuIo2Handle,
                                                                &SmramRangeBufferSize,
                                                                NULL
                                                                );

  if (Status != EFI_BUFFER_TOO_SMALL)
  {
    Status = EFI_BUFFER_TOO_SMALL;
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\SmmMemoryAllocationLib\\MemoryAllocationLib.c",
      78,
      "Status == ((RETURN_STATUS)(0x8000000000000000ULL | (5)))"
      );
  }

  //
  // Step 6: Allocate buffer for SMRAM ranges
  //
  gSmramRanges = AllocateSmramPool (EfiRuntimeServicesData, SmramRangeBufferSize);
  if (gSmramRanges == NULL)
  {
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\SmmMemoryAllocationLib\\MemoryAllocationLib.c",
      81,
      "mSmramRanges != ((void *) 0)"
      );
  }

  //
  // Step 7: Re-read SMRAM ranges into the allocated buffer
  //
  Status = ((EFI_SMM_ACCESS2_PROTOCOL *)(UINTN)CpuIo2Handle)->GetCapabilities (
                                                                (EFI_SMM_ACCESS2_PROTOCOL *)(UINTN)CpuIo2Handle,
                                                                &SmramRangeBufferSize,
                                                                gSmramRanges
                                                                );
  if (EFI_ERROR (Status))
  {
    DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
    DebugAssert (
      "e:\\hs\\MdePkg\\Library\\SmmMemoryAllocationLib\\MemoryAllocationLib.c",
      84,
      "!EFI_ERROR (Status)"
      );
  }

  //
  // Step 8: Calculate SMRAM range count (each range is 32 bytes = 5 qwords >> 5)
  //
  gSmramRangeCount = SmramRangeBufferSize >> 5;

  //
  // Step 9: Get PCD protocol and read platform type
  //
  gPcdDbValue = ((PCD_PROTOCOL *)GetPcdProtocol ())->Get32 (5);

  //
  // Step 10: Initialize HOB list
  //
  GeHobList ();

  //
  // Step 11: Check PCIe config address for Express presence
  //
  if ((INT8)(*(UINT8 *)PciExpressReadAddress (1024068)) >= 0)
  {
    //
    // Write 0x500 to the word at PCIe config address 0x100100 (1024064)
    //
    PciExpressWrite500 ((UINT16 *)PciExpressReadAddress (1024064));
    //
    // Set bit 7 on the byte at 0x100104 (1024068) -- enable memory space
    //
    *(UINT8 *)PciExpressReadAddress (1024068) |= 0x80;
  }

  //
  // Step 12: TSC-based short delay (approx 357 TSC cycles)
  //
  TargetEflags = GetCallerEflags ();
  InterruptsEnabled = (TargetEflags & 0x200) != 0;

  DisableInterrupts ();

  //
  // Read initial TSC
  //
  CmosDelayTsc = ReadMmio32 (1288) & 0xFFFFFF;

  //
  // Calculate target TSC: initial + 357 cycles
  //
  InitialTsc = ReadTsc ();

  while ((((CmosDelayTsc + 357 - (UINT32)ReadMmio32 (1288)) & 0x800000) == 0))
  {
    CpuPause ();
  }

  ReadTsc ();

  //
  // Restore previous interrupt state
  //
  if (InterruptsEnabled)
  {
    EnableInterrupts ();
  }
  else
  {
    DisableInterrupts ();
  }

  return EFI_SUCCESS;
}

// ============================================================================
// SmmCoreEntry (sub_480 at 0x480 -> sub_560 at 0x560)
// ============================================================================

/**
  SMM Core Entry - called from _ModuleEntryPoint.
  Calls PcRtcSmmDriverInit to initialize all globals and protocol interfaces.

  @param[in] ImageHandle  EFI image handle for this driver.
  @param[in] SystemTable  EFI system table.
**/
VOID
EFIAPI
SmmCoreEntry (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  PcRtcSmmDriverInit (ImageHandle, SystemTable);
}

// ============================================================================
// _ModuleEntryPoint (0x4B4)
// ============================================================================

/**
  Module entry point for the SMM driver.

  This function:
    1. Calls PcRtcSmmDriverInit (via sub_560) for EFI library init.
    2. Sets gModuleEntryStatus to 0x8000000000000001 (EfiNotStarted).
    3. Sets up a SetJump buffer for recovery on LongJump.
    4. On initial SetJump return (0):
       a. Calls PcRtcInitialize (sub_884) to register RTC handlers.
       b. If initialization fails or recovery needed: calls LongJump.
       c. On recovery path: calls DebugAssert for AutoGen.c ASSERTs.
    5. On LongJump (non-zero): stores the return status.
    6. Returns the final status. If error: calls FreePoolMmramAware.

  @param[in] ImageHandle  EFI image handle for this driver.
  @param[in] SystemTable  EFI system table.

  @return  EFI_STATUS from driver initialization.
**/
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  UINT64      ReturnStatus;
  EFI_STATUS  Status;

  //
  // Initialize the driver
  //
  PcRtcSmmDriverInit (ImageHandle, SystemTable);

  gModuleEntryStatus = 0x8000000000000001ULL;

  //
  // SetJump for error recovery
  //
  if (SetJump (&gJumpBuffer) == 0)
  {
    //
    // First execution: initialize RTC and register handlers
    //
    Status = PcRtcInitialize (gSmst);

    if (Status >= EFI_SUCCESS || gModuleEntryStatus < 0)
    {
      gModuleEntryStatus = Status;
    }

    //
    // Reset the jump buffer and prepare for re-initialization
    //
    PcRtcValidateJumpBuffer (&gJumpBuffer);
    LongJump (&gJumpBuffer, -1);

    //
    // These ASSERTs are reached only via AutoGen.c recovery:
    //
    DebugAssert (
      "e:\\hs\\Build\\HR6N0XMLK\\DEBUG_VS2015\\X64\\PcAtChipsetPkg\\PcatRealTimeClockSmm\\PcatRealTimeClockSmm\\DEBUG\\AutoGen.c",
      436,
      "((BOOLEAN)(0==1))"
      );
    DebugAssert (
      "e:\\hs\\Build\\HR6N0XMLK\\DEBUG_VS2015\\X64\\PcAtChipsetPkg\\PcatRealTimeClockSmm\\PcatRealTimeClockSmm\\DEBUG\\AutoGen.c",
      451,
      "((BOOLEAN)(0==1))"
      );
  }

  ReturnStatus = gModuleEntryStatus;

  if (gModuleEntryStatus < 0)
  {
    //
    // Error path: free SMRAM pool
    //
    FreePoolMmramAware (gSmramRanges);
  }

  return ReturnStatus;
}

// ============================================================================
// SmmMain - backward compatibility entry (forwarded from entry point)
// ============================================================================

/**
  SmmMain - main initialization (previously separate, now part of _ModuleEntryPoint).

  @param[in] ImageHandle  EFI image handle for this driver.
  @param[in] Smst         SMM system table.

  @return  EFI_SUCCESS.
**/
EFI_STATUS
EFIAPI
SmmMain (
  IN EFI_HANDLE                ImageHandle,
  IN EFI_SMM_SYSTEM_TABLE2     *Smst
  )
{
  //
  // Save the SMM system table
  //
  gSmst = Smst;

  //
  // All remaining init happens in _ModuleEntryPoint via PcRtcSmmDriverInit
  // and PcRtcInitialize.
  //

  return EFI_SUCCESS;
}

/**
  SmmInstallConfigurationTable - install SMST + config protocol (unused wrapper)
  Original at 0x1158.
**/
VOID
SmmInstallConfigurationTable (
  VOID
  )
{
  //
  // This function is a no-op in the reconstructed driver; the original
  // source allocated and populated the configuration table via
  // gSmst->SmmInstallConfigurationTable.
  //
}