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