From b7c51c9cf4864df6aabb99a1ae843becd577237c Mon Sep 17 00:00:00 2001 From: raywu Date: Fri, 15 Jun 2018 00:00:50 +0800 Subject: init. 1AQQW051 --- Core/EM/CmosManager/CmosManager.c | 1193 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1193 insertions(+) create mode 100644 Core/EM/CmosManager/CmosManager.c (limited to 'Core/EM/CmosManager/CmosManager.c') diff --git a/Core/EM/CmosManager/CmosManager.c b/Core/EM/CmosManager/CmosManager.c new file mode 100644 index 0000000..6513e67 --- /dev/null +++ b/Core/EM/CmosManager/CmosManager.c @@ -0,0 +1,1193 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/CMOS Manager/CMOS Core/CMOS Source/CmosManager.c 22 6/15/10 2:24p Michaela $ +// +// $Revision: 22 $ +// +// $Date: 6/15/10 2:24p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/CMOS Manager/CMOS Core/CMOS Source/CmosManager.c $ +// +// 22 6/15/10 2:24p Michaela +// +// 21 3/08/10 5:40p Michaela +// +// 20 3/05/10 4:55p Michaela +// +// 19 12/04/09 7:32p Michaela +// +// 18 12/03/09 6:31p Michaela +// 1. Moved gIsBsp here and added gIsColdBoot definition +// +// 2. Updated CmosConfigureManager() to force calculation of +// checksum after enabling the Optimal Defaults buffer. +// +// 3. Updated NewCmosManagerInterface() to update first boot, +// BSP detected and incoherency policy settings bits prior to +// calculating the checksum and getting the battery status. +// +// 17 11/10/09 9:14p Michaela +// +// 16 7/29/09 9:59a Michaela +// updates Aptio Enhancement EIP 22205 +// (no code changes) +// +// 15 6/15/09 5:11p Michaela +// +// 14 6/02/09 3:27p Michaela +// For label: 4.6.3_CMOSMGR_11 +// +// 13 3/11/09 3:38p Michaela +// +// 12 2/16/09 10:26p Michaela +// Rename CmosManagerAsm to gCmosManagerAsm +// +// 11 2/06/09 2:02p Michaela +// removed hard-coded FIRST_CMOS_REGISTER value +// +// 10 11/25/08 3:20p Michaela +// Updates for Label 4.6.3_CMOSMGR_08 +// - Assembly macro fixes +// - Added assembly macros +// - Moved loading defaults into DXE phase +// - Updated help file example +// +// 9 11/17/08 4:41p Michaela +// --Removed Token Name strings in debug development code +// +// 8 11/17/08 3:33p Michaela +// -added CMOS_ACCESS_TYPE typedef for client code usage +// -CMOS Buffer feature is depreciated +// -Removed debug code +// -SaveApiPointerToCmos & GetApiPointerFromCmos are now +// directly calling CmosPhysicalReadWrite to avoid error if using +// Optimal Defaults buffer for Reads/Writes +// -ABORT_ERROR_STATUS replaced with EFI_ERROR macro +// usage +// +// 7 11/14/08 9:07a Michaela +// CMOS register variables changed from UINT8 to UINT16 +// +// 6 11/07/08 5:13p Michaela +// Updated to make CMOS manager available in all phases +// of the boot process: +// +// A CMOS API Pointer is maintained in CMOS and accessible +// via provided macros in C and assembly source. +// +// 5 3/25/08 3:00p Michaela +// Modified call to SynchronizeLegacyStatusRegisters +// +// 4 3/07/08 4:07p Michaela +// Label 4.6.3_CMOSMGR_05 fixes: +// -- write errors to Optimal Defaults buffer before memory detection +// -- CMOS Token table corruption when name strings are disabled +// +// 3 2/29/08 9:35p Michaela +// - Added recovery path policy +// - fixed other minor bugs +// +// 2 2/26/08 12:48p Michaela +// Added/modified Helpbuilder headers +// +// 1 2/22/08 2:29p Michaela +// +// 1 2/04/08 6:00p MichaelA +// Created +// +//********************************************************************** + +// +//--------------------------------------------------------------------------- +// +// Name: CmosManager.c +// +// Description: Contains the routines that constitute the CMOS manager +// implementation. This files is used to create object code +// for both PEI and DXE phases, based upon the build +// macro PEI_COMPILE. +// +//--------------------------------------------------------------------------- +// + +#include +#ifdef PEI_COMPILE + #include + #include +#else + #include +#endif +#ifdef SMM_COMPILE + #include +#endif +#include +#include "CmosManager.h" +#include "CmosManagerHob.h" +#include "SspTokens.h" +#include "CmosBoard.h" + +//--------------------------------------------------------------------------- +// These functions are originally defined in CmosAccess.c +//--------------------------------------------------------------------------- +extern EFI_STATUS CmosRead( + IN EFI_CMOS_ACCESS_INTERFACE *Cmos, + IN UINT16 CmosToken, + OUT UINT8 *CmosValue ); +extern EFI_STATUS CmosWrite( + IN EFI_CMOS_ACCESS_INTERFACE *Cmos, + IN UINT16 CmosToken, + IN UINT8 CmosValue ); +extern UINT16 CmosGetTokenFromRegister( + IN EFI_CMOS_ACCESS_INTERFACE *Cmos, + IN UINT16 CmosRegister ); +extern EFI_STATUS CalculateChecksum( + IN EFI_CMOS_MANAGER_INTERFACE *Manager, + OUT UINT16 *ChecksumValue ); +extern EFI_STATUS LoadOptimalDefaults( + IN EFI_CMOS_MANAGER_INTERFACE *Manager ); +extern EFI_STATUS WriteChecksum( + IN EFI_CMOS_MANAGER_INTERFACE *Manager, + OUT UINT16 ChecksumValue ); +extern EFI_STATUS ReadChecksum( + IN EFI_CMOS_MANAGER_INTERFACE *Manager, + OUT UINT16 *ChecksumValue ); +extern EFI_STATUS ReadCmosStatusBytes( + IN EFI_CMOS_ACCESS_INTERFACE *Cmos, + OUT CMOS_STATUS_BYTES *StatusBytes ); +extern EFI_STATUS SynchronizeLegacyStatusRegisters( + IN EFI_CMOS_MANAGER_INTERFACE *Manager, + IN CMOS_MANAGER_STATUS BitMap, + IN CMOS_BIT_ACCESS_TYPE AccessType ); +extern EFI_STATUS CmosPhysicalReadWrite( + IN EFI_CMOS_MANAGER_INTERFACE *Manager, + IN CMOS_ACCESS_TYPE AccessType, + IN UINT16 CmosAddress, + IN UINT8 BitsToWrite, + IN OUT UINT8 *CmosParameterValue ); + +extern EFI_STATUS CmosGetDateTime ( + IN EFI_CMOS_ACCESS_INTERFACE *Cmos, + OUT EFI_TIME *Time ); + +extern EFI_STATUS CmosSetDateTime ( + IN EFI_CMOS_ACCESS_INTERFACE *Cmos, + IN EFI_TIME *Time ); + +EFI_STATUS UpdateBatteryStatus ( + IN EFI_CMOS_MANAGER_INTERFACE *Manager ); + +// porting functions + +EFI_CMOS_IS_FIRST_BOOT gIsFirstBoot = CMOS_IS_FIRST_BOOT_MAPPING; +EFI_CMOS_IS_BSP gIsBsp = CMOS_IS_BSP_MAPPING; +EFI_CMOS_IS_COLD_BOOT gIsColdBoot = CMOS_IS_COLD_BOOT_MAPPING; +EFI_CMOS_IS_CMOS_USABLE gCmosIsUsable = CMOS_IS_USABLE_MAPPING; + + +#if defined( PEI_COMPILE ) || defined( SMM_COMPILE ) + + // In early PEI, these data items are accessed in ROM. + + // In SMM, the gCmosOptimalDefaultTable structure is + // read/write. + + extern CONST CMOS_TOKEN gCmosTokenTable[]; + extern CONST UINT16 gCmosTokenTableSize; + extern CONST CMOS_REGISTER gCmosNoCheckSumTable[]; + extern CONST UINT16 gCmosNoCheckSumTableSize; + extern CONST CMOS_REGISTER gUnmanagedTable[]; + extern CONST UINT16 gUnmanagedTableSize; + extern CMOS_REGISTER gCmosOptimalDefaultTable[]; + extern CONST UINT16 gCmosOptimalDefaultTableSize; + extern CONST UINT8 gFirstManagedRegister; + extern CONST UINT8 gLastManagedRegister; +#endif + + +#ifdef PEI_COMPILE // PEI phase-specific declarations + extern EFI_STATUS SaveCmosDataTablesToHob( + EFI_PEI_SERVICES **PeiServices, + EFI_CMOS_MANAGER_INTERFACE *Manager ); + extern VOID CmosSynchronizeHobManagerStatus( + IN EFI_CMOS_MANAGER_INTERFACE *Manager ); +#endif + + +// DXE phase-specific declarations + +#if !defined(PEI_COMPILE) && !defined(SMM_COMPILE) + extern EFI_STATUS InitializeCmosTablesFromHob( + EFI_CMOS_MANAGER_INTERFACE *Manager ); + +#endif + + +#ifdef PEI_COMPILE // PEI phase-specific globals + EFI_GUID gCmosAccessGuid = EFI_PEI_CMOS_ACCESS_GUID; + EFI_GUID gMemoryInstalledGuid = + EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI; + +#elif defined(SMM_COMPILE) // SMM-specific globals + EFI_GUID gCmosAccessGuid = EFI_SMM_CMOS_ACCESS_GUID; + +#else // default is DXE phase-specific globals + EFI_GUID gCmosAccessGuid = EFI_DXE_CMOS_ACCESS_GUID; + +#endif + + +// +//--------------------------------------------------------------------------- +// +// Procedure: CmosManagerAllocatePool +// +// Description: +// This function allocates memory for all boot phases. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// -- PEI Services table (NULL in DXE phase) +// IN UINTN Size +// -- Number of bytes to allocate +// OUT VOID **Buffer +// -- Pointer to buffer for which memory is allocated +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS if successful +// = or other valid EFI error code +// +// Notes: +// None +// +//--------------------------------------------------------------------------- +// + +EFI_STATUS CmosManagerAllocatePool( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer ) +{ +#ifdef PEI_COMPILE + return (*PeiServices)->AllocatePool( PeiServices, + Size, Buffer); +#elif defined(SMM_COMPILE) + return pSmst->SmmAllocatePool(0, Size, Buffer); +#else // DXE + return pBS->AllocatePool( EfiBootServicesData, Size, Buffer); +#endif + +} + + +// +//--------------------------------------------------------------------------- +// +// Procedure: CmosGetMangerInterface +// +// Description: +// Gets the EFI_CMOS_MANAGER_INTERFACE for the current access +// interface. +// +// Input: +// IN EFI_CMOS_ACCESS_INTERFACE *Cmos +// -- This is the access interface pointer. +// +// Output: +// EFI_CMOS_MANAGER_INTERFACE * (Return Value) +// -- If successful, the CMOS manager interface is returned. +// -- Otherwise, a valid EFI error code +// +// Notes: +// None +// +//--------------------------------------------------------------------------- +// + +EFI_CMOS_MANAGER_INTERFACE *GetCmosMangerInterface( + IN EFI_CMOS_ACCESS_INTERFACE *Cmos ) +{ + // The installed Protocol type will be EFI_CMOS_ACCESS_INTERFACE + // (converted as needed by the CMOS manager) + + EFI_CMOS_MANAGER_INTERFACE *Interface = (EFI_CMOS_MANAGER_INTERFACE*) Cmos; + return Interface; +} + + +// +//--------------------------------------------------------------------------- +// +// Procedure: GetCmosAccessInterface +// +// Description: +// Gets the EFI_CMOS_ACCESS_INTERFACE for the current manager +// interface. +// +// Input: +// IN EFI_CMOS_MANAGER_INTERFACE *Manager +// -- This is the manager interface pointer. +// +// Output: +// EFI_CMOS_ACCESS_INTERFACE * (Return Value) +// -- If successful, the CMOS access interface is returned. +// -- Otherwise, NULL is returned. +// +// Notes: +// None +// +//--------------------------------------------------------------------------- +// + +EFI_CMOS_ACCESS_INTERFACE *GetCmosAccessInterface( + IN EFI_CMOS_MANAGER_INTERFACE *Manager ) +{ + EFI_CMOS_ACCESS_INTERFACE *Interface = NULL; + + // The installed Protocol type will be EFI_CMOS_ACCESS_INTERFACE + // (converted as needed by the CMOS manager) + if (Manager != NULL && + Manager->CheckStatus(Manager, CMOS_VALID_INTERFACE)) + Interface = (EFI_CMOS_ACCESS_INTERFACE*) Manager; + + return Interface; +} + + +// +//--------------------------------------------------------------------------- +// +// Procedure: CmosManagerCheckStatus +// +// Description: +// This function returns true if all the status bits are set as +// specified by the BitMap. +// +// Input: +// IN EFI_CMOS_MANAGER_INTERFACE *Manager +// -- Pointer to the Manager's interface +// IN CMOS_MANAGER_STATUS BitMap +// -- Bits to check +// +// +// Output: +// BOOLEAN (Return value) +// = TRUE, if all bits in ManagerStatus specified by +// BitMap are set. +// +// = FALSE, otherwise. +// +// Notes: +// +//--------------------------------------------------------------------------- +// + +BOOLEAN CmosManagerCheckStatus( + IN EFI_CMOS_MANAGER_INTERFACE *Manager, + IN CMOS_MANAGER_STATUS BitMap ) +{ + if ((Manager->ManagerStatus & BitMap) == BitMap) + return TRUE; + else + return FALSE; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: CmosManagerCheckAnyStatus +// +// Description: +// This function returns true if any of the status bits are set as +// specified by the BitMap. +// +// Input: +// IN EFI_CMOS_MANAGER_INTERFACE *Manager +// -- Pointer to the Manager's interface +// IN CMOS_MANAGER_STATUS BitMap +// -- Bits to check +// +// +// Output: +// BOOLEAN (Return value) +// = TRUE, if one or more of the bits in ManagerStatus +// specified by BitMap are set. +// +// = FALSE, otherwise. +// +// Notes: +// +//--------------------------------------------------------------------------- +// + +BOOLEAN CmosManagerCheckAnyStatus( + IN EFI_CMOS_MANAGER_INTERFACE *Manager, + IN CMOS_MANAGER_STATUS BitMap ) +{ + if ((Manager->ManagerStatus & BitMap) != 0) + return TRUE; + else + return FALSE; +} + + +// +//--------------------------------------------------------------------------- +// +// Procedure: CmosManagerSetClearStatus +// +// Description: +// This function provides a single entry point into the code that +// actually updates status values. +// +// Input: +// IN EFI_CMOS_MANAGER_INTERFACE *Manager +// -- Pointer to the Manager's interface +// IN CMOS_MANAGER_STATUS BitMap +// -- Bits to set or clear +// IN CMOS_BIT_ACCESS_TYPE AccessType +// -- SetType or ClearType depending upon whether +// setting or clearing bits +// +// Output: +// EFI_STATUS (Return value) +// = EFI_SUCCESS or valid EFI error code +// +// Notes: +// +//--------------------------------------------------------------------------- +// + +VOID CmosManagerSetClearStatus( + IN EFI_CMOS_MANAGER_INTERFACE *Mgr, + IN CMOS_MANAGER_STATUS BitMap, + IN CMOS_BIT_ACCESS_TYPE AccessType ) +{ + if (AccessType == SetType){ + Mgr->ManagerStatus = Mgr->ManagerStatus | BitMap; + + // A boot/setup event callback explicitly clears these bits each boot + + if ( Mgr->CheckStatus(Mgr, CMOS_IS_USABLE) ){ + if ( BitMap & CMOS_BAD_BATTERY ) + Mgr->Access.Write(&Mgr->Access, CMOS_MGR_BATTERY_BAD, 1); + if ( BitMap & CMOS_BAD_CHECKSUM ) + Mgr->Access.Write(&Mgr->Access, CMOS_MGR_CHECKSUM_BAD, 1); + if ( BitMap & CMOS_DEFAULTS_LOADED ) + Mgr->Access.Write(&Mgr->Access, CMOS_MGR_DEFAULTS_LOADED, 1); + if ( BitMap & CMOS_FIRST_BOOT_DETECTED ) + Mgr->Access.Write(&Mgr->Access, CMOS_MGR_FIRST_BOOT_DETECTED, 1); + } + + } + else + Mgr->ManagerStatus = Mgr->ManagerStatus & ~BitMap; + +#ifdef PEI_COMPILE // In PEI, update ManagerStatus for DXE + CmosSynchronizeHobManagerStatus(Mgr); +#endif + + // if the Checksum or Battery status is being modified, then + // update the legacy status registers + if ( (BitMap & (CMOS_BAD_CHECKSUM | CMOS_BAD_BATTERY)) != 0 ){ + SynchronizeLegacyStatusRegisters(Mgr, BitMap, AccessType); + } + +} + + +// +//--------------------------------------------------------------------------- +// +// Procedure: CmosManagerSetStatus +// +// Description: +// This function sets status bits according to the specified bitmap. +// +// Input: +// IN EFI_CMOS_MANAGER_INTERFACE *Manager +// -- Pointer to the Manager's interface +// IN CMOS_MANAGER_STATUS BitMap +// -- Bits to set +// +// +// Output: +// EFI_STATUS (Return value) +// = EFI_SUCCESS or valid EFI error code +// +// Notes: +// +//--------------------------------------------------------------------------- +// + +VOID CmosManagerSetStatus( + IN EFI_CMOS_MANAGER_INTERFACE *Manager, + IN CMOS_MANAGER_STATUS BitMap ) +{ + CmosManagerSetClearStatus(Manager, BitMap, SetType); +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: CmosManagerClearStatus +// +// Description: +// This function clears status bits according to the specified bitmap. +// +// Input: +// IN EFI_CMOS_MANAGER_INTERFACE *Manager +// -- Pointer to the Manager's interface +// IN CMOS_MANAGER_STATUS BitMap +// -- Bits to clear +// +// +// Output: +// EFI_STATUS (Return value) +// = EFI_SUCCESS or valid EFI error code +// +// Notes: +// +//--------------------------------------------------------------------------- +// + +VOID CmosManagerClearStatus( + IN EFI_CMOS_MANAGER_INTERFACE *Manager, + IN CMOS_MANAGER_STATUS BitMap ) +{ + CmosManagerSetClearStatus(Manager, BitMap, ClearType); +} + + +// +//--------------------------------------------------------------------------- +// +// Procedure: CmosUpdateMemoryStatus +// +// Description: +// This function is used in the PEI phase to set/clear the +// CMOS_EXECUTING_IN_MEMORY depending on whether or not the manager +// is executing after permanent memory has been initialized. +// +// Input: +// IN EFI_CMOS_MANAGER_INTERFACE *Manager +// -- Pointer to the Manager's interface +// +// +// Output: +// EFI_STATUS (Return value) +// = EFI_SUCCESS or valid EFI error code +// +// Notes: +// +//--------------------------------------------------------------------------- +// + +#ifdef PEI_COMPILE +VOID CmosUpdateMemoryStatus ( + IN EFI_CMOS_MANAGER_INTERFACE *Manager ) +{ + EFI_STATUS Status = EFI_SUCCESS; + VOID *InterfacePtr; + DEFINE_PEI_SERVICES(Manager->Access.PeiServices); + + CMOS_TRACE_FULL(( CMOS_TRACE_ALWAYS, "CmosUpdateMemoryStatus Entry\n")); + + Status = (*PeiServices)->LocatePpi( PeiServices, &gMemoryInstalledGuid, + 0, NULL, &InterfacePtr); + if ( EFI_ERROR(Status) ) + Manager->ClearStatus(Manager, CMOS_EXECUTING_IN_MEMORY); + else + Manager->SetStatus(Manager, CMOS_EXECUTING_IN_MEMORY); + +} +#endif + + +// +//--------------------------------------------------------------------------- +// +// Procedure: CmosConfigureManager +// +// Description: +// This function configures the CMOS Manager. +// +// Input: +// IN EFI_CMOS_MANAGER_INTERFACE *Manager +// -- Pointer to the Manager's interface +// IN CMOS_CONFIGURATION_SETTING Setting +// -- Configuration setting to invoke. +// +// Output: +// EFI_STATUS (Return value) +// = EFI_SUCCESS or valid EFI error code +// +// Notes: +// +//--------------------------------------------------------------------------- +// + +EFI_STATUS CmosConfigureManager( + IN EFI_CMOS_MANAGER_INTERFACE *Mgr, + IN CMOS_CONFIGURATION_SETTING Setting ) +{ + EFI_STATUS Status = EFI_SUCCESS; + DEFINE_PEI_SERVICES(Mgr->Access.PeiServices); + +#define Request(x) ((Setting & (x)) != 0) + + // Basic error checking + + if ( Request(CMOS_OPTIMAL_DEFAULTS_ON) + && Request(CMOS_OPTIMAL_DEFAULTS_OFF) ) + { + return Status = EFI_INVALID_PARAMETER; + } + + //----------------------------------------------------------------------- + // CMOS_OPTIMAL_DEFAULTS_ON + //----------------------------------------------------------------------- + // If configuring usage of the optimal defaults buffer and it's already + // enabled, simply return. Otherwise... + // + // * If executing in memory, enable the optimal defaults buffer + // and update the checksum. + // * If not executing in memory, allocate the optimal defaults buffer, + // copy the values into it, and update the + // Manager->OptimalDefaultTable pointer to point to the read/write + // buffer. + // * Set the manager status bit to indicate usage of the optimal + // defaults buffer. + + if ( Request( CMOS_OPTIMAL_DEFAULTS_ON ) ) + { + if (Mgr->CheckStatus(Mgr, CMOS_OPTIMAL_DEFAULTS_ENABLED)) + return EFI_SUCCESS; // already configured + + // This will only occur in PEI phase!! + + if (!Mgr->CheckStatus(Mgr, CMOS_EXECUTING_IN_MEMORY)) { + VOID *Temp; + CmosManagerAllocatePool( PeiServices, + Mgr->OptimalDefaultCount * sizeof(CMOS_REGISTER), + &Temp); + MemCpy( Temp , Mgr->OptimalDefaultTable, + Mgr->OptimalDefaultCount * sizeof(CMOS_REGISTER) ); + Mgr->OptimalDefaultTable = Temp; + } + + Mgr->SetStatus(Mgr, CMOS_OPTIMAL_DEFAULTS_ENABLED); + Mgr->CalculateChecksum(Mgr, &Mgr->Checksum); + Mgr->WriteChecksum(Mgr, Mgr->Checksum); + + } + + //----------------------------------------------------------------------- + // CMOS_OPTIMAL_DEFAULTS_OFF + //----------------------------------------------------------------------- + // + // Clear the status bit, and let the Manager interface user must decide + // what to do next ...call LoadOptimalDefaults, enable buffered CMOS + // mode, .... + + if ( Request( CMOS_OPTIMAL_DEFAULTS_OFF ) ){ + Mgr->ClearStatus(Mgr, CMOS_OPTIMAL_DEFAULTS_ENABLED); + } + +#undef Request + + return Status; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SaveApiPointerToCmos +// +// Description: +// This function saves the specified pointer to a predefined 4-byte +// CMOS location. +// +// Input: +// IN EFI_CMOS_MANAGER_INTERFACE *CmosManager +// - Pointer to the manager's interface +// IN EFI_CMOS_ACCESS_INTERFACE *ApiPointer +// - API address +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS or valid EFI error code +// +// Notes: +// None +// +//--------------------------------------------------------------------------- +// + +EFI_STATUS SaveApiPointerToCmos( + IN EFI_CMOS_MANAGER_INTERFACE *Mgr, + IN EFI_CMOS_ACCESS_INTERFACE *ApiPointer ) +{ + UINT32 Offset; + UINT8 Byte; // Only used in PEI + DEFINE_PEI_SERVICES(Mgr->Access.PeiServices); + + if (ApiPointer == NULL) + ApiPointer = Mgr->GetAccessInterface(Mgr); + + if ( !Mgr->CheckAnyStatus(Mgr, CMOS_IS_USABLE ) ){ + CMOS_TRACE_FULL(( CMOS_TRACE_ALWAYS, + "CMOS Not Usable: Could not save API pointer.\n")); + return EFI_DEVICE_ERROR; + } + + for (Offset = 0; Offset < 4; Offset++){ + Byte = (UINT8)((UINT32)ApiPointer >> (24 - (Offset * 8))) & 0xff; + CmosPhysicalReadWrite( Mgr, + WriteType, + CMOS_ACCESS_API_BYTE3 + Offset, + ALL_BITS, + &Byte ); + } + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: GetApiPointerFromCmos +// +// Description: +// This function get the CMOS API pointer from a predefined 4-byte +// CMOS location and updates the output parameter with the pointer. +// +// Input: +// IN EFI_CMOS_MANAGER_INTERFACE *CmosManager +// - Pointer to the manager's interface to be installed +// OUT EFI_CMOS_ACCESS_INTERFACE **ApiPointer +// - Address of the API pointer +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS or valid EFI error code +// +// Notes: +// None +// +//--------------------------------------------------------------------------- +// + +EFI_STATUS GetApiPointerFromCmos( + IN EFI_CMOS_MANAGER_INTERFACE *Mgr, + EFI_CMOS_ACCESS_INTERFACE **ApiPointer ) +{ + UINT8 Temp; + UINT32 Ptr = 0; + UINT8 Offset; + DEFINE_PEI_SERVICES(Mgr->Access.PeiServices); + + if ( !Mgr->CheckAnyStatus(Mgr, CMOS_IS_USABLE ) ){ + CMOS_TRACE_FULL(( CMOS_TRACE_ALWAYS, + "CMOS Not Usable: Could not read API pointer.\n")); + return EFI_DEVICE_ERROR; + } + + for (Offset = 0; Offset < 4; Offset++){ + CmosPhysicalReadWrite( Mgr, + ReadType, + CMOS_ACCESS_API_BYTE3 + Offset, + 0, + &Temp ); + Ptr = (Ptr << 8) | Temp; + } + + *ApiPointer = (EFI_CMOS_ACCESS_INTERFACE*) Ptr; + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: InstallCmosAccessInterface +// +// Description: +// This function installs either the PEI or DXE phase interface +// (PPI or Protocol) for accessing CMOS. +// +// Input: +// IN EFI_CMOS_MANAGER_INTERFACE *CmosManager +// - Pointer to the interface to be installed +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS or valid EFI error code +// CmosManager->ManagerStatus +// = CMOS_VALID_MANAGER indicates successful +// installation of interface. +// +// Notes: +// This function is used for both PEI and DXE phase. The build +// macro PEI_COMPILE will determine how the object code is +// created/linked. +// +//--------------------------------------------------------------------------- +// + +EFI_STATUS InstallCmosAccessInterface( + IN EFI_CMOS_MANAGER_INTERFACE *CmosManager ) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_HANDLE Handle = 0; + DEFINE_PEI_SERVICES(CmosManager->Access.PeiServices); + +#ifdef PEI_COMPILE + Status = (*PeiServices)->InstallPpi( + PeiServices, &CmosManager->Ppi[CMOS_ACCESS_PPI_TYPE]); +#else + Status = pBS->InstallMultipleProtocolInterfaces( + &Handle, &CmosManager->AccessGuid, CmosManager, NULL); +#endif + + if (!EFI_ERROR(Status)) + CmosManager->SetStatus(CmosManager, CMOS_VALID_MANAGER); + else { + CmosManager->SetStatus(CmosManager, CMOS_INSTALL_FAILED); + CmosManager->ClearStatus(CmosManager, CMOS_VALID_MANAGER); + } + + return Status; +} + + +// +//--------------------------------------------------------------------------- +// +// Procedure: InitializeCmosManagerInterface +// +// Description: +// This function initializes structure data and function pointer +// elements for a EFI_CMOS_MANAGER_INTERFACE. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// - This parameter will be NULL in the DXE phase +// OUT EFI_CMOS_MANAGER_INTERFACE *CmosManager +// - Pointer to the interface to be initialized +// +// Output: +// EFI_STATUS (Return Value) +// = EFI_SUCCESS or valid EFI error code +// CmosManager->ManagerStatus +// = CMOS_VALID_INTERFACE indicates successful +// initialization of the structure. +// +// Notes: +// This function is used for both PEI and DXE phase. The build +// macro PEI_COMPILE will determine how the object code is +// created. +// +//--------------------------------------------------------------------------- +// + + +EFI_STATUS InitializeCmosManagerInterface( + IN EFI_PEI_SERVICES **PeiServices, + OUT EFI_CMOS_MANAGER_INTERFACE *CmosManager ) +{ + EFI_STATUS Status = EFI_SUCCESS; + + CMOS_TRACE_FULL(( CMOS_TRACE_ALWAYS, + "InitializeCmosManagerInterface Entry\n")); + + // Note: all pointers/values are already NULL/Zero + + // Not using an initializer list in order to avoid problems + // if/when the interface declarations are modified. + + //----------------------------------------------------------------------- + // Phase-independent initialization + //----------------------------------------------------------------------- + CmosManager->AccessGuid = gCmosAccessGuid; + CmosManager->Access.PeiServices = PeiServices; // ensure NULL in DXE + CmosManager->Access.Read = CmosRead; + CmosManager->Access.Write = CmosWrite; + CmosManager->Access.GetTokenFromRegister = CmosGetTokenFromRegister; + CmosManager->Access.ReadCmosStatusBytes = ReadCmosStatusBytes; + CmosManager->Access.GetTime = CmosGetDateTime; + CmosManager->Access.SetTime = CmosSetDateTime; + CmosManager->GetAccessInterface = GetCmosAccessInterface; + CmosManager->InstallAccessInterface = InstallCmosAccessInterface; + CmosManager->CalculateChecksum = CalculateChecksum; + CmosManager->ReadChecksum = ReadChecksum; + CmosManager->WriteChecksum = WriteChecksum; + CmosManager->ConfigureManager = CmosConfigureManager; + CmosManager->CheckStatus = CmosManagerCheckStatus; + CmosManager->CheckAnyStatus = CmosManagerCheckAnyStatus; + CmosManager->SetStatus = CmosManagerSetStatus; + CmosManager->ClearStatus = CmosManagerClearStatus; + CmosManager->LoadOptimalDefaults = LoadOptimalDefaults; + CmosManager->SaveApiPointerToCmos = SaveApiPointerToCmos; + CmosManager->GetApiPointerFromCmos = GetApiPointerFromCmos; + + //----------------------------------------------------------------------- + // Phase-specific initialization + //----------------------------------------------------------------------- + // update the access PPI descriptor and CMOS data table pointers. + // + // Note: + // Before memory detection, the tables to which these pointers refer + // will reside in ROM. At runtime, these tables will reside in + // SMRAM and boot updates will be copied into them. + //----------------------------------------------------------------------- + +#if defined(PEI_COMPILE) || defined(SMM_COMPILE) + CmosManager->FirstManagedRegister = gFirstManagedRegister; + CmosManager->LastManagedRegister = gLastManagedRegister; + CmosManager->TokenTable = (CMOS_TOKEN*) gCmosTokenTable; + CmosManager->TokenCount = gCmosTokenTableSize; + CmosManager->NoChecksumTable = (CMOS_REGISTER*) gCmosNoCheckSumTable; + CmosManager->NoChecksumCount = gCmosNoCheckSumTableSize; + CmosManager->UnmanagedTable = (CMOS_REGISTER*) gUnmanagedTable; + CmosManager->UnmanagedTableCount = gUnmanagedTableSize; + CmosManager->OptimalDefaultTable = + (CMOS_REGISTER*) gCmosOptimalDefaultTable; + CmosManager->OptimalDefaultCount = gCmosOptimalDefaultTableSize; +#endif + +#if defined(PEI_COMPILE) + CmosManager->Ppi[CMOS_ACCESS_PPI_TYPE].Flags = + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + CmosManager->Ppi[CMOS_ACCESS_PPI_TYPE].Guid = &gCmosAccessGuid; + CmosManager->Ppi[CMOS_ACCESS_PPI_TYPE].Ppi = (VOID*)CmosManager; +#endif + + CmosManager->SetStatus(CmosManager, CMOS_VALID_INTERFACE); + + return Status; +} + + +// +//--------------------------------------------------------------------------- +// +// Procedure: NewCmosManagerInterface +// +// Description: +// This function locates (or allocates memory for) the +// EFI_CMOS_MANAGER_INTERFACE, calculates the checksum, checks the +// battery condition and updates the Manager's status bits. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices +// - This parameter will be NULL in the DXE phase +// +// Output: +// EFI_CMOS_MANAGER_INTERFACE* (Return Value) +// = If successful, a pointer to the allocated/found +// structure is returned. +// = NULL is returned on failure to allocate +// +// NewManager->ManagerStatus +// = CMOS_INTERFACE_ALREADY_INSTALLED, if the interface is +// found prior to allocating +// = CMOS_VALID_INTERFACE, on successful initialization +// of the access interface. +// +// Notes: +// This function is used for PEI, DXE and SMM interface initialization. +// The build macros PEI_COMPILE and SMM_COMPILE will determine how the +// object code is compiled. +// +// See CMOS_MANAGER_STATUS enum type for more information on manager +// status bits. +// +// Assumptions: +// +// 1) This function should only be called once for each +// entrypoint. +// +// 2) It is up to the user of the Manager interface to determine +// how to use the CMOS_MANAGER_STATUS bits upon return from +// this function. +// +//--------------------------------------------------------------------------- +// + +EFI_CMOS_MANAGER_INTERFACE* NewCmosManagerInterface( + IN EFI_PEI_SERVICES **PeiServices ) +{ + EFI_CMOS_MANAGER_INTERFACE *NewManager; + EFI_STATUS Status; + + //----------------------------------------------------------------------- + // If the interface is found then no initialization is done. + //----------------------------------------------------------------------- + +#ifdef PEI_COMPILE + LOCATE_CMOS_ACCESS_PPI(Status, NewManager); +#elif defined (SMM_COMPILE) + LOCATE_CMOS_ACCESS_SMM_PROTOCOL(Status, NewManager) +#else + LOCATE_CMOS_ACCESS_PROTOCOL(Status, NewManager) +#endif + if (Status == EFI_SUCCESS) + { + NewManager->SetStatus(NewManager, CMOS_INTERFACE_ALREADY_INSTALLED); + return NewManager; + } + + //----------------------------------------------------------------------- + // Return NULL on allocation error. + //----------------------------------------------------------------------- + + if (EFI_ERROR(CmosManagerAllocatePool( PeiServices, + sizeof(EFI_CMOS_MANAGER_INTERFACE), + (VOID**)&NewManager ) )){ + return NULL; + } + + //----------------------------------------------------------------------- + // Zero the interface buffer (also ensures ManagerStatus bits are clear + // and ensures pointers are NULL) + //----------------------------------------------------------------------- + + MemSet( (void*)NewManager, sizeof(EFI_CMOS_MANAGER_INTERFACE), 0); + + //----------------------------------------------------------------------- + // Initialize general structures and function pointers + //----------------------------------------------------------------------- + + InitializeCmosManagerInterface(PeiServices, NewManager); + + //----------------------------------------------------------------------- + // Initialize pointers to/from data structures in the HOB or DXE Buffer + // updates + //----------------------------------------------------------------------- + // In PEI phase: + // 1. Update memory status + // + // In DXE phase: + // 1. Get the HOB and complete the initialization of the Manager + // interface data structure pointers. + // + // In SMM registration: + // 1. Use the original optimal defaults buffer, as the DXE buffer + // has already by flushed to the physical registers if the battery + // is good. (If the battery is bad, it is unlikely CMOS is of + // any use in SMM.) + +#ifdef PEI_COMPILE + CmosUpdateMemoryStatus( NewManager ); +#elif !defined(SMM_COMPILE) + if (EFI_ERROR( InitializeCmosTablesFromHob(NewManager) )) + return NULL; +#endif + + CMOS_TRACE_FULL((CMOS_TRACE_ALWAYS, "Call CmosIsUsable: " )); + if ( gCmosIsUsable( NewManager->Access.PeiServices ) ){ + NewManager->SetStatus(NewManager, CMOS_IS_USABLE); + CMOS_TRACE_FULL((CMOS_TRACE_ALWAYS, "CMOS is usable\n" )); + } + else { + NewManager->ClearStatus(NewManager, CMOS_IS_USABLE); + CMOS_TRACE_FULL((CMOS_TRACE_ALWAYS, "CMOS is not usable\n" )); + } + + //----------------------------------------------------------------------- + // Update CMOS_FIRST_BOOT_DETECTED status bit before calculating + // the checksum or determining the battery status. + //----------------------------------------------------------------------- + + CMOS_TRACE_FULL((CMOS_TRACE_ALWAYS, "Call gIsFirstBoot: " )); + if ( gIsFirstBoot( NewManager->Access.PeiServices ) ){ + NewManager->SetStatus(NewManager, CMOS_FIRST_BOOT_DETECTED); + CMOS_TRACE_FULL((CMOS_TRACE_ALWAYS, "First boot detected\n" )); + } + else { + CMOS_TRACE_FULL((CMOS_TRACE_ALWAYS, "First boot NOT detected\n" )); + } + + // Update CMOS_COLD_BOOT_DETECTED status bit. + + CMOS_TRACE_FULL((CMOS_TRACE_ALWAYS, "Call gIsColdBoot: " )); + if ( gIsColdBoot( NewManager->Access.PeiServices ) ){ + NewManager->SetStatus(NewManager, CMOS_COLD_BOOT_DETECTED); + CMOS_TRACE_FULL((CMOS_TRACE_ALWAYS, "Cold boot detected\n" )); + } + else { + CMOS_TRACE_FULL((CMOS_TRACE_ALWAYS, "Cold boot NOT detected\n" )); + } + + // Update CMOS_BSP_IS_EXECUTING status bit. + + CMOS_TRACE_FULL((CMOS_TRACE_ALWAYS, "Call gIsBsp: " )); + if ( gIsBsp( NewManager->Access.PeiServices ) ){ + NewManager->SetStatus(NewManager, CMOS_BSP_IS_EXECUTING); + CMOS_TRACE_FULL((CMOS_TRACE_ALWAYS, "BSP is executing\n" )); + } + else { + CMOS_TRACE_FULL((CMOS_TRACE_ALWAYS, "BSP is NOT executing\n" )); + } + + // Configure incoherency recovery policy + +#if CMOS_MGR_RECOVER_ONLY_CHECKUMMED + NewManager->SetStatus(NewManager, CMOS_RECOVER_ONLY_CHECKSUMMED); +#endif + +#if CMOS_MGR_RECOVER_IN_PEI + NewManager->SetStatus(NewManager, CMOS_RECOVER_IN_PEI); +#endif + + + //----------------------------------------------------------------------- + // Update the NewManager->Checksum + // + // Note: This call only calculates and updates the checksum in + // the manager interface structure. The CMOS_BAD_CHECKSUM bit + // is set in NewManager->ManagerStatus, if the calculated checksum + // does not match the current checksum in CMOS. + // + // The user of the Manager interface will decide how to handle + // a bad checksum. + //----------------------------------------------------------------------- + + NewManager->CalculateChecksum(NewManager, &NewManager->Checksum); + + UpdateBatteryStatus(NewManager); + + return NewManager; +} + + + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* -- cgit v1.2.3