pointer verification (not NULL) and buffer overrun fixes.
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / Bcfg.c
1 /** @file\r
2   Main file for bcfg shell Debug1 function.\r
3 \r
4   Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
5   This program and the accompanying materials\r
6   are licensed and made available under the terms and conditions of the BSD License\r
7   which accompanies this distribution.  The full text of the license may be found at\r
8   http://opensource.org/licenses/bsd-license.php\r
9 \r
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 \r
13 **/\r
14 \r
15 #include "UefiShellDebug1CommandsLib.h"\r
16 #include <Guid/GlobalVariable.h>\r
17 #include <Library/PrintLib.h>\r
18 #include <Library/HandleParsingLib.h>\r
19 #include <Library/DevicePathLib.h>\r
20 \r
21 typedef enum {\r
22   BcfgTargetBootOrder    = 0,\r
23   BcfgTargetDriverOrder  = 1,\r
24   BcfgTargetMax          = 2\r
25 } BCFG_OPERATION_TARGET;\r
26 \r
27 typedef enum {\r
28   BcfgTypeDump       = 0,\r
29   BcfgTypeAdd        = 1,\r
30   BcfgTypeAddp       = 2,\r
31   BcfgTypeAddh       = 3,\r
32   BcfgTypeRm         = 4,\r
33   BcfgTypeMv         = 5,\r
34   BcfgTypeOpt        = 6,\r
35   BcfgTypeMax        = 7\r
36 } BCFG_OPERATION_TYPE;\r
37 \r
38 typedef struct {\r
39   BCFG_OPERATION_TARGET Target;\r
40   BCFG_OPERATION_TYPE   Type;\r
41   UINT16                Number1;\r
42   UINT16                Number2;\r
43   UINTN                 HandleIndex;\r
44   CHAR16                *FileName;\r
45   CHAR16                *Description;\r
46   UINT16                *Order;\r
47   CONST CHAR16          *OptData;\r
48 } BGFG_OPERATION;\r
49 \r
50 /**\r
51   Function to add a option.\r
52 \r
53   @param[in] Position       The position to add Target at.\r
54   @param[in] File           The file to make the target.\r
55   @param[in] Desc           The description text.\r
56   @param[in] CurrentOrder   The pointer to the current order of items.\r
57   @param[in] OrderCount     The number if items in CurrentOrder.\r
58   @param[in] Target         The info on the option to add.\r
59   @param[in] UseHandle      TRUE to use HandleNumber, FALSE to use File and Desc.\r
60   @param[in] UsePath        TRUE to convert to devicepath.\r
61   @param[in] HandleNumber   The handle number to add.\r
62 \r
63   @retval SHELL_SUCCESS             The operation was successful.\r
64   @retval SHELL_INVALID_PARAMETER   A parameter was invalid.\r
65 **/\r
66 SHELL_STATUS\r
67 EFIAPI\r
68 BcfgAddDebug1(\r
69   IN       UINTN                  Position,\r
70   IN CONST CHAR16                 *File,\r
71   IN CONST CHAR16                 *Desc,\r
72   IN CONST UINT16                 *CurrentOrder,\r
73   IN CONST UINTN                  OrderCount,\r
74   IN CONST BCFG_OPERATION_TARGET  Target,\r
75   IN CONST BOOLEAN                UseHandle,\r
76   IN CONST BOOLEAN                UsePath,\r
77   IN CONST UINTN                  HandleNumber\r
78   )\r
79 {\r
80   EFI_STATUS                Status;\r
81   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
82   EFI_DEVICE_PATH_PROTOCOL  *FilePath;\r
83   EFI_DEVICE_PATH_PROTOCOL  *FileNode;\r
84   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
85   CHAR16                    *Str;\r
86   CONST CHAR16              *StringWalker;\r
87   UINT8                     *TempByteBuffer;\r
88   UINT8                     *TempByteStart;\r
89   EFI_SHELL_FILE_INFO       *Arg;\r
90   EFI_SHELL_FILE_INFO       *FileList;\r
91   CHAR16                    OptionStr[40];\r
92   UINTN                     DescSize, FilePathSize;\r
93   BOOLEAN                   Found;\r
94   UINTN                     TargetLocation;\r
95   UINTN                     Index;\r
96   EFI_HANDLE                *Handles;\r
97   EFI_HANDLE                CurHandle;\r
98   UINTN                     DriverBindingHandleCount;\r
99   UINTN                     ParentControllerHandleCount;\r
100   UINTN                     ChildControllerHandleCount;\r
101   SHELL_STATUS              ShellStatus;\r
102   UINT16                    *NewOrder;\r
103   UINT64                    Intermediate;\r
104 \r
105   if (!UseHandle) {\r
106     if (File == NULL || Desc == NULL) {\r
107       return (SHELL_INVALID_PARAMETER);\r
108     }\r
109   } else {\r
110     if (HandleNumber == 0) {\r
111       return (SHELL_INVALID_PARAMETER);\r
112     }\r
113   }\r
114 \r
115   if (Position > OrderCount) {\r
116     Position =  OrderCount;\r
117   }\r
118 \r
119   Str             = NULL;\r
120   FilePath        = NULL;\r
121   FileNode        = NULL;\r
122   FileList        = NULL;\r
123   Handles         = NULL;\r
124   ShellStatus     = SHELL_SUCCESS;\r
125   TargetLocation  = 0xFFFF;\r
126 \r
127   if (UseHandle) {\r
128     Status = ShellConvertStringToUint64(File, &Intermediate, TRUE, FALSE);\r
129     CurHandle = ConvertHandleIndexToHandle((UINTN)Intermediate);\r
130     if (CurHandle == NULL || EFI_ERROR(Status)) {\r
131       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, File);\r
132       ShellStatus = SHELL_INVALID_PARAMETER;\r
133     } else {\r
134       //\r
135       //Make sure that the handle should point to a real controller\r
136       //\r
137       Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (\r
138                  CurHandle,\r
139                  &DriverBindingHandleCount,\r
140                  NULL);\r
141 \r
142       Status = PARSE_HANDLE_DATABASE_PARENTS (\r
143                  CurHandle,\r
144                  &ParentControllerHandleCount,\r
145                  NULL);\r
146 \r
147       Status = ParseHandleDatabaseForChildControllers (\r
148                  CurHandle,\r
149                  &ChildControllerHandleCount,\r
150                  NULL);\r
151 \r
152       if (DriverBindingHandleCount > 0\r
153             || ParentControllerHandleCount > 0\r
154             || ChildControllerHandleCount > 0) {\r
155         FilePath = NULL;\r
156         Status = gBS->HandleProtocol (\r
157                    CurHandle,\r
158                    &gEfiDevicePathProtocolGuid,\r
159                    (VOID**)&FilePath);\r
160       }\r
161       if (EFI_ERROR (Status)) {\r
162         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellDebug1HiiHandle, Intermediate);\r
163         ShellStatus = SHELL_INVALID_PARAMETER;\r
164       }\r
165     }\r
166   } else {\r
167     //\r
168     // Get file info\r
169     //\r
170     ShellOpenFileMetaArg ((CHAR16*)File, EFI_FILE_MODE_READ, &FileList);\r
171 \r
172     if (FileList == NULL) {\r
173       //\r
174       // If filename matched nothing fail\r
175       //\r
176       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, File);\r
177       ShellStatus = SHELL_INVALID_PARAMETER;\r
178     } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {\r
179       //\r
180       // If filename expanded to multiple names, fail\r
181       //\r
182       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellDebug1HiiHandle, File);\r
183       ShellStatus = SHELL_INVALID_PARAMETER;\r
184     } else {\r
185       Arg = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link);\r
186       if (EFI_ERROR(Arg->Status)) {\r
187         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellDebug1HiiHandle, File, Arg->Status);\r
188         ShellStatus = SHELL_INVALID_PARAMETER;\r
189       } else {\r
190         //\r
191         // Build FilePath to the filename\r
192         //\r
193 \r
194         //\r
195         // get the device path\r
196         //\r
197         DevicePath = mEfiShellProtocol->GetDevicePathFromFilePath(Arg->FullName);\r
198         if (DevicePath == NULL) {\r
199           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellDebug1HiiHandle, Arg->FullName);\r
200           ShellStatus = SHELL_UNSUPPORTED;\r
201         } else {\r
202           if (UsePath) {\r
203             DevPath = DevicePath;\r
204             while (!IsDevicePathEnd(DevPath)) {\r
205               if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&\r
206                 (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {\r
207 \r
208                 //\r
209                 // If we find it use it instead\r
210                 //\r
211                 DevicePath = DevPath;\r
212                 break;\r
213               }\r
214               DevPath = NextDevicePathNode(DevPath);\r
215             }\r
216             //\r
217             // append the file\r
218             //\r
219             for(StringWalker=Arg->FullName; *StringWalker != CHAR_NULL && *StringWalker != ':'; StringWalker++);\r
220             FileNode = FileDevicePath(NULL, StringWalker+1);\r
221             FilePath = AppendDevicePath(DevicePath, FileNode);\r
222             FreePool(FileNode);\r
223           } else {\r
224             FilePath = DuplicateDevicePath(DevicePath);\r
225           }\r
226 \r
227           FreePool(DevicePath);\r
228         }\r
229       }\r
230     }\r
231   }\r
232 \r
233 \r
234   if (ShellStatus == SHELL_SUCCESS) {\r
235     //\r
236     // Find a free target ,a brute force implementation\r
237     //\r
238     Found = FALSE;\r
239     for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) {\r
240       Found = TRUE;\r
241       for (Index=0; Index < OrderCount; Index++) {\r
242         if (CurrentOrder[Index] == TargetLocation) {\r
243           Found = FALSE;\r
244           break;\r
245         }\r
246       }\r
247 \r
248       if (Found) {\r
249         break;\r
250       }\r
251     }\r
252 \r
253     if (TargetLocation == 0xFFFF) {\r
254       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellDebug1HiiHandle);\r
255     } else {\r
256       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellDebug1HiiHandle, TargetLocation);\r
257     }\r
258   }\r
259 \r
260   if (ShellStatus == SHELL_SUCCESS) {\r
261     //\r
262     // Add the option\r
263     //\r
264     DescSize = StrSize(Desc);\r
265     FilePathSize = GetDevicePathSize (FilePath);\r
266 \r
267     TempByteBuffer = AllocateZeroPool(sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize);\r
268     if (TempByteBuffer != NULL) {\r
269       TempByteStart  = TempByteBuffer;\r
270       *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE;      // Attributes\r
271       TempByteBuffer += sizeof (UINT32);\r
272 \r
273       *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize;    // FilePathListLength\r
274       TempByteBuffer += sizeof (UINT16);\r
275 \r
276       CopyMem (TempByteBuffer, Desc, DescSize);\r
277       TempByteBuffer += DescSize;\r
278       CopyMem (TempByteBuffer, FilePath, FilePathSize);\r
279 \r
280       UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", TargetLocation);\r
281       Status = gRT->SetVariable (\r
282             OptionStr,\r
283             &gEfiGlobalVariableGuid,\r
284             EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
285             sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize,\r
286             TempByteStart\r
287            );\r
288 \r
289       FreePool(TempByteStart);\r
290     } else {\r
291       Status = EFI_OUT_OF_RESOURCES;\r
292     }\r
293 \r
294     if (EFI_ERROR(Status)) {\r
295       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellDebug1HiiHandle, OptionStr, Status);\r
296     } else {\r
297       NewOrder = AllocateZeroPool((OrderCount+1)*sizeof(NewOrder[0]));\r
298       ASSERT(NewOrder != NULL);\r
299       CopyMem(NewOrder, CurrentOrder, (OrderCount)*sizeof(NewOrder[0]));\r
300 \r
301       //\r
302       // Insert target into order list\r
303       //\r
304       for (Index=OrderCount; Index > Position; Index--) {\r
305         NewOrder[Index] = NewOrder[Index-1];\r
306       }\r
307 \r
308       NewOrder[Position] = (UINT16) TargetLocation;\r
309       Status = gRT->SetVariable (\r
310         Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder",\r
311         &gEfiGlobalVariableGuid,\r
312         EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
313         (OrderCount+1) * sizeof(UINT16),\r
314         NewOrder\r
315        );\r
316 \r
317       FreePool(NewOrder);\r
318 \r
319       if (EFI_ERROR(Status)) {\r
320         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellDebug1HiiHandle, Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder", Status);\r
321         ShellStatus = SHELL_INVALID_PARAMETER;\r
322       } else {\r
323         Print (L"bcfg: Add %s as %x\n", OptionStr, Position);\r
324       }\r
325     }\r
326   }\r
327   if (FileNode != NULL) {\r
328     FreePool (FileNode);\r
329   }\r
330 \r
331 //\r
332 //If always Free FilePath, will free devicepath in system when use "addh"\r
333 //\r
334 \r
335   if (FilePath!=NULL && !UseHandle) {\r
336     FreePool (FilePath);\r
337   }\r
338 \r
339   if (Str != NULL) {\r
340     FreePool(Str);\r
341   }\r
342 \r
343   if (Handles != NULL) {\r
344     FreePool (Handles);\r
345   }\r
346 \r
347   if (FileList != NULL) {\r
348     ShellCloseFileMetaArg (&FileList);\r
349   }\r
350 \r
351   return (ShellStatus);\r
352 }\r
353 \r
354 /**\r
355   Funciton to remove an item.\r
356 \r
357   @param[in] Target         The target item to move.\r
358   @param[in] CurrentOrder   The pointer to the current order of items.\r
359   @param[in] OrderCount     The number if items in CurrentOrder.\r
360   @param[in] Location       The current location of the Target.\r
361 \r
362   @retval SHELL_SUCCESS             The operation was successful.\r
363   @retval SHELL_INVALID_PARAMETER   A parameter was invalid.\r
364 **/\r
365 SHELL_STATUS\r
366 EFIAPI\r
367 BcfgRemoveDebug1(\r
368   IN CONST BCFG_OPERATION_TARGET  Target,\r
369   IN CONST UINT16                 *CurrentOrder,\r
370   IN CONST UINTN                  OrderCount,\r
371   IN CONST UINT16                  Location\r
372   )\r
373 {\r
374   CHAR16      VariableName[12];\r
375   UINT16      *NewOrder;\r
376   EFI_STATUS  Status;\r
377   UINTN       LoopVar;\r
378   UINTN       NewCount;\r
379 \r
380   UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", Location);\r
381   Status = gRT->SetVariable(\r
382     VariableName,\r
383     (EFI_GUID*)&gEfiGlobalVariableGuid,\r
384     EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
385     0,\r
386     NULL);\r
387   if (EFI_ERROR(Status)) {\r
388     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellDebug1HiiHandle, VariableName, Status);\r
389     return (SHELL_INVALID_PARAMETER);\r
390   }\r
391   NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0]));\r
392   if (NewOrder != NULL) {\r
393     NewCount = OrderCount;\r
394     CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0]));\r
395     for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++){\r
396       if (NewOrder[LoopVar] == Location) {\r
397         CopyMem(NewOrder+LoopVar, NewOrder+LoopVar+1, (OrderCount - LoopVar - 1)*sizeof(CurrentOrder[0]));\r
398         NewCount--;\r
399       }\r
400     }\r
401     Status = gRT->SetVariable(\r
402       Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",\r
403       (EFI_GUID*)&gEfiGlobalVariableGuid,\r
404       EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
405       NewCount*sizeof(NewOrder[0]),\r
406       NewOrder);\r
407     FreePool(NewOrder);\r
408   } else {\r
409     Status = EFI_OUT_OF_RESOURCES;\r
410   }\r
411   if (EFI_ERROR(Status)) {\r
412     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellDebug1HiiHandle, Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status);\r
413     return (SHELL_INVALID_PARAMETER);\r
414   }\r
415   return (SHELL_SUCCESS);\r
416 }\r
417 \r
418 /**\r
419   Funciton to move a item to another location.\r
420 \r
421   @param[in] Target         The target item to move.\r
422   @param[in] CurrentOrder   The pointer to the current order of items.\r
423   @param[in] OrderCount     The number if items in CurrentOrder.\r
424   @param[in] OldLocation    The current location of the Target.\r
425   @param[in] NewLocation    The desired location of the Target.\r
426 \r
427   @retval SHELL_SUCCESS             The operation was successful.\r
428   @retval SHELL_INVALID_PARAMETER   A parameter was invalid.\r
429 **/\r
430 SHELL_STATUS\r
431 EFIAPI\r
432 BcfgMoveDebug1(\r
433   IN CONST BCFG_OPERATION_TARGET  Target,\r
434   IN CONST UINT16                 *CurrentOrder,\r
435   IN CONST UINTN                  OrderCount,\r
436   IN CONST UINT16                 OldLocation,\r
437   IN CONST UINT16                 NewLocation\r
438   )\r
439 {\r
440   UINT16            *NewOrder;\r
441   EFI_STATUS        Status;\r
442   UINT16            Temp;\r
443 \r
444   NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0]));\r
445   ASSERT(NewOrder != NULL);\r
446 \r
447   Temp = CurrentOrder[OldLocation];\r
448   CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0]));\r
449   CopyMem(NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof(CurrentOrder[0]));\r
450   CopyMem(NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof(CurrentOrder[0]));\r
451   NewOrder[NewLocation] = Temp;\r
452 \r
453 \r
454   Status = gRT->SetVariable(\r
455     Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",\r
456     (EFI_GUID*)&gEfiGlobalVariableGuid,\r
457     EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
458     OrderCount*sizeof(CurrentOrder[0]),\r
459     NewOrder);\r
460 \r
461   FreePool(NewOrder);\r
462 \r
463   if (EFI_ERROR(Status)) {\r
464     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellDebug1HiiHandle, Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status);\r
465     return (SHELL_INVALID_PARAMETER);\r
466   }\r
467   return (SHELL_SUCCESS);\r
468 }\r
469 \r
470 SHELL_STATUS\r
471 EFIAPI\r
472 BcfgAddOptDebug1(\r
473   IN CONST CHAR16                 *OptData,\r
474   IN CONST BCFG_OPERATION_TARGET  Target\r
475   )\r
476 {\r
477   ASSERT(OptData != NULL);\r
478   return SHELL_SUCCESS;\r
479 }\r
480 \r
481 /**\r
482   Function to dump the Bcfg information.\r
483 \r
484   @param[in] Op             The operation.\r
485   @param[in] OrderCount     How many to dump.\r
486   @param[in] CurrentOrder   The pointer to the current order of items.\r
487   @param[in] VerboseOutput  TRUE for extra output.  FALSE otherwise.\r
488 \r
489   @retval SHELL_SUCCESS           The dump was successful.\r
490   @retval SHELL_INVALID_PARAMETER A parameter was invalid.\r
491 **/\r
492 SHELL_STATUS\r
493 EFIAPI\r
494 BcfgDisplayDumpDebug1(\r
495   IN CONST CHAR16   *Op,\r
496   IN CONST UINTN    OrderCount,\r
497   IN CONST UINT16   *CurrentOrder,\r
498   IN CONST BOOLEAN  VerboseOutput\r
499   )\r
500 {\r
501   EFI_STATUS  Status;\r
502   UINT8       *Buffer;\r
503   UINTN       BufferSize;\r
504   CHAR16      VariableName[12];\r
505   UINTN       LoopVar;\r
506   UINTN       LoopVar2;\r
507   CHAR16      *DevPathString;\r
508   VOID        *DevPath;\r
509 \r
510   if (OrderCount == 0) {\r
511     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_BCFG_NONE), gShellDebug1HiiHandle);\r
512     return (SHELL_SUCCESS);\r
513   }\r
514 \r
515   for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++) {\r
516     Buffer      = NULL;\r
517     BufferSize  = 0;\r
518     UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]);\r
519 \r
520     Status = gRT->GetVariable(\r
521         VariableName,\r
522         (EFI_GUID*)&gEfiGlobalVariableGuid,\r
523         NULL,\r
524         &BufferSize,\r
525         Buffer);\r
526     if (Status == EFI_BUFFER_TOO_SMALL) {\r
527       Buffer = AllocateZeroPool(BufferSize);\r
528       Status = gRT->GetVariable(\r
529           VariableName,\r
530           (EFI_GUID*)&gEfiGlobalVariableGuid,\r
531           NULL,\r
532           &BufferSize,\r
533           Buffer);\r
534     }\r
535 \r
536     if (EFI_ERROR(Status) || Buffer == NULL) {\r
537       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellDebug1HiiHandle, VariableName, Status);\r
538       return (SHELL_INVALID_PARAMETER);\r
539     }\r
540 \r
541     DevPath = AllocateZeroPool(*(UINT16*)(Buffer+4));\r
542     CopyMem(DevPath, Buffer+6+StrSize((CHAR16*)(Buffer+6)), *(UINT16*)(Buffer+4));\r
543     DevPathString = gDevPathToText->ConvertDevicePathToText(DevPath, TRUE, FALSE);\r
544     ShellPrintHiiEx(\r
545       -1,\r
546       -1,\r
547       NULL,\r
548       STRING_TOKEN(STR_BCFG_LOAD_OPTIONS),\r
549       gShellDebug1HiiHandle,\r
550       LoopVar,\r
551       VariableName,\r
552       (CHAR16*)(Buffer+6),\r
553       DevPathString,\r
554       (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6) <= BufferSize?L'N':L'Y');\r
555     if (VerboseOutput) {\r
556       for (LoopVar2 = (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6);LoopVar2<BufferSize;LoopVar2++){\r
557         ShellPrintEx(\r
558           -1,\r
559           -1,\r
560           NULL,\r
561           L"%02x",\r
562           Buffer[LoopVar2]);\r
563       }\r
564       ShellPrintEx(\r
565         -1,\r
566         -1,\r
567         NULL,\r
568         L"\r\n");\r
569     }\r
570 \r
571     if (Buffer != NULL) {\r
572       FreePool(Buffer);\r
573     }\r
574     if (DevPath != NULL) {\r
575       FreePool(DevPath);\r
576     }\r
577     if (DevPathString != NULL) {\r
578       FreePool(DevPathString);\r
579     }\r
580   }\r
581   return (SHELL_SUCCESS);\r
582 }\r
583 \r
584 /**\r
585   Function to initialize the BCFG operation structure.\r
586 \r
587   @param[in] Struct   The stuct to initialize.\r
588 **/\r
589 VOID\r
590 EFIAPI\r
591 InitBcfgStructDebug1(\r
592   IN BGFG_OPERATION *Struct\r
593   )\r
594 {\r
595   ASSERT(Struct != NULL);\r
596   Struct->Target      = BcfgTargetMax;\r
597   Struct->Type        = BcfgTypeMax;\r
598   Struct->Number1     = 0;\r
599   Struct->Number2     = 0;\r
600   Struct->HandleIndex = 0;\r
601   Struct->FileName    = NULL;\r
602   Struct->Description = NULL;\r
603   Struct->Order       = NULL;\r
604   Struct->OptData     = NULL;\r
605 }\r
606 \r
607 \r
608 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
609   {L"-v", TypeFlag},\r
610   {L"-opt", TypeMaxValue},\r
611   {NULL, TypeMax}\r
612   };\r
613 \r
614 /**\r
615   Function for 'bcfg' command.\r
616 \r
617   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
618   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
619 **/\r
620 SHELL_STATUS\r
621 EFIAPI\r
622 ShellCommandRunBcfg (\r
623   IN EFI_HANDLE        ImageHandle,\r
624   IN EFI_SYSTEM_TABLE  *SystemTable\r
625   )\r
626 {\r
627   EFI_STATUS            Status;\r
628   LIST_ENTRY            *Package;\r
629   CHAR16                *ProblemParam;\r
630   SHELL_STATUS          ShellStatus;\r
631   UINTN                 ParamNumber;\r
632   CONST CHAR16          *CurrentParam;\r
633   BGFG_OPERATION        CurrentOperation;\r
634   UINTN                 Length;\r
635   UINT64                Intermediate;\r
636 \r
637   Length              = 0;\r
638   ProblemParam        = NULL;\r
639   Package             = NULL;\r
640   ShellStatus         = SHELL_SUCCESS;\r
641 \r
642   InitBcfgStructDebug1(&CurrentOperation);\r
643 \r
644   //\r
645   // initialize the shell lib (we must be in non-auto-init...)\r
646   //\r
647   Status = ShellInitialize();\r
648   ASSERT_EFI_ERROR(Status);\r
649 \r
650   Status = CommandInit();\r
651   ASSERT_EFI_ERROR(Status);\r
652 \r
653   //\r
654   // parse the command line\r
655   //\r
656   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
657   if (EFI_ERROR(Status)) {\r
658     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
659       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam);\r
660       FreePool(ProblemParam);\r
661       ShellStatus = SHELL_INVALID_PARAMETER;\r
662     } else {\r
663       ASSERT(FALSE);\r
664     }\r
665   } else {\r
666     //\r
667     // Read in if we are doing -OPT\r
668     //\r
669     if (ShellCommandLineGetFlag(Package, L"-opt")) {\r
670       CurrentOperation.OptData = ShellCommandLineGetValue(Package, L"-opt");\r
671       if (CurrentOperation.OptData == NULL) {\r
672         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"-opt");\r
673         ShellStatus = SHELL_INVALID_PARAMETER;\r
674       }\r
675       CurrentOperation.Type = BcfgTypeOpt;\r
676     }\r
677 \r
678     //\r
679     // small block to read the target of the operation\r
680     //\r
681     if ((ShellCommandLineGetCount(Package) < 3 && CurrentOperation.Type != BcfgTypeOpt) ||\r
682         (ShellCommandLineGetCount(Package) < 2 && CurrentOperation.Type == BcfgTypeOpt)\r
683        ){\r
684       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);\r
685       ShellStatus = SHELL_INVALID_PARAMETER;\r
686     } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"driver") == 0) {\r
687       CurrentOperation.Target = BcfgTargetDriverOrder;\r
688     } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"boot") == 0) {\r
689       CurrentOperation.Target = BcfgTargetBootOrder;\r
690     } else {\r
691       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellDebug1HiiHandle);\r
692       ShellStatus = SHELL_INVALID_PARAMETER;\r
693     }\r
694 \r
695 \r
696     //\r
697     // Read in the boot or driver order environment variable (not needed for opt)\r
698     //\r
699     if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type != BcfgTypeOpt) {\r
700       Length = 0;\r
701       Status = gRT->GetVariable(\r
702         CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",\r
703         (EFI_GUID*)&gEfiGlobalVariableGuid,\r
704         NULL,\r
705         &Length,\r
706         CurrentOperation.Order);\r
707       if (Status == EFI_BUFFER_TOO_SMALL) {\r
708         CurrentOperation.Order = AllocateZeroPool(Length+(4*sizeof(CurrentOperation.Order[0])));\r
709         Status = gRT->GetVariable(\r
710           CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",\r
711           (EFI_GUID*)&gEfiGlobalVariableGuid,\r
712           NULL,\r
713           &Length,\r
714           CurrentOperation.Order);\r
715       }\r
716     }\r
717 \r
718     //\r
719     // large block to read the type of operation and verify parameter types for the info.\r
720     //\r
721     if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {\r
722       for (ParamNumber = 2 ; ParamNumber < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) {\r
723         CurrentParam = ShellCommandLineGetRawValue(Package, ParamNumber);\r
724         if        (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"dump") == 0)    {\r
725           CurrentOperation.Type = BcfgTypeDump;\r
726         } else if (ShellCommandLineGetFlag(Package, L"-v")) {\r
727           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"-v (without dump)");\r
728           ShellStatus = SHELL_INVALID_PARAMETER;\r
729         } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"add") == 0)     {\r
730           if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {\r
731             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);\r
732             ShellStatus = SHELL_INVALID_PARAMETER;\r
733           }\r
734           CurrentOperation.Type = BcfgTypeAdd;\r
735           CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
736           if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
737             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);\r
738             ShellStatus = SHELL_INVALID_PARAMETER;\r
739           } else {\r
740             Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
741             CurrentOperation.Number1     = (UINT16)Intermediate;\r
742             ASSERT(CurrentOperation.FileName == NULL);\r
743             CurrentOperation.FileName    = StrnCatGrow(&CurrentOperation.FileName   , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
744             ASSERT(CurrentOperation.Description == NULL);\r
745             CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
746           }\r
747         } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addp") == 0)    {\r
748           if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {\r
749             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);\r
750             ShellStatus = SHELL_INVALID_PARAMETER;\r
751           }\r
752           CurrentOperation.Type = BcfgTypeAddp;\r
753           CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
754           if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
755             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);\r
756             ShellStatus = SHELL_INVALID_PARAMETER;\r
757           } else {\r
758             Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
759             CurrentOperation.Number1     = (UINT16)Intermediate;\r
760             ASSERT(CurrentOperation.FileName == NULL);\r
761             CurrentOperation.FileName    = StrnCatGrow(&CurrentOperation.FileName   , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
762             ASSERT(CurrentOperation.Description == NULL);\r
763             CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
764           }\r
765         } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addh") == 0)    {\r
766           if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {\r
767             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);\r
768             ShellStatus = SHELL_INVALID_PARAMETER;\r
769           }\r
770           CurrentOperation.Type = BcfgTypeAddh;\r
771           CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
772           if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
773             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);\r
774             ShellStatus = SHELL_INVALID_PARAMETER;\r
775           } else {\r
776             Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
777             CurrentOperation.Number1     = (UINT16)Intermediate;\r
778             CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
779             if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
780               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);\r
781               ShellStatus = SHELL_INVALID_PARAMETER;\r
782             } else {\r
783               Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
784               CurrentOperation.HandleIndex = (UINT16)Intermediate;\r
785               ASSERT(CurrentOperation.Description == NULL);\r
786               CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
787             }\r
788           }\r
789         } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"rm") == 0)      {\r
790           if ((ParamNumber + 1) >= ShellCommandLineGetCount(Package)) {\r
791             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);\r
792             ShellStatus = SHELL_INVALID_PARAMETER;\r
793           }\r
794           CurrentOperation.Type = BcfgTypeRm;\r
795           CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
796           if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
797             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);\r
798             ShellStatus = SHELL_INVALID_PARAMETER;\r
799           } else {\r
800             Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
801             CurrentOperation.Number1     = (UINT16)Intermediate;\r
802             if (CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))){\r
803               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellDebug1HiiHandle, Length / sizeof(CurrentOperation.Order[0]));\r
804               ShellStatus = SHELL_INVALID_PARAMETER;\r
805             }\r
806           }\r
807         } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"mv") == 0)      {\r
808           if ((ParamNumber + 2) >= ShellCommandLineGetCount(Package)) {\r
809             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);\r
810             ShellStatus = SHELL_INVALID_PARAMETER;\r
811           }\r
812           CurrentOperation.Type = BcfgTypeMv;\r
813           CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
814           if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
815             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);\r
816             ShellStatus = SHELL_INVALID_PARAMETER;\r
817           } else {\r
818             Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
819             CurrentOperation.Number1     = (UINT16)Intermediate;\r
820             if (CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))){\r
821               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellDebug1HiiHandle, Length / sizeof(CurrentOperation.Order[0]));\r
822               ShellStatus = SHELL_INVALID_PARAMETER;\r
823             }\r
824             CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
825             if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
826               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);\r
827               ShellStatus = SHELL_INVALID_PARAMETER;\r
828             } else {\r
829               Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
830               CurrentOperation.Number2     = (UINT16)Intermediate;\r
831             }\r
832             if (CurrentOperation.Number2 == CurrentOperation.Number1\r
833               ||CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))\r
834               ||CurrentOperation.Number2 > (Length / sizeof(CurrentOperation.Order[0]))\r
835              ){\r
836               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellDebug1HiiHandle, Length / sizeof(CurrentOperation.Order[0]));\r
837               ShellStatus = SHELL_INVALID_PARAMETER;\r
838             }\r
839           }\r
840         } else {\r
841           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);\r
842           ShellStatus = SHELL_INVALID_PARAMETER;\r
843         }\r
844       }\r
845     }\r
846     if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type < BcfgTypeMax) {\r
847       //\r
848       // we have all the info.  Do the work\r
849       //\r
850       switch (CurrentOperation.Type) {\r
851         case   BcfgTypeDump:\r
852           ShellStatus = BcfgDisplayDumpDebug1(\r
853             CurrentOperation.Target == BcfgTargetBootOrder?L"Boot":L"Driver",\r
854             Length / sizeof(CurrentOperation.Order[0]),\r
855             CurrentOperation.Order,\r
856             ShellCommandLineGetFlag(Package, L"-v"));\r
857           break;\r
858         case   BcfgTypeMv:\r
859           ShellStatus = BcfgMoveDebug1(\r
860             CurrentOperation.Target,\r
861             CurrentOperation.Order,\r
862             Length / sizeof(CurrentOperation.Order[0]),\r
863             CurrentOperation.Number1,\r
864             CurrentOperation.Number2);\r
865           break;\r
866         case   BcfgTypeRm:\r
867           ShellStatus = BcfgRemoveDebug1(\r
868             CurrentOperation.Target,\r
869             CurrentOperation.Order,\r
870             Length / sizeof(CurrentOperation.Order[0]),\r
871             CurrentOperation.Number1);\r
872           break;\r
873         case   BcfgTypeAdd:\r
874         case   BcfgTypeAddp:\r
875         case   BcfgTypeAddh:\r
876           ShellStatus = BcfgAddDebug1(\r
877             CurrentOperation.Number1,\r
878             CurrentOperation.FileName,\r
879             CurrentOperation.Description,\r
880             CurrentOperation.Order,\r
881             Length / sizeof(CurrentOperation.Order[0]),\r
882             CurrentOperation.Target,\r
883             (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh),\r
884             (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp),\r
885             CurrentOperation.HandleIndex);\r
886           break;\r
887         case   BcfgTypeOpt:\r
888           ShellStatus = BcfgAddOptDebug1(\r
889             CurrentOperation.OptData,\r
890             CurrentOperation.Target);\r
891           break;\r
892         default:\r
893           ASSERT(FALSE);\r
894       }\r
895     }\r
896   }\r
897 \r
898   if (Package != NULL) {\r
899     ShellCommandLineFreeVarList (Package);\r
900   }\r
901   if (CurrentOperation.FileName != NULL) {\r
902     FreePool(CurrentOperation.FileName);\r
903   }\r
904   if (CurrentOperation.Description != NULL) {\r
905     FreePool(CurrentOperation.Description);\r
906   }\r
907   if (CurrentOperation.Order != NULL) {\r
908     FreePool(CurrentOperation.Order);\r
909   }\r
910 \r
911   return (ShellStatus);\r
912 }\r