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