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