summaryrefslogtreecommitdiff
path: root/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c
diff options
context:
space:
mode:
Diffstat (limited to 'EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c')
-rw-r--r--EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c
new file mode 100644
index 0000000000..d96a44304a
--- /dev/null
+++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c
@@ -0,0 +1,306 @@
+/** @file
+ Variable services implemented from system memory
+
+ There is just a single runtime memory buffer that contans all the data.
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ 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.
+
+
+**/
+
+
+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;
+
+
+ SizeOfString = StrSize (VariableName);
+ 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);
+
+ if (!EfiAtRuntime ()) {
+ // Exit Critical section
+ gBS->RestoreTPL (CurrentTpl);
+ }
+
+ return Entry;
+}
+
+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;
+ }
+
+ // 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;
+ }
+
+ 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;
+ }
+
+ if (*VariableNameSize < StringSize) {
+ *VariableNameSize = StringSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *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);
+
+ mMaximumVariableStorageSize = Size - sizeof (VARIABLE_ARRAY_ENTRY);
+ mRemainingVariableStorageSize = mMaximumVariableStorageSize;
+ mMaximumVariableSize = mMaximumVariableStorageSize;
+}
+