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