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