]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c
ShellPkg: Add a new library for "bcfg" command
[mirror_edk2.git] / ShellPkg / Library / UefiShellBcfgCommandLib / UefiShellBcfgCommandLib.c
CommitLineData
7b01f0f3
JC
1/** @file\r
2 Main file for BCFG command.\r
3\r
4 Copyright (c) 2010 - 2014, 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\r
16#include <Uefi.h>\r
17#include <ShellBase.h>\r
18\r
19#include <Guid/GlobalVariable.h>\r
20#include <Guid/ShellLibHiiGuid.h>\r
21\r
22#include <Protocol/EfiShell.h>\r
23#include <Protocol/EfiShellParameters.h>\r
24#include <Protocol/DevicePath.h>\r
25#include <Protocol/LoadedImage.h>\r
26#include <Protocol/UnicodeCollation.h>\r
27\r
28#include <Library/BaseLib.h>\r
29#include <Library/BaseMemoryLib.h>\r
30#include <Library/DebugLib.h>\r
31#include <Library/MemoryAllocationLib.h>\r
32#include <Library/PcdLib.h>\r
33#include <Library/ShellCommandLib.h>\r
34#include <Library/ShellLib.h>\r
35#include <Library/SortLib.h>\r
36#include <Library/UefiLib.h>\r
37#include <Library/UefiRuntimeServicesTableLib.h>\r
38#include <Library/UefiBootServicesTableLib.h>\r
39#include <Library/HiiLib.h>\r
40#include <Library/FileHandleLib.h>\r
41#include <Library/PrintLib.h>\r
42#include <Library/HandleParsingLib.h>\r
43#include <Library/DevicePathLib.h>\r
44\r
45STATIC CONST CHAR16 mFileName[] = L"ShellCommands";\r
46STATIC EFI_HANDLE gShellBcfgHiiHandle = NULL;\r
47\r
48typedef enum {\r
49 BcfgTargetBootOrder = 0,\r
50 BcfgTargetDriverOrder = 1,\r
51 BcfgTargetMax = 2\r
52} BCFG_OPERATION_TARGET;\r
53\r
54typedef enum {\r
55 BcfgTypeDump = 0,\r
56 BcfgTypeAdd = 1,\r
57 BcfgTypeAddp = 2,\r
58 BcfgTypeAddh = 3,\r
59 BcfgTypeRm = 4,\r
60 BcfgTypeMv = 5,\r
61 BcfgTypeOpt = 6,\r
62 BcfgTypeMax = 7\r
63} BCFG_OPERATION_TYPE;\r
64\r
65typedef struct {\r
66 BCFG_OPERATION_TARGET Target;\r
67 BCFG_OPERATION_TYPE Type;\r
68 UINT16 Number1;\r
69 UINT16 Number2;\r
70 UINTN HandleIndex;\r
71 CHAR16 *FileName;\r
72 CHAR16 *Description;\r
73 UINT16 *Order;\r
74 CONST CHAR16 *OptData;\r
75} BGFG_OPERATION;\r
76\r
77/**\r
78 Update the optional data for a boot or driver option.\r
79\r
80 If optional data exists it will be changed.\r
81\r
82 @param[in] Index The boot or driver option index update.\r
83 @param[in] DataSize The size in bytes of Data.\r
84 @param[in] Data The buffer for the optioanl data.\r
85 @param[in] Target The target of the operation.\r
86\r
87 @retval EFI_SUCCESS The data was sucessfully updated.\r
88 @retval other A error occured.\r
89**/\r
90EFI_STATUS\r
91EFIAPI\r
92UpdateOptionalData(\r
93 UINT16 Index, \r
94 UINTN DataSize, \r
95 UINT8 *Data,\r
96 IN CONST BCFG_OPERATION_TARGET Target\r
97 )\r
98{\r
99 EFI_STATUS Status;\r
100 CHAR16 VariableName[12];\r
101 UINTN OriginalSize;\r
102 UINT8 *OriginalData;\r
103 UINTN NewSize;\r
104 UINT8 *NewData;\r
105 UINTN OriginalOptionDataSize;\r
106\r
107 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", Index);\r
108 \r
109 OriginalSize = 0;\r
110 OriginalData = NULL;\r
111 NewData = NULL;\r
112 NewSize = 0;\r
113\r
114 Status = gRT->GetVariable(\r
115 VariableName,\r
116 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
117 NULL,\r
118 &OriginalSize,\r
119 OriginalData);\r
120 if (Status == EFI_BUFFER_TOO_SMALL) {\r
121 OriginalData = AllocateZeroPool(OriginalSize);\r
122 if (OriginalData == NULL) {\r
123 return (EFI_OUT_OF_RESOURCES);\r
124 }\r
125 Status = gRT->GetVariable(\r
126 VariableName,\r
127 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
128 NULL,\r
129 &OriginalSize,\r
130 OriginalData);\r
131 }\r
132\r
133 if (!EFI_ERROR(Status)) {\r
134 //\r
135 // Allocate new struct and discard old optional data.\r
136 //\r
137 ASSERT (OriginalData != NULL);\r
138 OriginalOptionDataSize = sizeof(UINT32) + sizeof(UINT16) + StrSize(((CHAR16*)(OriginalData + sizeof(UINT32) + sizeof(UINT16))));\r
139 OriginalOptionDataSize += (*(UINT16*)(OriginalData + sizeof(UINT32)));\r
140 OriginalOptionDataSize -= OriginalSize;\r
141 NewSize = OriginalSize - OriginalOptionDataSize + DataSize;\r
142 NewData = AllocateCopyPool(NewSize, OriginalData);\r
143 if (NewData == NULL) {\r
144 Status = EFI_OUT_OF_RESOURCES;\r
145 } else {\r
146 CopyMem(NewData + OriginalSize - OriginalOptionDataSize, Data, DataSize);\r
147 }\r
148 }\r
149\r
150 if (!EFI_ERROR(Status)) {\r
151 //\r
152 // put the data back under the variable\r
153 //\r
154 Status = gRT->SetVariable(\r
155 VariableName, \r
156 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
157 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
158 NewSize,\r
159 NewData);\r
160 }\r
161\r
162 SHELL_FREE_NON_NULL(OriginalData);\r
163 SHELL_FREE_NON_NULL(NewData);\r
164 return (Status);\r
165}\r
166\r
167/**\r
168 This function will get a CRC for a boot option.\r
169\r
170 @param[in, out] Crc The CRC value to return.\r
171 @param[in] BootIndex The boot option index to CRC.\r
172\r
173 @retval EFI_SUCCESS The CRC was sucessfully returned.\r
174 @retval other A error occured.\r
175**/\r
176EFI_STATUS\r
177EFIAPI\r
178GetBootOptionCrc(\r
179 UINT32 *Crc, \r
180 UINT16 BootIndex\r
181 )\r
182{\r
183 CHAR16 VariableName[12];\r
184 EFI_STATUS Status;\r
185 UINT8 *Buffer;\r
186 UINTN BufferSize;\r
187\r
188 Buffer = NULL;\r
189 BufferSize = 0;\r
190\r
191 //\r
192 // Get the data Buffer\r
193 //\r
194 UnicodeSPrint(VariableName, sizeof(VariableName), L"%Boot%04x", BootIndex);\r
195 Status = gRT->GetVariable(\r
196 VariableName,\r
197 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
198 NULL,\r
199 &BufferSize,\r
200 NULL);\r
201 if (Status == EFI_BUFFER_TOO_SMALL) {\r
202 Buffer = AllocateZeroPool(BufferSize);\r
203 Status = gRT->GetVariable(\r
204 VariableName,\r
205 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
206 NULL,\r
207 &BufferSize,\r
208 Buffer);\r
209 }\r
210\r
211 //\r
212 // Get the CRC computed\r
213 //\r
214 if (!EFI_ERROR(Status)) {\r
215 Status = gBS->CalculateCrc32 (Buffer, BufferSize, Crc);\r
216 }\r
217\r
218 SHELL_FREE_NON_NULL(Buffer);\r
219 return EFI_SUCCESS;\r
220}\r
221\r
222/**\r
223 This function will populate the device path protocol parameter based on TheHandle.\r
224\r
225 @param[in] TheHandle Driver handle.\r
226 @param[in, out] FilePath On a sucessful return the device path to the handle.\r
227\r
228 @retval EFI_SUCCESS The device path was sucessfully returned.\r
229 @retval other A error from gBS->HandleProtocol.\r
230\r
231 @sa HandleProtocol\r
232**/\r
233EFI_STATUS\r
234EFIAPI\r
235GetDevicePathForDriverHandle (\r
236 IN EFI_HANDLE TheHandle,\r
237 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath\r
238 )\r
239{\r
240 EFI_STATUS Status;\r
241 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
242 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;\r
243\r
244 Status = gBS->OpenProtocol (\r
245 TheHandle,\r
246 &gEfiLoadedImageProtocolGuid,\r
247 (VOID**)&LoadedImage,\r
248 gImageHandle,\r
249 NULL,\r
250 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
251 );\r
252 if (!EFI_ERROR (Status)) {\r
253 Status = gBS->OpenProtocol (\r
254 LoadedImage->DeviceHandle,\r
255 &gEfiDevicePathProtocolGuid,\r
256 (VOID**)&ImageDevicePath,\r
257 gImageHandle,\r
258 NULL,\r
259 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
260 );\r
261 if (!EFI_ERROR (Status)) {\r
262// *DevPath = DuplicateDevicePath (ImageDevicePath);\r
263// *FilePath = DuplicateDevicePath (LoadedImage->FilePath);\r
264 *FilePath = AppendDevicePath(ImageDevicePath,LoadedImage->FilePath);\r
265 gBS->CloseProtocol(\r
266 LoadedImage->DeviceHandle,\r
267 &gEfiDevicePathProtocolGuid,\r
268 gImageHandle,\r
269 NULL);\r
270 }\r
271 gBS->CloseProtocol(\r
272 TheHandle,\r
273 &gEfiLoadedImageProtocolGuid,\r
274 gImageHandle,\r
275 NULL);\r
276 }\r
277 return (Status);\r
278}\r
279\r
280/**\r
281 Function to add a option.\r
282\r
283 @param[in] Position The position to add Target at.\r
284 @param[in] File The file to make the target.\r
285 @param[in] Desc The description text.\r
286 @param[in] CurrentOrder The pointer to the current order of items.\r
287 @param[in] OrderCount The number if items in CurrentOrder.\r
288 @param[in] Target The info on the option to add.\r
289 @param[in] UseHandle TRUE to use HandleNumber, FALSE to use File and Desc.\r
290 @param[in] UsePath TRUE to convert to devicepath.\r
291 @param[in] HandleNumber The handle number to add.\r
292\r
293 @retval SHELL_SUCCESS The operation was successful.\r
294 @retval SHELL_INVALID_PARAMETER A parameter was invalid.\r
295**/\r
296SHELL_STATUS\r
297EFIAPI\r
298BcfgAdd(\r
299 IN UINTN Position,\r
300 IN CONST CHAR16 *File,\r
301 IN CONST CHAR16 *Desc,\r
302 IN CONST UINT16 *CurrentOrder,\r
303 IN CONST UINTN OrderCount,\r
304 IN CONST BCFG_OPERATION_TARGET Target,\r
305 IN CONST BOOLEAN UseHandle,\r
306 IN CONST BOOLEAN UsePath,\r
307 IN CONST UINTN HandleNumber\r
308 )\r
309{\r
310 EFI_STATUS Status;\r
311 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
312 EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
313 CHAR16 *Str;\r
314 UINT8 *TempByteBuffer;\r
315 UINT8 *TempByteStart;\r
316 EFI_SHELL_FILE_INFO *Arg;\r
317 EFI_SHELL_FILE_INFO *FileList;\r
318 CHAR16 OptionStr[40];\r
319 UINTN DescSize, FilePathSize;\r
320 BOOLEAN Found;\r
321 UINTN TargetLocation;\r
322 UINTN Index;\r
323 EFI_HANDLE *Handles;\r
324 EFI_HANDLE CurHandle;\r
325 UINTN DriverBindingHandleCount;\r
326 UINTN ParentControllerHandleCount;\r
327 UINTN ChildControllerHandleCount;\r
328 SHELL_STATUS ShellStatus;\r
329 UINT16 *NewOrder;\r
330\r
331 if (!UseHandle) {\r
332 if (File == NULL || Desc == NULL) {\r
333 return (SHELL_INVALID_PARAMETER);\r
334 }\r
335 } else {\r
336 if (HandleNumber == 0) {\r
337 return (SHELL_INVALID_PARAMETER);\r
338 }\r
339 }\r
340\r
341 if (Position > OrderCount) {\r
342 Position = OrderCount;\r
343 }\r
344\r
345 Str = NULL;\r
346 FilePath = NULL;\r
347 FileList = NULL;\r
348 Handles = NULL;\r
349 ShellStatus = SHELL_SUCCESS;\r
350 TargetLocation = 0xFFFF;\r
351\r
352 if (UseHandle) {\r
353 CurHandle = ConvertHandleIndexToHandle(HandleNumber);\r
354 if (CurHandle == NULL) {\r
355 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"Handle Number");\r
356 ShellStatus = SHELL_INVALID_PARAMETER;\r
357 } else {\r
358 if (Target == BcfgTargetBootOrder) {\r
359 //\r
360 //Make sure that the handle should point to a real controller\r
361 //\r
362 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (\r
363 CurHandle,\r
364 &DriverBindingHandleCount,\r
365 NULL);\r
366\r
367 Status = PARSE_HANDLE_DATABASE_PARENTS (\r
368 CurHandle,\r
369 &ParentControllerHandleCount,\r
370 NULL);\r
371\r
372 Status = ParseHandleDatabaseForChildControllers (\r
373 CurHandle,\r
374 &ChildControllerHandleCount,\r
375 NULL);\r
376\r
377 if (DriverBindingHandleCount > 0\r
378 || ParentControllerHandleCount > 0\r
379 || ChildControllerHandleCount > 0) {\r
380 FilePath = NULL;\r
381 Status = gBS->HandleProtocol (\r
382 CurHandle,\r
383 &gEfiDevicePathProtocolGuid,\r
384 (VOID**)&FilePath);\r
385 }\r
386 if (EFI_ERROR (Status)) {\r
387 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellBcfgHiiHandle, HandleNumber);\r
388 ShellStatus = SHELL_INVALID_PARAMETER;\r
389 }\r
390 } else {\r
391 //\r
392 //Make sure that the handle should point to driver, not a controller.\r
393 //\r
394 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (\r
395 CurHandle,\r
396 &DriverBindingHandleCount,\r
397 NULL);\r
398\r
399 Status = PARSE_HANDLE_DATABASE_PARENTS (\r
400 CurHandle,\r
401 &ParentControllerHandleCount,\r
402 NULL);\r
403\r
404 Status = ParseHandleDatabaseForChildControllers (\r
405 CurHandle,\r
406 &ChildControllerHandleCount,\r
407 NULL);\r
408\r
409 Status = gBS->HandleProtocol (\r
410 CurHandle,\r
411 &gEfiDevicePathProtocolGuid,\r
412 (VOID**)&FilePath);\r
413\r
414 if (DriverBindingHandleCount > 0\r
415 || ParentControllerHandleCount > 0\r
416 || ChildControllerHandleCount > 0\r
417 || !EFI_ERROR(Status) ) {\r
418 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"Handle Number");\r
419 ShellStatus = SHELL_INVALID_PARAMETER;\r
420 } else {\r
421 //\r
422 // Get the DevicePath from the loaded image information.\r
423 //\r
424 Status = GetDevicePathForDriverHandle(CurHandle, &FilePath);\r
425 }\r
426 }\r
427 }\r
428 } else {\r
429 //\r
430 // Get file info\r
431 //\r
432 ShellOpenFileMetaArg ((CHAR16*)File, EFI_FILE_MODE_READ, &FileList);\r
433\r
434 if (FileList == NULL) {\r
435 //\r
436 // If filename matched nothing fail\r
437 //\r
438 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, File);\r
439 ShellStatus = SHELL_INVALID_PARAMETER;\r
440 } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {\r
441 //\r
442 // If filename expanded to multiple names, fail\r
443 //\r
444 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, File);\r
445 ShellStatus = SHELL_INVALID_PARAMETER;\r
446 } else {\r
447 Arg = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link);\r
448 if (EFI_ERROR(Arg->Status)) {\r
449 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, File, Arg->Status);\r
450 ShellStatus = SHELL_INVALID_PARAMETER;\r
451 } else {\r
452 //\r
453 // Build FilePath to the filename\r
454 //\r
455\r
456 //\r
457 // get the device path\r
458 //\r
459 DevicePath = gEfiShellProtocol->GetDevicePathFromFilePath(Arg->FullName);\r
460 if (DevicePath == NULL) {\r
461 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, Arg->FullName);\r
462 ShellStatus = SHELL_UNSUPPORTED;\r
463 } else {\r
464/*\r
465 if (UsePath) {\r
466 DevPath = DevicePath;\r
467 while (!IsDevicePathEnd(DevPath)) {\r
468 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&\r
469 (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {\r
470\r
471 //\r
472 // If we find it use it instead\r
473 //\r
474 DevicePath = DevPath;\r
475 break;\r
476 }\r
477 DevPath = NextDevicePathNode(DevPath);\r
478 }\r
479 //\r
480 // append the file\r
481 //\r
482 for(StringWalker=Arg->FullName; *StringWalker != CHAR_NULL && *StringWalker != ':'; StringWalker++);\r
483 FileNode = FileDevicePath(NULL, StringWalker+1);\r
484 FilePath = AppendDevicePath(DevicePath, FileNode);\r
485 FreePool(FileNode);\r
486 } else {\r
487*/\r
488 FilePath = DuplicateDevicePath(DevicePath);\r
489/*\r
490 }\r
491*/\r
492 FreePool(DevicePath);\r
493 }\r
494 }\r
495 }\r
496 }\r
497\r
498\r
499 if (ShellStatus == SHELL_SUCCESS) {\r
500 //\r
501 // Find a free target ,a brute force implementation\r
502 //\r
503 Found = FALSE;\r
504 for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) {\r
505 Found = TRUE;\r
506 for (Index=0; Index < OrderCount; Index++) {\r
507 if (CurrentOrder[Index] == TargetLocation) {\r
508 Found = FALSE;\r
509 break;\r
510 }\r
511 }\r
512\r
513 if (Found) {\r
514 break;\r
515 }\r
516 }\r
517\r
518 if (TargetLocation == 0xFFFF) {\r
519 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellBcfgHiiHandle);\r
520 } else {\r
521 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellBcfgHiiHandle, TargetLocation);\r
522 }\r
523 }\r
524\r
525 if (ShellStatus == SHELL_SUCCESS) {\r
526 //\r
527 // Add the option\r
528 //\r
529 DescSize = StrSize(Desc);\r
530 FilePathSize = GetDevicePathSize (FilePath);\r
531\r
532 TempByteBuffer = AllocateZeroPool(sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize);\r
533 if (TempByteBuffer != NULL) {\r
534 TempByteStart = TempByteBuffer;\r
535 *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes\r
536 TempByteBuffer += sizeof (UINT32);\r
537\r
538 *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength\r
539 TempByteBuffer += sizeof (UINT16);\r
540\r
541 CopyMem (TempByteBuffer, Desc, DescSize);\r
542 TempByteBuffer += DescSize;\r
543 ASSERT (FilePath != NULL);\r
544 CopyMem (TempByteBuffer, FilePath, FilePathSize);\r
545\r
546 UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", TargetLocation);\r
547 Status = gRT->SetVariable (\r
548 OptionStr,\r
549 &gEfiGlobalVariableGuid,\r
550 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
551 sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize,\r
552 TempByteStart\r
553 );\r
554\r
555 FreePool(TempByteStart);\r
556 } else {\r
557 Status = EFI_OUT_OF_RESOURCES;\r
558 }\r
559\r
560 if (EFI_ERROR(Status)) {\r
561 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, OptionStr, Status);\r
562 } else {\r
563 NewOrder = AllocateZeroPool((OrderCount+1)*sizeof(NewOrder[0]));\r
564 ASSERT(NewOrder != NULL);\r
565 CopyMem(NewOrder, CurrentOrder, (OrderCount)*sizeof(NewOrder[0]));\r
566\r
567 //\r
568 // Insert target into order list\r
569 //\r
570 for (Index=OrderCount; Index > Position; Index--) {\r
571 NewOrder[Index] = NewOrder[Index-1];\r
572 }\r
573\r
574 NewOrder[Position] = (UINT16) TargetLocation;\r
575 Status = gRT->SetVariable (\r
576 Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder",\r
577 &gEfiGlobalVariableGuid,\r
578 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
579 (OrderCount+1) * sizeof(UINT16),\r
580 NewOrder\r
581 );\r
582\r
583 FreePool(NewOrder);\r
584\r
585 if (EFI_ERROR(Status)) {\r
586 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder", Status);\r
587 ShellStatus = SHELL_INVALID_PARAMETER;\r
588 } else {\r
589 Print (L"bcfg: Add %s as %x\n", OptionStr, Position);\r
590 }\r
591 }\r
592 }\r
593\r
594//\r
595//If always Free FilePath, will free devicepath in system when use "addh"\r
596//\r
597 if (FilePath!=NULL && !UseHandle) {\r
598 FreePool (FilePath);\r
599 }\r
600\r
601 if (Str != NULL) {\r
602 FreePool(Str);\r
603 }\r
604\r
605 if (Handles != NULL) {\r
606 FreePool (Handles);\r
607 }\r
608\r
609 if (FileList != NULL) {\r
610 ShellCloseFileMetaArg (&FileList);\r
611 }\r
612\r
613 return (ShellStatus);\r
614}\r
615\r
616/**\r
617 Funciton to remove an item.\r
618\r
619 @param[in] Target The target item to move.\r
620 @param[in] CurrentOrder The pointer to the current order of items.\r
621 @param[in] OrderCount The number if items in CurrentOrder.\r
622 @param[in] Location The current location of the Target.\r
623\r
624 @retval SHELL_SUCCESS The operation was successful.\r
625 @retval SHELL_INVALID_PARAMETER A parameter was invalid.\r
626**/\r
627SHELL_STATUS\r
628EFIAPI\r
629BcfgRemove(\r
630 IN CONST BCFG_OPERATION_TARGET Target,\r
631 IN CONST UINT16 *CurrentOrder,\r
632 IN CONST UINTN OrderCount,\r
633 IN CONST UINT16 Location\r
634 )\r
635{\r
636 CHAR16 VariableName[12];\r
637 UINT16 *NewOrder;\r
638 EFI_STATUS Status;\r
639 UINTN NewCount;\r
640\r
641 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", CurrentOrder[Location]);\r
642 Status = gRT->SetVariable(\r
643 VariableName,\r
644 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
645 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
646 0,\r
647 NULL);\r
648 if (EFI_ERROR(Status)) {\r
649 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, VariableName, Status);\r
650 return (SHELL_INVALID_PARAMETER);\r
651 }\r
652 NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0]));\r
653 if (NewOrder != NULL) {\r
654 NewCount = OrderCount;\r
655 CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0]));\r
656 CopyMem(NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof(CurrentOrder[0]));\r
657 NewCount--;\r
658\r
659 Status = gRT->SetVariable(\r
660 Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",\r
661 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
662 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
663 NewCount*sizeof(NewOrder[0]),\r
664 NewOrder);\r
665 FreePool(NewOrder);\r
666 } else {\r
667 Status = EFI_OUT_OF_RESOURCES;\r
668 }\r
669 if (EFI_ERROR(Status)) {\r
670 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status);\r
671 return (SHELL_INVALID_PARAMETER);\r
672 }\r
673 return (SHELL_SUCCESS);\r
674}\r
675\r
676/**\r
677 Funciton to move a item to another location.\r
678\r
679 @param[in] Target The target item to move.\r
680 @param[in] CurrentOrder The pointer to the current order of items.\r
681 @param[in] OrderCount The number if items in CurrentOrder.\r
682 @param[in] OldLocation The current location of the Target.\r
683 @param[in] NewLocation The desired location of the Target.\r
684\r
685 @retval SHELL_SUCCESS The operation was successful.\r
686 @retval SHELL_INVALID_PARAMETER A parameter was invalid.\r
687**/\r
688SHELL_STATUS\r
689EFIAPI\r
690BcfgMove(\r
691 IN CONST BCFG_OPERATION_TARGET Target,\r
692 IN CONST UINT16 *CurrentOrder,\r
693 IN CONST UINTN OrderCount,\r
694 IN CONST UINT16 OldLocation,\r
695 IN UINT16 NewLocation\r
696 )\r
697{\r
698 UINT16 *NewOrder;\r
699 EFI_STATUS Status;\r
700 UINT16 Temp;\r
701\r
702 NewOrder = AllocateCopyPool(OrderCount*sizeof(CurrentOrder[0]), CurrentOrder);\r
703 if (NewOrder == NULL) {\r
704 return (SHELL_OUT_OF_RESOURCES);\r
705 }\r
706\r
707 //\r
708 // correct the new location\r
709 //\r
710 if (NewLocation >= OrderCount) {\r
711 if (OrderCount > 0) {\r
712 NewLocation = (UINT16)OrderCount - 1;\r
713 } else {\r
714 NewLocation = 0;\r
715 }\r
716 }\r
717\r
718 Temp = CurrentOrder[OldLocation];\r
719 CopyMem(NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof(CurrentOrder[0]));\r
720 CopyMem(NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof(CurrentOrder[0]));\r
721 NewOrder[NewLocation] = Temp;\r
722\r
723 Status = gRT->SetVariable(\r
724 Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",\r
725 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
726 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
727 OrderCount*sizeof(CurrentOrder[0]),\r
728 NewOrder);\r
729\r
730 FreePool(NewOrder);\r
731\r
732 if (EFI_ERROR(Status)) {\r
733 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status);\r
734 return (SHELL_INVALID_PARAMETER);\r
735 }\r
736 return (SHELL_SUCCESS);\r
737}\r
738\r
739/**\r
740 Function to add optional data to an option.\r
741\r
742 @param[in] OptData The optional data to add.\r
743 @param[in] CurrentOrder The pointer to the current order of items.\r
744 @param[in] OrderCount The number if items in CurrentOrder.\r
745 @param[in] Target The target of the operation.\r
746\r
747 @retval SHELL_SUCCESS The operation was succesful.\r
748**/\r
749SHELL_STATUS\r
750EFIAPI\r
751BcfgAddOpt(\r
752 IN CONST CHAR16 *OptData,\r
753 IN CONST UINT16 *CurrentOrder,\r
754 IN CONST UINTN OrderCount,\r
755 IN CONST BCFG_OPERATION_TARGET Target\r
756 )\r
757{\r
758 EFI_KEY_OPTION NewKeyOption;\r
759 EFI_KEY_OPTION *KeyOptionBuffer;\r
760 SHELL_STATUS ShellStatus;\r
761 EFI_STATUS Status;\r
762 UINT16 OptionIndex;\r
763 UINT16 LoopCounter;\r
764 UINT64 Intermediate;\r
765 CONST CHAR16 *Temp;\r
766 CONST CHAR16 *Walker;\r
767 CHAR16 *FileName;\r
768 CHAR16 *Temp2;\r
769 CHAR16 *Data;\r
770 UINT16 KeyIndex;\r
771 CHAR16 VariableName[12];\r
772\r
773 SHELL_FILE_HANDLE FileHandle;\r
774\r
775 Status = EFI_SUCCESS;\r
776 ShellStatus = SHELL_SUCCESS;\r
777 Walker = OptData;\r
778 FileName = NULL;\r
779 Data = NULL;\r
780 KeyOptionBuffer = NULL;\r
781\r
782 ZeroMem(&NewKeyOption, sizeof(EFI_KEY_OPTION));\r
783\r
784 while(Walker[0] == L' ') {\r
785 Walker++;\r
786 }\r
787\r
788 //\r
789 // Get the index of the variable we are changing.\r
790 //\r
791 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);\r
792 if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL || ((UINT16)Intermediate) > ((UINT16)OrderCount)) {\r
793 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"Option Index");\r
794 ShellStatus = SHELL_INVALID_PARAMETER;\r
795 return (ShellStatus);\r
796 }\r
797 OptionIndex = (UINT16)Intermediate;\r
798\r
799 Temp = StrStr(Walker, L" ");\r
800 if (Temp != NULL) {\r
801 Walker = Temp;\r
802 }\r
803 while(Walker[0] == L' ') {\r
804 Walker++;\r
805 }\r
806\r
807 //\r
808 // determine whether we have file with data, quote delimited information, or a hot-key \r
809 //\r
810 if (Walker[0] == L'\"') {\r
811 //\r
812 // quoted filename or quoted information.\r
813 //\r
814 Temp = StrStr(Walker+1, L"\"");\r
815 if (Temp == NULL || StrLen(Temp) != 1) {\r
816 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, Walker);\r
817 ShellStatus = SHELL_INVALID_PARAMETER;\r
818 } else {\r
819 FileName = StrnCatGrow(&FileName, NULL, Walker+1, 0);\r
820 if (FileName == NULL) {\r
821 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellBcfgHiiHandle);\r
822 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
823 return (ShellStatus);\r
824 }\r
825 Temp2 = StrStr(FileName, L"\"");\r
826 ASSERT(Temp2 != NULL);\r
827 Temp2[0] = CHAR_NULL;\r
828 Temp2++;\r
829 if (StrLen(Temp2)>0) {\r
830 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, Walker);\r
831 ShellStatus = SHELL_INVALID_PARAMETER;\r
832 }\r
833 if (EFI_ERROR(ShellFileExists(Walker))) {\r
834 //\r
835 // Not a file. must be misc information.\r
836 //\r
837 Data = FileName;\r
838 FileName = NULL;\r
839 } else {\r
840 FileName = StrnCatGrow(&FileName, NULL, Walker, 0);\r
841 }\r
842 }\r
843 } else {\r
844 //\r
845 // filename or hot key information.\r
846 //\r
847 if (StrStr(Walker, L" ") == NULL) {\r
848 //\r
849 // filename\r
850 //\r
851 if (EFI_ERROR(ShellFileExists(Walker))) {\r
852 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellBcfgHiiHandle, Walker);\r
853 ShellStatus = SHELL_INVALID_PARAMETER;\r
854 } else {\r
855 FileName = StrnCatGrow(&FileName, NULL, Walker, 0);\r
856 }\r
857 } else {\r
858 if (Target != BcfgTargetBootOrder) {\r
859 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_BOOT_ONLY), gShellBcfgHiiHandle);\r
860 ShellStatus = SHELL_INVALID_PARAMETER;\r
861 }\r
862\r
863 if (ShellStatus == SHELL_SUCCESS) {\r
864 //\r
865 // Get hot key information\r
866 //\r
867 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);\r
868 if (EFI_ERROR(Status) || (((UINT32)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) {\r
869 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, Walker);\r
870 ShellStatus = SHELL_INVALID_PARAMETER;\r
871 }\r
872 NewKeyOption.KeyData.PackedValue = (UINT32)Intermediate;\r
873 Temp = StrStr(Walker, L" ");\r
874 if (Temp != NULL) {\r
875 Walker = Temp;\r
876 }\r
877 while(Walker[0] == L' ') {\r
878 Walker++;\r
879 }\r
880 }\r
881\r
882 if (ShellStatus == SHELL_SUCCESS) {\r
883 //\r
884 // Now we know how many EFI_INPUT_KEY structs we need to attach to the end of the EFI_KEY_OPTION struct. \r
885 // Re-allocate with the added information.\r
886 //\r
887 KeyOptionBuffer = AllocateCopyPool(sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount), &NewKeyOption);\r
888 if (KeyOptionBuffer == NULL) {\r
889 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle);\r
890 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
891 }\r
892 }\r
893 for (LoopCounter = 0 ; ShellStatus == SHELL_SUCCESS && LoopCounter < NewKeyOption.KeyData.Options.InputKeyCount; LoopCounter++) {\r
894 //\r
895 // ScanCode\r
896 //\r
897 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);\r
898 if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) {\r
899 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, Walker);\r
900 ShellStatus = SHELL_INVALID_PARAMETER;\r
901 }\r
902 ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].ScanCode = (UINT16)Intermediate;\r
903 Temp = StrStr(Walker, L" ");\r
904 if (Temp != NULL) {\r
905 Walker = Temp;\r
906 }\r
907 while(Walker[0] == L' ') {\r
908 Walker++;\r
909 }\r
910\r
911 //\r
912 // UnicodeChar\r
913 //\r
914 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);\r
915 if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate)) {\r
916 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, Walker);\r
917 ShellStatus = SHELL_INVALID_PARAMETER;\r
918 }\r
919 ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].UnicodeChar = (UINT16)Intermediate;\r
920 Temp = StrStr(Walker, L" ");\r
921 if (Temp != NULL) {\r
922 Walker = Temp;\r
923 }\r
924 while(Walker[0] == L' ') {\r
925 Walker++;\r
926 }\r
927 }\r
928\r
929 if (ShellStatus == SHELL_SUCCESS) {\r
930 //\r
931 // Now do the BootOption / BootOptionCrc\r
932 //\r
933 ASSERT (OptionIndex <= OrderCount);\r
934 KeyOptionBuffer->BootOption = CurrentOrder[OptionIndex];\r
935 Status = GetBootOptionCrc(&(KeyOptionBuffer->BootOptionCrc), KeyOptionBuffer->BootOption);\r
936 if (EFI_ERROR(Status)) {\r
937 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"Option Index");\r
938 ShellStatus = SHELL_INVALID_PARAMETER;\r
939 } \r
940 }\r
941\r
942 if (ShellStatus == SHELL_SUCCESS) {\r
943 for (Temp2 = NULL, KeyIndex = 0 ; KeyIndex < 0xFFFF ; KeyIndex++) {\r
944 UnicodeSPrint(VariableName, sizeof(VariableName), L"Key%04x", KeyIndex);\r
945 Status = gRT->GetVariable(\r
946 VariableName,\r
947 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
948 NULL,\r
949 (UINTN*)&Intermediate,\r
950 NULL);\r
951 if (Status == EFI_NOT_FOUND) {\r
952 break;\r
953 }\r
954 }\r
955 Status = gRT->SetVariable(\r
956 VariableName,\r
957 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
958 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
959 sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount),\r
960 KeyOptionBuffer);\r
961 if (EFI_ERROR(Status)) {\r
962 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, VariableName, Status);\r
963 ShellStatus = SHELL_INVALID_PARAMETER;\r
964 } \r
965 ASSERT(FileName == NULL && Data == NULL);\r
966 }\r
967 }\r
968 }\r
969\r
970 //\r
971 // Shouldn't be possible to have have both. Neither is ok though.\r
972 //\r
973 ASSERT(FileName == NULL || Data == NULL);\r
974\r
975 if (ShellStatus == SHELL_SUCCESS && (FileName != NULL || Data != NULL)) {\r
976 if (FileName != NULL) {\r
977 //\r
978 // Open the file and populate the data buffer.\r
979 //\r
980 Status = ShellOpenFileByName(\r
981 FileName,\r
982 &FileHandle,\r
983 EFI_FILE_MODE_READ,\r
984 0);\r
985 if (!EFI_ERROR(Status)) {\r
986 Status = ShellGetFileSize(FileHandle, &Intermediate);\r
987 }\r
988 Data = AllocateZeroPool((UINTN)Intermediate);\r
989 if (Data == NULL) {\r
990 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle);\r
991 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
992 }\r
993 if (!EFI_ERROR(Status)) {\r
994 Status = ShellReadFile(FileHandle, (UINTN *)&Intermediate, Data);\r
995 }\r
996 } else {\r
997 Intermediate = StrSize(Data);\r
998 }\r
999\r
1000 if (!EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS && Data != NULL) {\r
1001 Status = UpdateOptionalData(CurrentOrder[OptionIndex], (UINTN)Intermediate, (UINT8*)Data, Target);\r
1002 if (EFI_ERROR(Status)) {\r
1003 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, VariableName, Status);\r
1004 ShellStatus = SHELL_INVALID_PARAMETER;\r
1005 } \r
1006 }\r
1007 if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {\r
1008 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, VariableName, Status);\r
1009 ShellStatus = SHELL_INVALID_PARAMETER;\r
1010 } \r
1011 }\r
1012\r
1013 SHELL_FREE_NON_NULL(Data);\r
1014 SHELL_FREE_NON_NULL(KeyOptionBuffer);\r
1015 SHELL_FREE_NON_NULL(FileName);\r
1016 return ShellStatus;\r
1017}\r
1018\r
1019/**\r
1020 Function to dump the Bcfg information.\r
1021\r
1022 @param[in] Op The operation.\r
1023 @param[in] OrderCount How many to dump.\r
1024 @param[in] CurrentOrder The pointer to the current order of items.\r
1025 @param[in] VerboseOutput TRUE for extra output. FALSE otherwise.\r
1026\r
1027 @retval SHELL_SUCCESS The dump was successful.\r
1028 @retval SHELL_INVALID_PARAMETER A parameter was invalid.\r
1029**/\r
1030SHELL_STATUS\r
1031EFIAPI\r
1032BcfgDisplayDump(\r
1033 IN CONST CHAR16 *Op,\r
1034 IN CONST UINTN OrderCount,\r
1035 IN CONST UINT16 *CurrentOrder,\r
1036 IN CONST BOOLEAN VerboseOutput\r
1037 )\r
1038{\r
1039 EFI_STATUS Status;\r
1040 UINT8 *Buffer;\r
1041 UINTN BufferSize;\r
1042 CHAR16 VariableName[12];\r
1043 UINTN LoopVar;\r
1044 UINTN LoopVar2;\r
1045 CHAR16 *DevPathString;\r
1046 VOID *DevPath;\r
1047\r
1048 if (OrderCount == 0) {\r
1049 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_BCFG_NONE), gShellBcfgHiiHandle);\r
1050 return (SHELL_SUCCESS);\r
1051 }\r
1052\r
1053 for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++) {\r
1054 Buffer = NULL;\r
1055 BufferSize = 0;\r
1056 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]);\r
1057\r
1058 Status = gRT->GetVariable(\r
1059 VariableName,\r
1060 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
1061 NULL,\r
1062 &BufferSize,\r
1063 Buffer);\r
1064 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1065 Buffer = AllocateZeroPool(BufferSize);\r
1066 Status = gRT->GetVariable(\r
1067 VariableName,\r
1068 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
1069 NULL,\r
1070 &BufferSize,\r
1071 Buffer);\r
1072 }\r
1073\r
1074 if (EFI_ERROR(Status) || Buffer == NULL) {\r
1075 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellBcfgHiiHandle, VariableName, Status);\r
1076 return (SHELL_INVALID_PARAMETER);\r
1077 }\r
1078\r
1079 if ((*(UINT16*)(Buffer+4)) != 0) {\r
1080 DevPath = AllocateZeroPool(*(UINT16*)(Buffer+4));\r
1081 if (DevPath == NULL) {\r
1082 DevPathString = NULL;\r
1083 } else {\r
1084 CopyMem(DevPath, Buffer+6+StrSize((CHAR16*)(Buffer+6)), *(UINT16*)(Buffer+4));\r
1085 DevPathString = ConvertDevicePathToText(DevPath, TRUE, FALSE);\r
1086 }\r
1087 } else {\r
1088 DevPath = NULL;\r
1089 DevPathString = NULL;\r
1090 }\r
1091 ShellPrintHiiEx(\r
1092 -1,\r
1093 -1,\r
1094 NULL,\r
1095 STRING_TOKEN(STR_BCFG_LOAD_OPTIONS),\r
1096 gShellBcfgHiiHandle,\r
1097 LoopVar,\r
1098 VariableName,\r
1099 (CHAR16*)(Buffer+6),\r
1100 DevPathString,\r
1101 (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6) <= BufferSize?L'N':L'Y');\r
1102 if (VerboseOutput) {\r
1103 for (LoopVar2 = (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6);LoopVar2<BufferSize;LoopVar2++){\r
1104 ShellPrintEx(\r
1105 -1,\r
1106 -1,\r
1107 NULL,\r
1108 L"%02x",\r
1109 Buffer[LoopVar2]);\r
1110 }\r
1111 ShellPrintEx(\r
1112 -1,\r
1113 -1,\r
1114 NULL,\r
1115 L"\r\n");\r
1116 }\r
1117\r
1118 if (Buffer != NULL) {\r
1119 FreePool(Buffer);\r
1120 }\r
1121 if (DevPath != NULL) {\r
1122 FreePool(DevPath);\r
1123 }\r
1124 if (DevPathString != NULL) {\r
1125 FreePool(DevPathString);\r
1126 }\r
1127 }\r
1128 return (SHELL_SUCCESS);\r
1129}\r
1130\r
1131/**\r
1132 Function to initialize the BCFG operation structure.\r
1133\r
1134 @param[in] Struct The stuct to initialize.\r
1135**/\r
1136VOID\r
1137EFIAPI\r
1138InitBcfgStruct(\r
1139 IN BGFG_OPERATION *Struct\r
1140 )\r
1141{\r
1142 ASSERT(Struct != NULL);\r
1143 Struct->Target = BcfgTargetMax;\r
1144 Struct->Type = BcfgTypeMax;\r
1145 Struct->Number1 = 0;\r
1146 Struct->Number2 = 0;\r
1147 Struct->HandleIndex = 0;\r
1148 Struct->FileName = NULL;\r
1149 Struct->Description = NULL;\r
1150 Struct->Order = NULL;\r
1151 Struct->OptData = NULL;\r
1152}\r
1153\r
1154\r
1155STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
1156 {L"-v", TypeFlag},\r
1157 {L"-opt", TypeMaxValue},\r
1158 {NULL, TypeMax}\r
1159 };\r
1160\r
1161/**\r
1162 Function for 'bcfg' command.\r
1163\r
1164 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
1165 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
1166**/\r
1167SHELL_STATUS\r
1168EFIAPI\r
1169ShellCommandRunBcfg (\r
1170 IN EFI_HANDLE ImageHandle,\r
1171 IN EFI_SYSTEM_TABLE *SystemTable\r
1172 )\r
1173{\r
1174 EFI_STATUS Status;\r
1175 LIST_ENTRY *Package;\r
1176 CHAR16 *ProblemParam;\r
1177 SHELL_STATUS ShellStatus;\r
1178 UINTN ParamNumber;\r
1179 CONST CHAR16 *CurrentParam;\r
1180 BGFG_OPERATION CurrentOperation;\r
1181 UINTN Length;\r
1182 UINT64 Intermediate;\r
1183 UINT16 Count;\r
1184\r
1185 Length = 0;\r
1186 ProblemParam = NULL;\r
1187 Package = NULL;\r
1188 ShellStatus = SHELL_SUCCESS;\r
1189\r
1190 InitBcfgStruct(&CurrentOperation);\r
1191\r
1192 //\r
1193 // initialize the shell lib (we must be in non-auto-init...)\r
1194 //\r
1195 Status = ShellInitialize();\r
1196 ASSERT_EFI_ERROR(Status);\r
1197\r
1198 Status = CommandInit();\r
1199 ASSERT_EFI_ERROR(Status);\r
1200\r
1201 //\r
1202 // parse the command line\r
1203 //\r
1204 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
1205 if (EFI_ERROR(Status)) {\r
1206 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
1207 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, ProblemParam);\r
1208 FreePool(ProblemParam);\r
1209 ShellStatus = SHELL_INVALID_PARAMETER;\r
1210 } else {\r
1211 ASSERT(FALSE);\r
1212 }\r
1213 } else {\r
1214 //\r
1215 // Read in if we are doing -OPT\r
1216 //\r
1217 if (ShellCommandLineGetFlag(Package, L"-opt")) {\r
1218 CurrentOperation.OptData = ShellCommandLineGetValue(Package, L"-opt");\r
1219 if (CurrentOperation.OptData == NULL) {\r
1220 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellBcfgHiiHandle, L"-opt");\r
1221 ShellStatus = SHELL_INVALID_PARAMETER;\r
1222 }\r
1223 CurrentOperation.Type = BcfgTypeOpt;\r
1224 }\r
1225\r
1226 //\r
1227 // small block to read the target of the operation\r
1228 //\r
1229 if ((ShellCommandLineGetCount(Package) < 3 && CurrentOperation.Type != BcfgTypeOpt) ||\r
1230 (ShellCommandLineGetCount(Package) < 2 && CurrentOperation.Type == BcfgTypeOpt)\r
1231 ){\r
1232 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle);\r
1233 ShellStatus = SHELL_INVALID_PARAMETER;\r
1234 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"driver") == 0) {\r
1235 CurrentOperation.Target = BcfgTargetDriverOrder;\r
1236 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"boot") == 0) {\r
1237 CurrentOperation.Target = BcfgTargetBootOrder;\r
1238 } else {\r
1239 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellBcfgHiiHandle);\r
1240 ShellStatus = SHELL_INVALID_PARAMETER;\r
1241 }\r
1242\r
1243\r
1244 //\r
1245 // Read in the boot or driver order environment variable (not needed for opt)\r
1246 //\r
1247 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {\r
1248 Length = 0;\r
1249 Status = gRT->GetVariable(\r
1250 CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",\r
1251 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
1252 NULL,\r
1253 &Length,\r
1254 CurrentOperation.Order);\r
1255 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1256 CurrentOperation.Order = AllocateZeroPool(Length+(4*sizeof(CurrentOperation.Order[0])));\r
1257 if (CurrentOperation.Order == NULL) {\r
1258 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
1259 } else {\r
1260 Status = gRT->GetVariable(\r
1261 CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",\r
1262 (EFI_GUID*)&gEfiGlobalVariableGuid,\r
1263 NULL,\r
1264 &Length,\r
1265 CurrentOperation.Order);\r
1266 }\r
1267 }\r
1268 }\r
1269\r
1270 Count = (UINT16) (Length / sizeof(CurrentOperation.Order[0]));\r
1271\r
1272 //\r
1273 // large block to read the type of operation and verify parameter types for the info.\r
1274 //\r
1275 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {\r
1276 for (ParamNumber = 2 ; ParamNumber < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) {\r
1277 CurrentParam = ShellCommandLineGetRawValue(Package, ParamNumber);\r
1278 if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"dump") == 0) {\r
1279 CurrentOperation.Type = BcfgTypeDump;\r
1280 } else if (ShellCommandLineGetFlag(Package, L"-v")) {\r
1281 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"-v (without dump)");\r
1282 ShellStatus = SHELL_INVALID_PARAMETER;\r
1283 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"add") == 0) {\r
1284 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {\r
1285 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle);\r
1286 ShellStatus = SHELL_INVALID_PARAMETER;\r
1287 }\r
1288 CurrentOperation.Type = BcfgTypeAdd;\r
1289 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
1290 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
1291 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
1292 ShellStatus = SHELL_INVALID_PARAMETER;\r
1293 } else {\r
1294 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
1295 CurrentOperation.Number1 = (UINT16)Intermediate;\r
1296 ASSERT(CurrentOperation.FileName == NULL);\r
1297 CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
1298 ASSERT(CurrentOperation.Description == NULL);\r
1299 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
1300 }\r
1301 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addp") == 0) {\r
1302 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {\r
1303 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle);\r
1304 ShellStatus = SHELL_INVALID_PARAMETER;\r
1305 }\r
1306 CurrentOperation.Type = BcfgTypeAddp;\r
1307 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
1308 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
1309 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
1310 ShellStatus = SHELL_INVALID_PARAMETER;\r
1311 } else {\r
1312 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
1313 CurrentOperation.Number1 = (UINT16)Intermediate;\r
1314 ASSERT(CurrentOperation.FileName == NULL);\r
1315 CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
1316 ASSERT(CurrentOperation.Description == NULL);\r
1317 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
1318 }\r
1319 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addh") == 0) {\r
1320 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {\r
1321 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle);\r
1322 ShellStatus = SHELL_INVALID_PARAMETER;\r
1323 }\r
1324 CurrentOperation.Type = BcfgTypeAddh;\r
1325 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
1326 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
1327 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
1328 ShellStatus = SHELL_INVALID_PARAMETER;\r
1329 } else {\r
1330 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
1331 CurrentOperation.Number1 = (UINT16)Intermediate;\r
1332 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
1333 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
1334 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
1335 ShellStatus = SHELL_INVALID_PARAMETER;\r
1336 } else {\r
1337 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
1338 CurrentOperation.HandleIndex = (UINT16)Intermediate;\r
1339 ASSERT(CurrentOperation.Description == NULL);\r
1340 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
1341 }\r
1342 }\r
1343 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"rm") == 0) {\r
1344 if ((ParamNumber + 1) >= ShellCommandLineGetCount(Package)) {\r
1345 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle);\r
1346 ShellStatus = SHELL_INVALID_PARAMETER;\r
1347 }\r
1348 CurrentOperation.Type = BcfgTypeRm;\r
1349 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
1350 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
1351 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
1352 ShellStatus = SHELL_INVALID_PARAMETER;\r
1353 } else {\r
1354 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
1355 CurrentOperation.Number1 = (UINT16)Intermediate;\r
1356 if (CurrentOperation.Number1 > Count){\r
1357 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, Count);\r
1358 ShellStatus = SHELL_INVALID_PARAMETER;\r
1359 }\r
1360 }\r
1361 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"mv") == 0) {\r
1362 if ((ParamNumber + 2) >= ShellCommandLineGetCount(Package)) {\r
1363 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle);\r
1364 ShellStatus = SHELL_INVALID_PARAMETER;\r
1365 }\r
1366 CurrentOperation.Type = BcfgTypeMv;\r
1367 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
1368 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
1369 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
1370 ShellStatus = SHELL_INVALID_PARAMETER;\r
1371 } else {\r
1372 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
1373 CurrentOperation.Number1 = (UINT16)Intermediate;\r
1374 if (CurrentOperation.Number1 > Count){\r
1375 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, Count);\r
1376 ShellStatus = SHELL_INVALID_PARAMETER;\r
1377 } else {\r
1378 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
1379 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
1380 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
1381 ShellStatus = SHELL_INVALID_PARAMETER;\r
1382 } else {\r
1383 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
1384 CurrentOperation.Number2 = (UINT16)Intermediate;\r
1385 }\r
1386 if (CurrentOperation.Number2 == CurrentOperation.Number1\r
1387 ||CurrentOperation.Number2 >= Count\r
1388 ){\r
1389 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, Count);\r
1390 ShellStatus = SHELL_INVALID_PARAMETER;\r
1391 }\r
1392 }\r
1393 }\r
1394 } else {\r
1395 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
1396 ShellStatus = SHELL_INVALID_PARAMETER;\r
1397 }\r
1398 }\r
1399 }\r
1400 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type < BcfgTypeMax) {\r
1401 //\r
1402 // we have all the info. Do the work\r
1403 //\r
1404 switch (CurrentOperation.Type) {\r
1405 case BcfgTypeDump:\r
1406 ShellStatus = BcfgDisplayDump(\r
1407 CurrentOperation.Target == BcfgTargetBootOrder?L"Boot":L"Driver",\r
1408 Count,\r
1409 CurrentOperation.Order,\r
1410 ShellCommandLineGetFlag(Package, L"-v"));\r
1411 break;\r
1412 case BcfgTypeMv:\r
1413 ShellStatus = BcfgMove(\r
1414 CurrentOperation.Target,\r
1415 CurrentOperation.Order,\r
1416 Count,\r
1417 CurrentOperation.Number1,\r
1418 CurrentOperation.Number2);\r
1419 break;\r
1420 case BcfgTypeRm:\r
1421 ShellStatus = BcfgRemove(\r
1422 CurrentOperation.Target,\r
1423 CurrentOperation.Order,\r
1424 Count,\r
1425 CurrentOperation.Number1);\r
1426 break;\r
1427 case BcfgTypeAdd:\r
1428 case BcfgTypeAddp:\r
1429 case BcfgTypeAddh:\r
1430 ShellStatus = BcfgAdd(\r
1431 CurrentOperation.Number1,\r
1432 CurrentOperation.FileName,\r
1433 CurrentOperation.Description==NULL?L"":CurrentOperation.Description,\r
1434 CurrentOperation.Order,\r
1435 Count,\r
1436 CurrentOperation.Target,\r
1437 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh),\r
1438 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp),\r
1439 CurrentOperation.HandleIndex);\r
1440 break;\r
1441 case BcfgTypeOpt:\r
1442 ShellStatus = BcfgAddOpt(\r
1443 CurrentOperation.OptData,\r
1444 CurrentOperation.Order,\r
1445 Count,\r
1446 CurrentOperation.Target);\r
1447 break;\r
1448 default:\r
1449 ASSERT(FALSE);\r
1450 }\r
1451 }\r
1452 }\r
1453\r
1454 if (Package != NULL) {\r
1455 ShellCommandLineFreeVarList (Package);\r
1456 }\r
1457 if (CurrentOperation.FileName != NULL) {\r
1458 FreePool(CurrentOperation.FileName);\r
1459 }\r
1460 if (CurrentOperation.Description != NULL) {\r
1461 FreePool(CurrentOperation.Description);\r
1462 }\r
1463 if (CurrentOperation.Order != NULL) {\r
1464 FreePool(CurrentOperation.Order);\r
1465 }\r
1466\r
1467 return (ShellStatus);\r
1468}\r
1469\r
1470\r
1471/**\r
1472 Function to get the filename with help context if HII will not be used.\r
1473\r
1474 @return The filename with help text in it.\r
1475**/\r
1476CONST CHAR16*\r
1477EFIAPI\r
1478ShellCommandGetManFileNameBcfg (\r
1479 VOID\r
1480 )\r
1481{\r
1482 return (mFileName);\r
1483}\r
1484\r
1485/**\r
1486 "Constructor" for the library.\r
1487\r
1488 This will register the handler for the bcfg command.\r
1489\r
1490 @param[in] ImageHandle the image handle of the process\r
1491 @param[in] SystemTable the EFI System Table pointer\r
1492 @param[in] Name the profile name to use\r
1493\r
1494 @retval EFI_SUCCESS the shell command handlers were installed sucessfully\r
1495 @retval EFI_UNSUPPORTED the shell level required was not found.\r
1496**/\r
1497EFI_STATUS\r
1498EFIAPI\r
1499BcfgLibraryRegisterBcfgCommand (\r
1500 IN EFI_HANDLE ImageHandle,\r
1501 IN EFI_SYSTEM_TABLE *SystemTable,\r
1502 IN CONST CHAR16 *Name\r
1503 )\r
1504{\r
1505 if (gShellBcfgHiiHandle) {\r
1506 return (EFI_SUCCESS);\r
1507 }\r
1508\r
1509 gShellBcfgHiiHandle = HiiAddPackages (&gShellBcfgHiiGuid, gImageHandle, UefiShellBcfgCommandLibStrings, NULL);\r
1510 if (gShellBcfgHiiHandle == NULL) {\r
1511 return (EFI_DEVICE_ERROR);\r
1512 }\r
1513\r
1514 //\r
1515 // install our shell command handler\r
1516 //\r
1517 ShellCommandRegisterCommandName(L"bcfg", ShellCommandRunBcfg , ShellCommandGetManFileNameBcfg, 0, Name, FALSE, gShellBcfgHiiHandle, STRING_TOKEN(STR_GET_HELP_BCFG));\r
1518\r
1519 return (EFI_SUCCESS);\r
1520}\r
1521\r
1522/**\r
1523 Destructor for the library. free any resources.\r
1524\r
1525 @param ImageHandle The image handle of the process.\r
1526 @param SystemTable The EFI System Table pointer.\r
1527**/\r
1528EFI_STATUS\r
1529EFIAPI\r
1530BcfgLibraryUnregisterBcfgCommand (\r
1531 IN EFI_HANDLE ImageHandle,\r
1532 IN EFI_SYSTEM_TABLE *SystemTable\r
1533 )\r
1534{\r
1535 if (gShellBcfgHiiHandle != NULL) {\r
1536 HiiRemovePackages(gShellBcfgHiiHandle);\r
1537 }\r
1538 gShellBcfgHiiHandle = NULL;\r
1539 return (EFI_SUCCESS);\r
1540}\r
1541\r