variable.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,542 行 · 第 1/3 页
C
1,542 行
/*++
Copyright (c) 2004 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Variable.c
Abstract:
Provide support functions for variable services.
--*/
#include "Variable.h"
#include "reclaim.h"
#include EFI_GUID_DEFINITION (FlashMapHob)
//
// Don't use module globals after the SetVirtualAddress map is signaled
//
ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal;
UINT32
EFIAPI
ArrayLength (
IN CHAR16 *String
)
/*++
Routine Description:
Determine the length of null terminated char16 array.
Arguments:
String Null-terminated CHAR16 array pointer.
Returns:
UINT32 Number of bytes in the string, including the double NULL at the end;
--*/
{
UINT32 Count;
if (NULL == String) {
return 0;
}
Count = 0;
while (0 != String[Count]) {
Count++;
}
return (Count * 2) + 2;
}
BOOLEAN
EFIAPI
IsValidVariableHeader (
IN VARIABLE_HEADER *Variable
)
/*++
Routine Description:
This code checks if variable header is valid or not.
Arguments:
Variable Pointer to the Variable Header.
Returns:
TRUE Variable header is valid.
FALSE Variable header is not valid.
--*/
{
if (Variable == NULL ||
Variable->StartId != VARIABLE_DATA ||
(sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize) > MAX_VARIABLE_SIZE
) {
return FALSE;
}
return TRUE;
}
EFI_STATUS
UpdateVariableStore (
IN VARIABLE_GLOBAL *Global,
IN BOOLEAN Volatile,
IN BOOLEAN SetByIndex,
IN UINTN Instance,
IN UINTN DataPtrIndex,
IN UINT32 DataSize,
IN UINT8 *Buffer
)
/*++
Routine Description:
This function writes data to the FWH at the correct LBA even if the LBAs
are fragmented.
Arguments:
Global - Pointer to VARAIBLE_GLOBAL structure
Volatile - If the Variable is Volatile or Non-Volatile
SetByIndex - TRUE: Target pointer is given as index
FALSE: Target pointer is absolute
Instance - Instance of FV Block services
DataPtrIndex - Pointer to the Data from the end of VARIABLE_STORE_HEADER
structure
DataSize - Size of data to be written.
Buffer - Pointer to the buffer from which data is written
Returns:
EFI_INVALID_PARAMETER - Parameters not valid
EFI_SUCCESS - Variable store successfully updated
--*/
{
EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
UINTN BlockIndex2;
UINTN LinearOffset;
UINTN CurrWriteSize;
UINTN CurrWritePtr;
UINT8 *CurrBuffer;
EFI_LBA LbaNumber;
UINTN Size;
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
VARIABLE_STORE_HEADER *VolatileBase;
EFI_PHYSICAL_ADDRESS FvVolHdr;
EFI_PHYSICAL_ADDRESS DataPtr;
EFI_STATUS Status;
FwVolHeader = NULL;
DataPtr = DataPtrIndex;
//
// Check if the Data is Volatile
//
if (!Volatile) {
EfiFvbGetPhysicalAddress (Instance, &FvVolHdr);
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr);
//
// Data Pointer should point to the actual Address where data is to be
// written
//
if (SetByIndex) {
DataPtr += Global->NonVolatileVariableBase;
}
if ((DataPtr + DataSize) >= ((EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) FwVolHeader + FwVolHeader->FvLength))) {
return EFI_INVALID_PARAMETER;
}
} else {
//
// Data Pointer should point to the actual Address where data is to be
// written
//
VolatileBase = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase);
if (SetByIndex) {
DataPtr += Global->VolatileVariableBase;
}
if ((DataPtr + DataSize) >= ((UINTN) ((UINT8 *) VolatileBase + VolatileBase->Size))) {
return EFI_INVALID_PARAMETER;
}
//
// If Volatile Variable just do a simple mem copy.
//
EfiCopyMem ((UINT8 *) ((UINTN) DataPtr), Buffer, DataSize);
return EFI_SUCCESS;
}
//
// If we are here we are dealing with Non-Volatile Variables
//
LinearOffset = (UINTN) FwVolHeader;
CurrWritePtr = (UINTN) DataPtr;
CurrWriteSize = DataSize;
CurrBuffer = Buffer;
LbaNumber = 0;
if (CurrWritePtr < LinearOffset) {
return EFI_INVALID_PARAMETER;
}
for (PtrBlockMapEntry = FwVolHeader->FvBlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {
//
// Check to see if the Variable Writes are spanning through multiple
// blocks.
//
if ((CurrWritePtr >= LinearOffset) && (CurrWritePtr < LinearOffset + PtrBlockMapEntry->BlockLength)) {
if ((CurrWritePtr + CurrWriteSize) <= (LinearOffset + PtrBlockMapEntry->BlockLength)) {
Status = EfiFvbWriteBlock (
Instance,
LbaNumber,
(UINTN) (CurrWritePtr - LinearOffset),
&CurrWriteSize,
CurrBuffer
);
return Status;
} else {
Size = (UINT32) (LinearOffset + PtrBlockMapEntry->BlockLength - CurrWritePtr);
Status = EfiFvbWriteBlock (
Instance,
LbaNumber,
(UINTN) (CurrWritePtr - LinearOffset),
&Size,
CurrBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
CurrWritePtr = LinearOffset + PtrBlockMapEntry->BlockLength;
CurrBuffer = CurrBuffer + Size;
CurrWriteSize = CurrWriteSize - Size;
}
}
LinearOffset += PtrBlockMapEntry->BlockLength;
LbaNumber++;
}
}
return EFI_SUCCESS;
}
VARIABLE_STORE_STATUS
EFIAPI
GetVariableStoreStatus (
IN VARIABLE_STORE_HEADER *VarStoreHeader
)
/*++
Routine Description:
This code gets the current status of Variable Store.
Arguments:
VarStoreHeader Pointer to the Variable Store Header.
Returns:
EfiRaw Variable store status is raw
EfiValid Variable store status is valid
EfiInvalid Variable store status is invalid
--*/
{
if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE &&
VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
VarStoreHeader->State == VARIABLE_STORE_HEALTHY
) {
return EfiValid;
} else if (VarStoreHeader->Signature == 0xffffffff &&
VarStoreHeader->Size == 0xffffffff &&
VarStoreHeader->Format == 0xff &&
VarStoreHeader->State == 0xff
) {
return EfiRaw;
} else {
return EfiInvalid;
}
}
UINT8 *
EFIAPI
GetVariableDataPtr (
IN VARIABLE_HEADER *Variable
)
/*++
Routine Description:
This code gets the pointer to the variable data.
Arguments:
Variable Pointer to the Variable Header.
Returns:
UINT8* Pointer to Variable Data
--*/
{
//
// Be careful about pad size for alignment
//
return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));
}
VARIABLE_HEADER *
EFIAPI
GetNextVariablePtr (
IN VARIABLE_HEADER *Variable
)
/*++
Routine Description:
This code gets the pointer to the next variable header.
Arguments:
Variable Pointer to the Variable Header.
Returns:
VARIABLE_HEADER* Pointer to next variable header.
--*/
{
if (!IsValidVariableHeader (Variable)) {
return NULL;
}
//
// Be careful about pad size for alignment
//
return (VARIABLE_HEADER *) ((UINTN) GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));
}
VARIABLE_HEADER *
EFIAPI
GetEndPointer (
IN VARIABLE_STORE_HEADER *VarStoreHeader
)
/*++
Routine Description:
This code gets the pointer to the last variable memory pointer byte
Arguments:
VarStoreHeader Pointer to the Variable Store Header.
Returns:
VARIABLE_HEADER* Pointer to last unavailable Variable Header
--*/
{
//
// The end of variable store
//
return (VARIABLE_HEADER *) ((UINTN) VarStoreHeader + VarStoreHeader->Size);
}
EFI_STATUS
EFIAPI
Reclaim (
IN EFI_PHYSICAL_ADDRESS VariableBase,
OUT UINTN *LastVariableOffset,
IN BOOLEAN IsVolatile,
IN VARIABLE_HEADER *CurrentVariable OPTIONAL
)
/*++
Routine Description:
Variable store garbage collection and reclaim operation
Arguments:
VariableBase Base address of variable store
LastVariableOffset Offset of last variable
IsVolatile The variable store is volatile or not,
if it is non-volatile, need FTW
CurrentVairable If it is not NULL, it means not to process
current variable for Reclaim.
Returns:
EFI STATUS
--*/
{
VARIABLE_HEADER *Variable;
VARIABLE_HEADER *NextVariable;
VARIABLE_STORE_HEADER *VariableStoreHeader;
UINT8 *ValidBuffer;
UINTN ValidBufferSize;
UINTN VariableSize;
UINT8 *CurrPtr;
EFI_STATUS Status;
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
//
// Start Pointers for the variable.
//
Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);
ValidBufferSize = sizeof (VARIABLE_STORE_HEADER);
while (IsValidVariableHeader (Variable)) {
NextVariable = GetNextVariablePtr (Variable);
if ((Variable->State == VAR_ADDED) ||
((Variable != CurrentVariable) &&
(Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)))) {
VariableSize = (UINTN) NextVariable - (UINTN) Variable;
ValidBufferSize += VariableSize;
}
Variable = NextVariable;
}
Status = gBS->AllocatePool (
EfiBootServicesData,
ValidBufferSize,
&ValidBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
EfiSetMem (ValidBuffer, ValidBufferSize, 0xff);
CurrPtr = ValidBuffer;
//
// Copy variable store header
//
EfiCopyMem (CurrPtr, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));
CurrPtr += sizeof (VARIABLE_STORE_HEADER);
//
// Start Pointers for the variable.
//
Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);
while (IsValidVariableHeader (Variable)) {
NextVariable = GetNextVariablePtr (Variable);
if ((Variable->State == VAR_ADDED) ||
((Variable != CurrentVariable) &&
(Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)))) {
VariableSize = (UINTN) NextVariable - (UINTN) Variable;
EfiCopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);
//
// Mark all variable as VAR_ADDED
//
((VARIABLE_HEADER *)CurrPtr)->State = VAR_ADDED;
CurrPtr += VariableSize;
}
Variable = NextVariable;
}
if (IsVolatile) {
//
// If volatile variable store, just copy valid buffer
//
EfiSetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff);
EfiCopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, ValidBufferSize);
*LastVariableOffset = ValidBufferSize;
Status = EFI_SUCCESS;
} else {
//
// If non-volatile variable store, perform FTW here.
//
Status = FtwVariableSpace (
VariableBase,
ValidBuffer,
ValidBufferSize
);
if (!EFI_ERROR (Status)) {
*LastVariableOffset = ValidBufferSize;
}
}
gBS->FreePool (ValidBuffer);
if (EFI_ERROR (Status)) {
*LastVariableOffset = 0;
}
return Status;
}
EFI_STATUS
EFIAPI
FindVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT VARIABLE_POINTER_TRACK *PtrTrack,
IN VARIABLE_GLOBAL *Global
)
/*++
Routine Description:
This code finds variable in storage blocks (Volatile or Non-Volatile)
Arguments:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?