SHEL10
[efi/shell/.git] / dmpstore / dmpstore.c
1 /*++
2
3 Copyright (c) 2005 - 2008, Intel Corporation                                                         
4 All rights reserved. This program and the accompanying materials                          
5 are licensed and made available under the terms and conditions of the BSD License         
6 which accompanies this distribution. The full text of the license may be found at         
7 http://opensource.org/licenses/bsd-license.php                                            
8                                                                                           
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
11
12 Module Name:
13
14   dmpstore.c
15   
16 Abstract:
17
18   Shell app "dmpstore"
19
20
21
22 Revision History
23
24 --*/
25
26 #include "EfiShellLib.h"
27 #include "EfiVariable.h"
28 #include "dmpstore.h"
29
30 extern UINT8  STRING_ARRAY_NAME[];
31
32 //
33 // This is the generated header file which includes whatever needs to be exported (strings + IFR)
34 //
35 #include STRING_DEFINES_FILE
36
37 #define DEBUG_NAME_SIZE MAX_VARIABLE_SIZE
38
39 STATIC CHAR16   *AttrType[] = {
40   L"invalid",   // 000
41   L"invalid",   // 001
42   L"BS",        // 010
43   L"NV+BS",     // 011
44   L"RT+BS",     // 100
45   L"NV+RT+BS",  // 101
46   L"RT+BS",     // 110
47   L"NV+RT+BS",  // 111
48 };
49
50 //
51 //
52 //
53 EFI_STATUS
54 InitializeDumpStore (
55   IN EFI_HANDLE         ImageHandle,
56   IN EFI_SYSTEM_TABLE   *SystemTable
57   );
58
59 EFI_STATUS
60 LoadVariableStore (
61   IN CHAR16   *VarName,
62   IN CHAR16   *FileName
63   );
64
65 EFI_STATUS
66 DumpVariableStore (
67   IN CHAR16           *VarName,
68   IN BOOLEAN          Delete,
69   IN EFI_FILE_HANDLE  FileHandle  
70   );
71
72 EFI_STATUS
73 CreateOutputFile (
74   IN CHAR16           *FileName, 
75   OUT EFI_FILE_HANDLE *FileHandle
76   );
77
78 EFI_STATUS
79 GetFileVariable (
80   IN EFI_FILE_HANDLE FileHandle,
81   IN OUT UINTN       *VariableNameSize,
82   IN CHAR16          *VariableName,
83   IN EFI_GUID        *VendorGuid,
84   OUT UINT32         *Attributes,
85   IN OUT UINTN       *DataSize,
86   OUT VOID           *Data
87   );
88
89 EFI_STATUS
90 SetFileVariable (
91   IN EFI_FILE_HANDLE FileHandle,
92   IN UINTN           VariableNameSize,
93   IN CHAR16          *VariableName,
94   IN EFI_GUID        *VendorGuid,
95   IN UINT32          Attributes,
96   IN UINTN           DataSize,
97   IN VOID            *Data  
98   );
99
100 //
101 // Global Variables
102 //
103 EFI_HII_HANDLE  HiiHandle;
104 EFI_GUID        EfiDmpstoreGuid = EFI_DMPSTORE_GUID;
105 SHELL_VAR_CHECK_ITEM    DmpstoreCheckList[] = {
106   {
107     L"-b",
108     0x01,
109     0,
110     FlagTypeSingle
111   },
112   {
113     L"-?",
114     0x02,
115     0,
116     FlagTypeSingle
117   },
118   {
119     L"-d",
120     0x04,
121     0x18,
122     FlagTypeSingle
123   },
124   {
125     L"-s",
126     0x08,
127     0x14,
128     FlagTypeNeedVar
129   },  
130   {
131     L"-l",
132     0x10,
133     0x0c,
134     FlagTypeNeedVar
135   },  
136   {
137     NULL,
138     0,
139     0,
140     0
141   }
142 };
143
144 EFI_BOOTSHELL_CODE(
145   EFI_APPLICATION_ENTRY_POINT(InitializeDumpStore)
146 )
147
148 EFI_STATUS
149 InitializeDumpStore (
150   IN EFI_HANDLE         ImageHandle,
151   IN EFI_SYSTEM_TABLE   *SystemTable
152   )
153 /*++
154
155 Routine Description:
156
157   Command entry point
158
159 Arguments:
160
161   ImageHandle - The image handle
162   SystemTable - The system table
163
164 Returns:
165
166   EFI_SUCCESS - Success
167
168 --*/
169 {
170   CHAR16                  *VarName;
171   EFI_STATUS              Status;
172   BOOLEAN                 Delete;
173   EFI_FILE_HANDLE         FileHandle;
174   SHELL_VAR_CHECK_CODE    RetCode;
175   CHAR16                  *Useful;
176   SHELL_VAR_CHECK_PACKAGE ChkPck;
177   SHELL_ARG_LIST          *Item;
178
179   ZeroMem (&ChkPck, sizeof (SHELL_VAR_CHECK_PACKAGE));
180   //
181   // We are no being installed as an internal command driver, initialize
182   // as an nshell app and run
183   //
184   EFI_SHELL_APP_INIT (ImageHandle, SystemTable);
185
186   //
187   // Enable tab key which can pause the output
188   //
189   EnableOutputTabPause();
190    
191   //
192   // Register our string package with HII and return the handle to it.
193   // If previously registered we will simply receive the handle
194   //
195   Status = LibInitializeStrings (&HiiHandle, STRING_ARRAY_NAME, &EfiDmpstoreGuid);
196   if (EFI_ERROR (Status)) {
197     return Status;
198   }
199
200   VarName    = NULL;
201   Status     = EFI_SUCCESS;
202   Delete     = FALSE;
203   FileHandle = NULL;
204
205   LibFilterNullArgs ();
206   //
207   // Check flags
208   //
209   Useful  = NULL;
210   RetCode = LibCheckVariables (SI, DmpstoreCheckList, &ChkPck, &Useful);
211   if (VarCheckOk != RetCode) {
212     switch (RetCode) {
213     case VarCheckConflict:
214       PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_FLAG_CONFLICT), HiiHandle, L"dmpstore", Useful);
215       break;
216           
217     case VarCheckDuplicate:
218       PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_DUP_FLAG), HiiHandle, L"dmpstore", Useful);
219       break;
220
221     case VarCheckUnknown:
222       PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_UNKNOWN_FLAG), HiiHandle, L"dmpstore", Useful);
223       break;
224
225     case VarCheckLackValue:
226       PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_LACK_ARG), HiiHandle, L"dmpstore", Useful);
227       break;
228       
229     default:
230       break;
231     }
232
233     Status = EFI_INVALID_PARAMETER;
234     goto Done;
235   }
236
237   if (LibCheckVarGetFlag (&ChkPck, L"-b") != NULL) {
238     EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);
239   }
240
241   if (LibCheckVarGetFlag (&ChkPck, L"-?")) {
242     if (ChkPck.ValueCount > 0 ||
243         ChkPck.FlagCount > 2 ||
244         (2 == ChkPck.FlagCount && !LibCheckVarGetFlag (&ChkPck, L"-b"))
245         ) {
246       PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_TOO_MANY), HiiHandle, L"dmpstore");
247       Status = EFI_INVALID_PARAMETER;
248     } else {
249       PrintToken (STRING_TOKEN (STR_DMPSTORE_VERBOSEHELP), HiiHandle);
250       Status = EFI_SUCCESS;
251     }
252
253     goto Done;
254   }
255
256   if (ChkPck.ValueCount > 1) {
257     PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_TOO_MANY), HiiHandle, L"dmpstore");
258     Status = EFI_INVALID_PARAMETER;
259     goto Done;
260   }
261
262   if (NULL != ChkPck.VarList) {
263     VarName = ChkPck.VarList->VarStr;
264   }
265   
266   Item = LibCheckVarGetFlag (&ChkPck, L"-l");
267   if (Item != NULL) {
268     //
269     // Load and set variables from previous saved file
270     //
271     Status = LoadVariableStore (VarName, Item->VarStr);
272     goto Done;
273   }
274
275   Item = LibCheckVarGetFlag (&ChkPck, L"-s");
276   if (Item != NULL) {
277     //
278     // Create output file for saving variables
279     //
280     Status = CreateOutputFile (Item->VarStr, &FileHandle);
281     if (EFI_ERROR (Status)) {
282       goto Done;
283     }
284   }
285
286   if (LibCheckVarGetFlag (&ChkPck, L"-d") != NULL) {
287     Delete = TRUE;
288   }
289       
290   //
291   // Dump variables in store
292   //
293   Status = DumpVariableStore (VarName, Delete, FileHandle);
294
295   //
296   // Done
297   //
298 Done:
299   LibCheckVarFreeVarList (&ChkPck);
300   LibUnInitializeStrings ();
301   if (FileHandle != NULL) {
302     LibCloseFile (FileHandle);
303   };
304   return Status;
305 }
306
307 EFI_STATUS
308 LoadVariableStore (
309   IN CHAR16   *VarName,
310   IN CHAR16   *FileName
311   )
312 {
313   EFI_STATUS         Status;
314   EFI_FILE_HANDLE    FileHandle;  
315   EFI_GUID           Guid;
316   UINT32             Attributes;
317   CHAR16             Name[DEBUG_NAME_SIZE / 2];
318   UINTN              NameSize;
319   CHAR16             Data[DEBUG_NAME_SIZE / 2];
320   UINTN              DataSize;
321   BOOLEAN            Found;
322   EFI_FILE_INFO      *FileInfo;
323
324   Found      = FALSE;
325   FileHandle = NULL;
326   FileInfo   = NULL;
327       
328   //
329   // Open the previous saved output file
330   //  
331   Status = LibOpenFileByName (
332              FileName,
333              &FileHandle,
334              EFI_FILE_MODE_READ,
335              0
336              );
337   if (EFI_ERROR (Status)) {
338     PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_CANNOT_OPEN_FILE), HiiHandle, L"dmpstore", FileName);
339     goto Done;
340   }
341   
342   //
343   // If the file is directory, abort
344   //
345   FileInfo = LibGetFileInfo (FileHandle);
346   if (FileInfo == NULL) {
347     Status = EFI_ABORTED;
348     PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_CANNOT_OPEN_FILE), HiiHandle, L"dmpstore", FileName);
349     goto Done;
350   } else if (FileInfo->Attribute & EFI_FILE_DIRECTORY) {
351     Status = EFI_ABORTED;
352     PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_CANNOT_OPEN_FILE), HiiHandle, L"dmpstore", FileName);
353     goto Done;
354   }
355   
356   PrintToken (STRING_TOKEN (STR_DMPSTORE_LOAD), HiiHandle);
357   do {
358     //
359     // Break the execution?
360     //
361     if (GetExecutionBreak ()) {
362       break;
363     }
364     
365     NameSize = DEBUG_NAME_SIZE;
366     DataSize = DEBUG_NAME_SIZE;
367     Status = GetFileVariable (FileHandle, &NameSize, Name, &Guid, &Attributes, &DataSize, Data);
368     if (Status == EFI_NOT_FOUND) {
369       Status = EFI_SUCCESS;
370       break;
371     }
372     if (EFI_ERROR (Status)) {
373       PrintToken (STRING_TOKEN (STR_DMPSTORE_LOAD_ERR2), HiiHandle);
374       goto Done;
375     }
376  
377     if (VarName != NULL) {
378       if (!MetaiMatch (Name, VarName)) {
379         continue;
380       }
381     }
382     
383     Found = TRUE;
384     //
385     // Dump variable name
386     //        
387     PrintToken (
388       STRING_TOKEN (STR_DMPSTORE_VAR),
389       HiiHandle,
390       AttrType[Attributes & 7],
391       &Guid,
392       Name,
393       DataSize
394       );    
395  
396     Status = RT->SetVariable (Name, &Guid, Attributes, DataSize, Data);
397     if (EFI_ERROR (Status)) {
398       PrintToken (STRING_TOKEN (STR_DMPSTORE_LOAD_ERR), HiiHandle);
399       goto Done;
400     }
401   } while (!EFI_ERROR (Status));
402
403   if (!Found) {
404     if (VarName != NULL) {
405       PrintToken (STRING_TOKEN (STR_DMPSTORE_VAR_NOT_FOUND), HiiHandle, VarName);
406     } else {
407       PrintToken (STRING_TOKEN (STR_DMPSTORE_VAR_EMPTY), HiiHandle);
408     }
409   }
410
411 Done:
412   if (FileInfo != NULL) {
413     FreePool (FileInfo); 
414   }  
415   if (FileHandle != NULL) {
416     LibCloseFile (FileHandle);
417   };
418   return Status;
419 }
420
421 EFI_STATUS
422 DumpVariableStore (
423   IN CHAR16           *VarName,
424   IN BOOLEAN          Delete,
425   IN EFI_FILE_HANDLE  FileHandle
426   )
427 {
428   EFI_STATUS  Status;
429   EFI_GUID    Guid;
430   UINT32      Attributes;
431   CHAR16      Name[DEBUG_NAME_SIZE / 2];
432   UINTN       NameSize;
433   CHAR16      Data[DEBUG_NAME_SIZE / 2];
434   UINTN       DataSize;
435   BOOLEAN     Found;
436
437   Found  = FALSE;
438   Status = EFI_SUCCESS;
439
440   if (VarName != NULL) {
441     if (Delete) {
442       PrintToken (STRING_TOKEN (STR_DMPSTORE_DELETE_ONE_VAR), HiiHandle, VarName);
443     } else if (FileHandle != NULL) {
444       PrintToken (STRING_TOKEN (STR_DMPSTORE_SAVE_ONE_VAR), HiiHandle, VarName);
445     } else {
446       PrintToken (STRING_TOKEN (STR_DMPSTORE_DUMP_ONE_VAR), HiiHandle, VarName);
447     }
448   } else {
449     if (Delete) {
450       PrintToken (STRING_TOKEN (STR_DMPSTORE_DELETE), HiiHandle);
451     } else if (FileHandle != NULL) {
452       PrintToken (STRING_TOKEN (STR_DMPSTORE_SAVE), HiiHandle);
453     } else {
454       PrintToken (STRING_TOKEN (STR_DMPSTORE_DUMP), HiiHandle);
455     }    
456   }
457
458   Name[0] = 0x0000;
459   do {
460     //
461     // Break the execution?
462     //
463     if (GetExecutionBreak ()) {
464       goto Done;
465     }
466     
467     NameSize  = DEBUG_NAME_SIZE;
468     Status    = RT->GetNextVariableName (&NameSize, Name, &Guid);
469     if (!EFI_ERROR (Status)) {
470       if (VarName != NULL) {
471         if (!MetaiMatch (Name, VarName)) {
472           continue;
473         }
474       }      
475
476       Found     = TRUE;
477       DataSize  = DEBUG_NAME_SIZE;
478       Status    = RT->GetVariable (Name, &Guid, &Attributes, &DataSize, Data);
479       if (!EFI_ERROR (Status)) {
480         //
481         // Dump variable name
482         //        
483         PrintToken (
484           STRING_TOKEN (STR_DMPSTORE_VAR),
485           HiiHandle,
486           AttrType[Attributes & 7],
487           &Guid,
488           Name,
489           DataSize
490           );
491         if (Delete) {
492           //
493           // Delete variables
494           //
495           DataSize = 0;
496           Status   = RT->SetVariable (Name, &Guid, Attributes, DataSize, Data);
497           if (EFI_ERROR (Status)) {
498             PrintToken (STRING_TOKEN (STR_DMPSTORE_DELETE_ERR), HiiHandle);
499             goto Done;
500           } else {
501             Name[0] = 0x0000;
502           }
503         } else if (FileHandle != NULL) {
504           //
505           // Save variables to output file
506           //
507           Status = SetFileVariable (FileHandle, NameSize, Name, &Guid, Attributes, DataSize, Data);
508           if (EFI_ERROR (Status)) {
509             PrintToken (STRING_TOKEN (STR_DMPSTORE_SAVE_ERR), HiiHandle);
510             goto Done;
511           }
512         } else {
513           //
514           // Dump variable data
515           //
516           PrivateDumpHex (2, 0, DataSize, Data);
517         }
518       }
519     } else if (Status == EFI_NOT_FOUND) {
520       Status = EFI_SUCCESS;
521       break;
522     }
523   } while (!EFI_ERROR (Status));
524
525   if (!Found) {
526     if (VarName != NULL) {
527       PrintToken (STRING_TOKEN (STR_DMPSTORE_VAR_NOT_FOUND), HiiHandle, VarName);
528     } else {
529       PrintToken (STRING_TOKEN (STR_DMPSTORE_VAR_EMPTY), HiiHandle);
530     }
531   }
532
533 Done:
534   return Status;
535 }
536
537 EFI_STATUS
538 CreateOutputFile (
539   IN CHAR16           *FileName, 
540   OUT EFI_FILE_HANDLE *FileHandle
541   )
542 {
543   EFI_STATUS     Status;
544   EFI_FILE_INFO  *FileInfo;
545
546   FileInfo = NULL;
547   
548   //
549   // Delete the output file first if it exist
550   //  
551   Status = LibOpenFileByName (
552              FileName,
553              FileHandle,
554              EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE,
555              0
556              );
557   if (!EFI_ERROR (Status)) {
558     //
559     // If the existing file is directory, abort
560     //
561     FileInfo = LibGetFileInfo (*FileHandle);
562     if (FileInfo == NULL) {
563       Status = EFI_ABORTED;
564       goto Done;
565     } else if (FileInfo->Attribute & EFI_FILE_DIRECTORY) {
566       Status = EFI_ABORTED;
567       goto Done;
568     }    
569     LibDeleteFile (*FileHandle);
570   } else if (Status != EFI_NOT_FOUND) {
571     goto Done;
572   }
573
574   //
575   // Create the output file
576   //
577   Status = LibOpenFileByName (
578              FileName,
579              FileHandle,
580              EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE,
581              0
582              );
583   
584 Done: 
585   if (FileInfo != NULL) {
586     FreePool (FileInfo); 
587   }
588   if (EFI_ERROR (Status)) {
589     PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_CANNOT_OPEN_FILE), HiiHandle, L"dmpstore", FileName);
590   }
591   return Status;
592 }
593
594 EFI_STATUS
595 GetFileVariable (
596   IN EFI_FILE_HANDLE FileHandle,
597   IN OUT UINTN       *VariableNameSize,
598   IN CHAR16          *VariableName,
599   IN EFI_GUID        *VendorGuid,
600   OUT UINT32         *Attributes,
601   IN OUT UINTN       *DataSize,
602   OUT VOID           *Data
603   )
604 {
605   EFI_STATUS  Status;
606   UINTN       BufferSize;
607   UINTN       NameSize;
608   UINTN       Size;
609   
610   NameSize   = 0;
611   BufferSize = sizeof (UINT32);
612   Status     = LibReadFile (FileHandle, &BufferSize, &NameSize);
613   if (!EFI_ERROR (Status) && (BufferSize == 0)) {
614     return EFI_NOT_FOUND; // End of file
615   }
616   if (EFI_ERROR (Status) || (BufferSize != sizeof (UINT32)) || 
617       (NameSize > *VariableNameSize)) {
618     return EFI_ABORTED;
619   }
620   
621   BufferSize = NameSize;
622   Status     = LibReadFile (FileHandle, &BufferSize, VariableName);
623   if (EFI_ERROR (Status) || (BufferSize != NameSize)) {
624     return EFI_ABORTED;
625   }
626
627   BufferSize = sizeof (EFI_GUID);
628   Status     = LibReadFile (FileHandle, &BufferSize, VendorGuid);
629   if (EFI_ERROR (Status) || (BufferSize != sizeof (EFI_GUID))) {
630     return EFI_ABORTED;
631   }
632
633   BufferSize = sizeof (UINT32);
634   Status     = LibReadFile (FileHandle, &BufferSize, Attributes);
635   if (EFI_ERROR (Status) || (BufferSize != sizeof (UINT32))) {
636     return EFI_ABORTED;
637   }
638
639   Size       = 0;
640   BufferSize = sizeof (UINT32);
641   Status     = LibReadFile (FileHandle, &BufferSize, &Size);
642   if (EFI_ERROR (Status) || (BufferSize != sizeof (UINT32)) || 
643       (Size > *DataSize)) {
644     return EFI_ABORTED;
645   }
646   
647   BufferSize = Size;
648   Status     = LibReadFile (FileHandle, &BufferSize, Data);
649   if (EFI_ERROR (Status) || (BufferSize != Size)) {
650     return EFI_ABORTED;
651   }
652   
653   *VariableNameSize = NameSize;
654   *DataSize = Size;
655   return EFI_SUCCESS;
656 }
657
658 EFI_STATUS
659 SetFileVariable (
660   IN EFI_FILE_HANDLE FileHandle,
661   IN UINTN           VariableNameSize,
662   IN CHAR16          *VariableName,
663   IN EFI_GUID        *VendorGuid,
664   IN UINT32          Attributes,
665   IN UINTN           DataSize,
666   IN VOID            *Data  
667   )
668 {
669   EFI_STATUS  Status;
670   UINTN       BufferSize;
671
672   BufferSize = sizeof (UINT32);
673   Status = LibWriteFile (FileHandle, &BufferSize, &VariableNameSize);
674   if (EFI_ERROR (Status)) {
675     return Status;
676   }
677   
678   BufferSize = VariableNameSize;
679   Status = LibWriteFile (FileHandle, &BufferSize, VariableName);
680   if (EFI_ERROR (Status)) {
681     return Status;
682   }
683
684   BufferSize = sizeof (EFI_GUID);
685   Status = LibWriteFile (FileHandle, &BufferSize, VendorGuid);
686   if (EFI_ERROR (Status)) {
687     return Status;
688   }
689
690   BufferSize = sizeof (UINT32);
691   Status = LibWriteFile (FileHandle, &BufferSize, &Attributes);
692   if (EFI_ERROR (Status)) {
693     return Status;
694   }
695
696   BufferSize = sizeof (UINT32);
697   Status = LibWriteFile (FileHandle, &BufferSize, &DataSize);
698   if (EFI_ERROR (Status)) {
699     return Status;
700   }
701
702   BufferSize = DataSize;
703   Status = LibWriteFile (FileHandle, &BufferSize, Data);
704
705   return Status;
706 }
707
708 EFI_STATUS
709 InitializeDumpStoreGetLineHelp (
710   OUT CHAR16                **Str
711   )
712 /*++
713
714 Routine Description:
715
716   Get this command's line help
717
718 Arguments:
719
720   Str - The line help
721
722 Returns:
723
724   EFI_SUCCESS   - Success
725
726 --*/
727 {
728   return LibCmdGetStringByToken (STRING_ARRAY_NAME, &EfiDmpstoreGuid, STRING_TOKEN (STR_DMPSTORE_LINEHELP), Str);
729 }