diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/NVRAM | |
download | zprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz |
Diffstat (limited to 'Core/EM/NVRAM')
-rw-r--r-- | Core/EM/NVRAM/NVRAM.chm | bin | 0 -> 89864 bytes | |||
-rw-r--r-- | Core/EM/NVRAM/NVRAM.cif | 14 | ||||
-rw-r--r-- | Core/EM/NVRAM/NVRAM.h | 490 | ||||
-rw-r--r-- | Core/EM/NVRAM/NVRAM.mak | 225 | ||||
-rw-r--r-- | Core/EM/NVRAM/NVRAM.sdl | 65 | ||||
-rw-r--r-- | Core/EM/NVRAM/NVRAMDXE.c | 5719 | ||||
-rw-r--r-- | Core/EM/NVRAM/NVRAMPEI.c | 584 | ||||
-rw-r--r-- | Core/EM/NVRAM/NVRAMRead.c | 1508 |
8 files changed, 8605 insertions, 0 deletions
diff --git a/Core/EM/NVRAM/NVRAM.chm b/Core/EM/NVRAM/NVRAM.chm Binary files differnew file mode 100644 index 0000000..19c9c5b --- /dev/null +++ b/Core/EM/NVRAM/NVRAM.chm diff --git a/Core/EM/NVRAM/NVRAM.cif b/Core/EM/NVRAM/NVRAM.cif new file mode 100644 index 0000000..b17adef --- /dev/null +++ b/Core/EM/NVRAM/NVRAM.cif @@ -0,0 +1,14 @@ +<component> + name = "NVRAM" + category = ModulePart + LocalRoot = "Core\EM\NVRAM\" + RefName = "NVRAM" +[files] +"NVRAM.chm" +"NVRAM.sdl" +"NVRAM.mak" +"NVRAM.h" +"NVRAMRead.c" +"NVRAMPEI.c" +"NVRAMDXE.c" +<endComponent> diff --git a/Core/EM/NVRAM/NVRAM.h b/Core/EM/NVRAM/NVRAM.h new file mode 100644 index 0000000..a7a892b --- /dev/null +++ b/Core/EM/NVRAM/NVRAM.h @@ -0,0 +1,490 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/Modules/NVRAM/NVRAM.h 28 11/29/12 5:10p Felixp $ +// +// $Revision: 28 $ +// +// $Date: 11/29/12 5:10p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Modules/NVRAM/NVRAM.h $ +// +// 28 11/29/12 5:10p Felixp +// Minor improvement: Since UEFI Specification versions prior to 2.1 +// (0x2000A) are no longer supported, +// all the "#if EFI_SPECIFICATION_VERSION >= 0x2000A" conditional +// compilation statements are removed. +// Files modified: NVRAM.h, NVRAMRead.c, NVRAMDXE.c +// +// 27 11/29/12 3:27p Felixp +// Nvram.h, NvramDxe.c: +// 1. Bug Fix (EIP106441): The Authenticated Variable SCT test was +// failing due to a +// bug in UpdateVariable function. The function was skipping the +// update if new variable data +// is equal to the old variable data. The update should not be skipped +// in case of the append operation +// (when EFI_VARIABLE_APPEND_WRITE attribute is set). +// The function is updated accordingly. +// 2. Bug fix: External declaration for the FlashEmpty variable declared +// variable type as UINT32, +// even though the variable is defined in Tokenc.c as UINTN. +// +// 26 11/07/12 4:13p Oleksiyy +// [TAG] EIP99114 +// [Category] New Feature +// [Description] Please make state of "Runtime" variable used in +// NvramDxe.c globally available +// [Files] NVRAM.h and NVRAMDXE.c +// +// 25 7/13/11 9:24a Justinj +// [TAG] EIP62762 +// [Category] Improvement +// [Description] Optimize NVRAM cache index so that the entire linked +// list is not walked every time a variable is set or retrieved. +// [Files] NVRAM.h +// NVRAMRead.c +// NVRAMDXE.c +// +// 24 5/13/11 5:44p Artems +// Added CheckStore function definition +// +// 23 5/13/11 5:22p Artems +// Minor code beautification change +// +// 22 5/11/11 6:34p Oleksiyy +// [TAG] EIP60206 +// [Category] Improvement +// [Description] Authenticated Variables improvement. +// NV_CACHE_SUPPORT == O support added. +// [Files] NVRAMDXE.c and NVRAM.h +// +// 21 5/09/11 11:04a Artems +// Minor code beautification change +// +// 19 9/30/10 4:35p Oleksiyy +// Issue Number: 40356 and 39462 +// +// Category: New Feature +// +// Description: Support for EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS +// Small fix of previously checked in code. +// +// Files: NVRAM. h, NVRAMRead.c, NVRAMDXE.c +// +// 18 9/22/10 6:39p Felixp +// Enhancement(EIP 39462 and EIP 40356): +// Support of the authenticated update of the NVRAM variables +// as described in UEFI specification version 2.1 and above. +// NOTE: The actual authentication is performed by the external SecureMod +// eModule, +// which must be in the proejct to use this feature. +// +// 17 12/04/09 12:27p Felixp +// NvarEqNvar function is added +// +// 16 11/23/09 4:44p Felixp +// Code to validate NVRAM header fields used by the NVRAM driver is added. +// If problem is found, the header fields are updated with the correct +// values. +// +// 15 11/20/09 4:06p Felixp +// NVRAM driver is updated to support UEFI2.1 +// EFI_VARIABLE_HARDWARE_ERROR_RECORD attribue. +// +// 14 8/25/09 4:11p Felixp +// NVRAM Record Checksum Support(EIP 23825) is added. +// Disabled by default. Enable using NVRAM_RECORD_CHECKSUM_SUPPORT SDL +// token. +// +// 13 6/26/09 3:28p Felixp +// +// 12 6/26/09 3:27p Felixp +// New IsMainNvramStoreValid function is added. +// The function detects is main NVRAM or backup NVRAM is currently active +// (returns FALSE when backup is active). +// +// 11 10/09/08 11:47a Felixp +// 1. Fault tolerant NVRAM garbage collection support is added. +// Use FAULT_TOLERANT_NVRAM_UPDATE SDL token to enable/disable (disabled +// by default). +// NOTE: This feature requires upgrade of the Board module. +// NOTE: This feature requires porting: +// Fault tolerant update requires reserved flash area of size NVRAM_SIZE +// used for back up during NVRAM garbage collection. +// The address of the area is defined by NVRAM_BACKUP_ADDRESS SDL token +// defined in Board.sdl. +// Size and Base addresses of other firmware volumes may need to be +// adjusted to free up space for the NVRAM back up area. +// Default ROM layout expects NVRAM back up area immediately below the +// main NVRAM area. +// For projects with the customized ROM layout Core.mak has to be updated. +// 2. Top level NVRAM function updated to be reentrance-safe. +// NOTE: This feature requires upgrade of the SB module. +// 3. Improved recovery from the flash programming failures and +// corruptions within NVRAM area. +// 4. More reliable non-fault tolerant garbage collection. +// +// 10 9/06/07 12:14a Felixp +// +// 9 8/31/07 3:44p Felixp +// NVRAM code has been significantly changed to introduce the following +// improvements: +// 1. The code is chaned to always use the same amount of memory. +// Previous implementation allocated memory as needed, which caused +// occasional S4 problems. +// Plus S4 resume never worked during the very first boot after the +// firmware update. +// 2. Support for NVRAM defaults added. +// NVRAM image with the default values for the Setup variables is now +// generated by the build process. +// The image is generated by the HpkTool (included into AMITSE module +// part). +// In addition to standard Setup defaults it is also possible +// to generate manufactoring defaults. Support for the manufactoring +// defaults +// is disabled by default and can be enabled using +// MANUFACTURING_MODE_SUPPORT SDL token. +// 3. Support for boot with alternative configurations is added. +// Decision to switch to the alternative configuration +// (alternative set of values for NVRAM variables) +// is based on values returned by the porintg routine in OemPort.c. +// During boot with alternative configurations GetVariable service +// returns alternative values for the setup-related variables. +// If variable does not have an alternative value, current value is +// returned. +// Two alternative configurations are supported: +// Boot with manufactoring settings(activated when IsMfgMode routine in +// OemPort.c returns TRUE). +// Boot with default settings(activated when IsDefaultConfigMode routine +// in OemPort.c returns TRUE). +// NOTE: This feature requires of the Board module +// 4.NVRAM reset option is added. +// If porting routine IsResetConfigMode in OemPort.c returns TRUE in PEI +// phase, +// NVRAM content will be reset during initialization of the DXE NVRAM +// driver. +// During reset operation all setup-related variables are reset to their +// default values. +// All other variables are deleted. +// NOTE: This feature requires upgrade of the Board module +// 5.Detection of NVRAM update added. +// NVRAM implementation detects if NVRAM has been updated since the last +// NVRAM call. +// This provides ability to use variables services before and after +// firmware update. +// 6.Overall code clean up and simplification. +// 7.Core Sources are no longer required in order to use NV_SIMULATION +// option. +// 8.PI 1.0 support. +// Support for a PI 1.0 complient variable PPI is added. Old PPI is still +// preserved in this label for backward compatibility. +// New library routines PeiGetVariable and PeiGetNextVariableName are +// created in order to hide the differences between two PPIs. +// It is recommended to update existing code to use new library routines. +// Support of the old PPI may be dropped in the future versions of Core. +// 9. NVRAM is now packaged as a raw FFS file embedded into the standard +// FV (used to be non-standard FV with raw NVRAM image). +// Validation: New NVRAM code has been validated using SCT and EFI version +// of Windows Server 2008 +// Files modified: Core.sdl, Core.mak, AmiPeiLib.h, PeiLib.c, +// ReadOnlyVariable.h, , Token.c, HpkTool.exe, AMITSE.mak, Setup.ini, +// NVRAM.sdl, NVRAM.mak, NVRAM.h, NVRAMRead.c, NVRAMPEI.c, +// NVRAMDXE.c +// +// 8 5/01/07 6:06p Felixp +// Clean up +// +// 7 3/18/07 4:08p Felixp +// 1. IsNvramBlock function declaration added +// 2. Clean up +// +// 6 12/29/06 3:02p Felixp +// Update to use new flash interface +// +// 5 12/20/06 1:33p Felixp +// Bug fix in BLOCK macro +// +// 4 10/27/06 11:45a Felixp +// +// 3 10/27/06 10:42a Felixp +// Bug fixes for correct work in Virtual Address Space. +// +// 2 10/23/06 7:03p Felixp +// 1. Virtual address space fixup of the global variables added +// 2. NVRAM simulation support +// +// 1 8/24/06 12:38p Felixp +// +// 4 3/22/05 9:51p Felixp +// sAmiRomFile added +// +// 3 3/22/05 8:59p Felixp +// FlashSize variable added +// +// 2 3/04/05 9:40a Mandal +// +// 1 1/28/05 12:44p Felixp +// +// 3 1/20/05 11:37a Felixp +// Component restructurized to support release in binary format +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/27/04 4:08p Felixp +// +// 8 12/09/04 9:02p Felixp +// minor iprovements +// +// 7 8/28/04 1:49a Felixp +// NVRAM Routines fixes +// +// +// 1 3/29/04 2:32a Felixp +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: NVRAM.h +// +// Description: NVRAM Definitions +// +//<AMI_FHDR_END> +//********************************************************************** +#ifndef __NVRAM__H__ +#define __NVRAM__H__ +#ifdef __cplusplus +extern "C" { +#endif +#include <AmiLib.h> +#include <Flash.h> +#include <Hob.h> +#include <Ffs.h> + +#define FLASH_EMPTY_BYTE ((UINT8)FlashEmpty) +#define FLASH_EMPTY_FLAG FLASH_EMPTY_BYTE +#define FLASH_EMPTY_NEXT FlashEmptyNext +#define FLASH_EMPTY_SIGNATURE ((UINT32)FlashEmpty) +#define FLASH_EMPTY_SIZE ((VAR_SIZE_TYPE)FlashEmpty) + +#define NVRAM_FLAG_VALID 0x80 +#define NVRAM_FLAG_RUNTIME 1 +#define NVRAM_FLAG_ASCII_NAME 2 +#define NVRAM_FLAG_GUID 4 +#define NVRAM_FLAG_DATA_ONLY 8 +#define NVRAM_FLAG_EXT_HEDER 0x10 +#define NVRAM_FLAG_AUTH_WRITE 0x40 +#define NVRAM_FLAG_HARDWARE_ERROR_RECORD 0x20 +#define UEFI21_SPECIFIC_NVRAM_FLAGS (NVRAM_FLAG_HARDWARE_ERROR_RECORD | NVRAM_FLAG_AUTH_WRITE) +#define UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES \ + (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) + +#define NVRAM_EXT_FLAG_CHECKSUM 1 + +#define NVRAM_eFLAG_AUTH_WRITE EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS //0x10 +#define NVRAM_eFLAG_TIME_BASED_AUTH_WRITE EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS //0x20 + +#define ALL_FLAGS (NVRAM_FLAG_VALID | NVRAM_FLAG_RUNTIME |\ + NVRAM_FLAG_ASCII_NAME | NVRAM_FLAG_GUID|\ + NVRAM_FLAG_DATA_ONLY | NVRAM_FLAG_EXT_HEDER|\ + UEFI21_SPECIFIC_NVRAM_FLAGS\ + ) + +#define NVAR_SIGNATURE ('N'+('V'<<8)+(('A'+('R'<<8))<<16))//NVAR + +// {C0EC00FD-C2F8-4e47-90EF-9C8155285BEC} +#define NVRAM_HOB_GUID \ + { 0xc0ec00fd, 0xc2f8, 0x4e47, { 0x90, 0xef, 0x9c, 0x81, 0x55, 0x28, 0x5b, 0xec } } + +#define NVRAM_MODE_MANUFACTORING 1 +#define NVRAM_MODE_RESET_CONFIGURATION 2 +#define NVRAM_MODE_DEFAULT_CONFIGURATION 4 +#define NVRAM_MODE_SIMULATION 8 + +#define NVRAM_STORE_FLAG_NON_VALATILE 1 +#define NVRAM_STORE_FLAG_READ_ONLY 2 +#define NVRAM_STORE_FLAG_DO_NOT_ENUMERATE 4 + +extern const UINTN FlashEmpty; +extern const UINT32 FlashEmptyNext; +extern const EFI_GUID AmiDefaultsVariableGuid; +extern const EFI_GUID AmiNvramHobGuid; +extern const CHAR16 MfgDefaults[]; +extern const CHAR16 StdDefaults[]; +extern const UINT32 NvramHeaderLength; + +typedef UINT16 VAR_SIZE_TYPE; +#define NEXT_OFFSET (EFI_FIELD_OFFSET(NVAR,size)+sizeof(VAR_SIZE_TYPE)) +#define NEXT_SIZE 3 +#define FLAG_SIZE 1 +#define FLAG_OFFSET (NEXT_OFFSET + NEXT_SIZE) +#define MAX_NVRAM_VARIABLE_SIZE ((1<<(sizeof(VAR_SIZE_TYPE)<<3))-1) +#pragma pack(push) +#pragma pack(1) +typedef struct{ + UINT32 signature; + VAR_SIZE_TYPE size; + UINT32 next:24; + UINT32 flags:8; +// guid and name are there only if NVRAM_FLAG_DATA_ONLY is not set +// UINT8 guid; +// CHAR8 or CHAR16 name[...]; +// UINT8 data[...]; +// if NVRAM_FLAG_EXT_HEDER is set +// UINT8 extflags; +// UINT8 extdata[...]; +// VAR_SIZE_TYPE extsize; +}NVAR; + +typedef struct { + EFI_HOB_GUID_TYPE Header; + EFI_PHYSICAL_ADDRESS NvramAddress; + EFI_PHYSICAL_ADDRESS BackupAddress; + UINT32 NvramSize; + UINT32 HeaderLength; + UINT32 NvramMode; +} NVRAM_HOB; +#pragma pack(pop) + +typedef struct { + UINT8 *NvramAddress; + UINTN NvramSize; + EFI_GUID* NvramGuidsAddress; + UINT8 *pEndOfVars, *pFirstVar; + INT16 NextGuid; + VAR_SIZE_TYPE LastVarSize; + NVAR *pLastReturned; + UINT8 Flags; +} NVRAM_STORE_INFO; + +//Low level access routines +EFI_GUID* NvGetGuid(NVAR* pVar, NVRAM_STORE_INFO *pInfo); +VOID* NvGetName(NVAR* pVar); +NVAR* NvGetDataNvar(NVAR *pVar, NVRAM_STORE_INFO *pInfo); +VOID* NvGetData(NVAR* pVar, UINTN NameLength, UINTN* pDataSize, NVRAM_STORE_INFO *pInfo); + +//Validation routines +BOOLEAN NvIsVariable(NVAR *pVar, NVRAM_STORE_INFO *pInfo); +BOOLEAN NvIsValid(NVAR* pVar); + +//Iteration routines +NVAR* NvGetNextNvar(NVAR* pVar, NVRAM_STORE_INFO *pInfo); +NVAR* NvGetNextValid(NVAR* pVar, NVRAM_STORE_INFO *pInfo); + +//Comparison routines +BOOLEAN NvAttribEq(NVAR* pNvar, UINT32 Attributes, NVRAM_STORE_INFO *pInfo); +BOOLEAN NvVarEq(NVAR* pNvar, CHAR16* sName, EFI_GUID* pGuid, UINTN* pNameSize, NVRAM_STORE_INFO *pInfo); +BOOLEAN NvarEqNvar(NVAR *Nvar1, NVRAM_STORE_INFO *Info1, NVAR *Nvar2, NVRAM_STORE_INFO *Info2); + +//High level routines that work with a single NV store +VOID* NvFindVariable(CHAR16* sName, EFI_GUID* pGuid, UINTN* pNameSize, NVRAM_STORE_INFO *pInfo); +EFI_STATUS NvGetVariable( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, OUT VOID *Data, + NVRAM_STORE_INFO *pInfo, OUT NVAR **Var OPTIONAL +); +EFI_STATUS NvGetNextVariableName( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid, + NVRAM_STORE_INFO *pInfo, BOOLEAN Runtime +); + +//High level routines that work with a multiple NV stores +EFI_STATUS NvGetVariable2( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, OUT VOID *Data, + UINT32 InfoCount, NVRAM_STORE_INFO *pInfo +); +EFI_STATUS NvGetNextVariableName2( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid, + UINT32 InfoCount, NVRAM_STORE_INFO *pInfo, UINT32 *LastInfoIndex, + BOOLEAN Runtime +); + +//Service routines +VOID NvInitInfoBuffer(IN NVRAM_STORE_INFO *pInfo, UINTN HeaderSize, UINT8 Flags); +NVRAM_STORE_INFO* NvGetDefaultsInfo( + IN const CHAR16* DefaultsVar, + IN NVRAM_STORE_INFO *pInInfo, OUT NVRAM_STORE_INFO *pOutInfo +); +EFI_STATUS NvGetAttributesFromNvar( + IN NVAR *pNvar, IN NVRAM_STORE_INFO *pInfo, + OUT UINT32 *Attributes +); +EFI_STATUS NvGetVariableFromNvar( + NVAR *pNvar, UINTN NameSize, OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, OUT VOID *Data, + IN NVRAM_STORE_INFO *pInfo, OUT UINT8 *Flags OPTIONAL +); +EFI_FFS_FILE_STATE* GetNvramFfsFileStatePtr(NVRAM_STORE_INFO *Info); +EFI_FFS_FILE_STATE GetNvramFfsFileState(NVRAM_STORE_INFO *Info); +BOOLEAN IsMainNvramStoreValid( + NVRAM_STORE_INFO *MainInfo, VOID *BackUpAddress, + BOOLEAN *BackupStoreValid +); + +UINT8 NvCalculateNvarChecksum(NVAR* pVar); +UINT8* NvGetExtFlags (NVAR* pVar); + +// Shared with AuthVariable service +typedef struct { + UINT8 AuthFlags; // AuthWriteAccess = 0x10 and TimeWriteAccess = 0x20 + UINT64 Mc; + UINT8 KeyHash[32]; // sha256 +}EXT_SEC_FLAGS; + +VOID +GetVarAuthExtFlags( + IN NVAR *Var, + IN NVRAM_STORE_INFO *pInfo, + OUT EXT_SEC_FLAGS *ExtFlags +); + +EFI_STATUS FindVariable( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes , + IN OUT UINTN *DataSize, OUT VOID **Data +); + +VOID CheckStore( + IN BOOLEAN Recover +); + +BOOLEAN IsNvramRuntime(); + +/****** DO NOT WRITE BELOW THIS LINE *******/ +#ifdef __cplusplus +} +#endif +#endif +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//**********************************************************************
\ No newline at end of file diff --git a/Core/EM/NVRAM/NVRAM.mak b/Core/EM/NVRAM/NVRAM.mak new file mode 100644 index 0000000..43d544b --- /dev/null +++ b/Core/EM/NVRAM/NVRAM.mak @@ -0,0 +1,225 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (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/Core/Modules/NVRAM/NVRAM.mak 12 1/14/14 5:45p Oleksiyy $ +# +# $Revision: 12 $ +# +# $Date: 1/14/14 5:45p $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Core/Modules/NVRAM/NVRAM.mak $ +# +# 12 1/14/14 5:45p Oleksiyy +# [TAG] EIP121524 +# [Category] New Feature +# [Description] Extended Aptio functionality for clearing or restoring +# NVRAM to factory default state (preserving only selected Vars). +# [Files] NVRAM.sdl +# NVRAM.mak +# NVRAMDXE.c +# NVRAM.cif +# +# 11 11/07/12 5:42p Oleksiyy +# [TAG] EIP98678 +# [Category] Improvement +# [Description] GetVariable() response slow. Added token to process +# only SetVariable through SMI. +# [Files] NvramSmi.c, NvramSmi.sdl and NVRAM.mak +# +# 10 11/11/11 3:23p Felixp +# Set DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME macro when NvramSmi +# eModule is in the project. +# +# 9 2/04/10 3:58p Felixp +# Hook eLinks are renamed +# +# 8 2/02/10 5:14p Oleksiyy +# EIP 33263 : Hooks for SetVariable, GetVariable and GetNextVarName +# added +# +# 7 5/01/09 6:13p Felixp +# Bug fix(EIP 19816). $(AMICSPLib) is no longer linked with NVRAM +# libraries. +# (it caused problems on systems without Core Sources). +# $(AMICSPLib) is linked with Runtime and CORE_PEI instead. +# +# 6 10/09/08 11:47a Felixp +# 1. Fault tolerant NVRAM garbage collection support is added. +# Use FAULT_TOLERANT_NVRAM_UPDATE SDL token to enable/disable (disabled +# by default). +# NOTE: This feature requires upgrade of the Board module. +# NOTE: This feature requires porting: +# Fault tolerant update requires reserved flash area of size NVRAM_SIZE +# used for back up during NVRAM garbage collection. +# The address of the area is defined by NVRAM_BACKUP_ADDRESS SDL token +# defined in Board.sdl. +# Size and Base addresses of other firmware volumes may need to be +# adjusted to free up space for the NVRAM back up area. +# Default ROM layout expects NVRAM back up area immediately below the +# main NVRAM area. +# For projects with the customized ROM layout Core.mak has to be updated. +# 2. Top level NVRAM function updated to be reentrance-safe. +# NOTE: This feature requires upgrade of the SB module. +# 3. Improved recovery from the flash programming failures and +# corruptions within NVRAM area. +# 4. More reliable non-fault tolerant garbage collection. +# +# 5 9/06/07 12:14a Felixp +# +# 4 8/31/07 3:44p Felixp +# NVRAM code has been significantly changed to introduce the following +# improvements: +# 1. The code is chaned to always use the same amount of memory. +# Previous implementation allocated memory as needed, which caused +# occasional S4 problems. +# Plus S4 resume never worked during the very first boot after the +# firmware update. +# 2. Support for NVRAM defaults added. +# NVRAM image with the default values for the Setup variables is now +# generated by the build process. +# The image is generated by the HpkTool (included into AMITSE module +# part). +# In addition to standard Setup defaults it is also possible +# to generate manufactoring defaults. Support for the manufactoring +# defaults +# is disabled by default and can be enabled using +# MANUFACTURING_MODE_SUPPORT SDL token. +# 3. Support for boot with alternative configurations is added. +# Decision to switch to the alternative configuration +# (alternative set of values for NVRAM variables) +# is based on values returned by the porintg routine in OemPort.c. +# During boot with alternative configurations GetVariable service +# returns alternative values for the setup-related variables. +# If variable does not have an alternative value, current value is +# returned. +# Two alternative configurations are supported: +# Boot with manufactoring settings(activated when IsMfgMode routine in +# OemPort.c returns TRUE). +# Boot with default settings(activated when IsDefaultConfigMode routine +# in OemPort.c returns TRUE). +# NOTE: This feature requires of the Board module +# 4.NVRAM reset option is added. +# If porting routine IsResetConfigMode in OemPort.c returns TRUE in PEI +# phase, +# NVRAM content will be reset during initialization of the DXE NVRAM +# driver. +# During reset operation all setup-related variables are reset to their +# default values. +# All other variables are deleted. +# NOTE: This feature requires upgrade of the Board module +# 5.Detection of NVRAM update added. +# NVRAM implementation detects if NVRAM has been updated since the last +# NVRAM call. +# This provides ability to use variables services before and after +# firmware update. +# 6.Overall code clean up and simplification. +# 7.Core Sources are no longer required in order to use NV_SIMULATION +# option. +# 8.PI 1.0 support. +# Support for a PI 1.0 complient variable PPI is added. Old PPI is still +# preserved in this label for backward compatibility. +# New library routines PeiGetVariable and PeiGetNextVariableName are +# created in order to hide the differences between two PPIs. +# It is recommended to update existing code to use new library routines. +# Support of the old PPI may be dropped in the future versions of Core. +# 9. NVRAM is now packaged as a raw FFS file embedded into the standard +# FV (used to be non-standard FV with raw NVRAM image). +# Validation: New NVRAM code has been validated using SCT and EFI version +# of Windows Server 2008 +# Files modified: Core.sdl, Core.mak, AmiPeiLib.h, PeiLib.c, +# ReadOnlyVariable.h, , Token.c, HpkTool.exe, AMITSE.mak, Setup.ini, +# NVRAM.sdl, NVRAM.mak, NVRAM.h, NVRAMRead.c, NVRAMPEI.c, +# NVRAMDXE.c +# +# 3 10/13/06 1:27a Felixp +# +# 2 8/25/06 10:59a Felixp +# +# 1 8/24/06 12:38p Felixp +# +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: NVRAM.mak +# +# Description: +# +#<AMI_FHDR_END> +#********************************************************************** +all : NvramPei NvramDxe + +NVRAM_PEI_OBJECTS=\ +$$(BUILD_DIR)\$(NVRAM_DIR)\NVRAMRead.obj\ +$$(BUILD_DIR)\$(NVRAM_DIR)\NVRAMPEI.obj + +NVRAM_DXE_OBJECTS=\ +$$(BUILD_DIR)\$(NVRAM_DIR)\NVRAMRead.obj\ +$$(BUILD_DIR)\$(NVRAM_DIR)\NVRAMDXE.obj + +$(BUILD_DIR)\NVRAM.mak : $(NVRAM_DIR)\$(@B).cif $(NVRAM_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(NVRAM_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +Runtime_LIBBin : $(BUILD_DIR)\NVRAMDXE.lib +CORE_PEI_LIBBin : $(BUILD_DIR)\NVRAMPEI.lib + +$(BUILD_DIR)\NVRAMDXE.lib : NvramDxe +$(BUILD_DIR)\NVRAMPEI.lib : NvramPei + +NvramDxe : $(BUILD_DIR)\NVRAM.mak NvramDxeBin +NvramPei : $(BUILD_DIR)\NVRAM.mak NvramPeiBin + +NvramDxeBin : + $(ECHO) #define NVRAM_PRESERVE_VARIABLES_LIST $(NvramPreserveVariables) > $(BUILD_DIR)\NvramPreserveList.h + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\NVRAM.mak all\ + "OBJECTS=$(NVRAM_DXE_OBJECTS)"\ + "EXT_HEADERS=$(BUILD_DIR)\token.h\ + $(BUILD_DIR)\NvramPreserveList.h" \ + TYPE=LIBRARY LIBRARY_NAME=$(BUILD_DIR)\NVRAMDXE.lib\ + "MY_DEFINES=/D\"GET_VAR_LIST=$(GetVariableHook)\"\ + /D\"GET_NEXT_VAR_NAME_LIST=$(GetNextVariableNameHook)\"\ +!IF "$(NvramSmiSupport)"=="1" && "$(NVRAM_SMI_FULL_PROTECTION)"=="1" + /D\"DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME=1\"\ +!ENDIF + /D\"SET_VAR_LIST=$(SetVariableHook)\"" + +NvramPeiBin : + $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\ + /f $(BUILD_DIR)\NVRAM.mak all\ +!IF "$(x64_BUILD)"=="1" + BUILD_DIR=$(BUILD_DIR)\IA32\ +!ELSE + BUILD_DIR=$(BUILD_DIR)\ +!ENDIF + "OBJECTS=$(NVRAM_PEI_OBJECTS)"\ + TYPE=PEI_LIBRARY LIBRARY_NAME=$(BUILD_DIR)\NVRAMPEI.lib\ + "MY_DEFINES=/D\"PEI_GET_VAR_LIST=$(PeiGetVariableHook)\"\ + /D\"PEI_GET_NEXT_VAR_NAME_LIST=$(PeiGetNextVariableNameHook)\"" + +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2009, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/Core/EM/NVRAM/NVRAM.sdl b/Core/EM/NVRAM/NVRAM.sdl new file mode 100644 index 0000000..e7a9214 --- /dev/null +++ b/Core/EM/NVRAM/NVRAM.sdl @@ -0,0 +1,65 @@ +TOKEN + Name = "NVRAM_SUPPORT" + Value = "1" + Help = "Main switch to enable NVRAM support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "NVRAM_DIR" +End + +MODULE + Help = "Includes NVRAM.mak to Project" + File = "NVRAM.mak" +End + +ELINK + Name = "GetVariableHook" + Help = "Called before GetVariable" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "GetNextVariableNameHook" + Help = "Called before GetNextVariableName" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "SetVariableHook" + Help = "Called before SetVariable" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "PeiGetVariableHook" + Help = "Called before GetVariable in PEI" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "PeiGetNextVariableNameHook" + Help = "Called before GetNextVariableName in PEI" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "NvramPreserveVariables" + InvokeOrder = ReplaceParent +End + +ELINK + Name = '{L"Setup", { 0xEC87D643, 0xEBA4, 0x4BB5, 0xA1, 0xE5, 0x3F, 0x3E, 0x36, 0xB2, 0x0D, 0xA9 }},' + Parent = "NvramPreserveVariables" + InvokeOrder = AfterParent +End + +ELINK + Name = '{L"AMITSESetup", { 0xc811fa38, 0x42c8, 0x4579, 0xa9, 0xbb, 0x60, 0xe9, 0x4e, 0xdd, 0xfb, 0x34 }},' + Parent = "NvramPreserveVariables" + InvokeOrder = AfterParent +End
\ No newline at end of file diff --git a/Core/EM/NVRAM/NVRAMDXE.c b/Core/EM/NVRAM/NVRAMDXE.c new file mode 100644 index 0000000..ef43629 --- /dev/null +++ b/Core/EM/NVRAM/NVRAMDXE.c @@ -0,0 +1,5719 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/Modules/NVRAM/NVRAMDXE.c 117 6/11/14 3:12p Oleksiyy $ +// +// $Revision: 117 $ +// +// $Date: 6/11/14 3:12p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Modules/NVRAM/NVRAMDXE.c $ +// +// 117 6/11/14 3:12p Oleksiyy +// [TAG] EIP173026 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] With AMITSE 2.17.1245 windows 8.1 (UEFI) does not install +// [RootCause] GetNextVariableName was in certain cases returning name +// and GUID of a boot time variable +// [Solution] Variable name and GUID of a boot time variable X were +// returned at runtime under the following conditions: +// - The variable X was present in the default var.store and not +// present in the main var.store +// - The variable immediately before variable X in the default +// var.store was present in the main var.store +// The default var.store is a var.store generated at build time that +// contains default values for all setup variables +// (variables associated with setup controls). +// The main var.store is the main NVRAM area. Variable is added into a +// main var.store when somebody +// calls SetVariable. +// [Files] NVRAMRead.c +// NVRAMDXE.c +// NVRAM.cif +// +// 116 3/28/14 5:25p Oleksiyy +// [TAG] EIP159166 +// [Category] Improvement +// [Description] Set Auth Variable behaivour when AuthVariable_SUPPORT +// is not present in project made up to speck. +// [Files] NVRAMDXE.c +// +// 115 3/28/14 3:01p Oleksiyy +// [TAG] EIP159166 +// [Category] Improvement +// [Description] When SetVariable is called with gEfiGlobalVariableGuid +// and Variable Name, which is not in the list of Efi Global Variables, +// EFI_INVALID_PARAMETER must be returned according to recent changes to +// UEFI spec. +// [Files] NVRAMDXE.c +// +// 114 3/10/14 4:46p Oleksiyy +// [TAG] EIP156697 +// [Category] Improvement +// [Description] Multiple copies of the same variable through +// GetNextVariableName resolved for Default and Manufactoring modes. +// [Files] NVRAMDXE.c +// +// 113 3/05/14 4:41p Oleksiyy +// [TAG] EIP154299 +// [Category] Improvement +// [Description] Integer + heap potential overflow in SetVariable +// patched. +// [Files] NVRAMDXE.c +// +// 112 1/30/14 10:57a Oleksiyy +// [TAG] EIP148909 +// [Category] Improvement +// [Description] Variable creation on Default Configuration fixed. +// [Files] NVRAMDXE.c +// +// 111 1/14/14 5:45p Oleksiyy +// [TAG] EIP121524 +// [Category] New Feature +// [Description] Extended Aptio functionality for clearing or restoring +// NVRAM to factory default state (preserving only selected Vars). +// [Files] NVRAM.sdl +// NVRAM.mak +// NVRAMDXE.c +// NVRAM.cif +// +// 110 9/24/13 4:42p Oleksiyy +// [TAG] EIP132754 +// [Category] Improvement +// [Description] Removing #ifdef statement as unnecessary. +// [Files] NVRAMDXE.c +// +// 109 8/28/13 6:46p Oleksiyy +// [TAG] EIP132754 +// [Category] Improvement +// [Description] NVRAM modifications for Legacy2Efi module. Sequrity +// update. +// [Files] NVRAMDXE.c +// +// 108 8/27/13 7:45p Oleksiyy +// [TAG] EIP129423 +// [Category] Improvement +// [Description] Setup items behaviour on first and second boot unified. +// [Files] NVRAMDXE.c +// +// 107 8/15/13 12:38p Oleksiyy +// [TAG] EIP132754 +// [Category] New Feature +// [Description] NVRAM modifications for Legacy2Efi module +// [Files] NVRAMDXE.c +// +// 106 2/22/13 4:42p Oleksiyy +// [TAG] EIP115154 +// [Category] Improvement +// [Description] System hangs or resets when all SetVariable calls +// fails. +// Do not return EFI_OUT_OF_RESOURCES if Mailbox failed to save. +// +// [Files] NVRAMDXE.c +// +// 105 1/04/13 5:40p Felixp +// Code clean up: redundant if statements are consolidated. +// +// 104 1/04/13 10:40a Felixp +// [TAG] EIP109422 +// [Category] Improvement +// [Description] Issues found by CppCheck in NVRAM Module part +// InstallNvramControlSmmProtocol call that has been accidently +// deleted by previous check in is restored. +// +// 103 12/13/12 6:16p Oleksiyy +// [TAG] EIP109422 +// [Category] Improvement +// [Description] Issues found by CppCheck in NVRAM Module part +// [Files] NVRAMDXE.c and NVRAMPEI.c +// +// 102 12/13/12 6:12p Felixp +// [TAG] EIP103562 +// [Category] New Feature +// [Description] A mechanism to preserve non-runtime (NV+BS) variables +// across firmware update. +// This feature is required to support +// item 29 of the System.Fundamentals.Firmware.UEFISecureBoot WIN8 Logo +// requirement. +// [Files] NvramDxe.c, SMIFlashLinks.c +// +// 101 11/29/12 5:10p Felixp +// Minor improvement: Since UEFI Specification versions prior to 2.1 +// (0x2000A) are no longer supported, +// all the "#if EFI_SPECIFICATION_VERSION >= 0x2000A" conditional +// compilation statements are removed. +// Files modified: NVRAM.h, NVRAMRead.c, NVRAMDXE.c +// +// 100 11/29/12 4:20p Felixp +// [TAG] EIP106617 +// [Category] Bug Fix +// [Symptom] BeginCriticalSection/EndCriticalSection primitives are not +// really thread safe +// [RootCause] The main problem with the previous implementation was +// that the Critical Section object ("cs") itself was not +// also protected by the critical section, meaning that code must not +// write to this object when interrupts are +// enabled. +// If BeginCriticalSection() is interrupted before the "Busy" flag is set, +// and the interrupt handler attempts to +// re-enter the critical section, interrupt masks and SMI enable state +// will become permanently corrupted. +// Likewise, if EndCriticalSection is interrupted at the wrong time, the +// saved interrupt masks and SMI enable +// state will be overwritten by the interrupt handler re- entering the +// critical section. +// [Solution] By introducing a local temp context, the problem is +// completely solved. +// [Files] NvramDxe.c +// +// 99 11/29/12 3:41p Felixp +// IsStoreOk bug fix (introduced by previous check in) +// +// 98 11/29/12 3:27p Felixp +// Nvram.h, NvramDxe.c: +// 1. Bug Fix (EIP106441): The Authenticated Variable SCT test was +// failing due to a +// bug in UpdateVariable function. The function was skipping the +// update if new variable data +// is equal to the old variable data. The update should not be skipped +// in case of the append operation +// (when EFI_VARIABLE_APPEND_WRITE attribute is set). +// The function is updated accordingly. +// 2. Bug fix: External declaration for the FlashEmpty variable declared +// variable type as UINT32, +// even though the variable is defined in Tokenc.c as UINTN. +// +// 97 11/07/12 4:15p Oleksiyy +// [TAG] EIP99114 +// [Category] New Feature +// [Description] Please make state of "Runtime" variable used in +// NvramDxe.c globally available +// [Files] 99114 +// +// 96 9/18/12 10:57a Felixp +// [TAG] EIP91311 +// [Category] Bug Fix +// [Symptom] The variable defaults are missing at runtime when NvramSmi +// module is used. +// [RootCause] The defaults variable store data structure where not +// updated with the new buffer address. +// It was still pointing to the old address. +// [Solution] ReallocateHybridVarstoreToSmm function is updated to fix +// the main NVRAM store and all the nested variable stores. +// [Files] NvramDxe.c +// +// 95 6/06/12 3:46p Oleksiyy +// [TAG] EIP88436 +// [Category] Improvement +// [Description] Windows 8 feature test UEFI PXE Boot - System hangs. +// [Files] NVRAMDXE.c +// +// 94 5/25/12 4:33p Felixp +// [TAG] EIP88550 +// [Category] Bug Fix +// [Symptom] On Rose City label 17, sometimes setup entry is very slow +// [RootCause] The system occasionally became very slow during start up +// of the setup client. +// The problem was caused missynchronization of the global data used by +// NVRAM DXE and NVRAM SMM drivers. +// +// [Solution] The code is updated to make sure NvramMailBox data is up +// to date at the time of NVRAM SMM driver initialization. +// [Files] NvramDxe.c +// +// 93 5/22/12 6:00p Oleksiyy +// [TAG] EIP90318 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] ChiefRiver SCT Fail, improper variable MonotonicCounter in +// NVRAM module +// [RootCause] EFI_GLOBAL_VARIABLE guid is used in non EFI defined +// variable. +// [Solution] New guig AMI_GLOBAL_VARIABLE_GUID is created and used. +// [Files] AmiLib.h, Misc.c and NVRAMDXE.c +// +// 92 3/22/12 5:31p Oleksiyy +// [TAG] EIP85222 +// [Category] Improvement +// [Description] NVRAM hooks needs virtualization +// [Files] NVRAMDXE.c +// +// 91 3/20/12 10:43a Felixp +// [TAG] EIP85396 +// [Category] Bug Fix +// [Symptom] Loading SETUP defaults using IsResetConfigMode() +// [RootCause] The NVRAM reset happens very early in the NVRAM driver +// initialization process. +// The hybrid interface functions, used during NVRAM reset, +// were accessing global data that has not yet been initialized. +// [Solution] The NVRAM reset is now performed using direct flash access +// (without hybrid interface). +// The hybrid interface is initialized after the NVRAM reset. +// +// 90 3/13/12 10:29a Felixp +// Bug fix in HybridGetAddressDelta: +// Symptoms: The system was hanging during initialization of the NVRAM DXE +// driver +// when NVRAM FV header was corrupted. +// Details: NvramInitialize detects FV header corruption and calls +// NvResetConfiguration to fix it. +// NvResetConfiguration call other functions and control eventually goes +// to HybridGetAddressDelta, +// which didn't work properly since it used VarStoreInfo global data +// structure that had not been initialized yet. +// HybridGetAddressDelta is updated to work properly before VarStoreInfo +// has been initialized. +// +// 89 3/03/12 2:48p Felixp +// Bug fixes in DxeSetVariable: +// Return EFI_INVALID parameter when: +// - Illegal attribute bits are set +// - Boot time variable is being set at runtime +// +// 88 2/22/12 4:07p Oleksiyy +// [TAG] EIP83723 +// [Category] Improvement +// [Description] Review commnts from EIP 82122 applied. +// [Files] NVRAMDXE.c +// +// 87 2/17/12 6:27p Oleksiyy +// [TAG] EIP82122 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] "Secure Boot Manual Logo Test" fails +// [RootCause] If Garbage Collection happens during append operation - +// after garbage collection previous data will be lost after GC. +// [Solution] Append after Garbage collection treated in special way. +// [Files] NVRAMDXE.c +// +// 86 1/30/12 2:17p Felixp +// [TAG] EIP81531 +// [Category] Bug Fix +// [Symptom] ASSERT in debug mode during boot with default configuration +// [RootCause] HybridGetAddressDelta() checks bounds against the wrong +// NVRAM region +// [Solution] HybridGetAddressDelta() is updated to use NvInfo pointer +// instead of NvramInfo +// +// 85 11/11/11 3:19p Felixp +// 1.Performance of the NVRAM driver has been improved by creation of the +// in-memory cache of the +// NVRAM data (older code accessed ROM directly). The feature can be +// disabled by commenting out +// definition of the HYBRID_NV_INTERFACE macro in NvramDxe.c +// 2. Support for isolation of the SMM NVRAM services at runtime (no data +// access outside of SMM). +// The isolation of the SMM NVRAM driver implies migration of the NVRAM +// API into SMM. The DXE +// portion of the NVRAM driver is getting shut down. It is replaced by +// the NvramSmi driver (external +// eModule; not part of the Core) that redirects NVRAM calls into SMM. +// The feature should be used +// when flash part is locked at runtime. The support is automatically +// enabled when NvramSmi module +// is in the project (by defining +// DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME macro). +// +// 84 7/13/11 9:24a Justinj +// [TAG] EIP62762 +// [Category] Improvement +// [Description] Optimize NVRAM cache index so that the entire linked +// list is not walked every time a variable is set or retrieved. +// [Files] NVRAM.h +// NVRAMRead.c +// NVRAMDXE.c +// +// 83 7/08/11 3:31p Oleksiyy +// [TAG] EIP64390 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Repetitive SetVariables calls cause UEFI OS crash +// [RootCause] When NVRAM_RT_GARBAGE_COLLECTION_SUPPORT is off, +// CopyVarStoreToMemStore does not do anything (immediately returns error) +// but SelectiveFree was still trying to free memory at uninitialized +// address (NewInfo.NvramAddress is not initialized). +// +// [Solution] Added check for Rintime before going to BS. +// [Files] NVRAMDXE.c +// +// 82 6/16/11 10:23a Artems +// Bugfix in authenticated variable support +// +// 81 6/16/11 8:58a Felixp +// Bug fix in the IndexInit function: VarIndexPtr->BufferSize was not +// initialized. +// +// 80 6/13/11 6:42p Artems +// Added changes to support Authenticated Variable +// +// 79 5/11/11 6:33p Oleksiyy +// [TAG] EIP60206 +// [Category] Improvement +// [Description] Authenticated Variables improvement. +// NV_CACHE_SUPPORT == O support added. +// [Files] NVRAMDXE.c and NVRAM.h +// +// 78 5/06/11 6:15p Oleksiyy +// [TAG] EIP53253 +// [Category] Improvement +// [Description] To comply with UEFI 2.3.1 +// EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS and +// EFI_VARIABLE_APPEND_WRITE attributes handling added. +// [Files] NVRAM.h, NVRAMRead.c and NVRAMDXE.c +// +// 77 3/09/11 6:18p Artems +// Undo previous changes, as they are unnecessary since SCT fixed bug on +// their side +// +// 76 2/25/11 3:01p Artems +// EIP 53749: SCT variable test fails. Here included partial fix. SCT uses +// wrong guid +// in its test - this part not included in generic source and available as +// patch for sole purpose +// of passing SCT test +// +// 75 2/11/11 11:08a Artems +// +// 74 2/02/11 3:09p Oleksiyy +// [TAG] EIP42253 +// [Category] Improvement +// [Description] Convert Flash Pointer added. +// [Files] NVRAMDXE.c +// +// 73 1/25/11 12:46p Oleksiyy +// [TAG] EIP42253 +// [Category] New Feature +// [Description] Added support for platforms, where flash part is not +// memory mapped while write enabled, controlled by +// NO_MMIO_FLASH_ACCESS_DURING_UPDATE sdl token. Flash protocol used to +// access flash in that case. +// [Files] NVRAMDXE.c, Flash.c, Tokens.c and Runtime.sdl +// +// 72 1/19/11 6:04p Oleksiyy +// [TAG] EIP52517 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] NVRAM inconsistency when updating Setup first time in 32 +// bit mode +// [RootCause] DxeSetVariable function in NVRAMDXE.c passes wrong +// Interface to UpdateVariable. +// [Solution] DxeSetVariable function in NVRAMDXE.c modified. +// [Files] NVRAMDXE.c +// +// 71 11/17/10 12:04p Oleksiyy +// [TAG] EIP39460 +// [Category] New Feature +// [Description] Runtime Garbage Collection potential bug fix. +// Initialization of Mailbox updated. +// [Files] NVRAMDXE.c +// +// 70 11/11/10 7:40a Felixp +// Bug fix: updated to compile in UEFI 2.0 mode. +// +// 69 11/08/10 5:58p Felixp +// Bug fixes in the RT Garbage Collection Support implementation +// (EIP39460). +// +// 68 11/08/10 5:29p Felixp +// Depdency from SecureMod_SUPPORT SDL token is removed +// +// 67 11/08/10 5:23p Felixp +// Bug fixes in the Runtime Garbage Collection Support implementation (EIP +// 39460). +// +// 66 11/05/10 2:14p Felixp +// Bug Fix in QueryVariableInfo. +// QueryVariableInfo was always reporting MaximumVariableSize of 8 bytes. +// +// 65 9/30/10 4:53p Oleksiyy +// Issue Number: 45053 +// +// Category: Improvement +// +// Description: If update on Next field in NVAR failed, the NVRAM +// recovery was not triggered. Problem fix now. +// +// Files: NVRAMDXE.c +// +// 64 9/30/10 4:38p Oleksiyy +// Issue Number: 40356 and 39462 +// +// Category: New Feature +// +// Description: Support for EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS +// Small fix of previously checked in code. +// +// Files: NVRAM. h, NVRAMRead.c, NVRAMDXE.c +// +// 63 9/24/10 8:00a Felixp +// Minor bug fix in initialization of NvramCs variable +// +// 62 9/24/10 7:57a Felixp +// Improvement( EIP 40257): +// BeginCriticalSection/EndCriticalSection are updated to enable/disable +// interrupts using +// PIC interrupt mask registers (ports 0x21 and oxa1) instead of just +// setting the CPU interrupt flag (CLI/STI). +// +// 61 9/22/10 6:39p Felixp +// Enhancement(EIP 39462 and EIP 40356): +// Support of the authenticated update of the NVRAM variables +// as described in UEFI specification version 2.1 and above. +// NOTE: The actual authentication is performed by the external SecureMod +// eModule, +// which must be in the proejct to use this feature. +// +// 60 9/22/10 5:47p Felixp +// Enhancement(EIP 39460): Runtime Garbage Collection Support. +// (controlled by the NVRAM_RT_GARBAGE_COLLECTION_SUPPORT SDL token ). +// +// 59 6/30/10 4:32p Felixp +// +// 58 6/30/10 2:19p Felixp +// Switching to simulation in recovery modue is disabled. +// +// 57 4/26/10 2:56p Felixp +// +// 56 4/26/10 11:57a Felixp +// Clean up of the trace messages. +// +// 55 4/23/10 5:32p Felixp +// 1. NVRAM Reset Policy is updated. +// Don't reset configuration if defaults are not available. +// Restore defaults is they disappeared from the NVRAM. +// 2. Turn on NVRAM simulation in Recovery mode (to protect main FV before +// main BIOS is updated) +// +// 54 4/22/10 11:50p Felixp +// Bug fix in the NvramInitialize. NvResetConfiguration after the +// DxeIsNvramCompatible was called with the wrong argument. +// This caused problems when fault tolerant NVRAM update was enabled. +// +// 53 4/22/10 11:47p Felixp +// EnumerateStore function is updated to skip incomplete +// NVAR record (if any) at the end of the NVRAM data area. +// +// 52 3/05/10 11:52a Felixp +// Bug fix: +// Symptoms: When FAULT_TOLERANT_NVRAM_UPDATE is enabled, +// UEFI Windows crashes with blue screen 1E during start up. +// Details: The VarStoreInfo.BackupAddress was not virtualized during +// virtual mode transition. +// +// 51 2/02/10 5:16p Oleksiyy +// EIP 33263 : Hooks for SetVariable, GetVariable and GetNextVarName +// added +// +// 50 12/04/09 12:29p Felixp +// NvarEqNvar moved to NvramRead.c +// +// 49 11/24/09 4:40p Felixp +// Minor bug fixes +// +// 48 11/23/09 11:00p Felixp +// +// 47 11/23/09 4:44p Felixp +// Code to validate NVRAM header fields used by the NVRAM driver is added. +// If problem is found, the header fields are updated with the correct +// values. +// +// 46 11/20/09 4:06p Felixp +// NVRAM driver is updated to support UEFI2.1 +// EFI_VARIABLE_HARDWARE_ERROR_RECORD attribue. +// +// 45 11/20/09 9:27a Felixp +// NVRAM record corruption check is added to IndexFindVariable and +// IndexUpdateVariable functions. +// +// 44 8/25/09 4:11p Felixp +// NVRAM Record Checksum Support(EIP 23825) is added. +// Disabled by default. Enable using NVRAM_RECORD_CHECKSUM_SUPPORT SDL +// token. +// +// 43 7/30/09 3:38p Felixp +// Bug fix: +// Symptoms: systems were occasionally hanging during first boot after +// flashing, +// when SetVariable call from SMM was followed by the GetVariable call +// from outside of SMM. +// Details: VarIndex data structure updated to save varstore indexes +// within VarStoreInfo.NvramInfo +// instead of pointers to varstore information (pointers cannot be used +// because VarIndex information is used by both SMM and non-SMM NVRAM +// services, +// which have independent copies of VarStoreInfo global variable). +// +// 42 7/10/09 8:53a Felixp +// +// 41 7/10/09 8:51a Felixp +// New NVRAM_MONOTONIC_COUNTER_SUPPORT SDL token is created. The token can +// be used +// to disable Core NVRAM-based implementation of the monotonic counter +// architectural protocol and +// to use stand alone monotonic counter driver instead. +// Code clean up; comments and function header added. +// +// 40 6/26/09 3:33p Felixp +// Bug fix (EIP 23329): +// 1. CheckStore function: Auto detect active NVRAM area (main or backup) +// before NVRAM access. +// 2. DxeSetVariable: Bug fix in parameter validation +// 3. Additional debug messages added +// +// 39 5/21/09 5:38p Felixp +// 1. Reset NVRAM content to defaults (loaded from FFS file in FV_MAIN or +// other FV) +// if it has been corrupted during failed BIOS update. +// 2. Validate compatibility of the NVRAM content using external hook +// (DxeIsNvramDataCompatible). +// It NVRAM content is incompatible, reset it to defaults +// (loaded from FFS file in FV_MAIN or other FV). +// +// 38 5/14/09 9:36a Felixp +// New feature: SMM version of Runtime Services +// NVRAM driver is updated to populate SMM runtime table +// with the pointers to SMM version of variable services. +// +// 37 5/04/09 2:26p Felixp +// +// 36 5/04/09 11:24a Felixp +// Make sure code compiles with NV_CACHE_SUPPORT set to zero +// +// 35 5/04/09 11:07a Felixp +// Bug fix. NVRAM DXE will crash if defaults are reset on first boot(EIP +// 20149). +// Symptoms: If TRUE is returned by IsResetConfig() on the first boot +// after a fresh flash, system hangs in the NVRAM DXE driver. +// Function updated: IndexReset +// +// 34 3/23/09 2:20p Felixp +// Bug fix: EIP 20442. +// Symptoms: USB mass storage device is sometimes missing from the BBS +// popup menu +// when F12 is pressed continuously on USB keyboard. +// Details: the problem was caused by the fact that timer interrupt +// handler was running with SMI disabled. +// BeginCriticalSection/EndCriticalSection updated to enable SMI's +// before interrupts. +// The change provides support for interrupt handlers depending upon +// processing performed by the SMI handler +// +// 33 1/02/09 2:19p Felixp +// Improved handling of the variables with default values. +// When variable is deleted, return EFI_WRITE_PROTECTED instead of +// EFI_NOT_FOUND +// if only default value (which can not be deleted) exists. +// When volatile variable is created, return EFI_INVALID_PARAMETER if +// default value exists +// (If default value exists, the variable is non volatile. Attributes +// for existing variable can not be changed). +// +// 32 11/21/08 2:13p Felixp +// Bug fix in IsClean routine. +// +// 31 11/20/08 6:17p Felixp +// Bug fin in CreateVariable (proper handling of the GUID index overflow). +// +// 30 11/20/08 2:23p Felixp +// Bug fix in the NextGuid detection logic within EnumerateStore routine. +// +// 29 10/17/08 9:40a Felixp +// Bug fix in IndexUpdateVariable (caused blue screen during UEFI Vista +// installation). +// +// 28 10/09/08 11:47a Felixp +// 1. Fault tolerant NVRAM garbage collection support is added. +// Use FAULT_TOLERANT_NVRAM_UPDATE SDL token to enable/disable (disabled +// by default). +// NOTE: This feature requires upgrade of the Board module. +// NOTE: This feature requires porting: +// Fault tolerant update requires reserved flash area of size NVRAM_SIZE +// used for back up during NVRAM garbage collection. +// The address of the area is defined by NVRAM_BACKUP_ADDRESS SDL token +// defined in Board.sdl. +// Size and Base addresses of other firmware volumes may need to be +// adjusted to free up space for the NVRAM back up area. +// Default ROM layout expects NVRAM back up area immediately below the +// main NVRAM area. +// For projects with the customized ROM layout Core.mak has to be updated. +// 2. Top level NVRAM function updated to be reentrance-safe. +// NOTE: This feature requires upgrade of the SB module. +// 3. Improved recovery from the flash programming failures and +// corruptions within NVRAM area. +// 4. More reliable non-fault tolerant garbage collection. +// +// 27 8/01/08 3:23p Felixp +// Bug fix in UpdateVariable routine (Index was not properly updated if +// NvCompact happened in the UpdateVariable) +// +// 26 7/14/08 3:16p Felixp +// +// 25 7/08/08 5:31p Felixp +// Don't do NvCompact at runtime +// +// 24 4/21/08 11:32p Felixp +// Bug fix in the NVRAM corruption recovery logic +// +// 23 3/12/08 2:52p Felixp +// Error code reporting when flash update failed added +// +// 22 2/19/08 11:11p Felixp +// 1. NvProgram updated: code added to verify if data have been programmed +// correctly +// 2. Minor bug fix in NvCompact +// 3. CreateVariable/UpdateVariable updated with the code that handles +// failed flash write operations +// 4. Bug fix in DxeSetVariable: during boot with default configuration, +// current value was not properly updated +// 5. Update in init routine VarStoreDiscovery: during boot with default +// configuration, main NVRAM store is also exposed. This is needed to +// provide current value for variables without defaults. +// +// 21 11/07/07 3:09p Felixp +// Bug fixes: +// 1. GetVariable/SetVariable crashed or returned EFI_NOT_FOUND after +// ExitBootServices and before SetVartualAddressMap +// 2. During first boot or boot with default values updated value of the +// variable did not show up until system reset (GetVariable was returning +// old value) +// +// 20 10/15/07 3:00p Felixp +// Bug fix in NvramInitialize: defaults were ignored in simulation mode. +// +// 19 10/12/07 3:06p Felixp +// Bug fix(EIP issue 10480): NVRAM initialization routine is updated to +// properly handle NV simulation. +// +// 18 9/13/07 10:18a Felixp +// Bug fix in DxeNvramInit routine. +// NVRAM area descriptor was not properly reinitialized +// during calls to DxeNvramInit with ResetVolatileStore set FALSE +// +// 17 9/06/07 12:14a Felixp +// +// 16 8/31/07 3:44p Felixp +// NVRAM code has been significantly changed to introduce the following +// improvements: +// 1. The code is chaned to always use the same amount of memory. +// Previous implementation allocated memory as needed, which caused +// occasional S4 problems. +// Plus S4 resume never worked during the very first boot after the +// firmware update. +// 2. Support for NVRAM defaults added. +// NVRAM image with the default values for the Setup variables is now +// generated by the build process. +// The image is generated by the HpkTool (included into AMITSE module +// part). +// In addition to standard Setup defaults it is also possible +// to generate manufactoring defaults. Support for the manufactoring +// defaults +// is disabled by default and can be enabled using +// MANUFACTURING_MODE_SUPPORT SDL token. +// 3. Support for boot with alternative configurations is added. +// Decision to switch to the alternative configuration +// (alternative set of values for NVRAM variables) +// is based on values returned by the porintg routine in OemPort.c. +// During boot with alternative configurations GetVariable service +// returns alternative values for the setup-related variables. +// If variable does not have an alternative value, current value is +// returned. +// Two alternative configurations are supported: +// Boot with manufactoring settings(activated when IsMfgMode routine in +// OemPort.c returns TRUE). +// Boot with default settings(activated when IsDefaultConfigMode routine +// in OemPort.c returns TRUE). +// NOTE: This feature requires of the Board module +// 4.NVRAM reset option is added. +// If porting routine IsResetConfigMode in OemPort.c returns TRUE in PEI +// phase, +// NVRAM content will be reset during initialization of the DXE NVRAM +// driver. +// During reset operation all setup-related variables are reset to their +// default values. +// All other variables are deleted. +// NOTE: This feature requires upgrade of the Board module +// 5.Detection of NVRAM update added. +// NVRAM implementation detects if NVRAM has been updated since the last +// NVRAM call. +// This provides ability to use variables services before and after +// firmware update. +// 6.Overall code clean up and simplification. +// 7.Core Sources are no longer required in order to use NV_SIMULATION +// option. +// 8.PI 1.0 support. +// Support for a PI 1.0 complient variable PPI is added. Old PPI is still +// preserved in this label for backward compatibility. +// New library routines PeiGetVariable and PeiGetNextVariableName are +// created in order to hide the differences between two PPIs. +// It is recommended to update existing code to use new library routines. +// Support of the old PPI may be dropped in the future versions of Core. +// 9. NVRAM is now packaged as a raw FFS file embedded into the standard +// FV (used to be non-standard FV with raw NVRAM image). +// Validation: New NVRAM code has been validated using SCT and EFI version +// of Windows Server 2008 +// Files modified: Core.sdl, Core.mak, AmiPeiLib.h, PeiLib.c, +// ReadOnlyVariable.h, , Token.c, HpkTool.exe, AMITSE.mak, Setup.ini, +// NVRAM.sdl, NVRAM.mak, NVRAM.h, NVRAMRead.c, NVRAMPEI.c, +// NVRAMDXE.c +// +// 15 8/07/07 2:42p Felixp +// Additional Status Codes added +// +// 14 4/25/07 6:02p Felixp +// MemSetVariable improvements: don't do memory deallocation/allocation +// when variable is updated with the data of the same size. +// +// 13 3/29/07 1:06p Felixp +// SCT workarounds removed (the issues have been fixed in the new version +// of SCT). +// +// 12 12/29/06 3:02p Felixp +// Update to use new flash interface +// +// 11 12/19/06 12:39p Felixp +// Bug fixes in Variable Services +// +// 10 12/18/06 3:00p Robert +// Updated for change in IsProgramCompleted parameters +// +// 9 11/01/06 4:40p Robert +// Added changes that are updates for the source to work with the new +// Flash module +// +// 8 10/27/06 10:42a Felixp +// Bug fixes for correct work in Virtual Address Space. +// +// 7 10/23/06 7:03p Felixp +// 1. Virtual address space fixup of the global variables added +// 2. NVRAM simulation support +// +// 6 10/12/06 9:07p Felixp +// +// 5 10/12/06 9:44a Felixp +// UEFI2.0 compliance: use CreateLegacyBootEvent instead of CreateEvent +// +// 3 10/09/06 10:08a Felixp +// UEFI2.0 support (QueryVariableInfo funciton added) +// +// 2 9/20/06 10:38a Felixp +// 1. Bug fix in MemSetVariable: cached variable data was not updated +// during variable update in Runtime +// 2. Legacy boot event handler added to switch to runtime mode in case of +// legacy boot +// +// 10 7/17/06 7:50p Felixp +// changes so that module can be compiled in NV_SIMULATION mode without +// Flash.lib +// +// 9 12/06/05 2:36p Felixp +// bug fixes in NVCompact and NVSetVariable +// +// 8 9/23/05 5:44p Felixp +// bug fix in NVSetVariable (when update of the variable causes NVCompact, +// NameSize is uninitialized) +// +// 5 7/22/05 2:19a Felixp +// 1. NVRAM enclosed into Firmware volume. +// 2. bug fixes (mostly in NVCompact) +// +// 4 4/07/05 12:09p Felixp +// bug fixing +// +// 3 1/20/05 11:37a Felixp +// Component restructurized to support release in binary format +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 21 11/18/04 6:08p Felixp +// checkpoint(0x99) removed +// +// 19 8/28/04 1:49a Felixp +// NVRAM Routines fixes +// +// 15 7/16/04 1:00p Markw +// Check max tpl. +// +// 1 3/29/04 2:32a Felixp +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: NVRAMDXE.h +// +// Description: +// +//<AMI_FHDR_END> +//********************************************************************** +#include "NVRAM.h" +#include <AmiDxeLib.h> +#include "token.h" + +#include <Protocol/Variable.h> +#include <Protocol/MonotonicCounter.h> +#include <Protocol/FlashProtocol.h> +#include <AmiCspLib.h> +#include "NvramPreserveList.h" + +#define HYBRID_NV_INTERFACE + +#define HASH_SHA256_LEN 32 + +#define UEFI21_SPECIFIC_VARIABLE_ATTRIBUTES (EFI_VARIABLE_HARDWARE_ERROR_RECORD |\ + EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) + +#define UEFI23_1_SPECIFIC_VARIABLE_ATTRIBUTES (EFI_VARIABLE_HARDWARE_ERROR_RECORD |\ + EFI_VARIABLE_APPEND_WRITE |\ + UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES) + +//##### Security ###### +#if AuthVariable_SUPPORT +VOID AuthVariableServiceInit (VOID); +VOID AuthVariableServiceInitSMM (VOID); +VOID AuthServiceVirtualFixup(VOID); +EFI_STATUS VerifyVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 *Attributes, + IN VOID **Data, + IN UINTN *DataSize, + IN VOID *OldData, + IN UINTN OldDataSize, + IN OUT EXT_SEC_FLAGS *ExtFlags +); +#else +VOID AuthVariableServiceInit (VOID) {}; +VOID AuthVariableServiceInitSMM (VOID) {}; +VOID AuthServiceVirtualFixup(VOID) {}; +EFI_STATUS VerifyVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 *Attributes, + IN VOID **Data, + IN UINTN *DataSize, + IN VOID *OldData, + IN UINTN OldDataSize, + IN OUT EXT_SEC_FLAGS *ExtFlags +){ +//UEFI 2.3.1 requres to return SECURITY_VIOLATION error if no Auth Var support present + if (*Attributes & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES) + return EFI_SECURITY_VIOLATION; + else + return EFI_SUCCESS; +} +#endif //#if AuthVariable_SUPPORT + +#define ALL_VARIABLE_ATTRIBUTES ( EFI_VARIABLE_NON_VOLATILE |\ + EFI_VARIABLE_BOOTSERVICE_ACCESS |\ + EFI_VARIABLE_RUNTIME_ACCESS|\ + UEFI23_1_SPECIFIC_VARIABLE_ATTRIBUTES) + +#define VALATILE_VARIABLE_STORE_SIZE 0x10000 + +#define BEGIN_CRITICAL_SECTION(Cs) \ + { if ((Cs)->Busy) return EFI_ACCESS_DENIED;\ + BeginCriticalSection(Cs);\ + } +#define END_CRITICAL_SECTION(Cs) EndCriticalSection(Cs) +#ifdef EFI_DEBUG + +#define NVRAM_TRACE(Arguments) { if (!Runtime) TRACE(Arguments); } +#else +#define NVRAM_TRACE(Arguments) +#endif + +//============================================================================ +// Type definitions +typedef BOOLEAN (*NVRAM_UPDATE_ROUTINE)(IN VOID *Address, UINTN Size); +typedef BOOLEAN (*NVRAM_PROGRAM_ROUTINE)(IN VOID *Address, UINTN Size, VOID *Data); +typedef BOOLEAN (*COPY_VAR_STORE_FILTER)( + IN VOID *Context, CHAR16* VarName, EFI_GUID* VarGuid, + NVRAM_STORE_INFO *Info +); + +typedef struct +{ + NVRAM_UPDATE_ROUTINE EnableUpdate; + NVRAM_UPDATE_ROUTINE DisableUpdate; + NVRAM_UPDATE_ROUTINE EraseBytes; + NVRAM_PROGRAM_ROUTINE WriteBytes; +} VARIABLE_INTERFACE; + +typedef struct +{ + UINT32 Mode; + UINT32 HeaderLength; + UINT32 NvramMode; + UINT32 InfoCount, LastInfoIndex; + NVRAM_STORE_INFO NvramInfo[10]; + NVRAM_STORE_INFO *NvInfo, *MemInfo; + VARIABLE_INTERFACE *NvInterface, *MemInterface; + UINT8 *BackupAddress; +#ifdef HYBRID_NV_INTERFACE + UINTN AddressDelta; + UINT8* NvramFlashAddress; +#endif +} VARSTORE_INFO; + +typedef struct +{ + BOOLEAN Busy; + BOOLEAN SmiState; + UINT8 IntState[2]; +} CRITICAL_SECTION; + +typedef EFI_STATUS (HOOK_GET_VARIABLE)( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, OUT VOID *Data +); +typedef EFI_STATUS (HOOK_SET_VARIABLE)( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data +); + +typedef EFI_STATUS (HOOK_GET_NEXT_VARIABLE_NAME)( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid +); + +typedef EFI_STATUS (*SHOW_BOOT_TIME_VARIABLES)(BOOLEAN Show); + +typedef struct{ + SHOW_BOOT_TIME_VARIABLES ShowBootTimeVariables; +} AMI_NVRAM_CONTROL_PROTOCOL; + +#define LTEB_GUID \ + {0xC8BCA618, 0xBFC6, 0x46B7, 0x8D, 0x19, 0x83, 0x14, 0xE2, 0xE5, 0x6E, 0xC1} + +typedef struct { + CHAR16 *Name; + EFI_GUID Guid; +} SDL_VAR_ENTRY; + +typedef struct { + CHAR16 *Name; + UINT32 Attributes; +} STD_EFI_VAR_ENTRY; + +//====================================================================== +//Function Prototypes +EFI_STATUS NvramReinitialize(); +EFI_STATUS InitVolatileStore( + NVRAM_STORE_INFO *Info, UINTN Size, + UINTN HeaderLength, UINT8 Flags, + BOOLEAN Runtime +); +BOOLEAN CheckTheHeader(NVRAM_STORE_INFO *Info, UINT32 HeaderLength, BOOLEAN Update); + +//====================================================================== +// Global and extern variables +extern const BOOLEAN NvramMonotonicCounterSupport; +extern BOOLEAN NvramChecksumSupport; +extern const BOOLEAN FlashNotMemoryMapped; +static BOOLEAN Runtime = FALSE; +static BOOLEAN HideBtVariables = TRUE; +static EFI_GUID gAmiNvramControlProtocolGuid = { 0xf7ca7568, 0x5a09, 0x4d2c, { 0x8a, 0x9b, 0x75, 0x84, 0x68, 0x59, 0x2a, 0xe2 } }; +static BOOLEAN SaveOnlyPreservedVars = FALSE; +#ifdef DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME +BOOLEAN NoAccessOutsideofSmm = FALSE; +#endif + +VARSTORE_INFO VarStoreInfo; +CRITICAL_SECTION NvramCs = {FALSE, FALSE, {0,0} }; +CRITICAL_SECTION *NvramCsPtr = &NvramCs; + +const static UINT32 NvramSignature = NVAR_SIGNATURE; +extern const BOOLEAN NvramRtGarbageCollectionSupport; +EFI_PHYSICAL_ADDRESS NvramDriverBuffer = 0; // Runtime buffer for use in Runtime with the size of 3 times NVRAM_SIZE +// First part (2 times NVRAM_SIZE) usialy used for TmpBuffer, while last part for VolatileStore. +UINT32 NvramDriverBufferSize = 0; +BOOLEAN FirstPartAlloc = FALSE; +BOOLEAN SecondPartAlloc = FALSE; + +static FLASH_PROTOCOL *Flash = NULL; +extern HOOK_GET_VARIABLE GET_VAR_LIST EndOfGetVariableHook; +extern HOOK_SET_VARIABLE SET_VAR_LIST EndOfSetVariableHook; +extern HOOK_GET_NEXT_VARIABLE_NAME GET_NEXT_VAR_NAME_LIST EndOfGetNextVarNameHook; + +HOOK_GET_VARIABLE* GetVariableHookList[]= + {GET_VAR_LIST NULL}; +HOOK_SET_VARIABLE* SetVariableHookList[]= + {SET_VAR_LIST NULL}; +HOOK_GET_NEXT_VARIABLE_NAME* GetNextVarNameHookList[]= + {GET_NEXT_VAR_NAME_LIST NULL}; +// Build time array of variables to be preserved. +SDL_VAR_ENTRY gSdlVarLst[] = { + NVRAM_PRESERVE_VARIABLES_LIST {NULL, {0,0,0,0,0,0,0,0,0,0,0}} +}; + +STD_EFI_VAR_ENTRY gStdEfiVarList[] = { + {L"LangCodes", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"Lang", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"Timeout", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"PlatformLangCodes", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"PlatformLang", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"ConIn", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"ConOut", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"ErrOut", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"ConInDev", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"ConOutDev", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"ErrOutDev", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"BootOrder", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"BootNext", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"BootCurrent", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"BootOptionSupport", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"DriverOrder", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"HwErrRecSupport", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"SetupMode", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"KEK", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS}, + {L"PK", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS}, + {L"SignatureSupport", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"SecureBoot", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"KEKDefault", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"PKDefault", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"dbDefault", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"dbxDefault", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"dbtDefault", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"OsIndicationsSupported", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {L"OsIndications", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"VendorKeys", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS}, + {NULL, 0} +}; + +STD_EFI_VAR_ENTRY gStdEfiVarListWildCard[] = { + {L"Boot****", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"Driver****", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {L"Key****", EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE}, + {NULL, 0} +}; + +EFI_STATUS ShowBootTimeVariables (BOOLEAN Show); +AMI_NVRAM_CONTROL_PROTOCOL NvramControl = {ShowBootTimeVariables }; + +EFI_STATUS GetVariableHook( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, OUT VOID *Data +){ + UINTN i; + EFI_STATUS Result = EFI_UNSUPPORTED; + for(i=0; GetVariableHookList[i] && (Result == EFI_UNSUPPORTED); i++) + Result = GetVariableHookList[i](VariableName, VendorGuid, Attributes, DataSize, Data); + return Result; +} + +EFI_STATUS SetVariableHook( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data +){ + UINTN i; + EFI_STATUS Result = EFI_UNSUPPORTED; + for(i=0; SetVariableHookList[i] && (Result == EFI_UNSUPPORTED); i++) + Result = SetVariableHookList [i](VariableName, VendorGuid, Attributes, DataSize, Data); + return Result; +} + +EFI_STATUS GetNextVarNameHook( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid +){ + UINTN i; + EFI_STATUS Result = EFI_UNSUPPORTED; + for(i=0; GetNextVarNameHookList[i] && (Result == EFI_UNSUPPORTED); i++) + Result = GetNextVarNameHookList [i](VariableNameSize, VariableName, VendorGuid); + return Result; +} +//--- GetVariable, SetVariable and GetNextVarName Hooks END ------ + +//Update Interfaces: +//Memory-based +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DummyUpdateRoutine +// +// Description: This function is dummy function doing nothing and always returning TRUE +// +// Input: IN VOID *Address - Memory address +// UINTN Size - Size +// +// Output: TRUE always +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN DummyUpdateRoutine(IN VOID *Address, UINTN Size) {return TRUE;} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MemErase +// +// Description: This function sets Size amount memory starting from Address to FLASH_EMPTY_BYTE +// +// Input: IN VOID *Address - Memory address +// UINTN Size - Size +// +// Output: TRUE always +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN MemErase(IN VOID *Address, UINTN Size) +{ + MemSet(Address,Size,FLASH_EMPTY_BYTE); + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MemProgram +// +// Description: This function writs Data to memory starting from Address +// +// Input: IN VOID *Address - Memory address +// UINTN Size - Size of data to write +// VOID *Data - pointer to data to write +// +// Output: TRUE always +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN MemProgram(IN VOID *Address, UINTN Size, VOID *Data) +{ + MemCpy(Address,Data,Size); + return TRUE; +} + +//Flash-based +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvEnableWrites +// +// Description: This function enables writes to flash starting from Address +// +// Input: IN VOID *Address - Start address +// UINTN Size - Size of flash to be write enabled +// +// Output: TRUE always +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN NvEnableWrites(IN VOID *Address, UINTN Size) +{ + UINT8* Start = (UINT8*)Address; + UINT8* p; + Flash->DeviceWriteEnable(); + + for (p=(UINT8*)BLOCK(Start); p<Start+Size; p+=FlashBlockSize) FlashBlockWriteEnable(p); + + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvDisableWrites +// +// Description: This function disables writes to flash starting from Address +// +// Input: IN VOID *Address - Start address +// UINTN Size - Size of flash to be write disable +// +// Output: TRUE always +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN NvDisableWrites(IN VOID *Address, UINTN Size) +{ + UINT8* Start = (UINT8*)Address; + UINT8* p; + + for (p=(UINT8*)BLOCK(Start); p<Start+Size; p+=FlashBlockSize) FlashBlockWriteDisable(p); + + Flash->DeviceWriteDisable(); + return TRUE; +} + +#define INT_SIZE sizeof(INTN) + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsProgrammableOrEqual +// +// Description: This function checks if defined memory chunks are the same and if destenation is programmable +// +// Input: IN UINT8 *pDest - pointer to memory to check +// IN UINT8 *pSource - pointer to the source to compare with +// IN UINTN Size - size of the chunk +// OUT BOOLEAN *pIsProgrammable - Will be set to TRUE if pDest is programable +// OUT BOOLEAN *pIsEqual - Will be set to TRUE if pDest and pSource has the same content +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID IsProgrammableOrEqual( + IN UINT8 *pDest, + IN UINT8 *pSource, + IN UINTN Size, + OUT BOOLEAN *pIsProgrammable, + OUT BOOLEAN *pIsEqual +) +{ + *pIsEqual = TRUE; + *pIsProgrammable = TRUE; + + // loops through the destination looking to see if the data is the same + // as the source, or if the Destination has already bee erased + if (!( (UINTN)pDest & (INT_SIZE-1) || (UINTN)pSource & (INT_SIZE-1) )) + { + UINTN *Dest = (UINTN*)pDest, *Source = (UINTN*)pSource; + + for ( ; Size >= INT_SIZE; Size -= INT_SIZE) + { + UINTN s,d; + + if (FLASH_EMPTY_BYTE==0) + { + s=~*Source; + if (FlashNotMemoryMapped) + Flash->Read((UINT8 *)Dest, INT_SIZE, &(UINT8)d); + else + d=*Dest; + } + + else + { + s=*Source; + if (FlashNotMemoryMapped) + { + Flash->Read((UINT8 *)Dest, INT_SIZE, &(UINT8)d); + d=~d; + } + else + d=~*Dest; + } + + if ((d&s)!=0) + { + *pIsProgrammable = FALSE; + *pIsEqual = FALSE; + return; + } + if (FlashNotMemoryMapped) + { + Flash->Read((UINT8 *)Dest, INT_SIZE, &(UINT8)d); + if (d != *Source++) *pIsEqual = FALSE; + Dest++; + } + else + if (*Dest++ != *Source++) *pIsEqual = FALSE; + + } + } + + // since the address may not be INT_SIZE aligned, this checks + // the rest of the data + for ( ; Size > 0; Size--) + { + UINT8 s,d; + + if (FLASH_EMPTY_BYTE==0) + { + s=~*pSource; + if (FlashNotMemoryMapped) + Flash->Read(pDest, 1, &d); + else + d=*pDest; + + } + else + { + s=*pSource; + if (FlashNotMemoryMapped) + { + Flash->Read(pDest, 1, &d); + d=~d; + } + else + d=~*pDest; + + } + + if ((d&s)!=0) + { + *pIsProgrammable = FALSE; + *pIsEqual = FALSE; + return; + } + if (FlashNotMemoryMapped) + { + Flash->Read(pDest, 1, &d); + if ( d != *pSource++) *pIsEqual = FALSE; + pDest++; + } + else + if (*pDest++ != *pSource++) + *pIsEqual = FALSE; + + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsClean +// +// Description: This function checks if defined memory chunk is clean +// +// Input: IN UINT8 *pDest - pointer to memory to check +// IN UINTN Size - size of the chunk +// +// Output: BOOLEAN - TRUE if pDest is clean, otherwice FALSE +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +static BOOLEAN IsClean( + IN UINT8 *pDest, + IN UINTN Size +) +{ + // loops through the destination looking to see if the buffer is empty + if (!( (UINTN)pDest & (INT_SIZE-1) )) + { + for ( ; Size >= INT_SIZE; Size -= INT_SIZE, pDest += INT_SIZE) + { + if (FlashNotMemoryMapped) + { + UINTN nData=0; + Flash->Read(pDest, INT_SIZE, &(UINT8)nData); + if (nData != FlashEmpty) return FALSE; + } + else + if (*(UINTN*)pDest != FlashEmpty) return FALSE; + } + } + + // since the address may not be INT_SIZE aligned, this checks + // the rest of the data + for ( ; Size > 0; Size--, pDest++) + { + if (FlashNotMemoryMapped) + { + UINT8 nData=0; + Flash->Read(pDest, 1, &(UINT8)nData); + if (nData != FLASH_EMPTY_BYTE) return FALSE; + } + else + if (*pDest != FLASH_EMPTY_BYTE) return FALSE; + } + + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvProgram +// +// Description: This function programms Size amount of flash starting with Address +// +// Input: IN VOID *Address - pointer to flash to programm +// IN UINTN Size - size of the data to programm +// VOID *Data - pointer to the data to be programed +// +// Output: BOOLEAN - TRUE if pDest is clean, otherwice FALSE +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN NvProgram(IN VOID *Address, UINTN Size, VOID *Data) +{ + BOOLEAN Status; + BOOLEAN Programmable,Equal; + + if (Size==0) return TRUE; + + IsProgrammableOrEqual(Address,Data,Size,&Programmable,&Equal); + + if (Equal) return TRUE; + + if (!Programmable) return FALSE; + + Status = FlashProgram(Address,Data,(UINT32)Size); + + if (Status) + { + if (FlashNotMemoryMapped) + { + UINT8 nData=0; + UINTN Count=0; + for ( Count=0; Count<Size; Count++) + { + Flash->Read((UINT8 *)Address+Count, 1, &nData ); + Status = ( nData == *((UINT8 *)Data+Count) ); + if (!Status) break; + } + } + else + Status = ( MemCmp(Address,Data,Size) == 0 ); + + } + + if (!Runtime && !Status) ERROR_CODE(DXE_FLASH_UPDATE_FAILED,EFI_ERROR_MAJOR); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SelectiveAllocate +// +// Description: This function returns pointer to allocated memory to use as +// temp buffer for any occasions. If NvramDriverBuffer is not 0 - +// memory allocated previously will be used. If not - function will +// allocate memory with the Size - and return pointer to it. +// +// Input: IN BOOLEAN FirstPart - if TRUE - first part of NvramDriverBuffer +// will be used. +// IN UINTN Size - size of memory to allocate. +// +// Output: UINT8* - pointer to allocated memory. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT8* SelectiveAllocate (BOOLEAN FirstPart, UINTN Size) +{ + if (NvramDriverBuffer){ + if (FirstPart){ + if (!FirstPartAlloc){ + FirstPartAlloc = TRUE; + return (UINT8*)NvramDriverBuffer; + }else return NULL; + }else{ + if (!SecondPartAlloc){ + SecondPartAlloc = TRUE; + return (UINT8*)(NvramDriverBuffer + NvramDriverBufferSize / 3 * 2); + }else return NULL; + } + }else{ + if (!Runtime){ +#ifdef DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME + if (NoAccessOutsideofSmm){ + UINT8 *Buffer; + EFI_STATUS Status = pSmst->SmmAllocatePool ( + EfiRuntimeServicesData,Size, &Buffer + ); + if (EFI_ERROR(Status)) return NULL; + return Buffer; + } + else +#endif + return (UINT8*)Malloc(Size); + } + } + return NULL; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SelectiveFree +// +// Description: This function free memory allocated for temp buffer +// for any occasions. If address passed to this function fits +// (NvramDriverBuffer + it's size) range memory allocated in +// NvramDriverBuffer will be released. If not - function will +// call FreePool routine. +// +// Input: UINT8* Target - pointer to the begining of memory to free +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID SelectiveFree (UINT8* Target) +{ + if (NvramDriverBuffer){ + if (Target == (UINT8*) NvramDriverBuffer){ + FirstPartAlloc = FALSE; + return; + } + if (Target == (UINT8*) (NvramDriverBuffer + NvramDriverBufferSize / 3 * 2)){ + SecondPartAlloc = FALSE; + return; + } + } + if (!Runtime){ +#ifdef DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME + if (NoAccessOutsideofSmm) pSmst->SmmFreePool (Target); + else +#endif + pBS->FreePool(Target); + } + return; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvErase +// +// Description: This function erases Size amount of flash starting with Address +// +// Input: IN VOID *Address - pointer to flash to erase +// IN UINTN Size - size of the flash to erase +// +// Output: BOOLEAN - TRUE or FALSE based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN NvErase(IN VOID *Address, UINTN Size) +{ + UINT8* pStart = (UINT8*)Address; + UINT8* pEnd = pStart+Size; + UINT8* pStartBlock = (UINT8*)BLOCK(pStart); + UINT8* pEndBlock = (UINT8*)BLOCK(pEnd-1)+FlashBlockSize; + UINTN PrologSize = pStart - pStartBlock; + UINTN EpilogSize = pEndBlock-pEnd; + UINT8* pBuffer=NULL; + UINT8* p; + BOOLEAN ok; + + if ( Size==0 || IsClean(Address,Size) ) return TRUE; + + if (PrologSize+EpilogSize) + { + pBuffer = SelectiveAllocate (TRUE, (PrologSize + EpilogSize)); + if (pBuffer == NULL) return FALSE; + MemCpy(pBuffer,pStartBlock,PrologSize); + MemCpy(pBuffer+PrologSize,pEnd,EpilogSize); + } + + //erase first block + if (ok=FlashEraseBlock(pStartBlock)) + { + if (PrologSize) ok=NvProgram(pStartBlock,PrologSize,pBuffer); + + if (ok) + { + //erase other blocks + for (p=pStartBlock+=FlashBlockSize; p!=pEndBlock; p+=FlashBlockSize) + { + if (!(ok=FlashEraseBlock(p))) break; + } + + if (ok && EpilogSize) ok=NvProgram(pEnd,EpilogSize,pBuffer+PrologSize); + } + } + + if (pBuffer) SelectiveFree (pBuffer); + + if (!ok) ERROR_CODE(DXE_FLASH_UPDATE_FAILED,EFI_ERROR_MAJOR); + + return ok; +} + +VARIABLE_INTERFACE MemInterface = {DummyUpdateRoutine, DummyUpdateRoutine, MemErase, MemProgram}; +VARIABLE_INTERFACE NvInterface = {NvEnableWrites, NvDisableWrites, NvErase, NvProgram}; + +#ifdef HYBRID_NV_INTERFACE + +UINTN HybridGetAddressDelta(UINT8 *Address, UINTN Size){ + if (VarStoreInfo.NvInfo == 0) return VarStoreInfo.AddressDelta; +//Sometimes VarStoreInfo.NvInterface is used to update +//store other than VarStoreInfo.NvramInfo. +//For example during UpdateFtVarstore it is used to update backup store. +//This function is used to fall-back to non-hybrid interface if varstore other than +//VarStoreInfo.NvramInfo is being updated. + return + ( Address >= VarStoreInfo.NvInfo->NvramAddress + && Address+Size + <= VarStoreInfo.NvInfo->NvramAddress + + VarStoreInfo.NvInfo->NvramSize + ) ? VarStoreInfo.AddressDelta : 0; +} + +BOOLEAN HybridEnableWrites(IN VOID *Address, UINTN Size){ + UINTN Delta = HybridGetAddressDelta(Address,Size); + return NvEnableWrites(Delta+(UINT8*)Address, Size); +} + +BOOLEAN HybridDisableWrites(IN VOID *Address, UINTN Size){ + UINTN Delta = HybridGetAddressDelta(Address,Size); + return NvDisableWrites(Delta+(UINT8*)Address, Size); +} + +BOOLEAN HybridErase(IN VOID *Address, UINTN Size){ + BOOLEAN ok; + UINTN Delta = HybridGetAddressDelta(Address,Size); + ok = NvErase(Delta+(UINT8*)Address, Size); + // Zero Delta implies that there is no memory buffer + if (Delta==0) return ok; + if (ok) return MemErase(Address, Size); + // Flash update operation has failed. + // The memory buffer is out of synch with the flash device. + // Re-synchronize the mememory buffer by reading flash device. + if (FlashNotMemoryMapped) + Flash->Read(Delta+(UINT8*)Address, Size, Address); + else + MemCpy(Address, Delta+(UINT8*)Address, Size); + return FALSE; +} + +BOOLEAN HybridProgram(IN VOID *Address, UINTN Size, VOID *Data){ + BOOLEAN ok; + UINTN Delta = HybridGetAddressDelta(Address,Size); + ok = NvProgram(Delta+(UINT8*)Address, Size, Data); + // Zero Delta implies that there is no memory buffer + if (Delta==0) return ok; + if (ok) return MemProgram(Address, Size, Data); + // Flash update operation has failed. + // The memory buffer is out of synch with the flash device. + // Re-synchronize the mememory buffer by reading flash device. + if (FlashNotMemoryMapped) + Flash->Read(Delta+(UINT8*)Address, Size, Address); + else + MemCpy(Address, Delta+(UINT8*)Address, Size); + return FALSE; +} + +VARIABLE_INTERFACE HybridInterface = {HybridEnableWrites, HybridDisableWrites, HybridErase, HybridProgram}; + +VOID InitHybridInterface(NVRAM_STORE_INFO *NvStore){ + EFI_STATUS Status; + //We can't use InitVolatileStore here because it will screw up SelectiveAllocate/SelectiveFree logic. + + //TODO: When DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME is defined, we assume that + //DXE Variable services will be replaced prior to transitioning to runtime. + //If this will not happen, the NVRAM driver may not work properly. + //It may either crash (or crash the Windows), or generate false garbage collections. + //To support fall back scenario the memory allocation below and registration of the virtual address change event must be changed + VarStoreInfo.NvramFlashAddress = NvStore->NvramAddress; + Status = pBS->AllocatePool ( +#ifdef DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME + EfiBootServicesData, +#else + EfiRuntimeServicesData, +#endif + NvStore->NvramSize, &NvStore->NvramAddress + ); + if (!EFI_ERROR(Status)){ + VarStoreInfo.NvInterface=&HybridInterface; + MemCpy(NvStore->NvramAddress,VarStoreInfo.NvramFlashAddress,NvStore->NvramSize); + NVRAM_TRACE((TRACE_DXE_CORE,"NVRAM: working in hybrid mode\n")); + }else{ + VarStoreInfo.NvInterface=&NvInterface; + NvStore->NvramAddress = VarStoreInfo.NvramFlashAddress; + } + //We altered content of the varstore. Let's reinitialize it. + NvInitInfoBuffer( + NvStore, VarStoreInfo.HeaderLength, + NVRAM_STORE_FLAG_NON_VALATILE + ); + VarStoreInfo.AddressDelta=VarStoreInfo.NvramFlashAddress-NvStore->NvramAddress; +} + +BOOLEAN SwapVarstoresInHybridMode(NVRAM_STORE_INFO *BackupInfo){ + UINT8* OriginalNvramFlashAddress; + if ( VarStoreInfo.NvramFlashAddress == 0 ) return FALSE; + OriginalNvramFlashAddress=VarStoreInfo.NvramFlashAddress; + + VarStoreInfo.NvramFlashAddress = VarStoreInfo.BackupAddress; + // Zero AddressDelta implies that the memory buffer is no longer used. + if (VarStoreInfo.AddressDelta!=0){ + VarStoreInfo.AddressDelta=VarStoreInfo.NvramFlashAddress-VarStoreInfo.NvInfo->NvramAddress; + + MemCpy( + VarStoreInfo.NvInfo->NvramAddress,VarStoreInfo.BackupAddress, + VarStoreInfo.NvInfo->NvramSize + ); + } + BackupInfo->NvramAddress = VarStoreInfo.NvInfo->NvramAddress; + BackupInfo->NvramSize = VarStoreInfo.NvInfo->NvramSize; + NvInitInfoBuffer( + BackupInfo, VarStoreInfo.HeaderLength, VarStoreInfo.NvInfo->Flags + ); + VarStoreInfo.BackupAddress = OriginalNvramFlashAddress; + return TRUE; +} + +VOID HybridStoreToRealStore(NVRAM_STORE_INFO *InInfo, NVRAM_STORE_INFO *OutInfo){ + *OutInfo = *InInfo; + OutInfo->NvramAddress = VarStoreInfo.NvramFlashAddress; + OutInfo->NvramGuidsAddress = (EFI_GUID*)((UINT8*)OutInfo->NvramGuidsAddress + VarStoreInfo.AddressDelta); + OutInfo->pEndOfVars += VarStoreInfo.AddressDelta; + OutInfo->pFirstVar += VarStoreInfo.AddressDelta; + OutInfo->pLastReturned=0; +} + +#ifdef DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME +VOID ReallocateHybridVarstoreToSmm(){ + NVRAM_STORE_INFO *Info = VarStoreInfo.NvInfo; + UINT8* SmmBuffer; + UINT32 i; + UINT8* NvramAddress; + UINT8* EndOfVars; + + EFI_STATUS Status = pSmst->SmmAllocatePool ( + EfiRuntimeServicesData, + Info->NvramSize, &SmmBuffer + ); + if (EFI_ERROR(Status)){ + // Zero AddressDelta implies that the memory buffer is no longer used. + VarStoreInfo.AddressDelta=0; + return; + } + MemCpy( + SmmBuffer,Info->NvramAddress,Info->NvramSize + ); + VarStoreInfo.AddressDelta=SmmBuffer-Info->NvramAddress; + NvramAddress = Info->NvramAddress; + EndOfVars= Info->pEndOfVars; + // Fix up the main NVRAM store and nested variable stores. + // An example of a nested store is the defaults store. + for (i=0; i<VarStoreInfo.InfoCount; i++){ + // If a store is embedded into the main NVRAM store, + // fix it up with the SMM buffer address + if ( VarStoreInfo.NvramInfo[i].NvramAddress >= NvramAddress + && VarStoreInfo.NvramInfo[i].pEndOfVars <= EndOfVars + ){ + VarStoreInfo.NvramInfo[i].NvramAddress += VarStoreInfo.AddressDelta; + VarStoreInfo.NvramInfo[i].NvramGuidsAddress = (EFI_GUID*)((UINT8*)VarStoreInfo.NvramInfo[i].NvramGuidsAddress + VarStoreInfo.AddressDelta); + VarStoreInfo.NvramInfo[i].pEndOfVars += VarStoreInfo.AddressDelta; + VarStoreInfo.NvramInfo[i].pFirstVar += VarStoreInfo.AddressDelta; + VarStoreInfo.NvramInfo[i].pLastReturned=0; + } + } + VarStoreInfo.AddressDelta=VarStoreInfo.NvramFlashAddress-SmmBuffer; +} +#endif // DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME +#endif + +#ifdef DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME +VOID ReallocateVolatileVarstoreToSmm(){ + NVRAM_STORE_INFO *Info = VarStoreInfo.MemInfo; + UINT8* SmmBuffer; + UINTN Delta; + + EFI_STATUS Status = pSmst->SmmAllocatePool ( + EfiRuntimeServicesData, + Info->NvramSize, &SmmBuffer + ); + if (EFI_ERROR(Status)){ + //TODO: Shutdown non-valatile services; + ASSERT(FALSE); + return; + } + MemCpy( + SmmBuffer,Info->NvramAddress,Info->NvramSize + ); + Delta=SmmBuffer-Info->NvramAddress; + Info->NvramAddress = SmmBuffer; + Info->NvramGuidsAddress = (EFI_GUID*)((UINT8*)Info->NvramGuidsAddress + Delta); + Info->pEndOfVars += Delta; + Info->pFirstVar += Delta; + Info->pLastReturned=0; +} +#endif + +/////////////////////////////////////////////////////////////////////////// +//Cache operations +#define NV_CACHE_SUPPORT 1 + +typedef struct +{ + DLINK Link; + NVAR *Nvar; + NVAR *FinalDataNvar; + UINT32 InfoIndex; + CHAR16 Name[8]; +} VAR_INDEX_ENTRY; + +typedef struct +{ + DLIST LetterIndex['z'-'a'+1]; + DLIST OtherIndex; + DLIST Blanks; + UINT8 *Buffer; + UINTN UsedSize; + UINTN BufferSize; +} VAR_INDEX; + +#if !NV_CACHE_SUPPORT +VAR_INDEX *VarIndexPtr=NULL; +#else +#define VARIABLE_INDEX_SIZE 0x10000 + +VAR_INDEX VarIndex; +VAR_INDEX *VarIndexPtr=&VarIndex; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsNvramRuntime +// +// Description: This function returns the value of Runtime local variable +// +// Input: None +// +// Output: BOOLEAN - current value of Runtime local variable +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsNvramRuntime() +{ + return Runtime; +} + +BOOLEAN AreBtVariablesHidden() +{ + return HideBtVariables && Runtime; +} +EFI_STATUS ShowBootTimeVariables (BOOLEAN Show){ + HideBtVariables = !Show; + TRACE((-1,"Setting HideBtVariables to %d\n",HideBtVariables)); + return EFI_SUCCESS; +} + +EFI_STATUS InstallNvramControlSmmProtocol(){ + return pSmst->SmmInstallConfigurationTable( + pSmst, &gAmiNvramControlProtocolGuid, &NvramControl, sizeof(NvramControl) + ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IndexGetList +// +// Description: This function gets list of variables starting with FirstLetter +// +// Input: CHAR16 FirstLetter - letter to search +// +// Output: DLIST* - pointer to list of Var starting with FirstLetter +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +DLIST* IndexGetList(CHAR16 FirstLetter) +{ + //convert to lower case + if (FirstLetter>='A'&&FirstLetter<='Z') FirstLetter -= 'A'; + else if (FirstLetter>='a'&&FirstLetter<='z') FirstLetter -= 'a'; + else return &VarIndexPtr->OtherIndex; + + return &VarIndexPtr->LetterIndex[FirstLetter]; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IndexGetListNvar +// +// Description: This function gets list of variables starting with First Letter of Nvar +// +// Input: NVAR *Nvar - pointer to Var +// +// Output: DLIST* - pointer to list of Var +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +DLIST* IndexGetListNvar(NVAR *Nvar) +{ + VOID *NamePtr; + CHAR16 FirstLetter; + + NamePtr = NvGetName(Nvar); + FirstLetter = (Nvar->flags&NVRAM_FLAG_ASCII_NAME) ? *(CHAR8*)NamePtr : *(CHAR16*)NamePtr; + return IndexGetList(FirstLetter); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IndexFindVariableEntry +// +// Description: This function searches for Var with specific GUID +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// OUT UINTN *VariableNameSize - size of Var name +// OUT NVRAM_STORE_INFO **Info - double pointer to NVRAM_STORE_INFO structure +// OUT BOOLEAN *UnindexedExists - indicator, that there is unindexed variables +// +// Output: VAR_INDEX_ENTRY* - pointer to Var's Index entry found; NULL if not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VAR_INDEX_ENTRY* IndexFindVariableEntry( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINTN *VariableNameSize, + OUT NVRAM_STORE_INFO **Info, OUT BOOLEAN *UnindexedExists +) +{ + DLINK *Link; + VAR_INDEX_ENTRY* Entry; + UINTN Count; + DLIST *List; + BOOLEAN CorruptedEntryFound; + + if (VarIndexPtr==NULL) + { + *UnindexedExists=TRUE; + return NULL; + } + + List = IndexGetList(VariableName[0]); + CorruptedEntryFound = FALSE; + + for (Link=List->pHead, Count=0; Link!=NULL; Link=Link->pNext, Count++) + { + UINTN i; + Entry = OUTTER(Link,Link, VAR_INDEX_ENTRY); + + for (i=0; i<sizeof(Entry->Name)/sizeof(CHAR16)&&Entry->Name[i]; i++) + if (Entry->Name[i]!=VariableName[i+1]) break; + + if (Entry->Name[i]&&Entry->Name[i]!=VariableName[i+1]) continue; + + if(!NvIsVariable( Entry->Nvar, + &VarStoreInfo.NvramInfo[Entry->InfoIndex] + ) + ){ + CorruptedEntryFound = TRUE; + continue; + } + + if (NvVarEq( + Entry->Nvar,VariableName,VendorGuid, + VariableNameSize,&VarStoreInfo.NvramInfo[Entry->InfoIndex] + ) + ) break; + } + + //entry found + if (Link!=NULL) + { + *Info=&VarStoreInfo.NvramInfo[Entry->InfoIndex]; + //VariableNameSize has already been initialized by the NvVarEq call + //Make sure the cached final data Nvar is valid + if (Entry->FinalDataNvar==NULL) + Entry->FinalDataNvar=NvGetDataNvar(Entry->Nvar, *Info); + + return Entry; + } + + *UnindexedExists=CorruptedEntryFound || Count<List->Size; + return NULL; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IndexFindVariable +// +// Description: This function searches for Var with specific GUID +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// OUT UINTN *VariableNameSize - size of Var name +// OUT NVRAM_STORE_INFO **Info - double pointer to NVRAM_STORE_INFO structure +// OUT BOOLEAN *UnindexedExists - indicator, that there is unindexed variables +// +// Output: NVAR* - pointer to Var found; NULL if not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +NVAR* IndexFindVariable( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINTN *VariableNameSize, + OUT NVRAM_STORE_INFO **Info, OUT BOOLEAN *UnindexedExists +) +{ + VAR_INDEX_ENTRY* Entry = IndexFindVariableEntry( + VariableName, VendorGuid, + VariableNameSize, + Info, UnindexedExists + ); + if (Entry != NULL) return Entry->Nvar; + + return NULL; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IndexGetBlankEntry +// +// Description: This function searches for the blank entry in VarIndexPtr structure +// +// Input: NONE +// +// Output: VAR_INDEX_ENTRY* - pointer to the blank entry, NUUL if no space +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VAR_INDEX_ENTRY* IndexGetBlankEntry() +{ + VAR_INDEX_ENTRY* Entry; + //---Check if there is space in buffer----- + if (VarIndexPtr->UsedSize<=VarIndexPtr->BufferSize-sizeof(VAR_INDEX_ENTRY)) + { + Entry = (VAR_INDEX_ENTRY*)(VarIndexPtr->Buffer+VarIndexPtr->UsedSize); + VarIndexPtr->UsedSize+=sizeof(VAR_INDEX_ENTRY); + } + //---If not - check in blanks-------- + else if (!DListEmpty(&VarIndexPtr->Blanks)) + { + Entry = OUTTER( + VarIndexPtr->Blanks.pTail, + Link, VAR_INDEX_ENTRY + ); + DListDelete(&VarIndexPtr->Blanks,&Entry->Link); + } + + else + { + Entry = NULL; + } + + return Entry; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IndexAddVariable +// +// Description: This function adds new Var +// +// Input: NVAR *Nvar - pointer to Var +// IN NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID IndexAddVariable( + IN NVAR *Nvar, IN NVRAM_STORE_INFO *Info +) +{ + DLIST *List; + VAR_INDEX_ENTRY *Entry; + UINTN i; + VOID *NamePtr; + + if (VarIndexPtr==NULL) return ; + + List = IndexGetListNvar(Nvar); + Entry = IndexGetBlankEntry(); + + if (Entry==NULL) + { + List->Size++; + return; + } + + Entry->Nvar=Nvar; + Entry->FinalDataNvar=NULL; + Entry->InfoIndex= (UINT32)(Info-&VarStoreInfo.NvramInfo[0]); + ASSERT(Entry->InfoIndex<VarStoreInfo.InfoCount) + NamePtr=NvGetName(Nvar); + + if (Nvar->flags&NVRAM_FLAG_ASCII_NAME) + { + CHAR8 *N = (CHAR8*)NamePtr+1; + + for (i=0; i<sizeof(Entry->Name)/sizeof(CHAR16)-1&&N[i]!=0; i++) + Entry->Name[i]=N[i]; + } + + else + { + CHAR16 *N = (CHAR16*)NamePtr+1; + + for (i=0; i<sizeof(Entry->Name)/sizeof(CHAR16)-1&&N[i]!=0; i++) + Entry->Name[i]=N[i]; + } + + Entry->Name[i]=0; + DListAdd(List,&Entry->Link); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IndexUpdateVariable +// +// Description: This function searces for Var and if it is found updates it, or add new var otherwise +// +// Input: NVAR *Nvar - pointer to Var +// IN NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID IndexUpdateVariable( + IN NVAR *Nvar, IN NVRAM_STORE_INFO *Info +) +{ + VAR_INDEX_ENTRY *Entry=NULL; + DLIST *List = IndexGetListNvar(Nvar); + DLINK *Link; + + if (VarIndexPtr==NULL) return ; + + for (Link=List->pHead; Link!=NULL; Link=Link->pNext) + { + VAR_INDEX_ENTRY *TmpEntry = OUTTER(Link,Link, VAR_INDEX_ENTRY); + + if(!NvIsVariable(TmpEntry->Nvar, + &VarStoreInfo.NvramInfo[TmpEntry->InfoIndex] + ) + ) continue; + + if (NvarEqNvar(TmpEntry->Nvar,&VarStoreInfo.NvramInfo[TmpEntry->InfoIndex],Nvar,Info)) + { + Entry=TmpEntry; + break; + } + } + + if (Entry==NULL) + { + IndexAddVariable(Nvar,Info); + } + else + { + Entry->Nvar=Nvar; + Entry->FinalDataNvar=NULL; + Entry->InfoIndex= (UINT32)(Info-&VarStoreInfo.NvramInfo[0]); + ASSERT(Entry->InfoIndex<VarStoreInfo.InfoCount) + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IndexDeleteVariable +// +// Description: This function deletes Var and adds it's entry in VarIndexPtr to blanks +// +// Input: NVAR *Nvar - pointer to Var to delete +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID IndexDeleteVariable(NVAR *Nvar) +{ + VAR_INDEX_ENTRY *Entry=NULL; + DLIST *List = IndexGetListNvar(Nvar); + DLINK *Link; + + if (VarIndexPtr==NULL) return ; + + for (Link=List->pHead; Link!=NULL; Link=Link->pNext) + { + Entry = OUTTER(Link,Link, VAR_INDEX_ENTRY); + + if (Entry->Nvar==Nvar) + { + DListDelete(List,&Entry->Link); + DListAdd(&VarIndexPtr->Blanks,&Entry->Link); + return; + } + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IndexDeleteVariableEntry +// +// Description: This function deletes Var and adds it's entry in VarIndexPtr to blanks +// +// Input: VAR_INDEX_ENTRY *Entry - pointer to Entry to delete +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID IndexDeleteVariableEntry(VAR_INDEX_ENTRY *Entry) +{ + DLIST *List; + if (Entry == NULL) return; + + List = IndexGetListNvar(Entry->Nvar); + + if (VarIndexPtr==NULL) return ; + + DListDelete(List,&Entry->Link); + DListAdd(&VarIndexPtr->Blanks,&Entry->Link); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IndexReset +// +// Description: This function resets the VarIndexPtr and updates VarStoreInfo structures +// +// Input: NONE +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID IndexReset() +{ + INTN i; + + if (VarIndexPtr==NULL) return ; + + VarIndexPtr->UsedSize=0; + + for (i=0; i<='z'-'a'; i++) DListInit(&VarIndexPtr->LetterIndex[i]); + //---Reset fields in VarIndexPtr--------------- + DListInit(&VarIndexPtr->OtherIndex); + DListInit(&VarIndexPtr->Blanks); + + for (i=(INTN)VarStoreInfo.InfoCount-1; i>=0; i--) + { + NVRAM_STORE_INFO *Info = &VarStoreInfo.NvramInfo[i]; + NVAR *Nvar=(NVAR*)Info->pFirstVar; + + if (!NvIsVariable(Nvar,Info)) continue; + + for (; Nvar!=NULL; Nvar=NvGetNextValid(Nvar,Info)) + IndexUpdateVariable(Nvar,Info); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IndexInit +// +// Description: This function allocates memory for Var Index Buffer and fils pointer to it in +// VarIndexPtr stucture +// +// Input: NONE +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID IndexInit() +{ + EFI_STATUS Status = pBS->AllocatePool( + EfiBootServicesData, + VARIABLE_INDEX_SIZE, + &VarIndexPtr->Buffer + ); + + if (EFI_ERROR(Status)) + { + VarIndexPtr=NULL; + return; + } + VarIndexPtr->BufferSize = VARIABLE_INDEX_SIZE; + IndexReset(); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IndexExitBs +// +// Description: This function resets VarIndexPtr to NULL on Exit BS +// +// Input: NONE +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID IndexExitBs() +{ + VarIndexPtr = NULL; +} + +VOID IndexVirtualFixup() +{ + +} +#endif +/////////////////////////////////////////////////////////////////////////// +//Basic operations +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsEnoughSpace +// +// Description: This function checks is there is Size space avaiable in NVRAM_STORE_INFO +// +// Input: NVRAM_STORE_INFO* Info - pointer to NVRAM_STORE_INFO stucture +// UINTN Size - Size to check for +// +// Output: BOOLEAN - TRUE if space avaiable, FALSE otherwise +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsEnoughSpace(NVRAM_STORE_INFO* Info, UINTN Size) +{ + return ( Info->pEndOfVars + Size + <= Info->NvramAddress+Info->NvramSize - sizeof(EFI_GUID)*(Info->NextGuid+1) - sizeof(NVAR) + ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: RecoverFromFlashUpdateFailure +// +// Description: This function checks is there was a flash update failure and signal about it +// to CheckStore +// +// Input: NVRAM_STORE_INFO* Info - pointer to NVRAM_STORE_INFO stucture +// VOID *EndOfVars - End of Vars pointer +// UINTN DataSize - Size of data, that was programed +// NVAR *PrevVar - pointer to previous instance of Var +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID RecoverFromFlashUpdateFailure( + NVRAM_STORE_INFO *Info, VOID *EndOfVars, UINTN DataSize, NVAR *PrevVar +) +{ + UINT8 *p; + NVAR *NewVar; + + //Nothing has been programmed. Just return + if (EndOfVars==Info->pEndOfVars) return; + + NewVar = (NVAR*)Info->pEndOfVars; + //Check if variable size has been programmed correctly + if (NewVar->size==DataSize) + { + // Let's see if the signature is correct. + // If the signature is correct, let's see if + // the 'next' field has been properly updated. + if ( NewVar->signature==NvramSignature + && NvGetDataNvar(PrevVar, Info) != NewVar + ){ + // if we are here, the next field has not been properly udpated + // leave pInfo->pEndOfVars at the address of the last record. + Info->LastVarSize=(VAR_SIZE_TYPE)DataSize; + return; + } + //Yes, the size has been programmed correctly. + //NvGetNextNvar routine is smart enough to skip + //invalid records with valid size. + Info->pEndOfVars+=DataSize;//Update Info->pEndOfVars + Info->LastVarSize=0;//Opearaion failed, set Info->LastVarSize to zero + return; + } + + //check if something has actually been programmed + for (p=Info->pEndOfVars; p<(UINT8*)EndOfVars && *p==FLASH_EMPTY_BYTE; p++) ; + + //if nothing has been programmed, just return + if (p==EndOfVars) return; + + //if we reached this point, NVRAM store is corruped + //Set pInfo->pEndOfVars at the address of corruption. + //This will trigger recovery operation + //(See 'Error Recovery' section at the end of the DxeSetVariable routine). + Info->pEndOfVars = p; + Info->LastVarSize=(VAR_SIZE_TYPE)DataSize; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetVarAuthExtFlags +// +// Description: This function returns Security fields Mc and KeyHash form existing +// Var in Var store +// It is called called every time variable with one of +// UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES is being verified. +// +// Input: NVAR *Var pointer to the 1st instance of Var +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// OUT EXT_SEC_FLAGS->MonotonicCount - value of MC or TIME stamp +// OUT EXT_SEC_FLAGS->KeyHash - pointer to memory, allocated by caller, +// where Hash of PublicKeyDigest will be returned. +// +// Output: *EXT_SEC_FLAGS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +GetVarAuthExtFlags( + IN NVAR *Var, + IN NVRAM_STORE_INFO *pInfo, + OUT EXT_SEC_FLAGS *ExtFlags +) +{ + if(Var==NULL || pInfo==NULL || ExtFlags==NULL) + return; +// Return Authenticate attributes along with NonVolitile attrib + if ( pInfo->Flags & NVRAM_STORE_FLAG_NON_VALATILE ) + ExtFlags->AuthFlags |=EFI_VARIABLE_NON_VOLATILE; + + if(Var->flags & (NVRAM_FLAG_AUTH_WRITE | NVRAM_FLAG_EXT_HEDER)) { + ExtFlags->AuthFlags |= (UINT8)(*NvGetExtFlags (Var) & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES) ;//(NVRAM_eFLAG_TIME_BASED_AUTH_WRITE | NVRAM_eFLAG_AUTH_WRITE)); + ExtFlags->Mc = (*(UINT64*)(NvGetExtFlags (NvGetDataNvar(Var, pInfo)) + 1)); + MemCpy(&ExtFlags->KeyHash[0], (VOID*)(NvGetExtFlags (Var) + 1 + 8), HASH_SHA256_LEN); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FlashMemFlashWrite +// +// Description: This function used to copy some information from one part of +// flash to another, when flash is not memory mapped. It uses temporary +// buffer one or more times. +// +// Input: IN VARIABLE_INTERFACE *Interface - pointer to Variable interface +// IN OUT UINT8 **PointerTo - Destination +// IN VOID *From - Source +// IN UINTN SizeToWrite - in bytes. +// IN NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO stucture +// +// Output: *EXT_SEC_FLAGS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN +FlashMemFlashWrite( + IN VARIABLE_INTERFACE *Interface, + IN OUT UINT8 **PointerTo, + IN VOID *From, + IN UINTN SizeToWrite, + IN NVRAM_STORE_INFO *Info +) +{ + UINT8 TempMemory [256]; + UINT8 *TempFrom = (UINT8*)From; + UINT16 TempSize; + BOOLEAN Result; + + do + { + Interface->DisableUpdate(Info->NvramAddress,Info->NvramSize); + if (SizeToWrite <= 256) + TempSize = (UINT16) SizeToWrite; + else + { + TempSize = 256; + SizeToWrite -= 256; + } + MemCpy(TempMemory, TempFrom, TempSize); + Interface->EnableUpdate(Info->NvramAddress,Info->NvramSize); + Result = Interface->WriteBytes(*PointerTo, TempSize, TempMemory); + *PointerTo += TempSize; + if ((TempSize < 256) || (SizeToWrite == 0) || !Result) break; + TempFrom += TempSize; + } + while (TRUE); + return Result; +} +#if AuthVariable_SUPPORT +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FindVariable +// +// Description: This function searches for Var with specific GUID and Name +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// OUT UINT32* Attributes - Pointer to memory where Attributes will be returned +// IN OUT UINTN *DataSize - size of Var - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// OUT VOID *Data - Pointer to memory where Var is loacted +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS FindVariable( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes , + IN OUT UINTN *DataSize, OUT VOID **Data +) +{ + UINTN VariableNameSize; + NVRAM_STORE_INFO *Info; + NVAR *Nvar; + + Info = VarStoreInfo.NvInfo; + Nvar = (NVAR*)NvFindVariable(VariableName,VendorGuid,&VariableNameSize,Info); + + if ((Nvar != NULL) && (Data != NULL)) + { +// if (Runtime && !(Nvar->flags & NVRAM_FLAG_RUNTIME)) return EFI_NOT_FOUND; + if (Attributes) + if (EFI_ERROR(NvGetAttributesFromNvar(Nvar, Info, Attributes))) + return EFI_NOT_FOUND; + + *Data = (UINT8*)NvGetData(Nvar, VariableNameSize, DataSize, Info); + + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} +#endif + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CreateVariableEx +// +// Description: This function adds new variable to Varstore +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// IN UINT32 Attributes - attributes of Variable +// IN UINTN DataSize - size of Var data +// IN VOID *Data - pointer to the Var data +// OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure +// VARIABLE_INTERFACE *Interface - pointer to the interface with the Variable routins +// (OPTIONAL) NVAR* OldVar - in case of garbage collection pointer to the first i +// nstance of variable to get Monotonic Counter and Flags from +// (OPTIONAL) NVRAM_STORE_INFO *FromInfo - in case of garbage collection pointer to the +// store info strucrure - to get Public Key from +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CreateVariableEx( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data, + NVRAM_STORE_INFO *Info, VARIABLE_INTERFACE *Interface, OPTIONAL NVAR* OldVar, EXT_SEC_FLAGS *ExtSecFlags, + OPTIONAL VOID *AppendData, OPTIONAL UINTN AppendDataSize +) +{ + UINTN Size=sizeof(NVAR) + AppendDataSize, ExtSize = 0; + NVAR Var = {FLASH_EMPTY_SIGNATURE,0,FLASH_EMPTY_NEXT,NVRAM_FLAG_VALID}; + CHAR16* s; + EFI_GUID* Guid; + INT16 guid=0; + BOOLEAN ok; + UINT8 *p, *p1, Dummy, ExtFlags = 0; + + if (Attributes & EFI_VARIABLE_RUNTIME_ACCESS) + Var.flags |= NVRAM_FLAG_RUNTIME; +#if AuthVariable_SUPPORT + if ( Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD ) + Var.flags |= NVRAM_FLAG_HARDWARE_ERROR_RECORD; + if (Attributes & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES/*EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS*/) + { + Var.flags |= NVRAM_FLAG_EXT_HEDER | NVRAM_FLAG_AUTH_WRITE; + ExtSize = 1 + 8 + HASH_SHA256_LEN + 2; //ExtFlags + Monotonic Counter + PublicKeyDigest Hash + ExtSize + ExtFlags |= Attributes & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES; + // We store PublicKeyDigest Hash only in the first instance of Var in store to save space + } +#endif + if (NvramChecksumSupport) + { + Var.flags |= NVRAM_FLAG_EXT_HEDER; + if (ExtSize == 0) ExtSize += 4; // ExtSize - Ext Flag, Checksumm and Size + else ExtSize += 1; // Add Checksumm Feild + ExtFlags |= NVRAM_EXT_FLAG_CHECKSUM; + } + + //find GUID in the GUID area + for ( Guid=Info->NvramGuidsAddress + ; Guid>Info->NvramGuidsAddress-Info->NextGuid + && guidcmp(Guid,VendorGuid) + ; Guid-- + ) guid++; + + if (((OldVar != NULL) && (OldVar->flags & NVRAM_FLAG_GUID)) || (Info->NextGuid>255 && guid>=Info->NextGuid)) + { + Var.flags |= NVRAM_FLAG_GUID; + Size+=sizeof(EFI_GUID); + } + + else + { + Size+=1; + } + + //Alalize the name. Check if it has non basic Latin characters + for (s=VariableName; *s&&!*((CHAR8*)s+1); s++) ; + + if (!*s) + { + Var.flags |= NVRAM_FLAG_ASCII_NAME; + Size+=s-VariableName+1; + } + + else + { + while (*s++); + + Size+=(UINT8*)s-(UINT8*)VariableName; + } + if ((UINTN)(~0) - Size < DataSize + ExtSize) + return EFI_OUT_OF_RESOURCES; + + Size += DataSize + ExtSize; + + if (!IsEnoughSpace(Info,Size)) return EFI_OUT_OF_RESOURCES; + + Var.size=(VAR_SIZE_TYPE)Size; + Interface->EnableUpdate(Info->NvramAddress,Info->NvramSize); + p = Info->pEndOfVars; + + do + { + //Program Var at pEndOfVars + ok=Interface->WriteBytes(p,sizeof(NVAR),&Var); + p += sizeof(NVAR); + + if (!ok) break; + + //Program Guid + if (Var.flags&NVRAM_FLAG_GUID) + { + //program the whole guid + ok=Interface->WriteBytes(p,sizeof(EFI_GUID),VendorGuid); + p+=sizeof(EFI_GUID); + } + + else + { + //program the whole guid at NVRAM_GUIDS_ADDRESS - NextGuid + if (guid==Info->NextGuid) + { + ok=Interface->WriteBytes( + (UINT8*)(Info->NvramGuidsAddress-Info->NextGuid), + sizeof(EFI_GUID),VendorGuid + ); + Info->NextGuid++; + + if (!ok) break; + } + + //program guid(1 byte) at pEndOfVars+sizeof(NVAR); + ok=Interface->WriteBytes(p++,1,&guid); + } + + if (!ok) break; + + //Program name and data + if (Var.flags&NVRAM_FLAG_ASCII_NAME) + { + UINT8* q; + + for (q=(UINT8*)VariableName; *(CHAR16*)q && ok ; q+=2,p++) + ok = Interface->WriteBytes(p,1,q); + + if (ok) ok = Interface->WriteBytes(p++,1,q); //zero at end + } + + else + { + UINT16* q; + + for (q=VariableName; *q && ok ; q++,p+=2) + ok = Interface->WriteBytes(p,2,q); + + if (ok) + { + ok = Interface->WriteBytes(p,2,q); //zero at end + p+=2; + } + } + + if (!ok) break; + + //AppendWrite after Garbage collection + if (Attributes & EFI_VARIABLE_APPEND_WRITE) { + if (FlashNotMemoryMapped){ + ok=FlashMemFlashWrite(Interface, &p, AppendData, AppendDataSize, Info); + } + else + { + ok=Interface->WriteBytes(p,AppendDataSize,AppendData); + p+=AppendDataSize; + } + if (!ok) break; + } + + //Program data + ok=Interface->WriteBytes(p,DataSize,Data); + p+=DataSize; + p1=p; + + if (!ok) break; + + //---Fill Ext area--- + if (Attributes & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES/*EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS*/) + { + ok=Interface->WriteBytes(p, 1, &ExtFlags);//--Ext Flag + if (!ok) break; + p += 1; + ok=Interface->WriteBytes(p, 8, &ExtSecFlags->Mc);//--Monotonic counter + if (!ok) break; + p += 8; + ok=Interface->WriteBytes(p, HASH_SHA256_LEN, &ExtSecFlags->KeyHash[0]);//--Public Key Hash + if (!ok) break; + p = Info->pEndOfVars + Size - 2; + ok=Interface->WriteBytes(p, 2,&ExtSize);//--Ext Size + if (!ok) break; + } + if (NvramChecksumSupport) + { + if (!(Var.flags & NVRAM_FLAG_AUTH_WRITE)) // ???NVRAM_FLAG_EXT_HEDER + { + p = p1 + ExtSize; + //write ExtSize + ok=Interface->WriteBytes(p-sizeof(VAR_SIZE_TYPE),sizeof(VAR_SIZE_TYPE),&ExtSize); + if (!ok) break; + //write ExtFlags + ok=Interface->WriteBytes(p1, 1, &ExtFlags); + if (!ok) break; + //write checksum + if (FlashNotMemoryMapped) + Interface->DisableUpdate(Info->NvramAddress,Info->NvramSize); + + Dummy = NvCalculateNvarChecksum((NVAR*)Info->pEndOfVars); + + if (FlashNotMemoryMapped) + Interface->EnableUpdate(Info->NvramAddress,Info->NvramSize); + + //adjust to exclude empty checksum field + Dummy += FLASH_EMPTY_BYTE; + ok=Interface->WriteBytes(p-3, 1, &Dummy); + if (!ok) break; + } + else + { + p = p1 + ExtSize; + if (FlashNotMemoryMapped) + Interface->DisableUpdate(Info->NvramAddress,Info->NvramSize); + + Dummy = NvCalculateNvarChecksum((NVAR*)Info->pEndOfVars); + + if (FlashNotMemoryMapped) + Interface->EnableUpdate(Info->NvramAddress,Info->NvramSize); + //adjust to exclude empty checksum field + Dummy += FLASH_EMPTY_BYTE; + ok=Interface->WriteBytes(p-3, 1, &Dummy); + if (!ok) break; + } + } + //write a signature + ok=Interface->WriteBytes( + Info->pEndOfVars,sizeof(NvramSignature),(VOID*)&NvramSignature + ); + + } + while (FALSE); + + Interface->DisableUpdate(Info->NvramAddress,Info->NvramSize); + + if (ok) + { + Info->pEndOfVars += Size; + Info->LastVarSize=(VAR_SIZE_TYPE)Size; + } + + else + { + RecoverFromFlashUpdateFailure(Info,p,Size,(NVAR*)Info->pEndOfVars); + } + + return (ok) ? EFI_SUCCESS : EFI_DEVICE_ERROR; +} + +EFI_STATUS CreateVariable( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data, + NVRAM_STORE_INFO *Info, VARIABLE_INTERFACE *Interface, OPTIONAL NVAR* OldVar, EXT_SEC_FLAGS *ExtSecFlags +) +{ + return CreateVariableEx(VariableName, VendorGuid, Attributes, DataSize, + Data, Info, Interface, OldVar, ExtSecFlags, NULL, 0); +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: UpdateVariable +// +// Description: This function updates variable +// +// Input: IN NVAR *OldVar - pointer to the old Var +// IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN UINTN NameSize - size of the Var mane +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// IN UINT32 Attributes - attributes of Variable +// IN UINTN DataSize - size of Var data +// IN VOID *Data - pointer to the Var data +// OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure +// VARIABLE_INTERFACE *Interface - pointer to the interface with the Variable routins +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS UpdateVariable( + IN NVAR *OldVar, IN CHAR16 *VariableName, IN UINTN NameSize, + IN EFI_GUID *VendorGuid, IN UINT32 Attributes, + IN UINTN DataSize, IN VOID *Data, + IN OUT VAR_INDEX_ENTRY *OldVarEntry OPTIONAL, + IN EXT_SEC_FLAGS *ExtSecFlags, + NVRAM_STORE_INFO *Info, VARIABLE_INTERFACE *Interface +) +{ + UINTN OldDataSize; + VOID *OldData; + BOOLEAN ok; + UINTN Size, ExtSize = 0; + NVAR Var = {FLASH_EMPTY_SIGNATURE,0,FLASH_EMPTY_NEXT,NVRAM_FLAG_VALID|NVRAM_FLAG_DATA_ONLY}; + UINT8 *p, *p1, Dummy, ExtFlags = 0; + + if (!NvAttribEq(OldVar,Attributes,Info)) return EFI_INVALID_PARAMETER; + + if (OldVarEntry != NULL && OldVarEntry->FinalDataNvar != NULL) + OldData = NvGetData( OldVarEntry->FinalDataNvar, NameSize, &OldDataSize, Info ); + else + OldData = NvGetData( OldVar, NameSize, &OldDataSize, Info ); + + if (Attributes & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES/*EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS*/) + { + Var.flags |= NVRAM_FLAG_EXT_HEDER | NVRAM_FLAG_AUTH_WRITE; + ExtSize = 1 + 8 + 2; //ExtFlags + Monotonic Counter + ExtSize + // AuthFlags only set in 1st instance + // ExtFlags |= Attributes & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES; + } + //if new data equal to the old data don't do anything + if (NvramChecksumSupport) + { ExtFlags |= NVRAM_EXT_FLAG_CHECKSUM; + if (ExtSize == 0) ExtSize += 4; // ExtSize - Ext Flag, Checksumm and Size + else ExtSize += 1; // Add Checksumm Feild + if ( (Attributes & EFI_VARIABLE_APPEND_WRITE) == 0 + && OldDataSize == DataSize && !MemCmp(OldData, Data, DataSize) + && (OldVar->flags & NVRAM_FLAG_EXT_HEDER)) + return EFI_SUCCESS; + else Var.flags |= NVRAM_FLAG_EXT_HEDER; + } + else + if ( (Attributes & EFI_VARIABLE_APPEND_WRITE) == 0 + && OldDataSize == DataSize && !MemCmp(OldData, Data, DataSize)) + return EFI_SUCCESS; + + // Append write implementation + if (Attributes & EFI_VARIABLE_APPEND_WRITE) + Size=sizeof(NVAR)+ OldDataSize + DataSize + ExtSize; + else + Size=sizeof(NVAR)+ DataSize + ExtSize; + + if (!IsEnoughSpace(Info,Size)) return EFI_OUT_OF_RESOURCES; + + Var.size=(VAR_SIZE_TYPE)Size; + Interface->EnableUpdate(Info->NvramAddress,Info->NvramSize); + p = Info->pEndOfVars; + + //Program Var at pEndOfVars + do + { + ok=Interface->WriteBytes(p,sizeof(NVAR),&Var); + p += sizeof(NVAR); + + if (!ok) break; + + //Program data + //AppendWrite + if (Attributes & EFI_VARIABLE_APPEND_WRITE) { + if (FlashNotMemoryMapped){ + ok=FlashMemFlashWrite(Interface, &p, OldData, OldDataSize, Info); + } + else + { + ok=Interface->WriteBytes(p,OldDataSize,OldData); + p+=OldDataSize; + } + if (!ok) break; + } + // end Append write + ok=Interface->WriteBytes(p,DataSize,Data); + p+=DataSize; + p1 = p; + if (!ok) break; + + //---Fill Ext area--- + if (Attributes & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES/*EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS*/) + { + ok=Interface->WriteBytes(p, 1, &ExtFlags);//--Ext Flag + if (!ok) break; + p += 1; + ok=Interface->WriteBytes(p, 8, &ExtSecFlags->Mc);//--Monotonic counter + if (!ok) break; + p = Info->pEndOfVars + Size - 2; + ok=Interface->WriteBytes(p, 2,&ExtSize);//--Ext Size + if (!ok) break; + } + if (NvramChecksumSupport) + { + if (!(Var.flags & NVRAM_FLAG_AUTH_WRITE)) // ??? should be ExtFlags? + { + p = p1 + ExtSize; + //write ExtSize + ok=Interface->WriteBytes(p-sizeof(VAR_SIZE_TYPE),sizeof(VAR_SIZE_TYPE),&ExtSize); + if (!ok) break; + //write ExtFlags + ok=Interface->WriteBytes(p-ExtSize, 1, &ExtFlags); + if (!ok) break; + //write checksum + if (FlashNotMemoryMapped) + Interface->DisableUpdate(Info->NvramAddress,Info->NvramSize); + + Dummy = NvCalculateNvarChecksum((NVAR*)Info->pEndOfVars); + + if (FlashNotMemoryMapped) + Interface->EnableUpdate(Info->NvramAddress,Info->NvramSize); + + //adjust to exclude empty checksum field + Dummy += FLASH_EMPTY_BYTE; + ok=Interface->WriteBytes(p-3, 1, &Dummy); + if (!ok) break; + } + else + { + p = p1 + ExtSize; + if (FlashNotMemoryMapped) + Interface->DisableUpdate(Info->NvramAddress,Info->NvramSize); + + Dummy = NvCalculateNvarChecksum((NVAR*)Info->pEndOfVars); + + if (FlashNotMemoryMapped) + Interface->EnableUpdate(Info->NvramAddress,Info->NvramSize); + + //adjust to exclude empty checksum field + Dummy += FLASH_EMPTY_BYTE; + ok=Interface->WriteBytes(p-3, 1, &Dummy); + if (!ok) break; + } + } + //write a signature + ok=Interface->WriteBytes(Info->pEndOfVars,sizeof(NvramSignature),(VOID*)&NvramSignature); + + if (!ok) break; + //set Var.next; + + if (FlashNotMemoryMapped) + Interface->DisableUpdate(Info->NvramAddress,Info->NvramSize); + + if (OldVarEntry != NULL && OldVarEntry->FinalDataNvar != NULL) + OldVar=OldVarEntry->FinalDataNvar; + else + OldVar=NvGetDataNvar(OldVar,Info); + + if (FlashNotMemoryMapped) + Interface->EnableUpdate(Info->NvramAddress,Info->NvramSize); + + Var.next=(UINT32)(Info->pEndOfVars-(UINT8*)OldVar); + ok=Interface->WriteBytes((UINT8*)OldVar+NEXT_OFFSET,NEXT_SIZE,(UINT8*)&Var+NEXT_OFFSET); + } + while (FALSE); + + Interface->DisableUpdate(Info->NvramAddress,Info->NvramSize); + + if (ok) + { + if (OldVarEntry != NULL) + OldVarEntry->FinalDataNvar = (NVAR*)Info->pEndOfVars; + Info->pEndOfVars += Size; + Info->LastVarSize=(VAR_SIZE_TYPE)Size; + } + + else + { + RecoverFromFlashUpdateFailure(Info,p,Size,OldVar); + } + + return (ok) ? EFI_SUCCESS : EFI_DEVICE_ERROR; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DeleteVariable +// +// Description: This function delets variable +// +// Input: IN NVAR *Var - pointer to the Var to be deleted +// OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure +// VARIABLE_INTERFACE *Interface - pointer to the interface with the Variable routins +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DeleteVariable(IN NVAR *Var, NVRAM_STORE_INFO *Info, VARIABLE_INTERFACE *Interface) +{ + UINT8 flag = Var->flags^NVRAM_FLAG_VALID;//invert validity bit + BOOLEAN ok; + CHAR8 *WriteAddress = (UINT8*)Var+FLAG_OFFSET; + UINTN WriteSize = FLAG_SIZE; + Interface->EnableUpdate(WriteAddress,WriteSize); + ok=Interface->WriteBytes(WriteAddress,WriteSize,&flag); + Interface->DisableUpdate(WriteAddress,WriteSize); + return (ok) ? EFI_SUCCESS : EFI_DEVICE_ERROR; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CopyVariable +// +// Description: This function copyes variable from one Nvram store to another +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// IN UINTN DataSize - size of Var data +// IN VOID *Data - pointer to the Var data temprary storadge +// OUT NVRAM_STORE_INFO *FromInfo - pointer to NVRAM_STORE_INFO structure to copy from +// OUT NVRAM_STORE_INFO *ToInfo - pointer to NVRAM_STORE_INFO structure to copy to +// VARIABLE_INTERFACE *ToInterface - pointer to the interface with the Variable routins +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CopyVariable( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, +//Buffer used for temporary variable data storage + IN UINTN DataSize, IN VOID *Data, + NVRAM_STORE_INFO *FromInfo, NVRAM_STORE_INFO *ToInfo, + VARIABLE_INTERFACE *ToInterface +) +{ + EFI_STATUS Status; + UINT32 Attributes; + NVAR *nVar; + EXT_SEC_FLAGS ExtSecFlags = {0,0,{0}}; + + Status = NvGetVariable( + VariableName, VendorGuid, &Attributes, &DataSize, Data, + FromInfo, &nVar + ); + + if (EFI_ERROR(Status)) return Status; + + GetVarAuthExtFlags(nVar, FromInfo, &ExtSecFlags); + + if (nVar->flags & NVRAM_FLAG_AUTH_WRITE) + return CreateVariable( + VariableName, VendorGuid, Attributes, DataSize, Data, + ToInfo, ToInterface, nVar, &ExtSecFlags); + else + return CreateVariable( + VariableName, VendorGuid, Attributes, DataSize, Data, + ToInfo, ToInterface, nVar, NULL); +} + +//Varstore maintenance +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: VarNotInPreserveList +// +// Description: Looks for the provided variable in the preserved list. +// +// Input: IN CHAR16 *VarName - Variable name to be found. +// IN EFI_GUID *Guid - Variable GUID to be found. +// +// Output: BOOLEAN - Depending on result. +// TRUE - if not in list, FALSE - if in list. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN VarNotInPreserveList( + IN CHAR16 *VarName, + IN EFI_GUID *Guid +) +{ + SDL_VAR_ENTRY *Entry; + UINTN Index; + if (VarName == NULL || Guid == NULL) + return TRUE; // If it has no name or GUID - it is not in the list + // Determine the size in bytes of the variable name string. + + + // Scan list + for (Index = 0, Entry = gSdlVarLst; + Entry->Name != NULL; + Entry = &gSdlVarLst[++Index] ) + { + // Check the GUID's for a match. + if (!guidcmp(&Entry->Guid, Guid)) { + //NVRAM_TRACE((TRACE_DXE_CORE,"VarNotInPreserveList: GUID Match found.\n")); + // Compare variable name strings. + if (Wcscmp(Entry->Name, VarName) == 0){ + //NVRAM_TRACE((TRACE_DXE_CORE,"VarNotInPreserveList: Compleat Match found!!!.\n")); + // Match found! + return FALSE; + } + } + } + + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: VarNotInEfiGlobalVarList +// +// Description: Searches for the passed variable in the EFI Global Var lists and +// if found, makes sure, that it has the same attributes. +// +// Input: IN CHAR16 *VarName - Variable name to be found. +// IN UINT32 Attributes - Variable attributes. +// +// Output: BOOLEAN - Depending on result. +// TRUE - if not in list, FALSE - if in list. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN VarNotInEfiGlobalVarList ( + IN CHAR16 *VariNameToTest, + IN UINT32 Attributes + ) +{ + UINT32 i, j; + UINTN CommonLength; + + + // Search through list where names are strictly predefined + for (i = 0; gStdEfiVarList[i].Name != NULL; i ++) + { + if ((Wcscmp(gStdEfiVarList[i].Name, VariNameToTest) == 0) && + (gStdEfiVarList[i].Attributes == Attributes || Attributes == 0)) + return FALSE; + } + + // Look in the list where names could have 4 different hexadecimal numbers at the end + CommonLength = Wcslen(VariNameToTest) - 4; // Subtract 4 last characters, that can be different from those, that are in list + for (i = 0; gStdEfiVarListWildCard[i].Name != NULL; i ++) + { + if ((CommonLength + 4 == Wcslen(gStdEfiVarListWildCard[i].Name)) && + (MemCmp(gStdEfiVarListWildCard[i].Name, VariNameToTest, CommonLength * sizeof(CHAR16)) == 0) && + (gStdEfiVarListWildCard[i].Attributes == Attributes || Attributes == 0)) + { + + for (j = 0; j < 4;) + { + // if 4 lasrt characters are not hexadecimal numbers - this is not a legal Efi Global Variable + if ((VariNameToTest[CommonLength + j] >= L'0' && VariNameToTest[CommonLength + j] <= L'9') || + (VariNameToTest[CommonLength + j] >= L'a' && VariNameToTest[CommonLength + j] <= L'f') || + (VariNameToTest[CommonLength + j] >= L'A' && VariNameToTest[CommonLength + j] <= L'F')) + j ++; + else + return TRUE; + + } + return FALSE; + } + } + + return TRUE; + +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SkipSpecificNvar +// +// Description: Helper varstore filtering function. +// Skips the variable that corresponds to the passed in NVAR. +// +// Output: BOOLEAN +// TRUE - skip the variable +// FALSE - do not skip the variable +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN SkipSpecificNvar( + NVAR *SkipVar, CHAR16* VarName, EFI_GUID* VarGuid, + NVRAM_STORE_INFO *Info +){ + return SkipVar!=NULL && NvVarEq(SkipVar, VarName, VarGuid, NULL, Info); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SkipVarsWithDefaults +// +// Description: Helper varstore filtering function. +// Skips the variables that have defaults. +// +// Output: BOOLEAN +// TRUE - skip the variable +// FALSE - do not skip the variable +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN SkipVarsWithDefaults( + NVRAM_STORE_INFO *DefInfo, CHAR16* VarName, EFI_GUID* VarGuid, + NVRAM_STORE_INFO *Info +){ + return DefInfo!=NULL + && ( Wcscmp(VarName, (CHAR16*)StdDefaults)==0 + || Wcscmp(VarName, (CHAR16*)MfgDefaults)==0 + || NvFindVariable(VarName, VarGuid, NULL, DefInfo) != NULL + ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CopyVariables +// +// Description: This function copies variables from one varstore to another +// +// Input: OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure to copy from +// OUT NVRAM_STORE_INFO *NewInfo - pointer to NVRAM_STORE_INFO structure to copy to +// VARIABLE_INTERFACE *NewInterface - pointer to the interface with the update routins +// COPY_VAR_STORE_FILTER FilterFunction - filtering function +// VOID *FilterContext - filtering function context +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CopyVariables( + IN NVRAM_STORE_INFO* Info, + OUT NVRAM_STORE_INFO *NewInfo, + VARIABLE_INTERFACE *NewInterface, + COPY_VAR_STORE_FILTER FilterFunction, + VOID *FilterContext +) +{ + EFI_STATUS Status; + VOID *TmpBuffer, *TmpData; + CHAR16 *TmpName; + UINTN NvramSize = Info->NvramSize; + EFI_GUID Guid; + + TmpBuffer = SelectiveAllocate (TRUE, NvramSize*2); + + if (TmpBuffer==NULL) return EFI_OUT_OF_RESOURCES; + + TmpName = TmpBuffer; TmpData = (UINT8*)TmpBuffer+NvramSize; + TmpName[0]=0; + + //Copy variables + do + { + UINTN Size = NvramSize; + Status = NvGetNextVariableName( + &Size, TmpName, &Guid, Info, FALSE + ); + + if (EFI_ERROR(Status)) break; + + //check if the variable needs to be skipped + if ( FilterFunction!=NULL + && FilterFunction(FilterContext, TmpName, &Guid, Info) + ) continue; + if (SaveOnlyPreservedVars && VarNotInPreserveList(TmpName, &Guid)) + continue; + Status=CopyVariable( + TmpName, &Guid, NvramSize, TmpData, Info, NewInfo, NewInterface + ); + + if (EFI_ERROR(Status)) + { + if (Status==EFI_NOT_FOUND) continue; + SelectiveFree (TmpBuffer); + SaveOnlyPreservedVars = FALSE; + return Status; + } + } + while (TRUE); + + SelectiveFree (TmpBuffer); + + if (Status==EFI_NOT_FOUND) Status=EFI_SUCCESS; + SaveOnlyPreservedVars = FALSE; + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CopyVarStore +// +// Description: This function copyes varstore to a new location +// +// Input: OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure to copy from +// OUT NVRAM_STORE_INFO *NewInfo - pointer to NVRAM_STORE_INFO structure to copy to +// VARIABLE_INTERFACE *NewInterface - pointer to the interface with the update routins +// COPY_VAR_STORE_FILTER FilterFunction - filtering function +// VOID *FilterContext - filtering function context +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CopyVarStore( + IN NVRAM_STORE_INFO* Info, + OUT NVRAM_STORE_INFO *NewInfo, + VARIABLE_INTERFACE *NewInterface, + COPY_VAR_STORE_FILTER FilterFunction, + VOID *FilterContext +) +{ + BOOLEAN ok; + + //This function assumes that the following + //fields of NewInfo have been initialized: + // NvramAddress, NvramSize, NvramGuidsAddress, Flags + if ((Runtime) && (!NvramDriverBuffer)) return EFI_OUT_OF_RESOURCES; + + NewInterface->EnableUpdate(NewInfo->NvramAddress,NewInfo->NvramSize); + ok=NewInterface->EraseBytes(NewInfo->NvramAddress,NewInfo->NvramSize); + NewInterface->DisableUpdate(NewInfo->NvramAddress,NewInfo->NvramSize); + NewInfo->pFirstVar = NewInfo->NvramAddress + VarStoreInfo.HeaderLength; + NewInfo->pEndOfVars = NewInfo->pFirstVar; + NewInfo->LastVarSize = 0; + NewInfo->pLastReturned = NULL; + NewInfo->NextGuid = 0; + + if (!ok) return EFI_DEVICE_ERROR; + + //Copy the header + NewInterface->EnableUpdate(NewInfo->NvramAddress,NewInfo->NvramSize); + ok=NewInterface->WriteBytes( + NewInfo->NvramAddress, + VarStoreInfo.HeaderLength, + Info->NvramAddress + ); + NewInterface->DisableUpdate(NewInfo->NvramAddress,NewInfo->NvramSize); + + if (!ok) return EFI_DEVICE_ERROR; + + + return CopyVariables(Info,NewInfo,NewInterface,FilterFunction,FilterContext); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CopyVarStoreToMemStore +// +// Description: This function allocates memory copyes varstore to a new location +// +// Input: OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure to copy from +// IN NVAR* SkipVar - pointer to var to be skiped +// OUT NVRAM_STORE_INFO *NewInfo - pointer to NVRAM_STORE_INFO structure which was created +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CopyVarStoreToMemStore( + IN NVRAM_STORE_INFO* Info, + IN NVAR* SkipVar, OUT NVRAM_STORE_INFO *NewInfo +) +{ + EFI_STATUS Status; + + if ((Runtime) && (!NvramDriverBuffer)) return EFI_OUT_OF_RESOURCES; + if (!Runtime) PROGRESS_CODE(DXE_NVRAM_CLEANUP); + NVRAM_TRACE((TRACE_DXE_CORE,"NVRAM Garbage Collection\n")); + + Status = InitVolatileStore( + NewInfo, Info->NvramSize, VarStoreInfo.HeaderLength, Info->Flags, FALSE + ); + + if (EFI_ERROR(Status)) return Status; + + Status = CopyVarStore( + Info,NewInfo,&MemInterface,SkipSpecificNvar,SkipVar + ); + + if (EFI_ERROR(Status)) SelectiveFree (NewInfo->NvramAddress); + else CheckTheHeader(NewInfo, VarStoreInfo.HeaderLength, TRUE); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SetNvramFfsFileState +// +// Description: This function updates State of Ffs file with new bits described by NewState +// +// Input: OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure +// VARIABLE_INTERFACE *Interface - pointer to the interface with the Variable routins +// EFI_FFS_FILE_STATE NewState - New state to update to +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SetNvramFfsFileState( + NVRAM_STORE_INFO *Info, VARIABLE_INTERFACE *Interface, + EFI_FFS_FILE_STATE NewState +) +{ + BOOLEAN ok; + EFI_FFS_FILE_STATE *StatePtr = GetNvramFfsFileStatePtr(Info); + + if (StatePtr==NULL) return EFI_DEVICE_ERROR; + + if (FlashEmpty!=0) NewState = ~NewState & *StatePtr; + else NewState |= *StatePtr; + + Interface->EnableUpdate(StatePtr,sizeof(NewState)); + ok = Interface->WriteBytes(StatePtr,sizeof(NewState),&NewState); + Interface->DisableUpdate(StatePtr,sizeof(NewState)); + return (ok) ? EFI_SUCCESS : EFI_DEVICE_ERROR; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ResetFfsFileStateInMemory +// +// Description: This function sets State of Ffs file to new value described by NewState +// +// Input: OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure +// EFI_FFS_FILE_STATE NewState - New state to set +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ResetFfsFileStateInMemory( + NVRAM_STORE_INFO *Info, EFI_FFS_FILE_STATE NewState +) +{ + EFI_FFS_FILE_STATE *StatePtr = GetNvramFfsFileStatePtr(Info); + + if (StatePtr==NULL) return EFI_DEVICE_ERROR; + + if (FlashEmpty!=0) NewState = ~NewState; + + *StatePtr = NewState; + return (*StatePtr == NewState) ? EFI_SUCCESS : EFI_DEVICE_ERROR; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CheckTheHeader +// +// Description: This function validates correctness of the header fields used by the driver +// and fixes them if Update parameter is TRUE +// +// Input: IN NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure to check +// IN UINT32 HeaderLength - length of the NVRAM header +// IN BOOLEAN Update - If TRUE, invalid header will be updated to fix the problem +// +// Output: BOOLEAN +// TRUE - No problems detected +// FALSE - Problem(s) detected +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN CheckTheHeader(NVRAM_STORE_INFO *Info, UINT32 HeaderLength, BOOLEAN Update){ + BOOLEAN HeaderValid = TRUE; + EFI_FIRMWARE_VOLUME_HEADER *Fv = (EFI_FIRMWARE_VOLUME_HEADER*)Info->NvramAddress; + + //check the signature + if ( Fv->Signature!=FV_SIGNATURE + || Fv->FvLength!=Info->NvramSize + || Fv->HeaderLength!=HeaderLength-sizeof(EFI_FFS_FILE_HEADER) + ){ + if (Update){ + Fv->Signature=FV_SIGNATURE; + Fv->FvLength=Info->NvramSize; + Fv->HeaderLength=(UINT16)(HeaderLength-sizeof(EFI_FFS_FILE_HEADER)); + } + HeaderValid = FALSE; + } + if (!IsMainNvramStoreValid(Info, VarStoreInfo.BackupAddress, NULL)){ + if (Update){ + ResetFfsFileStateInMemory( + Info, + EFI_FILE_HEADER_CONSTRUCTION + | EFI_FILE_HEADER_VALID + | EFI_FILE_DATA_VALID + ); + } + HeaderValid = FALSE; + } + return HeaderValid; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: UpdateFtVarstore +// +// Description: This function copyes Varstore to a new location and makes this copy main Varstore +// +// Input: OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure +// VARIABLE_INTERFACE *Interface - pointer to the interface with the Variable routins +// NVRAM_STORE_INFO* NewInfo - pointer to the new NVRAM_STORE_INFO Varstore +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS UpdateFtVarstore( + NVRAM_STORE_INFO* Info, VARIABLE_INTERFACE *Interface, NVRAM_STORE_INFO* NewInfo +) +{ + NVRAM_STORE_INFO BackupInfo; + EFI_STATUS Status; + + BackupInfo.NvramAddress = VarStoreInfo.BackupAddress; + BackupInfo.NvramSize = Info->NvramSize; + NvInitInfoBuffer( + &BackupInfo, VarStoreInfo.HeaderLength, Info->Flags + ); +// State Transitions: +// Main Backup Valid Store +// = Initial State After Firmware Flashing +// 1. DATA_VALID HEADER_INVALID Main +// = Update Cycle 1 +// 2. DATA_VALID HEADER_VALID Main +// 3. MARKED_FOR_UPDATE HEADER_VALID Main +// 4. MARKED_FOR_UPDATE DATA_VALID Backup +// = Update Cycle 1 is Over +// = Update Cycle 2 +// 5. HEADER_VALID DATA_VALID Backup +// 6. HEADER_VALID MARKED_FOR_UPDATE Backup +// 7. DATA_VALID MARKED_FOR_UPDATE Main +// = Update Cycle 2 is Over +// = Update Cycle 3 +// 8. DATA_VALID HEADER_VALID Main +// Stae 8 == State 2 + Status=ResetFfsFileStateInMemory( + NewInfo, EFI_FILE_HEADER_CONSTRUCTION|EFI_FILE_HEADER_VALID + ); + + if (EFI_ERROR(Status)) return Status; + + Status = CopyVarStore(NewInfo,&BackupInfo,Interface,NULL,NULL); + + if (EFI_ERROR(Status)) return Status; + + Status=SetNvramFfsFileState(Info, Interface, EFI_FILE_MARKED_FOR_UPDATE); + + if (EFI_ERROR(Status)) return Status; + + Status=SetNvramFfsFileState(&BackupInfo, Interface, EFI_FILE_DATA_VALID); + + if (EFI_ERROR(Status)) return Status; +#ifdef HYBRID_NV_INTERFACE + if (!SwapVarstoresInHybridMode(&BackupInfo)){ +#endif + VarStoreInfo.BackupAddress = Info->NvramAddress; +#ifdef HYBRID_NV_INTERFACE + } +#endif + *Info = BackupInfo; + NVRAM_TRACE((TRACE_DXE_CORE,"NVRAM areas swapped(NVRAM address: %X; Backup address: %X).\n", Info->NvramAddress, VarStoreInfo.BackupAddress)); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: UpdateVarstore +// +// Description: This function copyes Varstore to a new location and makes this copy main Varstore +// if old varstore flag has NVRAM_STORE_FLAG_NON_VALATILE and Backupadress is valid, else it +// just copy Varstor to new location +// +// Input: OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure +// VARIABLE_INTERFACE *Interface - pointer to the interface with the Variable routins +// NVRAM_STORE_INFO* NewInfo - pointer to the new NVRAM_STORE_INFO Varstore +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS UpdateVarstore( + NVRAM_STORE_INFO* Info, VARIABLE_INTERFACE *Interface, NVRAM_STORE_INFO* NewInfo +) +{ + EFI_STATUS Status; + + if ( (Info->Flags & NVRAM_STORE_FLAG_NON_VALATILE) + && VarStoreInfo.BackupAddress!=0 + && CheckTheHeader(Info, VarStoreInfo.HeaderLength, FALSE) + ) + { + Status = UpdateFtVarstore(Info,Interface,NewInfo); + } + + else + { + Status = CopyVarStore(NewInfo,Info,Interface,NULL,NULL); + } + + if (!EFI_ERROR(Status)) + { + if (Info==VarStoreInfo.NvInfo) NvramReinitialize(); + +#if NV_CACHE_SUPPORT + else IndexReset(); + +#endif + } + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvResetConfiguration +// +// Description: This function resets NvRam configuration +// +// Input: OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure +// VARIABLE_INTERFACE *Interface - pointer to the interface with the Variable routins +// BOOLEAN ExternalDefaults - if TRUE - use external defaults +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvResetConfiguration( + NVRAM_STORE_INFO* Info, VARIABLE_INTERFACE *Interface, + BOOLEAN ExternalDefaults, BOOLEAN PreserveVariablesWithNoDefaults +) +{ + UINT16 HeaderLength = VarStoreInfo.HeaderLength; + NVRAM_STORE_INFO NewInfo; + NVRAM_STORE_INFO DefaultsInfo; + NVRAM_STORE_INFO *DefInfo = NULL; + EFI_STATUS Status; + VOID *TmpBuffer; + UINTN NvramSize = Info->NvramSize; + BOOLEAN HeaderIsValid; + + PROGRESS_CODE(DXE_CONFIGURATION_RESET); + NVRAM_TRACE((TRACE_DXE_CORE, + "NVRAM Reset: ExternalDefaults=%d; PreserveVariablesWithNoDefaults=%d\n", + ExternalDefaults,PreserveVariablesWithNoDefaults + )); + + Status = InitVolatileStore( + &NewInfo, Info->NvramSize, VarStoreInfo.HeaderLength, Info->Flags, FALSE + ); + + if (EFI_ERROR(Status)) return Status; + + MemCpy(NewInfo.NvramAddress, Info->NvramAddress, HeaderLength); + HeaderIsValid = CheckTheHeader(&NewInfo, HeaderLength, TRUE); + if (!HeaderIsValid){ + PreserveVariablesWithNoDefaults=FALSE; + NVRAM_TRACE((TRACE_DXE_CORE, "NVRAM Reset: NVRAM FV header is corrupted\n")); + } + if (ExternalDefaults) + { + // {9221315B-30BB-46b5-813E-1B1BF4712BD3} +#define SETUP_DEFAULTS_FFS_GUID { 0x9221315b, 0x30bb, 0x46b5, { 0x81, 0x3e, 0x1b, 0x1b, 0xf4, 0x71, 0x2b, 0xd3 } } + static EFI_GUID SetupDefaultsFfsGuid = SETUP_DEFAULTS_FFS_GUID; + EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; + EFI_HANDLE *FvHandle; + UINTN Number,i; + UINT32 Authentication; + + Status = pBS->LocateHandleBuffer( + ByProtocol,&gEfiFirmwareVolumeProtocolGuid, NULL, &Number, &FvHandle + ); + + for (i=0; i<Number; i++) + { + Status=pBS->HandleProtocol(FvHandle[i], &gEfiFirmwareVolumeProtocolGuid, &Fv); + + if (EFI_ERROR(Status)) continue; + + DefaultsInfo.NvramAddress=NULL; + DefaultsInfo.NvramSize=0; + Status=Fv->ReadSection ( + Fv,&SetupDefaultsFfsGuid, + EFI_SECTION_RAW, 0, + &DefaultsInfo.NvramAddress, &DefaultsInfo.NvramSize, + &Authentication + ); + + if (!EFI_ERROR(Status)) + { + NVRAM_TRACE((TRACE_DXE_CORE, "NVRAM: External Defaults Found: Size=%X\n",DefaultsInfo.NvramSize)); + NvInitInfoBuffer( + &DefaultsInfo, 0, + NVRAM_STORE_FLAG_NON_VALATILE + | NVRAM_STORE_FLAG_READ_ONLY + | NVRAM_STORE_FLAG_DO_NOT_ENUMERATE + ); + DefInfo = &DefaultsInfo; + break; + } + } + } + + else + { + DefaultsInfo.NvramAddress = NULL; + DefInfo = Info; + } + + if (DefInfo!=NULL) + { + TmpBuffer = SelectiveAllocate (TRUE, NvramSize); + + if (TmpBuffer==NULL) + { + SelectiveFree (NewInfo.NvramAddress); + return EFI_OUT_OF_RESOURCES; + } + Status=CopyVariable( + (CHAR16*)StdDefaults, (EFI_GUID*)&AmiDefaultsVariableGuid, + NvramSize,TmpBuffer,DefInfo,&NewInfo,&MemInterface + ); + + if (Status!=EFI_OUT_OF_RESOURCES) + { + Status=CopyVariable( + (CHAR16*)MfgDefaults, (EFI_GUID*)&AmiDefaultsVariableGuid, + NvramSize,TmpBuffer,DefInfo,&NewInfo,&MemInterface + ); + } + + SelectiveFree (TmpBuffer); + + if (PreserveVariablesWithNoDefaults){ + NVRAM_STORE_INFO DefVarInfo; + if (NvGetDefaultsInfo(StdDefaults,DefInfo,&DefVarInfo) != NULL) + Status=CopyVariables( + Info, &NewInfo, &MemInterface, SkipVarsWithDefaults ,&DefVarInfo + ); + } + if (DefaultsInfo.NvramAddress!=NULL ) + { + pBS->FreePool(DefaultsInfo.NvramAddress); + } + // don't reset NVRAM if no defaults found + if (NewInfo.pEndOfVars == NewInfo.pFirstVar) DefInfo=NULL; + } + + if ( Status!=EFI_OUT_OF_RESOURCES + && ( DefInfo!=NULL || !HeaderIsValid ) + && ( Info->pEndOfVars - Info->NvramAddress!= NewInfo.pEndOfVars - NewInfo.NvramAddress + || DefInfo!=Info + ) + ) Status=UpdateVarstore(Info,Interface,&NewInfo); + + SelectiveFree (NewInfo.NvramAddress); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsStoreOk +// +// Description: This function checks is Varstore is correct +// +// Input: OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure +// +// Output: BOOLEAN - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsStoreOk(NVRAM_STORE_INFO *Info) +{ + return + ( Info->LastVarSize==0 + || NvIsVariable((NVAR*)(Info->pEndOfVars-Info->LastVarSize),Info) + ) + && *(UINT32*)Info->pEndOfVars==(UINT32)FlashEmpty + && ((NVAR*)Info->pEndOfVars)->size==FLASH_EMPTY_SIZE + && *(UINT32*)(Info->NvramGuidsAddress-Info->NextGuid)==(UINT32)FlashEmpty; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CheckStore +// +// Description: This function checks if Varstore is correct and otherwise tries to +// Reinitialize NvRam, copy Varstore to memory and prints messages +// based on situation. +// +// Input: OUT NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure +// +// Output: BOOLEAN - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID CheckStore(BOOLEAN Recover) +{ + NVRAM_STORE_INFO *Info = VarStoreInfo.NvInfo; + NVRAM_STORE_INFO NewInfo; + EFI_STATUS Status; + BOOLEAN MainStoreValid; + BOOLEAN BackupStoreValid; +#ifdef HYBRID_NV_INTERFACE + NVRAM_STORE_INFO FlashInfo; + HybridStoreToRealStore(Info,&FlashInfo); +#endif + MainStoreValid = IsMainNvramStoreValid( +#ifdef HYBRID_NV_INTERFACE + &FlashInfo, +#else + VarStoreInfo.NvInfo, +#endif + VarStoreInfo.BackupAddress, &BackupStoreValid + ); + if (!MainStoreValid){ + if (BackupStoreValid){ + NVRAM_STORE_INFO BackupInfo; + NVRAM_TRACE((TRACE_DXE_CORE,"NVRAM Store is not valid. Switching to Backup Store.\n")); +#ifdef HYBRID_NV_INTERFACE + if (!SwapVarstoresInHybridMode(&BackupInfo)){ +#endif + BackupInfo.NvramAddress = VarStoreInfo.BackupAddress; + BackupInfo.NvramSize = VarStoreInfo.NvInfo->NvramSize; + NvInitInfoBuffer( + &BackupInfo, VarStoreInfo.HeaderLength, VarStoreInfo.NvInfo->Flags + ); + VarStoreInfo.BackupAddress = VarStoreInfo.NvInfo->NvramAddress; +#ifdef HYBRID_NV_INTERFACE + } +#endif + *VarStoreInfo.NvInfo = BackupInfo; + NvramReinitialize(); + MainStoreValid = TRUE; +#ifdef HYBRID_NV_INTERFACE + HybridStoreToRealStore(Info,&FlashInfo); +#endif + }else{//both main and backup stores are invliad; force the recovery. + Recover = TRUE; + } + } +#ifdef HYBRID_NV_INTERFACE + if (MainStoreValid && IsStoreOk(&FlashInfo)) return; +#else + if (MainStoreValid && IsStoreOk(Info)) return; +#endif + + if (!Recover) + { + NVRAM_TRACE((TRACE_DXE_CORE,"NVRAM inconsistency detected. Reinitializing.\n")); +#ifdef HYBRID_NV_INTERFACE + //When inconsystency is detected, re-read the flash content into the memory buffer + //(they may be out of synchronization) + MemCpy( + VarStoreInfo.NvInfo->NvramAddress, + VarStoreInfo.NvramFlashAddress, + VarStoreInfo.NvInfo->NvramSize + ); +#endif + NvramReinitialize(); + + if (IsStoreOk(Info)) return; + } + NVRAM_TRACE((TRACE_DXE_CORE,"NVRAM corruption detected.\n")); + + Status = CopyVarStoreToMemStore(Info,NULL,&NewInfo); + + if (EFI_ERROR(Status)){ + SelectiveFree (NewInfo.NvramAddress); + return ; + } + + UpdateVarstore(Info,VarStoreInfo.NvInterface,&NewInfo); + SelectiveFree (NewInfo.NvramAddress); +} + +//High level routines +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DxeGetVariable +// +// Description: This function searches for Var with specific GUID and Name +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// OPTIONAL OUT UINT32* Attributes - Pointer to memory where Attributes will be returned +// IN OUT UINTN *DataSize - size of Var - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// OUT VOID *Data - Pointer to memory where Var will be returned +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DxeGetVariable( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, OUT VOID *Data +) +{ + EFI_STATUS Status; + UINT32 Attrib; + + if (!VariableName || !VendorGuid || !DataSize || !Data && *DataSize) + return EFI_INVALID_PARAMETER; + Status = GetVariableHook ( + VariableName,VendorGuid,Attributes,DataSize,Data + ); + if (Status != EFI_UNSUPPORTED) return Status; + CheckStore(FALSE); +#if NV_CACHE_SUPPORT + { + UINTN VariableNameSize; + NVRAM_STORE_INFO *Info; + BOOLEAN UnindexedExists; + NVAR *Nvar = NULL; + VAR_INDEX_ENTRY *NvarEntry = IndexFindVariableEntry( + VariableName,VendorGuid,&VariableNameSize, + &Info, &UnindexedExists + ); + + if (NvarEntry!=NULL) + { + Nvar = NvarEntry->Nvar; + if (AreBtVariablesHidden() && !(Nvar->flags & NVRAM_FLAG_RUNTIME)) return EFI_NOT_FOUND; + + // Get the attributes from the first entry, data-only entries do not store attribs + if (Attributes) + if (EFI_ERROR(NvGetAttributesFromNvar(Nvar, Info, Attributes))) + return EFI_NOT_FOUND; + + // Get the data using the cached data-only entry, if possible + return NvGetVariableFromNvar( + NvarEntry->FinalDataNvar,VariableNameSize,NULL,DataSize,Data,Info, NULL + ); + } + + if (!UnindexedExists) return EFI_NOT_FOUND; + } +#endif + Status = NvGetVariable2( + VariableName, VendorGuid, &Attrib, + DataSize, Data, + VarStoreInfo.InfoCount, VarStoreInfo.NvramInfo + ); + + if (!EFI_ERROR(Status) || Status == EFI_BUFFER_TOO_SMALL) + { + if (AreBtVariablesHidden() && !(Attrib & EFI_VARIABLE_RUNTIME_ACCESS)) return EFI_NOT_FOUND; + + if (Status != EFI_BUFFER_TOO_SMALL && Attributes) *Attributes=Attrib; + } + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DxeGetNextVariableName +// +// Description: This function searches for next Var after Var with specific name and GUID and returns it's Name. +// +// Input: IN OUT UINTN *VariableNameSize - size of Varname - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// IN OUT CHAR16 *VariableName - pointer where Var Name in Unicode will be stored +// IN OUT EFI_GUID *VendorGuid - pointer to menory where Var GUID is stored +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DxeGetNextVariableName( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid +) +{ + EFI_STATUS Status; + + if ( !VariableNameSize || !VariableName || !VendorGuid) + return EFI_INVALID_PARAMETER; + Status = GetNextVarNameHook ( + VariableNameSize, VariableName, VendorGuid + ); + if (Status != EFI_UNSUPPORTED) return Status; + CheckStore(FALSE); + Status = NvGetNextVariableName2( + VariableNameSize, VariableName, VendorGuid, + VarStoreInfo.InfoCount, VarStoreInfo.NvramInfo, + &VarStoreInfo.LastInfoIndex,AreBtVariablesHidden() + ); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DxeSetVariable +// +// Description: This function sets Var with specific GUID, Name and attributes +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// IN UINT32 Attributes - Attributes of the Var +// IN UINTN DataSize - size of Var +// IN VOID *Data - Pointer to memory where Var data is stored +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DxeSetVariable( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data +) +{ + NVAR *Var = NULL; + UINTN NameSize; + BOOLEAN NvVariableFound; + NVRAM_STORE_INFO *Info=NULL; + VARIABLE_INTERFACE *Interface; + EFI_STATUS Status; + NVRAM_STORE_INFO NewInfo; +#if NV_CACHE_SUPPORT + BOOLEAN UnindexedExists; + BOOLEAN UpdateIndex; + VAR_INDEX_ENTRY *VarEntry; +#endif + UINTN OldDataSize=0; + VOID *OldData=NULL; + EXT_SEC_FLAGS ExtSecFlags = {0, 0,{0}}; + EFI_GUID EfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE; + + if ( + !VariableName || VariableName[0]==0 || !VendorGuid + || ( Attributes & ~ALL_VARIABLE_ATTRIBUTES) + || (Attributes & EFI_VARIABLE_RUNTIME_ACCESS) && !(Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS ) + || DataSize && !Data + || Runtime && Attributes && ( + !(Attributes & EFI_VARIABLE_NON_VOLATILE) + || !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS) && AreBtVariablesHidden() + ) + ) return EFI_INVALID_PARAMETER; + if (guidcmp(VendorGuid, & EfiGlobalVariableGuid) == 0) + { + if (VarNotInEfiGlobalVarList (VariableName, Attributes)) + { + NVRAM_TRACE((TRACE_DXE_CORE, "Variable with EfiGlobalVariableGuid has illegal name: %S or attributes: %x ! Please use different GUID. \n", VariableName, Attributes)); + ASSERT(FALSE); + return EFI_INVALID_PARAMETER; + } + } + Status = SetVariableHook ( + VariableName,VendorGuid,Attributes,DataSize,Data + ); + if (Status != EFI_UNSUPPORTED) return Status; + if (DataSize>MAX_NVRAM_VARIABLE_SIZE) return EFI_OUT_OF_RESOURCES; + + CheckStore(FALSE); +#if NV_CACHE_SUPPORT + //UpdateIndex defines if indexed address has to be updated. + //Typically we don't have to update index because + //index contains address of the first NVAR for a particular variable, + //which does not change when we update variable data. + //However, there is one exception from the rule. + //We need to update the index, when indexed address points to the default value of the variable. + //In this case UpdateIndex will be set to TRUE + UpdateIndex = FALSE; + VarEntry = IndexFindVariableEntry( + VariableName,VendorGuid,&NameSize, + &Info, &UnindexedExists + ); + + if (VarEntry!=NULL) + { + Var = VarEntry->Nvar; + if (Info==VarStoreInfo.NvInfo) NvVariableFound=TRUE; + else if (Info==VarStoreInfo.MemInfo) NvVariableFound=FALSE; + else + { + //We are setting UnindexedExists to TRUE because + //there may be other variable instances in varstores with lower priority + Var=NULL; VarEntry=NULL; UpdateIndex=TRUE; UnindexedExists=TRUE; + } + } + + if (Var==NULL && UnindexedExists) + { + NvVariableFound=TRUE; + Var = NvFindVariable(VariableName,VendorGuid, &NameSize, VarStoreInfo.NvInfo); + + if (Var==NULL) + { + NvVariableFound=FALSE; + Var = NvFindVariable(VariableName,VendorGuid, &NameSize, VarStoreInfo.MemInfo); + } + } + +#else + NvVariableFound=TRUE; + Var = NvFindVariable(VariableName,VendorGuid, &NameSize, VarStoreInfo.NvInfo); + + if (Var==NULL) + { + NvVariableFound=FALSE; + Var = NvFindVariable(VariableName,VendorGuid, &NameSize, VarStoreInfo.MemInfo); + } + +#endif + if( Var!=NULL ) + { + // It's illegal to set boot time variable at run time. + if (AreBtVariablesHidden() && !(Var->flags & NVRAM_FLAG_RUNTIME)) return EFI_INVALID_PARAMETER; + if (NvVariableFound) + { + Info = VarStoreInfo.NvInfo; + Interface = VarStoreInfo.NvInterface; + } + else + { + Info = VarStoreInfo.MemInfo; + Interface = VarStoreInfo.MemInterface; + } + GetVarAuthExtFlags(Var, Info, &ExtSecFlags); +#if NV_CACHE_SUPPORT + if (VarEntry != NULL && VarEntry->FinalDataNvar != NULL) + OldData = NvGetData( VarEntry->FinalDataNvar, NameSize, &OldDataSize, Info); + else +#endif + OldData = NvGetData( Var, NameSize, &OldDataSize, Info); + } else { + if (Attributes & EFI_VARIABLE_NON_VOLATILE) + { + Info = VarStoreInfo.NvInfo; + Interface = VarStoreInfo.NvInterface; + } + else + { +#if NV_CACHE_SUPPORT + //if UpdateIndex is TRUE, default value exists + //If default value exists, the variable is non valatile + //Attributes for existing variable can not be changed + if (UpdateIndex) return EFI_INVALID_PARAMETER; +#endif + Info = VarStoreInfo.MemInfo; + Interface = VarStoreInfo.MemInterface; + } + OldDataSize = 0; + OldData = NULL; + } + + Status = VerifyVariable(VariableName, VendorGuid, &Attributes, &Data, &DataSize, OldData, OldDataSize, &ExtSecFlags); + if (EFI_ERROR(Status)) { + // case for SigDb Append mode. EFI_ALREADY_STARTED treat as Ok to exit SetVar + if(Status == EFI_ALREADY_STARTED) + Status = EFI_SUCCESS; + return Status; + } + +// Function called with empty access attributes - the variable shall be erased. + if(!Attributes) + DataSize = 0; + // + // Verification passed. + // + if ((!(Attributes & EFI_VARIABLE_APPEND_WRITE) && !DataSize) || + !(Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) ) + { + //delete + if (Var==NULL) return +#if NV_CACHE_SUPPORT + //if UpdateIndex is TRUE, default value (which can not be deleted ) exists + (UpdateIndex) ? EFI_WRITE_PROTECTED : +#endif + EFI_NOT_FOUND; + + if (Runtime && !NvVariableFound) return EFI_INVALID_PARAMETER; + + Status = DeleteVariable(Var,Info,Interface); +#if NV_CACHE_SUPPORT + + if (!EFI_ERROR(Status)) + { + //The variable has just been deleted from the primary varstore. + //However, we may still have variable instance in other stores. + INT32 i; + NVAR *v; + + if (NvVariableFound) + { + for (i=VarStoreInfo.InfoCount-1; i>=0; i--) + { + if ( Info == &VarStoreInfo.NvramInfo[i] + || (Info->Flags & NVRAM_STORE_FLAG_NON_VALATILE)==0 + ) continue; + + v = NvFindVariable( + VariableName,VendorGuid, &NameSize, + &VarStoreInfo.NvramInfo[i] + ); + + if (v!=NULL) + { + IndexUpdateVariable(v,&VarStoreInfo.NvramInfo[i]); + return Status; + } + } + } + + //If other instances are not found, delete the index entry + IndexDeleteVariableEntry(VarEntry); + } + +#endif + return Status; + } + + if (Var==NULL) + { + //create new + Status = CreateVariable( + VariableName,VendorGuid,Attributes, + DataSize, Data, Info,Interface, NULL, &ExtSecFlags// NULL + ); +#if NV_CACHE_SUPPORT + if (!EFI_ERROR(Status)) + { + if (UpdateIndex) + { + if ( ( !( VarStoreInfo.NvramMode & (NVRAM_MODE_DEFAULT_CONFIGURATION|NVRAM_MODE_MANUFACTORING) ) ) + || Info!=VarStoreInfo.NvInfo ) + { + IndexUpdateVariable( + (NVAR*)(Info->pEndOfVars-Info->LastVarSize),Info + ); + + } + } + else + IndexAddVariable( + (NVAR*)(Info->pEndOfVars-Info->LastVarSize),Info + ); + } + +#endif + } + + else + { + //update existing + Status = UpdateVariable( + Var,VariableName,NameSize,VendorGuid,Attributes, + DataSize, Data, +#if NV_CACHE_SUPPORT + VarEntry, +#else + NULL, +#endif + + &ExtSecFlags, + Info, Interface + ); + } + + //Error Recovery + if ( Status==EFI_OUT_OF_RESOURCES + || Status==EFI_DEVICE_ERROR && !IsStoreOk(Info) + ) + { + BOOLEAN FirstPass=TRUE; + do{ + if (!SaveOnlyPreservedVars) + { + NVRAM_TRACE((TRACE_DXE_CORE,"NVRAM: SetVariable failed. Status=%r. Starting Recovery...\n",Status)); + } + else + { + NVRAM_TRACE((TRACE_DXE_CORE,"NVRAM: SetVariable failed After Recovery. Clearing NVRAM...\n")); + } + NewInfo.NvramAddress = NULL; + if (EFI_ERROR(CopyVarStoreToMemStore(Info,Var,&NewInfo))){ + if (NewInfo.NvramAddress!=NULL) SelectiveFree (NewInfo.NvramAddress); + return Status; + } + if (Attributes & EFI_VARIABLE_APPEND_WRITE) + Status = CreateVariableEx( + VariableName,VendorGuid,Attributes, + DataSize, Data, &NewInfo, &MemInterface, NULL, &ExtSecFlags, + OldData, OldDataSize + ); + else + Status = CreateVariable( + VariableName,VendorGuid,Attributes, + DataSize, Data, &NewInfo, &MemInterface, NULL, &ExtSecFlags + ); + + if (!EFI_ERROR(Status)) + { + Status = UpdateVarstore(Info,Interface,&NewInfo); + } + + else + { + if ((Status==EFI_OUT_OF_RESOURCES) && (FirstPass)) SaveOnlyPreservedVars = TRUE; + + CheckStore(TRUE); + } + + SelectiveFree (NewInfo.NvramAddress); + + NVRAM_TRACE((TRACE_DXE_CORE,"NVRAM: SetVariable Status after recovery=%r.\n",Status)); + FirstPass = FALSE; + } + while (SaveOnlyPreservedVars); + } + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: BeginCriticalSection +// +// Description: This function calls when critical section begins. It disables interupts, +// and Smi and fills CRITICAL_SECTION structure fields +// +// Input: CRITICAL_SECTION *Cs - pointer to CRITICAL_SECTION structure +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID BeginCriticalSection(CRITICAL_SECTION *Cs) +{ + CRITICAL_SECTION TempCs; + + TempCs.IntState[0] = IoRead8(0x21); + TempCs.IntState[1] = IoRead8(0xa1); + TempCs.SmiState = SbLib_GetSmiState(); + + IoWrite8(0x21, 0xff); + IoWrite8(0xa1, 0xff); + SbLib_SmiDisable(); + + Cs->Busy = TRUE; + + Cs->IntState[0] = TempCs.IntState[0]; + Cs->IntState[1] = TempCs.IntState[1]; + Cs->SmiState = TempCs.SmiState; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: EndCriticalSection +// +// Description: This function calls when critical section ends. It enable interupts, +// and Smi and fills CRITICAL_SECTION structure fields +// +// Input: CRITICAL_SECTION *Cs - pointer to CRITICAL_SECTION structure +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID EndCriticalSection(CRITICAL_SECTION *Cs) +{ + CRITICAL_SECTION TempCs; + + TempCs.IntState[0] = Cs->IntState[0]; + TempCs.IntState[1] = Cs->IntState[1]; + TempCs.SmiState = Cs->SmiState; + + Cs->Busy = FALSE; + + if (TempCs.SmiState) SbLib_SmiEnable(); + IoWrite8(0x21, TempCs.IntState[0]); + IoWrite8(0xa1, TempCs.IntState[1]); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DxeGetVariableSafe +// +// Description: This function searches for Var with specific GUID and Name +// beginning and ending critical section +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// OPTIONAL OUT UINT32* Attributes - Pointer to memory where Attributes will be returned +// IN OUT UINTN *DataSize - size of Var - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// OUT VOID *Data - Pointer to memory where Var will be returned +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DxeGetVariableSafe( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, OUT VOID *Data +) +{ + EFI_STATUS Status; + BEGIN_CRITICAL_SECTION(NvramCsPtr); + Status = DxeGetVariable( + VariableName,VendorGuid,Attributes,DataSize,Data + ); + END_CRITICAL_SECTION(NvramCsPtr); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DxeGetNextVariableNameSafe +// +// Description: This function searches for Var folowing after Var with specific name and GUID +// and returns it's Name, beginning and ending critical section . +// +// Input: IN OUT UINTN *VariableNameSize - size of Varname - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// IN OUT CHAR16 *VariableName - pointer where Var Name in Unicode will be stored +// IN OUT EFI_GUID *VendorGuid - pointer to menory where Var GUID is stored +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DxeGetNextVariableNameSafe( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid +) +{ + EFI_STATUS Status; + BEGIN_CRITICAL_SECTION(NvramCsPtr); + Status = DxeGetNextVariableName( + VariableNameSize,VariableName,VendorGuid + ); + END_CRITICAL_SECTION(NvramCsPtr); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DxeSetVariableSafe +// +// Description: This function sets Var with specific GUID, Name and attributes +// beginning and ending critical section. +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// IN UINT32 Attributes - Attributes of the Var +// IN UINTN DataSize - size of Var +// IN VOID *Data - Pointer to memory where Var data is stored +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DxeSetVariableSafe( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data +) +{ + EFI_STATUS Status; + BEGIN_CRITICAL_SECTION(NvramCsPtr); + Status = DxeSetVariable( + VariableName,VendorGuid,Attributes,DataSize,Data + ); + END_CRITICAL_SECTION(NvramCsPtr); + return Status; +} + +//Initialization +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: InitVolatileStore +// +// Description: This function allocates memory and inits NVRAM_STORE_INFO structure. +// +// Input: NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// UINTN HeaderSize - Size of the header +// UINT8 Flags - default Flags +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS InitVolatileStore( + NVRAM_STORE_INFO *Info, UINTN Size, + UINTN HeaderLength, UINT8 Flags, + BOOLEAN Runtime +) +{ + EFI_STATUS Status = EFI_SUCCESS; + + if ((NvramDriverBuffer) && (Flags & NVRAM_STORE_FLAG_NON_VALATILE)) { + Info->NvramAddress = SelectiveAllocate (FALSE, Size); + if (Info->NvramAddress == NULL) return EFI_OUT_OF_RESOURCES; + }else{ +#ifdef DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME + if (NoAccessOutsideofSmm){ + Status = pSmst->SmmAllocatePool ( + EfiRuntimeServicesData,Size, &Info->NvramAddress + ); + if (EFI_ERROR(Status)) return Status; + } + else +#endif + { + Status = pBS->AllocatePool ( + (Runtime) ? EfiRuntimeServicesData : EfiBootServicesData, + Size, &Info->NvramAddress + ); + if (EFI_ERROR(Status)) return Status; + } + } + + Info->NvramSize = Size; + MemSet(Info->NvramAddress,Info->NvramSize,FLASH_EMPTY_BYTE); + NvInitInfoBuffer( + Info,HeaderLength,Flags + ); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: EnumerateStore +// +// Description: This function searches for last Ver and fills the NVRAM_STORE_INFO structure. +// +// Input: NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID EnumerateStore(NVRAM_STORE_INFO *Info) +{ + NVAR *Var, *LastVar; + INT16 NextGuid; + //Init NextGuid and pEndOfVars + Var = (NVAR*)Info->pFirstVar; + LastVar = Var; + NextGuid=0; + + if (NvIsVariable(Var,Info)) + { + //We assume that the first variable pInfo->pFirstVar is always valid + //It's OK since we checked for pInfo->pFirstVar validity + //during during NVRAM_STORE_INFO initialization in NvInitInfoBuffer routine + for (; Var; Var=NvGetNextNvar(Var,Info)) + { + if ( ( Var->flags&(NVRAM_FLAG_DATA_ONLY|NVRAM_FLAG_GUID) ) == 0 ) + { + INT16 guid = *(UINT8*)(Var+1); + + if (guid>NextGuid) NextGuid=guid; + } + + LastVar = Var; + } + + NextGuid++; + Info->LastVarSize = LastVar->size; + Info->pEndOfVars = (UINT8*)LastVar+LastVar->size; + Info->NextGuid = NextGuid; + + // Skip incomplete NVAR record at the end of the NVRAM area (if any) + LastVar = (NVAR*)Info->pEndOfVars; + if ( LastVar->size != FLASH_EMPTY_SIZE + && LastVar->size + <= (UINT8*)(Info->NvramGuidsAddress-NextGuid) - Info->pEndOfVars + ){ + Info->LastVarSize += LastVar->size; + Info->pEndOfVars += LastVar->size; + } + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: VarStoreDiscovery +// +// Description: This function searches for nested Verstores and adds them to the NVRAM_STORE_INFO structure. +// +// Input: NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// NVRAM_STORE_INFO *MemInfo - pointer to NVRAM store structure in memory +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID VarStoreDiscovery(NVRAM_STORE_INFO *NvInfo, NVRAM_STORE_INFO *MemInfo) +{ + VarStoreInfo.InfoCount = 0; + VarStoreInfo.LastInfoIndex = 0; + + //Handle Manufacturing mode + if ( VarStoreInfo.NvramMode & NVRAM_MODE_MANUFACTORING + && NvGetDefaultsInfo( + MfgDefaults,NvInfo,&VarStoreInfo.NvramInfo[VarStoreInfo.InfoCount] + ) != NULL + ) + { + VarStoreInfo.InfoCount++; + } + + //Handle Default config mode + if (!(VarStoreInfo.NvramMode & NVRAM_MODE_DEFAULT_CONFIGURATION)) + { + //add regular NVRAM + VarStoreInfo.NvramInfo[VarStoreInfo.InfoCount]=*NvInfo; + VarStoreInfo.NvInfo = &VarStoreInfo.NvramInfo[VarStoreInfo.InfoCount]; + if (VarStoreInfo.NvramMode & NVRAM_MODE_MANUFACTORING) + VarStoreInfo.NvramInfo[VarStoreInfo.InfoCount].Flags |= NVRAM_STORE_FLAG_DO_NOT_ENUMERATE; + VarStoreInfo.InfoCount++; + + //add defaults + if (NvGetDefaultsInfo( + StdDefaults,NvInfo,&VarStoreInfo.NvramInfo[VarStoreInfo.InfoCount] + ) != NULL + ) + { + VarStoreInfo.InfoCount++; + } + } + + else + { + //add defaults + if (NvGetDefaultsInfo( + StdDefaults,NvInfo,&VarStoreInfo.NvramInfo[VarStoreInfo.InfoCount] + ) != NULL + ) + { + VarStoreInfo.InfoCount++; + } + + //add regular NVRAM + VarStoreInfo.NvramInfo[VarStoreInfo.InfoCount]=*NvInfo; + VarStoreInfo.NvInfo = &VarStoreInfo.NvramInfo[VarStoreInfo.InfoCount]; + VarStoreInfo.NvramInfo[VarStoreInfo.InfoCount].Flags |= NVRAM_STORE_FLAG_DO_NOT_ENUMERATE; + VarStoreInfo.InfoCount++; + } + + VarStoreInfo.NvramInfo[VarStoreInfo.InfoCount] = *MemInfo; + VarStoreInfo.MemInfo=&VarStoreInfo.NvramInfo[VarStoreInfo.InfoCount]; + VarStoreInfo.InfoCount++; + //Init NextGuid and pEndOfVars + EnumerateStore(VarStoreInfo.NvInfo); +} + +//--- Hook to chek NvRam data +BOOLEAN DxeIsNvramDataCompatible(IN EFI_GET_VARIABLE GetVariable); + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvramInitialize +// +// Description: This function initializes Varstore +// +// Input: NONE +// +// Output: EFI_STATUS based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvramInitialize() +{ + static EFI_GUID guidHobList = HOB_LIST_GUID; + NVRAM_STORE_INFO NvStore, MemStore; + NVRAM_HOB *NvramHob = (NVRAM_HOB*)GetEfiConfigurationTable(pST,&guidHobList); + NVRAM_STORE_INFO DefaultsInfo; + BOOLEAN UseExternalDefaults=FALSE; + BOOLEAN PreserveVariablesWithNoDefaults=FALSE; + + if (!NvramHob) return EFI_NOT_FOUND; + + if (EFI_ERROR(FindNextHobByGuid((EFI_GUID*)&AmiNvramHobGuid, &NvramHob))) + return EFI_NOT_FOUND; + + if (NvramRtGarbageCollectionSupport) { + NvramDriverBufferSize = NvramHob->NvramSize * 3; + if( EFI_ERROR( pBS->AllocatePages( + AllocateAnyPages, EfiRuntimeServicesData, + EFI_SIZE_TO_PAGES(NvramDriverBufferSize), + &NvramDriverBuffer ) + )) NvramDriverBuffer = 0; + } + + MemSet(&VarStoreInfo,sizeof(VarStoreInfo),0); + VarStoreInfo.HeaderLength = NvramHob->HeaderLength; + VarStoreInfo.NvramMode = NvramHob->NvramMode; + VarStoreInfo.BackupAddress = (UINT8*)NvramHob->BackupAddress; +#ifdef EFI_DEBUG + if (VarStoreInfo.BackupAddress) + NVRAM_TRACE((TRACE_DXE_CORE,"NVRAM back up address: %X\n", VarStoreInfo.BackupAddress)); +#endif + VarStoreInfo.MemInterface=&MemInterface; + InitVolatileStore( + &MemStore, + VALATILE_VARIABLE_STORE_SIZE, + VarStoreInfo.HeaderLength,0,TRUE + ); + //TODO: comment out the code below for now. + // Switching to simulation during recovery is not necessarily a good idea. + // For example, it can cause endless reboot if recovery is enabled during the + // very first boot after BIOS flashing. Ideally we should switch to simulation + // only when NVRAM is incompatible with the FV_MAIN drivers + // (which is checked later in this function). While enabling the simulation + // we should also "notify" (notification mechanism TBD) the reflash module + // that if FV_MAIN is updated, NVRAM must also be updated. +/* + BootMode = GetBootMode(); + if (BootMode==BOOT_IN_RECOVERY_MODE) + VarStoreInfo.NvramMode |= NVRAM_MODE_SIMULATION; +*/ + //If we are in the simulation mode let's create new + //memory based variable store and initialze it with + //content of the NVRAM flash area. + if (VarStoreInfo.NvramMode & NVRAM_MODE_SIMULATION) + { + VarStoreInfo.NvInterface=&MemInterface; + InitVolatileStore( + &NvStore, NvramHob->NvramSize, + VarStoreInfo.HeaderLength, + NVRAM_STORE_FLAG_NON_VALATILE,TRUE + ); + MemCpy(NvStore.NvramAddress,(UINT8*)NvramHob->NvramAddress,NvStore.NvramSize); + //We altered content of the varstore. Let's reinitialize it. + NvInitInfoBuffer( + &NvStore, VarStoreInfo.HeaderLength, + NVRAM_STORE_FLAG_NON_VALATILE + ); + //no backup in the simulation mode + VarStoreInfo.BackupAddress=0; + NVRAM_TRACE((TRACE_DXE_CORE,"NVRAM: working in simulation mode\n")); + } + + else + { + VarStoreInfo.NvInterface=&NvInterface; + NvStore.NvramAddress = (UINT8*)NvramHob->NvramAddress; + NvStore.NvramSize = NvramHob->NvramSize; + NvInitInfoBuffer( + &NvStore, + VarStoreInfo.HeaderLength, + NVRAM_STORE_FLAG_NON_VALATILE + ); + } + + //If FV header is corrupted or built-in defaults are not found, + //reset NVRAM data; use external defaults. + if ( ((EFI_FIRMWARE_VOLUME_HEADER*)NvStore.NvramAddress)->Signature!=FV_SIGNATURE + || NvGetDefaultsInfo(StdDefaults, &NvStore, &DefaultsInfo) == NULL + ){ + UseExternalDefaults = TRUE; + PreserveVariablesWithNoDefaults = TRUE; + VarStoreInfo.NvramMode |= NVRAM_MODE_RESET_CONFIGURATION; + } + //Handle NVRAM reset + if (VarStoreInfo.NvramMode & NVRAM_MODE_RESET_CONFIGURATION) + { + NvResetConfiguration( + &NvStore,VarStoreInfo.NvInterface, + UseExternalDefaults, PreserveVariablesWithNoDefaults + ); + VarStoreInfo.NvramMode&=~NVRAM_MODE_RESET_CONFIGURATION; + } +#ifdef HYBRID_NV_INTERFACE + if (!(VarStoreInfo.NvramMode & NVRAM_MODE_SIMULATION)) + InitHybridInterface(&NvStore); +#endif + VarStoreDiscovery(&NvStore,&MemStore); +#if NV_CACHE_SUPPORT + IndexInit(); +#endif + + if (!DxeIsNvramDataCompatible(DxeGetVariableSafe)) + { + NVRAM_TRACE((TRACE_DXE_CORE, "NVRAM DXE: Incompactible NVRAM detected\n")); + NvResetConfiguration( + VarStoreInfo.NvInfo, VarStoreInfo.NvInterface, + TRUE, TRUE + ); + } + + return EFI_SUCCESS; +} + +EFI_STATUS NvramReinitialize() +{ + NVRAM_STORE_INFO NvStore, MemStore; + + NvStore.NvramAddress = VarStoreInfo.NvInfo->NvramAddress; + NvStore.NvramSize = VarStoreInfo.NvInfo->NvramSize; + MemStore = *VarStoreInfo.MemInfo; + NvInitInfoBuffer( + &NvStore, + VarStoreInfo.HeaderLength, + NVRAM_STORE_FLAG_NON_VALATILE + ); + VarStoreDiscovery(&NvStore,&MemStore); +#if NV_CACHE_SUPPORT + IndexReset(); +#endif + return EFI_SUCCESS; +} +//////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +static EFI_GUID guidVariable = EFI_VARIABLE_ARCH_PROTOCOL_GUID; +static EFI_GUID guidVariableWrite = EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID; +static EFI_GUID guidMonotonicCounter = EFI_MONOTONIC_COUNTER_ARCH_PROTOCOL_GUID; +extern EFI_GUID gAmiGlobalVariableGuid; +UINT32 CounterLo=0, CounterHi=0; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetNextHighMonotonicCount +// +// Description: This function gets Next High Monotonic Count +// +// Input: OUT UINT32 *HighCount - pointer to where result will be stored +// +// Output: EFI_STATUS based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetNextHighMonotonicCount(OUT UINT32 *HighCount) +{ + EFI_STATUS Status; + UINTN Size = sizeof(UINT32); + + if (!HighCount) return EFI_INVALID_PARAMETER; + + if (!CounterHi) + { + Status = pRS->GetVariable(L"MonotonicCounter", &gAmiGlobalVariableGuid, + NULL, &Size, &CounterHi + ); + + if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) + return Status; + } + + ++CounterHi; + Status = pRS->SetVariable( + L"MonotonicCounter", &gAmiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + Size, &CounterHi + ); + + if (EFI_ERROR(Status)) return Status; + + *HighCount = CounterHi; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetNextMonotonicCount +// +// Description: This function gets Next low and high Monotonic Count +// +// Input: OUT UINT64 *Count - pointer to where result will be stored +// +// Output: EFI_STATUS based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetNextMonotonicCount(OUT UINT64 *Count) +{ + if (!Count) return EFI_INVALID_PARAMETER; + + ((UINT32*)Count)[0] = CounterLo++; + //--- If low counter overflovs - GetNextHighMonotonicCount + if (!CounterLo) return GetNextHighMonotonicCount(&((UINT32*)Count)[1]); + //--- If not - get current HighMonotonicCount + else ((UINT32*)Count)[1] = CounterHi; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: QueryVariableInfo +// +// Description: This function returns parameters of VarStore with passed attributes +// +// Input: IN UINT32 Attributes - Atributes to search for +// OUT UINT64 *MaximumVariableStorageSize - Maximum Variable Storage Size +// OUT UINT64 *RemainingVariableStorageSize - Remaining Variable Storage Size +// OUT UINT64 *MaximumVariableSize - Maximum Variable Size +// +// Output: EFI_STATUS based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS QueryVariableInfo ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize +) +{ + UINT64 StorageSize,RemainingStorage,MaxVarSize; + NVRAM_STORE_INFO *Info; + UINTN SizeOfVarSizeType = MAX_NVRAM_VARIABLE_SIZE; + + if ( !Attributes || (Attributes & ~ALL_VARIABLE_ATTRIBUTES) + ||(Attributes & EFI_VARIABLE_RUNTIME_ACCESS) && !(Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS ) + || !MaximumVariableStorageSize || !RemainingVariableStorageSize || !MaximumVariableSize + ) + return EFI_INVALID_PARAMETER; + + Info = (Attributes & EFI_VARIABLE_NON_VOLATILE) + ? VarStoreInfo.NvInfo : VarStoreInfo.MemInfo; + StorageSize=Info->NvramSize; + RemainingStorage=(UINT8*)( + (EFI_GUID*)(Info->NvramAddress+Info->NvramSize) + - Info->NextGuid-1 + )-Info->pEndOfVars; + MaxVarSize= (SizeOfVarSizeType>RemainingStorage) + ? RemainingStorage : SizeOfVarSizeType; + MaxVarSize -= sizeof(NVAR) + sizeof(EFI_GUID); + + if ((INTN)MaxVarSize<0) MaxVarSize=0; + + *MaximumVariableStorageSize = StorageSize; + *RemainingVariableStorageSize = RemainingStorage; + *MaximumVariableSize = MaxVarSize; + return EFI_SUCCESS; +} + +VOID NvramNotInSmmExitBs(); +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: VarExitBS +// +// Description: This function will be called when Exit BS will signaled +// will update data to work in RunTime. +// +// Input: IN EFI_EVENT Event - signalled event +// IN VOID *Context - calling context +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID VarExitBS (IN EFI_EVENT Event, IN VOID *Context) +{ + Runtime = TRUE; +#if NV_CACHE_SUPPORT + IndexExitBs(); +#endif + //When we call this function from SMM, Event is NULL + if (Event!=NULL) NvramNotInSmmExitBs(); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: VarStoreVirtualFixup +// +// Description: This function will be invoked to convert +// runtime pointers to virtual address +// +// Input: NVRAM_STORE_INFO *Info - pointer to NVRAM_STORE_INFO structure to fixup +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID VarStoreVirtualFixup(NVRAM_STORE_INFO *Info) +{ + pRS->ConvertPointer(0,&Info->pFirstVar); + pRS->ConvertPointer(0,&Info->pEndOfVars); + pRS->ConvertPointer(0,&Info->NvramGuidsAddress); + pRS->ConvertPointer(0,&Info->NvramAddress); + Info->pLastReturned=NULL; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: VarInterfaceVirtualFixup +// +// Description: This function will be invoked to convert +// runtime pointers to virtual address +// +// Input: VARIABLE_INTERFACE *Interface - pointer to VARIABLE_INTERFACE structure to fixup +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID VarInterfaceVirtualFixup(VARIABLE_INTERFACE *Interface) +{ + pRS->ConvertPointer(0,(VOID**)&Interface->EnableUpdate); + pRS->ConvertPointer(0,(VOID**)&Interface->DisableUpdate); + pRS->ConvertPointer(0,(VOID**)&Interface->EraseBytes); + pRS->ConvertPointer(0,(VOID**)&Interface->WriteBytes); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: VarVirtAddressChange +// +// Description: This function will be invoked to convert whole Var infrustructure +// and pRS runtime pointers to virtual address +// +// Input: IN EFI_EVENT Event - signalled event +// IN VOID *Context - calling context +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID VarVirtAddressChange (IN EFI_EVENT Event, IN VOID *Context) +{ + UINTN i; + VarStoreVirtualFixup(VarStoreInfo.NvInfo); +#ifdef HYBRID_NV_INTERFACE + pRS->ConvertPointer(0,&VarStoreInfo.NvramFlashAddress); + VarStoreInfo.AddressDelta=VarStoreInfo.NvramFlashAddress-VarStoreInfo.NvInfo->NvramAddress; +#endif + for (i=0; i< VarStoreInfo.InfoCount; i++) + if (VarStoreInfo.NvInfo!=&VarStoreInfo.NvramInfo[i]) + VarStoreVirtualFixup(&VarStoreInfo.NvramInfo[i]); + + for (i=0; GetVariableHookList[i]; i++){ + pRS->ConvertPointer(0,(VOID**)&(GetVariableHookList[i])); + } + + for (i=0; SetVariableHookList[i]; i++){ + pRS->ConvertPointer(0,(VOID**)&(SetVariableHookList[i])); + } + + for (i=0; GetNextVarNameHookList[i]; i++){ + pRS->ConvertPointer(0,(VOID**)&(GetNextVarNameHookList[i])); + } + + pRS->ConvertPointer(0,&VarStoreInfo.NvInfo); + pRS->ConvertPointer(0,&VarStoreInfo.MemInfo); + VarInterfaceVirtualFixup(VarStoreInfo.NvInterface); + VarInterfaceVirtualFixup(VarStoreInfo.MemInterface); + pRS->ConvertPointer(0,&VarStoreInfo.NvInterface); + pRS->ConvertPointer(0,&VarStoreInfo.MemInterface); + if (VarStoreInfo.BackupAddress!=NULL) + pRS->ConvertPointer(0,&VarStoreInfo.BackupAddress); + if (NvramDriverBuffer) + pRS->ConvertPointer(0,(VOID**)&NvramDriverBuffer); + VarStoreInfo.LastInfoIndex = 0; + pRS->ConvertPointer(0, &Flash); +#if NV_CACHE_SUPPORT + IndexVirtualFixup(); +#endif + //Fixup global data for for a virtual address space. + FlashVirtualFixup(pRS); + //pRS is converted by the library + //(call to InitAmiRuntimeLib initiates the processes) + AuthServiceVirtualFixup(); +} + +/////////////////////////////////////////////////////////////////// + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MonotonicCounterInit +// +// Description: This function initialize pBS MonotonicCount servicies and installs +// corresponding protocols +// +// Input: IN EFI_HANDLE ImageHandle - Image handle +// IN EFI_SYSTEM_TABLE *SystemTable - pointer to System Table +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID MonotonicCounterInit( + IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable +) +{ + EFI_HANDLE Handle = NULL; + UINT32 HighCount; + InitAmiLib(ImageHandle,SystemTable); + pRS->GetNextHighMonotonicCount = GetNextHighMonotonicCount; + pBS->GetNextMonotonicCount = GetNextMonotonicCount; + //Init Hi part of the monotonic counter + GetNextHighMonotonicCount(&HighCount); + pBS->InstallMultipleProtocolInterfaces( + &Handle, + &guidMonotonicCounter, NULL, + NULL + ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvRamInit +// +// Description: This function initialize pRS Var servicies and MonotonicCount servicies +// (if MONOTONIC_COUNT_IN_NVRAM token is set) installs +// corresponding protocols +// +// Input: IN EFI_HANDLE ImageHandle - Image handle +// IN EFI_SYSTEM_TABLE *SystemTable - pointer to System Table +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID NvRamInit( + IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable +) +{ + EFI_HANDLE Handle = NULL; + EFI_EVENT Event; + EFI_STATUS Status; + + //TODO: When DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME is defined, we assume that + //DXE Variable services will be replaced prior to transitioning to runtime. + //If this will not happen, the NVRAM driver may not work properly. + //It may either crash (or crash the Windows), or generate false garbage collections. + //If support fall back scenario the memory registration of the virtual address change event + //and cdoe that allocates hybrid mode buffer must be changed + //TODO: When DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME is defined, we can allocate MemStore buffer in boot time memory. + InitAmiRuntimeLib( + ImageHandle, SystemTable, VarExitBS, +#ifdef DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME + NULL +#else + VarVirtAddressChange +#endif + ); + PROGRESS_CODE(DXE_NVRAM_INIT); + + Status = pBS->LocateProtocol(&gFlashProtocolGuid, NULL, &Flash); + ASSERT_EFI_ERROR(Status); + + NvramInitialize(); +// We need to know when to switch to the Runtime mode. +// Switch to runtime happens on exit boot services or legacy boot event. +// exit boot services callabck is installed by the InitAmiRuntimeLib function. +// Let's install legacy boot callbakc here. + CreateLegacyBootEvent(TPL_CALLBACK, &VarExitBS, NULL, &Event); + pRS->GetNextVariableName = DxeGetNextVariableNameSafe; + pRS->GetVariable = DxeGetVariableSafe; + pRS->SetVariable = DxeSetVariableSafe; + pRS->QueryVariableInfo = QueryVariableInfo; + + pBS->InstallMultipleProtocolInterfaces( + &Handle, + &guidVariable, NULL, + &guidVariableWrite, NULL, + NULL + ); + //--- Install MonotonicCount servicies (if NVRAM_MONOTONIC_COUNTER_SUPPORT token is set) + if (NvramMonotonicCounterSupport) MonotonicCounterInit(ImageHandle, SystemTable); +} + + +//********************************************************************** +// NVRAM SMM BEGIN +//********************************************************************** +//when this type is changed, initialization of the NvRamMailboxBuffer variable must also be changed. +typedef struct +{ +//TODO: StopRtDataAccess - must be the first field; NvramSmi driver is using it + BOOLEAN StopRtDataAccess; + VARSTORE_INFO *VarStoreInfoPtr; + VAR_INDEX *VarIndexPtr; + BOOLEAN SwitchToRuntime; + CRITICAL_SECTION *NvramCsPtr; + EFI_PHYSICAL_ADDRESS NvramDriverBuffer; + UINT32 NvramBuffSize; +} NVRAM_MAILBOX; + +#define NVRAM_MAILBOX_ADDRESS_VARIABLE_GUID \ + {0x54913a6d, 0xf4ee, 0x4cdb, 0x84, 0x75, 0x74, 0x6, 0x2b, 0xfc, 0xec, 0xf5} + +EFI_GUID NvRamMailboxVariableGuid = NVRAM_MAILBOX_ADDRESS_VARIABLE_GUID; +NVRAM_MAILBOX *NvRamMailbox; + +/*************** OUTSIDE SMM **********************************/ + +NVRAM_MAILBOX NvRamMailboxBuffer = {FALSE, &VarStoreInfo, NULL, FALSE, NULL, 0, 0}; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: LegacyToEfiFn +// +// Description: +// +// Input: +// +// Output: +// +// Notes: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +LegacyToEfiFn ( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + // NvramCsPtr = &NvramCs; + Runtime = FALSE; + NvRamMailbox->SwitchToRuntime = FALSE; + + + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvramNotInSmmInit +// +// Description: This function initialize pRS Var, MonotonicCount servicies +// (if MONOTONIC_COUNT_IN_NVRAM token is set) and installs +// corresponding protocols and sets NvRamMailbox Var not in SMM +// +// Input: IN EFI_HANDLE ImageHandle - Image handle +// IN EFI_SYSTEM_TABLE *SystemTable - pointer to System Table +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvramNotInSmmInit( + IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable +) +{ + + EFI_GUID pLTEBGuid = LTEB_GUID; + EFI_EVENT Event; + + EFI_STATUS Status; + + NvRamInit(ImageHandle, SystemTable); + NvRamMailboxBuffer.VarIndexPtr = VarIndexPtr; + NvRamMailboxBuffer.NvramCsPtr = NvramCsPtr; + if (NvramRtGarbageCollectionSupport) { + NvRamMailboxBuffer.NvramDriverBuffer = NvramDriverBuffer; + NvRamMailboxBuffer.NvramBuffSize = NvramDriverBufferSize; + } + NvRamMailbox = &NvRamMailboxBuffer; + + AuthVariableServiceInit (); + + Status = pBS->CreateEventEx( EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + LegacyToEfiFn, + NULL, + &pLTEBGuid, + &Event); + + Status = pRS->SetVariable( + L"NvRamMailbox",&NvRamMailboxVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof(NvRamMailbox), &NvRamMailbox + ); + ASSERT_EFI_ERROR(Status); + + return EFI_SUCCESS; +} +/*************** INSIDE SMM **********************************/ +VARSTORE_INFO *RtVarStoreInfoPtr; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SynchronizeVarStore +// +// Description: This function synchronizes NVRAM_STORE_INFO structure after enterin SMM +// +// Input: NVRAM_STORE_INFO *Source - source NVRAM_STORE_INFO structure +// NVRAM_STORE_INFO *Target - synchronized NVRAM_STORE_INFO structure +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID SynchronizeVarStore(NVRAM_STORE_INFO *Source, NVRAM_STORE_INFO *Target) +{ + UINTN Delta = Target->NvramAddress - Source->NvramAddress; + Target->pFirstVar = Source->pFirstVar + Delta; + Target->pEndOfVars = Source->pEndOfVars + Delta; + Target->NextGuid = Source->NextGuid; + Target->LastVarSize = Source->LastVarSize; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SynchronizeVarStoreInfo +// +// Description: This function synchronizes all NVRAM_STORE_INFO structures in VARSTORE_INFO after enterin SMM +// +// Input: VARSTORE_INFO *From - source VARSTORE_INFO structure +// VARSTORE_INFO *To - synchronized VARSTORE_INFO structure +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID SynchronizeVarStoreInfo(VARSTORE_INFO *From, VARSTORE_INFO *To) +{ + UINT32 i; + To->InfoCount = From->InfoCount; + + for (i=0; i<From->InfoCount; i++) + { + SynchronizeVarStore(&From->NvramInfo[i], &To->NvramInfo[i]); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SynchronizeBeforeOperation +// +// Description: This function synchronizes Runtime and non Runtime Var Structures after enterin SMM +// before each operation with Variables +// +// Input: NONE +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID SynchronizeBeforeOperation() +{ +#ifdef DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME +if (!NoAccessOutsideofSmm) +#endif +{ + SynchronizeVarStoreInfo( + RtVarStoreInfoPtr,&VarStoreInfo + ); + VarStoreInfo.NvInfo = (NVRAM_STORE_INFO*)( + (UINT8*)RtVarStoreInfoPtr->NvInfo - (UINT8*)NvRamMailbox->VarStoreInfoPtr + + (UINT8*)&VarStoreInfo + ); + VarStoreInfo.MemInfo = (NVRAM_STORE_INFO*)( + (UINT8*)RtVarStoreInfoPtr->MemInfo - (UINT8*)NvRamMailbox->VarStoreInfoPtr + + (UINT8*)&VarStoreInfo + ); +#ifdef DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME + if (NvRamMailbox->StopRtDataAccess){ + NoAccessOutsideofSmm=TRUE; +#if NV_CACHE_SUPPORT +//TODO: This has to be reviewed if RT Index support is added + //Shutdown the index + IndexExitBs(); +#endif + ReallocateVolatileVarstoreToSmm(); +#ifdef HYBRID_NV_INTERFACE + ReallocateHybridVarstoreToSmm(); +#endif + NvramCs = *NvramCsPtr; + NvramCsPtr->Busy = FALSE; + NvramCsPtr = &NvramCs; // switch to local CS + } +#endif +} + if (!Runtime && NvRamMailbox->SwitchToRuntime){ + VarExitBS(NULL,NULL); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SynchronizeAfterOperation +// +// Description: This function synchronizes Runtime and non Runtime Var Structures after enterin SMM +// after each operation with Variables +// +// Input: NONE +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID SynchronizeAfterOperation() +{ +#ifdef DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME +if (!NoAccessOutsideofSmm) +#endif +{ + SynchronizeVarStoreInfo( + &VarStoreInfo, RtVarStoreInfoPtr + ); + RtVarStoreInfoPtr->NvInfo = (NVRAM_STORE_INFO*)( + (UINT8*)VarStoreInfo.NvInfo - (UINT8*)&VarStoreInfo + + (UINT8*)NvRamMailbox->VarStoreInfoPtr + ); + RtVarStoreInfoPtr->MemInfo = (NVRAM_STORE_INFO*)( + (UINT8*)VarStoreInfo.MemInfo - (UINT8*)&VarStoreInfo + + (UINT8*)NvRamMailbox->VarStoreInfoPtr + ); +} +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmmGetVariable +// +// Description: This function searches for Var with specific GUID and Name in SMM +// synchronizing Varstors before and after operation +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// OPTIONAL OUT UINT32* Attributes - Pointer to memory where Attributes will be returned +// IN OUT UINTN *DataSize - size of Var - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// OUT VOID *Data - Pointer to memory where Var will be returned +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SmmGetVariable( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, OUT VOID *Data +) +{ + EFI_STATUS Status; + BEGIN_CRITICAL_SECTION(NvramCsPtr); + SynchronizeBeforeOperation(); + Status = DxeGetVariable( + VariableName, VendorGuid, Attributes, DataSize, Data + ); + SynchronizeAfterOperation(); + END_CRITICAL_SECTION(NvramCsPtr); + return Status; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmmSetVariable +// +// Description: This function sets Var with specific GUID, Name and attributes in SMM +// synchronizing Varstors before and after operation +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// IN UINT32 Attributes - Attributes of the Var +// IN UINTN DataSize - size of Var +// IN VOID *Data - Pointer to memory where Var data is stored +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SmmSetVariable( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data +) +{ + EFI_STATUS Status; + + BEGIN_CRITICAL_SECTION(NvramCsPtr); + SynchronizeBeforeOperation(); + Status = DxeSetVariable( + VariableName, VendorGuid, Attributes, DataSize, Data + ); + SynchronizeAfterOperation(); + END_CRITICAL_SECTION(NvramCsPtr); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmmGetNextVariableName +// +// Description: This function searches for next Var after Var with specific name and GUID and returns it's Name +// in SMM synchronizing Varstors before and after operation. +// +// Input: IN OUT UINTN *VariableNameSize - size of Varname - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// IN OUT CHAR16 *VariableName - pointer where Var Name in Unicode will be stored +// IN OUT EFI_GUID *VendorGuid - pointer to menory where Var GUID is stored +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SmmGetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid +) +{ + EFI_STATUS Status; + + BEGIN_CRITICAL_SECTION(NvramCsPtr); + SynchronizeBeforeOperation(); + Status = DxeGetNextVariableName( + VariableNameSize, VariableName, VendorGuid + ); + SynchronizeAfterOperation(); + END_CRITICAL_SECTION(NvramCsPtr); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmmQueryVariableInfo +// +// Description: This function returns parameters of VarStore with passed attributes in SMM +// synchronizing Varstors before operation. +// +// Input: IN UINT32 Attributes - Atributes to search for +// OUT UINT64 *MaximumVariableStorageSize - Maximum Variable Storage Size +// OUT UINT64 *RemainingVariableStorageSize - Remaining Variable Storage Size +// OUT UINT64 *MaximumVariableSize - Maximum Variable Size +// +// Output: EFI_STATUS based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SmmQueryVariableInfo ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize +) +{ + EFI_STATUS Status; + + SynchronizeBeforeOperation(); + Status = QueryVariableInfo( + Attributes, MaximumVariableStorageSize, + RemainingVariableStorageSize, MaximumVariableSize + ); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvramSmmInit +// +// Description: This function gets NvRamMailbox and initialize pRS Var servicies and +// corresponding structures +// +// Input: IN EFI_HANDLE ImageHandle - Image handle +// IN EFI_SYSTEM_TABLE *SystemTable - pointer to System Table +// +// Output: EFI_STATUS based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvramSmmInit( + IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable +) +{ + EFI_STATUS Status; + UINTN Size=sizeof(NvRamMailbox); + + Status = pST->RuntimeServices->GetVariable( + L"NvRamMailbox",&NvRamMailboxVariableGuid, + NULL, &Size, &NvRamMailbox + ); + + if (EFI_ERROR(Status)) return Status; + + RtVarStoreInfoPtr = NvRamMailbox->VarStoreInfoPtr; + VarStoreInfo=*RtVarStoreInfoPtr; + VarIndexPtr=NvRamMailbox->VarIndexPtr; + NvramCsPtr=NvRamMailbox->NvramCsPtr; + + if (NvramRtGarbageCollectionSupport){ + NvramDriverBuffer = NvRamMailbox->NvramDriverBuffer; + NvramDriverBufferSize = NvRamMailbox->NvramBuffSize; + } + + VarStoreInfo.MemInterface=&MemInterface; + VarStoreInfo.NvInfo = + &VarStoreInfo.NvramInfo[ + RtVarStoreInfoPtr->NvInfo - RtVarStoreInfoPtr->NvramInfo + ]; + VarStoreInfo.MemInfo = + &VarStoreInfo.NvramInfo[ + RtVarStoreInfoPtr->MemInfo - RtVarStoreInfoPtr->NvramInfo + ]; +#ifdef HYBRID_NV_INTERFACE + VarStoreInfo.NvInterface=&HybridInterface; +#else + VarStoreInfo.NvInterface=&NvInterface; +#endif + + pRS->GetNextVariableName = SmmGetNextVariableName; + pRS->GetVariable = SmmGetVariable; + pRS->SetVariable = SmmSetVariable; + pRS->QueryVariableInfo = SmmQueryVariableInfo; + Status = pBS->LocateProtocol(&gFlashSmmProtocolGuid, NULL, &Flash); + ASSERT_EFI_ERROR (Status); + AuthVariableServiceInitSMM(); + InstallNvramControlSmmProtocol(); + return EFI_SUCCESS; +} + +/*************** INSIDE and OUSIDE SMM ************************/ +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvramNotInSmmExitBs +// +// Description: This function signals that exit BS event was taken place and switches +// SwitchToRuntime field in NvRamMailbox +// +// Input: NONE +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID NvramNotInSmmExitBs() +{ + NvRamMailbox->SwitchToRuntime = !NvRamMailbox->SwitchToRuntime; +#ifdef DO_NOT_ACCESS_DATA_OUTSIDE_OF_SMM_AT_RUNTIME + //Make a dummy SMM GetVariable call to process SwitchToRuntime + //make sure GetVariable is substituted + if (pRS->GetVariable!=DxeGetVariableSafe){ + static EFI_GUID DummyGuid={0}; + UINTN Size = 0; + UINTN Dummy; + pRS->GetVariable(L"Dummy", &DummyGuid,NULL, &Size, &Dummy); + } +#endif +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvRamSmmEntry +// +// Description: This function is the entry point for this DXE. This function +// installs NvRam services in and outside SMM. +// +// Input: IN EFI_HANDLE ImageHandle - Image handle +// IN EFI_SYSTEM_TABLE *SystemTable - Pointer to the system table +// +// Output: EFI_STATUS - Status based on errors that occurred while waiting for +// time to expire. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvRamSmmEntry( + IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable +) +{ + InitAmiLib(ImageHandle,SystemTable); + return InitSmmHandlerEx( + ImageHandle, SystemTable, NvramSmmInit, NvramNotInSmmInit + ); +} +//********************************************************************** +// NVRAM SMM END +//********************************************************************** +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/NVRAM/NVRAMPEI.c b/Core/EM/NVRAM/NVRAMPEI.c new file mode 100644 index 0000000..53ebd2b --- /dev/null +++ b/Core/EM/NVRAM/NVRAMPEI.c @@ -0,0 +1,584 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/Modules/NVRAM/NVRAMPEI.c 19 5/22/14 6:05p Oleksiyy $ +// +// $Revision: 19 $ +// +// $Date: 5/22/14 6:05p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Modules/NVRAM/NVRAMPEI.c $ +// +// 19 5/22/14 6:05p Oleksiyy +// [TAG] EIP170545 +// [Category] Improvement +// [Description] Spelling errors corrected. +// [Files] NVRAMPEI.c +// +// 18 1/04/13 10:35a Felixp +// Minor improvement in PeiInitNV: when CreateHob fails, still install the +// PPI. +// +// 17 12/13/12 6:17p Oleksiyy +// [TAG] EIP109422 +// [Category] Improvement +// [Description] Issues found by CppCheck in NVRAM Module part +// [Files] NVRAMDXE.c and NVRAMPEI.c +// +// 16 8/12/11 12:15p Artems +// EIP 64107: Added changes for module to be compliant with UEFI +// specification v 2.3.1 +// +// 15 2/02/10 5:15p Oleksiyy +// EIP 33263 : Hooks for SetVariable, GetVariable and GetNextVarName +// added +// +// 14 11/24/09 4:05p Oleksiyy +// EIP 26085: Added support to read All the NVRAM variable (including +// defoults) with GetNextVariable in PEI and DXE. +// +// 13 11/23/09 6:25p Felixp +// +// 12 11/23/09 4:44p Felixp +// Code to validate NVRAM header fields used by the NVRAM driver is added. +// If problem is found, the header fields are updated with the correct +// values. +// +// 11 7/10/09 8:50a Felixp +// Code clean up; comments and function header added +// +// 10 6/26/09 3:29p Felixp +// Active varstore detection is moved into new IsMainNvramStoreValid +// function in NvramRead.c +// +// 9 5/21/09 5:39p Felixp +// 1. Disable NVRAM content if it has been corrupted during failed BIOS +// update +// 2. Validate compatibility of the NVRAM data using external hook +// (IsNvramDataCompatible). +// Disable incompatible NVRAM content. +// +// 8 1/16/09 3:39p Felixp +// New Feature. EIP 18483. Interface of the hooks that detect NVRAM +// operational mode is extended. +// NVRAM driver uses platform hooks(IsMfgMode, IsResetConfigMode, +// IsDefaultConfigMode) to detect, which set of configuration values +// are to be used. In some cases the mode is detected based on value of +// the NVRAM variable. +// Interface of the hook functions is extended. New parameter is added. +// Pointer to EFI_PEI_READ_ONLY_VARIABLE2_PPI PPI is passed to the hook +// functions. +// The pointer can be used to read and enumerate existing NVRAM variables. +// +// 7 10/09/08 11:47a Felixp +// 1. Fault tolerant NVRAM garbage collection support is added. +// Use FAULT_TOLERANT_NVRAM_UPDATE SDL token to enable/disable (disabled +// by default). +// NOTE: This feature requires upgrade of the Board module. +// NOTE: This feature requires porting: +// Fault tolerant update requires reserved flash area of size NVRAM_SIZE +// used for back up during NVRAM garbage collection. +// The address of the area is defined by NVRAM_BACKUP_ADDRESS SDL token +// defined in Board.sdl. +// Size and Base addresses of other firmware volumes may need to be +// adjusted to free up space for the NVRAM back up area. +// Default ROM layout expects NVRAM back up area immediately below the +// main NVRAM area. +// For projects with the customized ROM layout Core.mak has to be updated. +// 2. Top level NVRAM function updated to be reentrance-safe. +// NOTE: This feature requires upgrade of the SB module. +// 3. Improved recovery from the flash programming failures and +// corruptions within NVRAM area. +// 4. More reliable non-fault tolerant garbage collection. +// +// 6 6/06/08 11:01a Felixp +// +// 4 2/19/08 11:07p Felixp +// Update in init routine PeiInitNV: during boot with default +// configuration, main NVRAM store is also exposed. This is needed to +// provide current value for variables without defaults. +// +// 3 9/06/07 12:14a Felixp +// +// 2 8/31/07 3:44p Felixp +// NVRAM code has been significantly changed to introduce the following +// improvements: +// 1. The code is chaned to always use the same amount of memory. +// Previous implementation allocated memory as needed, which caused +// occasional S4 problems. +// Plus S4 resume never worked during the very first boot after the +// firmware update. +// 2. Support for NVRAM defaults added. +// NVRAM image with the default values for the Setup variables is now +// generated by the build process. +// The image is generated by the HpkTool (included into AMITSE module +// part). +// In addition to standard Setup defaults it is also possible +// to generate manufactoring defaults. Support for the manufactoring +// defaults +// is disabled by default and can be enabled using +// MANUFACTURING_MODE_SUPPORT SDL token. +// 3. Support for boot with alternative configurations is added. +// Decision to switch to the alternative configuration +// (alternative set of values for NVRAM variables) +// is based on values returned by the porintg routine in OemPort.c. +// During boot with alternative configurations GetVariable service +// returns alternative values for the setup-related variables. +// If variable does not have an alternative value, current value is +// returned. +// Two alternative configurations are supported: +// Boot with manufactoring settings(activated when IsMfgMode routine in +// OemPort.c returns TRUE). +// Boot with default settings(activated when IsDefaultConfigMode routine +// in OemPort.c returns TRUE). +// NOTE: This feature requires of the Board module +// 4.NVRAM reset option is added. +// If porting routine IsResetConfigMode in OemPort.c returns TRUE in PEI +// phase, +// NVRAM content will be reset during initialization of the DXE NVRAM +// driver. +// During reset operation all setup-related variables are reset to their +// default values. +// All other variables are deleted. +// NOTE: This feature requires upgrade of the Board module +// 5.Detection of NVRAM update added. +// NVRAM implementation detects if NVRAM has been updated since the last +// NVRAM call. +// This provides ability to use variables services before and after +// firmware update. +// 6.Overall code clean up and simplification. +// 7.Core Sources are no longer required in order to use NV_SIMULATION +// option. +// 8.PI 1.0 support. +// Support for a PI 1.0 complient variable PPI is added. Old PPI is still +// preserved in this label for backward compatibility. +// New library routines PeiGetVariable and PeiGetNextVariableName are +// created in order to hide the differences between two PPIs. +// It is recommended to update existing code to use new library routines. +// Support of the old PPI may be dropped in the future versions of Core. +// 9. NVRAM is now packaged as a raw FFS file embedded into the standard +// FV (used to be non-standard FV with raw NVRAM image). +// Validation: New NVRAM code has been validated using SCT and EFI version +// of Windows Server 2008 +// Files modified: Core.sdl, Core.mak, AmiPeiLib.h, PeiLib.c, +// ReadOnlyVariable.h, , Token.c, HpkTool.exe, AMITSE.mak, Setup.ini, +// NVRAM.sdl, NVRAM.mak, NVRAM.h, NVRAMRead.c, NVRAMPEI.c, +// NVRAMDXE.c +// +// 1 8/24/06 12:38p Felixp +// +// 3 10/09/05 11:25a Felixp +// Performance measurements added. +// +// 2 3/04/05 9:42a Mandal +// +// 1 1/28/05 12:44p Felixp +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/27/04 4:08p Felixp +// +// 3 4/05/04 1:10a Felixp +// +// 2 4/04/04 2:58p Felixp +// +// 1 3/29/04 2:32a Felixp +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: NVRAMPEI.h +// +// Description: +// +//<AMI_FHDR_END> +//********************************************************************** +#include <PPI/ReadOnlyVariable2.h> +#include <PPI/ReadOnlyVariable.h> +#include <AmiPeiLib.h> +#include "NVRAM.h" + +//Defined in CSPLib(OEMPort.c) +BOOLEAN IsMfgMode( + IN EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadVariablePpi +); +BOOLEAN IsResetConfigMode( + IN EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadVariablePpi +); +BOOLEAN IsDefaultConfigMode( + IN EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadVariablePpi +); +BOOLEAN IsNvramDataCompatible( + IN EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadVariablePpi +); + +//Defined in Tokens.c +extern UINTN NvramAddress; +extern UINTN NvramBackupAddress; +extern const UINTN NvramSize; +extern const BOOLEAN NvSimulation; + +typedef struct{ + EFI_PEI_READ_ONLY_VARIABLE2_PPI Ppi; + UINT32 InfoCount; + UINT32 LastInfoIndex; + NVRAM_STORE_INFO NvramInfo[3]; + NVRAM_STORE_INFO *MainInfo; +} VARIABLE_PPI; + +//--- GetVariable and GetNextVarName Hooks ------ +//============================================================================ +// Type definitions +typedef EFI_STATUS (PEI_HOOK_GET_VARIABLE)( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN CONST CHAR16 *VariableName, IN CONST EFI_GUID *VendorGuid, + OUT UINT32 *Attributes, IN OUT UINTN *DataSize, OUT VOID *Data +); + +typedef EFI_STATUS (PEI_HOOK_GET_NEXT_VARIABLE_NAME)( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid +); + +//====================================================================== +// Global extern variables + +extern PEI_HOOK_GET_VARIABLE PEI_GET_VAR_LIST EndOfGetVariableHook; +extern PEI_HOOK_GET_NEXT_VARIABLE_NAME PEI_GET_NEXT_VAR_NAME_LIST EndOfGetNextVarNameHook; + +PEI_HOOK_GET_VARIABLE* PeiGetVariableHookList[]= + {PEI_GET_VAR_LIST NULL}; +PEI_HOOK_GET_NEXT_VARIABLE_NAME* PeiGetNextVarNameHookList[]= + {PEI_GET_NEXT_VAR_NAME_LIST NULL}; + +EFI_STATUS PeiGetVariableHook( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN CONST CHAR16 *VariableName, IN CONST EFI_GUID *VendorGuid, + OUT UINT32 *Attributes, IN OUT UINTN *DataSize, OUT VOID *Data +){ + UINTN i; + EFI_STATUS Result = EFI_UNSUPPORTED; + for(i=0; PeiGetVariableHookList[i] && (Result == EFI_UNSUPPORTED); i++) + Result = PeiGetVariableHookList[i](This,VariableName, VendorGuid,Attributes, DataSize, Data); + return Result; +} + +EFI_STATUS PeiGetNextVarNameHook( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid +){ + UINTN i; + EFI_STATUS Result = EFI_UNSUPPORTED; + for(i=0; PeiGetNextVarNameHookList[i] && (Result == EFI_UNSUPPORTED); i++) + Result = PeiGetNextVarNameHookList [i](This,VariableNameSize,VariableName, VendorGuid); + return Result; +} +//---GetVariable and GetNextVarName Hooks END------ + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: VarPpiGetVariable +// +// Description: This function searches for a Variable with specific GUID and Name +// +// Input: IN EFI_PEI_SERVICES **PeiServices - Double pointer to Pei Services instance +// IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// OPTIONAL OUT UINT32* Attributes - Pointer to memory where Attributes will be returned +// IN OUT UINTN *DataSize - size of Var - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// OUT VOID *Data - Pointer to memory where Var will be returned +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS VarPpiGetVariable( + IN EFI_PEI_SERVICES **PeiServices, + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, OUT VOID *Data +) +{ + return PeiGetVariable( + PeiServices, VariableName, VendorGuid, Attributes, DataSize, Data + ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: VarPpiGetNextVariableName +// +// Description: This function searches for Var folowed by the Var with specific name (optional) +// and GUID and returns it's Name. +// +// Input: IN EFI_PEI_SERVICES **PeiServices - Double pointer to Pei Services instance +// IN OUT UINTN *VariableNameSize - size of Varname - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// IN OUT CHAR16 *VariableName - pointer where Var Name in Unicode will be stored +// IN OUT EFI_GUID *VendorGuid - pointer to menory where Var GUID is stored +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS VarPpiGetNextVariableName( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid +) +{ + return PeiGetNextVariableName( + PeiServices, VariableNameSize, VariableName, VendorGuid + ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: VarPpi2GetVariable +// +// Description: This function searches for Var with specific GUID +// +// Input: IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This - pointer to FI_PEI_READ_ONLY_VARIABLE2_PPI +// IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// OPTIONAL OUT UINT32* Attributes - Pointer to memory where Attributes will be returned +// IN OUT UINTN *DataSize - size of Var - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// OUT VOID *Data - Pointer to memory where Var will be returned +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS VarPpi2GetVariable( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN CONST CHAR16 *VariableName, IN CONST EFI_GUID *VendorGuid, + OUT UINT32 *Attributes, IN OUT UINTN *DataSize, OUT VOID *Data +) +{ + EFI_STATUS Status; + VARIABLE_PPI *VarPpi = (VARIABLE_PPI*)This; + Status = PeiGetVariableHook ( + This, VariableName, VendorGuid, Attributes, DataSize, Data + ); + if (Status != EFI_UNSUPPORTED) return Status; + Status = NvGetVariable2( + (CHAR16*)VariableName, (EFI_GUID*)VendorGuid, Attributes, + DataSize, Data, VarPpi->InfoCount, VarPpi->NvramInfo + ); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetNextVariableName2 +// +// Description: This function searches for Var with specific GUID and Enty number +// not betwin LastInfoIndex - InfoCount parameter and returns it's Name. +// +// Input: IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This - pointer to FI_PEI_READ_ONLY_VARIABLE2_PPI +// IN OUT UINTN *VariableNameSize - size of Varname - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// IN OUT CHAR16 *VariableName - pointer where Var Name in Unicode will be stored +// IN OUT EFI_GUID *VendorGuid - pointer to menory where Var GUID will be stored +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS VarPpi2GetNextVariableName( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid +) +{ + EFI_STATUS Status; + VARIABLE_PPI *VarPpi = (VARIABLE_PPI*)This; + Status = PeiGetNextVarNameHook ( + This, VariableNameSize, VariableName, VendorGuid + ); + if (Status != EFI_UNSUPPORTED) return Status; + Status = NvGetNextVariableName2( + VariableNameSize, VariableName, VendorGuid, + VarPpi->InfoCount, VarPpi->NvramInfo, + &(VarPpi->LastInfoIndex),FALSE + ); + return Status; +} + +// PPI interface definition +EFI_PEI_READ_ONLY_VARIABLE_PPI VariablePpi = {VarPpiGetVariable, VarPpiGetNextVariableName}; +EFI_PEI_READ_ONLY_VARIABLE2_PPI Variable2Ppi = {VarPpi2GetVariable, VarPpi2GetNextVariableName}; + +// PPI to be installed +EFI_PEI_PPI_DESCRIPTOR VariablePpiListTemplate[] = +{ + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiPeiReadOnlyVariable2PpiGuid, &Variable2Ppi + }, + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiReadOnlyVariablePpiGuid, &VariablePpi + } +}; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: PeiInitNV +// +// Description: This function inits NVRAM +// +// Input: IN EFI_FFS_FILE_HEADER *FfsHeader - pointer to FfsHeader +// IN EFI_PEI_SERVICES **PeiServices - double pointer to the Pei Sevices structure +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS PeiInitNV ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +) +{ + EFI_STATUS Status; + EFI_PEI_PPI_DESCRIPTOR *VariablePpiList; + VARIABLE_PPI *VarPpi; + UINT32 NvramMode=0; + NVRAM_HOB *pHob; + BOOLEAN ResetConfigMode; + NVRAM_STORE_INFO MainNvram; + VARIABLE_PPI TmpVarPpi; + VOID *BackupNvramAddress = (VOID*)NvramBackupAddress; + BOOLEAN BackupStoreValid; + BOOLEAN NvramIsCorrupted = FALSE; + + Status = (*PeiServices)->AllocatePool(PeiServices, sizeof(VariablePpiListTemplate)+sizeof(VARIABLE_PPI), &VariablePpiList); + if (EFI_ERROR(Status)) return Status; + VariablePpiList[0]=VariablePpiListTemplate[0]; + VariablePpiList[1]=VariablePpiListTemplate[1]; + VarPpi = (VARIABLE_PPI*)(VariablePpiList + 2); + VariablePpiList[0].Ppi = VarPpi; + VarPpi->Ppi = Variable2Ppi; + VarPpi->InfoCount = 0; + VarPpi->LastInfoIndex = 0; + MainNvram.NvramAddress = (UINT8*)NvramAddress; + MainNvram.NvramSize = NvramSize; + if (!IsMainNvramStoreValid(&MainNvram, BackupNvramAddress,&BackupStoreValid)){ + if (BackupStoreValid){ + VOID *Tmp = BackupNvramAddress; + BackupNvramAddress = MainNvram.NvramAddress; + MainNvram.NvramAddress = Tmp; + }else{ + NvramIsCorrupted = TRUE; + } + } + NvInitInfoBuffer( + &MainNvram, + NvramHeaderLength, + NVRAM_STORE_FLAG_NON_VALATILE + ); + //Check if FV signature is valid + NvramIsCorrupted = NvramIsCorrupted + || ((EFI_FIRMWARE_VOLUME_HEADER*)MainNvram.NvramAddress)->Signature!=FV_SIGNATURE; + if (NvramIsCorrupted){ + VarPpi->MainInfo = NULL; + NvramMode=NVRAM_MODE_RESET_CONFIGURATION; + PEI_TRACE((-1, PeiServices, "PEI: NVRAM header corruption is detected\n")); + }else{ + TmpVarPpi = *VarPpi; + TmpVarPpi.NvramInfo[0]=MainNvram; + TmpVarPpi.MainInfo = &TmpVarPpi.NvramInfo[0]; + TmpVarPpi.InfoCount=1; + + if ( IsMfgMode(PeiServices,&TmpVarPpi.Ppi) + && NvGetDefaultsInfo( + MfgDefaults,&MainNvram,&VarPpi->NvramInfo[VarPpi->InfoCount] + ) != NULL + ){ + VarPpi->InfoCount++; + NvramMode|=NVRAM_MODE_MANUFACTORING; + } + ResetConfigMode = IsResetConfigMode(PeiServices,&TmpVarPpi.Ppi); + if (!ResetConfigMode && !IsDefaultConfigMode(PeiServices,&TmpVarPpi.Ppi)){ + VarPpi->NvramInfo[VarPpi->InfoCount]=MainNvram; + VarPpi->MainInfo = &VarPpi->NvramInfo[VarPpi->InfoCount]; + VarPpi->InfoCount++; + if (NvGetDefaultsInfo( + StdDefaults,&MainNvram,&VarPpi->NvramInfo[VarPpi->InfoCount] + ) != NULL + ){ + VarPpi->InfoCount++; + } + }else{ + if (NvGetDefaultsInfo( + StdDefaults,&MainNvram,&VarPpi->NvramInfo[VarPpi->InfoCount] + ) != NULL + ){ + VarPpi->InfoCount++; + } + if (ResetConfigMode){ + VarPpi->MainInfo = NULL; + NvramMode|=NVRAM_MODE_RESET_CONFIGURATION; + }else{ + VarPpi->NvramInfo[VarPpi->InfoCount]=MainNvram; + VarPpi->MainInfo = &VarPpi->NvramInfo[VarPpi->InfoCount]; + VarPpi->InfoCount++; + NvramMode|=NVRAM_MODE_DEFAULT_CONFIGURATION; + } + } + if (!IsNvramDataCompatible(PeiServices, &VarPpi->Ppi)){ + PEI_TRACE((-1, PeiServices, "PEI: Incompatible NVRAM detected\n")); + VarPpi->MainInfo = NULL; + VarPpi->InfoCount=0; + } + } + Status=(*PeiServices)->CreateHob(PeiServices, EFI_HOB_TYPE_GUID_EXTENSION, sizeof(NVRAM_HOB),&pHob); + ASSERT_PEI_ERROR(PeiServices,Status) + if (!EFI_ERROR(Status)){ + pHob->Header.Name=AmiNvramHobGuid; + pHob->NvramAddress=(EFI_PHYSICAL_ADDRESS)(UINTN)MainNvram.NvramAddress; + pHob->BackupAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)BackupNvramAddress; + pHob->NvramSize = MainNvram.NvramSize; + if (NvSimulation) NvramMode|=NVRAM_MODE_SIMULATION; + pHob->NvramMode = NvramMode; + pHob->HeaderLength = NvramHeaderLength; + } + return (*PeiServices)->InstallPpi(PeiServices,VariablePpiList); +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2013, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//**********************************************************************
\ No newline at end of file diff --git a/Core/EM/NVRAM/NVRAMRead.c b/Core/EM/NVRAM/NVRAMRead.c new file mode 100644 index 0000000..463ed5b --- /dev/null +++ b/Core/EM/NVRAM/NVRAMRead.c @@ -0,0 +1,1508 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/Modules/NVRAM/NVRAMRead.c 32 6/11/14 3:12p Oleksiyy $ +// +// $Revision: 32 $ +// +// $Date: 6/11/14 3:12p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/Modules/NVRAM/NVRAMRead.c $ +// +// 32 6/11/14 3:12p Oleksiyy +// [TAG] EIP173026 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] With AMITSE 2.17.1245 windows 8.1 (UEFI) does not install +// [RootCause] GetNextVariableName was in certain cases returning name +// and GUID of a boot time variable +// [Solution] Variable name and GUID of a boot time variable X were +// returned at runtime under the following conditions: +// - The variable X was present in the default var.store and not +// present in the main var.store +// - The variable immediately before variable X in the default +// var.store was present in the main var.store +// The default var.store is a var.store generated at build time that +// contains default values for all setup variables +// (variables associated with setup controls). +// The main var.store is the main NVRAM area. Variable is added into a +// main var.store when somebody +// calls SetVariable. +// [Files] NVRAMRead.c +// NVRAMDXE.c +// NVRAM.cif +// +// 31 4/11/14 5:13p Oleksiyy +// [TAG] EIP162446 +// [Category] Improvement +// [Description] Chm file added. +// [Files] NVRAMRead.c +// NVRAM.cif +// +// 30 1/08/14 5:34p Oleksiyy +// [TAG] EIP125555 +// [Category] Improvement +// [Description] A Work-around provided for NvGetNextVariableName2() to +// preserve the original VariableName when returning an +// EFI_BUFFER_TOO_SMALL error from NvGetNameFromNvar(). +// [Files] NVRANRead.c +// +// 29 11/29/12 5:10p Felixp +// Minor improvement: Since UEFI Specification versions prior to 2.1 +// (0x2000A) are no longer supported, +// all the "#if EFI_SPECIFICATION_VERSION >= 0x2000A" conditional +// compilation statements are removed. +// Files modified: NVRAM.h, NVRAMRead.c, NVRAMDXE.c +// +// 28 7/13/11 9:24a Justinj +// [TAG] EIP62762 +// [Category] Improvement +// [Description] Optimize NVRAM cache index so that the entire linked +// list is not walked every time a variable is set or retrieved. +// [Files] NVRAM.h +// NVRAMRead.c +// NVRAMDXE.c +// +// 27 5/06/11 6:14p Oleksiyy +// [TAG] EIP53253 +// [Category] Improvement +// [Description] To comply with UEFI 2.3.1 +// EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS and +// EFI_VARIABLE_APPEND_WRITE attributes handling added. +// [Files] NVRAM.h, NVRAMRead.c and NVRAMDXE.c +// +// 26 9/30/10 4:36p Oleksiyy +// Issue Number: 40356 and 39462 +// +// Category: New Feature +// +// Description: Support for EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS +// Small fix of previously checked in code. +// +// Files: NVRAM. h, NVRAMRead.c, NVRAMDXE.c +// +// 25 9/22/10 6:39p Felixp +// Enhancement(EIP 39462 and EIP 40356): +// Support of the authenticated update of the NVRAM variables +// as described in UEFI specification version 2.1 and above. +// NOTE: The actual authentication is performed by the external SecureMod +// eModule, +// which must be in the proejct to use this feature. +// +// 24 8/18/10 11:08a Oleksiyy +// [TAG] EIP42324 +// [Category] BUG FIX +// [Severity] Normal +// [Symptom] NVRAM checksum at EFI Variable deletion +// [RootCause] Deleted variables also were checksummed when NVRAM +// consistency is checked. +// [Solution] Deleted variables not checksummed any more. +// [Files] NVRAMRead.c +// +// 23 12/16/09 5:55p Oleksiyy +// EIP 26085: Added support to read All the NVRAM variable. Final version. +// +// 22 12/04/09 2:27p Felixp +// NvarEqNvar moved from NvramDxe.c to NvramRead.c +// +// 21 11/25/09 4:42p Felixp +// NvGetNextVariableName2 changes are rolled back +// +// 20 11/25/09 4:38p Felixp +// NvGetNextVariableName2 updated. +// +// 19 11/24/09 4:40p Felixp +// Minor bug fixes +// +// 18 11/24/09 4:04p Oleksiyy +// EIP 26085: Added support to read All the NVRAM variable (including +// defoults) with GetNextVariable in PEI and DXE. +// +// 17 11/23/09 11:00p Felixp +// +// 16 11/23/09 4:44p Felixp +// Code to validate NVRAM header fields used by the NVRAM driver is added. +// If problem is found, the header fields are updated with the correct +// values. +// +// 15 11/20/09 4:06p Felixp +// NVRAM driver is updated to support UEFI2.1 +// EFI_VARIABLE_HARDWARE_ERROR_RECORD attribue. +// +// 14 11/19/09 4:30p Felixp +// +// 13 11/18/09 12:10p Oleksiyy +// EIP 30751: Bug fix in the NVRAM record checksum implementation +// +// 12 8/25/09 4:11p Felixp +// NVRAM Record Checksum Support(EIP 23825) is added. +// Disabled by default. Enable using NVRAM_RECORD_CHECKSUM_SUPPORT SDL +// token. +// +// 11 7/10/09 8:50a Felixp +// Code clean up; comments and function header added +// +// 10 6/26/09 3:28p Felixp +// New IsMainNvramStoreValid function is added. +// The function detects is main NVRAM or backup NVRAM is currently active +// (returns FALSE when backup is active). +// +// 9 5/14/09 9:36a Felixp +// New feature: SMM version of Runtime Services +// NVRAM driver is updated to populate SMM runtime table +// with the pointers to SMM version of variable services. +// +// 8 11/18/08 5:45p Felixp +// Bug fix in NvIsVariable and NvGetNextNvar functions. +// Symptoms: False NVRAM corruption detection on systems with +// NVRAM larger than 64KB during creation or update of the large +// variables. +// Reason: overflow during validation of record size +// +// 7 10/09/08 11:47a Felixp +// 1. Fault tolerant NVRAM garbage collection support is added. +// Use FAULT_TOLERANT_NVRAM_UPDATE SDL token to enable/disable (disabled +// by default). +// NOTE: This feature requires upgrade of the Board module. +// NOTE: This feature requires porting: +// Fault tolerant update requires reserved flash area of size NVRAM_SIZE +// used for back up during NVRAM garbage collection. +// The address of the area is defined by NVRAM_BACKUP_ADDRESS SDL token +// defined in Board.sdl. +// Size and Base addresses of other firmware volumes may need to be +// adjusted to free up space for the NVRAM back up area. +// Default ROM layout expects NVRAM back up area immediately below the +// main NVRAM area. +// For projects with the customized ROM layout Core.mak has to be updated. +// 2. Top level NVRAM function updated to be reentrance-safe. +// NOTE: This feature requires upgrade of the SB module. +// 3. Improved recovery from the flash programming failures and +// corruptions within NVRAM area. +// 4. More reliable non-fault tolerant garbage collection. +// +// 6 9/06/07 12:14a Felixp +// +// 5 8/31/07 3:44p Felixp +// NVRAM code has been significantly changed to introduce the following +// improvements: +// 1. The code is chaned to always use the same amount of memory. +// Previous implementation allocated memory as needed, which caused +// occasional S4 problems. +// Plus S4 resume never worked during the very first boot after the +// firmware update. +// 2. Support for NVRAM defaults added. +// NVRAM image with the default values for the Setup variables is now +// generated by the build process. +// The image is generated by the HpkTool (included into AMITSE module +// part). +// In addition to standard Setup defaults it is also possible +// to generate manufactoring defaults. Support for the manufactoring +// defaults +// is disabled by default and can be enabled using +// MANUFACTURING_MODE_SUPPORT SDL token. +// 3. Support for boot with alternative configurations is added. +// Decision to switch to the alternative configuration +// (alternative set of values for NVRAM variables) +// is based on values returned by the porintg routine in OemPort.c. +// During boot with alternative configurations GetVariable service +// returns alternative values for the setup-related variables. +// If variable does not have an alternative value, current value is +// returned. +// Two alternative configurations are supported: +// Boot with manufactoring settings(activated when IsMfgMode routine in +// OemPort.c returns TRUE). +// Boot with default settings(activated when IsDefaultConfigMode routine +// in OemPort.c returns TRUE). +// NOTE: This feature requires of the Board module +// 4.NVRAM reset option is added. +// If porting routine IsResetConfigMode in OemPort.c returns TRUE in PEI +// phase, +// NVRAM content will be reset during initialization of the DXE NVRAM +// driver. +// During reset operation all setup-related variables are reset to their +// default values. +// All other variables are deleted. +// NOTE: This feature requires upgrade of the Board module +// 5.Detection of NVRAM update added. +// NVRAM implementation detects if NVRAM has been updated since the last +// NVRAM call. +// This provides ability to use variables services before and after +// firmware update. +// 6.Overall code clean up and simplification. +// 7.Core Sources are no longer required in order to use NV_SIMULATION +// option. +// 8.PI 1.0 support. +// Support for a PI 1.0 complient variable PPI is added. Old PPI is still +// preserved in this label for backward compatibility. +// New library routines PeiGetVariable and PeiGetNextVariableName are +// created in order to hide the differences between two PPIs. +// It is recommended to update existing code to use new library routines. +// Support of the old PPI may be dropped in the future versions of Core. +// 9. NVRAM is now packaged as a raw FFS file embedded into the standard +// FV (used to be non-standard FV with raw NVRAM image). +// Validation: New NVRAM code has been validated using SCT and EFI version +// of Windows Server 2008 +// Files modified: Core.sdl, Core.mak, AmiPeiLib.h, PeiLib.c, +// ReadOnlyVariable.h, , Token.c, HpkTool.exe, AMITSE.mak, Setup.ini, +// NVRAM.sdl, NVRAM.mak, NVRAM.h, NVRAMRead.c, NVRAMPEI.c, +// NVRAMDXE.c +// +// 4 4/27/07 7:12p Pavell +// Bug fix in NVGetNextVariableName: GetNextVariable did not return +// EFI_NOT_FOUND after the last variable if the very first operation after +// ExitBootServices was update of the existing NV variable. +// +// 3 3/18/07 4:08p Felixp +// 1. IsNvramBlock function added +// 2. Clean up +// +// 2 10/27/06 10:42a Felixp +// Bug fixes for correct work in Virtual Address Space. +// +// 3 1/20/05 11:37a Felixp +// Component restructurized to support release in binary format +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/27/04 4:08p Felixp +// +// 11 12/09/04 9:02p Felixp +// minor improvements +// +// 10 8/28/04 1:49a Felixp +// NVRAM Routines fixes +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: NVRAMRead.c +// +// Description: NVRAM data area access API +// +//<AMI_FHDR_END> +//********************************************************************** +#include "NVRAM.h" + +#define VALID_STATE_FLAGS (\ + EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID |\ + EFI_FILE_DATA_VALID | EFI_FILE_MARKED_FOR_UPDATE) + +//Definitions for Variables that are used +//to store nested defaults images +// {4599D26F-1A11-49b8-B91F-858745CFF824} +const EFI_GUID AmiDefaultsVariableGuid = + { 0x4599d26f, 0x1a11, 0x49b8, { 0xb9, 0x1f, 0x85, 0x87, 0x45, 0xcf, 0xf8, 0x24 } }; +const CHAR16 MfgDefaults[] = L"MfgDefaults"; +const CHAR16 StdDefaults[] = L"StdDefaults"; +const EFI_GUID AmiNvramHobGuid = NVRAM_HOB_GUID; + +//Low level access routines + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetGuid +// +// Description: This function returns GUID of specified variable. +// +// Input: NVAR* pVar - pointer to Var +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: EFI_GUID* - pionter to the Var GUID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_GUID* NvGetGuid(NVAR* pVar, NVRAM_STORE_INFO *pInfo) +{ + if (pVar->flags&NVRAM_FLAG_GUID) return (EFI_GUID*)(pVar+1); + else return pInfo->NvramGuidsAddress-*(UINT8*)(pVar+1); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetName +// +// Description: This function returns pointer to the Var name. +// +// Input: NVAR* pVar - pointer to the Var +// +// Output: VOID* - pionter to the Var name +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID* NvGetName(NVAR* pVar) +{ + return (INT8*)(pVar+1)+(pVar->flags&NVRAM_FLAG_GUID ? sizeof(EFI_GUID) : 1); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetDataNvar +// +// Description: This function returns last variable in NVRAM storage. +// +// Input: NVAR* pVar - pointer to Var +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: NVAR* - pointer to the last Var +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +NVAR* NvGetDataNvar(NVAR *pVar, NVRAM_STORE_INFO *pInfo) +{ + NVAR *pLastVar=NULL; + + for ( + ; NvIsVariable(pVar,pInfo) //--Check if pVar reccord is correct + ; pVar = (NVAR*)((UINT8*)pVar + pVar->next) + ) + { + if (pVar->next==FLASH_EMPTY_NEXT) return pVar; + + pLastVar=pVar; + } + + return pLastVar; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetExtSize +// +// Description: This function returs pointer to Ext Size feild in Var +// +// Input: NVAR* NvStart - pointer to the Var to checksumm +// +// Output: +// UINT16* Pointer to Ext Size feild in Var +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VAR_SIZE_TYPE* NvGetExtSize (NVAR* pVar) +{ + return (VAR_SIZE_TYPE*) (((UINT8*) pVar + pVar->size) - sizeof(VAR_SIZE_TYPE)); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetExtFlags +// +// Description: This function returs pointer to Ext Flags feild in Var +// +// Input: NVAR* NvStart - pointer to the Var to checksumm +// +// Output: +// UINT8* Pointer to Ext Flags feild in Var +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT8* NvGetExtFlags (NVAR* pVar) +{ + return (UINT8*) ((UINT8*) NvGetExtSize (pVar) - *NvGetExtSize (pVar) + sizeof(VAR_SIZE_TYPE)); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvCalculateNvarChecksum +// +// Description: This function calculates and Checks the checksum of the Var +// +// Input: NVAR* NvStart - pointer to the Var to checksumm +// BOOLEAN Calculate - if TRUE - skeep checksumm feild in Var +// +// Output: +// UINT8 Checksum value +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT8 NvCalculateNvarChecksum(NVAR* pVar) +{ + UINT8 *p, *Start; + UINT8 Checksum = 0; + + if ( !(pVar->flags & NVRAM_FLAG_EXT_HEDER) + || !(*NvGetExtFlags(pVar) & NVRAM_EXT_FLAG_CHECKSUM) + ) return 0; + + //calculate checksum of the variable excluding the header + Start = (UINT8*)(pVar+1); + for(p=Start; p < Start+pVar->size - sizeof(NVAR); p++) + { + Checksum += *p; + } + //add variable size + Start = (UINT8*)&pVar->size; + for(p=Start; p < Start+sizeof(VAR_SIZE_TYPE); p++) + { + Checksum += *p; + } + //add flags except NVRAM_FLAG_VALID + Checksum += pVar->flags; + + return 0 - Checksum; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetData +// +// Description: This function returns last variable in NVRAM storage. +// +// Input: NVAR* pVar - pointer to Var +// UINTN NameLength - Length of the Var name +// UINTN* pDataSize - pointer to where the site of data returned will be store +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: VOID* - pointer to the Data +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID* NvGetData(NVAR* pVar, UINTN NameLength, UINTN* pDataSize, NVRAM_STORE_INFO *pInfo) +{ + UINTN DataOffset; + UINTN ExtSize; + + pVar = NvGetDataNvar(pVar,pInfo); + + if (pVar==NULL) return NULL; + + DataOffset = sizeof(NVAR); + + if (!(pVar->flags&NVRAM_FLAG_DATA_ONLY)) + { + DataOffset += NameLength + + ( pVar->flags&NVRAM_FLAG_GUID + ? sizeof(EFI_GUID) : 1 + ); + } + + if (pDataSize) + { // if Ext. Header present - get its size + if (pVar->flags & NVRAM_FLAG_EXT_HEDER) ExtSize = *NvGetExtSize (pVar); + else ExtSize = 0; + *pDataSize = pVar->size - DataOffset - ExtSize; + } + + return (INT8*)pVar+DataOffset; +} + +//Validation routines +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvIsValid +// +// Description: This function checks if passed Var is valid. +// +// Input: NVAR* pVar - pointer to the Var +// +// Output: BOOLEAN - TRUE of FALSE based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN NvIsValid(NVAR* pVar) +{ + return ((pVar->flags^~FLASH_EMPTY_FLAG)&NVRAM_FLAG_VALID) && + !(pVar->flags&NVRAM_FLAG_DATA_ONLY); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvIsVariable +// +// Description: This function checks if pVar reccord is correct. +// +// Input: NVAR* pVar - pointer to Var +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: BOOLEAN - TRUE of FALSE based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN NvIsVariable(NVAR *pVar, NVRAM_STORE_INFO *pInfo) +{ + return + pVar->signature==NVAR_SIGNATURE + && pVar->flags!=FLASH_EMPTY_FLAG + && !(pVar->flags&~ALL_FLAGS) + && pVar->size!=FLASH_EMPTY_SIZE && pVar->size>sizeof(NVAR) + && pVar->size<=(pInfo->pEndOfVars-(UINT8*)pVar) + && ( pVar->next==FLASH_EMPTY_NEXT + || pVar->next>=pVar->size + && pVar->next<=(UINT32)(pInfo->pEndOfVars-(UINT8*)pVar) + ) + && ( !(pVar->flags & NVRAM_FLAG_EXT_HEDER) + || !(*NvGetExtFlags (pVar) & NVRAM_EXT_FLAG_CHECKSUM) + || !(pVar->flags & NVRAM_FLAG_VALID) + || !NvCalculateNvarChecksum(pVar) + ) + ; +} + +//Iteration routines +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetNextNvar +// +// Description: This function returns the next valid Var after pVar. +// +// Input: NVAR* pVar - pointer to Var +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: NVAR* - pointer to next valid Var after pVar, NULL - if none +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +NVAR* NvGetNextNvar(NVAR* pVar, NVRAM_STORE_INFO *pInfo) +{ + if (!pVar || pVar >= (NVAR*)pInfo->pEndOfVars) return NULL; + + if (NvIsVariable(pVar,pInfo)) + { + pVar = (NVAR*)((UINT8*)pVar+pVar->size); + + if (pVar >= (NVAR*)pInfo->pEndOfVars) return NULL; + } + + do + { + if (pVar >= (NVAR*)pInfo->pEndOfVars) return NULL; + + //If we found a variable, we are done + if (NvIsVariable(pVar,pInfo)) return pVar; + + //Otherwise, let's check if record size seems valid + //If size is valid, skip corrupted NVAR + //Otherwise give up and return NULL + if ( pVar->size!=FLASH_EMPTY_SIZE + && pVar->size>sizeof(NVAR) + && pVar->size<=(pInfo->pEndOfVars-(UINT8*)pVar) + ) pVar = (NVAR*)((UINT8*)pVar+pVar->size); + else return NULL; + } + while (TRUE); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetNextNvar +// +// Description: This function returns the next valid Var after pVar. +// +// Input: NVAR* pVar - pointer to Var +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: NVAR* - pointer to next valid Var after pVar, NULL - if none +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +NVAR* NvGetNextValid(NVAR* pVar, NVRAM_STORE_INFO *pInfo) +{ + do + { + pVar = NvGetNextNvar(pVar,pInfo); + } + while (pVar && !NvIsValid(pVar)); + + return pVar; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetFirstValid +// +// Description: This function returns the first valid Var in NVRAM. +// +// Input: NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: NVAR* - pointer to first valid Var in NVRAM, NULL - if none +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +NVAR* NvGetFirstValid(NVRAM_STORE_INFO *pInfo) +{ + NVAR* pNvar = (NVAR*)pInfo->pFirstVar; + + //We assume that the first variable pInfo->pFirstVar is non-corrupted. + //We checked for pInfo->pFirstVar validity + //during NVRAM_STORE_INFO initialization in NvInitInfoBuffer routine. + if (!NvIsVariable(pNvar,pInfo)) return NULL; + + if (NvIsValid(pNvar)) return pNvar; + + return NvGetNextValid(pNvar,pInfo); +} + +//Comparison routines +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvAttribEq +// +// Description: This function checks if pNvar attributes ara same with Attributes passed. +// +// Input: NVAR* pNVar - pointer to Var +// UINT32 Attributes - Attributes of Var +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: NVAR* - pointer to next valid Var after pVar, NULL - if none +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN NvAttribEq(NVAR* pNvar, UINT32 Attributes, NVRAM_STORE_INFO *pInfo) +{ + //--- By ! we convert integer to boolean + return !(pNvar->flags & NVRAM_FLAG_RUNTIME) + == !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS) + && !(pInfo->Flags & NVRAM_STORE_FLAG_NON_VALATILE) + == !(Attributes & EFI_VARIABLE_NON_VOLATILE) + && !(pNvar->flags & NVRAM_FLAG_HARDWARE_ERROR_RECORD) + == !(Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) + && !(pNvar->flags & NVRAM_FLAG_AUTH_WRITE) + == !(Attributes & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES) + ; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvarEqNvar +// +// Description: This function verifies if two Var are the same +// +// Input: NVAR *Nvar1 - pointer to the first Var +// IN NVRAM_STORE_INFO *Info1 - pointer to the first NVRAM_STORE_INFO structure +// NVAR *Nvar2 - pointer to the second Var +// IN NVRAM_STORE_INFO *Info2 - pointer to the second NVRAM_STORE_INFO structure +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN NvarEqNvar( + NVAR *Nvar1, NVRAM_STORE_INFO *Info1, + NVAR *Nvar2, NVRAM_STORE_INFO *Info2 +) +{ + EFI_GUID *Guid1, *Guid2; + UINT8 *Name1, *Name2; + BOOLEAN AsciiName = Nvar1->flags&NVRAM_FLAG_ASCII_NAME; + + if (AsciiName != (Nvar2->flags&NVRAM_FLAG_ASCII_NAME)) return FALSE; + + if ( (Info1->Flags & NVRAM_STORE_FLAG_NON_VALATILE) + != (Info2->Flags & NVRAM_STORE_FLAG_NON_VALATILE) + ) return FALSE; + + Guid1=NvGetGuid(Nvar1,Info1); + Guid2=NvGetGuid(Nvar2,Info2); + + if (guidcmp(Guid1,Guid2)) return FALSE; + + Name1=(UINT8*)NvGetName(Nvar1); + Name2=(UINT8*)NvGetName(Nvar2); + + if (AsciiName) + { + while (*Name1 && *Name1==*Name2) {Name1++; Name2++;} + + if (*Name1!=*Name2) return FALSE; + } + + else + { + CHAR16 *N1 = (CHAR16*)Name1; + CHAR16 *N2 = (CHAR16*)Name2; + + while (*N1 && *N1==*N2) {N1++; N2++;} + + if (*N1!=*N2) return FALSE; + } + + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvVarEq +// +// Description: This function checks if pNvar GUID and Name ara same with passed one. +// +// Input: NVAR* pNVar - pointer to Var +// CHAR16* sName - Name of the Var to compare +// EFI_GUID* pGuid - pointer to GUID to compare with +// UINTN* pNameSize - Pointer to memory where Nane size will be returned +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: BOOLEAN - TRUE of FALSE based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN NvVarEq(NVAR* pNvar, CHAR16* sName, EFI_GUID* pGuid, UINTN* pNameSize, NVRAM_STORE_INFO *pInfo) +{ + UINT8 *pVarGuid, *pNameStart, *pN; + pVarGuid=(UINT8*)NvGetGuid(pNvar,pInfo); + pN=(UINT8*)NvGetName(pNvar); + pNameStart=pN; + //-- Check name if ASCII + if (pNvar->flags&NVRAM_FLAG_ASCII_NAME) + { + while (*pN && *pN==*sName) {pN++; sName++;} + + if (*pN!=*sName) return FALSE; + + pN++; + } + + else //-- Check name if Unicode + { + CHAR16 *sN=(CHAR16*)pN; + + while (*sN && *sN==*sName) {sN++; sName++;} + + if (*sN!=*sName) return FALSE; + + pN=(UINT8*)++sN; + } + + if (!guidcmp(pVarGuid,pGuid))//---Check GUID + { + if (pNameSize) *pNameSize=pN-pNameStart; + + return TRUE; + } + + return FALSE; +} + +//High level routines that work with a single NV store +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvFindVariable +// +// Description: This function searches for Var with specific GUID and Name. +// +// Input: CHAR16* sName - Name of the Var to search +// EFI_GUID* pGuid - pointer to GUID to search +// UINTN* pNameSize - Pointer to memory where Nane size will be returned +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: VOID* - Pointer to found Var, NULL - if not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID* NvFindVariable( + CHAR16* sName, EFI_GUID* pGuid, + UINTN* pNameSize, NVRAM_STORE_INFO *pInfo +) +{ + NVAR* pNvar = NvGetFirstValid(pInfo); + + for (; pNvar; pNvar=NvGetNextValid(pNvar,pInfo)) + { + if (NvVarEq(pNvar,sName,pGuid,pNameSize,pInfo)) return pNvar; + } + + return NULL; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvFindVariableByNvar +// +// Description: This function searches for Var equal to one passed. +// +// Input: NVAR* SourceNvar - pointer to Var, which need to be found +// NVRAM_STORE_INFO* SourceInfo - pointer to source NVRAM store structure +// NVRAM_STORE_INFO* DestInfo - pointer to NVRAM store structure where to search +// +// Output: VOID* - Pointer to found Var, NULL - if not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID* NvFindVariableByNvar(NVAR* SourceNvar, + NVRAM_STORE_INFO *SourceInfo, NVRAM_STORE_INFO *DestInfo +) +{ + NVAR* pNvar = NvGetFirstValid(DestInfo); + + for (; pNvar; pNvar=NvGetNextValid(pNvar,DestInfo)) + { + if (NvarEqNvar(SourceNvar, SourceInfo, pNvar, DestInfo)) return pNvar; + } + + return NULL; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetAttributesFromNvar +// +// Description: This function returns the attributes from a given Nvar +// +// Input: NVAR* pNVar - pointer to Var +// OPTIONAL OUT UINT32* Attributes - Pointer to memory where Attributes will be returned +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvGetAttributesFromNvar( + IN NVAR *pNvar, IN NVRAM_STORE_INFO *pInfo, + OUT UINT32 *Attributes +) +{ + if (!pNvar || !pInfo || !Attributes) return EFI_INVALID_PARAMETER; + + *Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS; + if ( pNvar->flags & NVRAM_FLAG_RUNTIME ) + *Attributes|=EFI_VARIABLE_RUNTIME_ACCESS; + if ( pInfo->Flags & NVRAM_STORE_FLAG_NON_VALATILE ) + *Attributes|=EFI_VARIABLE_NON_VOLATILE; + if ( pNvar->flags & NVRAM_FLAG_HARDWARE_ERROR_RECORD ) + *Attributes|=EFI_VARIABLE_HARDWARE_ERROR_RECORD; + if ( pNvar->flags & NVRAM_FLAG_AUTH_WRITE ) + *Attributes|= (UINT8)(*NvGetExtFlags (pNvar) & UEFI23_1_AUTHENTICATED_VARIABLE_ATTRIBUTES); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetVariableFromNvar +// +// Description: This function searches for Var with specific GUID and Name. +// +// Input: NVAR* pNVar - pointer to Var +// UINTN NameSize - size of the Var name +// OPTIONAL OUT UINT32* Attributes - Pointer to memory where Attributes will be returned +// IN OUT UINTN *DataSize - size of Var - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// OUT VOID *Data - Pointer to memory where Var will be returned +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// OUT UINT8 *Flags - Pointer to memory where Var Flags will be returned +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvGetVariableFromNvar( + NVAR *pNvar, UINTN NameSize, OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, OUT VOID *Data, + IN NVRAM_STORE_INFO *pInfo, OUT UINT8 *Flags +) +{ + UINT8* pN; + UINTN Size; + + if (!pNvar || !NvIsVariable(pNvar,pInfo)) return EFI_NOT_FOUND; + + if (Attributes) + NvGetAttributesFromNvar(pNvar, pInfo, Attributes); + + // Data + pN = (UINT8*)NvGetData(pNvar,NameSize,&Size,pInfo); + + if (*DataSize<Size) { *DataSize=Size; return EFI_BUFFER_TOO_SMALL;} + + *DataSize=Size; + MemCpy(Data,pN,Size); + + if (Flags) *Flags=pNvar->flags; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetVariable +// +// Description: This function searches for a Var after Var with specific GUID and Name. +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// OPTIONAL OUT UINT32* Attributes - Pointer to memory where Attributes will be returned +// IN OUT UINTN *DataSize - size of Var - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// OUT VOID *Data - Pointer to memory where Var will be returned +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// OUT NVAR **Var - pointer to found Var variable +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvGetVariable( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, OUT VOID *Data, + IN NVRAM_STORE_INFO *pInfo, OUT NVAR **Var +) +{ + UINTN NameSize; + NVAR* pNvar; + + if (!VariableName || !VendorGuid || !DataSize || !Data && *DataSize) + return EFI_INVALID_PARAMETER; + + pNvar = (NVAR*)NvFindVariable(VariableName,VendorGuid,&NameSize,pInfo); + if ((Var != NULL) && (pNvar != NULL)) + *Var = pNvar; + return NvGetVariableFromNvar(pNvar,NameSize,Attributes,DataSize,Data,pInfo, NULL); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetNameFromNvar +// +// Description: This function searches for a Var after Var with specific GUID and returns it's Name. +// +// Input: IN OUT UINTN *VariableNameSize - size of Varname - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// IN OUT CHAR16 *VariableName - pointer where Var Name in Unicode will be stored +// IN OUT EFI_GUID *VendorGuid - pointer to menory where Var GUID will be stored +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// BOOLEAN Runtime - search for Var with NVRAM_FLAG_RUNTIME set +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvGetNameFromNvar( + IN NVAR *pNvar, IN OUT CHAR16 *VariableName, + IN OUT UINTN *VariableNameSize, + IN OUT EFI_GUID *VendorGuid, NVRAM_STORE_INFO *pInfo +) +{ + UINTN NameSize; + UINT8 *pN, *pNameStart; + EFI_GUID* pVarGuid; + + if (!pNvar || !VariableNameSize || !VariableName || !VendorGuid) return EFI_INVALID_PARAMETER; + + + pN = pNameStart = (UINT8*)NvGetName(pNvar); + + if (pNvar->flags&NVRAM_FLAG_ASCII_NAME) + { + while (*pN++); + + NameSize = (pN - pNameStart)*2; + } + + else + { + CHAR16* sN=(CHAR16*)pN; + + while (*sN++); + + pN=(UINT8*)sN; + NameSize = pN - pNameStart; + } + + if (NameSize>*VariableNameSize) + { + *VariableNameSize=NameSize; + return EFI_BUFFER_TOO_SMALL; + } + + *VariableNameSize=NameSize; + pVarGuid=NvGetGuid(pNvar,pInfo); + + if (pNvar->flags&NVRAM_FLAG_ASCII_NAME) while (*VariableName++=*pNameStart++); + else + { + CHAR16* sN = (CHAR16*)pNameStart; + + while (*VariableName++=*sN++); + } + + MemCpy(VendorGuid,pVarGuid,sizeof(EFI_GUID)); + pInfo->pLastReturned = pNvar; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetNextVariableNvar +// +// Description: This function searches for a Var after Var with specific GUID and returns +// pointer to is using NextNvar parameter +// +// Input: +// IN CHAR16 *VariableName - pointer to a Var Name in Unicode +// IN OUT EFI_GUID *VendorGuid - pointer to Var GUID +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// BOOLEAN Runtime - search for Var with NVRAM_FLAG_RUNTIME set +// NVAR **NextNvar - pointer to the next varaible's NVAR +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvGetNextVariableNvar( + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid, + NVRAM_STORE_INFO *pInfo, BOOLEAN Runtime, NVAR **NextNvar +) +{ + NVAR* pNvar; + + if (!VariableName || !VendorGuid) return EFI_INVALID_PARAMETER; + + if (VariableName[0]==0) + { + pNvar = NvGetFirstValid(pInfo); + } + + else + { + if ( pInfo->pLastReturned!=NULL + && NvIsVariable(pInfo->pLastReturned, pInfo) + && NvVarEq(pInfo->pLastReturned,VariableName,VendorGuid,NULL, pInfo) + ) + { + pNvar=pInfo->pLastReturned; + } + + else + { + UINTN NameSize; + pNvar=(NVAR*)NvFindVariable(VariableName,VendorGuid,&NameSize,pInfo); + + if (!pNvar) return EFI_INVALID_PARAMETER; + } + if (Runtime && !(pNvar->flags & NVRAM_FLAG_RUNTIME) ) return EFI_INVALID_PARAMETER; + pNvar=NvGetNextValid(pNvar,pInfo); + } + + if (!pNvar) + { + pInfo->pLastReturned = NULL; + return EFI_NOT_FOUND; + } + + if (Runtime) + { + while (pNvar && !(pNvar->flags & NVRAM_FLAG_RUNTIME)) + pNvar=NvGetNextValid(pNvar,pInfo); + + if (!pNvar) + { + pInfo->pLastReturned = NULL; + return EFI_NOT_FOUND; + } + } + if (NextNvar) *NextNvar = pNvar; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetNextVariableName +// +// Description: This function searches for a Var after Var with specific GUID and returns it's Name. +// +// Input: IN OUT UINTN *VariableNameSize - size of Varname - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// IN OUT CHAR16 *VariableName - pointer where Var Name in Unicode will be stored +// IN OUT EFI_GUID *VendorGuid - pointer to menory where Var GUID will be stored +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// BOOLEAN Runtime - search for Var with NVRAM_FLAG_RUNTIME set +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvGetNextVariableName( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid, + NVRAM_STORE_INFO *pInfo, BOOLEAN Runtime +) +{ + NVAR* pNvar; + EFI_STATUS Status; + + Status=NvGetNextVariableNvar(VariableName,VendorGuid,pInfo,Runtime,&pNvar); + if (EFI_ERROR(Status)) return Status; + return NvGetNameFromNvar( + pNvar, VariableName, VariableNameSize, VendorGuid, pInfo + ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvInitInfoBuffer +// +// Description: This function inits NVRAM_STORE_INFO structure. +// +// Input: NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// UINTN HeaderSize - Size of the header +// UINT8 Flags - default Flags +// +// Output: VOID +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID NvInitInfoBuffer(IN NVRAM_STORE_INFO *pInfo, UINTN HeaderSize, UINT8 Flags) +{ + NVAR *pVar; + pInfo->NvramGuidsAddress = (EFI_GUID*)(pInfo->NvramAddress+pInfo->NvramSize-sizeof(EFI_GUID)); + pInfo->pFirstVar = pInfo->NvramAddress+HeaderSize; + pInfo->NextGuid = 0; + pInfo->Flags = Flags; + pInfo->LastVarSize = 0; + pInfo->pLastReturned = NULL; + + if (!(Flags & NVRAM_STORE_FLAG_NON_VALATILE)) + { + pInfo->pEndOfVars = pInfo->pFirstVar; + return; + } + + pInfo->pEndOfVars = pInfo->NvramAddress+pInfo->NvramSize; + pVar = NvGetFirstValid(pInfo); + + if ((NVAR*)pInfo->pFirstVar!=pVar) + { + if (pVar!=NULL) + { + pInfo->pFirstVar=(UINT8*)pVar; + } + + else //if pVar==NULL + { + //there are no valid variables + //set pEndOfVars equal to pFirstVar to indicate that variable store is empty + pInfo->pEndOfVars = pInfo->pFirstVar; + } + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetDefaultsInfo +// +// Description: This function returns Default Variables info. +// +// Input: IN const CHAR16* DefaultsVar - name of the defaults Vars +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// OUT NVRAM_STORE_INFO *pOutInfo - pointer to memory where defaults vill be stored +// NULL - if not found +// +// Output: NVRAM_STORE_INFO* +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +NVRAM_STORE_INFO* NvGetDefaultsInfo(IN const CHAR16* DefaultsVar, IN NVRAM_STORE_INFO *pInInfo, OUT NVRAM_STORE_INFO *pOutInfo) +{ + UINTN NameSize; + NVAR* pNvar; + pNvar = (NVAR*)NvFindVariable( + (CHAR16*)DefaultsVar, (EFI_GUID*)&AmiDefaultsVariableGuid, + &NameSize,pInInfo + ); + + if (!pNvar) return NULL; + + pOutInfo->NvramAddress = (UINT8*)NvGetData( + pNvar,NameSize, + &pOutInfo->NvramSize,pInInfo + ); + + if (pOutInfo->NvramAddress==NULL) return NULL; + + NvInitInfoBuffer( + pOutInfo, 0, + NVRAM_STORE_FLAG_NON_VALATILE + | NVRAM_STORE_FLAG_READ_ONLY + | NVRAM_STORE_FLAG_DO_NOT_ENUMERATE + ); + return pOutInfo; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetVariable2 +// +// Description: This function searches for Var with specific GUID, Name and Enty number +// not bigger than InfoCount parameter. +// +// Input: IN CHAR16 *VariableName - pointer to Var Name in Unicode +// IN EFI_GUID *VendorGuid - pointer to Var GUID +// OPTIONAL OUT UINT32* Attributes - Pointer to memory where Attributes will be returned +// IN OUT UINTN *DataSize - size of Var - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// OUT VOID *Data - Pointer to memory where Var will be returned +// UINT32 InfoCount - Max NVRAM entry number +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvGetVariable2( + IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, OUT VOID *Data, + UINT32 InfoCount, NVRAM_STORE_INFO *Info +) +{ + UINT32 i; + + for (i=0; i<InfoCount; i++) + { + EFI_STATUS Status = NvGetVariable( + VariableName,VendorGuid,Attributes,DataSize,Data,&Info[i],NULL + ); + + if (Status!=EFI_NOT_FOUND) return Status; + } + + return EFI_NOT_FOUND; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NvGetNextVariableName2 +// +// Description: This function searches for Var with specific GUID and Enty number +// not betwin LastInfoIndex - InfoCount parameter and returns it's Name. +// +// Input: IN OUT UINTN *VariableNameSize - size of Varname - if smaller than actual EFI_BUFFER_TOO_SMALL +// will be returned and DataSize will be set to actual size needed +// IN OUT CHAR16 *VariableName - pointer where Var Name in Unicode will be stored +// IN OUT EFI_GUID *VendorGuid - pointer to menory where Var GUID will be stored +// UINT32 InfoCount - Max NVRAM entry number +// NVRAM_STORE_INFO *pInfo - pointer to NVRAM store structure +// UINT32 *LastInfoIndex - NVRAM entry number to starf from +// BOOLEAN Runtime - search for Var with NVRAM_FLAG_RUNTIME set +// +// Output: EFI_STATUS - based on result +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS NvGetNextVariableName2( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid, + UINT32 InfoCount, NVRAM_STORE_INFO *pInfo, UINT32 *LastInfoIndex, + BOOLEAN Runtime +) +{ + UINT32 i; + EFI_STATUS Status; + NVAR* Nvar; + CHAR16 OrgName; + + OrgName = VariableName[0]; + // Preserve first letter of passed Var name, for the case when NvGetNameFromNvar returns EFI_BUFFER_TOO_SMALL right + // after setting first letter of name to 0 for search in the next Varstore + if (VariableName[0]==0 && LastInfoIndex) *LastInfoIndex=0; + + for ( i=(LastInfoIndex) ? *LastInfoIndex : 0 + ; i<InfoCount; i++ + ) + { + Status=NvGetNextVariableNvar(VariableName,VendorGuid,&pInfo[i],Runtime,&Nvar); + if (!EFI_ERROR(Status) && pInfo[i].Flags & NVRAM_STORE_FLAG_DO_NOT_ENUMERATE){ + while ( Nvar ){ + UINT32 j; + for (j = 0; j < i; j++) + if (NvFindVariableByNvar(Nvar, &pInfo[i], &pInfo[j] )) + break; + if (j==i) break; + Nvar=NvGetNextValid(Nvar,&pInfo[i]); + if ( Runtime ){ + while (Nvar && !(Nvar->flags & NVRAM_FLAG_RUNTIME)) + Nvar=NvGetNextValid(Nvar,&pInfo[i]); + } + } + if (!Nvar) + { + pInfo[i].pLastReturned = NULL; + Status=EFI_NOT_FOUND; + } + } + + if (!EFI_ERROR(Status)) + { + if (LastInfoIndex) *LastInfoIndex=i; + Status = NvGetNameFromNvar( + Nvar, VariableName, VariableNameSize, VendorGuid, &pInfo[i] + ); + if (EFI_ERROR(Status)) { + VariableName[0] = OrgName; //Restore first letter in case it was set to 0 before going to new Varstore + } + return Status; + } + + //When variable with VariableName/VendorGuid + //is not is the store EFI_INVALID_PARAMETER is returned + //and we have to keep searching. + //EFI_NOT_FOUND is returned when variable with VariableName/VendorGuid + //is found but it's the last variable in the store. + //In this case we have to return first variable from the next store + //In order to do that we need to reset the name + if (Status==EFI_NOT_FOUND) + { + VariableName[0]=0; + } + + else + { + //If we are here the Status should be EFI_INVALID_PARAMETER, + //which means the variable with VariableName/VendorGuid has not been found. + //If we were using LastInfoIndex, the fact that variable has not been found + //indicates that LastInfoIndex is invalid and we have to restart the search. + //The condition below checks if LastInfoIndex has been used during this iteration. + //Seting i to -1 in conjunction with i++ at the end of the iteration restarts + //the search from 0. + if (LastInfoIndex && i!=0 && i==*LastInfoIndex){ + i=(UINT32)-1; + *LastInfoIndex = 0; + } + } + } + + if (LastInfoIndex) *LastInfoIndex=0; + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetNvramFfsFileStatePtr +// +// Description: This function searches for firmvare vol header and returns pointer to its State field +// +// Input: NVRAM_STORE_INFO *Info - pointer to NVRAM store structure +// +// Output: EFI_FFS_FILE_STATE* - pointer to Ffs header State field +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_FFS_FILE_STATE* GetNvramFfsFileStatePtr(NVRAM_STORE_INFO *Info) +{ + EFI_FFS_FILE_HEADER *FfsFileHeader; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Info->NvramAddress; + + if (FwVolHeader->FvLength == Info->NvramSize) + { + FfsFileHeader = (EFI_FFS_FILE_HEADER *)( + Info->NvramAddress + FwVolHeader->HeaderLength + ); + return &FfsFileHeader->State; + } + + return NULL; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetNvramFfsFileState +// +// Description: This function searches for the header of the NVRAM image FFS file and returns the value of its State field +// +// Input: NVRAM_STORE_INFO *Info - pointer to NVRAM store structure +// +// Output: EFI_FFS_FILE_STATE - Ffs header State +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_FFS_FILE_STATE GetNvramFfsFileState(NVRAM_STORE_INFO *Info) +{ + EFI_FFS_FILE_STATE State; + EFI_FFS_FILE_STATE *StatePtr = GetNvramFfsFileStatePtr(Info); + if (StatePtr==NULL) return EFI_FILE_HEADER_INVALID; + State = (FlashEmpty==0) ? *StatePtr : ~*StatePtr; + if (State==0) State = EFI_FILE_HEADER_INVALID; + return State; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsMainNvramStoreValid +// +// Description: This function verifies if main NVRAM storage is valid +// +// Input: +// NVRAM_STORE_INFO *MainInfo - pointer to Main NVRAM storage descriptor +// VOID *BackUpAddress - address of the back up storage +// +// Output: BOOLEAN +// TRUE - the main NVRAM storage is valid +// FALSE - the main NVRAM storage is invalid. Back up srorage should be used. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsMainNvramStoreValid( + NVRAM_STORE_INFO *MainInfo, VOID *BackUpAddress, + BOOLEAN *BackupStoreValid +){ + NVRAM_STORE_INFO BackupNvram; + EFI_FFS_FILE_STATE MainState; + EFI_FFS_FILE_STATE BackupState; + + if (BackUpAddress==NULL) return TRUE; + BackupNvram.NvramAddress = BackUpAddress; + BackupNvram.NvramSize = MainInfo->NvramSize; + MainState = GetNvramFfsFileState(MainInfo); + BackupState = GetNvramFfsFileState(&BackupNvram); +// State Transitions: +// Main Backup Valid Store +// = Initial State After Firmware Flashing +// 1. DATA_VALID HEADER_INVALID Main +// = Update Cycle 1 +// 2. DATA_VALID HEADER_VALID Main +// 3. MARKED_FOR_UPDATE HEADER_VALID Main +// 4. MARKED_FOR_UPDATE DATA_VALID Backup +// = Update Cycle 1 is Over +// = Update Cycle 2 +// 5. HEADER_VALID DATA_VALID Backup +// 6. HEADER_VALID MARKED_FOR_UPDATE Backup +// 7. DATA_VALID MARKED_FOR_UPDATE Main +// = Update Cycle 2 is Over +// = Update Cycle 3 +// 8. DATA_VALID HEADER_VALID Main +// Stae 8 == State 2 + if ( (MainState & EFI_FILE_DATA_VALID)==0 + || (MainState & EFI_FILE_MARKED_FOR_UPDATE)!=0 + &&(BackupState & EFI_FILE_DATA_VALID)!=0 + ||(MainState & ~VALID_STATE_FLAGS)!=0 + ){ + if (BackupStoreValid) + *BackupStoreValid= + ((BackupState & EFI_FILE_DATA_VALID)!=0) + &&((BackupState & ~VALID_STATE_FLAGS)==0) + ; + return FALSE; + } + return TRUE; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2014, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |