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