Newer
Older
AMI-Aptio-BIOS-Reversed / PcRtc / PcRtc.h
@Ajax Dong Ajax Dong 2 days ago 23 KB Init
/**
 * @file PcRtc.h
 *
 * @brief PcRtc - PC-AT Real-Time Clock Runtime DXE Driver
 *
 * UEFI Runtime DXE driver that implements the EFI RealTimeClock services
 * (GetTime, SetTime, GetWakeupTime, SetWakeupTime) by accessing the
 * CMOS RTC hardware via legacy I/O ports 0x70/0x71.
 *
 * Source: PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/
 * Files:  PcRtcEntry.c, PcRtc.c, AutoGen.c
 *
 * This driver is part of the HR650X BIOS PcRtc module (index 0034).
 */

#ifndef PC_RTC_H_
#define PC_RTC_H_

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

// =========================================================================
// GUID Definitions
// =========================================================================

// -------------------------------------------------------------------------
// DebugLib Protocol GUID (UBA Platform Debug Library)
// 36232936-0E76-31C8-A13A-3AF2FC1C3932
// Located at .data +0x0000 (VA 0x5000)
// -------------------------------------------------------------------------
#define DEBUGLIB_PROTOCOL_GUID \
  { 0x36232936, 0x0E76, 0x31C8, \
    { 0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32 } }

// -------------------------------------------------------------------------
// HOB List GUID (Standard UEFI Hand-Off Block list)
// 7739F24C-93D7-11D4-9A3A-0090273FC14D
// Located at .data +0x0050 (VA 0x5050)
// -------------------------------------------------------------------------
#define HOB_LIST_GUID \
  { 0x7739F24C, 0x93D7, 0x11D4, \
    { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }

// -------------------------------------------------------------------------
// Real-Time Clock Architecture Protocol GUID (customized variant)
// NOTE: Standard UEFI spec defines this as 27CFAC88-..., but this binary
//       has 27CFAC87-... (one bit difference in Data1). This may be a
//       vendor-customized GUID.
// 27CFAC87-46CC-11D4-9A38-0090273FC14D
// Located at .data +0x0060 (VA 0x5060)
// -------------------------------------------------------------------------
#define RTC_ARCH_PROTOCOL_GUID \
  { 0x27CFAC87, 0x46CC, 0x11D4, \
    { 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }

// -------------------------------------------------------------------------
// Unknown Protocol GUID 1
// 11B34006-D85B-4D0A-A290-D5A571310EF7
// Located at .data +0x0020 (VA 0x5020)
// -------------------------------------------------------------------------
#define UNKNOWN_PROTOCOL_1_GUID \
  { 0x11B34006, 0xD85B, 0x4D0A, \
    { 0xA2, 0x90, 0xD5, 0xA5, 0x71, 0x31, 0x0E, 0xF7 } }

// -------------------------------------------------------------------------
// Unknown Protocol GUID 2
// 27ABF055-B1B8-4C26-8048-748F37BAA2DF
// Located at .data +0x0070 (VA 0x5070)
// -------------------------------------------------------------------------
#define UNKNOWN_PROTOCOL_2_GUID \
  { 0x27ABF055, 0xB1B8, 0x4C26, \
    { 0x80, 0x48, 0x74, 0x8F, 0x37, 0xBA, 0xA2, 0xDF } }

// -------------------------------------------------------------------------
// Unknown Protocol GUID 3
// 13FA7698-C831-49C7-87EA-8F43FCC25196
// Located at .data +0x0080 (VA 0x5080)
// -------------------------------------------------------------------------
#define UNKNOWN_PROTOCOL_3_GUID \
  { 0x13FA7698, 0xC831, 0x49C7, \
    { 0x87, 0xEA, 0x8F, 0x43, 0xFC, 0xC2, 0x51, 0x96 } }

// -------------------------------------------------------------------------
// DXE Services Table GUID (Standard UEFI)
// 05AD34BA-6F02-4214-952E-4DA0398E2BB9
// Located at .data +0x0090 (VA 0x5090)
// -------------------------------------------------------------------------
#define DXE_SERVICES_TABLE_GUID \
  { 0x05AD34BA, 0x6F02, 0x4214, \
    { 0x95, 0x2E, 0x4D, 0xA0, 0x39, 0x8E, 0x2B, 0xB9 } }

// -------------------------------------------------------------------------
// Unknown Protocol GUID 4
// 378D7B65-8DA9-4773-B6E4-A47826A833E1
// Located at .data +0x00A0 (VA 0x50A0)
// -------------------------------------------------------------------------
#define UNKNOWN_PROTOCOL_4_GUID \
  { 0x378D7B65, 0x8DA9, 0x4773, \
    { 0xB6, 0xE4, 0xA4, 0x78, 0x26, 0xA8, 0x33, 0xE1 } }


// =========================================================================
// CMOS RTC Register Map
// =========================================================================

/// CMOS I/O port to select register index (NMI enable in bit 7)
#define RTC_INDEX_PORT      0x70

/// CMOS I/O port to read/write data
#define RTC_DATA_PORT       0x71

/// NMI enable bit mask -- must be ORed into index port value
#define RTC_NMI_ENABLE      0x80

/// CMOS register addresses for time/date
#define RTC_REG_SECONDS     0x00
#define RTC_REG_SECONDS_ALARM  0x01
#define RTC_REG_MINUTES     0x02
#define RTC_REG_MINUTES_ALARM  0x03
#define RTC_REG_HOURS       0x04
#define RTC_REG_HOURS_ALARM     0x05
#define RTC_REG_DAY_OF_WEEK 0x06
#define RTC_REG_DAY_OF_MONTH    0x07
#define RTC_REG_MONTH       0x08
#define RTC_REG_YEAR        0x09

/// CMOS register addresses for RTC status
#define RTC_REG_STATUS_A    0x0A
#define RTC_REG_STATUS_B    0x0B
#define RTC_REG_STATUS_C    0x0C
#define RTC_REG_STATUS_D    0x0D

/// Century byte offset (configurable via PCD, default = 0x55)
#define RTC_REG_CENTURY_DEFAULT 0x55

// -------------------------------------------------------------------------
// Register A bits
// -------------------------------------------------------------------------
#define RTC_REG_A_UIP       BIT7   ///< Update In Progress -- 1 = time update active
#define RTC_REG_A_DV_SHIFT  4      ///< Divider chain setting
#define RTC_REG_A_DV_MASK   0x70   ///< DV0-DV2 divider bits
#define RTC_REG_A_RATE_MASK 0x0F   ///< Rate selection bits

// -------------------------------------------------------------------------
// Register B bits
// -------------------------------------------------------------------------
#define RTC_REG_B_SET       BIT7   ///< 1 = inhibit updates (for writing time)
#define RTC_REG_B_PIE       BIT6   ///< Periodic Interrupt Enable
#define RTC_REG_B_AIE       BIT5   ///< Alarm Interrupt Enable
#define RTC_REG_B_UIE       BIT4   ///< Update Interrupt Enable
#define RTC_REG_B_SQWE      BIT3   ///< Square Wave Enable
#define RTC_REG_B_DM        BIT2   ///< Data Mode: 0=BCD, 1=Binary
#define RTC_REG_B_24H       BIT1   ///< Hour Format: 0=12h, 1=24h
#define RTC_REG_B_DSE       BIT0   ///< Daylight Savings Enable

// -------------------------------------------------------------------------
// Register C bits
// -------------------------------------------------------------------------
#define RTC_REG_C_IRQF      BIT7   ///< Interrupt Request Flag (any IRQ)
#define RTC_REG_C_PF        BIT6   ///< Periodic Interrupt Flag
#define RTC_REG_C_AF        BIT5   ///< Alarm Interrupt Flag
#define RTC_REG_C_UF        BIT4   ///< Update Interrupt Flag

// -------------------------------------------------------------------------
// Register D bits
// -------------------------------------------------------------------------
#define RTC_REG_D_VRT       BIT7   ///< Valid RAM and Time (battery status)


// =========================================================================
// Alarm "Don't Care" Values
// =========================================================================

/// When an alarm register reads 0xC0-0xFF, the field is "don't care"
#define RTC_ALARM_DONT_CARE_MIN 0xC0


// =========================================================================
// Time Conversion Constants
// =========================================================================

/// Maximum BCD byte value for decimal tens digit
#define BCD_TENS_MAX        0x09

/// Maximum valid binary year value for validation (year <= 2099 typically)
#define MAX_VALID_YEAR      2099


// =========================================================================
// EFI_TIME Default Values (used when RTC battery is dead)
// =========================================================================

/// Default year when RTC time is invalid
#define RTC_DEFAULT_YEAR    2000

/// Default month when RTC time is invalid
#define RTC_DEFAULT_MONTH   1

/// Default day when RTC time is invalid
#define RTC_DEFAULT_DAY     1

/// Default hour when RTC time is invalid
#define RTC_DEFAULT_HOUR    0

/// Default minute when RTC time is invalid
#define RTC_DEFAULT_MINUTE  0

/// Default second when RTC time is invalid
#define RTC_DEFAULT_SECOND  0


// =========================================================================
// RTC Lock States
// =========================================================================

#define RTC_LOCK_INITIALIZER    { EFI_TPL_APPLICATION }


// =========================================================================
// Function Prototypes - PcRtcEntry.c
// =========================================================================

/**
 * @brief UEFI Driver Entry Point
 *
 * Called by the DXE Core dispatcher. Saves global UEFI table pointers
 * (gImageHandle, gST, gBS, gRT) and initializes the RTC driver.
 * Entry point address: 0x1114.
 *
 * The entry point performs:
 *   1. Cache ImageHandle, SystemTable, BootServices, RuntimeServices
 *      in global variables
 *   2. Call PcRtcEntryInit() to initialize RTC hardware and install
 *      runtime services
 *   3. Return EFI_SUCCESS or error code from PcRtcEntryInit()
 *
 * @param[in] ImageHandle  UEFI image handle for this driver
 * @param[in] SystemTable  Pointer to EFI System Table
 *
 * @return EFI_STATUS
 * @retval EFI_SUCCESS        RTC driver initialized successfully
 * @retval other              Error from PcRtcEntryInit() (asserts on error)
 */
EFI_STATUS
EFIAPI
ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  );

// =========================================================================
// Function Prototypes - PcRtc.c (provided by EDK2)
//
// These are the standard PcAtChipsetPkg RTC functions. Their exact
// addresses in the binary require IDA-based disassembly to determine
// (listed as approximate VA ranges for the .text section).
// =========================================================================

/**
 * @brief Initialize the RTC driver and register runtime services
 *
 * Main initialization function (called from ModuleEntryPoint).
 * Performs the following:
 *   1. Get HOB list via GetHobList()
 *   2. Verify RTC hardware is functional (check Registers A, D)
 *   3. Read current time, validate, default if invalid
 *   4. Register SetVirtualAddressMap event for runtime pointer conversion
 *   5. Install EFI RealTimeClock services in gRT->GetTime/SetTime/
 *      GetWakeupTime/SetWakeupTime
 *
 * Located in PcRtcEntry.c (~0x113C in .text or nearby)
 *
 * @return EFI_STATUS
 * @retval EFI_SUCCESS           RTC driver ready
 * @retval EFI_INVALID_PARAMETER Could not validate time
 */
EFI_STATUS
PcRtcEntryInit (
  VOID
  );

/**
 * @brief Read current time from CMOS RTC
 *
 * Implements EFI_RUNTIME_SERVICES.GetTime.
 * Reading flow:
 *   1. Acquire RTC lock (raise TPL to TPL_HIGH_LEVEL)
 *   2. Wait for update cycle to complete (UIP bit clears)
 *   3. Read all time registers (seconds, minutes, hours, day-of-week,
 *      day-of-month, month, year, century)
 *   4. Convert BCD to binary if needed (check Register B bit 2)
 *   5. Convert 12h to 24h if needed (check Register B bit 1)
 *   6. Release lock
 *   7. Return time (and capabilities if requested)
 *
 * Address: ~0x... in .text section
 *
 * @param[out]  Time         Pointer to EFI_TIME to receive current time
 * @param[out]  Capabilities Optional pointer to EFI_TIME_CAPABILITIES
 *
 * @return EFI_STATUS
 * @retval EFI_SUCCESS           Time read successfully
 * @retval EFI_INVALID_PARAMETER Time is NULL
 * @retval EFI_DEVICE_ERROR      RTC hardware error (Register D VRT bit cleared)
 */
EFI_STATUS
EFIAPI
PcRtcGetTime (
  OUT EFI_TIME               *Time,
  OUT EFI_TIME_CAPABILITIES  *Capabilities OPTIONAL
  );

/**
 * @brief Set current time in CMOS RTC
 *
 * Implements EFI_RUNTIME_SERVICES.SetTime.
 * Writing flow:
 *   1. Validate Time fields (year, month, day, hour, minute, second)
 *   2. Acquire RTC lock
 *   3. Set Register B SET bit (inhibit updates)
 *   4. Write all time registers (seconds, minutes, hours, day-of-week,
 *      day-of-month, month, year, century)
 *   5. Ensure 24h mode is set (Register B bit 1)
 *   6. Clear SET bit (re-enable updates)
 *   7. Release lock
 *
 * Address: ~0x... in .text section
 *
 * @param[in] Time  Pointer to EFI_TIME to set
 *
 * @return EFI_STATUS
 * @retval EFI_SUCCESS           Time set successfully
 * @retval EFI_INVALID_PARAMETER Time fields are invalid
 * @retval EFI_DEVICE_ERROR      RTC hardware error
 */
EFI_STATUS
EFIAPI
PcRtcSetTime (
  IN EFI_TIME  *Time
  );

/**
 * @brief Read RTC alarm time (wakeup time)
 *
 * Implements EFI_RUNTIME_SERVICES.GetWakeupTime.
 * Reads CMOS alarm registers (0x01, 0x03, 0x05) and checks if
 * AIE (Alarm Interrupt Enable) is set in Register B.
 * Values of 0xC0-0xFF in alarm registers indicate "don't care"
 * fields (per RTC specification).
 *
 * Address: ~0x... in .text section
 *
 * @param[out] Enabled  TRUE if alarm is enabled (Register B AIE bit set)
 * @param[out] Pending  TRUE if alarm interrupt is pending (Register C AF bit)
 * @param[out] Time     Current alarm time (enabled fields only)
 *
 * @return EFI_STATUS
 * @retval EFI_SUCCESS           Alarm read successfully
 * @retval EFI_INVALID_PARAMETER Time or Enabled is NULL
 * @retval EFI_UNSUPPORTED       Alarm not supported or no interrupt connected
 */
EFI_STATUS
EFIAPI
PcRtcGetWakeupTime (
  OUT BOOLEAN   *Enabled,
  OUT BOOLEAN   *Pending,
  OUT EFI_TIME  *Time
  );

/**
 * @brief Set RTC alarm time (wakeup time)
 *
 * Implements EFI_RUNTIME_SERVICES.SetWakeupTime.
 * Writing flow:
 *   1. Acquire RTC lock
 *   2. Clear AIE bit in Register B (disable alarm)
 *   3. Write alarm registers: second (0x01), minute (0x03), hour (0x05)
 *      With Enabled=FALSE, writes 0xC0 to all (= don't care = disabled)
 *   4. Read Register C to clear any pending alarm IRQ
 *   5. If Enabled=TRUE, set AIE bit in Register B
 *   6. Release lock
 *
 * Address: ~0x... in .text section
 *
 * @param[in] Enabled  TRUE to enable alarm, FALSE to disable
 * @param[in] Time     Alarm time (ignored if Enabled=FALSE)

 * @return EFI_STATUS
 * @retval EFI_SUCCESS           Alarm set successfully
 * @retval EFI_INVALID_PARAMETER Time is NULL with Enabled=TRUE
 * @retval EFI_DEVICE_ERROR      RTC hardware error
 */
EFI_STATUS
EFIAPI
PcRtcSetWakeupTime (
  IN BOOLEAN   Enabled,
  IN EFI_TIME  *Time OPTIONAL
  );

/**
 * @brief Read a byte from CMOS RAM
 *
 * Selects the CMOS register via port 0x70 and reads it via port 0x71.
 * Preserves the NMI enable bit (bit 7) in the index register.
 *
 * @param[in] Address  CMOS register address (0x00-0x7F typically)
 *
 * @return UINT8  The data byte read from the selected CMOS register
 */
UINT8
PcRtcRead (
  IN UINT8  Address
  );

/**
 * @brief Write a byte to CMOS RAM
 *
 * Selects the CMOS register via port 0x70 and writes data via port 0x71.
 * Preserves the NMI enable bit (bit 7) in the index register.
 *
 * @param[in] Address  CMOS register address (0x00-0x7F typically)
 * @param[in] Data     The data byte to write
 */
VOID
PcRtcWrite (
  IN UINT8  Address,
  IN UINT8  Data
  );

/**
 * @brief Wait for RTC update cycle to complete
 *
 * Polls Register A bit 7 (UIP = Update In Progress) until it clears.
 * When UIP is 1, the RTC is updating its time registers and reading
 * them would return inconsistent data.
 *
 * After UIP clears, reading the time registers must complete within
 * 244 microseconds (one update cycle at 4.096 kHz) to avoid reading
 * during the next update.
 *
 * @retval EFI_SUCCESS    Update completed, safe to read time
 * @retval EFI_TIMEOUT    Update did not complete (hardware error)
 */
EFI_STATUS
PcRtcWaitForUpdate (
  VOID
  );

/**
 * @brief Validate all time fields
 *
 * Checks EFI_TIME fields:
 *   - Year: >= 1998 (typical, may vary by PCD)
 *   - Month: 1-12
 *   - Day: 1-max_days_in_month (validates against month/year)
 *   - Hour: 0-23
 *   - Minute: 0-59
 *   - Second: 0-59
 *   - Nanosecond: 0-999999999 (if checked)
 *   - Timezone: valid range or EFI_UNSPECIFIED_TIMEZONE
 *   - Daylight: valid flags
 *
 * @param[in] Time  Pointer to EFI_TIME to validate
 *
 * @return BOOLEAN
 * @retval TRUE   All time fields are within valid ranges
 * @retval FALSE  One or more time fields are invalid
 */
BOOLEAN
PcRtcValidateTime (
  IN EFI_TIME  *Time
  );

/**
 * @brief Validate the Day field against the month/year
 *
 * Returns the maximum day number in the specified month,
 * accounting for leap years (Gregorian calendar rules).
 * February in a leap year returns 29.
 *
 * @param[in] Month   Month (1-12)
 * @param[in] Year    Full year (e.g., 2024)
 *
 * @return UINT8  Maximum number of days in the given month/year
 */
UINT8
PcRtcValidateDay (
  IN UINT8   Month,
  IN UINT16  Year
  );

/**
 * @brief Check if an EFI_TIME structure has all fields valid
 *
 * Quick validation of time fields without detailed error reporting.
 * Used internally before writing to CMOS.
 *
 * @param[in] Time  Pointer to EFI_TIME to check
 *
 * @return BOOLEAN
 * @retval TRUE   All fields valid
 * @retval FALSE  Invalid fields
 */
BOOLEAN
PcRtcTimeFieldsValid (
  IN EFI_TIME  *Time
  );

/**
 * @brief Convert time fields between BCD and Binary formats
 *
 * Checks Register B bit 2 (DM = Data Mode):
 *   - If DM=0 (BCD), converts BCD time registers to binary EFI_TIME
 *   - If DM=1 (Binary), leaves time values as-is
 *
 * Also handles 12h-to-24h conversion by checking Register B bit 1:
 *   - If bit 1=0 (12h mode), checks PM bit (bit 7 of hour register)
 *     and converts to 24h format
 *
 * @param[in,out] Time      EFI_TIME structure to convert
 * @param[in]     RegisterB Current value of CMOS Register B
 */
VOID
PcRtcConvertTimeFields (
  IN OUT EFI_TIME  *Time,
  IN     UINT8     RegisterB
  );

/**
 * @brief Convert BCD-encoded byte to binary
 *
 * Example: 0x59 BCD -> 59 binary
 * Asserts: Value < 0xA0, (Value & 0xF) < 0xA
 *
 * @param[in] BcdValue  BCD-encoded byte (e.g., 0x59 for 59)
 *
 * @return UINT8  Binary value (e.g., 59)
 */
UINT8
PcRtcBcdToBinary (
  IN UINT8  BcdValue
  );

/**
 * @brief Convert binary value to BCD-encoded byte
 *
 * Example: 59 binary -> 0x59 BCD
 * Asserts: Value < 100
 *
 * @param[in] BinaryValue  Binary value (0-99)
 *
 * @return UINT8  BCD-encoded byte (e.g., 0x59)
 */
UINT8
PcRtcBinaryToBcd (
  IN UINT8  BinaryValue
  );

/**
 * @brief Set RTC time in hardware (internal, locked)
 *
 * Writes all time registers to CMOS:
 *   - Sets Register B SET bit (bit 7) to freeze time during write
 *   - Writes seconds (0x00), minutes (0x02), hours (0x04)
 *   - Writes day-of-week (0x06), day-of-month (0x07), month (0x08), year (0x09)
 *   - Writes century byte to PCD-configured CMOS offset
 *   - Ensures 24h mode in Register B bit 1
 *   - Clears SET bit to resume updates
 *
 * Caller must hold RTC lock before calling.
 *
 * @param[in] Time  EFI_TIME structure to write
 *
 * @return EFI_STATUS
 * @retval EFI_SUCCESS  Time written to CMOS successfully
 */
EFI_STATUS
PcRtcSetTimeInternal (
  IN EFI_TIME  *Time
  );

/**
 * @brief Get RTC time from hardware (internal, locked)
 *
 * Reads all time registers from CMOS:
 *   - Waits for UIP bit to clear
 *   - Reads seconds (0x00), minutes (0x02), hours (0x04)
 *   - Reads day-of-week (0x06), day-of-month (0x07), month (0x08), year (0x09)
 *   - Reads century from PCD-configured CMOS offset
 *   - Converts BCD/binary and 12h/24h as needed
 *
 * Caller must hold RTC lock before calling.
 *
 * @param[out] Time  EFI_TIME structure to fill
 *
 * @return EFI_STATUS
 * @retval EFI_SUCCESS  Time read from CMOS successfully
 */
EFI_STATUS
PcRtcGetTimeInternal (
  OUT EFI_TIME  *Time
  );

/**
 * @brief Acquire the RTC lock
 *
 * Raises TPL to TPL_HIGH_LEVEL and acquires the RTC spin lock
 * to prevent interrupt reentrancy during RTC register access.
 * This is critical because RTC reads require atomic access to
 * multiple registers (seconds, minutes, hours, etc.) and
 * must not be interrupted.
 *
 * @param[out] OldTpl  Receives the previous TPL to restore later
 */
VOID
PcRtcLockRtc (
  OUT EFI_TPL  *OldTpl
  );

/**
 * @brief Release the RTC lock
 *
 * Restores TPL to the value saved by PcRtcLockRtc().
 *
 * @param[in] OldTpl  TPL value to restore (from PcRtcLockRtc)
 */
VOID
PcRtcUnlockRtc (
  IN EFI_TPL  OldTpl
  );


// =========================================================================
// Library Function Prototypes (standard EDK2 BaseLib/BootService wrappers)
// =========================================================================

/**
 * @brief Locate and cache the DebugLib Protocol
 *
 * Searches for the platform DebugLib protocol by GUID
 * (36232936-0E76-31C8-A13A-3AF2FC1C3932) via gBS->LocateProtocol().
 * Caches the result globally for use by DebugPrint and DebugAssert.
 *
 * @return VOID*  Pointer to DebugLib protocol interface, or NULL if not found
 */
VOID *
GetDebugProtocol (
  VOID
  );

/**
 * @brief Debug output through platform DebugLib protocol
 *
 * Formats and outputs a debug message. Checks the debug level
 * mask from CMOS register 0x4B or MMIO fallback to determine
 * which error levels are enabled for this platform.
 *
 * @param[in] ErrorLevel  Debug message severity (EFI_D_* bitmask)
 * @param[in] Format      Format string (printf-style)
 * @param[in] ...         Variable arguments for format string
 */
VOID
DebugPrint (
  IN UINTN   ErrorLevel,
  IN CHAR8   *Format,
  ...
  );

/**
 * @brief Assertion handler through platform DebugLib protocol
 *
 * Called by ASSERT() macro when a condition fails.
 * Delegates to the DebugLib protocol's assertion handler.
 *
 * @param[in] FileName      Source file name where assertion failed
 * @param[in] LineNumber    Source line number where assertion failed
 * @param[in] Expression    Text of the assertion expression
 */
VOID
DebugAssert (
  IN CHAR8   *FileName,
  IN UINTN   LineNumber,
  IN CHAR8   *Expression
  );

/**
 * @brief Locate the HOB (Hand-Off Block) list
 *
 * Scans gST->ConfigurationTable[] for the entry with VendorGuid
 * matching gEfiHobListGuid (7739F24C-93D7-11D4-9A3A-0090273FC14D).
 * Caches the result globally.
 *
 * Each configuration table entry is 24 bytes:
 *   +0x00: EFI_GUID VendorGuid (16 bytes)
 *   +0x10: VOID*    VendorTable (8 bytes)
 *
 * @return VOID*  Pointer to HOB list start, or NULL if not found
 */
VOID *
GetHobList (
  VOID
  );

/**
 * @brief Read UINT64 from unaligned address
 *
 * Performs a 64-bit read from a potentially unaligned memory address.
 * Asserts that Buffer is not NULL.
 *
 * Standard implementation from MdePkg BaseLib Unaligned.c
 *
 * @param[in] Buffer  Pointer to read from (may be unaligned)
 *
 * @return UINT64  Value read
 */
UINT64
ReadUnaligned64 (
  IN CONST VOID  *Buffer
  );

/**
 * @brief Write UINT64 to unaligned address
 *
 * Performs a 64-bit write to a potentially unaligned memory address.
 * Asserts that Buffer is not NULL.
 *
 * Standard implementation from MdePkg BaseLib Unaligned.c
 *
 * @param[out] Buffer  Pointer to write to (may be unaligned)
 * @param[in]  Value   Value to write
 */
VOID
WriteUnaligned64 (
  OUT VOID    *Buffer,
  IN  UINT64  Value
  );

/**
 * @brief Compare two GUIDs for equality
 *
 * Compares GUIDs by reading their first 8 bytes and second 8 bytes
 * as UINT64 values via ReadUnaligned64.
 *
 * Standard implementation from MdePkg BaseLib
 *
 * @param[in] Guid1  First GUID to compare
 * @param[in] Guid2  Second GUID to compare
 *
 * @return BOOLEAN
 * @retval TRUE   GUIDs are identical
 * @retval FALSE  GUIDs differ
 */
BOOLEAN
CompareGuid (
  IN CONST EFI_GUID  *Guid1,
  IN CONST EFI_GUID  *Guid2
  );


#endif /* PC_RTC_H_ */