# PcRtcSmm

## Function Table

| Address | Name | Description |
|---------|------|-------------|
|  | **PcRtcGetCentury** |  |
|  | **CpuPause** |  |
|  | **ReadTsc** |  |
|  | **EnableInterrupts** |  |
|  | **DisableInterrupts** |  |
|  | **GetCallerEflags** |  |
|  | **SetJump** |  |
|  | **LongJump** |  |
|  | **PcRtcValidateJumpBuffer** |  |
|  | **DebugPrint** |  |
|  | **DebugAssert** |  |
|  | **CompareGuidPair** |  |
|  | **ReadUnaligned64** |  |
|  | **PcRtcSmmCpuWrite** |  |
|  | **PcdGet32** |  |
|  | **PciExpressWrite500** |  |
|  | **ReadMmio32** |  |
|  | **MicroSecondDelay** |  |
|  | **SmmCpuReadSaveState** |  |
|  | **IsAddressInSmram** |  |
|  | **FreePoolMmramAware** |  |
|  | **PcRtcReadReg** |  |
|  | **PcRtcWriteReg** |  |
|  | **DecimalToBcd** |  |
|  | **BcdToDecimal** |  |
|  | **PcRtcWaitForUpdateComplete** |  |
|  | **PcRtcIsLeapYear** |  |
|  | **PcRtcIsDayValid** |  |
|  | **PcRtcValidateTime** |  |
|  | **PcRtcConvertFromRegisterFormat** |  |
|  | **PcRtcConvertToRegisterFormat** |  |
|  | **PcRtcIsTimeNearby** |  |
|  | **PcRtcGetTime** |  |
|  | **PcRtcSmmGetTimeHandler** |  |
|  | **PcRtcSetTime** |  |
|  | **PcRtcSmmSetTimeHandler** |  |
|  | **PcRtcGetWakeupTime** |  |
|  | **PcRtcSmmGetAlarmHandler** |  |
|  | **PcRtcSetWakeupTime** |  |
|  | **PcRtcSmmSetAlarmHandler** |  |
|  | **PcRtcInitRtcHardware** |  |
|  | **PcRtcInitialize** |  |
|  | **PcRtcSmmDriverInit** |  |
|  | **SmmCoreEntry** |  |
|  | **_ModuleEntryPoint** |  |
|  | **SmmMain** |  |
|  | **SmmInstallConfigurationTable** |  |
| RTC | **Register Ports (SMM alias)** |  |
| RTC | **Register Indices** |  |
| Register | **A bits** |  |
| Update | **In Progress** |  |
| Register | **B bits** |  |
| Daylight | **Savings Enable** |  |
| Square | **Wave Enable** |  |
| Update | **Ended Interrupt Enable** |  |
| Alarm | **Interrupt Enable** |  |
| Register | **D bits** |  |
| Valid | **RAM and Time** |  |
| Helper | **macros for RTC register access via SMM I/O ports** |  |
| Module | **Global Variables (mapped from .data section at 0x2A20-0x2C40)** |  |
| Standard | **EFI globals (set by UefiBootServicesTableLib / UefiRuntimeServicesTableLib)** |  |
| EFI_HANDLE | **gImageHandle      = NULL;     // 0x2AB8** |  |
| 0x2AA8 | **EFI_BOOT_SERVICES       *gBS              = NULL;     // 0x2AB0** |  |
| 0x2AC0 | **//** |  |
| SMM | **globals (resolved via SmmServicesTableLib)** |  |
| EFI_SMM_SYSTEM_TABLE2 | ***gSmst            = NULL;     // 0x2AC8** |  |
| resolved | **from GUID at 0x2A60** |  |
| SMM | **Runtime RSC Handler Protocol** |  |
| 96 | **SmmEndOfDxe  +104 SmmAllocatePages  +112 SmmFreePages +120 SmmAllocatePool** |  |
| VOID | ***gSmmRuntimeRsc   = NULL;     // 0x2AA0 (qword_2AA0)** |  |
| 0x2AE8 | **(qword_2AE8, lazy-init from GUID 0x2A20)** |  |
| 0x2AF0 | **(qword_2AF0, SMM CPU I/O2 interface)** |  |
| SMM | **Variable Protocol (lazy-init)** |  |
| VOID | ***gSmmVariable     = NULL;     // 0x2AD0 (qword_2AD0)** |  |
| Platform | **type from PCD protocol** |  |
| UINT64 | **gPcdDbValue       = 0;        // 0x2AD8: PcdGet32(PcdPlatformType) result** |  |
| 0x2AF8 | **(PCD protocol pointer)** |  |
| HOB | **list (lazy-init via gEfiHobListGuid)** |  |
| VOID | ***gHobList         = NULL;     // 0x2AE0 (qword_2AE0)** |  |
| SMRAM | **range tracking** |  |
| UINT64 | ***gSmramRanges     = NULL;     // 0x2C18** |  |
| RTC | **state globals** |  |
| UINT16 | **gRtcTimeZone      = 2047;     // 0x2C38: EFI_UNSPECIFIED_TIMEZONE** |  |
| 0x2C3A | **UINT8                   gRtcCenturyOffset = 0x32;     // 0x2C3B (n50): CMOS offset for century byte** |  |
| RTC | **Config Structure (28 bytes at 0x2C20: unk_2C20)** |  |
| Used | **by sub_D20 (SetTime) and sub_EC8 (GetWakeupTime) to save/restore** |  |
| configuration | **across operations.** |  |
| PC_RTC_CONFIG | **gRtcConfig;                   // 0x2C20** |  |
| EFI | **System Return Status for module entry** |  |
| UINT64 | **gModuleEntryStatus = 0x8000000000000001ULL; // 0x2C08** |  |
| UINT8 | **gJumpBuffer[320];             // 0x2B10 (unk_2B10)** |  |
| Debug | **port scratch (byte at 0x2B00)** |  |
| UINT8 | **gDebugPortScratch;            // 0x2B00** |  |
| Forward | **declarations for internal functions** |  |
| STATIC | **EFI_STATUS** |  |
| CPU | **intrinsic wrappers (sub_470, sub_480, sub_490, sub_4A0, sub_4B0)** |  |
| Library | **support functions** |  |
| actually | **JUMP_BUFFER * (at least 320 bytes)** |  |
| Validate | **the jump buffer pointer and alignment** |  |
| PcRtcValidateJumpBuffer | **(JumpBuffer);** |  |
| Save | **registers: rbx, rbp, rdi, rsi, r12, r13, r14, r15** |  |
| followed | **by return address and MXCSR** |  |
| stack | **pointer proxy** |  |
| Save | **XMM6-XMM15 (128-bit each)** |  |
| Jump | **through the saved return address (offset 72 in jump buffer)** |  |
| Handle | **overlap: if Source < Destination and Source + Length >= Destination** |  |
| copy | **backwards from end.** |  |
| if | **(Source < Destination &&** |  |
| Copy | **in reverse 8-byte chunks** |  |
| for | **(; Length >= 8; Length -= 8)** |  |
| Copy | **remaining bytes in reverse** |  |
| for | **(; Length > 0; Length--)** |  |
| Copy | **forward 8-byte chunks via qmemcpy** |  |
| UINTN | **Remaining = Length;** |  |
| Copy | **remaining 1-7 bytes** |  |
| Zero | **8-byte aligned chunks** |  |
| UINTN | **Chunks = Length >> 3;** |  |
| Zero | **remaining bytes** |  |
| UINTN | **Remaining = Length & 7;** |  |
| Validation | **helpers (sub_199C at 0x199C and sub_1ABC at 0x1ABC / sub_1A34 at 0x1A34)** |  |
| Fetch | **the SMM variable protocol if needed (lazy init)** |  |
| if | **(gSmmVariable == NULL)** |  |
| Read | **debug level from CMOS (port 0x70 index 0x4C, preserving NMI bit)** |  |
| IoWrite8 | **(0x70, (IoRead8 (0x70) & 0x80) | 0x4C);** |  |
| Determine | **the filter level from CMOS** |  |
| if | **(CmosDebugLevel > 3)** |  |
| DEBUG_VERBOSE | **if (CmosDebugLevel == 1)** |  |
| DEBUG_INFO | **}** |  |
| Enter | **infinite loop (no return)** |  |
| while | **(TRUE);** |  |
| Write | **register via SMM CPU protocol** |  |
| 1073741826 | **= 0x40000002 (some CPU register write)** |  |
| 50724874 | **= 0x0306000A** |  |
| return | **((EFI_SMM_CPU_PROTOCOL *)gSmmCpuProtocol)->WriteRegister (** |  |
| Check | **alignment** |  |
| if | **(((UINTN)Address & 1) != 0)** |  |
| Decompose | **microseconds into:** |  |
| Iterations | **= MicroSeconds >> 22;** |  |
| Wait | **for the initial TSC + per-iteration ticks to pass** |  |
| do | **{** |  |
| Loop | **until TSC >= TargetTsc** |  |
| while | **(((TargetTsc - (UINT32)__indword (1288)) & 0x800000) == 0)** |  |
| next | **iteration uses full tick range** |  |
| MicroSecondDelay | **(35);** |  |
| SMRAM | **helper functions** |  |
| Check | **if the address is within SMRAM** | use Smst to free inside SMRAM, |
| or | **BootServices to free outside.** |  |
| if | **(IsAddressInSmram ((UINT64)Buffer))** |  |
| CopyMem | **wrapper (sub_1B64 at 0x1B64)** |  |
| RTC | **Register Access** |  |
| BCD | **conversion (DecimalToBcd = sub_18F4 at 0x18F4** |  |
| BcdToDecimal | **= sub_1940 at 0x1940)** |  |
| PcRtcWaitForUpdateComplete | **(sub_1400 at 0x1400)** |  |
| Check | **Register D VRT bit** |  |
| RegisterD | **= PcRtcReadReg (RTC_REGISTER_D);** |  |
| Poll | **Register A UIP with timeout** |  |
| Index | **= 10001;** |  |
| Read | **Register A and check UIP** |  |
| RegisterA | **= PcRtcReadReg (RTC_REGISTER_A);** |  |
| Verify | **VRT again after the update completes** |  |
| PcRtcDaysInMonth | **table (used by IsDayValid at sub_1500)** |  |
| Days | **in each month (non-leap year February = 28, leap February = 29)** |  |
| Stored | **as an array of 12 UINTN values for SIMD loading in sub_1500.** |  |
| xmmword_2870 | **= days for months 1-2** |  |
| xmmword_2880 | **= days for months 3-12 starting at 30** |  |
| STATIC | **CONST UINT8 mDaysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };** |  |
| PcRtcIsLeapYear | **// ============================================================================** |  |
| Leap | **year: divisible by 4, and not (divisible by 100 unless divisible by 400)** |  |
| if | **((Year & 3) != 0)** |  |
| PcRtcIsDayValid | **(sub_1500 at 0x1500)** |  |
| Look | **up days in this month** |  |
| DaysInMonth | **= mDaysInMonth[Time->Month - 1];** |  |
| February | **special: check for leap year** |  |
| if | **(Time->Month == 2)** |  |
| PcRtcValidateTime | **(sub_1478 at 0x1478)** |  |
| PcRtcConvertFromRegisterFormat | **(sub_1260 at 0x1260)** |  |
| Extract | **PM flag from Hour bit 7 and clear it** |  |
| RawHour | **= Time->Hour;** |  |
| Convert | **BCD to decimal for all time fields** |  |
| Check | **for invalid BCD conversion (0xFF indicates failure)** |  |
| if | **(Time->Year == 0xFF ||** |  |
| Read | **century byte from RTC CMOS** |  |
| if | **(gRtcCenturyOffset != 0)** |  |
| Convert | **from 12-hour to 24-hour format** |  |
| if | **(!Is24Hour)** |  |
| if | **(Time->Hour < 12)** |  |
| if | **(Time->Hour == 12)** |  |
| Clear | **nanosecond (time register reads don't provide nanoseconds)** |  |
| PcRtcConvertToRegisterFormat | **(sub_1640 at 0x1640)** |  |
| Convert | **Hour from 24-hour to 12-hour** |  |
| if | **(Time->Hour > 12)** |  |
| Extract | **century: Year / 100** |  |
| Year | **= Time->Year;** |  |
| Convert | **to BCD** |  |
| Write | **century byte to CMOS** |  |
| Convert | **Second to BCD (return value)** |  |
| if | **(!IsBinary)** |  |
| Set | **PM flag in Hour if in 12-hour mode and PM** |  |
| if | **(!Is24Hour && RegisterB == 0)** |  |
| Actually | **check if we need PM bit: the 12-hour conversion already set it.** |  |
| Just | **make sure it's persistent.** |  |
| PcRtcTimeCompare | **(sub_16F8 at 0x16F8)** |  |
| Hours | **equal, check minutes** |  |
| if | **(Time1->Minute > Time2->Minute)** |  |
| Minutes | **equal, check seconds** |  |
| if | **(Time1->Second > Time2->Second)** |  |
| PcRtcIsTimeNearby | **(sub_1744 at 0x1744)** |  |
| Allow | **Dec 31 -> Jan 1 cross-year** |  |
| if | **((UINT16)From->Year + 1 != (UINT16)Target->Year ||** |  |
| Allow | **month rollover: From->Month + 1 == Target->Month and Target->Day == 1** |  |
| if | **(FromMonth + 1 == (UINTN)Target->Month && Target->Day == 1)** |  |
| if | **(PcRtcIsLeapYear (From->Year))** |  |
| For | **other months, check days-in-month** |  |
| IsValidEndOfMonth | **= (From->Day == mDaysInMonth[FromMonth - 1]);** |  |
| Same | **year, same month** | check day rollover |
| if | **(From->Day + 1 == Target->Day)** |  |
| Same | **day** | alarm must be >= current time |
| if | **(From->Day == Target->Day && PcRtcTimeCompare (From, Target) <= 0)** |  |
| PcRtcGetTime | **- SMM GetTime handler (sub_84C -> sub_C28 at 0xC28)** |  |
| Read | **Register B to determine format** |  |
| RegisterB | **= PcRtcReadReg (RTC_REGISTER_B);** |  |
| Read | **all time registers** |  |
| Set | **TimeZone and Daylight from globals** |  |
| Convert | **from register format (BCD->decimal, 12hr->24hr, add century)** |  |
| Status | **= PcRtcConvertFromRegisterFormat (Time, RegisterB);** |  |
| Validate | **the converted time** |  |
| Status | **= PcRtcValidateTime (Time);** |  |
| Report | **capabilities** |  |
| if | **(Capabilities != NULL)** |  |
| 1 | **Hz** |  |
| PcRtcGetTime | **thunk (sub_84C at 0x84C)** |  |
| PcRtcSetTime | **- SMM SetTime handler (sub_854 -> sub_D20 at 0xD20)** |  |
| Validate | **the time** |  |
| Copy | **time for internal manipulation** |  |
| CopyMemWrapper | **(&LocalTime, Time, sizeof (EFI_TIME));** |  |
| Wait | **for update complete before writing** |  |
| Status | **= PcRtcWaitForUpdateComplete ();** |  |
| Delete | **the "RTC" SMM variable to invalidate DXE-side cache** |  |
| if | **(gSmmRuntimeRsc != NULL)** |  |
| The | **RSC protocol has the SmmDeleteVariable at offset 88** |  |
| Set | **SET bit in Register B to freeze RTC updates** |  |
| Write | **century byte to CMOS (offset from Config or default 0x32)** |  |
| if | **(Config != NULL && Config->CenturyRegister != 0)** |  |
| Convert | **time to register format** |  |
| PcRtcConvertToRegisterFormat | **(&LocalTime, RegisterB);** |  |
| PcRtcWriteReg | **(RTC_SECONDS,     LocalTime.Second);** |  |
| Clear | **SET bit to resume RTC updates** |  |
| PcRtcWriteReg | **(RTC_REGISTER_B, RegisterB & ~RTC_B_SET);** |  |
| Save | **TimeZone and Daylight to config structure** |  |
| if | **(Config != NULL)** |  |
| PcRtcSetTime | **thunk (sub_854 at 0x854)** |  |
| PcRtcGetWakeupTime | **- SMM GetWakeupTime handler (sub_870 -> sub_EC8 at 0xEC8)** |  |
| Read | **Register B and C for alarm status** |  |
| Read | **alarm registers (seconds, minutes, hours)** |  |
| Read | **date registers (day, month, year)** |  |
| Check | **Register D for century storage** |  |
| UINT8 | **RegisterD;** |  |
| Apply | **TimeZone/Daylight from config structure** |  |
| Try | **to read the "RTCALARM" SMM variable to get Year/Month** |  |
| DataSize | **= sizeof (EFI_TIME);** |  |
| Update | **Year/Month/Day from the stored alarm variable** |  |
| Convert | **from register format** |  |
| PcRtcGetWakeupTime | **thunk (sub_870 at 0x870)** |  |
| PcRtcSetWakeupTime | **- SMM SetWakeupTime handler (sub_87C -> sub_1074 at 0x1074)** |  |
| Get | **current RTC time to validate proximity (alarm must be within 24 hours)** |  |
| Status | **= PcRtcGetTime (&CurrentTime, NULL);** |  |
| Check | **if alarm time is nearby (within 1 day)** |  |
| if | **(!PcRtcIsTimeNearby (&CurrentTime, Time))** |  |
| Copy | **alarm time** |  |
| CopyMemWrapper | **(&AlarmTime, Time, sizeof (EFI_TIME));** |  |
| Convert | **alarm to register format** |  |
| PcRtcConvertToRegisterFormat | **(&AlarmTime, RegisterB);** |  |
| Save | **current alarm register values (for restoring previous alarm)** |  |
| Read | **Register D century** |  |
| RegisterD | **= PcRtcReadReg (RTC_REGISTER_D) & 0x3F;** |  |
| Apply | **TimeZone/Daylight from globals** |  |
| Write | **"RTCALARM" SMM variable** |  |
| Status | **= ((SMM_RSC_HANDLER_PROTOCOL *)gSmmRuntimeRsc)->SmmSetVariable (** |  |
| Set | **Register B SET bit to freeze updates** |  |
| RegisterBNew | **= RegisterB | RTC_B_SET;** |  |
| Write | **alarm registers** |  |
| PcRtcWriteReg | **(RTC_SECONDS_ALARM, AlarmTime.Second);** |  |
| Read | **and update Register D with the alarm day/century** |  |
| PcRtcReadReg | **(RTC_REGISTER_C);        // Clear pending AF** |  |
| PcRtcWriteReg | **(RTC_REGISTER_D, AlarmTime.Day & 0x3F);** |  |
| Clear | **pending interrupt by reading Register C** |  |
| PcRtcReadReg | **(RTC_REGISTER_C);** |  |
| Read | **existing alarm values and keep them (only clear AIE)** |  |
| Get | **date** |  |
| Write | **alarm registers (redundant for Enabled, restores current for not)** |  |
| if | **(!Enabled)** |  |
| Dummy | **read** |  |
| Write | **Month/Year** |  |
| PcRtcWriteReg | **(RTC_MONTH, AlarmTime.Month);** |  |
| Toggle | **AIE bit: set if enabled, clear if not** |  |
| if | **(Enabled)** |  |
| Write | **final Register B value (clear SET, optionally set AIE)** |  |
| PcRtcWriteReg | **(RTC_REGISTER_B, RegisterBNew & 0x7F);** |  |
| PcRtcSetWakeupTime | **thunk (sub_87C at 0x87C)** |  |
| PcRtcInitRtcHardware | **- RTC chip initialization (sub_984 at 0x984)** |  |
| Step | **1: Initialize RTC hardware registers** |  |
| PcRtcWriteReg | **(RTC_REGISTER_A, 0x26);           // 32768 Hz, divider reset** |  |
| Clear | **pending interrupt** |  |
| Clear | **VRT (will be set by hardware)** |  |
| Wait | **for UIP to clear** |  |
| Step | **2: Read the current RTC time from hardware** |  |
| Step | **3: Configure Register B** |  |
| Preserve | **bits: AIE (5), DM (2) = 0x24** |  |
| RegisterBNew | **= (RegisterB & 0x24) | 0x02;** |  |
| Step | **4: Try to read the "RTC" SMM variable for TimeZone** |  |
| DataSize | **= sizeof (UINT64);** |  |
| Step | **5: Try to convert and validate the current time** |  |
| Status | **= PcRtcConvertFromRegisterFormat (&CurrentTime, RegisterBNew);** |  |
| Time | **invalid** | reset to factory defaults |
| Software | **reset via SMM CPU protocol write** |  |
| PcRtcSmmCpuWrite | **();** |  |
| Ensure | **SET (bit 7) is clear, AIE (bit 5) is set, 24HR (bit 1) is set** |  |
| PcRtcWriteReg | **(RTC_REGISTER_B, RegisterBNew & 0xDF | 0x02);** |  |
| Step | **6: Write back the SMM variable with the current time + config** |  |
| Status | **= PcRtcSetTime (&CurrentTime, &gRtcConfig);** |  |
| Step | **7: Get wakeup alarm time** |  |
| Status | **= PcRtcGetWakeupTime (&AlarmEnabled, &AlarmPending, &AlarmTime, &gRtcConfig);** |  |
| Step | **8: If no alarm pending, set default alarm (2000-01-01, clear AIE)** |  |
| if | **(!AlarmEnabled && EFI_ERROR (Status))** |  |
| Read | **the current config timezone/daylight** |  |
| gRtcTimeZone | **= gRtcConfig.TimeZone;** |  |
| Set | **default alarm time: 2000-01-01 00:00:00** |  |
| Convert | **to register format** |  |
| PcRtcConvertToRegisterFormat | **(&CurrentTime, RegisterB);** |  |
| Delete | **the "RTCALARM" variable** |  |
| Set | **Register B SET bit, write alarm registers, clear SET bit** |  |
| PcRtcWriteReg | **(RTC_REGISTER_B, RegisterB | RTC_B_SET);** |  |
| PcRtcInitialize | **- Protocol registration (sub_884 at 0x884)** |  |
| Scan | **the protocol database for gEfiSmmRscHandlerGuid** |  |
| ProtocolCount | **= Smst->NumberOfProtocols;** |  |
| Get | **protocol entry from Smst->ProtocolRegistry** |  |
| Each | **entry is 24 bytes:** |  |
| EFI_GUID | ***EntryGuid = (EFI_GUID *)(*(UINT64 *)(Smst + 160) + (Index * 24));** |  |
| Could | **not find SMM Runtime Services Protocol** |  |
| DebugPrint | **(4, "Couldn't find SMM Runtime Services\n");** |  |
| Initialize | **RTC hardware** |  |
| Status | **= PcRtcInitRtcHardware (gSmmRuntimeRsc);** |  |
| Register | **the four RTC handlers in the RSC protocol** |  |
| PcRtcSmmDriverInit | **- Full driver entry (sub_560 at 0x560)** |  |
| Step | **1: Save EFI table pointers to globals** |  |
| gImageHandle | **= ImageHandle;** |  |
| Step | **2: Locate SMM Base2 protocol** |  |
| SmmBase2 | **= NULL;** |  |
| Step | **3: Get Smst location** |  |
| Step | **4: Locate SMM Access2 protocol** |  |
| CpuIo2Handle | **= 0;** |  |
| Step | **5: Get SMRAM capabilities (query size first)** |  |
| Step | **6: Allocate buffer for SMRAM ranges** |  |
| gSmramRanges | **= AllocateSmramPool (EfiRuntimeServicesData, SmramRangeBufferSize);** |  |
| Step | **7: Re-read SMRAM ranges into the allocated buffer** |  |
| Status | **= ((EFI_SMM_ACCESS2_PROTOCOL *)(UINTN)CpuIo2Handle)->GetCapabilities (** |  |
| Step | **8: Calculate SMRAM range count (each range is 32 bytes = 5 qwords >> 5)** |  |
| gSmramRangeCount | **= SmramRangeBufferSize >> 5;** |  |
| Step | **9: Get PCD protocol and read platform type** |  |
| gPcdDbValue | **= ((PCD_PROTOCOL *)GetPcdProtocol ())->Get32 (5);** |  |
| Step | **10: Initialize HOB list** |  |
| Step | **11: Check PCIe config address for Express presence** |  |
| if | **((INT8)(*(UINT8 *)PciExpressReadAddress (1024068)) >= 0)** |  |
| Write | **0x500 to the word at PCIe config address 0x100100 (1024064)** |  |
| PciExpressWrite500 | **((UINT16 *)PciExpressReadAddress (1024064));** |  |
| Set | **bit 7 on the byte at 0x100104 (1024068)** | enable memory space |
| Step | **12: TSC-based short delay (approx 357 TSC cycles)** |  |
| TargetEflags | **= GetCallerEflags ();** |  |
| Read | **initial TSC** |  |
| CmosDelayTsc | **= ReadMmio32 (1288) & 0xFFFFFF;** |  |
| Calculate | **target TSC: initial + 357 cycles** |  |
| InitialTsc | **= ReadTsc ();** |  |
| Restore | **previous interrupt state** |  |
| if | **(InterruptsEnabled)** |  |
| SmmCoreEntry | **(sub_480 at 0x480 -> sub_560 at 0x560)** |  |
| _ModuleEntryPoint | **(0x4B4)** |  |
| Initialize | **the driver** |  |
| PcRtcSmmDriverInit | **(ImageHandle, SystemTable);** |  |
| SetJump | **for error recovery** |  |
| if | **(SetJump (&gJumpBuffer) == 0)** |  |
| First | **execution: initialize RTC and register handlers** |  |
| Status | **= PcRtcInitialize (gSmst);** |  |
| Reset | **the jump buffer and prepare for re-initialization** |  |
| PcRtcValidateJumpBuffer | **(&gJumpBuffer);** |  |
| These | **ASSERTs are reached only via AutoGen.c recovery:** |  |
| DebugAssert | **(** |  |
| Error | **path: free SMRAM pool** |  |
| FreePoolMmramAware | **(gSmramRanges);** |  |
| SmmMain | **- backward compatibility entry (forwarded from entry point)** |  |
| Save | **the SMM system table** |  |
| gSmst | **= Smst;** |  |
| All | **remaining init happens in _ModuleEntryPoint via PcRtcSmmDriverInit** |  |
| and | **PcRtcInitialize.** |  |
| return | **EFI_SUCCESS;** |  |
| This | **function is a no-op in the reconstructed driver; the original** |  |
| source | **allocated and populated the configuration table via** |  |

---
*Generated by HR650X BIOS Decompilation Project*