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