/*
* NvramDxe.c - NVRAM DXE Driver Implementation
*
* Source: AmiModulePkg/NVRAM/NvramDxe
* Original source paths:
* e:\hs\AmiModulePkg\NVRAM\NvramDxe.c
* e:\hs\AmiModulePkg\NVRAM\NvramDxeCommon.c
* e:\hs\AmiModulePkg\NVRAM\NvramSmmWrapper.c
* e:\hs\AmiModulePkg\SecureBoot\AuthenticatedVariable\AuthService.c
*
* Build: HR6N0XMLK, DEBUG_VS2015, X64
* Platform: Intel/AMD64 UEFI
*
* This UEFI DXE driver implements the NVRAM variable services for the
* HR650X BIOS. It handles:
* - UEFI Runtime Variable Services (GetVariable, SetVariable,
* GetNextVariableName, QueryVariableInfo)
* - NVRAM store initialization from HOB or simulation mode
* - SMM communication for authenticated variable writes
* - Secure Boot variable initialization (SetupMode, SecureBoot)
* - NVRAM mailbox protocol for inter-module communication
* - NVRAM garbage collection and store reclamation
*/
#include "NvramDxe.h"
/*===========================================================================
* Global State
*===========================================================================*/
//
// Protocol interfaces
//
STATIC EFI_HANDLE mImageHandle = NULL;
STATIC EFI_SYSTEM_TABLE *mSystemTable = NULL;
STATIC EFI_BOOT_SERVICES *mBootServices = NULL;
STATIC EFI_RUNTIME_SERVICES *mRuntimeServices = NULL;
//
// NVRAM Variable Stores
//
STATIC NVRAM_VARIABLE_STORE *mPrimaryStore = NULL;
STATIC NVRAM_VARIABLE_STORE *mSecondaryStore = NULL;
//
// SMM Communication
//
STATIC VOID *mSmmCommunication = NULL;
STATIC VOID *mSmmVariableProtocol = NULL;
STATIC VOID *mSharedBuffer = NULL;
STATIC UINT64 mSharedBufferSize = 0;
STATIC UINT64 mSharedBufferUsed = 0;
STATIC UINT64 mSharedBufferBase = 0;
//
// NVRAM Store Workspace
//
STATIC UINT32 mNvramStoreType = 0;
STATIC UINT32 mNvramStoreCount = 0;
STATIC UINT32 mCurrentWorkspace = 0;
STATIC UINT8 mNvramWorkspaceFlags = 0;
STATIC UINT8 *mNvramStoreBuffer = NULL;
STATIC UINT32 mNvramAllocSize = 0;
//
// NVRAM Mailbox state
//
STATIC UINT16 mMailboxState = 0;
//
// State Flags
//
STATIC BOOLEAN mDebugEnabled = FALSE;
STATIC BOOLEAN mSmmEstablished = FALSE;
STATIC BOOLEAN mRuntimeTransitioned = FALSE;
STATIC BOOLEAN mSmmStarted = FALSE;
STATIC BOOLEAN mRuntimeServicesReady = FALSE;
//
// Reference counts
//
STATIC UINT32 mBootServiceRefCount = 0;
STATIC UINT32 mRuntimeServiceRefCount = 0;
//
// Protocol registration handles
//
STATIC VOID *mProtocolNotifySmmVariable = NULL;
STATIC VOID *mProtocolNotifyVarStore = NULL;
STATIC VOID *mSmmVarStorageProtocol = NULL;
STATIC VOID *mNvramRuntimeProtocol = NULL;
STATIC VOID *mVarStorageProtocol = NULL;
//
// Debug output protocol
//
STATIC VOID *mDebugProtocol = NULL;
STATIC VOID *mDebugProtocolHandle = NULL;
//
// Event notification handles
//
STATIC EFI_EVENT mReadyToBootEvent;
STATIC EFI_EVENT mVirtAddrChangeEvent;
STATIC EFI_EVENT mSmmReadyToLockEvent;
//
// Crypto / hash resources
//
STATIC VOID *mHashContext = NULL;
STATIC UINT64 mHashCount = 0;
STATIC VOID *mCryptoLib = NULL;
STATIC VOID *mCryptoLibReg = NULL;
/*===========================================================================
* Forward Declarations
*===========================================================================*/
STATIC
EFI_STATUS
NvDxeFindVariableInStore (
IN NVRAM_VARIABLE_STORE *Store,
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT UINT32 *Attributes OPTIONAL,
IN OUT UINTN *DataSize,
OUT VOID *Data OPTIONAL
);
STATIC
EFI_STATUS
NvDxeSetVariableInternal (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
);
STATIC
BOOLEAN
NvDxeValidateVariableEntry (
IN UINT8 *Entry,
IN NVRAM_VARIABLE_STORE *Store
);
STATIC
BOOLEAN
NvDxeIsCompatibleNvram (
VOID
);
STATIC
EFI_STATUS
NvDxeAllocateNvStore (
VOID
);
STATIC
EFI_STATUS
NvDxeInitializeStores (
VOID
);
STATIC
EFI_STATUS
NvDxeGarbageCollect (
IN NVRAM_VARIABLE_STORE *Store
);
STATIC
EFI_STATUS
NvDxeReclaimStore (
IN NVRAM_VARIABLE_STORE *Store
);
STATIC
EFI_STATUS
NvDxeRegisterSmiHandler (
VOID
);
STATIC
VOID
EFIAPI
NvDxeMailboxCallback (
IN UINT64 MailboxState
);
STATIC
EFI_STATUS
NvDxeMailboxInstall (
VOID
);
STATIC
VOID
NvDxeCheckStoreState (
VOID
);
STATIC
VOID
EFIAPI
NvDxeReadyToBootCallback (
IN EFI_EVENT Event,
IN VOID *Context
);
STATIC
VOID
EFIAPI
NvDxeVirtualAddressChangeCallback (
IN EFI_EVENT Event,
IN VOID *Context
);
STATIC
VOID
EFIAPI
NvDxeSmmReadyToLockCallback (
IN EFI_EVENT Event,
IN VOID *Context
);
STATIC
VOID
NvDxeConvertPointer (
VOID
);
/*===========================================================================
* Debug / Assert Helpers
*===========================================================================*/
/**
* Initialize debug output protocol.
* Reads debug level from CMOS 0x4B to enable/disable debug output.
*/
STATIC
EFI_STATUS
NvDxeInitDebugProtocol (
VOID
)
{
EFI_STATUS Status;
UINT8 DebugLevel;
DebugLevel = IoRead8(0x71);
if (DebugLevel > 3) {
DebugLevel = 3;
}
mDebugEnabled = (DebugLevel != 0);
if (mDebugProtocolHandle == NULL) {
return EFI_NOT_FOUND;
}
Status = mBootServices->LocateProtocol (
&gEfiDebugProtocolGuid,
NULL,
&mDebugProtocol
);
if (EFI_ERROR(Status)) {
mDebugProtocol = NULL;
}
return Status;
}
/**
* Debug print wrapper. Outputs formatted message via debug protocol
* if the CMOS debug level permits the given error level.
*/
STATIC
UINTN
NvDxeDebugPrint (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
)
{
VA_LIST Marker;
UINT8 DebugLevel;
UINTN ErrorMask;
VA_START(Marker, Format);
IoWrite8(0x70, (IoRead8(0x70) & 0x80) | 0x4B);
DebugLevel = IoRead8(0x71);
if (DebugLevel > 3) {
DebugLevel = 3;
}
if (DebugLevel == 0) {
VA_END(Marker);
return 0;
}
ErrorMask = (DebugLevel == 1) ? 0x80000000 :
(DebugLevel == 2) ? 0x80000004 :
(DebugLevel == 3) ? 0x80000002 : 0;
if ((ErrorMask & ErrorLevel) == 0) {
VA_END(Marker);
return 0;
}
if (mDebugProtocol != NULL) {
((EFI_DEBUG_PROTOCOL*)mDebugProtocol)->DebugPrint (
ErrorLevel,
Format,
Marker
);
}
VA_END(Marker);
return 0;
}
/**
* Assert handler: prints assertion and dead-loops.
*/
STATIC
VOID
NvDxeAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
if (mDebugProtocol != NULL) {
((EFI_DEBUG_PROTOCOL*)mDebugProtocol)->DebugAssert (
FileName,
LineNumber,
Description
);
}
CpuDeadLoop();
}
/*===========================================================================
* NVRAM Store Initialization
*===========================================================================*/
/**
* Initialize NVRAM variable store from HOB data.
*
* When HobData is NULL, simulation mode is used with default size.
*/
STATIC
EFI_STATUS
NvDxeInitStoreFromHob (
IN UINT16 *HobData
)
{
UINT8 *NvStoreBase;
UINT64 NvStoreSize;
UINT64 AllocSize;
if (HobData == NULL) {
mNvramStoreType = 8;
NvStoreBase = NULL;
NvStoreSize = 0x80000;
AllocSize = 0x180000;
if (!mDebugEnabled) {
NvDxeDebugPrint (
0x80000000,
"NVRAM: NVRAM HOB is not found. Switching to simulation mode.\n"
);
}
} else {
mNvramStoreType = *((UINT32*)HobData + 12);
NvStoreBase = (UINT8*)*((UINT64*)HobData + 3);
NvStoreSize = *((UINT32*)HobData + 10);
if (NvStoreSize < 0x80000) {
NvStoreSize = 0x80000;
}
if (NvStoreBase == NULL) {
if (!mDebugEnabled) {
NvDxeDebugPrint (
0x80000000,
"NVRAM: ERROR: NVRAM HOB contains NULL base address!\n"
);
}
return EFI_INVALID_PARAMETER;
}
AllocSize = 3 * NvStoreSize;
}
mNvramAllocSize = (UINT32)AllocSize;
mNvramStoreBuffer = AllocateRuntimePages (EFI_SIZE_TO_PAGES (AllocSize));
if (mNvramStoreBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if (HobData != NULL && NvStoreBase != NULL) {
CopyMem (mNvramStoreBuffer, NvStoreBase, NvStoreSize);
}
mNvramWorkspaceFlags = 0x07;
return EFI_SUCCESS;
}
/**
* Allocate NVRAM variable storage by scanning the system HOB.
*/
STATIC
EFI_STATUS
NvDxeAllocateNvStore (
VOID
)
{
EFI_STATUS Status;
UINT16 *HobList;
UINT16 *CurrentHob;
UINT16 HobType;
UINT16 HobLength;
UINT16 *NvHobData;
NvHobData = NULL;
HobList = (UINT16*)NvDxeGetHobList ();
if (HobList != NULL) {
CurrentHob = HobList;
do {
HobType = *CurrentHob;
if (HobType == 0x0004) {
break;
}
if (HobType == HOB_TYPE_NV_STORAGE) {
NvHobData = CurrentHob;
break;
}
HobLength = *(CurrentHob + 1);
if (HobLength == 0) {
break;
}
CurrentHob = (UINT16*)((UINT8*)CurrentHob + HobLength);
} while (CurrentHob != NULL);
}
Status = NvDxeInitStoreFromHob (NvHobData);
return Status;
}
/**
* Initialize NVRAM stores: allocate shared buffer for SMM communication.
*/
STATIC
EFI_STATUS
NvDxeInitializeStores (
VOID
)
{
EFI_STATUS Status;
UINT64 MaxVarSize;
MaxVarSize = NvDxeGetNvStoreSizeFromHob ();
if (MaxVarSize == 0) {
MaxVarSize = 0x80000;
}
if (MaxVarSize < 0x100000000) {
mSharedBufferSize = 2 * MaxVarSize;
Status = mBootServices->AllocatePages (
AllocateAnyPages,
EfiRuntimeServicesData,
EFI_SIZE_TO_PAGES (mSharedBufferSize),
&mSharedBufferBase
);
if (!EFI_ERROR(Status)) {
mSharedBuffer = (VOID*)(UINTN)mSharedBufferBase;
CopyMem (mSharedBuffer, &xmmword_13160, 16);
mSharedBufferUsed = 24;
mSharedBufferSize -= 24;
}
}
return Status;
}
/*===========================================================================
* Check NVRAM Compatibility
*===========================================================================*/
/**
* Check if the NVRAM store is compatible with this driver.
* Reads "Setup" and registered platform variables.
*/
STATIC
BOOLEAN
NvDxeIsCompatibleNvram (
VOID
)
{
UINT64 SetupVarSize = 0;
EFI_STATUS Status;
Status = NvDxeVarStoreGetVariable (
L"Setup",
&gEfiSetupVariableGuid,
0,
&SetupVarSize,
NULL
);
if (Status == EFI_NOT_FOUND && SetupVarSize != 814) {
return FALSE;
}
if (off_13CF0[0] != NULL) {
for (UINTN i = 0; off_13CF0[i * 3] != NULL; i++) {
VOID *Guid = off_13CF0[i * 3];
CHAR16 *Name = (CHAR16*)off_13CF0[i * 3 + 1];
UINTN ExpectedSize = (UINTN)off_13CF0[i * 3 + 2];
SetupVarSize = 0;
Status = NvDxeVarStoreGetVariable (
Name,
Guid,
0,
&SetupVarSize,
NULL
);
if (Status == EFI_NOT_FOUND && SetupVarSize != ExpectedSize) {
return FALSE;
}
}
}
return TRUE;
}
/*===========================================================================
* Variable Store Operations
*===========================================================================*/
/**
* Check variable store for pending operations from mailbox.
*/
STATIC
VOID
NvDxeCheckStoreState (
VOID
)
{
if (mSmmEstablished && !mRuntimeTransitioned) {
if ((mMailboxState & 0x100) != 0) {
if (mPrimaryStore != NULL) {
NvDxeReclaimStore (mPrimaryStore);
mCurrentWorkspace = 0;
NvDxeStoreSync ((UINT64)mPrimaryStore);
}
}
if ((mMailboxState & 0x200) != 0) {
if (mSecondaryStore != NULL) {
NvDxeReclaimStore (mSecondaryStore);
}
}
if ((mMailboxState & 0xFF00) != 0) {
mMailboxState &= 0x00FF;
}
}
}
/*===========================================================================
* UEFI Runtime Variable Services
*===========================================================================*/
/**
* GetVariable - Retrieve a UEFI variable from NVRAM.
*/
EFI_STATUS
EFIAPI
NvDxeGetVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT UINT32 *Attributes OPTIONAL,
IN OUT UINTN *DataSize,
OUT VOID *Data OPTIONAL
)
{
EFI_STATUS Status;
UINT64 CheckStatus;
CheckStatus = NvDxeCheckRuntimeState ();
if (CheckStatus != EFI_SUCCESS && CheckStatus != EFI_NOT_READY) {
return (EFI_STATUS)CheckStatus;
}
NvDxeCheckStoreState ();
if (!mRuntimeTransitioned) {
if (mSmmEstablished && mSmmVariableProtocol != NULL) {
Status = NvDxeGetVariableSmm (
VariableName,
VendorGuid,
Attributes,
DataSize,
Data
);
} else {
Status = NvDxeFindVariableInStore (
mPrimaryStore,
VariableName,
VendorGuid,
Attributes,
DataSize,
Data
);
}
} else {
Status = NvDxeFindVariableInStore (
mPrimaryStore,
VariableName,
VendorGuid,
Attributes,
DataSize,
Data
);
}
return Status;
}
/**
* SetVariable - Set/delete a UEFI variable in NVRAM.
*
* Supports authenticated variable writes, append mode, and
* automatic garbage collection on store exhaustion.
*/
EFI_STATUS
EFIAPI
NvDxeSetVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
EFI_STATUS Status;
NVRAM_VARIABLE_STORE *Store;
UINT64 VarOffset;
UINT64 VarSize;
UINT32 FoundAttribs;
UINT8 VarStateBuf[8];
BOOLEAN Found;
BOOLEAN AuthVarFlag;
UINT64 AuthVarSize;
UINT64 MaxDataSize;
UINT8 AuthFlag;
if (VariableName == NULL || *VariableName == 0 || VendorGuid == NULL) {
return EFI_INVALID_PARAMETER;
}
if ((Attributes & 0xFFFFFF80) != 0 || (Attributes & 6) == 4) {
return EFI_INVALID_PARAMETER;
}
Status = NvDxeValidateSetVariableParams (
VariableName, VendorGuid, Attributes, DataSize, Data
);
if (EFI_ERROR(Status)) {
return Status;
}
Store = (Attributes & 1) ? mPrimaryStore : mSecondaryStore;
if (mSmmCommunication != NULL && mSmmStarted) {
Status = NvDxeCheckPendingOperations (VariableName, VendorGuid);
if (Status == EFI_WRITE_PROTECTED) {
return Status;
}
}
Found = NvDxeFindVarEntry (
VariableName, VendorGuid,
&VarOffset, &VarSize, &FoundAttribs, VarStateBuf
);
if (Found) {
if (mDebugEnabled &&
(*(UINT32*)(VarOffset + 6) & 0x1000000) == 0) {
return EFI_NOT_FOUND;
}
if (Attributes & 2) {
UINT64 ExpectedStore = (Attributes & 1) ?
(UINT64)mPrimaryStore : (UINT64)mSecondaryStore;
if (VarOffset != ExpectedStore) {
return EFI_NOT_FOUND;
}
}
NvDxeDecryptVarHeader (VarOffset, VarStateBuf, 0);
AuthVarSize = NvDxeParseVarHeader (
VarOffset, VarSize, &MaxDataSize, FoundAttribs
);
} else {
if (VarOffset != 0) {
NvDxeDecryptVarHeader (VarOffset, VarStateBuf, VarSize);
AuthVarSize = NvDxeParseVarHeader (
VarOffset, VarSize, &MaxDataSize, FoundAttribs
);
} else {
MaxDataSize = 0;
AuthVarSize = 0;
}
Store = (Attributes & 1) ? mPrimaryStore : mSecondaryStore;
if (Store == NULL) {
return EFI_NOT_FOUND;
}
}
Status = NvDxeCheckStoreLock (Store);
if (Status == EFI_ACCESS_DENIED) return Status;
if (Status == EFI_NOT_READY) return EFI_OUT_OF_RESOURCES;
if ((UINT64)NvDxeGetStoreFreeSpace (Store->StoreBase) > Store->StoreSize) {
return EFI_VOLUME_CORRUPTED;
}
AuthVarFlag = NvDxeIsAuthVariableNeeded (VariableName, VendorGuid);
if ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0 && MaxDataSize == 0) {
if (!Found) {
return EFI_SUCCESS;
}
if (mDebugEnabled &&
(*(UINT8*)((UINT8*)Store + 56) & 1) == 0) {
return EFI_NOT_FOUND;
}
if (AuthVarFlag) {
return EFI_WRITE_PROTECTED;
}
{
UINT8 StoreBit;
BOOLEAN WriteResult;
StoreBit = (*(UINT8*)(VarOffset + 9) ^ 0x80);
if (Store->FlushContext == NULL) {
return EFI_UNSUPPORTED;
}
WriteResult = ((BOOLEAN(*)(VOID*, UINT8*, UINTN, UINTN))
Store->FlushContext)(
Store->FlushContext,
(UINT8*)VarOffset + 9,
1,
StoreBit
);
if (!WriteResult) {
return EFI_OUT_OF_RESOURCES;
}
Status = NvDxeFlushVariableData (
Store, VariableName, VendorGuid,
Attributes, DataSize, Data
);
}
return Status;
}
Status = NvDxePerformSetVariable (
VariableName, VendorGuid, Attributes, DataSize, Data,
Store, VarOffset, MaxDataSize, AuthVarFlag, AuthVarSize
);
return Status;
}
/**
* Perform the actual variable write operation.
*/
STATIC
EFI_STATUS
NvDxePerformSetVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data,
IN NVRAM_VARIABLE_STORE *Store,
IN UINT64 VarOffset,
IN UINT64 MaxDataSize,
IN UINT8 AuthVarFlag,
IN UINT64 AuthVarSize
)
{
EFI_STATUS Status;
UINTN RetryCount;
if (AuthVarFlag) {
if (Store->FlushContext == NULL) {
return EFI_UNSUPPORTED;
}
Status = NvDxeSetAuthVariableSmm (
Store, VariableName, VendorGuid,
Attributes, DataSize, Data
);
if (!EFI_ERROR(Status)) {
NvDxeMailboxSync ();
}
return Status;
}
if (VarOffset == 0) {
if (DataSize == 0) {
return EFI_SUCCESS;
}
Status = NvDxeEncodeVariable (
VariableName, VendorGuid, Attributes,
DataSize, Data, Store
);
if (Status == EFI_OUT_OF_RESOURCES) {
RetryCount = 0;
while (RetryCount < 2) {
Status = NvDxeGarbageCollect (Store);
if (!EFI_ERROR(Status)) {
Status = NvDxeEncodeVariable (
VariableName, VendorGuid, Attributes,
DataSize, Data, Store
);
if (!EFI_ERROR(Status)) break;
}
RetryCount++;
}
}
if (!EFI_ERROR(Status) && Store->FlushContext != NULL) {
Status = NvDxeFlushVariableData (
Store, VariableName, VendorGuid,
Attributes, DataSize, Data
);
}
return Status;
}
return EFI_SUCCESS;
}
/**
* GetNextVariableName - Enumerate UEFI variables.
*/
EFI_STATUS
EFIAPI
NvDxeGetNextVariableName (
IN OUT UINTN *VariableNameSize,
IN OUT CHAR16 *VariableName,
IN OUT EFI_GUID *VendorGuid
)
{
EFI_STATUS Status;
Status = NvDxeCheckRuntimeState ();
if (Status != EFI_SUCCESS && Status != EFI_NOT_READY) {
return Status;
}
NvDxeCheckStoreState ();
if (!mRuntimeTransitioned) {
if (mSmmEstablished) {
Status = NvDxeGetNextVariableSmm (
VariableNameSize, VariableName, VendorGuid
);
} else {
Status = NvDxeNextVariableName (
mPrimaryStore,
VariableNameSize, VariableName, VendorGuid
);
}
} else {
Status = NvDxeNextVariableName (
mPrimaryStore,
VariableNameSize, VariableName, VendorGuid
);
}
return Status;
}
/**
* QueryVariableInfo - Get NVRAM store usage info.
*/
EFI_STATUS
EFIAPI
NvDxeQueryVariableInfo (
IN UINT32 Attributes,
OUT UINT64 *MaximumVariableStorageSize,
OUT UINT64 *RemainingVariableStorageSize,
OUT UINT64 *MaximumVariableSize
)
{
NVRAM_VARIABLE_STORE *Store;
UINT64 StoreDataSize;
UINT64 AvailableSize;
UINT64 MaxSize;
EFI_STATUS Status;
UINT64 TempBuffer[5];
if ((Attributes & 0xFFFFFF80) != 0 || (Attributes & 6) == 4) {
return EFI_INVALID_PARAMETER;
}
if (MaximumVariableStorageSize == NULL ||
RemainingVariableStorageSize == NULL ||
MaximumVariableSize == NULL) {
return EFI_INVALID_PARAMETER;
}
Store = (Attributes & 1) ? mPrimaryStore : mSecondaryStore;
if (Store == NULL || Store->StoreBase == 0) {
return EFI_NOT_FOUND;
}
StoreDataSize = Store->StoreEnd - Store->StoreBase;
Status = NvDxeQueryStoreBlocks (Store, TempBuffer);
if (EFI_ERROR(Status)) {
return Status;
}
AvailableSize = TempBuffer[0] + TempBuffer[1] -
16 * (TempBuffer[4] + 1) - TempBuffer[3];
NvDxeFreeStoreBlock (TempBuffer[0]);
*MaximumVariableStorageSize = StoreDataSize;
*RemainingVariableStorageSize = AvailableSize;
MaxSize = (AvailableSize < 0xFFFF) ? AvailableSize : 0xFFFF;
*MaximumVariableSize = (MaxSize < 26) ? 0 : (MaxSize - 26);
return EFI_SUCCESS;
}
/*===========================================================================
* Variable Search / Enumeration
*===========================================================================*/
/**
* Find a variable entry in the NVRAM store.
*/
STATIC
EFI_STATUS
NvDxeFindVariableInStore (
IN NVRAM_VARIABLE_STORE *Store,
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT UINT32 *Attributes OPTIONAL,
IN OUT UINTN *DataSize,
OUT VOID *Data OPTIONAL
)
{
UINT8 *CurrentEntry;
UINT64 RemainingSize;
if (Store == NULL || Store->CurrentPtr == 0) {
return EFI_NOT_FOUND;
}
CurrentEntry = (UINT8*)(UINTN)Store->CurrentPtr;
RemainingSize = Store->StoreEnd - Store->CurrentPtr;
if (CurrentEntry == NULL || RemainingSize == 0) {
return EFI_NOT_FOUND;
}
while (TRUE) {
NVRAM_VARIABLE_ENTRY *Entry = (NVRAM_VARIABLE_ENTRY*)CurrentEntry;
UINT32 EntryState = *(UINT32*)(&Entry->VariableInfo);
if (!NvDxeValidateVariableEntry (CurrentEntry, Store)) {
break;
}
if ((EntryState & 0x1000000) == 0) {
if (NvDxeCompareGuidEx ((UINT32*)&Entry->VendorGuidData0,
(UINT32*)VendorGuid)) {
UINT16 NameLen = *(UINT16*)(CurrentEntry + 4);
if (NameLen <= RemainingSize &&
NvDxeCompareName (
VariableName,
(CHAR16*)(CurrentEntry + sizeof(NVRAM_VARIABLE_ENTRY)),
NameLen)) {
UINTN DataOffset = (EntryState & 0x8000000) ?
sizeof(NVRAM_VARIABLE_ENTRY) + NameLen + 26 :
sizeof(NVRAM_VARIABLE_ENTRY) + NameLen + 11;
UINTN EntryDataSize = Entry->Length - (UINT16)DataOffset;
if (Data != NULL) {
if (*DataSize >= EntryDataSize) {
CopyMem (Data, CurrentEntry + DataOffset,
EntryDataSize);
} else {
*DataSize = EntryDataSize;
return EFI_BUFFER_TOO_SMALL;
}
}
if (Attributes != NULL) {
*Attributes = EntryState & 0xFFFFFF;
}
*DataSize = EntryDataSize;
return EFI_SUCCESS;
}
}
}
if (Entry->Length == 0) break;
CurrentEntry += Entry->Length;
if ((UINT64)CurrentEntry >= Store->StoreEnd) break;
}
return EFI_NOT_FOUND;
}
/**
* Get next variable name for enumeration.
*/
STATIC
EFI_STATUS
NvDxeNextVariableName (
IN NVRAM_VARIABLE_STORE *Store,
IN OUT UINTN *VariableNameSize,
IN OUT CHAR16 *VariableName,
IN OUT EFI_GUID *VendorGuid
)
{
return EFI_NOT_FOUND;
}
/*===========================================================================
* Validate Variable Entry Format
*===========================================================================*/
/**
* Validate a variable entry in the NVRAM store.
*/
STATIC
BOOLEAN
NvDxeValidateVariableEntry (
IN UINT8 *Entry,
IN NVRAM_VARIABLE_STORE *Store
)
{
UINT16 NameLength;
UINT32 EntryInfo;
NameLength = *(UINT16*)(Entry + 4);
if (NameLength > (Store->StoreEnd - (UINT64)Entry)) {
return FALSE;
}
if (*(UINT32*)(Entry) != 0x524F5252) {
return FALSE;
}
if (*(UINT8*)(Entry + 9) == 0xFF) {
return FALSE;
}
if (NameLength < 11 || NameLength > 0xFFFE) {
return FALSE;
}
EntryInfo = *(UINT32*)(Entry + 6);
if ((EntryInfo & 0xFFFFFF) != 0xFFFFFF) {
UINT32 DataOffset = (EntryInfo & 0x8000000) != 0 ?
NameLength + 26 : NameLength + 11;
UINT32 TotalSize = sizeof(NVRAM_VARIABLE_ENTRY) + DataOffset;
if (TotalSize > (Store->StoreEnd - (UINT64)Entry)) {
return FALSE;
}
}
if (EntryInfo & 0x10000000) {
UINT8 *NextEntry = NvDxeGetNextAuthVarEntry (Entry);
if ((NextEntry != NULL) && ((*NextEntry & 1) != 0)) {
if (EntryInfo & 0x80000000) {
return FALSE;
}
}
}
return TRUE;
}
/*===========================================================================
* SMM Communication
*===========================================================================*/
/**
* Register SMM variable handler for SMI communication.
*/
STATIC
EFI_STATUS
NvDxeRegisterSmiHandler (
VOID
)
{
EFI_STATUS Status;
if (mSmmVariableProtocol != NULL) {
return EFI_ALREADY_STARTED;
}
if (mSharedBuffer == NULL) {
return EFI_NOT_FOUND;
}
Status = mBootServices->LocateProtocol (
&gEfiSmmVariableProtocolGuid,
NULL,
&mSmmVariableProtocol
);
if (!EFI_ERROR(Status)) {
mSmmEstablished = TRUE;
if (mRuntimeServices != NULL) {
mRuntimeServices->SetVariable (
L"NvramSmiBuffer",
&gEfiNvramMailboxGuid,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
2,
(UINT8*)mSharedBuffer + 24
);
}
}
return Status;
}
/*===========================================================================
* Secure Boot Initialization
*===========================================================================*/
/**
* Initialize Secure Boot mode and variables.
* Sets SetupMode, SecureBoot, and SignatureSupport based on
* DeploymentModeNv variable.
*/
EFI_STATUS
NvDxeInitSecureBootVariables (
VOID
)
{
EFI_STATUS Status;
UINT8 SecureBootMode;
UINT32 Attributes;
BOOLEAN IsManufacturingMode;
UINTN VarSize;
UINT8 CurrentMode;
IsManufacturingMode = NvDxeIsManufacturingMode ();
SecureBootMode = 0;
VarSize = sizeof(SecureBootMode);
Status = NvDxeGetVariable (
L"DeploymentModeNv",
&gAmiGlobalVariableGuid,
NULL,
&VarSize,
&SecureBootMode
);
if (EFI_ERROR(Status)) {
SecureBootMode = IsManufacturingMode ? 0 : 1;
} else {
if (SecureBootMode >= 4) {
NvDxeAssert (
"e:\\hs\\AmiModulePkg\\SecureBoot\\AuthenticatedVariable\\AuthService.c",
382,
"mSecureBootMode < SecureBootModeTypeMax"
);
}
if (IsManufacturingMode) {
if (SecureBootMode == 1) SecureBootMode = 0;
if (SecureBootMode == 2) SecureBootMode = 3;
} else {
if (SecureBootMode == 0 || SecureBootMode == 3) {
SecureBootMode = 1;
}
}
}
CurrentMode = SecureBootMode;
if (EFI_ERROR(Status)) {
Status = NvDxeSetVariable (
L"DeploymentModeNv",
&gAmiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS,
sizeof(SecureBootMode),
&SecureBootMode
);
}
if (EFI_ERROR(Status)) return Status;
{
UINT8 SetupMode;
UINT8 *ModeTable = (UINT8*)&unk_13EB0;
SetupMode = ModeTable[6 * CurrentMode + 4];
Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS;
if (CurrentMode == 0) {
Attributes |= EFI_VARIABLE_NON_VOLATILE;
}
Status = NvDxeSetVariable (
L"SetupMode",
&gEfiGlobalVariableGuid,
Attributes,
1,
&SetupMode
);
if (!mDebugEnabled) {
NvDxeDebugPrint (64, "Init Var %s = %d, %r\n",
L"SetupMode", SetupMode, Status);
}
}
if (EFI_ERROR(Status)) return Status;
{
UINT8 SecureBootValue;
SecureBootValue = (IsManufacturingMode &&
*(UINT8*)&gEfiSecurityBootMode == 1) ? 1 : 0;
Status = NvDxeSetVariable (
L"SecureBoot",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
1,
&SecureBootValue
);
if (!mDebugEnabled) {
NvDxeDebugPrint (64, "Init Var %s = %d, %r\n",
L"SecureBoot", SecureBootValue, Status);
}
}
if (EFI_ERROR(Status)) return Status;
{
extern UINT8 gSignatureSupportData[0x90];
Status = NvDxeSetVariable (
L"SignatureSupport",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
0x90,
&gSignatureSupportData
);
}
return Status;
}
/*===========================================================================
* NVRAM Mailbox Protocol
*===========================================================================*/
/**
* Install the NvramMailBox protocol/notify mechanism.
*/
EFI_STATUS
NvDxeMailboxInstall (
VOID
)
{
EFI_STATUS Status;
UINT64 MailboxBuffer[3];
MailboxBuffer[0] = (UINT64)&mNvramStoreType;
MailboxBuffer[1] = (UINT64)NvDxeMailboxCallback;
MailboxBuffer[2] = (UINT64)&mMailboxState;
Status = NvDxeMailboxAddVariable (
L"NvramMailBox",
&gNvramMailboxGuid,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(MailboxBuffer),
MailboxBuffer
);
if (EFI_ERROR(Status)) {
Status = NvDxeMailboxAddVariable (
L"NvramMailBox", &gNvramMailboxGuid,
0, 0, MailboxBuffer
);
if (!EFI_ERROR(Status)) {
Status = NvDxeMailboxAddVariable (
L"NvramMailBox", &gNvramMailboxGuid,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(MailboxBuffer),
MailboxBuffer
);
}
}
return Status;
}
/**
* Mailbox callback: triggered when NvramMailBox state changes.
*/
STATIC
VOID
EFIAPI
NvDxeMailboxCallback (
IN UINT64 MailboxState
)
{
if (MailboxState & 1) {
if (mPrimaryStore != NULL) {
NvDxeStoreSync ((UINT64)mPrimaryStore);
NvDxeReclaimStore (mPrimaryStore);
}
}
if (MailboxState & 2) {
if (mSecondaryStore != NULL) {
NvDxeStoreSync ((UINT64)mSecondaryStore);
}
}
}
/*===========================================================================
* Event Notification Callbacks
*===========================================================================*/
STATIC
VOID
EFIAPI
NvDxeReadyToBootCallback (
IN EFI_EVENT Event,
IN VOID *Context
)
{
mRuntimeServicesReady = TRUE;
}
STATIC
VOID
EFIAPI
NvDxeVirtualAddressChangeCallback (
IN EFI_EVENT Event,
IN VOID *Context
)
{
mRuntimeTransitioned = TRUE;
EfiConvertPointer (0, (VOID**)&mBootServices);
EfiConvertPointer (0, (VOID**)&mRuntimeServices);
EfiConvertPointer (0, (VOID**)&mSystemTable);
EfiConvertPointer (0, (VOID**)&mImageHandle);
if (mSharedBuffer != NULL) {
EfiConvertPointer (0, (VOID**)&mSharedBuffer);
}
if (mPrimaryStore != NULL) {
EfiConvertPointer (0, (VOID**)&mPrimaryStore);
}
if (mSecondaryStore != NULL) {
EfiConvertPointer (0, (VOID**)&mSecondaryStore);
}
NvDxeConvertPointer ();
}
STATIC
VOID
EFIAPI
NvDxeSmmReadyToLockCallback (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
VOID *Registration;
Status = NvDxeMailboxInstall ();
if (!EFI_ERROR(Status)) {
mBootServices->RegisterProtocolNotify (
&gEfiSmmCommunicateHeaderGuid,
NvDxeSmmVariableReady,
&Registration
);
}
mSmmStarted = TRUE;
if (!mDebugEnabled) {
NvDxeDebugPrint (64, "NVRAM: SMM NVRAM ready\n");
}
}
/*===========================================================================
* NVRAM Garbage Collection
*===========================================================================*/
/**
* Perform garbage collection on NVRAM store.
*/
STATIC
EFI_STATUS
NvDxeGarbageCollect (
IN NVRAM_VARIABLE_STORE *Store
)
{
if (!mDebugEnabled) {
NvDxeDebugPrint (64, "NVRAM: NV Store Garbage Collection\n");
}
NvDxeLockStore (Store);
if (NvDxeGetStoreWorkspaceSize (Store->StoreBase) != 0) {
UINT32 WorkspaceSize = NvDxeGetWorkspaceSize (Store->StoreBase);
UINT32 TotalSize = WorkspaceSize + 24;
if (TotalSize != 0) {
if (TotalSize > 0 && Store->CurrentPtr != 0) {
UINT64 Base = Store->StoreBase;
Store->CurrentPtr = Base +
((Store->CurrentPtr - Base) ^ 1);
if (Store->CurrentPtr != 0) {
*(UINT32*)(Store->CurrentPtr + 23) = 0xFFFFFFFC;
}
}
NvDxeUnlockStore (Store);
return EFI_SUCCESS;
}
}
NvDxeUnlockStore (Store);
return EFI_OUT_OF_RESOURCES;
}
/**
* Reclaim (compact) the NVRAM store.
*/
STATIC
EFI_STATUS
NvDxeReclaimStore (
IN NVRAM_VARIABLE_STORE *Store
)
{
return NvDxeGarbageCollect (Store);
}
/*===========================================================================
* Runtime Transition
*===========================================================================*/
STATIC
VOID
NvDxeConvertPointer (
VOID
)
{
if (mDebugProtocol != NULL) {
EfiConvertPointer (0, (VOID**)&mDebugProtocol);
}
if (mNvramStoreBuffer != NULL) {
EfiConvertPointer (0, (VOID**)&mNvramStoreBuffer);
}
}
/*===========================================================================
* Platform Policy Helpers
*===========================================================================*/
STATIC
BOOLEAN
NvDxeIsHardwareErrorRecord (
IN CHAR16 *VariableName
)
{
return (NvDxeStrCmp (VariableName, L"HwErrRec") == 12);
}
STATIC
BOOLEAN
NvDxeIsSystemAccessVariable (
VOID
)
{
UINT32 Attributes;
UINT8 Value = 0;
UINTN DataSize = sizeof(Value);
EFI_STATUS Status = NvDxeGetVariable (
L"SystemAccess",
&gAmiDebugGuid,
&Attributes,
&DataSize,
&Value
);
return (!EFI_ERROR(Status) && Attributes == 2 && Value == 0);
}
EFI_STATUS
EFIAPI
NvDxeGetNextHighMonotonicCount (
OUT UINT32 *HighCount
)
{
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
NvDxeGetNextMonotonicCount (
OUT UINT32 *Count
)
{
return EFI_UNSUPPORTED;
}
/*===========================================================================
* Stubs for missing forward references
*
* These are platform-specific helper functions that would be
* implemented in the NVRAM common library (NvramDxeCommon.c)
* or the SMM wrapper (NvramSmmWrapper.c).
*===========================================================================*/
STATIC
UINT64
NvDxeCheckRuntimeState (
VOID
)
{
return EFI_SUCCESS;
}
STATIC
UINT16*
NvDxeGetHobList (
VOID
)
{
return NULL;
}
STATIC
UINT64
NvDxeGetNvStoreSizeFromHob (
VOID
)
{
return 0x80000;
}
STATIC
EFI_STATUS
NvDxeInitNvVariableStore (
VOID
)
{
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
NvDxeInitSmmVariableProtocol (
VOID
)
{
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
NvDxeVarStoreGetVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN OUT UINT64 *DataSize,
OUT VOID *Data OPTIONAL
)
{
return EFI_NOT_FOUND;
}
STATIC
EFI_STATUS
NvDxeValidateSetVariableParams (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
NvDxeCheckPendingOperations (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid
)
{
return EFI_SUCCESS;
}
STATIC
BOOLEAN
NvDxeFindVarEntry (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT UINT64 *VarOffset,
OUT UINT64 *VarSize,
OUT UINT32 *FoundAttribs,
OUT UINT8 *VarStateBuf
)
{
return FALSE;
}
STATIC
VOID
NvDxeDecryptVarHeader (
IN UINT64 VarOffset,
IN UINT8 *VarStateBuf,
IN UINT64 VarSize
)
{
}
STATIC
UINT64
NvDxeParseVarHeader (
IN UINT64 VarOffset,
IN UINT64 VarSize,
OUT UINT64 *MaxDataSize,
IN UINT32 FoundAttribs
)
{
*MaxDataSize = 0;
return 0;
}
STATIC
EFI_STATUS
NvDxeCheckStoreLock (
IN NVRAM_VARIABLE_STORE *Store
)
{
return EFI_SUCCESS;
}
STATIC
UINT64
NvDxeGetStoreFreeSpace (
IN UINT64 StoreBase
)
{
return 0x100000;
}
STATIC
BOOLEAN
NvDxeIsAuthVariableNeeded (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid
)
{
return FALSE;
}
STATIC
EFI_STATUS
NvDxeFlushVariableData (
IN NVRAM_VARIABLE_STORE *Store,
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
NvDxeSetAuthVariableSmm (
IN NVRAM_VARIABLE_STORE *Store,
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
return EFI_UNSUPPORTED;
}
STATIC
VOID
NvDxeMailboxSync (
VOID
)
{
}
STATIC
EFI_STATUS
NvDxeEncodeVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data,
IN NVRAM_VARIABLE_STORE *Store
)
{
return EFI_UNSUPPORTED;
}
STATIC
BOOLEAN
NvDxeIsManufacturingMode (
VOID
)
{
return FALSE;
}
STATIC
EFI_STATUS
NvDxeGetVariableSmm (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT UINT32 *Attributes OPTIONAL,
IN OUT UINTN *DataSize,
OUT VOID *Data OPTIONAL
)
{
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
NvDxeGetNextVariableSmm (
IN OUT UINTN *VariableNameSize,
IN OUT CHAR16 *VariableName,
IN OUT EFI_GUID *VendorGuid
)
{
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
NvDxeQueryStoreBlocks (
IN NVRAM_VARIABLE_STORE *Store,
OUT UINT64 *Buffer
)
{
return EFI_UNSUPPORTED;
}
STATIC
VOID
NvDxeFreeStoreBlock (
IN UINT64 Block
)
{
}
STATIC
BOOLEAN
NvDxeCompareGuidEx (
IN UINT32 *Guid1,
IN UINT32 *Guid2
)
{
return (Guid1[0] == Guid2[0] &&
Guid1[1] == Guid2[1] &&
Guid1[2] == Guid2[2] &&
Guid1[3] == Guid2[3]);
}
STATIC
BOOLEAN
NvDxeCompareName (
IN CHAR16 *Name,
IN CHAR16 *EntryName,
IN UINT16 NameLength
)
{
return FALSE;
}
STATIC
UINTN
NvDxeStrCmp (
IN CHAR16 *Str1,
IN CHAR16 *Str2
)
{
return 0;
}
STATIC
UINT8*
NvDxeGetNextAuthVarEntry (
IN UINT8 *Entry
)
{
return NULL;
}
STATIC
VOID
NvDxeLockStore (
IN NVRAM_VARIABLE_STORE *Store
)
{
}
STATIC
VOID
NvDxeUnlockStore (
IN NVRAM_VARIABLE_STORE *Store
)
{
}
STATIC
UINT32
NvDxeGetStoreWorkspaceSize (
IN UINT64 StoreBase
)
{
return 0;
}
STATIC
UINT32
NvDxeGetWorkspaceSize (
IN UINT64 StoreBase
)
{
return 0;
}
STATIC
EFI_STATUS
NvDxeMailboxAddVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
return EFI_UNSUPPORTED;
}
STATIC
VOID
NvDxeStoreSync (
IN UINT64 StoreHandle
)
{
}
STATIC
EFI_STATUS
NvDxeSetVariableFlags (
IN NVRAM_VARIABLE_STORE *Store,
IN UINT8 Flags
)
{
return EFI_SUCCESS;
}
STATIC
VOID
NvDxeResetNvramVariable (
VOID
)
{
}
STATIC
VOID
NvDxeSmmVariableReady (
IN EFI_EVENT Event,
IN VOID *Context
)
{
}
STATIC
BOOLEAN
NvDxeIsVariableGuidValid (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid
)
{
return TRUE;
}
STATIC
EFI_STATUS
NvDxeCheckSecureBootVariableAccess (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
NvDxeCreateVariableStore (
IN CHAR16 *Name,
IN EFI_GUID *Guid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
NvDxeDeleteVariable (
IN NVRAM_VARIABLE_STORE *Store,
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid
)
{
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
NvDxeUpdateVariable (
IN NVRAM_VARIABLE_STORE *Store,
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
NvDxeAddVariable (
IN NVRAM_VARIABLE_STORE *Store,
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
return EFI_SUCCESS;
}
STATIC
VOID
NvDxeInitSecureBootState (
IN BOOLEAN IsManufacturingMode
)
{
}
STATIC
EFI_STATUS
NvDxeCopyHobDataToStores (
IN UINT16 *HobData,
IN NVRAM_STORE_HEADER *StoreHeader,
IN UINT64 AllocSize
)
{
return EFI_SUCCESS;
}
STATIC
VOID
InitializeStoreWorkspace (
IN VOID *Workspace,
IN UINT8 *Base,
IN UINT64 Size
)
{
}
STATIC
NVRAM_WORKSPACE_DESC mStoreWorkspaces[3];
/*===========================================================================
* Entry Point
*===========================================================================*/
/**
* NvramDxe entry point.
*
* Initializes the NVRAM variable driver:
* 1. Saves UEFI handles and boot/runtime service pointers
* 2. Initializes debug protocol
* 3. Registers event callbacks for virtual address change
* 4. Initializes variable store / SMM protocol
* 5. Checks NVRAM compatibility, resets if incompatible
* 6. Initializes Secure Boot variables (SetupMode, SecureBoot)
* 7. Allocates NVRAM stores
* 8. Installs NVRAM mailbox protocol
* 9. Overrides runtime service variable functions
* (GetVariable, SetVariable, GetNextVariableName,
* QueryVariableInfo, GetNextHighMonotonicCount)
* 10. Overrides boot service monotonic count
* 11. Registers ready-to-boot and SMM ready events
*
* @param[in] ImageHandle Driver image handle
* @param[in] SystemTable UEFI system table
* @return EFI_SUCCESS Driver initialized successfully
*/
EFI_STATUS
EFIAPI
NvramDxeEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
VOID *Registration;
//
// 1. Save global UEFI handles
//
mImageHandle = ImageHandle;
mSystemTable = SystemTable;
mBootServices = SystemTable->BootServices;
mRuntimeServices = SystemTable->RuntimeServices;
gST = SystemTable;
gBS = mBootServices;
gRT = mRuntimeServices;
gImageHandle = ImageHandle;
//
// 2. Initialize debug protocol
//
NvDxeInitDebugProtocol ();
//
// 3. Increment reference counts
//
mBootServiceRefCount++;
mRuntimeServiceRefCount++;
//
// 4. Register events
//
Status = mBootServices->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
NvDxeVirtualAddressChangeCallback,
NULL,
&mVirtAddrChangeEvent
);
Status = mBootServices->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
NvDxeVirtualAddressChangeCallback,
NULL,
&mSmmReadyToLockEvent
);
//
// 5. Initialize variable store
//
NvDxeInitNvVariableStore ();
Status = NvDxeInitSmmVariableProtocol ();
if (EFI_ERROR(Status)) {
NvDxeDebugPrint (
0x80000000,
"\nASSERT_EFI_ERROR (Status = %r)\n",
Status
);
return Status;
}
//
// 6. Check NVRAM compatibility
//
if (!NvDxeIsCompatibleNvram ()) {
NvDxeDebugPrint (
0x80000000,
"NVRAM DXE: Incompatible NVRAM detected\n"
);
NvDxeResetNvramVariable ();
NvDxeSetVariableFlags (mPrimaryStore, 1);
}
//
// 7. Initialize Secure Boot variables
//
Status = NvDxeInitSecureBootVariables ();
if (EFI_ERROR(Status)) {
return Status;
}
//
// 8. Allocate and initialize stores
//
Status = NvDxeInitializeStores ();
if (EFI_ERROR(Status)) {
return Status;
}
//
// 9. Install NVRAM mailbox protocol
//
mMailboxState = 0;
Status = NvDxeMailboxInstall ();
if (EFI_ERROR(Status)) {
Status = NvDxeMailboxInstall ();
}
//
// 10. Register ready-to-boot and SMM ready events
//
{
EFI_EVENT ReadyToBootEvent;
mBootServices->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
NvDxeReadyToBootCallback,
NULL,
&gEfiEventReadyToBootGuid,
&ReadyToBootEvent
);
}
{
EFI_EVENT SmmReadyEvent;
mBootServices->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
NvDxeSmmReadyToLockCallback,
NULL,
&gEfiSmmReadyToLockProtocolGuid,
&SmmReadyEvent
);
}
//
// 11. Register protocol notifications
//
mBootServices->RegisterProtocolNotify (
&gEfiVariableArchGuid,
NvDxeReadyToBootCallback,
&Registration
);
mBootServices->RegisterProtocolNotify (
&gEfiVariableWriteArchGuid,
NvDxeSmmReadyToLockCallback,
&Registration
);
//
// 12. Override runtime variable services
//
*(UINT64*)((UINT8*)mRuntimeServices + 72) = (UINT64)NvDxeGetVariable;
*(UINT64*)((UINT8*)mRuntimeServices + 80) = (UINT64)NvDxeSetVariable;
*(UINT64*)((UINT8*)mRuntimeServices + 88) = (UINT64)NvDxeGetNextVariableName;
*(UINT64*)((UINT8*)mRuntimeServices + 128) = (UINT64)NvDxeQueryVariableInfo;
*(UINT64*)((UINT8*)mRuntimeServices + 144) = (UINT64)NvDxeGetNextHighMonotonicCount;
*(UINT64*)((UINT8*)mBootServices + 328) = (UINT64)NvDxeGetNextMonotonicCount;
//
* 13. Initialize monotonic counter
//
NvDxeGetNextHighMonotonicCount ((UINT32*)&mVirtAddrChangeEvent);
//
* 14. Final registration
//
mBootServices->RegisterProtocolNotify (
&gEfiEventVirtualAddressChangeGuid,
NULL,
Registration
);
return EFI_SUCCESS;
}