]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ShellPkg / Library / UefiShellBcfgCommandLib / UefiShellBcfgCommandLib.c
1 /** @file
2 Main file for BCFG command.
3
4 (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <Uefi.h>
11
12 #include <Guid/GlobalVariable.h>
13 #include <Guid/ShellLibHiiGuid.h>
14
15 #include <Protocol/Shell.h>
16 #include <Protocol/ShellParameters.h>
17 #include <Protocol/DevicePath.h>
18 #include <Protocol/LoadedImage.h>
19 #include <Protocol/UnicodeCollation.h>
20
21 #include <Library/BaseLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugLib.h>
24 #include <Library/MemoryAllocationLib.h>
25 #include <Library/PcdLib.h>
26 #include <Library/ShellCommandLib.h>
27 #include <Library/ShellLib.h>
28 #include <Library/SortLib.h>
29 #include <Library/UefiLib.h>
30 #include <Library/UefiRuntimeServicesTableLib.h>
31 #include <Library/UefiBootServicesTableLib.h>
32 #include <Library/HiiLib.h>
33 #include <Library/FileHandleLib.h>
34 #include <Library/PrintLib.h>
35 #include <Library/HandleParsingLib.h>
36 #include <Library/DevicePathLib.h>
37 #include <Library/UefiBootManagerLib.h>
38
39 STATIC CONST CHAR16 mFileName[] = L"ShellCommands";
40 STATIC EFI_HII_HANDLE gShellBcfgHiiHandle = NULL;
41
42 typedef enum {
43 BcfgTargetBootOrder = 0,
44 BcfgTargetDriverOrder = 1,
45 BcfgTargetMax = 2
46 } BCFG_OPERATION_TARGET;
47
48 typedef enum {
49 BcfgTypeDump = 0,
50 BcfgTypeAdd = 1,
51 BcfgTypeAddp = 2,
52 BcfgTypeAddh = 3,
53 BcfgTypeRm = 4,
54 BcfgTypeMv = 5,
55 BcfgTypeOpt = 6,
56 BcfgTypeMod = 7,
57 BcfgTypeModf = 8,
58 BcfgTypeModp = 9,
59 BcfgTypeModh = 10,
60 BcfgTypeMax = 11
61 } BCFG_OPERATION_TYPE;
62
63 typedef struct {
64 BCFG_OPERATION_TARGET Target;
65 BCFG_OPERATION_TYPE Type;
66 UINT16 Number1;
67 UINT16 Number2;
68 UINTN HandleIndex;
69 CHAR16 *FileName;
70 CHAR16 *Description;
71 UINT16 *Order;
72 CONST CHAR16 *OptData;
73 } BGFG_OPERATION;
74
75 /**
76 Update the optional data for a boot or driver option.
77
78 If optional data exists it will be changed.
79
80 @param[in] Index The boot or driver option index update.
81 @param[in] DataSize The size in bytes of Data.
82 @param[in] Data The buffer for the optioanl data.
83 @param[in] Target The target of the operation.
84
85 @retval EFI_SUCCESS The data was sucessfully updated.
86 @retval other A error occurred.
87 **/
88 EFI_STATUS
89 UpdateOptionalData (
90 UINT16 Index,
91 UINTN DataSize,
92 UINT8 *Data,
93 IN CONST BCFG_OPERATION_TARGET Target
94 )
95 {
96 EFI_STATUS Status;
97 CHAR16 VariableName[12];
98 UINTN OriginalSize;
99 UINT8 *OriginalData;
100 UINTN NewSize;
101 UINT8 *NewData;
102 UINTN OriginalOptionDataSize;
103
104 UnicodeSPrint (VariableName, sizeof (VariableName), L"%s%04x", Target == BcfgTargetBootOrder ? L"Boot" : L"Driver", Index);
105
106 OriginalSize = 0;
107 OriginalData = NULL;
108 NewData = NULL;
109 NewSize = 0;
110
111 Status = gRT->GetVariable (
112 VariableName,
113 (EFI_GUID *)&gEfiGlobalVariableGuid,
114 NULL,
115 &OriginalSize,
116 OriginalData
117 );
118 if (Status == EFI_BUFFER_TOO_SMALL) {
119 OriginalData = AllocateZeroPool (OriginalSize);
120 if (OriginalData == NULL) {
121 return (EFI_OUT_OF_RESOURCES);
122 }
123
124 Status = gRT->GetVariable (
125 VariableName,
126 (EFI_GUID *)&gEfiGlobalVariableGuid,
127 NULL,
128 &OriginalSize,
129 OriginalData
130 );
131 }
132
133 if (!EFI_ERROR (Status)) {
134 //
135 // Allocate new struct and discard old optional data.
136 //
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 = AllocatePool (NewSize);
143 if (NewData == NULL) {
144 Status = EFI_OUT_OF_RESOURCES;
145 } else {
146 CopyMem (NewData, OriginalData, OriginalSize - OriginalOptionDataSize);
147 CopyMem (NewData + OriginalSize - OriginalOptionDataSize, Data, DataSize);
148 }
149 }
150
151 if (!EFI_ERROR (Status)) {
152 //
153 // put the data back under the variable
154 //
155 Status = gRT->SetVariable (
156 VariableName,
157 (EFI_GUID *)&gEfiGlobalVariableGuid,
158 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
159 NewSize,
160 NewData
161 );
162 }
163
164 SHELL_FREE_NON_NULL (OriginalData);
165 SHELL_FREE_NON_NULL (NewData);
166 return (Status);
167 }
168
169 /**
170 This function will get a CRC for a boot option.
171
172 @param[in, out] Crc The CRC value to return.
173 @param[in] BootIndex The boot option index to CRC.
174
175 @retval EFI_SUCCESS The CRC was sucessfully returned.
176 @retval other A error occurred.
177 **/
178 EFI_STATUS
179 GetBootOptionCrc (
180 UINT32 *Crc,
181 UINT16 BootIndex
182 )
183 {
184 CHAR16 VariableName[12];
185 EFI_STATUS Status;
186 UINT8 *Buffer;
187 UINTN BufferSize;
188
189 Buffer = NULL;
190 BufferSize = 0;
191
192 //
193 // Get the data Buffer
194 //
195 UnicodeSPrint (VariableName, sizeof (VariableName), L"%Boot%04x", BootIndex);
196 Status = gRT->GetVariable (
197 VariableName,
198 (EFI_GUID *)&gEfiGlobalVariableGuid,
199 NULL,
200 &BufferSize,
201 NULL
202 );
203 if (Status == EFI_BUFFER_TOO_SMALL) {
204 Buffer = AllocateZeroPool (BufferSize);
205 Status = gRT->GetVariable (
206 VariableName,
207 (EFI_GUID *)&gEfiGlobalVariableGuid,
208 NULL,
209 &BufferSize,
210 Buffer
211 );
212 }
213
214 //
215 // Get the CRC computed
216 //
217 if (!EFI_ERROR (Status)) {
218 Status = gBS->CalculateCrc32 (Buffer, BufferSize, Crc);
219 }
220
221 SHELL_FREE_NON_NULL (Buffer);
222 return EFI_SUCCESS;
223 }
224
225 /**
226 This function will populate the device path protocol parameter based on TheHandle.
227
228 @param[in] TheHandle Driver handle.
229 @param[in, out] FilePath On a sucessful return the device path to the handle.
230
231 @retval EFI_SUCCESS The device path was sucessfully returned.
232 @retval other A error from gBS->HandleProtocol.
233
234 @sa HandleProtocol
235 **/
236 EFI_STATUS
237 GetDevicePathForDriverHandle (
238 IN EFI_HANDLE TheHandle,
239 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
240 )
241 {
242 EFI_STATUS Status;
243 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
244 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
245
246 Status = gBS->OpenProtocol (
247 TheHandle,
248 &gEfiLoadedImageProtocolGuid,
249 (VOID **)&LoadedImage,
250 gImageHandle,
251 NULL,
252 EFI_OPEN_PROTOCOL_GET_PROTOCOL
253 );
254 if (!EFI_ERROR (Status)) {
255 Status = gBS->OpenProtocol (
256 LoadedImage->DeviceHandle,
257 &gEfiDevicePathProtocolGuid,
258 (VOID **)&ImageDevicePath,
259 gImageHandle,
260 NULL,
261 EFI_OPEN_PROTOCOL_GET_PROTOCOL
262 );
263 if (!EFI_ERROR (Status)) {
264 // *DevPath = DuplicateDevicePath (ImageDevicePath);
265 // *FilePath = DuplicateDevicePath (LoadedImage->FilePath);
266 *FilePath = AppendDevicePath (ImageDevicePath, LoadedImage->FilePath);
267 gBS->CloseProtocol (
268 LoadedImage->DeviceHandle,
269 &gEfiDevicePathProtocolGuid,
270 gImageHandle,
271 NULL
272 );
273 }
274
275 gBS->CloseProtocol (
276 TheHandle,
277 &gEfiLoadedImageProtocolGuid,
278 gImageHandle,
279 NULL
280 );
281 }
282
283 return (Status);
284 }
285
286 /**
287 Functino to get Device Path by a handle.
288
289 @param[in] TheHandle Use it to get DevicePath.
290 @param[in] Target Boot option target.
291 @param[in, out] DevicePath On a sucessful return the device path to the handle.
292
293 @retval SHELL_INVALID_PARAMETER The handle was NULL.
294 @retval SHELL_NOT_FOUND Not found device path by handle.
295 @retval SHELL_SUCCESS Get device path successfully.
296 **/
297 SHELL_STATUS
298 GetDevicePathByHandle (
299 IN EFI_HANDLE TheHandle,
300 IN BCFG_OPERATION_TARGET Target,
301 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
302 )
303 {
304 EFI_STATUS Status;
305 SHELL_STATUS ShellStatus;
306
307 UINTN DriverBindingHandleCount;
308 UINTN ParentControllerHandleCount;
309 UINTN ChildControllerHandleCount;
310
311 ShellStatus = SHELL_SUCCESS;
312
313 if (TheHandle == NULL) {
314 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
315 return SHELL_INVALID_PARAMETER;
316 }
317
318 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (TheHandle, &DriverBindingHandleCount, NULL);
319 if (EFI_ERROR (Status)) {
320 DriverBindingHandleCount = 0;
321 }
322
323 Status = PARSE_HANDLE_DATABASE_PARENTS (TheHandle, &ParentControllerHandleCount, NULL);
324 if (EFI_ERROR (Status)) {
325 ParentControllerHandleCount = 0;
326 }
327
328 Status = ParseHandleDatabaseForChildControllers (TheHandle, &ChildControllerHandleCount, NULL);
329 if (EFI_ERROR (Status)) {
330 ChildControllerHandleCount = 0;
331 }
332
333 Status = gBS->HandleProtocol (TheHandle, &gEfiDevicePathProtocolGuid, (VOID **)DevicePath);
334
335 if ((DriverBindingHandleCount > 0) ||
336 (ParentControllerHandleCount > 0) ||
337 (ChildControllerHandleCount > 0) ||
338 !EFI_ERROR (Status)
339 )
340 {
341 //
342 // The handle points to a real controller which has a device path.
343 //
344 if (Target == BcfgTargetDriverOrder) {
345 ShellPrintHiiEx (
346 -1,
347 -1,
348 NULL,
349 STRING_TOKEN (STR_GEN_PARAM_INV),
350 gShellBcfgHiiHandle,
351 L"bcfg",
352 L"Handle should point to driver image."
353 );
354 ShellStatus = SHELL_NOT_FOUND;
355 }
356 } else {
357 //
358 // The handle points to a driver image.
359 //
360 if (Target == BcfgTargetBootOrder) {
361 ShellPrintHiiEx (
362 -1,
363 -1,
364 NULL,
365 STRING_TOKEN (STR_GEN_PARAM_INV),
366 gShellBcfgHiiHandle,
367 L"bcfg",
368 L"Handle should point to controller."
369 );
370 ShellStatus = SHELL_NOT_FOUND;
371 } else {
372 if (EFI_ERROR (GetDevicePathForDriverHandle (TheHandle, DevicePath))) {
373 ShellStatus = SHELL_NOT_FOUND;
374 }
375 }
376 }
377
378 return (ShellStatus);
379 }
380
381 /**
382 Function to modify an option.
383
384 @param[in] BcfgOperation Pointer to BCFG operation.
385 @param[in] OrderCount The number if items in CurrentOrder.
386
387 @retval SHELL_SUCCESS The operation was successful.
388 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
389 @retval SHELL_OUT_OF_RESOUCES A memory allocation failed.
390 **/
391 SHELL_STATUS
392 BcfgMod (
393 IN CONST BGFG_OPERATION *BcfgOperation,
394 IN CONST UINTN OrderCount
395 )
396 {
397 EFI_STATUS Status;
398 EFI_HANDLE CurHandle;
399 SHELL_STATUS ShellStatus;
400 CHAR16 OptionStr[40];
401 EFI_SHELL_FILE_INFO *FileList;
402 EFI_SHELL_FILE_INFO *Arg;
403 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
404 EFI_DEVICE_PATH_PROTOCOL *DevicePathBuffer;
405 EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker;
406 EFI_BOOT_MANAGER_LOAD_OPTION LoadOption;
407
408 ShellStatus = SHELL_SUCCESS;
409 FileList = NULL;
410 DevicePath = NULL;
411 DevicePathBuffer = NULL;
412
413 ZeroMem (&LoadOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
414
415 if (((BcfgOperation->Type == BcfgTypeMod) && (BcfgOperation->Description == NULL)) ||
416 ((BcfgOperation->Type == BcfgTypeModf) && (BcfgOperation->FileName == NULL)) ||
417 ((BcfgOperation->Type == BcfgTypeModp) && (BcfgOperation->FileName == NULL)) ||
418 ((BcfgOperation->Type == BcfgTypeModh) && (BcfgOperation->HandleIndex == 0)) ||
419 (BcfgOperation->Number1 > OrderCount)
420 )
421 {
422 return (SHELL_INVALID_PARAMETER);
423 }
424
425 if (BcfgOperation->Type == BcfgTypeModh) {
426 CurHandle = ConvertHandleIndexToHandle (BcfgOperation->HandleIndex);
427 ShellStatus = GetDevicePathByHandle (CurHandle, BcfgOperation->Target, &DevicePathBuffer);
428 if (ShellStatus == SHELL_SUCCESS) {
429 DevicePath = DuplicateDevicePath (DevicePathBuffer);
430 }
431 } else if ((BcfgOperation->Type == BcfgTypeModf) || (BcfgOperation->Type == BcfgTypeModp)) {
432 //
433 // Get Device Path by FileName.
434 //
435 ShellOpenFileMetaArg ((CHAR16 *)BcfgOperation->FileName, EFI_FILE_MODE_READ, &FileList);
436 if (FileList == NULL) {
437 //
438 // The name of file matched nothing.
439 //
440 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName);
441 ShellStatus = SHELL_INVALID_PARAMETER;
442 } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {
443 //
444 // If the name of file expanded to multiple names, it's fail.
445 //
446 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName);
447 ShellStatus = SHELL_INVALID_PARAMETER;
448 } else {
449 Arg = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link);
450 if (EFI_ERROR (Arg->Status)) {
451 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName);
452 ShellStatus = SHELL_INVALID_PARAMETER;
453 } else {
454 DevicePathBuffer = gEfiShellProtocol->GetDevicePathFromFilePath (Arg->FullName);
455 if (DevicePathBuffer == NULL) {
456 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName);
457 ShellStatus = SHELL_UNSUPPORTED;
458 }
459 }
460 }
461
462 if (ShellStatus == SHELL_SUCCESS) {
463 if (BcfgOperation->Type == BcfgTypeModp) {
464 ShellStatus = SHELL_INVALID_PARAMETER;
465 DevicePathWalker = DevicePathBuffer;
466 while (!IsDevicePathEnd (DevicePathWalker)) {
467 if ((DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH) &&
468 (DevicePathSubType (DevicePathWalker) == MEDIA_HARDDRIVE_DP)
469 )
470 {
471 //
472 // We found the portion of device path starting with the hard driver partition.
473 //
474 ShellStatus = SHELL_SUCCESS;
475 DevicePath = DuplicateDevicePath (DevicePathWalker);
476 break;
477 } else {
478 DevicePathWalker = NextDevicePathNode (DevicePathWalker);
479 }
480 }
481 } else {
482 DevicePath = DuplicateDevicePath (DevicePathBuffer);
483 }
484
485 FreePool (DevicePathBuffer);
486 }
487 }
488
489 if (ShellStatus == SHELL_SUCCESS) {
490 if (BcfgOperation->Target == BcfgTargetBootOrder) {
491 UnicodeSPrint (OptionStr, sizeof (OptionStr), L"Boot%04x", BcfgOperation->Order[BcfgOperation->Number1]);
492 } else {
493 UnicodeSPrint (OptionStr, sizeof (OptionStr), L"Driver%04x", BcfgOperation->Order[BcfgOperation->Number1]);
494 }
495
496 Status = EfiBootManagerVariableToLoadOption (OptionStr, &LoadOption);
497 if (EFI_ERROR (Status)) {
498 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NONE), gShellBcfgHiiHandle);
499 ShellStatus = SHELL_NOT_FOUND;
500 }
501 }
502
503 if (ShellStatus == SHELL_SUCCESS) {
504 if (BcfgOperation->Type == BcfgTypeMod) {
505 SHELL_FREE_NON_NULL (LoadOption.Description);
506 LoadOption.Description = AllocateCopyPool (StrSize (BcfgOperation->Description), BcfgOperation->Description);
507 } else {
508 SHELL_FREE_NON_NULL (LoadOption.FilePath);
509 LoadOption.FilePath = DuplicateDevicePath (DevicePath);
510 }
511
512 Status = EfiBootManagerLoadOptionToVariable (&LoadOption);
513 if (EFI_ERROR (Status)) {
514 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr);
515 ShellStatus = SHELL_INVALID_PARAMETER;
516 }
517 }
518
519 EfiBootManagerFreeLoadOption (&LoadOption);
520
521 if (DevicePath != NULL) {
522 FreePool (DevicePath);
523 }
524
525 if (FileList != NULL) {
526 ShellCloseFileMetaArg (&FileList);
527 }
528
529 return (ShellStatus);
530 }
531
532 /**
533 Function to add a option.
534
535 @param[in] Position The position to add Target at.
536 @param[in] File The file to make the target.
537 @param[in] Desc The description text.
538 @param[in] CurrentOrder The pointer to the current order of items.
539 @param[in] OrderCount The number if items in CurrentOrder.
540 @param[in] Target The info on the option to add.
541 @param[in] UseHandle TRUE to use HandleNumber, FALSE to use File and Desc.
542 @param[in] UsePath TRUE to convert to devicepath.
543 @param[in] HandleNumber The handle number to add.
544
545 @retval SHELL_SUCCESS The operation was successful.
546 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
547 **/
548 SHELL_STATUS
549 BcfgAdd (
550 IN UINTN Position,
551 IN CONST CHAR16 *File,
552 IN CONST CHAR16 *Desc,
553 IN CONST UINT16 *CurrentOrder,
554 IN CONST UINTN OrderCount,
555 IN CONST BCFG_OPERATION_TARGET Target,
556 IN CONST BOOLEAN UseHandle,
557 IN CONST BOOLEAN UsePath,
558 IN CONST UINTN HandleNumber
559 )
560 {
561 EFI_STATUS Status;
562 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
563 EFI_DEVICE_PATH_PROTOCOL *DevPath;
564 EFI_DEVICE_PATH_PROTOCOL *FilePath;
565 CHAR16 *Str;
566 UINT8 *TempByteBuffer;
567 UINT8 *TempByteStart;
568 EFI_SHELL_FILE_INFO *Arg;
569 EFI_SHELL_FILE_INFO *FileList;
570 CHAR16 OptionStr[40];
571 UINTN DescSize, FilePathSize;
572 BOOLEAN Found;
573 UINTN TargetLocation;
574 UINTN Index;
575 EFI_HANDLE *Handles;
576 EFI_HANDLE CurHandle;
577 UINTN DriverBindingHandleCount;
578 UINTN ParentControllerHandleCount;
579 UINTN ChildControllerHandleCount;
580 SHELL_STATUS ShellStatus;
581 UINT16 *NewOrder;
582
583 if (!UseHandle) {
584 if ((File == NULL) || (Desc == NULL)) {
585 return (SHELL_INVALID_PARAMETER);
586 }
587 } else {
588 if (HandleNumber == 0) {
589 return (SHELL_INVALID_PARAMETER);
590 }
591 }
592
593 if (Position > OrderCount) {
594 Position = OrderCount;
595 }
596
597 Str = NULL;
598 FilePath = NULL;
599 FileList = NULL;
600 Handles = NULL;
601 ShellStatus = SHELL_SUCCESS;
602 TargetLocation = 0xFFFF;
603
604 if (UseHandle) {
605 CurHandle = ConvertHandleIndexToHandle (HandleNumber);
606 if (CurHandle == NULL) {
607 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
608 ShellStatus = SHELL_INVALID_PARAMETER;
609 } else {
610 if (Target == BcfgTargetBootOrder) {
611 //
612 // Make sure that the handle should point to a real controller
613 //
614 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
615 CurHandle,
616 &DriverBindingHandleCount,
617 NULL
618 );
619
620 Status = PARSE_HANDLE_DATABASE_PARENTS (
621 CurHandle,
622 &ParentControllerHandleCount,
623 NULL
624 );
625
626 Status = ParseHandleDatabaseForChildControllers (
627 CurHandle,
628 &ChildControllerHandleCount,
629 NULL
630 );
631
632 if ( (DriverBindingHandleCount > 0)
633 || (ParentControllerHandleCount > 0)
634 || (ChildControllerHandleCount > 0))
635 {
636 FilePath = NULL;
637 Status = gBS->HandleProtocol (
638 CurHandle,
639 &gEfiDevicePathProtocolGuid,
640 (VOID **)&FilePath
641 );
642 }
643
644 if (EFI_ERROR (Status)) {
645 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellBcfgHiiHandle, L"bcfg", HandleNumber);
646 ShellStatus = SHELL_INVALID_PARAMETER;
647 }
648 } else {
649 //
650 // Make sure that the handle should point to driver, not a controller.
651 //
652 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
653 CurHandle,
654 &DriverBindingHandleCount,
655 NULL
656 );
657
658 Status = PARSE_HANDLE_DATABASE_PARENTS (
659 CurHandle,
660 &ParentControllerHandleCount,
661 NULL
662 );
663
664 Status = ParseHandleDatabaseForChildControllers (
665 CurHandle,
666 &ChildControllerHandleCount,
667 NULL
668 );
669
670 Status = gBS->HandleProtocol (
671 CurHandle,
672 &gEfiDevicePathProtocolGuid,
673 (VOID **)&FilePath
674 );
675
676 if ( (DriverBindingHandleCount > 0)
677 || (ParentControllerHandleCount > 0)
678 || (ChildControllerHandleCount > 0)
679 || !EFI_ERROR (Status))
680 {
681 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
682 ShellStatus = SHELL_INVALID_PARAMETER;
683 } else {
684 //
685 // Get the DevicePath from the loaded image information.
686 //
687 Status = GetDevicePathForDriverHandle (CurHandle, &FilePath);
688 }
689 }
690 }
691 } else {
692 //
693 // Get file info
694 //
695 ShellOpenFileMetaArg ((CHAR16 *)File, EFI_FILE_MODE_READ, &FileList);
696
697 if (FileList == NULL) {
698 //
699 // If filename matched nothing fail
700 //
701 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", File);
702 ShellStatus = SHELL_INVALID_PARAMETER;
703 } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {
704 //
705 // If filename expanded to multiple names, fail
706 //
707 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", File);
708 ShellStatus = SHELL_INVALID_PARAMETER;
709 } else {
710 Arg = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link);
711 if (EFI_ERROR (Arg->Status)) {
712 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", File);
713 ShellStatus = SHELL_INVALID_PARAMETER;
714 } else {
715 //
716 // Build FilePath to the filename
717 //
718
719 //
720 // get the device path
721 //
722 DevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (Arg->FullName);
723 if (DevicePath == NULL) {
724 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName);
725 ShellStatus = SHELL_UNSUPPORTED;
726 } else {
727 if (UsePath) {
728 DevPath = DevicePath;
729 ShellStatus = SHELL_INVALID_PARAMETER;
730 while (!IsDevicePathEnd (DevPath)) {
731 if ((DevicePathType (DevPath) == MEDIA_DEVICE_PATH) &&
732 (DevicePathSubType (DevPath) == MEDIA_HARDDRIVE_DP))
733 {
734 //
735 // If we find it use it instead
736 //
737 ShellStatus = SHELL_SUCCESS;
738 FilePath = DuplicateDevicePath (DevPath);
739 break;
740 }
741
742 DevPath = NextDevicePathNode (DevPath);
743 }
744 } else {
745 FilePath = DuplicateDevicePath (DevicePath);
746 }
747
748 FreePool (DevicePath);
749 }
750 }
751 }
752 }
753
754 if (ShellStatus == SHELL_SUCCESS) {
755 //
756 // Find a free target ,a brute force implementation
757 //
758 Found = FALSE;
759 for (TargetLocation = 0; TargetLocation < 0xFFFF; TargetLocation++) {
760 Found = TRUE;
761 for (Index = 0; Index < OrderCount; Index++) {
762 if (CurrentOrder[Index] == TargetLocation) {
763 Found = FALSE;
764 break;
765 }
766 }
767
768 if (Found) {
769 break;
770 }
771 }
772
773 if (TargetLocation == 0xFFFF) {
774 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellBcfgHiiHandle, L"bcfg");
775 } else {
776 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellBcfgHiiHandle, TargetLocation);
777 }
778 }
779
780 if (ShellStatus == SHELL_SUCCESS) {
781 //
782 // Add the option
783 //
784 DescSize = StrSize (Desc);
785 FilePathSize = GetDevicePathSize (FilePath);
786
787 TempByteBuffer = AllocateZeroPool (sizeof (UINT32) + sizeof (UINT16) + DescSize + FilePathSize);
788 if (TempByteBuffer != NULL) {
789 TempByteStart = TempByteBuffer;
790 *((UINT32 *)TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes
791 TempByteBuffer += sizeof (UINT32);
792
793 *((UINT16 *)TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength
794 TempByteBuffer += sizeof (UINT16);
795
796 CopyMem (TempByteBuffer, Desc, DescSize);
797 TempByteBuffer += DescSize;
798 ASSERT (FilePath != NULL);
799 CopyMem (TempByteBuffer, FilePath, FilePathSize);
800
801 UnicodeSPrint (OptionStr, sizeof (OptionStr), L"%s%04x", Target == BcfgTargetBootOrder ? L"Boot" : L"Driver", TargetLocation);
802 Status = gRT->SetVariable (
803 OptionStr,
804 &gEfiGlobalVariableGuid,
805 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
806 sizeof (UINT32) + sizeof (UINT16) + DescSize + FilePathSize,
807 TempByteStart
808 );
809
810 FreePool (TempByteStart);
811 } else {
812 Status = EFI_OUT_OF_RESOURCES;
813 }
814
815 if (EFI_ERROR (Status)) {
816 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr);
817 } else {
818 NewOrder = AllocateZeroPool ((OrderCount + 1) * sizeof (NewOrder[0]));
819 if (NewOrder != NULL) {
820 CopyMem (NewOrder, CurrentOrder, (OrderCount) * sizeof (NewOrder[0]));
821
822 //
823 // Insert target into order list
824 //
825 for (Index = OrderCount; Index > Position; Index--) {
826 NewOrder[Index] = NewOrder[Index - 1];
827 }
828
829 NewOrder[Position] = (UINT16)TargetLocation;
830 Status = gRT->SetVariable (
831 Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder",
832 &gEfiGlobalVariableGuid,
833 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
834 (OrderCount + 1) * sizeof (UINT16),
835 NewOrder
836 );
837
838 FreePool (NewOrder);
839
840 if (EFI_ERROR (Status)) {
841 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder");
842 ShellStatus = SHELL_INVALID_PARAMETER;
843 } else {
844 Print (L"bcfg: Add %s as %x\n", OptionStr, Position);
845 }
846 }
847 }
848 }
849
850 //
851 // If always Free FilePath, will free devicepath in system when use "addh"
852 //
853 if ((FilePath != NULL) && !UseHandle) {
854 FreePool (FilePath);
855 }
856
857 if (Str != NULL) {
858 FreePool (Str);
859 }
860
861 if (Handles != NULL) {
862 FreePool (Handles);
863 }
864
865 if (FileList != NULL) {
866 ShellCloseFileMetaArg (&FileList);
867 }
868
869 return (ShellStatus);
870 }
871
872 /**
873 Funciton to remove an item.
874
875 @param[in] Target The target item to move.
876 @param[in] CurrentOrder The pointer to the current order of items.
877 @param[in] OrderCount The number if items in CurrentOrder.
878 @param[in] Location The current location of the Target.
879
880 @retval SHELL_SUCCESS The operation was successful.
881 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
882 **/
883 SHELL_STATUS
884 BcfgRemove (
885 IN CONST BCFG_OPERATION_TARGET Target,
886 IN CONST UINT16 *CurrentOrder,
887 IN CONST UINTN OrderCount,
888 IN CONST UINT16 Location
889 )
890 {
891 CHAR16 VariableName[12];
892 UINT16 *NewOrder;
893 EFI_STATUS Status;
894 UINTN NewCount;
895
896 UnicodeSPrint (VariableName, sizeof (VariableName), L"%s%04x", Target == BcfgTargetBootOrder ? L"Boot" : L"Driver", CurrentOrder[Location]);
897 Status = gRT->SetVariable (
898 VariableName,
899 (EFI_GUID *)&gEfiGlobalVariableGuid,
900 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
901 0,
902 NULL
903 );
904 if (EFI_ERROR (Status)) {
905 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
906 return (SHELL_INVALID_PARAMETER);
907 }
908
909 NewOrder = AllocateZeroPool (OrderCount*sizeof (CurrentOrder[0]));
910 if (NewOrder != NULL) {
911 NewCount = OrderCount;
912 CopyMem (NewOrder, CurrentOrder, OrderCount*sizeof (CurrentOrder[0]));
913 CopyMem (NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof (CurrentOrder[0]));
914 NewCount--;
915
916 Status = gRT->SetVariable (
917 Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder",
918 (EFI_GUID *)&gEfiGlobalVariableGuid,
919 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
920 NewCount*sizeof (NewOrder[0]),
921 NewOrder
922 );
923 FreePool (NewOrder);
924 } else {
925 Status = EFI_OUT_OF_RESOURCES;
926 }
927
928 if (EFI_ERROR (Status)) {
929 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder");
930 return (SHELL_INVALID_PARAMETER);
931 }
932
933 return (SHELL_SUCCESS);
934 }
935
936 /**
937 Funciton to move a item to another location.
938
939 @param[in] Target The target item to move.
940 @param[in] CurrentOrder The pointer to the current order of items.
941 @param[in] OrderCount The number if items in CurrentOrder.
942 @param[in] OldLocation The current location of the Target.
943 @param[in] NewLocation The desired location of the Target.
944
945 @retval SHELL_SUCCESS The operation was successful.
946 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
947 **/
948 SHELL_STATUS
949 BcfgMove (
950 IN CONST BCFG_OPERATION_TARGET Target,
951 IN CONST UINT16 *CurrentOrder,
952 IN CONST UINTN OrderCount,
953 IN CONST UINT16 OldLocation,
954 IN UINT16 NewLocation
955 )
956 {
957 UINT16 *NewOrder;
958 EFI_STATUS Status;
959 UINT16 Temp;
960
961 NewOrder = AllocateCopyPool (OrderCount*sizeof (CurrentOrder[0]), CurrentOrder);
962 if (NewOrder == NULL) {
963 return (SHELL_OUT_OF_RESOURCES);
964 }
965
966 //
967 // correct the new location
968 //
969 if (NewLocation >= OrderCount) {
970 if (OrderCount > 0) {
971 NewLocation = (UINT16)OrderCount - 1;
972 } else {
973 NewLocation = 0;
974 }
975 }
976
977 Temp = CurrentOrder[OldLocation];
978 CopyMem (NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof (CurrentOrder[0]));
979 CopyMem (NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof (CurrentOrder[0]));
980 NewOrder[NewLocation] = Temp;
981
982 Status = gRT->SetVariable (
983 Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder",
984 (EFI_GUID *)&gEfiGlobalVariableGuid,
985 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
986 OrderCount*sizeof (CurrentOrder[0]),
987 NewOrder
988 );
989
990 FreePool (NewOrder);
991
992 if (EFI_ERROR (Status)) {
993 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder");
994 return (SHELL_INVALID_PARAMETER);
995 }
996
997 return (SHELL_SUCCESS);
998 }
999
1000 /**
1001 Function to add optional data to an option.
1002
1003 @param[in] OptData The optional data to add.
1004 @param[in] CurrentOrder The pointer to the current order of items.
1005 @param[in] OrderCount The number if items in CurrentOrder.
1006 @param[in] Target The target of the operation.
1007
1008 @retval SHELL_SUCCESS The operation was succesful.
1009 **/
1010 SHELL_STATUS
1011 BcfgAddOpt (
1012 IN CONST CHAR16 *OptData,
1013 IN CONST UINT16 *CurrentOrder,
1014 IN CONST UINTN OrderCount,
1015 IN CONST BCFG_OPERATION_TARGET Target
1016 )
1017 {
1018 EFI_KEY_OPTION NewKeyOption;
1019 EFI_KEY_OPTION *KeyOptionBuffer;
1020 SHELL_STATUS ShellStatus;
1021 EFI_STATUS Status;
1022 UINT16 OptionIndex;
1023 UINT16 LoopCounter;
1024 UINT64 Intermediate;
1025 CONST CHAR16 *Temp;
1026 CONST CHAR16 *Walker;
1027 CHAR16 *FileName;
1028 CHAR16 *Temp2;
1029 CHAR16 *Data;
1030 UINT32 KeyIndex;
1031 CHAR16 VariableName[12];
1032 VOID *VariableData;
1033
1034 SHELL_FILE_HANDLE FileHandle;
1035
1036 Status = EFI_SUCCESS;
1037 ShellStatus = SHELL_SUCCESS;
1038 Walker = OptData;
1039 FileName = NULL;
1040 Data = NULL;
1041 KeyOptionBuffer = NULL;
1042 VariableData = NULL;
1043
1044 ZeroMem (&NewKeyOption, sizeof (EFI_KEY_OPTION));
1045 ZeroMem (VariableName, sizeof (VariableName));
1046
1047 while (Walker[0] == L' ') {
1048 Walker++;
1049 }
1050
1051 //
1052 // Get the index of the variable we are changing.
1053 //
1054 Status = ShellConvertStringToUint64 (Walker, &Intermediate, TRUE, TRUE);
1055 if (EFI_ERROR (Status) || (((UINT16)Intermediate) != Intermediate) || (StrStr (Walker, L" ") == NULL) || (((UINT16)Intermediate) > ((UINT16)OrderCount))) {
1056 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index");
1057 ShellStatus = SHELL_INVALID_PARAMETER;
1058 return (ShellStatus);
1059 }
1060
1061 OptionIndex = (UINT16)Intermediate;
1062
1063 Temp = StrStr (Walker, L" ");
1064 if (Temp != NULL) {
1065 Walker = Temp;
1066 }
1067
1068 while (Walker[0] == L' ') {
1069 Walker++;
1070 }
1071
1072 //
1073 // determine whether we have file with data, quote delimited information, or a hot-key
1074 //
1075 if (Walker[0] == L'\"') {
1076 //
1077 // quoted filename or quoted information.
1078 //
1079 Temp = StrStr (Walker+1, L"\"");
1080 if ((Temp == NULL) || (StrLen (Temp) != 1)) {
1081 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
1082 ShellStatus = SHELL_INVALID_PARAMETER;
1083 } else {
1084 FileName = StrnCatGrow (&FileName, NULL, Walker+1, 0);
1085 if (FileName == NULL) {
1086 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellBcfgHiiHandle, L"bcfg");
1087 ShellStatus = SHELL_OUT_OF_RESOURCES;
1088 return (ShellStatus);
1089 }
1090
1091 Temp2 = StrStr (FileName, L"\"");
1092 ASSERT (Temp2 != NULL);
1093 Temp2[0] = CHAR_NULL;
1094 Temp2++;
1095 if (StrLen (Temp2) > 0) {
1096 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
1097 ShellStatus = SHELL_INVALID_PARAMETER;
1098 }
1099
1100 if (EFI_ERROR (ShellFileExists (Walker))) {
1101 //
1102 // Not a file. must be misc information.
1103 //
1104 Data = FileName;
1105 FileName = NULL;
1106 } else {
1107 FileName = StrnCatGrow (&FileName, NULL, Walker, 0);
1108 }
1109 }
1110 } else {
1111 //
1112 // filename or hot key information.
1113 //
1114 if (StrStr (Walker, L" ") == NULL) {
1115 //
1116 // filename
1117 //
1118 if (EFI_ERROR (ShellFileExists (Walker))) {
1119 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellBcfgHiiHandle, L"bcfg", Walker);
1120 ShellStatus = SHELL_INVALID_PARAMETER;
1121 } else {
1122 FileName = StrnCatGrow (&FileName, NULL, Walker, 0);
1123 }
1124 } else {
1125 if (Target != BcfgTargetBootOrder) {
1126 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_BOOT_ONLY), gShellBcfgHiiHandle, L"bcfg");
1127 ShellStatus = SHELL_INVALID_PARAMETER;
1128 }
1129
1130 if (ShellStatus == SHELL_SUCCESS) {
1131 //
1132 // Get hot key information
1133 //
1134 Status = ShellConvertStringToUint64 (Walker, &Intermediate, FALSE, TRUE);
1135 if (EFI_ERROR (Status) || (((UINT32)Intermediate) != Intermediate) || (StrStr (Walker, L" ") == NULL)) {
1136 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
1137 ShellStatus = SHELL_INVALID_PARAMETER;
1138 }
1139
1140 NewKeyOption.KeyData.PackedValue = (UINT32)Intermediate;
1141 Temp = StrStr (Walker, L" ");
1142 if (Temp != NULL) {
1143 Walker = Temp;
1144 }
1145
1146 while (Walker[0] == L' ') {
1147 Walker++;
1148 }
1149 }
1150
1151 if (ShellStatus == SHELL_SUCCESS) {
1152 //
1153 // Now we know how many EFI_INPUT_KEY structs we need to attach to the end of the EFI_KEY_OPTION struct.
1154 // Re-allocate with the added information.
1155 //
1156 KeyOptionBuffer = AllocatePool (sizeof (EFI_KEY_OPTION) + (sizeof (EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount));
1157 if (KeyOptionBuffer == NULL) {
1158 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg");
1159 ShellStatus = SHELL_OUT_OF_RESOURCES;
1160 return ShellStatus;
1161 }
1162
1163 CopyMem (KeyOptionBuffer, &NewKeyOption, sizeof (EFI_KEY_OPTION));
1164 }
1165
1166 for (LoopCounter = 0; ShellStatus == SHELL_SUCCESS && LoopCounter < NewKeyOption.KeyData.Options.InputKeyCount; LoopCounter++) {
1167 //
1168 // ScanCode
1169 //
1170 Status = ShellConvertStringToUint64 (Walker, &Intermediate, FALSE, TRUE);
1171 if (EFI_ERROR (Status) || (((UINT16)Intermediate) != Intermediate) || (StrStr (Walker, L" ") == NULL)) {
1172 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
1173 ShellStatus = SHELL_INVALID_PARAMETER;
1174 }
1175
1176 ((EFI_INPUT_KEY *)(((UINT8 *)KeyOptionBuffer) + sizeof (EFI_KEY_OPTION)))[LoopCounter].ScanCode = (UINT16)Intermediate;
1177 Temp = StrStr (Walker, L" ");
1178 if (Temp != NULL) {
1179 Walker = Temp;
1180 }
1181
1182 while (Walker[0] == L' ') {
1183 Walker++;
1184 }
1185
1186 //
1187 // UnicodeChar
1188 //
1189 Status = ShellConvertStringToUint64 (Walker, &Intermediate, FALSE, TRUE);
1190 if (EFI_ERROR (Status) || (((UINT16)Intermediate) != Intermediate)) {
1191 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
1192 ShellStatus = SHELL_INVALID_PARAMETER;
1193 }
1194
1195 ((EFI_INPUT_KEY *)(((UINT8 *)KeyOptionBuffer) + sizeof (EFI_KEY_OPTION)))[LoopCounter].UnicodeChar = (UINT16)Intermediate;
1196 Temp = StrStr (Walker, L" ");
1197 if (Temp != NULL) {
1198 Walker = Temp;
1199 }
1200
1201 while (Walker[0] == L' ') {
1202 Walker++;
1203 }
1204 }
1205
1206 if (ShellStatus == SHELL_SUCCESS) {
1207 //
1208 // Now do the BootOption / BootOptionCrc
1209 //
1210 ASSERT (OptionIndex <= OrderCount);
1211 KeyOptionBuffer->BootOption = CurrentOrder[OptionIndex];
1212 Status = GetBootOptionCrc (&(KeyOptionBuffer->BootOptionCrc), KeyOptionBuffer->BootOption);
1213 if (EFI_ERROR (Status)) {
1214 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index");
1215 ShellStatus = SHELL_INVALID_PARAMETER;
1216 }
1217 }
1218
1219 if (ShellStatus == SHELL_SUCCESS) {
1220 for (Temp2 = NULL, KeyIndex = 0; KeyIndex <= 0xFFFF; KeyIndex++) {
1221 UnicodeSPrint (VariableName, sizeof (VariableName), L"Key%04x", KeyIndex);
1222 Status = GetEfiGlobalVariable2 (VariableName, &VariableData, NULL);
1223 if (Status == EFI_NOT_FOUND) {
1224 break;
1225 }
1226
1227 if (!EFI_ERROR (Status)) {
1228 SHELL_FREE_NON_NULL (VariableData);
1229 }
1230 }
1231
1232 if (KeyIndex <= 0xFFFF) {
1233 Status = gRT->SetVariable (
1234 VariableName,
1235 (EFI_GUID *)&gEfiGlobalVariableGuid,
1236 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
1237 sizeof (EFI_KEY_OPTION) + (sizeof (EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount),
1238 KeyOptionBuffer
1239 );
1240 if (EFI_ERROR (Status)) {
1241 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
1242 ShellStatus = SHELL_INVALID_PARAMETER;
1243 }
1244 } else {
1245 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_VAR_NO_NUM), gShellBcfgHiiHandle, L"bcfg");
1246 ShellStatus = SHELL_INVALID_PARAMETER;
1247 }
1248
1249 ASSERT (FileName == NULL && Data == NULL);
1250 }
1251 }
1252 }
1253
1254 //
1255 // Shouldn't be possible to have have both. Neither is ok though.
1256 //
1257 ASSERT (FileName == NULL || Data == NULL);
1258
1259 if ((ShellStatus == SHELL_SUCCESS) && ((FileName != NULL) || (Data != NULL))) {
1260 if (FileName != NULL) {
1261 //
1262 // Open the file and populate the data buffer.
1263 //
1264 Status = ShellOpenFileByName (
1265 FileName,
1266 &FileHandle,
1267 EFI_FILE_MODE_READ,
1268 0
1269 );
1270 if (!EFI_ERROR (Status)) {
1271 Status = ShellGetFileSize (FileHandle, &Intermediate);
1272 }
1273
1274 Data = AllocateZeroPool ((UINTN)Intermediate);
1275 if (Data == NULL) {
1276 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg");
1277 ShellStatus = SHELL_OUT_OF_RESOURCES;
1278 }
1279
1280 if (!EFI_ERROR (Status)) {
1281 Status = ShellReadFile (FileHandle, (UINTN *)&Intermediate, Data);
1282 }
1283 } else {
1284 Intermediate = StrSize (Data);
1285 }
1286
1287 if (!EFI_ERROR (Status) && (ShellStatus == SHELL_SUCCESS) && (Data != NULL)) {
1288 Status = UpdateOptionalData (CurrentOrder[OptionIndex], (UINTN)Intermediate, (UINT8 *)Data, Target);
1289 if (EFI_ERROR (Status)) {
1290 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
1291 ShellStatus = SHELL_INVALID_PARAMETER;
1292 }
1293 }
1294
1295 if (EFI_ERROR (Status) && (ShellStatus == SHELL_SUCCESS)) {
1296 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
1297 ShellStatus = SHELL_INVALID_PARAMETER;
1298 }
1299 }
1300
1301 SHELL_FREE_NON_NULL (Data);
1302 SHELL_FREE_NON_NULL (KeyOptionBuffer);
1303 SHELL_FREE_NON_NULL (FileName);
1304 return ShellStatus;
1305 }
1306
1307 /**
1308 Function to dump the Bcfg information.
1309
1310 @param[in] Op The operation.
1311 @param[in] OrderCount How many to dump.
1312 @param[in] CurrentOrder The pointer to the current order of items.
1313 @param[in] VerboseOutput TRUE for extra output. FALSE otherwise.
1314
1315 @retval SHELL_SUCCESS The dump was successful.
1316 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
1317 **/
1318 SHELL_STATUS
1319 BcfgDisplayDump (
1320 IN CONST CHAR16 *Op,
1321 IN CONST UINTN OrderCount,
1322 IN CONST UINT16 *CurrentOrder,
1323 IN CONST BOOLEAN VerboseOutput
1324 )
1325 {
1326 EFI_STATUS Status;
1327 UINT8 *Buffer;
1328 UINTN BufferSize;
1329 CHAR16 VariableName[12];
1330 UINTN LoopVar;
1331 CHAR16 *DevPathString;
1332 VOID *FilePathList;
1333 UINTN Errors;
1334 EFI_LOAD_OPTION *LoadOption;
1335 CHAR16 *Description;
1336 UINTN DescriptionSize;
1337 UINTN OptionalDataOffset;
1338
1339 if (OrderCount == 0) {
1340 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NONE), gShellBcfgHiiHandle, L"bcfg");
1341 return (SHELL_SUCCESS);
1342 }
1343
1344 Errors = 0;
1345
1346 for (LoopVar = 0; LoopVar < OrderCount; LoopVar++) {
1347 Buffer = NULL;
1348 BufferSize = 0;
1349 DevPathString = NULL;
1350
1351 UnicodeSPrint (VariableName, sizeof (VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]);
1352
1353 Status = gRT->GetVariable (
1354 VariableName,
1355 (EFI_GUID *)&gEfiGlobalVariableGuid,
1356 NULL,
1357 &BufferSize,
1358 Buffer
1359 );
1360 if (Status == EFI_BUFFER_TOO_SMALL) {
1361 Buffer = AllocateZeroPool (BufferSize);
1362 Status = gRT->GetVariable (
1363 VariableName,
1364 (EFI_GUID *)&gEfiGlobalVariableGuid,
1365 NULL,
1366 &BufferSize,
1367 Buffer
1368 );
1369 }
1370
1371 if (EFI_ERROR (Status) || (Buffer == NULL)) {
1372 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
1373 ++Errors;
1374 goto Cleanup;
1375 }
1376
1377 //
1378 // We expect the Attributes, FilePathListLength, and L'\0'-terminated
1379 // Description fields to be present.
1380 //
1381 if (BufferSize < sizeof *LoadOption + sizeof (CHAR16)) {
1382 ShellPrintHiiEx (
1383 -1,
1384 -1,
1385 NULL,
1386 STRING_TOKEN (STR_BCFG_VAR_CORRUPT),
1387 gShellBcfgHiiHandle,
1388 L"bcfg",
1389 VariableName
1390 );
1391 ++Errors;
1392 goto Cleanup;
1393 }
1394
1395 LoadOption = (EFI_LOAD_OPTION *)Buffer;
1396 Description = (CHAR16 *)(Buffer + sizeof (EFI_LOAD_OPTION));
1397 DescriptionSize = StrSize (Description);
1398
1399 if (LoadOption->FilePathListLength != 0) {
1400 FilePathList = (UINT8 *)Description + DescriptionSize;
1401 DevPathString = ConvertDevicePathToText (FilePathList, TRUE, FALSE);
1402 }
1403
1404 OptionalDataOffset = sizeof *LoadOption + DescriptionSize +
1405 LoadOption->FilePathListLength;
1406
1407 ShellPrintHiiEx (
1408 -1,
1409 -1,
1410 NULL,
1411 STRING_TOKEN (STR_BCFG_LOAD_OPTIONS),
1412 gShellBcfgHiiHandle,
1413 LoopVar,
1414 VariableName,
1415 Description,
1416 DevPathString,
1417 OptionalDataOffset >= BufferSize ? L'N' : L'Y'
1418 );
1419 if (VerboseOutput && (OptionalDataOffset < BufferSize)) {
1420 DumpHex (
1421 2, // Indent
1422 0, // Offset (displayed)
1423 BufferSize - OptionalDataOffset, // DataSize
1424 Buffer + OptionalDataOffset // UserData
1425 );
1426 }
1427
1428 Cleanup:
1429 if (Buffer != NULL) {
1430 FreePool (Buffer);
1431 }
1432
1433 if (DevPathString != NULL) {
1434 FreePool (DevPathString);
1435 }
1436 }
1437
1438 return (Errors > 0) ? SHELL_INVALID_PARAMETER : SHELL_SUCCESS;
1439 }
1440
1441 /**
1442 Function to initialize the BCFG operation structure.
1443
1444 @param[in] Struct The stuct to initialize.
1445 **/
1446 VOID
1447 InitBcfgStruct (
1448 IN BGFG_OPERATION *Struct
1449 )
1450 {
1451 ASSERT (Struct != NULL);
1452 Struct->Target = BcfgTargetMax;
1453 Struct->Type = BcfgTypeMax;
1454 Struct->Number1 = 0;
1455 Struct->Number2 = 0;
1456 Struct->HandleIndex = 0;
1457 Struct->FileName = NULL;
1458 Struct->Description = NULL;
1459 Struct->Order = NULL;
1460 Struct->OptData = NULL;
1461 }
1462
1463 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
1464 { L"-v", TypeFlag },
1465 { L"-opt", TypeMaxValue },
1466 { NULL, TypeMax }
1467 };
1468
1469 /**
1470 Function for 'bcfg' command.
1471
1472 @param[in] ImageHandle Handle to the Image (NULL if Internal).
1473 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
1474 **/
1475 SHELL_STATUS
1476 EFIAPI
1477 ShellCommandRunBcfg (
1478 IN EFI_HANDLE ImageHandle,
1479 IN EFI_SYSTEM_TABLE *SystemTable
1480 )
1481 {
1482 EFI_STATUS Status;
1483 LIST_ENTRY *Package;
1484 CHAR16 *ProblemParam;
1485 SHELL_STATUS ShellStatus;
1486 UINTN ParamNumber;
1487 CONST CHAR16 *CurrentParam;
1488 BGFG_OPERATION CurrentOperation;
1489 UINTN Length;
1490 UINT64 Intermediate;
1491 UINT16 Count;
1492
1493 Length = 0;
1494 ProblemParam = NULL;
1495 Package = NULL;
1496 ShellStatus = SHELL_SUCCESS;
1497
1498 InitBcfgStruct (&CurrentOperation);
1499
1500 //
1501 // initialize the shell lib (we must be in non-auto-init...)
1502 //
1503 Status = ShellInitialize ();
1504 ASSERT_EFI_ERROR (Status);
1505
1506 Status = CommandInit ();
1507 ASSERT_EFI_ERROR (Status);
1508
1509 //
1510 // parse the command line
1511 //
1512 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
1513 if (EFI_ERROR (Status)) {
1514 if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
1515 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"bcfg", ProblemParam);
1516 FreePool (ProblemParam);
1517 ShellStatus = SHELL_INVALID_PARAMETER;
1518 } else {
1519 ASSERT (FALSE);
1520 }
1521 } else {
1522 //
1523 // Read in if we are doing -OPT
1524 //
1525 if (ShellCommandLineGetFlag (Package, L"-opt")) {
1526 CurrentOperation.OptData = ShellCommandLineGetValue (Package, L"-opt");
1527 if (CurrentOperation.OptData == NULL) {
1528 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellBcfgHiiHandle, L"bcfg", L"-opt");
1529 ShellStatus = SHELL_INVALID_PARAMETER;
1530 }
1531
1532 CurrentOperation.Type = BcfgTypeOpt;
1533 }
1534
1535 //
1536 // small block to read the target of the operation
1537 //
1538 if (((ShellCommandLineGetCount (Package) < 3) && (CurrentOperation.Type != BcfgTypeOpt)) ||
1539 ((ShellCommandLineGetCount (Package) < 2) && (CurrentOperation.Type == BcfgTypeOpt))
1540 )
1541 {
1542 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1543 ShellStatus = SHELL_INVALID_PARAMETER;
1544 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)ShellCommandLineGetRawValue (Package, 1), L"driver") == 0) {
1545 CurrentOperation.Target = BcfgTargetDriverOrder;
1546 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)ShellCommandLineGetRawValue (Package, 1), L"boot") == 0) {
1547 CurrentOperation.Target = BcfgTargetBootOrder;
1548 } else {
1549 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellBcfgHiiHandle, L"bcfg");
1550 ShellStatus = SHELL_INVALID_PARAMETER;
1551 }
1552
1553 //
1554 // Read in the boot or driver order environment variable (not needed for opt)
1555 //
1556 if ((ShellStatus == SHELL_SUCCESS) && (CurrentOperation.Target < BcfgTargetMax)) {
1557 Length = 0;
1558 Status = gRT->GetVariable (
1559 CurrentOperation.Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder",
1560 (EFI_GUID *)&gEfiGlobalVariableGuid,
1561 NULL,
1562 &Length,
1563 CurrentOperation.Order
1564 );
1565 if (Status == EFI_BUFFER_TOO_SMALL) {
1566 CurrentOperation.Order = AllocateZeroPool (Length+(4*sizeof (CurrentOperation.Order[0])));
1567 if (CurrentOperation.Order == NULL) {
1568 ShellStatus = SHELL_OUT_OF_RESOURCES;
1569 } else {
1570 Status = gRT->GetVariable (
1571 CurrentOperation.Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder",
1572 (EFI_GUID *)&gEfiGlobalVariableGuid,
1573 NULL,
1574 &Length,
1575 CurrentOperation.Order
1576 );
1577 }
1578 }
1579 }
1580
1581 Count = (UINT16)(Length / sizeof (CurrentOperation.Order[0]));
1582
1583 //
1584 // large block to read the type of operation and verify parameter types for the info.
1585 //
1586 if ((ShellStatus == SHELL_SUCCESS) && (CurrentOperation.Target < BcfgTargetMax)) {
1587 for (ParamNumber = 2; ParamNumber < ShellCommandLineGetCount (Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) {
1588 CurrentParam = ShellCommandLineGetRawValue (Package, ParamNumber);
1589 if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"dump") == 0) {
1590 CurrentOperation.Type = BcfgTypeDump;
1591 if (ShellCommandLineGetCount (Package) > 3) {
1592 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellBcfgHiiHandle, L"bcfg");
1593 ShellStatus = SHELL_INVALID_PARAMETER;
1594 }
1595 } else if (ShellCommandLineGetFlag (Package, L"-v")) {
1596 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"-v (without dump)");
1597 ShellStatus = SHELL_INVALID_PARAMETER;
1598 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"add") == 0) {
1599 if ((ParamNumber + 3) >= ShellCommandLineGetCount (Package)) {
1600 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1601 ShellStatus = SHELL_INVALID_PARAMETER;
1602 }
1603
1604 CurrentOperation.Type = BcfgTypeAdd;
1605 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1606 if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1607 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1608 ShellStatus = SHELL_INVALID_PARAMETER;
1609 } else {
1610 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1611 CurrentOperation.Number1 = (UINT16)Intermediate;
1612 ASSERT (CurrentOperation.FileName == NULL);
1613 CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
1614 ASSERT (CurrentOperation.Description == NULL);
1615 CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
1616 }
1617 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"addp") == 0) {
1618 if ((ParamNumber + 3) >= ShellCommandLineGetCount (Package)) {
1619 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1620 ShellStatus = SHELL_INVALID_PARAMETER;
1621 }
1622
1623 CurrentOperation.Type = BcfgTypeAddp;
1624 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1625 if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1626 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1627 ShellStatus = SHELL_INVALID_PARAMETER;
1628 } else {
1629 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1630 CurrentOperation.Number1 = (UINT16)Intermediate;
1631 ASSERT (CurrentOperation.FileName == NULL);
1632 CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
1633 ASSERT (CurrentOperation.Description == NULL);
1634 CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
1635 }
1636 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"addh") == 0) {
1637 if ((ParamNumber + 3) >= ShellCommandLineGetCount (Package)) {
1638 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1639 ShellStatus = SHELL_INVALID_PARAMETER;
1640 }
1641
1642 CurrentOperation.Type = BcfgTypeAddh;
1643 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1644 if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1645 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1646 ShellStatus = SHELL_INVALID_PARAMETER;
1647 } else {
1648 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1649 CurrentOperation.Number1 = (UINT16)Intermediate;
1650 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1651 if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1652 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1653 ShellStatus = SHELL_INVALID_PARAMETER;
1654 } else {
1655 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1656 CurrentOperation.HandleIndex = (UINT16)Intermediate;
1657 ASSERT (CurrentOperation.Description == NULL);
1658 CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
1659 }
1660 }
1661 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"rm") == 0) {
1662 if ((ParamNumber + 1) >= ShellCommandLineGetCount (Package)) {
1663 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1664 ShellStatus = SHELL_INVALID_PARAMETER;
1665 }
1666
1667 CurrentOperation.Type = BcfgTypeRm;
1668 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1669 if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1670 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1671 ShellStatus = SHELL_INVALID_PARAMETER;
1672 } else {
1673 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1674 CurrentOperation.Number1 = (UINT16)Intermediate;
1675 if (CurrentOperation.Number1 >= Count) {
1676 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1677 ShellStatus = SHELL_INVALID_PARAMETER;
1678 }
1679 }
1680 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"mv") == 0) {
1681 if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
1682 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1683 ShellStatus = SHELL_INVALID_PARAMETER;
1684 }
1685
1686 CurrentOperation.Type = BcfgTypeMv;
1687 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1688 if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1689 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1690 ShellStatus = SHELL_INVALID_PARAMETER;
1691 } else {
1692 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1693 CurrentOperation.Number1 = (UINT16)Intermediate;
1694 if (CurrentOperation.Number1 >= Count) {
1695 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1696 ShellStatus = SHELL_INVALID_PARAMETER;
1697 } else {
1698 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1699 if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1700 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1701 ShellStatus = SHELL_INVALID_PARAMETER;
1702 } else {
1703 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1704 CurrentOperation.Number2 = (UINT16)Intermediate;
1705 }
1706
1707 if ( (CurrentOperation.Number2 == CurrentOperation.Number1)
1708 || (CurrentOperation.Number2 >= Count)
1709 )
1710 {
1711 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1712 ShellStatus = SHELL_INVALID_PARAMETER;
1713 }
1714 }
1715 }
1716 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"mod") == 0) {
1717 if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
1718 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1719 ShellStatus = SHELL_INVALID_PARAMETER;
1720 } else {
1721 CurrentOperation.Type = BcfgTypeMod;
1722 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1723 if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1724 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1725 ShellStatus = SHELL_INVALID_PARAMETER;
1726 } else {
1727 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1728 CurrentOperation.Number1 = (UINT16)Intermediate;
1729 if (CurrentOperation.Number1 >= Count) {
1730 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1731 ShellStatus = SHELL_INVALID_PARAMETER;
1732 } else {
1733 ASSERT (CurrentOperation.Description == NULL);
1734 CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
1735 }
1736 }
1737 }
1738 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"modf") == 0) {
1739 if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
1740 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1741 ShellStatus = SHELL_INVALID_PARAMETER;
1742 } else {
1743 CurrentOperation.Type = BcfgTypeModf;
1744 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1745 if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1746 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1747 ShellStatus = SHELL_INVALID_PARAMETER;
1748 } else {
1749 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1750 CurrentOperation.Number1 = (UINT16)Intermediate;
1751 if (CurrentOperation.Number1 >= Count) {
1752 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1753 ShellStatus = SHELL_INVALID_PARAMETER;
1754 } else {
1755 ASSERT (CurrentOperation.FileName == NULL);
1756 CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
1757 }
1758 }
1759 }
1760 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"modp") == 0) {
1761 if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
1762 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1763 ShellStatus = SHELL_INVALID_PARAMETER;
1764 } else {
1765 CurrentOperation.Type = BcfgTypeModp;
1766 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1767 if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1768 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1769 ShellStatus = SHELL_INVALID_PARAMETER;
1770 } else {
1771 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1772 CurrentOperation.Number1 = (UINT16)Intermediate;
1773 if (CurrentOperation.Number1 >= Count) {
1774 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1775 ShellStatus = SHELL_INVALID_PARAMETER;
1776 } else {
1777 ASSERT (CurrentOperation.FileName == NULL);
1778 CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
1779 }
1780 }
1781 }
1782 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"modh") == 0) {
1783 if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
1784 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1785 ShellStatus = SHELL_INVALID_PARAMETER;
1786 } else {
1787 CurrentOperation.Type = BcfgTypeModh;
1788 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1789 if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1790 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1791 ShellStatus = SHELL_INVALID_PARAMETER;
1792 } else {
1793 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1794 CurrentOperation.Number1 = (UINT16)Intermediate;
1795 if (CurrentOperation.Number1 >= Count) {
1796 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1797 ShellStatus = SHELL_INVALID_PARAMETER;
1798 } else {
1799 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1800 if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1801 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1802 ShellStatus = SHELL_INVALID_PARAMETER;
1803 } else {
1804 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1805 CurrentOperation.HandleIndex = (UINT16)Intermediate;
1806 }
1807 }
1808 }
1809 }
1810 } else {
1811 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1812 ShellStatus = SHELL_INVALID_PARAMETER;
1813 }
1814 }
1815 }
1816
1817 if ((ShellStatus == SHELL_SUCCESS) && (CurrentOperation.Target < BcfgTargetMax) && (CurrentOperation.Type < BcfgTypeMax)) {
1818 //
1819 // we have all the info. Do the work
1820 //
1821 switch (CurrentOperation.Type) {
1822 case BcfgTypeDump:
1823 ShellStatus = BcfgDisplayDump (
1824 CurrentOperation.Target == BcfgTargetBootOrder ? L"Boot" : L"Driver",
1825 Count,
1826 CurrentOperation.Order,
1827 ShellCommandLineGetFlag (Package, L"-v")
1828 );
1829 break;
1830 case BcfgTypeMv:
1831 ShellStatus = BcfgMove (
1832 CurrentOperation.Target,
1833 CurrentOperation.Order,
1834 Count,
1835 CurrentOperation.Number1,
1836 CurrentOperation.Number2
1837 );
1838 break;
1839 case BcfgTypeRm:
1840 ShellStatus = BcfgRemove (
1841 CurrentOperation.Target,
1842 CurrentOperation.Order,
1843 Count,
1844 CurrentOperation.Number1
1845 );
1846 break;
1847 case BcfgTypeAdd:
1848 case BcfgTypeAddp:
1849 case BcfgTypeAddh:
1850 ShellStatus = BcfgAdd (
1851 CurrentOperation.Number1,
1852 CurrentOperation.FileName,
1853 CurrentOperation.Description == NULL ? L"" : CurrentOperation.Description,
1854 CurrentOperation.Order,
1855 Count,
1856 CurrentOperation.Target,
1857 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh),
1858 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp),
1859 CurrentOperation.HandleIndex
1860 );
1861 break;
1862 case BcfgTypeMod:
1863 case BcfgTypeModf:
1864 case BcfgTypeModp:
1865 case BcfgTypeModh:
1866 ShellStatus = BcfgMod (&CurrentOperation, Count);
1867 break;
1868 case BcfgTypeOpt:
1869 ShellStatus = BcfgAddOpt (
1870 CurrentOperation.OptData,
1871 CurrentOperation.Order,
1872 Count,
1873 CurrentOperation.Target
1874 );
1875 break;
1876 default:
1877 ASSERT (FALSE);
1878 }
1879 }
1880 }
1881
1882 if (Package != NULL) {
1883 ShellCommandLineFreeVarList (Package);
1884 }
1885
1886 if (CurrentOperation.FileName != NULL) {
1887 FreePool (CurrentOperation.FileName);
1888 }
1889
1890 if (CurrentOperation.Description != NULL) {
1891 FreePool (CurrentOperation.Description);
1892 }
1893
1894 if (CurrentOperation.Order != NULL) {
1895 FreePool (CurrentOperation.Order);
1896 }
1897
1898 return (ShellStatus);
1899 }
1900
1901 /**
1902 Function to get the filename with help context if HII will not be used.
1903
1904 @return The filename with help text in it.
1905 **/
1906 CONST CHAR16 *
1907 EFIAPI
1908 ShellCommandGetManFileNameBcfg (
1909 VOID
1910 )
1911 {
1912 return (mFileName);
1913 }
1914
1915 /**
1916 "Constructor" for the library.
1917
1918 This will register the handler for the bcfg command.
1919
1920 @param[in] ImageHandle the image handle of the process
1921 @param[in] SystemTable the EFI System Table pointer
1922 @param[in] Name the profile name to use
1923
1924 @retval EFI_SUCCESS the shell command handlers were installed sucessfully
1925 @retval EFI_UNSUPPORTED the shell level required was not found.
1926 **/
1927 EFI_STATUS
1928 EFIAPI
1929 BcfgLibraryRegisterBcfgCommand (
1930 IN EFI_HANDLE ImageHandle,
1931 IN EFI_SYSTEM_TABLE *SystemTable,
1932 IN CONST CHAR16 *Name
1933 )
1934 {
1935 if (gShellBcfgHiiHandle != NULL) {
1936 return (EFI_SUCCESS);
1937 }
1938
1939 gShellBcfgHiiHandle = HiiAddPackages (&gShellBcfgHiiGuid, gImageHandle, UefiShellBcfgCommandLibStrings, NULL);
1940 if (gShellBcfgHiiHandle == NULL) {
1941 return (EFI_DEVICE_ERROR);
1942 }
1943
1944 //
1945 // install our shell command handler
1946 //
1947 ShellCommandRegisterCommandName (L"bcfg", ShellCommandRunBcfg, ShellCommandGetManFileNameBcfg, 0, Name, FALSE, gShellBcfgHiiHandle, STRING_TOKEN (STR_GET_HELP_BCFG));
1948
1949 return (EFI_SUCCESS);
1950 }
1951
1952 /**
1953 Destructor for the library. free any resources.
1954
1955 @param ImageHandle The image handle of the process.
1956 @param SystemTable The EFI System Table pointer.
1957 **/
1958 EFI_STATUS
1959 EFIAPI
1960 BcfgLibraryUnregisterBcfgCommand (
1961 IN EFI_HANDLE ImageHandle,
1962 IN EFI_SYSTEM_TABLE *SystemTable
1963 )
1964 {
1965 if (gShellBcfgHiiHandle != NULL) {
1966 HiiRemovePackages (gShellBcfgHiiHandle);
1967 }
1968
1969 gShellBcfgHiiHandle = NULL;
1970 return (EFI_SUCCESS);
1971 }