+ Load the variable data from file and set to variable data base.\r
+\r
+ @param[in] FileHandle The file to be read.\r
+ @param[in] Name The name of the variables to be loaded.\r
+ @param[in] Guid The guid of the variables to be loaded.\r
+ @param[out] Found TRUE when at least one variable was loaded and set.\r
+\r
+ @retval SHELL_DEVICE_ERROR Cannot access the file.\r
+ @retval SHELL_VOLUME_CORRUPTED The file is in bad format.\r
+ @retval SHELL_OUT_OF_RESOURCES There is not enough memory to perform the operation.\r
+ @retval SHELL_SUCCESS Successfully load and set the variables.\r
+**/\r
+SHELL_STATUS\r
+LoadVariablesFromFile (\r
+ IN SHELL_FILE_HANDLE FileHandle,\r
+ IN CONST CHAR16 *Name,\r
+ IN CONST EFI_GUID *Guid,\r
+ OUT BOOLEAN *Found\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SHELL_STATUS ShellStatus;\r
+ UINT32 NameSize;\r
+ UINT32 DataSize;\r
+ UINTN BufferSize;\r
+ UINTN RemainingSize;\r
+ UINT64 Position;\r
+ UINT64 FileSize;\r
+ LIST_ENTRY List;\r
+ DMP_STORE_VARIABLE *Variable;\r
+ LIST_ENTRY *Link;\r
+ CHAR16 *Attributes;\r
+ UINT8 *Buffer;\r
+ UINT32 Crc32;\r
+\r
+ Status = ShellGetFileSize (FileHandle, &FileSize);\r
+ if (EFI_ERROR (Status)) {\r
+ return SHELL_DEVICE_ERROR;\r
+ }\r
+ \r
+ ShellStatus = SHELL_SUCCESS;\r
+ \r
+ InitializeListHead (&List);\r
+ \r
+ Position = 0;\r
+ while (Position < FileSize) {\r
+ //\r
+ // NameSize\r
+ //\r
+ BufferSize = sizeof (NameSize);\r
+ Status = ShellReadFile (FileHandle, &BufferSize, &NameSize);\r
+ if (EFI_ERROR (Status) || (BufferSize != sizeof (NameSize))) {\r
+ ShellStatus = SHELL_VOLUME_CORRUPTED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // DataSize\r
+ //\r
+ BufferSize = sizeof (DataSize);\r
+ Status = ShellReadFile (FileHandle, &BufferSize, &DataSize);\r
+ if (EFI_ERROR (Status) || (BufferSize != sizeof (DataSize))) {\r
+ ShellStatus = SHELL_VOLUME_CORRUPTED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Name, Guid, Attributes, Data, Crc32\r
+ //\r
+ RemainingSize = NameSize + sizeof (EFI_GUID) + sizeof (UINT32) + DataSize + sizeof (Crc32);\r
+ BufferSize = sizeof (NameSize) + sizeof (DataSize) + RemainingSize;\r
+ Buffer = AllocatePool (BufferSize);\r
+ if (Buffer == NULL) {\r
+ ShellStatus = SHELL_OUT_OF_RESOURCES;\r
+ break;\r
+ }\r
+ BufferSize = RemainingSize;\r
+ Status = ShellReadFile (FileHandle, &BufferSize, (UINT32 *) Buffer + 2);\r
+ if (EFI_ERROR (Status) || (BufferSize != RemainingSize)) {\r
+ ShellStatus = SHELL_VOLUME_CORRUPTED;\r
+ FreePool (Buffer);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Check Crc32\r
+ //\r
+ * (UINT32 *) Buffer = NameSize;\r
+ * ((UINT32 *) Buffer + 1) = DataSize;\r
+ BufferSize = RemainingSize + sizeof (NameSize) + sizeof (DataSize) - sizeof (Crc32);\r
+ gBS->CalculateCrc32 (\r
+ Buffer,\r
+ BufferSize,\r
+ &Crc32\r
+ );\r
+ if (Crc32 != * (UINT32 *) (Buffer + BufferSize)) {\r
+ FreePool (Buffer);\r
+ ShellStatus = SHELL_VOLUME_CORRUPTED;\r
+ break;\r
+ }\r
+\r
+ Position += BufferSize + sizeof (Crc32);\r
+ \r
+ Variable = AllocateZeroPool (sizeof (*Variable) + NameSize + DataSize);\r
+ if (Variable == NULL) {\r
+ FreePool (Buffer);\r
+ ShellStatus = SHELL_OUT_OF_RESOURCES;\r
+ break;\r
+ }\r
+ Variable->Signature = DMP_STORE_VARIABLE_SIGNATURE;\r
+ Variable->Name = (CHAR16 *) (Variable + 1);\r
+ Variable->DataSize = DataSize;\r
+ Variable->Data = (UINT8 *) Variable->Name + NameSize;\r
+ CopyMem (Variable->Name, Buffer + sizeof (NameSize) + sizeof (DataSize), NameSize);\r
+ CopyMem (&Variable->Guid, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize, sizeof (EFI_GUID));\r
+ CopyMem (&Variable->Attributes, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize + sizeof (EFI_GUID), sizeof (UINT32));\r
+ CopyMem (Variable->Data, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize + sizeof (EFI_GUID) + sizeof (UINT32), DataSize);\r
+\r
+ InsertTailList (&List, &Variable->Link);\r
+ FreePool (Buffer);\r
+ }\r
+ \r
+ if ((Position != FileSize) || (ShellStatus != SHELL_SUCCESS)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD_BAD_FILE), gShellDebug1HiiHandle);\r
+ if (Position != FileSize) {\r
+ ShellStatus = SHELL_VOLUME_CORRUPTED;\r
+ }\r
+ }\r
+ \r
+ for ( Link = GetFirstNode (&List)\r
+ ; !IsNull (&List, Link) && (ShellStatus == SHELL_SUCCESS)\r
+ ; Link = GetNextNode (&List, Link)\r
+ ) {\r
+ Variable = CR (Link, DMP_STORE_VARIABLE, Link, DMP_STORE_VARIABLE_SIGNATURE);\r
+ \r
+ if (((Name == NULL) || gUnicodeCollation->MetaiMatch (gUnicodeCollation, Variable->Name, (CHAR16 *) Name)) &&\r
+ ((Guid == NULL) || CompareGuid (&Variable->Guid, Guid))\r
+ ) {\r
+ Attributes = GetAttrType (Variable->Attributes);\r
+ ShellPrintHiiEx (\r
+ -1, -1, NULL, STRING_TOKEN(STR_DMPSTORE_HEADER_LINE), gShellDebug1HiiHandle,\r
+ Attributes, &Variable->Guid, Variable->Name, Variable->DataSize\r
+ );\r
+ SHELL_FREE_NON_NULL(Attributes);\r
+\r
+ *Found = TRUE;\r
+ Status = gRT->SetVariable (\r
+ Variable->Name,\r
+ &Variable->Guid,\r
+ Variable->Attributes,\r
+ Variable->DataSize,\r
+ Variable->Data\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD_GEN_FAIL), gShellDebug1HiiHandle, Variable->Name, Status);\r
+ }\r
+ }\r
+ }\r
+\r
+ for (Link = GetFirstNode (&List); !IsNull (&List, Link); ) {\r
+ Variable = CR (Link, DMP_STORE_VARIABLE, Link, DMP_STORE_VARIABLE_SIGNATURE);\r
+ Link = RemoveEntryList (&Variable->Link);\r
+ FreePool (Variable);\r
+ }\r
+\r
+ return ShellStatus;\r
+}\r
+\r
+/**\r
+ Append one variable to file.\r
+\r
+ @param[in] FileHandle The file to be appended.\r
+ @param[in] Name The variable name.\r
+ @param[in] Guid The variable GUID.\r
+ @param[in] Attributes The variable attributes.\r
+ @param[in] DataSize The variable data size.\r
+ @param[in] Data The variable data.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory to perform the operation.\r
+ @retval EFI_SUCCESS The variable is appended to file successfully.\r
+ @retval others Failed to append the variable to file.\r
+**/\r
+EFI_STATUS\r
+AppendSingleVariableToFile (\r
+ IN SHELL_FILE_HANDLE FileHandle,\r
+ IN CONST CHAR16 *Name,\r
+ IN CONST EFI_GUID *Guid,\r
+ IN UINT32 Attributes,\r
+ IN UINT32 DataSize,\r
+ IN CONST UINT8 *Data\r
+ )\r
+{\r
+ UINT32 NameSize;\r
+ UINT8 *Buffer;\r
+ UINT8 *Ptr;\r
+ UINTN BufferSize;\r
+ EFI_STATUS Status;\r
+\r
+ NameSize = (UINT32) StrSize (Name);\r
+ BufferSize = sizeof (NameSize) + sizeof (DataSize)\r
+ + sizeof (*Guid)\r
+ + sizeof (Attributes)\r
+ + NameSize + DataSize\r
+ + sizeof (UINT32);\r
+\r
+ Buffer = AllocatePool (BufferSize);\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r