Newer
Older
AMI-Aptio-BIOS-Reversed / MdeModulePkg / Universal / TimestampDxe / TimestampDxe.h
@Ajax Dong Ajax Dong 2 days ago 14 KB Full restructure
/** @file
  TimestampDxe -- UEFI Timer Stamp DXE Driver

  This DXE driver implements the EFI_TIMESTAMP_PROTOCOL for UEFI. It calibrates the
  x86 Time-Stamp Counter (TSC) frequency by measuring TSC ticks against a known
  hardware counter accessible via I/O port 0x508, then publishes the timestamp
  protocol for use by other UEFI components.

  The driver performs TSC frequency calibration at initialization by executing a
  timed wait loop using an I/O-mapped counter at port 0x508 (a PCH timer counter,
  likely the TCO timer or a custom LPC-decoded counter). It measures elapsed TSC
  ticks over a fixed count of the reference counter (357 increments), then
  multiplies by 10000 to obtain the TSC frequency in Hz.

  UEFI Phase: DXE (Driver Execution Environment)
  Protocol Produced: gEfiTimestampProtocolGuid
  Dependencies: gEfiPcdProtocolGuid, gEfiHobListGuid (via System Table config table)

  Source (from debug strings): MdeModulePkg/Universal/TimestampDxe/TimestampDxe.c
  Build environment: e:\hs\ (presumably EDK2 build tree)

  Hardware-specific behavior:
  - Uses I/O port 0x508 for reference counter (24-bit free-running counter)
  - Uses RTC CMOS index 0x4B for platform identification (debug routing)
  - Writes to fixed physical address 0xFDAF0490 as fallback for platform detection
  - May access RTC through PCIe Enhanced Configuration Access Mechanism (ECAM)
    by writing to PCIe config space at PcdPciExpressBaseAddress

Copyright (c) HR650X BIOS Decompilation Project
**/

#ifndef __TIMESTAMP_DXE_H__
#define __TIMESTAMP_DXE_H__

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

//
// ---------------------------------------------------------------------------
// Protocol GUIDs
// ---------------------------------------------------------------------------

///
/// {AFBFDE41-2E6E-4262-BA65-62B9236E5495}
/// EFI Timestamp Protocol GUID (from UEFI Specification)
/// Defined in MdePkg/Protocol/Timestamp.h
///
#define EFI_TIMESTAMP_PROTOCOL_GUID \
  { 0xAFBFDE41, 0x2E6E, 0x4262, { 0xBA, 0x65, 0x62, 0xB9, 0x23, 0x6E, 0x54, 0x95 } }

///
/// {7739F24C-93D7-11D4-9A3A-0090273FC14D}
/// EFI HOB List GUID -- used to locate the HOB list via System Table
/// ConfigurationTable.
///
#define EFI_HOB_LIST_GUID \
  { 0x7739F24C, 0x93D7, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }

///
/// {11B34006-D85B-4D0A-A290-D5A571310EF7}
/// gEfiPcdProtocolGuid -- used to access PCD (Platform Configuration Database)
/// services. Required for retrieving PcdPciExpressBaseAddress and PCD values
/// for PCIe ECAM access.
///
#define EFI_PCD_PROTOCOL_GUID \
  { 0x11B34006, 0xD85B, 0x4D0A, { 0xA2, 0x90, 0xD5, 0xA5, 0x71, 0x31, 0x0E, 0xF7 } }

///
/// {36232936-0E76-31C8-A13A-3AF2FC1C3932}
/// Debug/Report Status Code Protocol GUID -- used to locate the debug
/// output protocol for assertion messages and debug prints.
/// NOTE: This GUID has been verified against the binary constants but is NOT
/// a standard UEFI spec GUID; it may be platform-specific or from an
/// EDK2-internal protocol definition (possibly gEfiStatusCodeRuntimeProtocolGuid
/// in a modified form, or a custom debug protocol).
///
#define EFI_DEBUG_PROTOCOL_GUID \
  { 0x36232936, 0x0E76, 0x31C8, { 0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32 } }

//
// ---------------------------------------------------------------------------
// Protocol Structures
// ---------------------------------------------------------------------------

/**
  Retrieves the current value of the time-stamp counter.

  Returns the raw TSC value (from RDTSC instruction) minus the base timestamp
  saved at driver initialization. This gives the number of TSC ticks elapsed
  since the driver was loaded.

  @param[out]  Timestamp  Pointer to a UINT64 that receives the timestamp value.
                           If NULL, the function returns immediately.

  @retval EFI_SUCCESS           The operation completed successfully.
  @retval EFI_INVALID_PARAMETER Timestamp is NULL.

**/
typedef
EFI_STATUS
(EFIAPI *EFI_TIMESTAMP_GET)(
  OUT UINT64  *Timestamp
  );

//
// EFI_TIMESTAMP_PROTOCOL
//
// NOTE: This driver's implementation installs the protocol interface as a
// simple function table containing two function pointers only:
//   [0] = GetTimestamp
//   [1] = GetProperties
//
// The Frequency and EndTime fields are maintained as module-global variables
// rather than being embedded in the protocol structure. This deviates from
// the standard EDK2 EFI_TIMESTAMP_PROTOCOL definition which places Frequency
// and EndTime inline. Consumers should use GetProperties() to retrieve these
// values.
//
typedef struct {
  EFI_TIMESTAMP_GET  GetTimestamp;   // Offset 0x00: Get current TSC value
  EFI_TIMESTAMP_GET  GetProperties;  // Offset 0x08: Get timestamp properties
} EFI_TIMESTAMP_PROTOCOL;

//
// ---------------------------------------------------------------------------
// Module Global State (stored in .data segment)
// ---------------------------------------------------------------------------

///
/// EFI System Table passed by DXE core. Saved at entry.
///
extern EFI_SYSTEM_TABLE  *gSystemTable;

///
/// EFI Boot Services pointer. Derived from gSystemTable->BootServices.
///
extern EFI_BOOT_SERVICES  *gBootServices;

///
/// EFI Runtime Services pointer. Derived from gSystemTable->RuntimeServices.
///
extern EFI_RUNTIME_SERVICES  *gRuntimeServices;

///
/// EFI Image Handle passed by DXE core at entry.
///
extern EFI_HANDLE  gImageHandle;

///
/// Pointer to the debug/report protocol interface. NULL until located.
/// Used by DebugPrint() and DebugAssert() wrappers.
///
extern VOID  *gDebugProtocol;

///
/// Cached pointer to the HOB list, located via System Table ConfigurationTable
/// by matching gEfiHobListGuid. NULL until located.
///
extern VOID  *mHobList;

///
/// Cached PCD protocol interface. Located via gBS->LocateProtocol().
///
extern VOID  *mPcdProtocol;

///
/// PCI Express Configuration Space Base Address (MMIO base for ECAM).
/// Retrieved via PCD protocol Get32(Token=5).
///
extern UINT64  mPciExpressBaseAddress;

///
/// TSC frequency in Hz, computed during driver initialization.
/// Derived by measuring TSC ticks over a calibrated I/O port delay.
///
extern UINT64  mTimestampFrequencyHz;

//
// ---------------------------------------------------------------------------
// Module Data for EFI_TIMESTAMP_PROTOCOL Implementation
// ---------------------------------------------------------------------------

///
/// Base TSC value captured at driver initialization. Subtracted from raw TSC
/// in GetTimestamp() to produce elapsed ticks since boot.
///
extern UINT64  mBaseTimeStamp;

///
/// Maximum timestamp value before wrap (EndTime). Set to MAX_UINT64 (all 1s).
///
extern UINT64  mEndTime;

///
/// Exported frequency value (copy of mTimestampFrequencyHz), accessible via
/// GetProperties().
///
extern UINT64  mFrequency;

//
// ---------------------------------------------------------------------------
// Hardware Constants
// ---------------------------------------------------------------------------

///
/// I/O port for the reference timer counter used in TSC frequency calibration.
/// This is a 32-bit I/O port read, masked to 24 bits by the calibration code.
/// Likely the PCH TCO timer counter or a custom LPC-decoded free-running counter.
///
#define TIMESTAMP_CALIBRATION_PORT    0x508

///
/// Number of reference counter ticks to wait during calibration.
/// The calibration loop waits for the counter at TIMESTAMP_CALIBRATION_PORT
/// to increment by this many units, then measures the elapsed TSC ticks and
/// multiplies by 10000 to derive the TSC frequency in Hz.
///
#define TIMESTAMP_CALIBRATION_DELTA   357

///
/// Multiplier applied to measured TSC ticks to compute frequency in Hz.
/// If the calibration wait duration is exactly 100 microseconds, then
/// TSC_ticks * 10000 = TSC ticks per second = TSC frequency in Hz.
///
#define TIMESTAMP_TICK_TO_HZ_MULTIPLIER  10000

///
/// RTC CMOS Index register (I/O port 0x70)
///
#define RTC_INDEX_PORT      0x70

///
/// RTC CMOS Data register (I/O port 0x71)
///
#define RTC_DATA_PORT       0x71

///
/// CMOS offset 0x4B: Platform identifier byte.
/// Used to determine debug output routing.
///
#define RTC_CMOS_PLATFORM_ID  0x4B

///
/// Fixed physical memory address for platform identification fallback.
/// On Intel PCH platforms, this is in the PMC register space.
/// Bit 1 indicates platform type (0 = mobile/desktop, 1 = server).
///
#define PLATFORM_ID_MMIO_ADDR  0xFDAF0490ULL

//
// ---------------------------------------------------------------------------
// EFI Status Code Types used by debug functions
// ---------------------------------------------------------------------------

#define EFI_STATUS_CODE_TYPE_DEBUG   0x80000004
#define EFI_STATUS_CODE_TYPE_ERROR   0x80000006

//
// ---------------------------------------------------------------------------
// Function Declarations
// ---------------------------------------------------------------------------

/**
  Main entry point for the TimestampDxe driver.

  Initializes module globals (ImageHandle, SystemTable, BootServices,
  RuntimeServices), gets the HOB list and PCD protocol, calibrates TSC
  frequency by measuring against a hardware reference counter at I/O port 0x508,
  writes the calibration result to mTimestampFrequencyHz, and then installs
  the EFI_TIMESTAMP_PROTOCOL on a new handle.

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

  @retval EFI_SUCCESS           The entry point executed successfully. Protocol
                                was installed (or ASSERT on failure).
  @retval EFI_INVALID_PARAMETER BootServices or RuntimeServices were NULL.
  @return                       Status from InstallMultipleProtocolInterfaces.
                                Errors trigger ASSERT.

**/
EFI_STATUS
EFIAPI
TimestampDxeEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  );

/**
  Returns the current timestamp value.

  Computes elapsed TSC ticks since driver initialization by subtracting the
  saved base TSC value from the current RDTSC value.

  @param[out] Timestamp  Pointer to receive the timestamp value in TSC ticks.

  @retval EFI_SUCCESS  Timestamp value returned.

**/
EFI_STATUS
EFIAPI
TimestampGetTimestamp (
  OUT UINT64  *Timestamp
  );

/**
  Returns the properties of the timestamp counter.

  Fills in the Frequency (TSC Hz) and EndTime (maximum counter value) of the
  timestamp counter.

  @param[out] Timestamp  Pointer to a buffer where properties are written.
                          The buffer is expected to be at least 16 bytes and
                          receives:
                          - Offset 0x00: Frequency in Hz (UINT64)
                          - Offset 0x08: EndTime / max value (UINT64, always
                                          MAX_UINT64 for TSC)

  @retval EFI_SUCCESS           Properties returned.
  @retval EFI_INVALID_PARAMETER Timestamp pointer is NULL.

**/
EFI_STATUS
EFIAPI
TimestampGetProperties (
  OUT UINT64  *Timestamp
  );

//
// ---------------------------------------------------------------------------
// Library/Helper Functions (linked from BaseLib, BaseMemoryLib, DxePcdLib,
// DxeHobLib, UefiBootServicesTableLib, UefiRuntimeServicesTableLib)
// ---------------------------------------------------------------------------

/**
  Reads the current TSC value using the RDTSC instruction.

  @return 64-bit TSC value.

**/
UINT64
EFIAPI
AsmReadTsc (
  void
  );

/**
  Reads CPU EFLAGS of the caller.

  @return EFLAGS register value.

**/
UINTN
EFIAPI
AsmReadEflags (
  void
  );

/**
  Disables interrupts (CLI).

**/
VOID
EFIAPI
AsmDisableInterrupts (
  void
  );

/**
  Enables interrupts (STI).

**/
VOID
EFIAPI
AsmEnableInterrupts (
  void
  );

/**
  Executes the PAUSE instruction (hint to the processor for spin-wait loops).

**/
VOID
EFIAPI
AsmPause (
  void
  );

/**
  Reads a 32-bit value from an I/O port.

  @param[in] Port  I/O port address.

  @return Value read from the I/O port.

**/
UINT32
EFIAPI
IoRead32 (
  IN UINTN  Port
  );

/**
  Writes a 16-bit value to a memory-mapped I/O address.

  @param[in] Address  MMIO address.
  @param[in] Value    Value to write.

**/
VOID
EFIAPI
MmioWrite16 (
  IN UINTN   Address,
  IN UINT16  Value
  );

/**
  Reads an 8-bit value from an I/O port.

  @param[in] Port  I/O port address.

  @return Value read from the I/O port.

**/
UINT8
EFIAPI
IoRead8 (
  IN UINTN  Port
  );

/**
  Writes an 8-bit value to an I/O port.

  @param[in] Port   I/O port address.
  @param[in] Value  Value to write.

**/
VOID
EFIAPI
IoWrite8 (
  IN UINTN  Port,
  IN UINT8  Value
  );

/**
  Copies a block of memory (may handle overlapping buffers).

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

  @return Pointer to destination buffer.

**/
VOID *
EFIAPI
CopyMem (
  OUT VOID       *Destination,
  IN  CONST VOID *Source,
  IN  UINTN      Length
  );

/**
  Reads a UINT64 value from an unaligned pointer.

  @param[in] Buffer  Pointer to read from.

  @return 64-bit value read.

**/
UINT64
EFIAPI
ReadUnaligned64 (
  IN CONST VOID  *Buffer
  );

/**
  Locates a protocol interface by GUID.

  Wrapper around gBS->LocateProtocol().

  @param[in]  ProtocolGuid  GUID of the protocol to locate.
  @param[in]  Registration  Optional registration key (NULL for first locate).
  @param[out] Interface     Receives the protocol interface pointer.

  @retval EFI_SUCCESS  Protocol located successfully.

**/
EFI_STATUS
EFIAPI
LocateProtocol (
  IN  EFI_GUID  *ProtocolGuid,
  IN  VOID      *Registration  OPTIONAL,
  OUT VOID      **Interface
  );

/**
  Debug print function. Routes to the debug/report protocol.

  @param[in] ErrorLevel  Severity of the message (e.g., DEBUG_INFO).
  @param[in] Format      Format string.
  @param[in] ...         Variable arguments for the format string.

**/
VOID
EFIAPI
DebugPrint (
  IN UINTN        ErrorLevel,
  IN CONST CHAR8  *Format,
  ...
  );

/**
  Assertion handler. Routes to the debug/report protocol.

  @param[in] FileName     Source file name.
  @param[in] LineNumber   Line number of the assertion.
  @param[in] Description  Assert description string.

**/
VOID
EFIAPI
DebugAssert (
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Description
  );

/**
  Returns the HOB list pointer by searching the EFI System Table's
  ConfigurationTable for gEfiHobListGuid.

  Results are cached in mHobList after the first successful lookup.
  Asserts if the HOB list GUID is not found.

  @return Pointer to the start of the HOB list (EFI_HOB_LIST).

**/
VOID *
EFIAPI
GetHobList (
  void
  );

/**
  Gets the PCD protocol interface pointer.

  Locates gEfiPcdProtocolGuid via gBS->LocateProtocol(). Caches the result
  in mPcdProtocol. Asserts on failure.

  @return Pointer to the PCD protocol interface.

**/
VOID *
EFIAPI
GetPcdProtocol (
  void
  );

/**
  Reads a 32-bit PCD value by token number.

  @param[in] TokenNumber  The PCD token number.

  @return The 32-bit PCD value.

**/
UINT32
EFIAPI
PcdGet32 (
  IN UINTN  TokenNumber
  );

#endif // __TIMESTAMP_DXE_H__