+ NextVariable->State = VAR_ADDED;\r
+ Status = UpdateVariableStore (\r
+ &mVariableModuleGlobal->VariableGlobal,\r
+ TRUE,\r
+ TRUE,\r
+ Fvb,\r
+ mVariableModuleGlobal->VolatileLastVariableOffset,\r
+ (UINT32) VarSize,\r
+ (UINT8 *) NextVariable\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ mVariableModuleGlobal->VolatileLastVariableOffset += HEADER_ALIGN (VarSize);\r
+ }\r
+\r
+ //\r
+ // Mark the old variable as deleted.\r
+ //\r
+ if (!Reclaimed && !EFI_ERROR (Status) && Variable->CurrPtr != NULL) {\r
+ State = Variable->CurrPtr->State;\r
+ State &= VAR_DELETED;\r
+\r
+ Status = UpdateVariableStore (\r
+ &mVariableModuleGlobal->VariableGlobal,\r
+ Variable->Volatile,\r
+ FALSE,\r
+ Fvb,\r
+ (UINTN) &Variable->CurrPtr->State,\r
+ sizeof (UINT8),\r
+ &State\r
+ );\r
+ if (!EFI_ERROR (Status) && !Variable->Volatile) { \r
+ CacheVariable->CurrPtr->State = State;\r
+ }\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);\r
+ }\r
+\r
+Done:\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ This code finds variable in storage blocks (Volatile or Non-Volatile).\r
+\r
+ @param VariableName Name of Variable to be found.\r
+ @param VendorGuid Variable vendor GUID.\r
+ @param Attributes Attribute value of the variable found.\r
+ @param DataSize Size of Data found. If size is less than the\r
+ data, this value contains the required size.\r
+ @param Data Data pointer.\r
+ \r
+ @return EFI_INVALID_PARAMETER Invalid parameter.\r
+ @return EFI_SUCCESS Find the specified variable.\r
+ @return EFI_NOT_FOUND Not found.\r
+ @return EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableServiceGetVariable (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINT32 *Attributes OPTIONAL,\r
+ IN OUT UINTN *DataSize,\r
+ OUT VOID *Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VARIABLE_POINTER_TRACK Variable;\r
+ UINTN VarDataSize;\r
+\r
+ if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+ \r
+ Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
+ if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get data size\r
+ //\r
+ VarDataSize = DataSizeOfVariable (Variable.CurrPtr);\r
+ ASSERT (VarDataSize != 0);\r
+\r
+ if (*DataSize >= VarDataSize) {\r
+ if (Data == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);\r
+ if (Attributes != NULL) {\r
+ *Attributes = Variable.CurrPtr->Attributes;\r
+ }\r
+\r
+ *DataSize = VarDataSize;\r
+ UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE);\r
+ \r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ } else {\r
+ *DataSize = VarDataSize;\r
+ Status = EFI_BUFFER_TOO_SMALL;\r
+ goto Done;\r
+ }\r
+\r
+Done:\r
+ ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+ return Status;\r
+}\r
+\r
+\r
+\r
+/**\r
+\r
+ This code Finds the Next available variable.\r
+\r
+ @param VariableNameSize Size of the variable name.\r
+ @param VariableName Pointer to variable name.\r
+ @param VendorGuid Variable Vendor Guid.\r
+\r
+ @return EFI_INVALID_PARAMETER Invalid parameter.\r
+ @return EFI_SUCCESS Find the specified variable.\r
+ @return EFI_NOT_FOUND Not found.\r
+ @return EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableServiceGetNextVariableName (\r
+ IN OUT UINTN *VariableNameSize,\r
+ IN OUT CHAR16 *VariableName,\r
+ IN OUT EFI_GUID *VendorGuid\r
+ )\r
+{\r
+ VARIABLE_STORE_TYPE Type;\r
+ VARIABLE_POINTER_TRACK Variable;\r
+ VARIABLE_POINTER_TRACK VariableInHob;\r
+ UINTN VarNameSize;\r
+ EFI_STATUS Status;\r
+ VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];\r
+\r
+ if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
+ Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
+ if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (VariableName[0] != 0) {\r
+ //\r
+ // If variable name is not NULL, get next variable.\r
+ //\r
+ Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
+ }\r
+\r
+ //\r
+ // 0: Volatile, 1: HOB, 2: Non-Volatile.\r
+ // The index and attributes mapping must be kept in this order as FindVariable\r
+ // makes use of this mapping to implement search algorithm.\r
+ //\r
+ VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;\r
+ VariableStoreHeader[VariableStoreTypeHob] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;\r
+ VariableStoreHeader[VariableStoreTypeNv] = mNvVariableCache;\r
+\r
+ while (TRUE) {\r
+ //\r
+ // Switch from Volatile to HOB, to Non-Volatile.\r
+ //\r
+ while ((Variable.CurrPtr >= Variable.EndPtr) ||\r
+ (Variable.CurrPtr == NULL) ||\r
+ !IsValidVariableHeader (Variable.CurrPtr)\r
+ ) {\r
+ //\r
+ // Find current storage index\r
+ //\r
+ for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {\r
+ if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) {\r
+ break;\r
+ }\r
+ }\r
+ ASSERT (Type < VariableStoreTypeMax);\r
+ //\r
+ // Switch to next storage\r
+ //\r
+ for (Type++; Type < VariableStoreTypeMax; Type++) {\r
+ if (VariableStoreHeader[Type] != NULL) {\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Capture the case that \r
+ // 1. current storage is the last one, or\r
+ // 2. no further storage\r
+ //\r
+ if (Type == VariableStoreTypeMax) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);\r
+ Variable.EndPtr = GetEndPointer (VariableStoreHeader[Type]);\r
+ Variable.CurrPtr = Variable.StartPtr;\r
+ }\r
+\r
+ //\r
+ // Variable is found\r
+ //\r
+ if (Variable.CurrPtr->State == VAR_ADDED) {\r
+ if ((AtRuntime () && ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) == 0) {\r
+\r
+ //\r
+ // Don't return NV variable when HOB overrides it\r
+ //\r
+ if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) && \r
+ (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))\r
+ ) {\r
+ VariableInHob.StartPtr = GetStartPointer (VariableStoreHeader[VariableStoreTypeHob]);\r
+ VariableInHob.EndPtr = GetEndPointer (VariableStoreHeader[VariableStoreTypeHob]);\r
+ Status = FindVariableEx (\r
+ GetVariableNamePtr (Variable.CurrPtr),\r
+ &Variable.CurrPtr->VendorGuid,\r
+ FALSE,\r
+ &VariableInHob\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
+ continue;\r
+ }\r
+ }\r
+\r
+ VarNameSize = NameSizeOfVariable (Variable.CurrPtr);\r
+ ASSERT (VarNameSize != 0);\r
+\r
+ if (VarNameSize <= *VariableNameSize) {\r
+ CopyMem (VariableName, GetVariableNamePtr (Variable.CurrPtr), VarNameSize);\r
+ CopyMem (VendorGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *VariableNameSize = VarNameSize;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);\r
+ }\r
+\r
+Done:\r
+ ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ This code sets variable in storage blocks (Volatile or Non-Volatile).\r
+\r
+ @param VariableName Name of Variable to be found.\r
+ @param VendorGuid Variable vendor GUID.\r
+ @param Attributes Attribute value of the variable found\r
+ @param DataSize Size of Data found. If size is less than the\r
+ data, this value contains the required size.\r
+ @param Data Data pointer.\r
+\r
+ @return EFI_INVALID_PARAMETER Invalid parameter.\r
+ @return EFI_SUCCESS Set successfully.\r
+ @return EFI_OUT_OF_RESOURCES Resource not enough to set variable.\r
+ @return EFI_NOT_FOUND Not found.\r
+ @return EFI_WRITE_PROTECTED Variable is read-only.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableServiceSetVariable (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN UINT32 Attributes,\r
+ IN UINTN DataSize,\r
+ IN VOID *Data\r
+ )\r
+{\r
+ VARIABLE_POINTER_TRACK Variable;\r
+ EFI_STATUS Status;\r
+ VARIABLE_HEADER *NextVariable;\r
+ EFI_PHYSICAL_ADDRESS Point;\r
+\r
+ //\r
+ // Check input parameters.\r
+ //\r
+ if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+\r
+ if (DataSize != 0 && Data == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Not support authenticated variable write yet.\r
+ //\r
+ if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Make sure if runtime bit is set, boot service bit is set also.\r
+ //\r
+ if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // The size of the VariableName, including the Unicode Null in bytes plus\r
+ // the DataSize is limited to maximum size of PcdGet32 (PcdMaxHardwareErrorVariableSize)\r
+ // bytes for HwErrRec, and PcdGet32 (PcdMaxVariableSize) bytes for the others.\r
+ //\r
+ if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+ if ((DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize)) ||\r
+ (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // According to UEFI spec, HARDWARE_ERROR_RECORD variable name convention should be L"HwErrRecXXXX".\r
+ //\r
+ if (StrnCmp(VariableName, L"HwErrRec", StrLen(L"HwErrRec")) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ } else {\r
+ //\r
+ // The size of the VariableName, including the Unicode Null in bytes plus\r
+ // the DataSize is limited to maximum size of PcdGet32 (PcdMaxVariableSize) bytes.\r
+ //\r
+ if ((DataSize > PcdGet32 (PcdMaxVariableSize)) ||\r
+ (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+ } \r
+\r
+ AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r