]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c
ShellPkg/Dp: Add null pointer check
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / DmpStore.c
CommitLineData
5d73d92f 1/** @file\r
2 Main file for DmpStore shell Debug1 function.\r
148af387 3 \r
c011b6c9 4 (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>\r
7f6511ee 5 Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.<BR>\r
5d73d92f 6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "UefiShellDebug1CommandsLib.h"\r
17\r
7e63fc9d
RN
18typedef enum {\r
19 DmpStoreDisplay,\r
20 DmpStoreDelete,\r
21 DmpStoreSave,\r
22 DmpStoreLoad\r
23} DMP_STORE_TYPE;\r
24\r
25typedef struct {\r
26 UINT32 Signature;\r
27 CHAR16 *Name;\r
28 EFI_GUID Guid;\r
29 UINT32 Attributes;\r
30 UINT32 DataSize;\r
31 UINT8 *Data;\r
32 LIST_ENTRY Link;\r
33} DMP_STORE_VARIABLE;\r
34\r
35#define DMP_STORE_VARIABLE_SIGNATURE SIGNATURE_32 ('_', 'd', 's', 's')\r
36\r
cd0842dc
ED
37/**\r
38 Base on the input attribute value to return the attribute string.\r
39\r
40 @param[in] Atts The input attribute value\r
cd0842dc
ED
41\r
42 @retval The attribute string info.\r
43**/\r
d6972185 44CHAR16 *\r
73c82041 45GetAttrType (\r
d6972185 46 IN CONST UINT32 Atts\r
73c82041
ED
47 )\r
48{\r
99bb0f8d 49 UINTN BufLen;\r
d6972185 50 CHAR16 *RetString;\r
73c82041 51\r
d6972185
ED
52 BufLen = 0;\r
53 RetString = NULL;\r
54 \r
cd0842dc 55 if ((Atts & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
d6972185 56 StrnCatGrow (&RetString, &BufLen, L"+NV", 0);\r
73c82041 57 }\r
cd0842dc 58 if ((Atts & EFI_VARIABLE_RUNTIME_ACCESS) != 0) {\r
14868afb 59 StrnCatGrow (&RetString, &BufLen, L"+RT+BS", 0);\r
cd0842dc 60 } else if ((Atts & EFI_VARIABLE_BOOTSERVICE_ACCESS) != 0) {\r
d6972185 61 StrnCatGrow (&RetString, &BufLen, L"+BS", 0);\r
73c82041 62 }\r
cd0842dc 63 if ((Atts & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {\r
d6972185 64 StrnCatGrow (&RetString, &BufLen, L"+HR", 0);\r
73c82041 65 }\r
cd0842dc 66 if ((Atts & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
d6972185 67 StrnCatGrow (&RetString, &BufLen, L"+AW", 0);\r
73c82041 68 }\r
cd0842dc 69 if ((Atts & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
d6972185 70 StrnCatGrow (&RetString, &BufLen, L"+AT", 0);\r
73c82041
ED
71 }\r
72\r
d6972185
ED
73 if (RetString == NULL) {\r
74 RetString = StrnCatGrow(&RetString, &BufLen, L"Invalid", 0);\r
73c82041 75 }\r
d6972185 76\r
44890dbd 77 if ((RetString != NULL) && (RetString[0] == L'+')) {\r
d6972185 78 CopyMem(RetString, RetString + 1, StrSize(RetString + 1));\r
73c82041 79 }\r
d6972185
ED
80\r
81 return RetString;\r
73c82041 82}\r
5d73d92f 83\r
e9597b45
RN
84/**\r
85 Convert binary to hex format string.\r
86\r
e9597b45 87 @param[in] Buffer The binary data.\r
ff28c72b 88 @param[in] BufferSize The size in bytes of the binary data.\r
e9597b45
RN
89 @param[in, out] HexString Hex format string.\r
90 @param[in] HexStringSize The size in bytes of the string.\r
91\r
92 @return The hex format string.\r
93**/\r
94CHAR16*\r
95BinaryToHexString (\r
96 IN VOID *Buffer,\r
97 IN UINTN BufferSize,\r
98 IN OUT CHAR16 *HexString,\r
99 IN UINTN HexStringSize\r
100 )\r
101{\r
102 UINTN Index;\r
103 UINTN StringIndex;\r
104\r
105 ASSERT (Buffer != NULL);\r
106 ASSERT ((BufferSize * 2 + 1) * sizeof (CHAR16) <= HexStringSize);\r
107\r
108 for (Index = 0, StringIndex = 0; Index < BufferSize; Index += 1) {\r
109 StringIndex +=\r
110 UnicodeSPrint (\r
111 &HexString[StringIndex],\r
112 HexStringSize - StringIndex * sizeof (CHAR16),\r
113 L"%02x",\r
114 ((UINT8 *) Buffer)[Index]\r
115 );\r
116 }\r
117 return HexString;\r
118}\r
119\r
7e63fc9d
RN
120/**\r
121 Load the variable data from file and set to variable data base.\r
122\r
123 @param[in] FileHandle The file to be read.\r
124 @param[in] Name The name of the variables to be loaded.\r
125 @param[in] Guid The guid of the variables to be loaded.\r
126 @param[out] Found TRUE when at least one variable was loaded and set.\r
127\r
5511b319
SQ
128 @retval SHELL_DEVICE_ERROR Cannot access the file.\r
129 @retval SHELL_VOLUME_CORRUPTED The file is in bad format.\r
130 @retval SHELL_OUT_OF_RESOURCES There is not enough memory to perform the operation.\r
131 @retval SHELL_SUCCESS Successfully load and set the variables.\r
7e63fc9d 132**/\r
5511b319 133SHELL_STATUS\r
7e63fc9d
RN
134LoadVariablesFromFile (\r
135 IN SHELL_FILE_HANDLE FileHandle,\r
136 IN CONST CHAR16 *Name,\r
137 IN CONST EFI_GUID *Guid,\r
138 OUT BOOLEAN *Found\r
139 )\r
140{\r
141 EFI_STATUS Status;\r
5511b319 142 SHELL_STATUS ShellStatus;\r
7e63fc9d
RN
143 UINT32 NameSize;\r
144 UINT32 DataSize;\r
145 UINTN BufferSize;\r
146 UINTN RemainingSize;\r
147 UINT64 Position;\r
148 UINT64 FileSize;\r
149 LIST_ENTRY List;\r
150 DMP_STORE_VARIABLE *Variable;\r
151 LIST_ENTRY *Link;\r
152 CHAR16 *Attributes;\r
153 UINT8 *Buffer;\r
154 UINT32 Crc32;\r
155\r
156 Status = ShellGetFileSize (FileHandle, &FileSize);\r
157 if (EFI_ERROR (Status)) {\r
5511b319 158 return SHELL_DEVICE_ERROR;\r
7e63fc9d 159 }\r
5511b319
SQ
160 \r
161 ShellStatus = SHELL_SUCCESS;\r
162 \r
7e63fc9d
RN
163 InitializeListHead (&List);\r
164 \r
165 Position = 0;\r
166 while (Position < FileSize) {\r
167 //\r
168 // NameSize\r
169 //\r
170 BufferSize = sizeof (NameSize);\r
171 Status = ShellReadFile (FileHandle, &BufferSize, &NameSize);\r
172 if (EFI_ERROR (Status) || (BufferSize != sizeof (NameSize))) {\r
5511b319 173 ShellStatus = SHELL_VOLUME_CORRUPTED;\r
7e63fc9d
RN
174 break;\r
175 }\r
176\r
177 //\r
178 // DataSize\r
179 //\r
180 BufferSize = sizeof (DataSize);\r
181 Status = ShellReadFile (FileHandle, &BufferSize, &DataSize);\r
182 if (EFI_ERROR (Status) || (BufferSize != sizeof (DataSize))) {\r
5511b319 183 ShellStatus = SHELL_VOLUME_CORRUPTED;\r
7e63fc9d
RN
184 break;\r
185 }\r
186\r
187 //\r
188 // Name, Guid, Attributes, Data, Crc32\r
189 //\r
190 RemainingSize = NameSize + sizeof (EFI_GUID) + sizeof (UINT32) + DataSize + sizeof (Crc32);\r
191 BufferSize = sizeof (NameSize) + sizeof (DataSize) + RemainingSize;\r
192 Buffer = AllocatePool (BufferSize);\r
193 if (Buffer == NULL) {\r
5511b319 194 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
7e63fc9d
RN
195 break;\r
196 }\r
197 BufferSize = RemainingSize;\r
198 Status = ShellReadFile (FileHandle, &BufferSize, (UINT32 *) Buffer + 2);\r
199 if (EFI_ERROR (Status) || (BufferSize != RemainingSize)) {\r
5511b319 200 ShellStatus = SHELL_VOLUME_CORRUPTED;\r
7e63fc9d
RN
201 FreePool (Buffer);\r
202 break;\r
203 }\r
204\r
205 //\r
206 // Check Crc32\r
207 //\r
208 * (UINT32 *) Buffer = NameSize;\r
209 * ((UINT32 *) Buffer + 1) = DataSize;\r
210 BufferSize = RemainingSize + sizeof (NameSize) + sizeof (DataSize) - sizeof (Crc32);\r
211 gBS->CalculateCrc32 (\r
212 Buffer,\r
213 BufferSize,\r
214 &Crc32\r
215 );\r
216 if (Crc32 != * (UINT32 *) (Buffer + BufferSize)) {\r
217 FreePool (Buffer);\r
5511b319 218 ShellStatus = SHELL_VOLUME_CORRUPTED;\r
7e63fc9d
RN
219 break;\r
220 }\r
221\r
222 Position += BufferSize + sizeof (Crc32);\r
223 \r
224 Variable = AllocateZeroPool (sizeof (*Variable) + NameSize + DataSize);\r
225 if (Variable == NULL) {\r
226 FreePool (Buffer);\r
5511b319 227 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
7e63fc9d
RN
228 break;\r
229 }\r
230 Variable->Signature = DMP_STORE_VARIABLE_SIGNATURE;\r
231 Variable->Name = (CHAR16 *) (Variable + 1);\r
232 Variable->DataSize = DataSize;\r
233 Variable->Data = (UINT8 *) Variable->Name + NameSize;\r
234 CopyMem (Variable->Name, Buffer + sizeof (NameSize) + sizeof (DataSize), NameSize);\r
235 CopyMem (&Variable->Guid, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize, sizeof (EFI_GUID));\r
236 CopyMem (&Variable->Attributes, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize + sizeof (EFI_GUID), sizeof (UINT32));\r
237 CopyMem (Variable->Data, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize + sizeof (EFI_GUID) + sizeof (UINT32), DataSize);\r
238\r
239 InsertTailList (&List, &Variable->Link);\r
240 FreePool (Buffer);\r
241 }\r
242 \r
5511b319 243 if ((Position != FileSize) || (ShellStatus != SHELL_SUCCESS)) {\r
4092a8f6 244 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD_BAD_FILE), gShellDebug1HiiHandle, L"dmpstore"); \r
5511b319
SQ
245 if (Position != FileSize) {\r
246 ShellStatus = SHELL_VOLUME_CORRUPTED;\r
247 }\r
7e63fc9d
RN
248 }\r
249 \r
250 for ( Link = GetFirstNode (&List)\r
5511b319 251 ; !IsNull (&List, Link) && (ShellStatus == SHELL_SUCCESS)\r
7e63fc9d
RN
252 ; Link = GetNextNode (&List, Link)\r
253 ) {\r
254 Variable = CR (Link, DMP_STORE_VARIABLE, Link, DMP_STORE_VARIABLE_SIGNATURE);\r
255 \r
256 if (((Name == NULL) || gUnicodeCollation->MetaiMatch (gUnicodeCollation, Variable->Name, (CHAR16 *) Name)) &&\r
257 ((Guid == NULL) || CompareGuid (&Variable->Guid, Guid))\r
258 ) {\r
259 Attributes = GetAttrType (Variable->Attributes);\r
260 ShellPrintHiiEx (\r
261 -1, -1, NULL, STRING_TOKEN(STR_DMPSTORE_HEADER_LINE), gShellDebug1HiiHandle,\r
262 Attributes, &Variable->Guid, Variable->Name, Variable->DataSize\r
263 );\r
264 SHELL_FREE_NON_NULL(Attributes);\r
265\r
266 *Found = TRUE;\r
267 Status = gRT->SetVariable (\r
268 Variable->Name,\r
269 &Variable->Guid,\r
270 Variable->Attributes,\r
271 Variable->DataSize,\r
272 Variable->Data\r
273 );\r
274 if (EFI_ERROR (Status)) {\r
4092a8f6 275 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD_GEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", Variable->Name, Status); \r
7e63fc9d
RN
276 }\r
277 }\r
278 }\r
279\r
280 for (Link = GetFirstNode (&List); !IsNull (&List, Link); ) {\r
281 Variable = CR (Link, DMP_STORE_VARIABLE, Link, DMP_STORE_VARIABLE_SIGNATURE);\r
282 Link = RemoveEntryList (&Variable->Link);\r
283 FreePool (Variable);\r
284 }\r
285\r
5511b319 286 return ShellStatus;\r
7e63fc9d
RN
287}\r
288\r
289/**\r
290 Append one variable to file.\r
291\r
292 @param[in] FileHandle The file to be appended.\r
293 @param[in] Name The variable name.\r
294 @param[in] Guid The variable GUID.\r
295 @param[in] Attributes The variable attributes.\r
296 @param[in] DataSize The variable data size.\r
297 @param[in] Data The variable data.\r
298\r
299 @retval EFI_OUT_OF_RESOURCES There is not enough memory to perform the operation.\r
300 @retval EFI_SUCCESS The variable is appended to file successfully.\r
301 @retval others Failed to append the variable to file.\r
302**/\r
303EFI_STATUS\r
304AppendSingleVariableToFile (\r
305 IN SHELL_FILE_HANDLE FileHandle,\r
306 IN CONST CHAR16 *Name,\r
307 IN CONST EFI_GUID *Guid,\r
308 IN UINT32 Attributes,\r
309 IN UINT32 DataSize,\r
310 IN CONST UINT8 *Data\r
311 )\r
312{\r
313 UINT32 NameSize;\r
314 UINT8 *Buffer;\r
315 UINT8 *Ptr;\r
316 UINTN BufferSize;\r
317 EFI_STATUS Status;\r
318\r
319 NameSize = (UINT32) StrSize (Name);\r
320 BufferSize = sizeof (NameSize) + sizeof (DataSize)\r
321 + sizeof (*Guid)\r
322 + sizeof (Attributes)\r
323 + NameSize + DataSize\r
324 + sizeof (UINT32);\r
325\r
326 Buffer = AllocatePool (BufferSize);\r
327 if (Buffer == NULL) {\r
328 return EFI_OUT_OF_RESOURCES;\r
329 }\r
330\r
331 Ptr = Buffer;\r
332 //\r
333 // NameSize and DataSize\r
334 //\r
335 * (UINT32 *) Ptr = NameSize;\r
336 Ptr += sizeof (NameSize);\r
337 *(UINT32 *) Ptr = DataSize;\r
338 Ptr += sizeof (DataSize);\r
339\r
340 //\r
341 // Name\r
342 //\r
343 CopyMem (Ptr, Name, NameSize);\r
344 Ptr += NameSize;\r
345\r
346 //\r
347 // Guid\r
348 //\r
349 CopyMem (Ptr, Guid, sizeof (*Guid));\r
350 Ptr += sizeof (*Guid);\r
351\r
352 //\r
353 // Attributes\r
354 //\r
355 * (UINT32 *) Ptr = Attributes;\r
356 Ptr += sizeof (Attributes);\r
357\r
358 //\r
359 // Data\r
360 //\r
361 CopyMem (Ptr, Data, DataSize);\r
362 Ptr += DataSize;\r
363\r
364 //\r
365 // Crc32\r
366 //\r
810c635d 367 gBS->CalculateCrc32 (Buffer, (UINTN) Ptr - (UINTN) Buffer, (UINT32 *) Ptr);\r
7e63fc9d
RN
368\r
369 Status = ShellWriteFile (FileHandle, &BufferSize, Buffer);\r
370 FreePool (Buffer);\r
371\r
372 if (!EFI_ERROR (Status) && \r
88963516 373 (BufferSize != sizeof (NameSize) + sizeof (DataSize) + sizeof (*Guid) + sizeof (Attributes) + NameSize + DataSize + sizeof (UINT32))\r
7e63fc9d
RN
374 ) {\r
375 Status = EFI_DEVICE_ERROR;\r
376 }\r
377 \r
378 return Status;\r
379}\r
380\r
3737ac2b 381/**\r
5bd12b05
JC
382 Recursive function to display or delete variables.\r
383\r
384 This function will call itself to create a stack-based list of allt he variables to process, \r
385 then fromt he last to the first, they will do either printing or deleting.\r
386\r
387 This is necessary since once a delete happens GetNextVariableName() will work.\r
3737ac2b 388\r
e9597b45
RN
389 @param[in] Name The variable name of the EFI variable (or NULL).\r
390 @param[in] Guid The GUID of the variable set (or NULL).\r
391 @param[in] Type The operation type.\r
392 @param[in] FileHandle The file to operate on (or NULL).\r
393 @param[in] PrevName The previous variable name from GetNextVariableName. L"" to start.\r
394 @param[in] FoundVarGuid The previous GUID from GetNextVariableName. ignored at start.\r
395 @param[in] FoundOne If a VariableName or Guid was specified and one was printed or\r
396 deleted, then set this to TRUE, otherwise ignored.\r
397 @param[in] StandardFormatOutput TRUE indicates Standard-Format Output.\r
3737ac2b 398\r
399 @retval SHELL_SUCCESS The operation was successful.\r
400 @retval SHELL_OUT_OF_RESOURCES A memorty allocation failed.\r
401 @retval SHELL_ABORTED The abort message was received.\r
402 @retval SHELL_DEVICE_ERROR UEFI Variable Services returned an error.\r
403 @retval SHELL_NOT_FOUND the Name/Guid pair could not be found.\r
404**/\r
5d73d92f 405SHELL_STATUS\r
5bd12b05 406CascadeProcessVariables (\r
7e63fc9d
RN
407 IN CONST CHAR16 *Name OPTIONAL,\r
408 IN CONST EFI_GUID *Guid OPTIONAL,\r
409 IN DMP_STORE_TYPE Type,\r
410 IN EFI_FILE_PROTOCOL *FileHandle OPTIONAL,\r
411 IN CONST CHAR16 * CONST PrevName,\r
412 IN EFI_GUID FoundVarGuid,\r
e9597b45
RN
413 IN BOOLEAN *FoundOne,\r
414 IN BOOLEAN StandardFormatOutput\r
5d73d92f 415 )\r
416{\r
417 EFI_STATUS Status;\r
5d73d92f 418 CHAR16 *FoundVarName;\r
5d73d92f 419 UINT8 *DataBuffer;\r
420 UINTN DataSize;\r
421 UINT32 Atts;\r
422 SHELL_STATUS ShellStatus;\r
73c82041 423 UINTN NameSize;\r
e9597b45
RN
424 CHAR16 *AttrString;\r
425 CHAR16 *HexString;\r
ff28c72b 426 EFI_STATUS SetStatus;\r
ba30d5f0 427 CONST CHAR16 *GuidName;\r
5d73d92f 428\r
5bd12b05
JC
429 if (ShellGetExecutionBreakFlag()) {\r
430 return (SHELL_ABORTED);\r
5d73d92f 431 }\r
432\r
5bd12b05
JC
433 NameSize = 0;\r
434 FoundVarName = NULL;\r
5d73d92f 435\r
5bd12b05
JC
436 if (PrevName!=NULL) {\r
437 StrnCatGrow(&FoundVarName, &NameSize, PrevName, 0);\r
438 } else {\r
439 FoundVarName = AllocateZeroPool(sizeof(CHAR16));\r
980af1eb 440 NameSize = sizeof(CHAR16);\r
5bd12b05
JC
441 }\r
442\r
443 Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);\r
444 if (Status == EFI_BUFFER_TOO_SMALL) {\r
445 SHELL_FREE_NON_NULL(FoundVarName);\r
446 FoundVarName = AllocateZeroPool (NameSize);\r
03bc7c2b
SQ
447 if (FoundVarName != NULL) {\r
448 if (PrevName != NULL) {\r
4dc0d578 449 StrnCpyS(FoundVarName, NameSize/sizeof(CHAR16), PrevName, NameSize/sizeof(CHAR16) - 1);\r
03bc7c2b
SQ
450 }\r
451\r
452 Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);\r
453 } else {\r
454 Status = EFI_OUT_OF_RESOURCES;\r
5d73d92f 455 }\r
5bd12b05
JC
456 }\r
457\r
458 //\r
459 // No more is fine.\r
460 //\r
461 if (Status == EFI_NOT_FOUND) {\r
462 SHELL_FREE_NON_NULL(FoundVarName);\r
463 return (SHELL_SUCCESS);\r
464 } else if (EFI_ERROR(Status)) {\r
465 SHELL_FREE_NON_NULL(FoundVarName);\r
466 return (SHELL_DEVICE_ERROR);\r
467 }\r
468\r
469 //\r
470 // Recurse to the next iteration. We know "our" variable's name.\r
471 //\r
e9597b45 472 ShellStatus = CascadeProcessVariables (Name, Guid, Type, FileHandle, FoundVarName, FoundVarGuid, FoundOne, StandardFormatOutput);\r
5bd12b05 473\r
148af387
TS
474 if (ShellGetExecutionBreakFlag() || (ShellStatus == SHELL_ABORTED)) {\r
475 SHELL_FREE_NON_NULL(FoundVarName);\r
476 return (SHELL_ABORTED);\r
477 }\r
478\r
5bd12b05
JC
479 //\r
480 // No matter what happened we process our own variable\r
481 // Only continue if Guid and VariableName are each either NULL or a match\r
482 //\r
7e63fc9d
RN
483 if ( ( Name == NULL \r
484 || gUnicodeCollation->MetaiMatch(gUnicodeCollation, FoundVarName, (CHAR16*) Name) )\r
5bd12b05
JC
485 && ( Guid == NULL \r
486 || CompareGuid(&FoundVarGuid, Guid) )\r
487 ) {\r
488 DataSize = 0;\r
489 DataBuffer = NULL;\r
5d73d92f 490 //\r
5bd12b05 491 // do the print or delete\r
5d73d92f 492 //\r
5bd12b05
JC
493 *FoundOne = TRUE;\r
494 Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);\r
73c82041 495 if (Status == EFI_BUFFER_TOO_SMALL) {\r
5bd12b05
JC
496 SHELL_FREE_NON_NULL (DataBuffer);\r
497 DataBuffer = AllocatePool (DataSize);\r
73c82041
ED
498 if (DataBuffer == NULL) {\r
499 Status = EFI_OUT_OF_RESOURCES;\r
5bd12b05
JC
500 } else {\r
501 Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);\r
73c82041 502 }\r
5bd12b05 503 }\r
5bd12b05
JC
504 //\r
505 // Last error check then print this variable out.\r
506 //\r
e9597b45 507 if (Type == DmpStoreDisplay) {\r
5511b319 508 if (!EFI_ERROR(Status) && (DataBuffer != NULL) && (FoundVarName != NULL)) {\r
e9597b45
RN
509 AttrString = GetAttrType(Atts);\r
510 if (StandardFormatOutput) {\r
511 HexString = AllocatePool ((DataSize * 2 + 1) * sizeof (CHAR16));\r
512 if (HexString != NULL) {\r
513 ShellPrintHiiEx (\r
514 -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_VAR_SFO), gShellDebug1HiiHandle,\r
515 FoundVarName, &FoundVarGuid, Atts, DataSize,\r
516 BinaryToHexString (\r
517 DataBuffer, DataSize, HexString, (DataSize * 2 + 1) * sizeof (CHAR16)\r
518 )\r
519 );\r
520 FreePool (HexString);\r
521 } else {\r
522 Status = EFI_OUT_OF_RESOURCES;\r
523 }\r
7e63fc9d 524 } else {\r
09e86783
HL
525 Status = gEfiShellProtocol->GetGuidName(&FoundVarGuid, &GuidName);\r
526 if (EFI_ERROR (Status)) {\r
527 ShellPrintHiiEx (\r
528 -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_HEADER_LINE), gShellDebug1HiiHandle,\r
529 AttrString, &FoundVarGuid, FoundVarName, DataSize\r
530 );\r
531 } else {\r
532 ShellPrintHiiEx (\r
533 -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_HEADER_LINE2), gShellDebug1HiiHandle,\r
534 AttrString, GuidName, FoundVarName, DataSize\r
535 );\r
536 }\r
e9597b45 537 DumpHex (2, 0, DataSize, DataBuffer);\r
7e63fc9d 538 }\r
e9597b45
RN
539 SHELL_FREE_NON_NULL (AttrString);\r
540 }\r
541 } else if (Type == DmpStoreSave) {\r
542 if (!EFI_ERROR(Status) && (DataBuffer != NULL) && (FoundVarName != NULL)) {\r
543 AttrString = GetAttrType (Atts);\r
544 ShellPrintHiiEx (\r
545 -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_HEADER_LINE), gShellDebug1HiiHandle,\r
546 AttrString, &FoundVarGuid, FoundVarName, DataSize\r
547 );\r
548 Status = AppendSingleVariableToFile (\r
549 FileHandle,\r
550 FoundVarName,\r
551 &FoundVarGuid,\r
552 Atts,\r
553 (UINT32) DataSize,\r
554 DataBuffer\r
555 );\r
556 SHELL_FREE_NON_NULL (AttrString);\r
5bd12b05 557 }\r
7e63fc9d 558 } else if (Type == DmpStoreDelete) {\r
5bd12b05
JC
559 //\r
560 // We only need name to delete it...\r
561 //\r
ff28c72b 562 SetStatus = gRT->SetVariable (FoundVarName, &FoundVarGuid, Atts, 0, NULL);\r
e9597b45
RN
563 if (StandardFormatOutput) {\r
564 if (SetStatus == EFI_SUCCESS) {\r
565 ShellPrintHiiEx (\r
566 -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_NG_SFO), gShellDebug1HiiHandle,\r
567 FoundVarName, &FoundVarGuid\r
568 );\r
569 }\r
570 } else {\r
571 ShellPrintHiiEx (\r
572 -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_DELETE_LINE), gShellDebug1HiiHandle,\r
573 &FoundVarGuid, FoundVarName, SetStatus\r
574 );\r
575 }\r
d6972185 576 }\r
5bd12b05 577 SHELL_FREE_NON_NULL(DataBuffer);\r
5d73d92f 578 }\r
579\r
5bd12b05
JC
580 SHELL_FREE_NON_NULL(FoundVarName);\r
581\r
582 if (Status == EFI_DEVICE_ERROR) {\r
583 ShellStatus = SHELL_DEVICE_ERROR;\r
584 } else if (Status == EFI_SECURITY_VIOLATION) {\r
585 ShellStatus = SHELL_SECURITY_VIOLATION;\r
586 } else if (EFI_ERROR(Status)) {\r
587 ShellStatus = SHELL_NOT_READY;\r
5d73d92f 588 }\r
5bd12b05
JC
589\r
590 return (ShellStatus);\r
591}\r
592\r
593/**\r
594 Function to display or delete variables. This will set up and call into the recursive function.\r
595\r
e9597b45
RN
596 @param[in] Name The variable name of the EFI variable (or NULL).\r
597 @param[in] Guid The GUID of the variable set (or NULL).\r
598 @param[in] Type The operation type.\r
599 @param[in] FileHandle The file to save or load variables.\r
600 @param[in] StandardFormatOutput TRUE indicates Standard-Format Output.\r
5bd12b05
JC
601\r
602 @retval SHELL_SUCCESS The operation was successful.\r
603 @retval SHELL_OUT_OF_RESOURCES A memorty allocation failed.\r
604 @retval SHELL_ABORTED The abort message was received.\r
605 @retval SHELL_DEVICE_ERROR UEFI Variable Services returned an error.\r
606 @retval SHELL_NOT_FOUND the Name/Guid pair could not be found.\r
607**/\r
608SHELL_STATUS\r
5bd12b05 609ProcessVariables (\r
7e63fc9d
RN
610 IN CONST CHAR16 *Name OPTIONAL,\r
611 IN CONST EFI_GUID *Guid OPTIONAL,\r
612 IN DMP_STORE_TYPE Type,\r
e9597b45
RN
613 IN SHELL_FILE_HANDLE FileHandle OPTIONAL,\r
614 IN BOOLEAN StandardFormatOutput\r
5bd12b05
JC
615 )\r
616{\r
617 SHELL_STATUS ShellStatus;\r
618 BOOLEAN Found;\r
619 EFI_GUID FoundVarGuid;\r
620\r
621 Found = FALSE;\r
622 ShellStatus = SHELL_SUCCESS;\r
623 ZeroMem (&FoundVarGuid, sizeof(EFI_GUID));\r
624\r
e9597b45
RN
625 if (StandardFormatOutput) {\r
626 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_GEN_SFO_HEADER), gShellDebug1HiiHandle, L"dmpstore");\r
627 }\r
628\r
7e63fc9d 629 if (Type == DmpStoreLoad) {\r
5511b319 630 ShellStatus = LoadVariablesFromFile (FileHandle, Name, Guid, &Found);\r
7e63fc9d 631 } else {\r
e9597b45 632 ShellStatus = CascadeProcessVariables (Name, Guid, Type, FileHandle, NULL, FoundVarGuid, &Found, StandardFormatOutput);\r
7e63fc9d 633 }\r
5bd12b05 634\r
3737ac2b 635 if (!Found) {\r
5bd12b05 636 if (ShellStatus == SHELL_OUT_OF_RESOURCES) {\r
4092a8f6 637 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"dmpstore"); \r
5bd12b05 638 return (ShellStatus);\r
7e63fc9d 639 } else if (Name != NULL && Guid == NULL) {\r
e9597b45
RN
640 if (StandardFormatOutput) {\r
641 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_N_SFO), gShellDebug1HiiHandle, Name);\r
642 } else {\r
643 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_N), gShellDebug1HiiHandle, L"dmpstore", Name); \r
644 }\r
7e63fc9d 645 } else if (Name != NULL && Guid != NULL) {\r
4092a8f6 646 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_GN), gShellDebug1HiiHandle, L"dmpstore", Guid, Name); \r
7e63fc9d 647 } else if (Name == NULL && Guid == NULL) {\r
e9597b45
RN
648 if (StandardFormatOutput) {\r
649 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_SFO), gShellDebug1HiiHandle);\r
650 } else {\r
651 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND), gShellDebug1HiiHandle, L"dmpstore");\r
652 }\r
7e63fc9d 653 } else if (Name == NULL && Guid != NULL) {\r
e9597b45
RN
654 if (StandardFormatOutput) {\r
655 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_G_SFO), gShellDebug1HiiHandle, Guid);\r
656 } else {\r
657 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_G), gShellDebug1HiiHandle, L"dmpstore", Guid);\r
658 }\r
3737ac2b 659 } \r
660 return (SHELL_NOT_FOUND);\r
661 }\r
224e8e2f 662 return (ShellStatus);\r
5d73d92f 663}\r
664\r
665STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
666 {L"-d", TypeFlag},\r
7e63fc9d
RN
667 {L"-l", TypeValue},\r
668 {L"-s", TypeValue},\r
5d73d92f 669 {L"-all", TypeFlag},\r
670 {L"-guid", TypeValue},\r
e9597b45 671 {L"-sfo", TypeFlag},\r
5d73d92f 672 {NULL, TypeMax}\r
673 };\r
674\r
3737ac2b 675/**\r
676 Function for 'dmpstore' command.\r
677\r
678 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
679 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
680**/\r
5d73d92f 681SHELL_STATUS\r
682EFIAPI\r
683ShellCommandRunDmpStore (\r
684 IN EFI_HANDLE ImageHandle,\r
685 IN EFI_SYSTEM_TABLE *SystemTable\r
686 )\r
687{\r
7e63fc9d 688 EFI_STATUS Status;\r
7f6511ee 689 RETURN_STATUS RStatus;\r
7e63fc9d
RN
690 LIST_ENTRY *Package;\r
691 CHAR16 *ProblemParam;\r
692 SHELL_STATUS ShellStatus;\r
693 CONST CHAR16 *GuidStr;\r
694 CONST CHAR16 *File;\r
695 EFI_GUID *Guid;\r
696 EFI_GUID GuidData;\r
697 CONST CHAR16 *Name;\r
698 DMP_STORE_TYPE Type;\r
699 SHELL_FILE_HANDLE FileHandle;\r
700 EFI_FILE_INFO *FileInfo;\r
e9597b45 701 BOOLEAN StandardFormatOutput;\r
5d73d92f 702\r
e9597b45
RN
703 ShellStatus = SHELL_SUCCESS;\r
704 Package = NULL;\r
705 FileHandle = NULL;\r
706 File = NULL;\r
707 Type = DmpStoreDisplay;\r
708 StandardFormatOutput = FALSE;\r
5d73d92f 709\r
710 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
711 if (EFI_ERROR(Status)) {\r
712 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
4092a8f6 713 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"dmpstore", ProblemParam); \r
5d73d92f 714 FreePool(ProblemParam);\r
715 ShellStatus = SHELL_INVALID_PARAMETER;\r
716 } else {\r
717 ASSERT(FALSE);\r
718 }\r
719 } else {\r
3737ac2b 720 if (ShellCommandLineGetCount(Package) > 2) {\r
4092a8f6 721 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"dmpstore"); \r
5d73d92f 722 ShellStatus = SHELL_INVALID_PARAMETER;\r
723 } else if (ShellCommandLineGetFlag(Package, L"-all") && ShellCommandLineGetFlag(Package, L"-guid")) {\r
4092a8f6 724 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-all", L"-guid"); \r
5d73d92f 725 ShellStatus = SHELL_INVALID_PARAMETER;\r
7e63fc9d 726 } else if (ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-l")) {\r
4092a8f6 727 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l", L"-s"); \r
7e63fc9d 728 ShellStatus = SHELL_INVALID_PARAMETER;\r
5d73d92f 729 } else if ((ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-l")) && ShellCommandLineGetFlag(Package, L"-d")) {\r
4092a8f6 730 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l or -s", L"-d"); \r
5d73d92f 731 ShellStatus = SHELL_INVALID_PARAMETER;\r
e9597b45
RN
732 } else if ((ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-l")) && ShellCommandLineGetFlag(Package, L"-sfo")) {\r
733 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l or -s", L"-sfo"); \r
734 ShellStatus = SHELL_INVALID_PARAMETER;\r
5d73d92f 735 } else {\r
9954df7b
JC
736 //\r
737 // Determine the GUID to search for based on -all and -guid parameters\r
738 //\r
5d73d92f 739 if (!ShellCommandLineGetFlag(Package, L"-all")) {\r
7e63fc9d
RN
740 GuidStr = ShellCommandLineGetValue(Package, L"-guid");\r
741 if (GuidStr != NULL) {\r
7f6511ee
RN
742 RStatus = StrToGuid (GuidStr, &GuidData);\r
743 if (RETURN_ERROR (RStatus) || (GuidStr[GUID_STRING_LENGTH] != L'\0')) {\r
4092a8f6 744 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dmpstore", GuidStr); \r
5d73d92f 745 ShellStatus = SHELL_INVALID_PARAMETER;\r
746 }\r
747 Guid = &GuidData;\r
748 } else {\r
749 Guid = &gEfiGlobalVariableGuid;\r
750 }\r
5d73d92f 751 } else {\r
7e63fc9d 752 Guid = NULL;\r
5d73d92f 753 }\r
9954df7b
JC
754\r
755 //\r
756 // Get the Name of the variable to find\r
757 //\r
758 Name = ShellCommandLineGetRawValue(Package, 1);\r
759\r
5d73d92f 760 if (ShellStatus == SHELL_SUCCESS) {\r
7e63fc9d
RN
761 if (ShellCommandLineGetFlag(Package, L"-s")) {\r
762 Type = DmpStoreSave;\r
763 File = ShellCommandLineGetValue(Package, L"-s");\r
764 if (File == NULL) {\r
4092a8f6 765 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"dmpstore", L"-s"); \r
7e63fc9d
RN
766 ShellStatus = SHELL_INVALID_PARAMETER;\r
767 } else {\r
768 Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);\r
769 if (!EFI_ERROR (Status)) {\r
770 //\r
771 // Delete existing file, but do not delete existing directory\r
772 //\r
773 FileInfo = ShellGetFileInfo (FileHandle);\r
774 if (FileInfo == NULL) {\r
4092a8f6 775 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File); \r
7e63fc9d
RN
776 Status = EFI_DEVICE_ERROR;\r
777 } else {\r
778 if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {\r
4092a8f6 779 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_IS_DIRECTORY), gShellDebug1HiiHandle, L"dmpstore", File); \r
7e63fc9d
RN
780 Status = EFI_INVALID_PARAMETER;\r
781 } else {\r
782 Status = ShellDeleteFile (&FileHandle);\r
783 if (EFI_ERROR (Status)) {\r
4092a8f6 784 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_DELETE_FAIL), gShellDebug1HiiHandle, L"dmpstore", File); \r
7e63fc9d
RN
785 }\r
786 }\r
787 FreePool (FileInfo);\r
788 }\r
789 } else if (Status == EFI_NOT_FOUND) {\r
790 //\r
791 // Good when file doesn't exist\r
792 //\r
793 Status = EFI_SUCCESS;\r
794 } else {\r
795 //\r
796 // Otherwise it's bad.\r
797 //\r
4092a8f6 798 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File); \r
7e63fc9d
RN
799 }\r
800\r
801 if (!EFI_ERROR (Status)) {\r
802 Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);\r
803 if (EFI_ERROR (Status)) {\r
4092a8f6 804 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File); \r
7e63fc9d
RN
805 }\r
806 }\r
807\r
808 if (EFI_ERROR (Status)) {\r
809 ShellStatus = SHELL_INVALID_PARAMETER;\r
810 }\r
811 }\r
812 } else if (ShellCommandLineGetFlag(Package, L"-l")) {\r
813 Type = DmpStoreLoad;\r
814 File = ShellCommandLineGetValue(Package, L"-l");\r
815 if (File == NULL) {\r
4092a8f6 816 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"dmpstore", L"-l"); \r
7e63fc9d
RN
817 ShellStatus = SHELL_INVALID_PARAMETER;\r
818 } else {\r
819 Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_READ, 0);\r
820 if (EFI_ERROR (Status)) {\r
4092a8f6 821 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File); \r
7e63fc9d
RN
822 ShellStatus = SHELL_INVALID_PARAMETER;\r
823 } else {\r
824 FileInfo = ShellGetFileInfo (FileHandle);\r
825 if (FileInfo == NULL) {\r
4092a8f6 826 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File); \r
7e63fc9d
RN
827 ShellStatus = SHELL_DEVICE_ERROR;\r
828 } else {\r
829 if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {\r
4092a8f6 830 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_IS_DIRECTORY), gShellDebug1HiiHandle, L"dmpstore", File); \r
7e63fc9d
RN
831 ShellStatus = SHELL_INVALID_PARAMETER;\r
832 }\r
833 FreePool (FileInfo);\r
834 }\r
835 }\r
836 }\r
837 } else if (ShellCommandLineGetFlag(Package, L"-d")) {\r
838 Type = DmpStoreDelete;\r
839 }\r
e9597b45
RN
840\r
841 if (ShellCommandLineGetFlag (Package,L"-sfo")) {\r
842 StandardFormatOutput = TRUE;\r
843 }\r
7e63fc9d
RN
844 }\r
845\r
846 if (ShellStatus == SHELL_SUCCESS) {\r
847 if (Type == DmpStoreSave) {\r
848 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_SAVE), gShellDebug1HiiHandle, File);\r
849 } else if (Type == DmpStoreLoad) {\r
850 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD), gShellDebug1HiiHandle, File);\r
851 }\r
e9597b45 852 ShellStatus = ProcessVariables (Name, Guid, Type, FileHandle, StandardFormatOutput);\r
7e63fc9d
RN
853 if ((Type == DmpStoreLoad) || (Type == DmpStoreSave)) {\r
854 ShellCloseFile (&FileHandle);\r
5d73d92f 855 }\r
856 }\r
857 }\r
858 }\r
859\r
860 if (Package != NULL) {\r
861 ShellCommandLineFreeVarList (Package);\r
862 }\r
863 return ShellStatus;\r
864}\r
865\r