Newer
Older
AMI-Aptio-BIOS-Reversed / Metronome / Metronome.h
@Ajax Dong Ajax Dong 2 days ago 7 KB Init
/** @file
  Metronome.h -- Header for the UEFI Metronome Arch Protocol driver.

  This driver installs the gEfiMetronomeArchProtocolGuid onto the handle
  created by _ModuleEntryPoint, providing the platform with a calibrated
  microsecond-level delay service.  The protocol uses the PIT (8254) channel
  1 and the RTC CMOS status register (port 0x70/0x71) to implement a busy-wait
  loop with TSC-based microsecond granularity.

  Derived from the HR650X BIOS Metronome.efi (MdeModulePkg/Universal/Metronome).

  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
  SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#ifndef __METRONOME_H__
#define __

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

//
// External UEFI types -- the caller is expected to include UefiBaseType.h,
// UefiSpec.h, and Protocol/Metronome.h from the EDK II tree before this file.
//
typedef unsigned long long  UINT64;
typedef long long           INT64;
typedef unsigned int        UINT32;
typedef int                 INT32;
typedef unsigned short      UINT16;
typedef short               INT16;
typedef unsigned char       UINT8;
typedef char                INT8;
typedef UINT8               BOOLEAN;
typedef UINT64              EFI_STATUS;
typedef void *              EFI_HANDLE;
typedef void *              EFI_EVENT;
typedef UINT16              EFI_TPL;

//
// EFI_SUCCESS and common error codes.
//
#define EFI_SUCCESS              0
#define EFI_ERROR(a)             ((INT64)(a) < 0)
#define EFI_ERR(a)               (0x8000000000000000ULL | (a))

//
// EFI Metronome Arch Protocol GUID  (from MdePkg)
// {2C1E6E47-7A7D-41A5-8A19-5C480BCE5B95}
//
#define EFI_METRONOME_ARCH_PROTOCOL_GUID \
  { 0x2C1E6E47, 0x7A7D, 0x41A5, \
    { 0x8A, 0x19, 0x5C, 0x48, 0x0B, 0xCE, 0x5B, 0x95 } }

//
// EFI Metronome Arch Protocol signature.
//
#define EFI_METRONOME_ARCH_PROTOCOL_REVISION  0x00010000

//
// PCD GUID for PcdMetronomeInternal  (platform-specific)
//
#define PCD_METRONOME_INTERNAL_GUID \
  { 0x6B9EBD9C, 0xFE23, 0x47C8, \
    { 0x92, 0x26, 0x24, 0x63, 0x28, 0x4F, 0xD1, 0xAA } }

///
/// The metronome protocol entry point.
///
typedef
EFI_STATUS
(EFIAPI *EFI_METRONOME_WAIT)(
  IN UINT32  Microseconds
  );

///
/// EFI_METRONOME_ARCH_PROTOCOL
///
typedef struct {
  UINT64                Revision;
  EFI_METRONOME_WAIT    Wait;
} EFI_METRONOME_ARCH_PROTOCOL;

//
// 8254 PIT constants (used in MicrosecondDelay).
//
#define PIT_PORT_COUNTER0     0x40
#define PIT_PORT_COUNTER1     0x41
#define PIT_PORT_COUNTER2     0x42
#define PIT_PORT_CONTROL      0x43
#define PIT_CONTROL_COUNTER2  0xB6    // Counter 2, mode 3, 16-bit binary
#define PIT_FREQUENCY         3579545 // 3.579545 MHz (OSC / 12 on typical PC)

//
// RTC CMOS constants (used for NMI / status).
//
#define RTC_PORT_CMOS_ADDR    0x70
#define RTC_PORT_CMOS_DATA    0x71
#define RTC_REGISTER_D        0x0D    // Status Register D (bit 7 = RTC power)
#define RTC_NMI_ENABLE_BIT    0x80    // OR with CMOS addr to enable NMI

//
// I/O port used for PCI Express config space access.
//
#define PCI_EXPRESS_BASE_ADDRESS  0xF0000000ULL

//
// Local constants.
//
#define MICROSECONDS_PER_SECOND  1000000ULL
#define NANO_100_PER_SECOND      10000000ULL
#define RDTSC_WAIT_MASK          0x3FFFFF
#define RDTSC_WAIT_SHIFT         22

//
// Forward declarations.
//
EFI_STATUS
EFIAPI
MetronomeWait (
  IN UINT32  Microseconds
  );

//
// Library internal helpers (named after their EDK II origin).
//

/**
  Reads the Time-Stamp Counter.

  @return  Current TSC value.
**/
UINT64
__rdtsc_w (
  VOID
  );

/**
  Reads the current EFLAGS (caller's flags).

  @return  EFLAGS value.
**/
UINT64
__getcallerseflags_w (
  VOID
  );

/**
  Issues a CPU PAUSE (rep; nop) -- yields to hyper-thread sibling.

  @return  None.
**/
VOID
_mm_pause_w (
  VOID
  );

/**
  Enables interrupts (STI).

  @return  None.
**/
VOID
_enable_w (
  VOID
  );

/**
  Disables interrupts (CLI).

  @return  None.
**/
VOID
_disable_w (
  VOID
  );

/**
  Reads a 32-bit value from an I/O port (port must be 4-byte aligned).

  @param[in]  Port  I/O port number (must be aligned to 4).

  @return  The 32-bit value read.
**/
UINT32
IoRead32 (
  IN UINT16  Port
  );

/**
  Reads an unaligned 64-bit value from memory.

  @param[in]  Buffer  Pointer to the unaligned 64-bit value.

  @return  The 64-bit value read.
**/
UINT64
ReadUnaligned64 (
  IN CONST VOID  *Buffer
  );

/**
  Translates a PCI Express address (MMIO) by adding the base address.

  @param[in]  Address  PCI Express register offset (< 0x10000000).

  @return  The full MMIO address.
**/
UINT64
PciExpressGetAddress (
  IN UINT64  Address
  );

/**
  Programmes the legacy PIC (8259) to a known state via I/O port 0x4D0 / 0x4D1.

  Writes 0x0500 (little-endian) to the port pointed to by Address.

  @param[in]  Address  Pointer to the I/O port (must be WORD-aligned).

  @return  The value written (0x0500).
**/
UINT16
IoWrite16 (
  IN UINT16  *Address
  );

/**
  Returns the singleton pointer to the gPcdMetronomeInternal PPI/Protocol.

  On first call, locates the protocol via BootServices->LocateProtocol.
  Caches the result in mPcd.

  @return  Pointer to the PCD protocol interface, or NULL on failure.
**/
VOID *
GetPcdProtocol (
  VOID
  );

/**
  Returns the singleton pointer to the DebugLib protocol/PPI.

  On first call, locates the protocol (if the image size is <= 16 pages).
  Caches the result in mDebugLib.

  @return  Pointer to the Debug protocol interface, or NULL on failure.
**/
VOID *
GetDebugLib (
  VOID
  );

/**
  Internal ASSERT + debug-log helper.

  Formats a message via the DebugLib protocol and then calls DebugAssert().

  @param[in]  FileName     Source file name string.
  @param[in]  LineNumber   Line number of the assertion.
  @param[in]  Description  The assertion expression string.
**/
VOID
InternalAssert (
  IN UINT64       FileName,
  IN UINT64       LineNumber,
  IN UINT64       Description
  );

/**
  Internal ASSERT_EFI_ERROR helper.

  If (Status & ERROR_MASK), calls DebugAssert and DebugPrint.

  @param[in]  Status       The EFI_STATUS to check.
  @param[in]  Format       Format string for the debug message.
  @param[in]  ...          Variable arguments.

  @return  The (char) result of the DebugLib chain.
**/
UINT8
InternalAssertEfiError (
  IN UINT64       Status,
  IN CONST CHAR8  *Format,
  ...
  );

/**
  Locates the first HOB that matches the requested GUID type.

  Walks the HOB list (from SystemTable->BootServices->Hob.Start).

  @param[in]  HobStart  Pointer to the start of the HOB list.

  @return  Pointer to the matching HOB structure, or NULL.
**/
VOID *
GetNextGuidHob (
  IN CONST VOID  *HobStart
  );

/**
  Returns a cached pointer to the HOB list (mHobList).

  Lazily initialized from SystemTable->BootServices->Hob on first call.

  @return  Pointer to the start of the HOB list.
**/
VOID *
GetHobList (
  VOID
  );

/**
  Busy-waits for the specified number of microseconds using the
  PIT channel 2 and TSC.

  Internal implementation shared by the Metronome protocol.

  @param[in]  Microseconds  Number of microseconds to wait (must be >= 10).
**/
VOID
MicrosecondDelay (
  IN UINT32  Microseconds
  );

//
// Global variables exposed by the driver.
//
extern EFI_HANDLE              gImageHandle;
extern UINT64                  gSystemTable;
extern UINT64                  gBootServices;
extern UINT64                  gRuntimeServices;

#endif /* __METRONOME_H__ */