# Metronome

## Function Table

| Address | Name | Description |
|---------|------|-------------|
|  | **_mm_pause_w** |  |
|  | **__rdtsc_w** |  |
|  | **_enable_w** |  |
|  | **_disable_w** |  |
|  | **__getcallerseflags_w** |  |
|  | **IoRead32** |  |
|  | **ReadUnaligned64** |  |
|  | **PciExpressGetAddress** |  |
|  | **IoWrite16** |  |
|  | **MetronomeDriverInit** |  |
|  | **MetronomeWait** |  |
|  | **MicrosecondDelay** |  |
|  | **InternalAssert** |  |
|  | **InternalAssertEfiError** |  |
|  | **_ModuleEntryPoint** |  |
| Global | **data (from .data section at 0xFC0-0x1060)** |  |
| The | **EFI_HANDLE for this driver image (populated by UefiBootServicesTableLib).** |  |
| The | **EFI_SYSTEM_TABLE pointer (populated by UefiBootServicesTableLib).** |  |
| The | **EFI_BOOT_SERVICES pointer (derived from gSystemTable->BootServices).** |  |
| The | **EFI_RUNTIME_SERVICES pointer (derived from gSystemTable->RuntimeServices).** |  |
| Cached | **DebugLib protocol/PPI interface (initialised lazily).** |  |
| Cached | **HOB list pointer (initialised lazily by GetHobList).** |  |
| PCI | **Express MMIO base address (read from PCD via GetPcdProtocol).** |  |
| Cached | **PCD protocol interface (initialised lazily by GetPcdProtocol).** |  |
| EFI_METRONOME_ARCH_PROTOCOL | **instance installed by the driver.** |  |
| Revision | **= 0x00010000, Wait = MetronomeWait.** |  |
| GUID | **constants (from .rdata section).** |  |
| gEfiMetronomeArchProtocolGuid | **const UINT8  gEfiMetronomeArchProtocolGuid[16] = EFI_METRONOME_ARCH_PROTOCOL_GUID;** |  |
| gEfiPcdMetronomeInternalGuid | **(the PCD protocol GUID used by DxePcdLib)** |  |
| The | **DebugLib singleton protocol GUID (gEfiDebugLibProtocolGuid placeholder)** |  |
| Thunk | **/ intrinsic wrappers** |  |
| ASSERT | **((Port & 3) == 0);** |  |
| if | **((Port & 3) != 0) {** |  |
| ASSERT | **(Buffer != NULL);** |  |
| if | **(Buffer == NULL) {** |  |
| ASSERT | **((Address & ~0xFFFFFFF) == 0)** |  |
| if | **((Address & 0xFFFFFFFFF0000000ULL) != 0) {** |  |
| ASSERT | **((Address & 1) == 0);** |  |
| if | **(((UINT64)Address & 1) != 0) {** |  |
| Library | **initialisation helpers** |  |
| Save | **ImageHandle and SystemTable (UefiBootServicesTableLib init).** |  |
| gImageHandle | **= ImageHandle;** |  |
| Initialise | **HOB list (DxeHobLib).** |  |
| GetHobList | **();** |  |
| Locate | **PCD protocol and read PcdPciExpressBaseAddress.** |  |
| PcdProtocol | **= (UINT64)GetPcdProtocol ();** |  |
| Call | **PcdGet64 (5) via the protocol's Get64 method at offset +32.** |  |
| mPciExpressBaseAddress | **= (*(UINT64 (*)(UINT64))(PcdProtocol + 32))(5);** |  |
| If | **PCI Express config space is accessible (PcdPciExpressBaseAddress != 0)** |  |
| program | **the PIC via I/O ports.** |  |
| if | **((INT8)PciExpressGetAddress (1024068) >= 0) {** |  |
| Set | **bit 7 at the PCI express offset for byte 1024068** |  |
| Save | **interrupt state and disable interrupts.** |  |
| InterruptsEnabled | **= (__getcallerseflags_w () & 0x200) != 0;** |  |
| Read | **the current TSC and calculate the number of ticks corresponding** |  |
| to | **1288 microseconds.  The calculation uses the PIT frequency:** |  |
| Ticks | **= (PIT_FREQUENCY * Microseconds) / 1000000** |  |
| The | **result captures the bottom 24 bits.** |  |
| StartTSC | **= IoRead32 (1288) & 0xFFFFFF;    // Read PIT counter 2 current value** |  |
| Spin | **until the PIT counter has decremented by the delta.** |  |
| RDTSC_WAIT_MASK | **handles 22-bit rollover.** |  |
| Elapsed | **= StartTSC;** |  |
| Capture | **the elapsed TSC value after the spin.** |  |
| Microseconds | **= __rdtsc_w ();** |  |
| Restore | **interrupt state.** |  |
| if | **(InterruptsEnabled) {** |  |
| Public | **Metronome protocol entry** |  |
| Convert | **Microseconds to PIT ticks:** |  |
| For | **large delays (>= 1000000 us == 1 s) we divide first to avoid overflow:** |  |
| Ticks | **= 3579545 * (Microseconds / 10) / 100000** |  |
| if | **(Microseconds >= MICROSECONDS_PER_SECOND) {** |  |
| Internal | **delay implementation** |  |
| Number | **of 0x400000-tick chunks** |  |
| Remainder | **(< 0x400000)** |  |
| Wait | **for the current 0x400000-tick chunk:** |  |
| target | **= Delta + (PIT counter current value & 0xFFFFFF)** |  |
| UINT32 | **Target = Delta + (IoRead32 (1288) & 0xFFFFFF);** |  |
| Subsequent | **iterations wait a full chunk** |  |
| Spin | **until the PIT counter passes the target.** |  |
| The | **0x800000 bit handles 24-bit counter rollover.** |  |
| while | **(((Target - (UINT32)IoRead32 (1288)) & 0x800000) == 0) {** |  |
| Library | **support functions** |  |
| gSystemTable | **+ 104 = Number of HOB entries** |  |
| gSystemTable | **+ 112 = Pointer to HOB entry array** |  |
| HobList | **= NULL;** |  |
| Walk | **the HOB entries looking for a GUID match with the** |  |
| for | **(Index = 0; Index < *(UINT64 *)(gSystemTable + 104); Index++) {** |  |
| Found | **-- extract the data pointer at offset +16 of the HOB entry.** |  |
| HobList | **= (VOID *)(*(UINT64 *)(*(UINT64 *)(gSystemTable + 112) + 24 * Index + 16));** |  |
| ASSERT_EFI_ERROR | **(EFI_NOT_FOUND)** |  |
| InternalAssertEfiError | **(0x80000000LL** |  |
| ASSERT | **(mHobList != NULL)** |  |
| if | **(mHobList == 0) {** |  |
| Read | **the GUID we are looking for (from the .data section at unk_FF0/FF8).** |  |
| Guid1 | **= ReadUnaligned64 ((VOID *)((UINT8 *)&gEfiMetronomeArchProtocolGuid + 0));** |  |
| Read | **the GUID from the HOB entry.** |  |
| EntryGuid1 | **= ReadUnaligned64 (Entry);** |  |
| if | **(Guid1 == EntryGuid1 && Guid2 == EntryGuid2) {** |  |
| Call | **BootServices->LocateProtocol(&gPcdMetronomeInternalGuid, NULL, &mPcd)** |  |
| BootServices | **at gSystemTable + (BootServices offset) = gBootServices.** |  |
| LocateProtocol | **offset within BootServices = 320.** |  |
| Status | **= (*(UINT64 (*)(VOID *, UINT64, UINT64 *))(gBootServices + 320))(** |  |
| ASSERT | **(mPcd != NULL)** |  |
| if | **(mPcd == 0) {** |  |
| Call | **BootServices->GetMemoryMap() to determine the number of pages** |  |
| occupied | **by this image.  For Metronome, this is a self-check.** |  |
| BootServices | **offsets: GetMemoryMap at +24, AllocatePages at +32.** |  |
| PageCount | **= (*(UINT64 (*)(UINT64))(gBootServices + 24))(31);** |  |
| Only | **proceed if the image fits within 16 pages.** |  |
| if | **(PageCount <= 16) {** |  |
| Call | **DebugAssert (DebugLib + 8) with (FileName, LineNumber, Description).** |  |
| Read | **RTC CMOS status register D (0x0D) via ports 0x70/0x71.** |  |
| Preserve | **bit 7 (NMI enable) on the address port.** |  |
| __outbyte | **(RTC_PORT_CMOS_ADDR, RTC_REGISTER_D | RTC_NMI_ENABLE_BIT);** |  |
| Determine | **the error mask based on RTC power status.** |  |
| If | **CMOS register D > 3 and non-zero, derive the mask from the** |  |
| if | **(CmosData > 3) {** |  |
| Map | **CmosData to error mask:** |  |
| CmosData | **== 1 -> ErrorMask = 0x80000004 (EFI_INVALID_PARAMETER style)** |  |
| Otherwise | **-> ErrorMask = 0x80000006 (EFI_UNSUPPORTED style)** |  |
| if | **((CmosData - 1) <= 0xFD) {** |  |
| If | **the status matches the error mask, call DebugPrint via the protocol.** |  |
| if | **((ErrorMask & Status) != 0) {** |  |
| Driver | **entry point** |  |
| Perform | **library and global initialisation.** |  |
| MetronomeDriverInit | **(ImageHandle, SystemTable);** |  |
| Check | **whether the Metronome Arch Protocol is already installed.** |  |
| Protocol | **already installed** | ASSERT. |
| InternalAssert | **(** |  |
| Install | **the protocol onto a new handle.** |  |
| gBootServices | **+ 328 = InstallProtocolInterface** |  |
| Status | **= (*(EFI_STATUS (*)(VOID *, VOID *, VOID *, UINT64))(gBootServices + 328))(** |  |
| New | **handle** |  |
| Protocol | **GUID** |  |
| Protocol | **interface** |  |
| Not | **native (BOOLEAN = FALSE)** |  |
| ASSERT_EFI_ERROR | **(Status)** |  |
| if | **(EFI_ERROR (Status)) {** |  |

---
*Generated by HR650X BIOS Decompilation Project*