Files

307 lines
8.6 KiB
C
Raw Permalink Normal View History

2009-12-06 01:57:05 +00:00
/** @file
Variable services implemented from system memory
2014-08-19 13:29:52 +00:00
There is just a single runtime memory buffer that contans all the data.
2009-12-06 01:57:05 +00:00
2010-04-29 12:40:51 +00:00
Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
2014-08-19 13:29:52 +00:00
2010-04-29 12:40:51 +00:00
This program and the accompanying materials
2009-12-06 01:57:05 +00:00
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.
**/
UINT64 mMaximumVariableStorageSize;
UINT64 mRemainingVariableStorageSize;
UINT64 mMaximumVariableSize;
typedef struct {
EFI_GUID VendorGuid;
UINT32 Attribute;
UINTN DataSize;
} VARIABLE_ARRAY_ENTRY;
// CHAR16 VariableName[]
// UINT8 Data[]
VARIABLE_ARRAY_ENTRY *mVariableArray = NULL;
VARIABLE_ARRAY_ENTRY *mVariableArrayNextFree = NULL;
VARIABLE_ARRAY_ENTRY *mVariableArrayEnd = NULL;
VARIABLE_ARRAY_ENTRY *
AddEntry (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
UINTN Size;
UINTN SizeOfString;
VARIABLE_ARRAY_ENTRY *Entry;
EFI_TPL CurrentTpl;
2014-08-19 13:29:52 +00:00
SizeOfString = StrSize (VariableName);
2009-12-06 01:57:05 +00:00
Size = SizeOfString + sizeof (VARIABLE_ARRAY_ENTRY) + DataSize;
if ((VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) + Size) > mVariableArrayEnd) {
// ran out of space
return NULL;
}
if (!EfiAtRuntime ()) {
// Enter critical section
CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
}
Entry = mVariableArrayNextFree;
CopyGuid (&Entry->VendorGuid, VendorGuid);
Entry->Attribute = Attributes;
Entry->DataSize = DataSize;
StrCpy ((CHAR16 *)++mVariableArrayNextFree, VariableName);
mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) + SizeOfString);
CopyMem (mVariableArrayNextFree, Data, DataSize);
mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) + DataSize);
2014-08-19 13:29:52 +00:00
2009-12-06 01:57:05 +00:00
if (!EfiAtRuntime ()) {
// Exit Critical section
gBS->RestoreTPL (CurrentTpl);
}
return Entry;
}
2014-08-19 13:29:52 +00:00
2009-12-06 01:57:05 +00:00
VOID
DeleteEntry (
IN VARIABLE_ARRAY_ENTRY *Entry
)
{
UINTN Size;
UINT8 *Data;
EFI_TPL CurrentTpl;
Size = StrSize ((CHAR16 *)(Entry + 1)) + sizeof (VARIABLE_ARRAY_ENTRY) + Entry->DataSize;
Data = ((UINT8 *)Entry) + Size;
CopyMem (Entry, Data, (UINTN)mVariableArrayNextFree - (UINTN)Data);
if (!EfiAtRuntime ()) {
// Enter critical section
CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
}
mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) - Size);
if (!EfiAtRuntime ()) {
// Exit Critical section
gBS->RestoreTPL (CurrentTpl);
}
}
VARIABLE_ARRAY_ENTRY *
GetVariableArrayEntry (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT VOID **Data OPTIONAL
)
{
VARIABLE_ARRAY_ENTRY *Entry;
UINTN Size;
if (*VariableName == L'\0') {
// by definition first entry is null-terminated string
if (mVariableArray == mVariableArrayNextFree) {
return NULL;
}
return mVariableArray;
}
for (Entry = mVariableArray; Entry < mVariableArrayEnd;) {
if (CompareGuid (VendorGuid, &Entry->VendorGuid)) {
if (StrCmp (VariableName, (CHAR16 *)(Entry + 1))) {
Size = StrSize ((CHAR16 *)(Entry + 1));
if (Data != NULL) {
*Data = (VOID *)(((UINT8 *)Entry) + (Size + sizeof (VARIABLE_ARRAY_ENTRY)));
}
return Entry;
}
}
Size = StrSize ((CHAR16 *)(Entry + 1)) + sizeof (VARIABLE_ARRAY_ENTRY) + Entry->DataSize;
Entry = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)Entry) + Size);
}
return NULL;
}
EFI_STATUS
LibGetVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT UINT32 *Attributes OPTIONAL,
IN OUT UINTN *DataSize,
OUT VOID *Data
)
{
VARIABLE_ARRAY_ENTRY *Entry;
VOID *InternalData;
if (EfiAtRuntime () && (Attributes != NULL)) {
if ((*Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) {
return EFI_NOT_FOUND;
}
}
Entry = GetVariableArrayEntry (VariableName, VendorGuid, &InternalData);
if (Entry == NULL) {
return EFI_NOT_FOUND;
}
if (*DataSize < Entry->DataSize) {
*DataSize = Entry->DataSize;
return EFI_BUFFER_TOO_SMALL;
}
*DataSize = Entry->DataSize;
if (Attributes != NULL) {
*Attributes = Entry->Attribute;
}
CopyMem (Data, InternalData, *DataSize);
return EFI_SUCCESS;
}
EFI_STATUS
LibGetNextVariableName (
IN OUT UINTN *VariableNameSize,
IN OUT CHAR16 *VariableName,
IN OUT EFI_GUID *VendorGuid
)
{
VARIABLE_ARRAY_ENTRY *Entry;
VOID *InternalData;
UINTN StringSize;
BOOLEAN Done;
for (Done = FALSE; !Done; ) {
Entry = GetVariableArrayEntry (VariableName, VendorGuid, &InternalData);
if (Entry == NULL) {
return EFI_NOT_FOUND;
}
2014-08-19 13:29:52 +00:00
2009-12-06 01:57:05 +00:00
// If we are at runtime skip variables that do not have the Runitme attribute set.
Done = (EfiAtRuntime () && ((Entry->Attribute & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) ? FALSE : TRUE;
2014-08-19 13:29:52 +00:00
}
2009-12-06 01:57:05 +00:00
StringSize = StrSize ((CHAR16 *)(Entry + 1));
Entry = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)Entry) + (StringSize + sizeof (VARIABLE_ARRAY_ENTRY) + Entry->DataSize));
if (Entry >= mVariableArrayEnd) {
return EFI_NOT_FOUND;
}
2014-08-19 13:29:52 +00:00
2009-12-06 01:57:05 +00:00
if (*VariableNameSize < StringSize) {
*VariableNameSize = StringSize;
return EFI_BUFFER_TOO_SMALL;
}
2014-08-19 13:29:52 +00:00
2009-12-06 01:57:05 +00:00
*VariableNameSize = StringSize;
CopyMem (VariableName, (CHAR16 *)(Entry + 1), StringSize);
CopyMem (VendorGuid, &Entry->VendorGuid, sizeof (EFI_GUID));
return EFI_SUCCESS;
}
EFI_STATUS
LibSetVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
VARIABLE_ARRAY_ENTRY *Entry;
VOID *InternalData;
if (EfiAtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
return EFI_NOT_FOUND;
}
Entry = GetVariableArrayEntry (VariableName, VendorGuid, &InternalData);
if (Entry == NULL) {
if (DataSize == 0) {
return EFI_NOT_FOUND;
}
Entry = AddEntry (VariableName, VendorGuid, Attributes, DataSize, Data);
return (Entry == NULL) ? EFI_OUT_OF_RESOURCES : EFI_SUCCESS;
} else if (DataSize == 0) {
// DataSize is zero so delete
DeleteEntry (Entry);
} else if (DataSize == Entry->DataSize) {
// No change is size so just update the store
Entry->Attribute |= Attributes;
CopyMem (InternalData, Data, DataSize);
} else {
// Grow the entry by deleting and adding back. Don't lose previous Attributes
Attributes |= Entry->Attribute;
DeleteEntry (Entry);
Entry = AddEntry (VariableName, VendorGuid, Attributes, DataSize, Data);
return (Entry == NULL) ? EFI_OUT_OF_RESOURCES : EFI_SUCCESS;
}
}
EFI_STATUS
LibQueryVariableInfo (
IN UINT32 Attributes,
OUT UINT64 *MaximumVariableStorageSize,
OUT UINT64 *RemainingVariableStorageSize,
OUT UINT64 *MaximumVariableSize
)
{
*MaximumVariableStorageSize = mMaximumVariableStorageSize;
*RemainingVariableStorageSize = mRemainingVariableStorageSize;
*MaximumVariableStorageSize = mRemainingVariableStorageSize;
return EFI_SUCCESS;
}
VOID
LibVariableVirtualAddressChangeEvent (VOID)
{
EfiConvertPointer (0, (VOID **)&mVariableArray);
EfiConvertPointer (0, (VOID **)&mVariableArrayNextFree);
EfiConvertPointer (0, (VOID **)&mVariableArrayEnd);
}
VOID
LibVariableInitialize (VOID)
{
UINTN Size;
Size = PcdGet32 (PcdEmbeddedMemVariableStoreSize);
mVariableArray = mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)AllocateRuntimePool (Size);
ASSERT (mVariableArray != NULL);
mVariableArrayEnd = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArray) + Size);
2014-08-19 13:29:52 +00:00
2009-12-06 01:57:05 +00:00
mMaximumVariableStorageSize = Size - sizeof (VARIABLE_ARRAY_ENTRY);
mRemainingVariableStorageSize = mMaximumVariableStorageSize;
mMaximumVariableSize = mMaximumVariableStorageSize;
}
2014-08-19 13:29:52 +00:00