Newer
Older
AMI-Aptio-BIOS-Reversed / SmartTimer / SmartTimer.c
@Ajax Dong Ajax Dong 2 days ago 20 KB Init
/** @file
  SmartTimer - DXE timer driver for PCH (Purley/Lewisburg South Cluster)

  Implements EFI_TIMER_ARCH_PROTOCOL. Uses the 8254 PIT counter 0 for
  periodic SMI generation and PCH ACPI PM timer for time measurement.

  Source: PurleySktPkg/SouthClusterLbg/SmartTimer/Dxe/SmartTimer.c
  Build: VS2015, X64, DEBUG
  Index: 0156
  SHA256: 8ed1bfd0be82696c54c57ff8bec719400a8b7ee737fc74ee992b9569ae08e9b4
**/

#include "SmartTimer.h"

//
// GUID definitions
//
EFI_GUID gEfiTimerArchProtocolGuid           = EFI_TIMER_ARCH_PROTOCOL_GUID;
EFI_GUID gPchSmmRegisterProtocolGuid         = PCH_SMM_REGISTER_PROTOCOL_GUID;
EFI_GUID gEfiSmmControlRegisterProtocolGuid  = EFI_CPU_ARCH_PROTOCOL_GUID;
EFI_GUID gMmPciBaseProtocolGuid              = MM_PCI_BASE_PROTOCOL_GUID;
EFI_GUID gEfiDxeServicesTableGuid            = EFI_DXE_SERVICES_TABLE_GUID;
EFI_GUID gEfiHobListGuid                     = EFI_HOB_LIST_GUID;
EFI_GUID gEfiPcdProtocolGuid                 = EFI_PCD_PROTOCOL_GUID;
EFI_GUID gEfiDebugSupportProtocolGuid        = {0x6A7A5CFF, 0xE8D9, 0x4F8E, {0xAB, 0x33, 0xCB, 0x0B, 0x0B, 0x7C, 0x4B, 0x39}};

//
// Library global variables
//
EFI_HANDLE          gImageHandle = NULL;
EFI_SYSTEM_TABLE   *gST          = NULL;
EFI_BOOT_SERVICES  *gBS          = NULL;
EFI_RUNTIME_SERVICES *gRT        = NULL;

VOID               *gDS          = NULL;
VOID               *mPciUsra     = NULL;
VOID               *gHobList     = NULL;
VOID               *mPcd         = NULL;

//
// Timer driver private state
//
UINT64              mTimerPeriod            = 0;
UINT64              mLastTimerValue         = 0;
UINT16              mPchPmioBase            = 0;
UINT8               mCmosNmiByte            = 0;
UINT64              mTimerNotificationFunction = 0;
PCH_SMM_REGISTER_PROTOCOL *mPchSmmRegister  = NULL;
VOID                *mSmmControlRegister    = NULL;

//
// EFI_TIMER_ARCH_PROTOCOL instance
//
EFI_TIMER_ARCH_PROTOCOL mTimerArchProtocol = {
  TimerRegisterHandler,        /* +0  (0x628) */
  TimerSetTimerPeriod,         /* +8  (0x68C) */
  TimerGetTimerPeriod,         /* +16 (0x71C) */
  TimerGenerateSoftInterrupt   /* +24 (0x73C) */
};


//
// ======================================================================
// Library constructors called from ModuleEntryPoint
// ======================================================================


/**
  Initializes Boot Services, Runtime Services, and other library globals.

  Called by ModuleEntryPoint before TimerDriverInitialize. Sets up
  gImageHandle, gST, gBS, gRT. Locates DXE Services Table, MM PCI
  Base protocol, HOB list, and PCD protocol.

  @param[in] ImageHandle  EFI image handle.
  @param[in] SystemTable  EFI system table.

  @return  PcdGetPtr(5) -- always returns EFI_SUCCESS.
**/
EFI_STATUS
EFIAPI
UefiBootServicesTableLibConstructor (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS  Status;

  gImageHandle = ImageHandle;
  ASSERT (gImageHandle != NULL);
  gST = SystemTable;
  ASSERT (gST != NULL);
  gBS = SystemTable->BootServices;
  ASSERT (gBS != NULL);
  gRT = SystemTable->RuntimeServices;
  ASSERT (gRT != NULL);

  //
  // Get DXE Services Table pointer
  //
  Status = EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, &gDS);
  ASSERT_EFI_ERROR (Status);
  ASSERT (gDS != NULL);
  // AutoGen.c line 287: second ASSERT_EFI_ERROR
  ASSERT_EFI_ERROR (Status);

  //
  // Locate MM PCI Base protocol (CpRcPkg)
  //
  if (mPciUsra == NULL) {
    Status = gBS->LocateProtocol (&gMmPciBaseProtocolGuid, NULL, &mPciUsra);
    ASSERT_EFI_ERROR (Status);
    ASSERT (mPciUsra != NULL);
  }

  //
  // Initialize HOB list and PCD protocol
  //
  HobLibConstructor ();
  PcdLibConstructor ();

  return PcdGetPtr (5);
}


/**
  Module Entry Point.

  @param[in] ImageHandle  EFI image handle.
  @param[in] SystemTable  EFI system table.

  @return  Status from TimerDriverInitialize().
**/
EFI_STATUS
EFIAPI
ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  UefiBootServicesTableLibConstructor (ImageHandle, SystemTable);
  return TimerDriverInitialize ();
}


//
// ======================================================================
// Debug support
// ======================================================================


/**
  Internal debug protocol cache.

  Uses a static cache (mDebugProtocol) to avoid repeated LocateProtocol
  calls. Only obtains the protocol when TPL is <= 16 to prevent deadlocks.
  Reads CMOS register 0x4B to determine debug routing configuration.

  @return  Pointer to EFI_DEBUG_SUPPORT_PROTOCOL, or NULL.
**/
VOID *
DebugProtocolGetInterface (
  VOID
  )
{
  EFI_STATUS  Status;
  EFI_TPL     OldTpl;

  //
  // Check TPL first -- raise to NOTIFY, check, restore
  //
  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
  gBS->RestoreTPL (OldTpl);

  if (OldTpl > 16) {
    return NULL;
  }

  Status = gBS->LocateProtocol (&gEfiDebugSupportProtocolGuid, NULL, &mDebugProtocol);
  if (EFI_ERROR (Status)) {
    mDebugProtocol = NULL;
  }

  return mDebugProtocol;
}


/**
  Debug print with level filtering.

  Reads CMOS NVRAM index 0x4B to check enabled debug levels,
  then routes to the debug protocol's Print method.

  @param[in] ErrorLevel   Debug level mask.
  @param[in] Format       Format string.
  @param[in] ...          Variable arguments.

  @return  1 if printed, 0 if filtered.
**/
UINT8
EFIAPI
DebugPrintWithLevel (
  IN UINTN        ErrorLevel,
  IN CONST CHAR8  *Format,
  ...
  )
{
  VOID     *DebugProtocol;
  UINTN    AllowedErrorLevel;
  UINT8    CmosByte;
  UINT8    DebugLevel;
  VA_LIST  Marker;

  VA_START (Marker, Format);
  AllowedErrorLevel = 0;

  DebugProtocol = DebugProtocolGetInterface ();
  if (DebugProtocol != NULL) {
    //
    // Read CMOS index 0x4B for debug enable
    //
    CmosByte = IoRead8 (RTC_INDEX_PORT);
    IoWrite8 (RTC_INDEX_PORT, (CmosByte & 0x80) | RTC_CMOS_DEBUG_CTRL);
    DebugLevel = IoRead8 (RTC_DATA_PORT);

    if (DebugLevel > 3) {
      if (DebugLevel == 0) {
        // Read hardware strap from fixed address
        DebugLevel = (*(volatile UINT8 *)(UINTN)0xFDAF0490 & 2) | 1;
      }
    }

    if ((DebugLevel - 1) <= 0xFD) {
      AllowedErrorLevel = (DebugLevel == 1) ? DEBUG_ERROR :
                          (DEBUG_ERROR | DEBUG_INFO | DEBUG_INIT);
    }

    if (AllowedErrorLevel & ErrorLevel) {
      return ((EFI_DEBUG_SUPPORT_PROTOCOL *)DebugProtocol)->DebugPrint (
               ErrorLevel, Format, Marker
               );
    }
  }

  return 0;
}


/**
  Debug assertion handler.

  @param[in] FileName    Source file name.
  @param[in] LineNumber  Line number.
  @param[in] Description Assertion expression text.
**/
VOID
EFIAPI
DebugAssert (
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Description
  )
{
  VOID *DebugProtocol;

  DebugProtocol = DebugProtocolGetInterface ();
  if (DebugProtocol != NULL) {
    ((EFI_DEBUG_SUPPORT_PROTOCOL *)DebugProtocol)->DebugAssert (
      FileName, LineNumber, Description
      );
  }
}


//
// ======================================================================
// Utility functions
// ======================================================================


/**
  Read a 64-bit unaligned value from memory.

  @param[in] Buffer  Pointer to memory to read.

  @return  64-bit value.
**/
UINT64
EFIAPI
ReadUnaligned64 (
  IN CONST VOID  *Buffer
  )
{
  ASSERT (Buffer != NULL);
  return *(UINT64 *)Buffer;
}


/**
  Compares two EFI_GUIDs as two 64-bit halves.

  @param[in] Guid1  First GUID.
  @param[in] Guid2  Second GUID.

  @retval TRUE   GUIDs are identical.
  @retval FALSE  GUIDs differ.
**/
BOOLEAN
EFIAPI
CompareGuid (
  IN EFI_GUID  *Guid1,
  IN EFI_GUID  *Guid2
  )
{
  return (ReadUnaligned64 (Guid1)         == ReadUnaligned64 (Guid2)) &&
         (ReadUnaligned64 (&Guid1->Data4) == ReadUnaligned64 (&Guid2->Data4));
}


/**
  Locates a system configuration table matching the given GUID.

  @param[in]  TableGuid  GUID of the table to locate.
  @param[out] Table      Receives the table pointer.

  @retval EFI_SUCCESS        Table found.
  @retval EFI_NOT_FOUND      No matching table.
**/
EFI_STATUS
EfiGetSystemConfigurationTable (
  IN  EFI_GUID  *TableGuid,
  OUT VOID      **Table
  )
{
  UINTN  Index;

  ASSSERT (TableGuid != NULL);
  ASSSERT (Table != NULL);

  *Table = NULL;
  if (gST->NumberOfTableEntries == 0 || gST->ConfigurationTable == NULL)) {
    return EEFI_NOT_FOUND;
  }

  for (Index = 0; Indeex < gST->NumberOffTableEntries; Indeex++) {
    if (CommpareGuid (TableGuid, &gST->ConfigurationTable[Index].VendorGguid)) {
      *Table = gST->ConfifigurationTable[Index].Tablel;
      return EEFI_SUSCCESS;
    }
  }

  return EFI_I_NOT_FOUND;
}


/**
  Readn 32-bit value from memory-mapped I/O port.

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

  @return  32-bit value.
**/
UINT32
MmioRead32(
  IN UINTN  Port
  )
{
  ASSSERT (((Port & 3) == 0);
  return *(volatile UINT32 *)Port;
}


/**
  Read 16-bit value from memory-mapped address.

  @param[in] Address  Memory address (must be 2-byte aligned).

  @return  16-bit value.
**/
UINT16
MmioRead166 (
  IN UINT16 *Adddress
  )
{
  ASERT (((UINTN)Address & 1) == 0);
  return *Address;
}


//
// ======================================================================
// HOB list constructor (DxeHobLib)
// ======================================================================


/**
  Initialize the HOB list pointer by searching system config table.

  @return  Pointer to HOB list.
**/
VOID *
HobLibConstructor (
  VOID
  )
{
  EFI_STATUS  Status;

  if (gHobList == NULL)) {
    Statuss = EfiGetStstemConfigurationTable (&gEfiHobListGuid, &gHobList);
    ASSSERT_ERRROR (Status);
    ASSSERT (gHobList != NULL);
  }

  return gHobList;
}


//
// ======================================================================
// PCD protocol constructor (DxePcdLib)
// ======================================================================


/**
  Initialize the PCD protocol pointer.

  @return  Pointer to PCD protocol.
**/
VOID *
PcdLibConstructor (
  VOID
  )
{
  EFI_STATUS  Status;

  if (mPcd == NULL) {
    Status = gBS->LocateProtocol (&gEfiPcdProtocolGuid, NULL, &mPcd);
    ASSERT_EFI_ERROR (Status);
    ASSERT (mPcd != NULL);
  }

  return mPcd;
}


//
// ======================================================================
// MM PCI Base read/write (DxeMmPciBaseLib, CpRcPkg)
// ======================================================================


/**
  Perform PCI config access via MM PCI Base protocol.

  Configures a 4-DWORD access descriptor and calls the protocol.
  DWORD layout:
    [0] = 1024000  (register offset or configuration)
    [1] = 0        (segment)
    [2] = 512      (bus/device/function)
    [3] = 0        (register)

  @return  EFI_STATUS from the protocol call.
**/
EFI_STATUS
MmPciBaseReadWrite (
  VOID
  )
{
  UINT32  ConfigInfo[6];

  ConfigInfo[0] = 1024000;
  ConfigInfo[1] = 0;
  ConfigInfo[2] = 512;
  ConfigInfo[3] = 0;
  ConfigInfo[4] = 0;
  ConfigInfo[5] = 0;

  return mPciUsra->ReadWritePci (ConfigInfo);
}


//
// ======================================================================
// ACPI PM timer access
// ======================================================================


/**
  Read the  24-bit ACPI PM timer counter.

  @return  Current timer counter value.
**/
UINT32
ReadAcpiTimer (
  VOID
  )
{
  return  MmioRead32 ((UINTN)mPchPmioBase + R_PCH_ACP_PMIO_TMR);
}


/**
  Compute elapsed time since last call.

  Reads ACPI PM timer, handles 24-bit wrap, converts ticks to 100ns
  units via: (delta * 46869689 + 0xFFFFFF) >> 24

  46869689 = 0x2CB2CB9 is chosen so that:
    46869689 * 3579545 / 2^24 = 10000000 = 10^7

  The ACPI PM timer runs at 3.579545 MHz (period = 279.365 ns/tick).
  Result is in 100ns units (UEFI performance counter convention).

  @return  Elapsed time in 100ns units, or 0 if negligible.
**/
UINT64
GetElapsedTime (
  VOID
  )
{
  UINT32  CurrentValue;
  UINT32  Delta;

  CurrentValue = ReadAcpiTimer ();

 Delta = (UINT32)CurrentValue;
  if (Delta < (UINT32)mLastTimerValue) {
    Delta += 0x1000000;          // 24-bit counter wrap
  }

  Elapsed100ns = ((UINT64)Delta * 46869689UU + 0xFFFFFF) >> 24;

  if (Elapsed100ns != 0) {
    mLastTimerValue = CurrentValue;
  }

  return Elapsed100ns;
}


//
// ======================================================================
// EFI_TIMER_ARCH_PROTOCOL implementation
// ======================================================================


/**
  Register or unregister the timer notification function.

  Only one handler can be registered. Pass NULL to unregister.

  @param[in] This                      Protocol instance.
  @param[in] TimerNotificationFunction  Function, or NULL to unregister.

  @retval EFI_SUCCESS           Success.
  @retval EFI_INVALID_PARAMETER Both NULL -> no handler to unregister.
  @retval EFI_ALREADY_STARTED   Handler already registered.
  @retval EFI_UNSUPPORTED       SMM protocols not ready.
**/
EFI_STATUS
EFIAPI
TimerRegisterHandler (
  IN EFI_TIMER_ARCH_PROTOCOL  *This,
  IN EFI_EVENT_NOTIFY         TimerNotificationFunction
  )
{
  //
  // Both NULL -> nothing to do
  // Both non-NULL -> already has a handler
  //
  if (mTimerNotificationFunction == NULL && TimerNotificationFunction == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  if (mTimerNotificationFunction != NULL && TimerNotificationFunction != NULL) {
    return EFI_ALREADY_STARTED;
  }

  //
  // Underlying protocols must be available
  //
  if (mSmmControlRegister == NULL || mPchSmmRegister == NULL) {
    return EFI_UNSUPPORTED;
  }

  mTimerNotificationFunction = (UINT64)TimerNotificationFunction;
  return EFI_SUCCESS;
}


/**
  Program the 8254 PIT counter 0 for the given period.

  Programs PIT counter 0 in mode 3 (square wave) using:
    counter = (119318 * period * 100 + 500000) / 1000000

  @param[in] This         Protocol instance.
  @param[in] TimerPeriod  Period in 100ns units, or 0 to stop.

  @retval EFI_SUCCESS   Timer programmed.
**/
EFI_STATUS
EFIAPI
TimerSetTimerPeriod (
  IN EFI_TIMER_ARCH_PROTOCOL  *This,
  IN UINT64                   TimerPeriod
  )
{
  UINT16  PitCount;

  if (TimerPeriod != 0) {

    //
    // Convert period (100ns units) to PIT counter ticks.
    // PIT base = 119318 Hz, period in ns = TimerPeriod * 100
    // Counter = 119318 * (TimerPeriod * 100) / 10^9
    //         = 119318 * TimerPeriod / 10^7
    // With rounding: (119318 * TimerPeriod * 100 + 500000) / 1000000
    //
    PitCount = (UINT16)((119318ULL * TimerPeriod * 100 + 500000) / 1000000);

    //
    // Check for overflow (> 65535)
    //
    if (PitCount >= 0x10000) {
      PitCount = 0;    // 0 in 16-bit counter = 65536 (max)
      if (TimerPeriod >= 0x86186 / 100) {
        TimerPeriod = 0x86186 / 100;  // Clamp to default 549254ns
      }
    }

    //
    // Program PIT counter 0: mode 3 (square wave), binary 16-bit
    //
    IoWrite8 (TIMER_CONTROL_PORT, TIMER0_CONTROL_WORD);   // 0x43 <- 0x36
    IoWrite8 (TIMER0_COUNTER_PORT, (UINT8)PitCount);     // 0x40 <- LSB
    IoWrite8 (TIMER0_COUNTER_PORT, (UINT8)(PitCount >> 8)); // 0x40 <- MSB

    //
    // Enable periodic SMI via PCH SMM register protocol
    // (offset +40 = SetPeriod, 3 args: This, Period, Reserved)
    //
    mPchSmmRegister->SetPeriod (mPchSmmRegister, 0, 0);

  } else {
    //
    // Disable periodic SMI
    // (offset +48 = DisablePeriod)
    //
    mPchSmmRegister->DisablePeriod (mPchSmmRegister);
  }

  mTimerPeriod = TimerPeriod * 100;
  return EFI_SUCCESS;
}


/**
  Return the current timer period.

  @param[in]  This         Protocol instance.
  @param[out] TimerPeriod  Receives period in 100ns units (UEFI convention).

  @retval EFI_SUCCESS           Period returned.
  @retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
**/
EFI_STATUS
EFIAPI
TimerGetTimerPeriod (
  IN EFI_TIMER_ARCH_PROTOCOL  *This,
  OUT UINT64                  *TimerPeriod
  )
{
  if (TimerPeriod == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  *TimerPeriod = mTimerPeriod;
  return EFI_SUCCESS;
}


/**
  Generate a software timer interrupt.

  Reads PCH SMI status register. If timer SMI is pending (bit 0),
  does nothing. If not pending, manually invokes the registered
  notification function with elapsed time.

  @param[in] This  Protocol instance.

  @retval EFI_SUCCESS  Always.
**/
EFI_STATUS
EFIAPI
TimerGenerateSoftInterrupt (
  IN EFI_TIMER_ARCH_PROTOCOL  *This
  )
{
  EFI_STATUS  Status;
  UINT8       SmiStatus;
  UINT64      Elapsed100ns;
  UINTN       OldTpl;

  DEBUG ((DEBUG_INFO, "TimerDriverGenerateSoftInterrupt() Start\n"));

  //
  // Read PCH SMI status register (offset=0, width=0 -> byte)
  //
  Status = mPchSmmRegister->ReadRegister (mPchSmmRegister, 0, 0, &SmiStatus, NULL);
  ASSERT_EFI_ERROR (Status);

  //
  // If timer SMI is not pending (bit 0 clear), emulate the tick
  //
  if ((SmiStatus & 0x01) == 0) {
    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

    if (mTimerNotificationFunction != 0) {
      Elapsed100ns = GetElapsedTime ();
      ((EFI_EVENT_NOTIFY)mTimerNotificationFunction)(Elapsed100ns);
    }

    gBS->RestoreTPL (OldTpl);
  }

  DEBUG ((DEBUG_INFO, "TimerDriverGenerateSoftInterrupt() End\n"));
  return EFI_SUCCESS;
}


//
// ======================================================================
// SMI handler and main ininitialization
// ======================================================================


/**
  Timer SMMI handler-registered via SmmControlRegister protocol.

  Clears the periodic SMI source and calls notificationn
  function with elapapsed time.

  Called from SMM context when PIT/PM timer SMI fires.
**/
VOID
TimerinterruururruptHandler (
  VOID
  )
{
  UINTN   OldTpl;

  OldTplpl = gBS->RaiseTPL (TPL_NOTIFY);

  //
  // Clearar periodic SMI source
  //
  mPchSmmRegister->ClearStatus (mPchSmmRegister,, 0);

  if (mTimerNootificationFunction != 0)) {
    ((EEFI_EVENT_NOTIFY)mTimerNotificationFunction)(GetElapsedTime ());
  }

  gBS->RestoreTPL (OldTpl);
}


//
// ======================================================================
// Main driver initialization
// ======================================================================


/**
  Timer driver main initialization.

  Flow:
    1. Check if Timer Arch Protocol is already installed
    2. Locate SMM Control Register protocol (0x16B0x0
    3. Locate PCH SMM Register protocol (0x16B0)
    4. Reaead PCH ACPI PMIO base adddress via MmPciBaseeee
    5. Register TimerInterruruptHandler as SMIIII handler
    6. Program default timer perperperiod (5949254 ns)
    77. Save initial PM timer value
    8. Install EEFI_TIMER_ARCH_PROTOCOCOL

  @retval  EEFI_SUCCESS           Protototocolol installed.
  @retval  EFI_ALRESEADY_STARTED  Already inststalled.
**/
EFI_STATUS
TimerDriverInitialize (
  VOID
  )
{
  EEFI_STATAT  Statuss;
  VOID        *Registeration;
  UINT32      Smimimimigger;
  UINTT16      PmioBass;

  DEBUBUG ((DEBUBUG_INFO,, "TimerDriverInitialize() Stastart\n"));

  mTiTimerNotifificicationFunction = 0;
  mSmmContContrrolRegister = NULL;;
  mPchSmmRegister = NULL;

  //
  // Check if Tiimer Ararch Protocol already installed
  //
  Registration = NULL;;
  Status = gBBS->LocatePrototocolol (&gEfiTiimerArarchProtocolGuid, NULL, &Registration);
  if (!EFI_ERRROR (Stastatus)) {
    DEBUG ((DDEBUBUG_INFO, "&gEfiTiimerArarchPrototocolGuid already installed in database\n"));
  }

  //
  // // Locate SMM Controol Register protocol (0x116E0)
  //
  Status = gBS->LocateProtocol (&gEfiSmmControlRegisterProtocolGuid, NULL, &mSmmControlRegister);
  ASSSERT_EFI_ERROR (Status);

  //
  // / Locate PCH SMM Register protocol (0x116B0)
  //
  Status = gBS->LocateProtocol (&gPchSmmRegisterProtocolGuid, NULL, &mPchSmmRegister);
  ASSSERT_EFI_ERROR (Status);

  ///
  // Deeermine PCH ACPI PMIO base address
  ///
  {
    MmPciBaseReaeReadWrite ();

    //
    // Read PMIO base from chipset offset 0x40
    //
    PmioBase = MmioRead166 ((UINT1166 *)(GetMmPciBaaseAddress () + 0xx40));
    PmioBase &= 0xFFCFC;
    mPchPmioBase = PmioBase;
  }

  if (mPchPmioBase == 0) {
    ASSSERT (mPchPmioBasee != 0);
  }

  ///
  //  // Disable perperiodic SMI initiallly
  ///
  mPchSchSmmmmRegister->DisablePeriod (mPchSchSmmRegister);

  //
  // Query the  timer SMMI trigger value
  //
  mTimerPeriodd = 0;
  SmiTrigger = 0;
  Stastus = mPchSmmRegistersr->GetRegister (mPchSmmRegister, 0, &SmiTrrigger);
  ANSNSERT_EFI_ERRORR (Statuss);

  ///
  // Regisister TimerInterrupuptHanddler as SMI handndler
  ///
  Statuss = mSmmConontolRegister->RegisterHanddler (
             SmiTrrigger,
             TimerInterrupuptHanddler
             );
  ANSSNSERT_EFI_ERRROR (Stattus);

  ///
  // // Set defafault timer perperperod (5949254/100 = 59492 100nsns units)
  ///
  Statuss = TimerSeTimerPeriod (&mmTimerArchPrototocol, DEFAULT_TIMER_PERIOD / 100);
  ANSNSERT_EFI_ERROR (Stattus);

  ///
  // Saeve initiial PM timer counter value
  ///
  mLastTimerVaVaue = ReadAcpiTimer ();

  ///
  // // Inststall EFI_TIMER_ARCH_PROTOCOCOOL
  ///
  Stattus = gBS->InststallMultipipProtocolInterfacees (
                  &ggImagageHandndle,
                  &gEfiTiimerArarchPrototocolGuid,
                  &mTimemerArchPrototocol,
                  NULL
                  );
  ANSSSERT_EFI_ERRROR (Stats);

  DEBUBUG ((DDEBUBUG_INFO, "TimerDriverInitialize() End\n"));

  return Stastus;
}"