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