Newer
Older
AMI-Aptio-BIOS-Reversed / PurleySktPkg / SouthClusterLbg / Wdt / WatchdogTimer / WatchdogTimer.md
@Ajax Dong Ajax Dong 2 days ago 6 KB Full restructure

WatchdogTimer

Function Table

Address Name Description
WatchdogTimerDriverEntryPoint
WatchdogTimerNotifyHandler
WatchdogTimerRegisterHandler
WatchdogTimerSetTimerPeriod
WatchdogTimerGetTimerPeriod
DebugAssertPrint
DebugAssert
SmmCommunicationSend
ReadUnaligned64
HobCompareGuidEntry
Protocol GUIDs
EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID /// {665E3FF5-46CC-11D4-9A38-0090273FC14D}
EFI_GUID gEfiWatchdogTimerArchProtocolGuid =
gEfiHobListGuid /// {7739F24C-93D7-11D4-9A3A-0090273FC14D}
EFI_GUID gEfiHobListGuid =
gEfiSmmCommunicationProtocolGuid /// {D2B2B828-0826-48A7-B3DF-983C006024F0}
EFI_GUID gEfiSmmCommunicationProtocolGuid =
gEfiGenericMemTestPatternGuid (HOB GUID for debug output device)
EFI_GUID gEfiGenericMemTestPatternGuid =
Global Variables
The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance installed on the handle.
Contains function pointers for RegisterHandler and SetTimerPeriod.
The third field (GetTimerPeriod) is overlapped with mWatchdogTimerPeriod.
EFI_WATCHDOG_TIMER_ARCH_PROTOCOL mWatchdogTimerProtocol = {
GetTimerPeriod is implicitly at &mWatchdogTimerPeriod
Stores the current watchdog timer period in 100ns units.
Initialized to WATCHDOG_TIMER_DEFAULT_PERIOD (1500 = 150us).
This also aliases with the third entry of the protocol structure
allowing GetTimerPeriod to return the period value directly.
UINT64 mWatchdogTimerPeriod = WATCHDOG_TIMER_DEFAULT_PERIOD;
Pointer to the registered watchdog notification function, or NULL.
VOID *mWatchdogNotifyFunction = NULL;
Flag indicating whether a watchdog notification handler is registered.
VOID *mWatchdogNotifyRegistered = NULL;
Cached pointer to the HOB list, obtained from the system configuration table.
VOID *mHobList = NULL;
Cached pointer to the SMM Communication Protocol interface.
VOID *mSmmCommunicationProtocol = NULL;
NMI flag byte. Accessed via CMOS I/O ports 0x70/0x71.
Bit layout: bit 7 of CMOS index 0x4B stores an NMI status value.
UINT8 mNmiFlag = 0;
Function Implementations
Initialize UEFI global variables (gImageHandle, gST, gBS, gRT)
gImageHandle = ImageHandle;
Initialize the HOB list
GetHobList ();
Install the EFI_WATCHDOG_TIMER_ARCH_PROTOCOL
Status = gBS->LocateProtocol (
Protocol already installed this is unexpected
DebugAssert (
Allocate pool for the protocol interface structure
EfiBootServicesData type, 16 bytes (2 function pointers)
Status = gBS->AllocatePool (
Initialize the protocol structure
is aliased at the same offset as the third protocol function pointer.
Install the protocol on the image handle
Status = gBS->InstallMultipleProtocolInterfaces (
Send SMM communication to update SMM watchdog handler state
Invoke registered notify function if present
if (mWatchdogNotifyRegistered != NULL) {
Log the reset event
Reset the system
if (NotifyFunction != NULL) {
Check if handler is already registered
if (mWatchdogNotifyRegistered == NULL) {
mWatchdogNotifyRegistered = (VOID *)NotifyFunction;
Store the period value (aliased with the GetTimerPeriod function pointer)
mWatchdogTimerPeriod = TimerPeriod;
Program the hardware timer
return gBS->SetTimer (
Return cached value if already initialized
DebugDevice = mHobList;
Allocate a buffer from EFI HOB space to read the HOB entry
HobSize = (UINTN)gBS->GetHobList ();
HOB is too small or invalid; return NULL
return NULL;
Locate the debug output device via protocol lookup
DebugDevice = NULL;
Cache the result
mHobList = DebugDevice;
Get the debug output device
DebugDevice = GetDebugOutputDevice ();
Read CMOS NMI flag to determine assert severity
Step 1: Save current CMOS index, mask to keep NMI enabled
SavedIndex = IoRead8 (0x70);
Step 2: Read the NMI status value at CMOS index 0x4B
NmiValue = IoRead8 (0x71);
Step 3: Determine effective error level from NMI value
NmiStatus = NmiValue;
If NMI value is zero, read from fixed memory location
NmiStatus *= ((volatile UINT8 *)0xFDAF0490) & 2 1;**
Map NMI status to error level:
NmiStatus == 1 -> EFI_ERROR_MAJOR (0x80000004)
NmiStatus != 1 -> EFI_ERROR_MINOR (0x80000006)
if ((NmiStatus - 1) <= 0xFD) {
DEBUG_WARN / DEBUG_ERROR level
EFI_D_ERROR (major)
EFI_D_WARN (minor)
Check if the determined error level matches the caller's mask
if ((EffectiveErrorLevel & ErrorLevel) != 0) {
Dispatch to debug output device
PrintFunction = (DEBUG_PRINT_ASSERT_FUNCTION)((DEBUG_PRINT_PROTOCOL *)DebugDevice)->Print;
Call the device's assert function
AssertFunction = (DEBUG_ASSERT_FUNCTION)((DEBUG_PRINT_PROTOCOL *)DebugDevice)->Assert;
if (mHobList != NULL) {
Initialize to failure state
Get the number of configuration table entries
TableCount = gST->NumberOfTableEntries;
Walk the configuration table looking for gEfiHobListGuid
ConfigTable = gST->ConfigurationTable;
HobEntry = ConfigTable[Index].VendorTable;
HOB list not found generate assert
Use cached protocol if available
SmmComm = (EFI_SMM_COMMUNICATION_PROTOCOL *)mSmmCommunicationProtocol;
Send the watchdog command via SMM communication
CommSize = sizeof (SMM_COMMUNICATION_BUFFER);
First call: validate Boot Services table
if (gBS == NULL) {
Locate the SMM Communication Protocol
Cache the protocol pointer
mSmmCommunicationProtocol = (VOID *)SmmComm;
Read the first 8 bytes of each GUID
EntryGuidPart1 = ReadUnaligned64 (Entry);
Read the second 8 bytes of each GUID
EntryGuidPart2 = ReadUnaligned64 ((UINT8 *)Entry + 8);
Compare both 64-bit halves
return (BOOLEAN)(EntryGuidPart1 == ExpectedGuidPart1 &&

Generated by HR650X BIOS Decompilation Project