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