2 Main file for BCFG command.
4 (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <ShellBase.h>
20 #include <Guid/GlobalVariable.h>
21 #include <Guid/ShellLibHiiGuid.h>
23 #include <Protocol/EfiShell.h>
24 #include <Protocol/EfiShellParameters.h>
25 #include <Protocol/DevicePath.h>
26 #include <Protocol/LoadedImage.h>
27 #include <Protocol/UnicodeCollation.h>
29 #include <Library/BaseLib.h>
30 #include <Library/BaseMemoryLib.h>
31 #include <Library/DebugLib.h>
32 #include <Library/MemoryAllocationLib.h>
33 #include <Library/PcdLib.h>
34 #include <Library/ShellCommandLib.h>
35 #include <Library/ShellLib.h>
36 #include <Library/SortLib.h>
37 #include <Library/UefiLib.h>
38 #include <Library/UefiRuntimeServicesTableLib.h>
39 #include <Library/UefiBootServicesTableLib.h>
40 #include <Library/HiiLib.h>
41 #include <Library/FileHandleLib.h>
42 #include <Library/PrintLib.h>
43 #include <Library/HandleParsingLib.h>
44 #include <Library/DevicePathLib.h>
46 STATIC CONST CHAR16 mFileName
[] = L
"ShellCommands";
47 STATIC EFI_HANDLE gShellBcfgHiiHandle
= NULL
;
50 BcfgTargetBootOrder
= 0,
51 BcfgTargetDriverOrder
= 1,
53 } BCFG_OPERATION_TARGET
;
64 } BCFG_OPERATION_TYPE
;
67 BCFG_OPERATION_TARGET Target
;
68 BCFG_OPERATION_TYPE Type
;
75 CONST CHAR16
*OptData
;
79 Update the optional data for a boot or driver option.
81 If optional data exists it will be changed.
83 @param[in] Index The boot or driver option index update.
84 @param[in] DataSize The size in bytes of Data.
85 @param[in] Data The buffer for the optioanl data.
86 @param[in] Target The target of the operation.
88 @retval EFI_SUCCESS The data was sucessfully updated.
89 @retval other A error occured.
96 IN CONST BCFG_OPERATION_TARGET Target
100 CHAR16 VariableName
[12];
105 UINTN OriginalOptionDataSize
;
107 UnicodeSPrint(VariableName
, sizeof(VariableName
), L
"%s%04x", Target
== BcfgTargetBootOrder
?L
"Boot":L
"Driver", Index
);
114 Status
= gRT
->GetVariable(
116 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
120 if (Status
== EFI_BUFFER_TOO_SMALL
) {
121 OriginalData
= AllocateZeroPool(OriginalSize
);
122 if (OriginalData
== NULL
) {
123 return (EFI_OUT_OF_RESOURCES
);
125 Status
= gRT
->GetVariable(
127 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
133 if (!EFI_ERROR(Status
)) {
135 // Allocate new struct and discard old optional data.
137 ASSERT (OriginalData
!= NULL
);
138 OriginalOptionDataSize
= sizeof(UINT32
) + sizeof(UINT16
) + StrSize(((CHAR16
*)(OriginalData
+ sizeof(UINT32
) + sizeof(UINT16
))));
139 OriginalOptionDataSize
+= (*(UINT16
*)(OriginalData
+ sizeof(UINT32
)));
140 OriginalOptionDataSize
-= OriginalSize
;
141 NewSize
= OriginalSize
- OriginalOptionDataSize
+ DataSize
;
142 NewData
= AllocateCopyPool(NewSize
, OriginalData
);
143 if (NewData
== NULL
) {
144 Status
= EFI_OUT_OF_RESOURCES
;
146 CopyMem(NewData
+ OriginalSize
- OriginalOptionDataSize
, Data
, DataSize
);
150 if (!EFI_ERROR(Status
)) {
152 // put the data back under the variable
154 Status
= gRT
->SetVariable(
156 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
157 EFI_VARIABLE_NON_VOLATILE
|EFI_VARIABLE_BOOTSERVICE_ACCESS
|EFI_VARIABLE_RUNTIME_ACCESS
,
162 SHELL_FREE_NON_NULL(OriginalData
);
163 SHELL_FREE_NON_NULL(NewData
);
168 This function will get a CRC for a boot option.
170 @param[in, out] Crc The CRC value to return.
171 @param[in] BootIndex The boot option index to CRC.
173 @retval EFI_SUCCESS The CRC was sucessfully returned.
174 @retval other A error occured.
182 CHAR16 VariableName
[12];
191 // Get the data Buffer
193 UnicodeSPrint(VariableName
, sizeof(VariableName
), L
"%Boot%04x", BootIndex
);
194 Status
= gRT
->GetVariable(
196 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
200 if (Status
== EFI_BUFFER_TOO_SMALL
) {
201 Buffer
= AllocateZeroPool(BufferSize
);
202 Status
= gRT
->GetVariable(
204 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
211 // Get the CRC computed
213 if (!EFI_ERROR(Status
)) {
214 Status
= gBS
->CalculateCrc32 (Buffer
, BufferSize
, Crc
);
217 SHELL_FREE_NON_NULL(Buffer
);
222 This function will populate the device path protocol parameter based on TheHandle.
224 @param[in] TheHandle Driver handle.
225 @param[in, out] FilePath On a sucessful return the device path to the handle.
227 @retval EFI_SUCCESS The device path was sucessfully returned.
228 @retval other A error from gBS->HandleProtocol.
233 GetDevicePathForDriverHandle (
234 IN EFI_HANDLE TheHandle
,
235 IN OUT EFI_DEVICE_PATH_PROTOCOL
**FilePath
239 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
240 EFI_DEVICE_PATH_PROTOCOL
*ImageDevicePath
;
242 Status
= gBS
->OpenProtocol (
244 &gEfiLoadedImageProtocolGuid
,
245 (VOID
**)&LoadedImage
,
248 EFI_OPEN_PROTOCOL_GET_PROTOCOL
250 if (!EFI_ERROR (Status
)) {
251 Status
= gBS
->OpenProtocol (
252 LoadedImage
->DeviceHandle
,
253 &gEfiDevicePathProtocolGuid
,
254 (VOID
**)&ImageDevicePath
,
257 EFI_OPEN_PROTOCOL_GET_PROTOCOL
259 if (!EFI_ERROR (Status
)) {
260 // *DevPath = DuplicateDevicePath (ImageDevicePath);
261 // *FilePath = DuplicateDevicePath (LoadedImage->FilePath);
262 *FilePath
= AppendDevicePath(ImageDevicePath
,LoadedImage
->FilePath
);
264 LoadedImage
->DeviceHandle
,
265 &gEfiDevicePathProtocolGuid
,
271 &gEfiLoadedImageProtocolGuid
,
279 Function to add a option.
281 @param[in] Position The position to add Target at.
282 @param[in] File The file to make the target.
283 @param[in] Desc The description text.
284 @param[in] CurrentOrder The pointer to the current order of items.
285 @param[in] OrderCount The number if items in CurrentOrder.
286 @param[in] Target The info on the option to add.
287 @param[in] UseHandle TRUE to use HandleNumber, FALSE to use File and Desc.
288 @param[in] UsePath TRUE to convert to devicepath.
289 @param[in] HandleNumber The handle number to add.
291 @retval SHELL_SUCCESS The operation was successful.
292 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
297 IN CONST CHAR16
*File
,
298 IN CONST CHAR16
*Desc
,
299 IN CONST UINT16
*CurrentOrder
,
300 IN CONST UINTN OrderCount
,
301 IN CONST BCFG_OPERATION_TARGET Target
,
302 IN CONST BOOLEAN UseHandle
,
303 IN CONST BOOLEAN UsePath
,
304 IN CONST UINTN HandleNumber
308 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
309 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
310 EFI_DEVICE_PATH_PROTOCOL
*FilePath
;
312 UINT8
*TempByteBuffer
;
313 UINT8
*TempByteStart
;
314 EFI_SHELL_FILE_INFO
*Arg
;
315 EFI_SHELL_FILE_INFO
*FileList
;
316 CHAR16 OptionStr
[40];
317 UINTN DescSize
, FilePathSize
;
319 UINTN TargetLocation
;
322 EFI_HANDLE CurHandle
;
323 UINTN DriverBindingHandleCount
;
324 UINTN ParentControllerHandleCount
;
325 UINTN ChildControllerHandleCount
;
326 SHELL_STATUS ShellStatus
;
330 if (File
== NULL
|| Desc
== NULL
) {
331 return (SHELL_INVALID_PARAMETER
);
334 if (HandleNumber
== 0) {
335 return (SHELL_INVALID_PARAMETER
);
339 if (Position
> OrderCount
) {
340 Position
= OrderCount
;
347 ShellStatus
= SHELL_SUCCESS
;
348 TargetLocation
= 0xFFFF;
351 CurHandle
= ConvertHandleIndexToHandle(HandleNumber
);
352 if (CurHandle
== NULL
) {
353 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", L
"Handle Number");
354 ShellStatus
= SHELL_INVALID_PARAMETER
;
356 if (Target
== BcfgTargetBootOrder
) {
358 //Make sure that the handle should point to a real controller
360 Status
= PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
362 &DriverBindingHandleCount
,
365 Status
= PARSE_HANDLE_DATABASE_PARENTS (
367 &ParentControllerHandleCount
,
370 Status
= ParseHandleDatabaseForChildControllers (
372 &ChildControllerHandleCount
,
375 if (DriverBindingHandleCount
> 0
376 || ParentControllerHandleCount
> 0
377 || ChildControllerHandleCount
> 0) {
379 Status
= gBS
->HandleProtocol (
381 &gEfiDevicePathProtocolGuid
,
384 if (EFI_ERROR (Status
)) {
385 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_HANDLE
), gShellBcfgHiiHandle
, L
"bcfg", HandleNumber
);
386 ShellStatus
= SHELL_INVALID_PARAMETER
;
390 //Make sure that the handle should point to driver, not a controller.
392 Status
= PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
394 &DriverBindingHandleCount
,
397 Status
= PARSE_HANDLE_DATABASE_PARENTS (
399 &ParentControllerHandleCount
,
402 Status
= ParseHandleDatabaseForChildControllers (
404 &ChildControllerHandleCount
,
407 Status
= gBS
->HandleProtocol (
409 &gEfiDevicePathProtocolGuid
,
412 if (DriverBindingHandleCount
> 0
413 || ParentControllerHandleCount
> 0
414 || ChildControllerHandleCount
> 0
415 || !EFI_ERROR(Status
) ) {
416 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", L
"Handle Number");
417 ShellStatus
= SHELL_INVALID_PARAMETER
;
420 // Get the DevicePath from the loaded image information.
422 Status
= GetDevicePathForDriverHandle(CurHandle
, &FilePath
);
430 ShellOpenFileMetaArg ((CHAR16
*)File
, EFI_FILE_MODE_READ
, &FileList
);
432 if (FileList
== NULL
) {
434 // If filename matched nothing fail
436 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL
), gShellBcfgHiiHandle
, L
"bcfg", File
);
437 ShellStatus
= SHELL_INVALID_PARAMETER
;
438 } else if (FileList
->Link
.ForwardLink
!= FileList
->Link
.BackLink
) {
440 // If filename expanded to multiple names, fail
442 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_FILE
), gShellBcfgHiiHandle
, L
"bcfg", File
);
443 ShellStatus
= SHELL_INVALID_PARAMETER
;
445 Arg
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&FileList
->Link
);
446 if (EFI_ERROR(Arg
->Status
)) {
447 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_FILE_OPEN
), gShellBcfgHiiHandle
, L
"bcfg", File
);
448 ShellStatus
= SHELL_INVALID_PARAMETER
;
451 // Build FilePath to the filename
455 // get the device path
457 DevicePath
= gEfiShellProtocol
->GetDevicePathFromFilePath(Arg
->FullName
);
458 if (DevicePath
== NULL
) {
459 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_FILE_DP
), gShellBcfgHiiHandle
, L
"bcfg", Arg
->FullName
);
460 ShellStatus
= SHELL_UNSUPPORTED
;
463 DevPath
= DevicePath
;
464 ShellStatus
= SHELL_INVALID_PARAMETER
;
465 while (!IsDevicePathEnd(DevPath
)) {
466 if ((DevicePathType(DevPath
) == MEDIA_DEVICE_PATH
) &&
467 (DevicePathSubType(DevPath
) == MEDIA_HARDDRIVE_DP
)) {
470 // If we find it use it instead
472 ShellStatus
= SHELL_SUCCESS
;
473 FilePath
= DuplicateDevicePath (DevPath
);
476 DevPath
= NextDevicePathNode(DevPath
);
479 FilePath
= DuplicateDevicePath(DevicePath
);
481 FreePool(DevicePath
);
488 if (ShellStatus
== SHELL_SUCCESS
) {
490 // Find a free target ,a brute force implementation
493 for (TargetLocation
=0; TargetLocation
< 0xFFFF; TargetLocation
++) {
495 for (Index
=0; Index
< OrderCount
; Index
++) {
496 if (CurrentOrder
[Index
] == TargetLocation
) {
507 if (TargetLocation
== 0xFFFF) {
508 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_TARGET_NF
), gShellBcfgHiiHandle
, L
"bcfg");
510 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_TARGET
), gShellBcfgHiiHandle
, TargetLocation
);
514 if (ShellStatus
== SHELL_SUCCESS
) {
518 DescSize
= StrSize(Desc
);
519 FilePathSize
= GetDevicePathSize (FilePath
);
521 TempByteBuffer
= AllocateZeroPool(sizeof(UINT32
) + sizeof(UINT16
) + DescSize
+ FilePathSize
);
522 if (TempByteBuffer
!= NULL
) {
523 TempByteStart
= TempByteBuffer
;
524 *((UINT32
*) TempByteBuffer
) = LOAD_OPTION_ACTIVE
; // Attributes
525 TempByteBuffer
+= sizeof (UINT32
);
527 *((UINT16
*) TempByteBuffer
) = (UINT16
)FilePathSize
; // FilePathListLength
528 TempByteBuffer
+= sizeof (UINT16
);
530 CopyMem (TempByteBuffer
, Desc
, DescSize
);
531 TempByteBuffer
+= DescSize
;
532 ASSERT (FilePath
!= NULL
);
533 CopyMem (TempByteBuffer
, FilePath
, FilePathSize
);
535 UnicodeSPrint (OptionStr
, sizeof(OptionStr
), L
"%s%04x", Target
== BcfgTargetBootOrder
?L
"Boot":L
"Driver", TargetLocation
);
536 Status
= gRT
->SetVariable (
538 &gEfiGlobalVariableGuid
,
539 EFI_VARIABLE_NON_VOLATILE
|EFI_VARIABLE_BOOTSERVICE_ACCESS
|EFI_VARIABLE_RUNTIME_ACCESS
,
540 sizeof(UINT32
) + sizeof(UINT16
) + DescSize
+ FilePathSize
,
544 FreePool(TempByteStart
);
546 Status
= EFI_OUT_OF_RESOURCES
;
549 if (EFI_ERROR(Status
)) {
550 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL
), gShellBcfgHiiHandle
, L
"bcfg", OptionStr
);
552 NewOrder
= AllocateZeroPool ((OrderCount
+ 1) * sizeof (NewOrder
[0]));
553 if (NewOrder
!= NULL
) {
554 CopyMem (NewOrder
, CurrentOrder
, (OrderCount
) * sizeof (NewOrder
[0]));
557 // Insert target into order list
559 for (Index
= OrderCount
; Index
> Position
; Index
--) {
560 NewOrder
[Index
] = NewOrder
[Index
- 1];
563 NewOrder
[Position
] = (UINT16
) TargetLocation
;
564 Status
= gRT
->SetVariable (
565 Target
== BcfgTargetBootOrder
? L
"BootOrder" : L
"DriverOrder",
566 &gEfiGlobalVariableGuid
,
567 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
568 (OrderCount
+ 1) * sizeof (UINT16
),
574 if (EFI_ERROR (Status
)) {
575 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_BCFG_WRITE_FAIL
), gShellBcfgHiiHandle
, L
"bcfg", Target
== BcfgTargetBootOrder
? L
"BootOrder" : L
"DriverOrder");
576 ShellStatus
= SHELL_INVALID_PARAMETER
;
578 Print (L
"bcfg: Add %s as %x\n", OptionStr
, Position
);
585 //If always Free FilePath, will free devicepath in system when use "addh"
587 if (FilePath
!=NULL
&& !UseHandle
) {
595 if (Handles
!= NULL
) {
599 if (FileList
!= NULL
) {
600 ShellCloseFileMetaArg (&FileList
);
603 return (ShellStatus
);
607 Funciton to remove an item.
609 @param[in] Target The target item to move.
610 @param[in] CurrentOrder The pointer to the current order of items.
611 @param[in] OrderCount The number if items in CurrentOrder.
612 @param[in] Location The current location of the Target.
614 @retval SHELL_SUCCESS The operation was successful.
615 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
619 IN CONST BCFG_OPERATION_TARGET Target
,
620 IN CONST UINT16
*CurrentOrder
,
621 IN CONST UINTN OrderCount
,
622 IN CONST UINT16 Location
625 CHAR16 VariableName
[12];
630 UnicodeSPrint(VariableName
, sizeof(VariableName
), L
"%s%04x", Target
== BcfgTargetBootOrder
?L
"Boot":L
"Driver", CurrentOrder
[Location
]);
631 Status
= gRT
->SetVariable(
633 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
634 EFI_VARIABLE_NON_VOLATILE
|EFI_VARIABLE_BOOTSERVICE_ACCESS
|EFI_VARIABLE_RUNTIME_ACCESS
,
637 if (EFI_ERROR(Status
)) {
638 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_WRITE_FAIL
), gShellBcfgHiiHandle
, L
"bcfg", VariableName
);
639 return (SHELL_INVALID_PARAMETER
);
641 NewOrder
= AllocateZeroPool(OrderCount
*sizeof(CurrentOrder
[0]));
642 if (NewOrder
!= NULL
) {
643 NewCount
= OrderCount
;
644 CopyMem(NewOrder
, CurrentOrder
, OrderCount
*sizeof(CurrentOrder
[0]));
645 CopyMem(NewOrder
+Location
, NewOrder
+Location
+1, (OrderCount
- Location
- 1)*sizeof(CurrentOrder
[0]));
648 Status
= gRT
->SetVariable(
649 Target
== BcfgTargetBootOrder
?(CHAR16
*)L
"BootOrder":(CHAR16
*)L
"DriverOrder",
650 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
651 EFI_VARIABLE_NON_VOLATILE
|EFI_VARIABLE_BOOTSERVICE_ACCESS
|EFI_VARIABLE_RUNTIME_ACCESS
,
652 NewCount
*sizeof(NewOrder
[0]),
656 Status
= EFI_OUT_OF_RESOURCES
;
658 if (EFI_ERROR(Status
)) {
659 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_WRITE_FAIL
), gShellBcfgHiiHandle
, L
"bcfg", Target
== BcfgTargetBootOrder
?(CHAR16
*)L
"BootOrder":(CHAR16
*)L
"DriverOrder");
660 return (SHELL_INVALID_PARAMETER
);
662 return (SHELL_SUCCESS
);
666 Funciton to move a item to another location.
668 @param[in] Target The target item to move.
669 @param[in] CurrentOrder The pointer to the current order of items.
670 @param[in] OrderCount The number if items in CurrentOrder.
671 @param[in] OldLocation The current location of the Target.
672 @param[in] NewLocation The desired location of the Target.
674 @retval SHELL_SUCCESS The operation was successful.
675 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
679 IN CONST BCFG_OPERATION_TARGET Target
,
680 IN CONST UINT16
*CurrentOrder
,
681 IN CONST UINTN OrderCount
,
682 IN CONST UINT16 OldLocation
,
683 IN UINT16 NewLocation
690 NewOrder
= AllocateCopyPool(OrderCount
*sizeof(CurrentOrder
[0]), CurrentOrder
);
691 if (NewOrder
== NULL
) {
692 return (SHELL_OUT_OF_RESOURCES
);
696 // correct the new location
698 if (NewLocation
>= OrderCount
) {
699 if (OrderCount
> 0) {
700 NewLocation
= (UINT16
)OrderCount
- 1;
706 Temp
= CurrentOrder
[OldLocation
];
707 CopyMem(NewOrder
+OldLocation
, NewOrder
+OldLocation
+1, (OrderCount
- OldLocation
- 1)*sizeof(CurrentOrder
[0]));
708 CopyMem(NewOrder
+NewLocation
+1, NewOrder
+NewLocation
, (OrderCount
- NewLocation
- 1)*sizeof(CurrentOrder
[0]));
709 NewOrder
[NewLocation
] = Temp
;
711 Status
= gRT
->SetVariable(
712 Target
== BcfgTargetBootOrder
?(CHAR16
*)L
"BootOrder":(CHAR16
*)L
"DriverOrder",
713 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
714 EFI_VARIABLE_NON_VOLATILE
|EFI_VARIABLE_BOOTSERVICE_ACCESS
|EFI_VARIABLE_RUNTIME_ACCESS
,
715 OrderCount
*sizeof(CurrentOrder
[0]),
720 if (EFI_ERROR(Status
)) {
721 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_WRITE_FAIL
), gShellBcfgHiiHandle
, L
"bcfg", Target
== BcfgTargetBootOrder
?(CHAR16
*)L
"BootOrder":(CHAR16
*)L
"DriverOrder");
722 return (SHELL_INVALID_PARAMETER
);
724 return (SHELL_SUCCESS
);
728 Function to add optional data to an option.
730 @param[in] OptData The optional data to add.
731 @param[in] CurrentOrder The pointer to the current order of items.
732 @param[in] OrderCount The number if items in CurrentOrder.
733 @param[in] Target The target of the operation.
735 @retval SHELL_SUCCESS The operation was succesful.
739 IN CONST CHAR16
*OptData
,
740 IN CONST UINT16
*CurrentOrder
,
741 IN CONST UINTN OrderCount
,
742 IN CONST BCFG_OPERATION_TARGET Target
745 EFI_KEY_OPTION NewKeyOption
;
746 EFI_KEY_OPTION
*KeyOptionBuffer
;
747 SHELL_STATUS ShellStatus
;
753 CONST CHAR16
*Walker
;
758 CHAR16 VariableName
[12];
761 SHELL_FILE_HANDLE FileHandle
;
763 Status
= EFI_SUCCESS
;
764 ShellStatus
= SHELL_SUCCESS
;
768 KeyOptionBuffer
= NULL
;
771 ZeroMem(&NewKeyOption
, sizeof(EFI_KEY_OPTION
));
772 ZeroMem(VariableName
, sizeof(VariableName
));
774 while(Walker
[0] == L
' ') {
779 // Get the index of the variable we are changing.
781 Status
= ShellConvertStringToUint64(Walker
, &Intermediate
, FALSE
, TRUE
);
782 if (EFI_ERROR(Status
) || (((UINT16
)Intermediate
) != Intermediate
) || StrStr(Walker
, L
" ") == NULL
|| ((UINT16
)Intermediate
) > ((UINT16
)OrderCount
)) {
783 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", L
"Option Index");
784 ShellStatus
= SHELL_INVALID_PARAMETER
;
785 return (ShellStatus
);
787 OptionIndex
= (UINT16
)Intermediate
;
789 Temp
= StrStr(Walker
, L
" ");
793 while(Walker
[0] == L
' ') {
798 // determine whether we have file with data, quote delimited information, or a hot-key
800 if (Walker
[0] == L
'\"') {
802 // quoted filename or quoted information.
804 Temp
= StrStr(Walker
+1, L
"\"");
805 if (Temp
== NULL
|| StrLen(Temp
) != 1) {
806 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", Walker
);
807 ShellStatus
= SHELL_INVALID_PARAMETER
;
809 FileName
= StrnCatGrow(&FileName
, NULL
, Walker
+1, 0);
810 if (FileName
== NULL
) {
811 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_OUT_MEM
), gShellBcfgHiiHandle
, L
"bcfg");
812 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
813 return (ShellStatus
);
815 Temp2
= StrStr(FileName
, L
"\"");
816 ASSERT(Temp2
!= NULL
);
817 Temp2
[0] = CHAR_NULL
;
819 if (StrLen(Temp2
)>0) {
820 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", Walker
);
821 ShellStatus
= SHELL_INVALID_PARAMETER
;
823 if (EFI_ERROR(ShellFileExists(Walker
))) {
825 // Not a file. must be misc information.
830 FileName
= StrnCatGrow(&FileName
, NULL
, Walker
, 0);
835 // filename or hot key information.
837 if (StrStr(Walker
, L
" ") == NULL
) {
841 if (EFI_ERROR(ShellFileExists(Walker
))) {
842 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FIND_FAIL
), gShellBcfgHiiHandle
, L
"bcfg", Walker
);
843 ShellStatus
= SHELL_INVALID_PARAMETER
;
845 FileName
= StrnCatGrow(&FileName
, NULL
, Walker
, 0);
848 if (Target
!= BcfgTargetBootOrder
) {
849 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_BOOT_ONLY
), gShellBcfgHiiHandle
, L
"bcfg");
850 ShellStatus
= SHELL_INVALID_PARAMETER
;
853 if (ShellStatus
== SHELL_SUCCESS
) {
855 // Get hot key information
857 Status
= ShellConvertStringToUint64(Walker
, &Intermediate
, FALSE
, TRUE
);
858 if (EFI_ERROR(Status
) || (((UINT32
)Intermediate
) != Intermediate
) || StrStr(Walker
, L
" ") == NULL
) {
859 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", Walker
);
860 ShellStatus
= SHELL_INVALID_PARAMETER
;
862 NewKeyOption
.KeyData
.PackedValue
= (UINT32
)Intermediate
;
863 Temp
= StrStr(Walker
, L
" ");
867 while(Walker
[0] == L
' ') {
872 if (ShellStatus
== SHELL_SUCCESS
) {
874 // Now we know how many EFI_INPUT_KEY structs we need to attach to the end of the EFI_KEY_OPTION struct.
875 // Re-allocate with the added information.
877 KeyOptionBuffer
= AllocateCopyPool(sizeof(EFI_KEY_OPTION
) + (sizeof(EFI_INPUT_KEY
) * NewKeyOption
.KeyData
.Options
.InputKeyCount
), &NewKeyOption
);
878 if (KeyOptionBuffer
== NULL
) {
879 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_MEM
), gShellBcfgHiiHandle
, L
"bcfg");
880 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
883 for (LoopCounter
= 0 ; ShellStatus
== SHELL_SUCCESS
&& LoopCounter
< NewKeyOption
.KeyData
.Options
.InputKeyCount
; LoopCounter
++) {
887 Status
= ShellConvertStringToUint64(Walker
, &Intermediate
, FALSE
, TRUE
);
888 if (EFI_ERROR(Status
) || (((UINT16
)Intermediate
) != Intermediate
) || StrStr(Walker
, L
" ") == NULL
) {
889 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", Walker
);
890 ShellStatus
= SHELL_INVALID_PARAMETER
;
892 ((EFI_INPUT_KEY
*)(((UINT8
*)KeyOptionBuffer
) + sizeof(EFI_KEY_OPTION
)))[LoopCounter
].ScanCode
= (UINT16
)Intermediate
;
893 Temp
= StrStr(Walker
, L
" ");
897 while(Walker
[0] == L
' ') {
904 Status
= ShellConvertStringToUint64(Walker
, &Intermediate
, FALSE
, TRUE
);
905 if (EFI_ERROR(Status
) || (((UINT16
)Intermediate
) != Intermediate
)) {
906 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", Walker
);
907 ShellStatus
= SHELL_INVALID_PARAMETER
;
909 ((EFI_INPUT_KEY
*)(((UINT8
*)KeyOptionBuffer
) + sizeof(EFI_KEY_OPTION
)))[LoopCounter
].UnicodeChar
= (UINT16
)Intermediate
;
910 Temp
= StrStr(Walker
, L
" ");
914 while(Walker
[0] == L
' ') {
919 if (ShellStatus
== SHELL_SUCCESS
) {
921 // Now do the BootOption / BootOptionCrc
923 ASSERT (OptionIndex
<= OrderCount
);
924 KeyOptionBuffer
->BootOption
= CurrentOrder
[OptionIndex
];
925 Status
= GetBootOptionCrc(&(KeyOptionBuffer
->BootOptionCrc
), KeyOptionBuffer
->BootOption
);
926 if (EFI_ERROR(Status
)) {
927 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", L
"Option Index");
928 ShellStatus
= SHELL_INVALID_PARAMETER
;
932 if (ShellStatus
== SHELL_SUCCESS
) {
933 for (Temp2
= NULL
, KeyIndex
= 0 ; KeyIndex
<= 0xFFFF ; KeyIndex
++) {
934 UnicodeSPrint(VariableName
, sizeof(VariableName
), L
"Key%04x", KeyIndex
);
935 Status
= GetEfiGlobalVariable2 (VariableName
, &VariableData
, NULL
);
936 if (Status
== EFI_NOT_FOUND
) {
939 if (!EFI_ERROR(Status
)) {
940 SHELL_FREE_NON_NULL(VariableData
);
943 if (KeyIndex
<= 0xFFFF) {
944 Status
= gRT
->SetVariable(
946 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
947 EFI_VARIABLE_NON_VOLATILE
|EFI_VARIABLE_BOOTSERVICE_ACCESS
|EFI_VARIABLE_RUNTIME_ACCESS
,
948 sizeof(EFI_KEY_OPTION
) + (sizeof(EFI_INPUT_KEY
) * NewKeyOption
.KeyData
.Options
.InputKeyCount
),
950 if (EFI_ERROR(Status
)) {
951 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL
), gShellBcfgHiiHandle
, L
"bcfg", VariableName
);
952 ShellStatus
= SHELL_INVALID_PARAMETER
;
955 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_VAR_NO_NUM
), gShellBcfgHiiHandle
, L
"bcfg");
956 ShellStatus
= SHELL_INVALID_PARAMETER
;
958 ASSERT(FileName
== NULL
&& Data
== NULL
);
964 // Shouldn't be possible to have have both. Neither is ok though.
966 ASSERT(FileName
== NULL
|| Data
== NULL
);
968 if (ShellStatus
== SHELL_SUCCESS
&& (FileName
!= NULL
|| Data
!= NULL
)) {
969 if (FileName
!= NULL
) {
971 // Open the file and populate the data buffer.
973 Status
= ShellOpenFileByName(
978 if (!EFI_ERROR(Status
)) {
979 Status
= ShellGetFileSize(FileHandle
, &Intermediate
);
981 Data
= AllocateZeroPool((UINTN
)Intermediate
);
983 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_MEM
), gShellBcfgHiiHandle
, L
"bcfg");
984 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
986 if (!EFI_ERROR(Status
)) {
987 Status
= ShellReadFile(FileHandle
, (UINTN
*)&Intermediate
, Data
);
990 Intermediate
= StrSize(Data
);
993 if (!EFI_ERROR(Status
) && ShellStatus
== SHELL_SUCCESS
&& Data
!= NULL
) {
994 Status
= UpdateOptionalData(CurrentOrder
[OptionIndex
], (UINTN
)Intermediate
, (UINT8
*)Data
, Target
);
995 if (EFI_ERROR(Status
)) {
996 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL
), gShellBcfgHiiHandle
, L
"bcfg", VariableName
);
997 ShellStatus
= SHELL_INVALID_PARAMETER
;
1000 if (EFI_ERROR(Status
) && ShellStatus
== SHELL_SUCCESS
) {
1001 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL
), gShellBcfgHiiHandle
, L
"bcfg", VariableName
);
1002 ShellStatus
= SHELL_INVALID_PARAMETER
;
1006 SHELL_FREE_NON_NULL(Data
);
1007 SHELL_FREE_NON_NULL(KeyOptionBuffer
);
1008 SHELL_FREE_NON_NULL(FileName
);
1013 Function to dump the Bcfg information.
1015 @param[in] Op The operation.
1016 @param[in] OrderCount How many to dump.
1017 @param[in] CurrentOrder The pointer to the current order of items.
1018 @param[in] VerboseOutput TRUE for extra output. FALSE otherwise.
1020 @retval SHELL_SUCCESS The dump was successful.
1021 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
1025 IN CONST CHAR16
*Op
,
1026 IN CONST UINTN OrderCount
,
1027 IN CONST UINT16
*CurrentOrder
,
1028 IN CONST BOOLEAN VerboseOutput
1034 CHAR16 VariableName
[12];
1036 CHAR16
*DevPathString
;
1039 EFI_LOAD_OPTION
*LoadOption
;
1040 CHAR16
*Description
;
1041 UINTN DescriptionSize
;
1042 UINTN OptionalDataOffset
;
1044 if (OrderCount
== 0) {
1045 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_BCFG_NONE
), gShellBcfgHiiHandle
, L
"bcfg");
1046 return (SHELL_SUCCESS
);
1051 for (LoopVar
= 0 ; LoopVar
< OrderCount
; LoopVar
++) {
1054 DevPathString
= NULL
;
1056 UnicodeSPrint(VariableName
, sizeof(VariableName
), L
"%s%04x", Op
, CurrentOrder
[LoopVar
]);
1058 Status
= gRT
->GetVariable(
1060 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
1064 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1065 Buffer
= AllocateZeroPool(BufferSize
);
1066 Status
= gRT
->GetVariable(
1068 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
1074 if (EFI_ERROR(Status
) || Buffer
== NULL
) {
1075 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_READ_FAIL
), gShellBcfgHiiHandle
, L
"bcfg", VariableName
);
1081 // We expect the Attributes, FilePathListLength, and L'\0'-terminated
1082 // Description fields to be present.
1084 if (BufferSize
< sizeof *LoadOption
+ sizeof (CHAR16
)) {
1089 STRING_TOKEN (STR_BCFG_VAR_CORRUPT
),
1090 gShellBcfgHiiHandle
,
1098 LoadOption
= (EFI_LOAD_OPTION
*)Buffer
;
1099 Description
= (CHAR16
*)(Buffer
+ sizeof (EFI_LOAD_OPTION
));
1100 DescriptionSize
= StrSize (Description
);
1102 if (LoadOption
->FilePathListLength
!= 0) {
1103 FilePathList
= (UINT8
*)Description
+ DescriptionSize
;
1104 DevPathString
= ConvertDevicePathToText(FilePathList
, TRUE
, FALSE
);
1107 OptionalDataOffset
= sizeof *LoadOption
+ DescriptionSize
+
1108 LoadOption
->FilePathListLength
;
1114 STRING_TOKEN(STR_BCFG_LOAD_OPTIONS
),
1115 gShellBcfgHiiHandle
,
1120 OptionalDataOffset
>= BufferSize
? L
'N' : L
'Y'
1122 if (VerboseOutput
&& (OptionalDataOffset
< BufferSize
)) {
1125 0, // Offset (displayed)
1126 BufferSize
- OptionalDataOffset
, // DataSize
1127 Buffer
+ OptionalDataOffset
// UserData
1132 if (Buffer
!= NULL
) {
1135 if (DevPathString
!= NULL
) {
1136 FreePool(DevPathString
);
1139 return (Errors
> 0) ? SHELL_INVALID_PARAMETER
: SHELL_SUCCESS
;
1143 Function to initialize the BCFG operation structure.
1145 @param[in] Struct The stuct to initialize.
1149 IN BGFG_OPERATION
*Struct
1152 ASSERT(Struct
!= NULL
);
1153 Struct
->Target
= BcfgTargetMax
;
1154 Struct
->Type
= BcfgTypeMax
;
1155 Struct
->Number1
= 0;
1156 Struct
->Number2
= 0;
1157 Struct
->HandleIndex
= 0;
1158 Struct
->FileName
= NULL
;
1159 Struct
->Description
= NULL
;
1160 Struct
->Order
= NULL
;
1161 Struct
->OptData
= NULL
;
1165 STATIC CONST SHELL_PARAM_ITEM ParamList
[] = {
1167 {L
"-opt", TypeMaxValue
},
1172 Function for 'bcfg' command.
1174 @param[in] ImageHandle Handle to the Image (NULL if Internal).
1175 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
1179 ShellCommandRunBcfg (
1180 IN EFI_HANDLE ImageHandle
,
1181 IN EFI_SYSTEM_TABLE
*SystemTable
1185 LIST_ENTRY
*Package
;
1186 CHAR16
*ProblemParam
;
1187 SHELL_STATUS ShellStatus
;
1189 CONST CHAR16
*CurrentParam
;
1190 BGFG_OPERATION CurrentOperation
;
1192 UINT64 Intermediate
;
1196 ProblemParam
= NULL
;
1198 ShellStatus
= SHELL_SUCCESS
;
1200 InitBcfgStruct(&CurrentOperation
);
1203 // initialize the shell lib (we must be in non-auto-init...)
1205 Status
= ShellInitialize();
1206 ASSERT_EFI_ERROR(Status
);
1208 Status
= CommandInit();
1209 ASSERT_EFI_ERROR(Status
);
1212 // parse the command line
1214 Status
= ShellCommandLineParse (ParamList
, &Package
, &ProblemParam
, TRUE
);
1215 if (EFI_ERROR(Status
)) {
1216 if (Status
== EFI_VOLUME_CORRUPTED
&& ProblemParam
!= NULL
) {
1217 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellBcfgHiiHandle
, L
"bcfg", ProblemParam
);
1218 FreePool(ProblemParam
);
1219 ShellStatus
= SHELL_INVALID_PARAMETER
;
1225 // Read in if we are doing -OPT
1227 if (ShellCommandLineGetFlag(Package
, L
"-opt")) {
1228 CurrentOperation
.OptData
= ShellCommandLineGetValue(Package
, L
"-opt");
1229 if (CurrentOperation
.OptData
== NULL
) {
1230 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_VALUE
), gShellBcfgHiiHandle
, L
"bcfg", L
"-opt");
1231 ShellStatus
= SHELL_INVALID_PARAMETER
;
1233 CurrentOperation
.Type
= BcfgTypeOpt
;
1237 // small block to read the target of the operation
1239 if ((ShellCommandLineGetCount(Package
) < 3 && CurrentOperation
.Type
!= BcfgTypeOpt
) ||
1240 (ShellCommandLineGetCount(Package
) < 2 && CurrentOperation
.Type
== BcfgTypeOpt
)
1242 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellBcfgHiiHandle
, L
"bcfg");
1243 ShellStatus
= SHELL_INVALID_PARAMETER
;
1244 } else if (gUnicodeCollation
->StriColl(gUnicodeCollation
, (CHAR16
*)ShellCommandLineGetRawValue(Package
, 1), L
"driver") == 0) {
1245 CurrentOperation
.Target
= BcfgTargetDriverOrder
;
1246 } else if (gUnicodeCollation
->StriColl(gUnicodeCollation
, (CHAR16
*)ShellCommandLineGetRawValue(Package
, 1), L
"boot") == 0) {
1247 CurrentOperation
.Target
= BcfgTargetBootOrder
;
1249 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT
), gShellBcfgHiiHandle
, L
"bcfg");
1250 ShellStatus
= SHELL_INVALID_PARAMETER
;
1255 // Read in the boot or driver order environment variable (not needed for opt)
1257 if (ShellStatus
== SHELL_SUCCESS
&& CurrentOperation
.Target
< BcfgTargetMax
) {
1259 Status
= gRT
->GetVariable(
1260 CurrentOperation
.Target
== BcfgTargetBootOrder
?(CHAR16
*)L
"BootOrder":(CHAR16
*)L
"DriverOrder",
1261 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
1264 CurrentOperation
.Order
);
1265 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1266 CurrentOperation
.Order
= AllocateZeroPool(Length
+(4*sizeof(CurrentOperation
.Order
[0])));
1267 if (CurrentOperation
.Order
== NULL
) {
1268 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
1270 Status
= gRT
->GetVariable(
1271 CurrentOperation
.Target
== BcfgTargetBootOrder
?(CHAR16
*)L
"BootOrder":(CHAR16
*)L
"DriverOrder",
1272 (EFI_GUID
*)&gEfiGlobalVariableGuid
,
1275 CurrentOperation
.Order
);
1280 Count
= (UINT16
) (Length
/ sizeof(CurrentOperation
.Order
[0]));
1283 // large block to read the type of operation and verify parameter types for the info.
1285 if (ShellStatus
== SHELL_SUCCESS
&& CurrentOperation
.Target
< BcfgTargetMax
) {
1286 for (ParamNumber
= 2 ; ParamNumber
< ShellCommandLineGetCount(Package
) && ShellStatus
== SHELL_SUCCESS
; ParamNumber
++) {
1287 CurrentParam
= ShellCommandLineGetRawValue(Package
, ParamNumber
);
1288 if (gUnicodeCollation
->StriColl(gUnicodeCollation
, (CHAR16
*)CurrentParam
, L
"dump") == 0) {
1289 CurrentOperation
.Type
= BcfgTypeDump
;
1290 if (ShellCommandLineGetCount(Package
) > 3) {
1291 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellBcfgHiiHandle
, L
"bcfg");
1292 ShellStatus
= SHELL_INVALID_PARAMETER
;
1294 } else if (ShellCommandLineGetFlag(Package
, L
"-v")) {
1295 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", L
"-v (without dump)");
1296 ShellStatus
= SHELL_INVALID_PARAMETER
;
1297 } else if (gUnicodeCollation
->StriColl(gUnicodeCollation
, (CHAR16
*)CurrentParam
, L
"add") == 0) {
1298 if ((ParamNumber
+ 3) >= ShellCommandLineGetCount(Package
)) {
1299 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellBcfgHiiHandle
, L
"bcfg");
1300 ShellStatus
= SHELL_INVALID_PARAMETER
;
1302 CurrentOperation
.Type
= BcfgTypeAdd
;
1303 CurrentParam
= ShellCommandLineGetRawValue(Package
, ++ParamNumber
);
1304 if (CurrentParam
== NULL
|| !ShellIsHexOrDecimalNumber(CurrentParam
, TRUE
, FALSE
)) {
1305 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", CurrentParam
);
1306 ShellStatus
= SHELL_INVALID_PARAMETER
;
1308 Status
= ShellConvertStringToUint64(CurrentParam
, &Intermediate
, TRUE
, FALSE
);
1309 CurrentOperation
.Number1
= (UINT16
)Intermediate
;
1310 ASSERT(CurrentOperation
.FileName
== NULL
);
1311 CurrentOperation
.FileName
= StrnCatGrow(&CurrentOperation
.FileName
, NULL
, ShellCommandLineGetRawValue(Package
, ++ParamNumber
), 0);
1312 ASSERT(CurrentOperation
.Description
== NULL
);
1313 CurrentOperation
.Description
= StrnCatGrow(&CurrentOperation
.Description
, NULL
, ShellCommandLineGetRawValue(Package
, ++ParamNumber
), 0);
1315 } else if (gUnicodeCollation
->StriColl(gUnicodeCollation
, (CHAR16
*)CurrentParam
, L
"addp") == 0) {
1316 if ((ParamNumber
+ 3) >= ShellCommandLineGetCount(Package
)) {
1317 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellBcfgHiiHandle
, L
"bcfg");
1318 ShellStatus
= SHELL_INVALID_PARAMETER
;
1320 CurrentOperation
.Type
= BcfgTypeAddp
;
1321 CurrentParam
= ShellCommandLineGetRawValue(Package
, ++ParamNumber
);
1322 if (CurrentParam
== NULL
|| !ShellIsHexOrDecimalNumber(CurrentParam
, TRUE
, FALSE
)) {
1323 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", CurrentParam
);
1324 ShellStatus
= SHELL_INVALID_PARAMETER
;
1326 Status
= ShellConvertStringToUint64(CurrentParam
, &Intermediate
, TRUE
, FALSE
);
1327 CurrentOperation
.Number1
= (UINT16
)Intermediate
;
1328 ASSERT(CurrentOperation
.FileName
== NULL
);
1329 CurrentOperation
.FileName
= StrnCatGrow(&CurrentOperation
.FileName
, NULL
, ShellCommandLineGetRawValue(Package
, ++ParamNumber
), 0);
1330 ASSERT(CurrentOperation
.Description
== NULL
);
1331 CurrentOperation
.Description
= StrnCatGrow(&CurrentOperation
.Description
, NULL
, ShellCommandLineGetRawValue(Package
, ++ParamNumber
), 0);
1333 } else if (gUnicodeCollation
->StriColl(gUnicodeCollation
, (CHAR16
*)CurrentParam
, L
"addh") == 0) {
1334 if ((ParamNumber
+ 3) >= ShellCommandLineGetCount(Package
)) {
1335 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellBcfgHiiHandle
, L
"bcfg");
1336 ShellStatus
= SHELL_INVALID_PARAMETER
;
1338 CurrentOperation
.Type
= BcfgTypeAddh
;
1339 CurrentParam
= ShellCommandLineGetRawValue(Package
, ++ParamNumber
);
1340 if (CurrentParam
== NULL
|| !ShellIsHexOrDecimalNumber(CurrentParam
, TRUE
, FALSE
)) {
1341 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", CurrentParam
);
1342 ShellStatus
= SHELL_INVALID_PARAMETER
;
1344 Status
= ShellConvertStringToUint64(CurrentParam
, &Intermediate
, TRUE
, FALSE
);
1345 CurrentOperation
.Number1
= (UINT16
)Intermediate
;
1346 CurrentParam
= ShellCommandLineGetRawValue(Package
, ++ParamNumber
);
1347 if (CurrentParam
== NULL
|| !ShellIsHexOrDecimalNumber(CurrentParam
, TRUE
, FALSE
)) {
1348 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", CurrentParam
);
1349 ShellStatus
= SHELL_INVALID_PARAMETER
;
1351 Status
= ShellConvertStringToUint64(CurrentParam
, &Intermediate
, TRUE
, FALSE
);
1352 CurrentOperation
.HandleIndex
= (UINT16
)Intermediate
;
1353 ASSERT(CurrentOperation
.Description
== NULL
);
1354 CurrentOperation
.Description
= StrnCatGrow(&CurrentOperation
.Description
, NULL
, ShellCommandLineGetRawValue(Package
, ++ParamNumber
), 0);
1357 } else if (gUnicodeCollation
->StriColl(gUnicodeCollation
, (CHAR16
*)CurrentParam
, L
"rm") == 0) {
1358 if ((ParamNumber
+ 1) >= ShellCommandLineGetCount(Package
)) {
1359 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellBcfgHiiHandle
, L
"bcfg");
1360 ShellStatus
= SHELL_INVALID_PARAMETER
;
1362 CurrentOperation
.Type
= BcfgTypeRm
;
1363 CurrentParam
= ShellCommandLineGetRawValue(Package
, ++ParamNumber
);
1364 if (CurrentParam
== NULL
|| !ShellIsHexOrDecimalNumber(CurrentParam
, TRUE
, FALSE
)) {
1365 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", CurrentParam
);
1366 ShellStatus
= SHELL_INVALID_PARAMETER
;
1368 Status
= ShellConvertStringToUint64(CurrentParam
, &Intermediate
, TRUE
, FALSE
);
1369 CurrentOperation
.Number1
= (UINT16
)Intermediate
;
1370 if (CurrentOperation
.Number1
>= Count
){
1371 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_NUMB_RANGE
), gShellBcfgHiiHandle
, L
"bcfg", Count
);
1372 ShellStatus
= SHELL_INVALID_PARAMETER
;
1375 } else if (gUnicodeCollation
->StriColl(gUnicodeCollation
, (CHAR16
*)CurrentParam
, L
"mv") == 0) {
1376 if ((ParamNumber
+ 2) >= ShellCommandLineGetCount(Package
)) {
1377 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellBcfgHiiHandle
, L
"bcfg");
1378 ShellStatus
= SHELL_INVALID_PARAMETER
;
1380 CurrentOperation
.Type
= BcfgTypeMv
;
1381 CurrentParam
= ShellCommandLineGetRawValue(Package
, ++ParamNumber
);
1382 if (CurrentParam
== NULL
|| !ShellIsHexOrDecimalNumber(CurrentParam
, TRUE
, FALSE
)) {
1383 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", CurrentParam
);
1384 ShellStatus
= SHELL_INVALID_PARAMETER
;
1386 Status
= ShellConvertStringToUint64(CurrentParam
, &Intermediate
, TRUE
, FALSE
);
1387 CurrentOperation
.Number1
= (UINT16
)Intermediate
;
1388 if (CurrentOperation
.Number1
>= Count
){
1389 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_NUMB_RANGE
), gShellBcfgHiiHandle
, L
"bcfg", Count
);
1390 ShellStatus
= SHELL_INVALID_PARAMETER
;
1392 CurrentParam
= ShellCommandLineGetRawValue(Package
, ++ParamNumber
);
1393 if (CurrentParam
== NULL
|| !ShellIsHexOrDecimalNumber(CurrentParam
, TRUE
, FALSE
)) {
1394 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", CurrentParam
);
1395 ShellStatus
= SHELL_INVALID_PARAMETER
;
1397 Status
= ShellConvertStringToUint64(CurrentParam
, &Intermediate
, TRUE
, FALSE
);
1398 CurrentOperation
.Number2
= (UINT16
)Intermediate
;
1400 if (CurrentOperation
.Number2
== CurrentOperation
.Number1
1401 ||CurrentOperation
.Number2
>= Count
1403 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_BCFG_NUMB_RANGE
), gShellBcfgHiiHandle
, L
"bcfg", Count
);
1404 ShellStatus
= SHELL_INVALID_PARAMETER
;
1409 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellBcfgHiiHandle
, L
"bcfg", CurrentParam
);
1410 ShellStatus
= SHELL_INVALID_PARAMETER
;
1414 if (ShellStatus
== SHELL_SUCCESS
&& CurrentOperation
.Target
< BcfgTargetMax
&& CurrentOperation
.Type
< BcfgTypeMax
) {
1416 // we have all the info. Do the work
1418 switch (CurrentOperation
.Type
) {
1420 ShellStatus
= BcfgDisplayDump(
1421 CurrentOperation
.Target
== BcfgTargetBootOrder
?L
"Boot":L
"Driver",
1423 CurrentOperation
.Order
,
1424 ShellCommandLineGetFlag(Package
, L
"-v"));
1427 ShellStatus
= BcfgMove(
1428 CurrentOperation
.Target
,
1429 CurrentOperation
.Order
,
1431 CurrentOperation
.Number1
,
1432 CurrentOperation
.Number2
);
1435 ShellStatus
= BcfgRemove(
1436 CurrentOperation
.Target
,
1437 CurrentOperation
.Order
,
1439 CurrentOperation
.Number1
);
1444 ShellStatus
= BcfgAdd(
1445 CurrentOperation
.Number1
,
1446 CurrentOperation
.FileName
,
1447 CurrentOperation
.Description
==NULL
?L
"":CurrentOperation
.Description
,
1448 CurrentOperation
.Order
,
1450 CurrentOperation
.Target
,
1451 (BOOLEAN
)(CurrentOperation
.Type
== BcfgTypeAddh
),
1452 (BOOLEAN
)(CurrentOperation
.Type
== BcfgTypeAddp
),
1453 CurrentOperation
.HandleIndex
);
1456 ShellStatus
= BcfgAddOpt(
1457 CurrentOperation
.OptData
,
1458 CurrentOperation
.Order
,
1460 CurrentOperation
.Target
);
1468 if (Package
!= NULL
) {
1469 ShellCommandLineFreeVarList (Package
);
1471 if (CurrentOperation
.FileName
!= NULL
) {
1472 FreePool(CurrentOperation
.FileName
);
1474 if (CurrentOperation
.Description
!= NULL
) {
1475 FreePool(CurrentOperation
.Description
);
1477 if (CurrentOperation
.Order
!= NULL
) {
1478 FreePool(CurrentOperation
.Order
);
1481 return (ShellStatus
);
1486 Function to get the filename with help context if HII will not be used.
1488 @return The filename with help text in it.
1492 ShellCommandGetManFileNameBcfg (
1500 "Constructor" for the library.
1502 This will register the handler for the bcfg command.
1504 @param[in] ImageHandle the image handle of the process
1505 @param[in] SystemTable the EFI System Table pointer
1506 @param[in] Name the profile name to use
1508 @retval EFI_SUCCESS the shell command handlers were installed sucessfully
1509 @retval EFI_UNSUPPORTED the shell level required was not found.
1513 BcfgLibraryRegisterBcfgCommand (
1514 IN EFI_HANDLE ImageHandle
,
1515 IN EFI_SYSTEM_TABLE
*SystemTable
,
1516 IN CONST CHAR16
*Name
1519 if (gShellBcfgHiiHandle
!= NULL
) {
1520 return (EFI_SUCCESS
);
1523 gShellBcfgHiiHandle
= HiiAddPackages (&gShellBcfgHiiGuid
, gImageHandle
, UefiShellBcfgCommandLibStrings
, NULL
);
1524 if (gShellBcfgHiiHandle
== NULL
) {
1525 return (EFI_DEVICE_ERROR
);
1529 // install our shell command handler
1531 ShellCommandRegisterCommandName(L
"bcfg", ShellCommandRunBcfg
, ShellCommandGetManFileNameBcfg
, 0, Name
, FALSE
, gShellBcfgHiiHandle
, STRING_TOKEN(STR_GET_HELP_BCFG
));
1533 return (EFI_SUCCESS
);
1537 Destructor for the library. free any resources.
1539 @param ImageHandle The image handle of the process.
1540 @param SystemTable The EFI System Table pointer.
1544 BcfgLibraryUnregisterBcfgCommand (
1545 IN EFI_HANDLE ImageHandle
,
1546 IN EFI_SYSTEM_TABLE
*SystemTable
1549 if (gShellBcfgHiiHandle
!= NULL
) {
1550 HiiRemovePackages(gShellBcfgHiiHandle
);
1552 gShellBcfgHiiHandle
= NULL
;
1553 return (EFI_SUCCESS
);