]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/Bcfg.c
Enhance code to more safely and follow coding style.
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / Bcfg.c
1 /** @file
2 Main file for bcfg shell Debug1 function.
3
4 Copyright (c) 2010 - 2012, 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 CopyMem (TempByteBuffer, FilePath, FilePathSize);
519
520 UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", TargetLocation);
521 Status = gRT->SetVariable (
522 OptionStr,
523 &gEfiGlobalVariableGuid,
524 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
525 sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize,
526 TempByteStart
527 );
528
529 FreePool(TempByteStart);
530 } else {
531 Status = EFI_OUT_OF_RESOURCES;
532 }
533
534 if (EFI_ERROR(Status)) {
535 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellDebug1HiiHandle, OptionStr, Status);
536 } else {
537 NewOrder = AllocateZeroPool((OrderCount+1)*sizeof(NewOrder[0]));
538 ASSERT(NewOrder != NULL);
539 CopyMem(NewOrder, CurrentOrder, (OrderCount)*sizeof(NewOrder[0]));
540
541 //
542 // Insert target into order list
543 //
544 for (Index=OrderCount; Index > Position; Index--) {
545 NewOrder[Index] = NewOrder[Index-1];
546 }
547
548 NewOrder[Position] = (UINT16) TargetLocation;
549 Status = gRT->SetVariable (
550 Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder",
551 &gEfiGlobalVariableGuid,
552 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
553 (OrderCount+1) * sizeof(UINT16),
554 NewOrder
555 );
556
557 FreePool(NewOrder);
558
559 if (EFI_ERROR(Status)) {
560 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellDebug1HiiHandle, Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder", Status);
561 ShellStatus = SHELL_INVALID_PARAMETER;
562 } else {
563 Print (L"bcfg: Add %s as %x\n", OptionStr, Position);
564 }
565 }
566 }
567
568 //
569 //If always Free FilePath, will free devicepath in system when use "addh"
570 //
571 if (FilePath!=NULL && !UseHandle) {
572 FreePool (FilePath);
573 }
574
575 if (Str != NULL) {
576 FreePool(Str);
577 }
578
579 if (Handles != NULL) {
580 FreePool (Handles);
581 }
582
583 if (FileList != NULL) {
584 ShellCloseFileMetaArg (&FileList);
585 }
586
587 return (ShellStatus);
588 }
589
590 /**
591 Funciton to remove an item.
592
593 @param[in] Target The target item to move.
594 @param[in] CurrentOrder The pointer to the current order of items.
595 @param[in] OrderCount The number if items in CurrentOrder.
596 @param[in] Location The current location of the Target.
597
598 @retval SHELL_SUCCESS The operation was successful.
599 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
600 **/
601 SHELL_STATUS
602 EFIAPI
603 BcfgRemoveDebug1(
604 IN CONST BCFG_OPERATION_TARGET Target,
605 IN CONST UINT16 *CurrentOrder,
606 IN CONST UINTN OrderCount,
607 IN CONST UINT16 Location
608 )
609 {
610 CHAR16 VariableName[12];
611 UINT16 *NewOrder;
612 EFI_STATUS Status;
613 UINTN NewCount;
614
615 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", CurrentOrder[Location]);
616 Status = gRT->SetVariable(
617 VariableName,
618 (EFI_GUID*)&gEfiGlobalVariableGuid,
619 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
620 0,
621 NULL);
622 if (EFI_ERROR(Status)) {
623 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellDebug1HiiHandle, VariableName, Status);
624 return (SHELL_INVALID_PARAMETER);
625 }
626 NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0]));
627 if (NewOrder != NULL) {
628 NewCount = OrderCount;
629 CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0]));
630 CopyMem(NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof(CurrentOrder[0]));
631 NewCount--;
632
633 Status = gRT->SetVariable(
634 Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
635 (EFI_GUID*)&gEfiGlobalVariableGuid,
636 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
637 NewCount*sizeof(NewOrder[0]),
638 NewOrder);
639 FreePool(NewOrder);
640 } else {
641 Status = EFI_OUT_OF_RESOURCES;
642 }
643 if (EFI_ERROR(Status)) {
644 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellDebug1HiiHandle, Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status);
645 return (SHELL_INVALID_PARAMETER);
646 }
647 return (SHELL_SUCCESS);
648 }
649
650 /**
651 Funciton to move a item to another location.
652
653 @param[in] Target The target item to move.
654 @param[in] CurrentOrder The pointer to the current order of items.
655 @param[in] OrderCount The number if items in CurrentOrder.
656 @param[in] OldLocation The current location of the Target.
657 @param[in] NewLocation The desired location of the Target.
658
659 @retval SHELL_SUCCESS The operation was successful.
660 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
661 **/
662 SHELL_STATUS
663 EFIAPI
664 BcfgMoveDebug1(
665 IN CONST BCFG_OPERATION_TARGET Target,
666 IN CONST UINT16 *CurrentOrder,
667 IN CONST UINTN OrderCount,
668 IN CONST UINT16 OldLocation,
669 IN CONST UINT16 NewLocation
670 )
671 {
672 UINT16 *NewOrder;
673 EFI_STATUS Status;
674 UINT16 Temp;
675
676 NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0]));
677 ASSERT(NewOrder != NULL);
678
679 Temp = CurrentOrder[OldLocation];
680 CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0]));
681 CopyMem(NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof(CurrentOrder[0]));
682 CopyMem(NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof(CurrentOrder[0]));
683 NewOrder[NewLocation] = Temp;
684
685
686 Status = gRT->SetVariable(
687 Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
688 (EFI_GUID*)&gEfiGlobalVariableGuid,
689 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
690 OrderCount*sizeof(CurrentOrder[0]),
691 NewOrder);
692
693 FreePool(NewOrder);
694
695 if (EFI_ERROR(Status)) {
696 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellDebug1HiiHandle, Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status);
697 return (SHELL_INVALID_PARAMETER);
698 }
699 return (SHELL_SUCCESS);
700 }
701
702 /**
703 Function to add optional data to an option.
704
705 @param[in] OptData The optional data to add.
706 @param[in] CurrentOrder The pointer to the current order of items.
707 @param[in] OrderCount The number if items in CurrentOrder.
708 @param[in] Target The target of the operation.
709
710 @retval SHELL_SUCCESS The operation was succesful.
711 **/
712 SHELL_STATUS
713 EFIAPI
714 BcfgAddOptDebug1(
715 IN CONST CHAR16 *OptData,
716 IN CONST UINT16 *CurrentOrder,
717 IN CONST UINTN OrderCount,
718 IN CONST BCFG_OPERATION_TARGET Target
719 )
720 {
721 EFI_KEY_OPTION NewKeyOption;
722 EFI_KEY_OPTION *KeyOptionBuffer;
723 SHELL_STATUS ShellStatus;
724 EFI_STATUS Status;
725 UINT16 OptionIndex;
726 UINT16 LoopCounter;
727 UINT64 Intermediate;
728 CONST CHAR16 *Temp;
729 CONST CHAR16 *Walker;
730 CHAR16 *FileName;
731 CHAR16 *Temp2;
732 CHAR16 *Data;
733 UINT16 KeyIndex;
734 CHAR16 VariableName[12];
735
736 SHELL_FILE_HANDLE FileHandle;
737
738 Status = EFI_SUCCESS;
739 ShellStatus = SHELL_SUCCESS;
740 Walker = OptData;
741 FileName = NULL;
742 Data = NULL;
743 KeyOptionBuffer = NULL;
744
745 ZeroMem(&NewKeyOption, sizeof(EFI_KEY_OPTION));
746
747 while(Walker[0] == L' ') {
748 Walker++;
749 }
750
751 //
752 // Get the index of the variable we are changing.
753 //
754 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
755 if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL || ((UINT16)Intermediate) > ((UINT16)OrderCount)) {
756 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"Option Index");
757 ShellStatus = SHELL_INVALID_PARAMETER;
758 return (ShellStatus);
759 }
760 OptionIndex = (UINT16)Intermediate;
761
762 Temp = StrStr(Walker, L" ");
763 if (Temp != NULL) {
764 Walker = Temp;
765 }
766 while(Walker[0] == L' ') {
767 Walker++;
768 }
769
770 //
771 // determine whether we have file with data, quote delimited information, or a hot-key
772 //
773 if (Walker[0] == L'\"') {
774 //
775 // quoted filename or quoted information.
776 //
777 Temp = StrStr(Walker+1, L"\"");
778 if (Temp == NULL || StrLen(Temp) != 1) {
779 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Walker);
780 ShellStatus = SHELL_INVALID_PARAMETER;
781 } else {
782 FileName = StrnCatGrow(&FileName, NULL, Walker+1, 0);
783 if (FileName == NULL) {
784 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle);
785 ShellStatus = SHELL_OUT_OF_RESOURCES;
786 return (ShellStatus);
787 }
788 Temp2 = StrStr(FileName, L"\"");
789 ASSERT(Temp2 != NULL);
790 Temp2[0] = CHAR_NULL;
791 Temp2++;
792 if (StrLen(Temp2)>0) {
793 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Walker);
794 ShellStatus = SHELL_INVALID_PARAMETER;
795 }
796 if (EFI_ERROR(ShellFileExists(Walker))) {
797 //
798 // Not a file. must be misc information.
799 //
800 Data = FileName;
801 FileName = NULL;
802 } else {
803 FileName = StrnCatGrow(&FileName, NULL, Walker, 0);
804 }
805 }
806 } else {
807 //
808 // filename or hot key information.
809 //
810 if (StrStr(Walker, L" ") == NULL) {
811 //
812 // filename
813 //
814 if (EFI_ERROR(ShellFileExists(Walker))) {
815 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellDebug1HiiHandle, Walker);
816 ShellStatus = SHELL_INVALID_PARAMETER;
817 } else {
818 FileName = StrnCatGrow(&FileName, NULL, Walker, 0);
819 }
820 } else {
821 if (Target != BcfgTargetBootOrder) {
822 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_BOOT_ONLY), gShellDebug1HiiHandle);
823 ShellStatus = SHELL_INVALID_PARAMETER;
824 }
825
826 if (ShellStatus == SHELL_SUCCESS) {
827 //
828 // Get hot key information
829 //
830 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
831 if (EFI_ERROR(Status) || (((UINT32)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) {
832 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Walker);
833 ShellStatus = SHELL_INVALID_PARAMETER;
834 }
835 NewKeyOption.KeyData.PackedValue = (UINT32)Intermediate;
836 Temp = StrStr(Walker, L" ");
837 if (Temp != NULL) {
838 Walker = Temp;
839 }
840 while(Walker[0] == L' ') {
841 Walker++;
842 }
843 }
844
845 if (ShellStatus == SHELL_SUCCESS) {
846 //
847 // Now we know how many EFI_INPUT_KEY structs we need to attach to the end of the EFI_KEY_OPTION struct.
848 // Re-allocate with the added information.
849 //
850 KeyOptionBuffer = AllocateCopyPool(sizeof(EFI_KEY_OPTION) + (sizeof(EFI_KEY_DATA) * NewKeyOption.KeyData.Options.InputKeyCount), &NewKeyOption);
851 if (KeyOptionBuffer == NULL) {
852 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellDebug1HiiHandle);
853 ShellStatus = SHELL_OUT_OF_RESOURCES;
854 }
855 }
856 for (LoopCounter = 0 ; ShellStatus == SHELL_SUCCESS && LoopCounter < KeyOptionBuffer->KeyData.Options.InputKeyCount; LoopCounter++) {
857 //
858 // ScanCode
859 //
860 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
861 if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) {
862 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Walker);
863 ShellStatus = SHELL_INVALID_PARAMETER;
864 }
865 ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].ScanCode = (UINT16)Intermediate;
866 Temp = StrStr(Walker, L" ");
867 if (Temp != NULL) {
868 Walker = Temp;
869 }
870 while(Walker[0] == L' ') {
871 Walker++;
872 }
873
874 //
875 // UnicodeChar
876 //
877 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
878 if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate)) {
879 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Walker);
880 ShellStatus = SHELL_INVALID_PARAMETER;
881 }
882 ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].UnicodeChar = (UINT16)Intermediate;
883 Temp = StrStr(Walker, L" ");
884 if (Temp != NULL) {
885 Walker = Temp;
886 }
887 while(Walker[0] == L' ') {
888 Walker++;
889 }
890 }
891
892 if (ShellStatus == SHELL_SUCCESS) {
893 //
894 // Now do the BootOption / BootOptionCrc
895 //
896 ASSERT (OptionIndex <= OrderCount);
897 KeyOptionBuffer->BootOption = CurrentOrder[OptionIndex];
898 Status = GetBootOptionCrcDebug1(&(KeyOptionBuffer->BootOptionCrc), KeyOptionBuffer->BootOption);
899 if (EFI_ERROR(Status)) {
900 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"Option Index");
901 ShellStatus = SHELL_INVALID_PARAMETER;
902 }
903 }
904
905 if (ShellStatus == SHELL_SUCCESS) {
906 for (Temp2 = NULL, KeyIndex = 0 ; KeyIndex < 0xFFFF ; KeyIndex++) {
907 UnicodeSPrint(VariableName, sizeof(VariableName), L"Key%04x", KeyIndex);
908 Status = gRT->GetVariable(
909 VariableName,
910 (EFI_GUID*)&gEfiGlobalVariableGuid,
911 NULL,
912 (UINTN*)&Intermediate,
913 NULL);
914 if (Status == EFI_NOT_FOUND) {
915 break;
916 }
917 }
918 Status = gRT->SetVariable(
919 VariableName,
920 (EFI_GUID*)&gEfiGlobalVariableGuid,
921 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
922 sizeof(EFI_KEY_OPTION) + (sizeof(EFI_KEY_DATA) * NewKeyOption.KeyData.Options.InputKeyCount),
923 KeyOptionBuffer);
924 if (EFI_ERROR(Status)) {
925 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellDebug1HiiHandle, VariableName, Status);
926 ShellStatus = SHELL_INVALID_PARAMETER;
927 }
928 ASSERT(FileName == NULL && Data == NULL);
929 }
930 }
931 }
932
933 //
934 // Shouldn't be possible to have have both. Neither is ok though.
935 //
936 ASSERT(FileName == NULL || Data == NULL);
937
938 if (ShellStatus == SHELL_SUCCESS && (FileName != NULL || Data != NULL)) {
939 if (FileName != NULL) {
940 //
941 // Open the file and populate the data buffer.
942 //
943 Status = ShellOpenFileByName(
944 FileName,
945 &FileHandle,
946 EFI_FILE_MODE_READ,
947 0);
948 if (!EFI_ERROR(Status)) {
949 Status = ShellGetFileSize(FileHandle, &Intermediate);
950 }
951 Data = AllocateZeroPool((UINTN)Intermediate);
952 if (Data == NULL) {
953 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellDebug1HiiHandle);
954 ShellStatus = SHELL_OUT_OF_RESOURCES;
955 }
956 if (!EFI_ERROR(Status)) {
957 Status = ShellReadFile(FileHandle, (UINTN *)&Intermediate, Data);
958 }
959 } else {
960 Intermediate = StrSize(Data);
961 }
962
963 if (!EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS && Data != NULL) {
964 Status = UpdateOptionalDataDebug1(CurrentOrder[OptionIndex], (UINTN)Intermediate, (UINT8*)Data, Target);
965 if (EFI_ERROR(Status)) {
966 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellDebug1HiiHandle, VariableName, Status);
967 ShellStatus = SHELL_INVALID_PARAMETER;
968 }
969 }
970 if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
971 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellDebug1HiiHandle, VariableName, Status);
972 ShellStatus = SHELL_INVALID_PARAMETER;
973 }
974 }
975
976 SHELL_FREE_NON_NULL(Data);
977 SHELL_FREE_NON_NULL(KeyOptionBuffer);
978 SHELL_FREE_NON_NULL(FileName);
979 return ShellStatus;
980 }
981
982 /**
983 Function to dump the Bcfg information.
984
985 @param[in] Op The operation.
986 @param[in] OrderCount How many to dump.
987 @param[in] CurrentOrder The pointer to the current order of items.
988 @param[in] VerboseOutput TRUE for extra output. FALSE otherwise.
989
990 @retval SHELL_SUCCESS The dump was successful.
991 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
992 **/
993 SHELL_STATUS
994 EFIAPI
995 BcfgDisplayDumpDebug1(
996 IN CONST CHAR16 *Op,
997 IN CONST UINTN OrderCount,
998 IN CONST UINT16 *CurrentOrder,
999 IN CONST BOOLEAN VerboseOutput
1000 )
1001 {
1002 EFI_STATUS Status;
1003 UINT8 *Buffer;
1004 UINTN BufferSize;
1005 CHAR16 VariableName[12];
1006 UINTN LoopVar;
1007 UINTN LoopVar2;
1008 CHAR16 *DevPathString;
1009 VOID *DevPath;
1010
1011 if (OrderCount == 0) {
1012 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_BCFG_NONE), gShellDebug1HiiHandle);
1013 return (SHELL_SUCCESS);
1014 }
1015
1016 for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++) {
1017 Buffer = NULL;
1018 BufferSize = 0;
1019 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]);
1020
1021 Status = gRT->GetVariable(
1022 VariableName,
1023 (EFI_GUID*)&gEfiGlobalVariableGuid,
1024 NULL,
1025 &BufferSize,
1026 Buffer);
1027 if (Status == EFI_BUFFER_TOO_SMALL) {
1028 Buffer = AllocateZeroPool(BufferSize);
1029 Status = gRT->GetVariable(
1030 VariableName,
1031 (EFI_GUID*)&gEfiGlobalVariableGuid,
1032 NULL,
1033 &BufferSize,
1034 Buffer);
1035 }
1036
1037 if (EFI_ERROR(Status) || Buffer == NULL) {
1038 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellDebug1HiiHandle, VariableName, Status);
1039 return (SHELL_INVALID_PARAMETER);
1040 }
1041
1042 if ((*(UINT16*)(Buffer+4)) != 0) {
1043 DevPath = AllocateZeroPool(*(UINT16*)(Buffer+4));
1044 CopyMem(DevPath, Buffer+6+StrSize((CHAR16*)(Buffer+6)), *(UINT16*)(Buffer+4));
1045 DevPathString = gDevPathToText->ConvertDevicePathToText(DevPath, TRUE, FALSE);
1046 } else {
1047 DevPath = NULL;
1048 DevPathString = NULL;
1049 }
1050 ShellPrintHiiEx(
1051 -1,
1052 -1,
1053 NULL,
1054 STRING_TOKEN(STR_BCFG_LOAD_OPTIONS),
1055 gShellDebug1HiiHandle,
1056 LoopVar,
1057 VariableName,
1058 (CHAR16*)(Buffer+6),
1059 DevPathString,
1060 (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6) <= BufferSize?L'N':L'Y');
1061 if (VerboseOutput) {
1062 for (LoopVar2 = (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6);LoopVar2<BufferSize;LoopVar2++){
1063 ShellPrintEx(
1064 -1,
1065 -1,
1066 NULL,
1067 L"%02x",
1068 Buffer[LoopVar2]);
1069 }
1070 ShellPrintEx(
1071 -1,
1072 -1,
1073 NULL,
1074 L"\r\n");
1075 }
1076
1077 if (Buffer != NULL) {
1078 FreePool(Buffer);
1079 }
1080 if (DevPath != NULL) {
1081 FreePool(DevPath);
1082 }
1083 if (DevPathString != NULL) {
1084 FreePool(DevPathString);
1085 }
1086 }
1087 return (SHELL_SUCCESS);
1088 }
1089
1090 /**
1091 Function to initialize the BCFG operation structure.
1092
1093 @param[in] Struct The stuct to initialize.
1094 **/
1095 VOID
1096 EFIAPI
1097 InitBcfgStructDebug1(
1098 IN BGFG_OPERATION *Struct
1099 )
1100 {
1101 ASSERT(Struct != NULL);
1102 Struct->Target = BcfgTargetMax;
1103 Struct->Type = BcfgTypeMax;
1104 Struct->Number1 = 0;
1105 Struct->Number2 = 0;
1106 Struct->HandleIndex = 0;
1107 Struct->FileName = NULL;
1108 Struct->Description = NULL;
1109 Struct->Order = NULL;
1110 Struct->OptData = NULL;
1111 }
1112
1113
1114 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
1115 {L"-v", TypeFlag},
1116 {L"-opt", TypeMaxValue},
1117 {NULL, TypeMax}
1118 };
1119
1120 /**
1121 Function for 'bcfg' command.
1122
1123 @param[in] ImageHandle Handle to the Image (NULL if Internal).
1124 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
1125 **/
1126 SHELL_STATUS
1127 EFIAPI
1128 ShellCommandRunBcfg (
1129 IN EFI_HANDLE ImageHandle,
1130 IN EFI_SYSTEM_TABLE *SystemTable
1131 )
1132 {
1133 EFI_STATUS Status;
1134 LIST_ENTRY *Package;
1135 CHAR16 *ProblemParam;
1136 SHELL_STATUS ShellStatus;
1137 UINTN ParamNumber;
1138 CONST CHAR16 *CurrentParam;
1139 BGFG_OPERATION CurrentOperation;
1140 UINTN Length;
1141 UINT64 Intermediate;
1142
1143 Length = 0;
1144 ProblemParam = NULL;
1145 Package = NULL;
1146 ShellStatus = SHELL_SUCCESS;
1147
1148 InitBcfgStructDebug1(&CurrentOperation);
1149
1150 //
1151 // initialize the shell lib (we must be in non-auto-init...)
1152 //
1153 Status = ShellInitialize();
1154 ASSERT_EFI_ERROR(Status);
1155
1156 Status = CommandInit();
1157 ASSERT_EFI_ERROR(Status);
1158
1159 //
1160 // parse the command line
1161 //
1162 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
1163 if (EFI_ERROR(Status)) {
1164 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
1165 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam);
1166 FreePool(ProblemParam);
1167 ShellStatus = SHELL_INVALID_PARAMETER;
1168 } else {
1169 ASSERT(FALSE);
1170 }
1171 } else {
1172 //
1173 // Read in if we are doing -OPT
1174 //
1175 if (ShellCommandLineGetFlag(Package, L"-opt")) {
1176 CurrentOperation.OptData = ShellCommandLineGetValue(Package, L"-opt");
1177 if (CurrentOperation.OptData == NULL) {
1178 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"-opt");
1179 ShellStatus = SHELL_INVALID_PARAMETER;
1180 }
1181 CurrentOperation.Type = BcfgTypeOpt;
1182 }
1183
1184 //
1185 // small block to read the target of the operation
1186 //
1187 if ((ShellCommandLineGetCount(Package) < 3 && CurrentOperation.Type != BcfgTypeOpt) ||
1188 (ShellCommandLineGetCount(Package) < 2 && CurrentOperation.Type == BcfgTypeOpt)
1189 ){
1190 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
1191 ShellStatus = SHELL_INVALID_PARAMETER;
1192 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"driver") == 0) {
1193 CurrentOperation.Target = BcfgTargetDriverOrder;
1194 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"boot") == 0) {
1195 CurrentOperation.Target = BcfgTargetBootOrder;
1196 } else {
1197 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellDebug1HiiHandle);
1198 ShellStatus = SHELL_INVALID_PARAMETER;
1199 }
1200
1201
1202 //
1203 // Read in the boot or driver order environment variable (not needed for opt)
1204 //
1205 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {
1206 Length = 0;
1207 Status = gRT->GetVariable(
1208 CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
1209 (EFI_GUID*)&gEfiGlobalVariableGuid,
1210 NULL,
1211 &Length,
1212 CurrentOperation.Order);
1213 if (Status == EFI_BUFFER_TOO_SMALL) {
1214 CurrentOperation.Order = AllocateZeroPool(Length+(4*sizeof(CurrentOperation.Order[0])));
1215 Status = gRT->GetVariable(
1216 CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
1217 (EFI_GUID*)&gEfiGlobalVariableGuid,
1218 NULL,
1219 &Length,
1220 CurrentOperation.Order);
1221 }
1222 }
1223
1224 //
1225 // large block to read the type of operation and verify parameter types for the info.
1226 //
1227 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {
1228 for (ParamNumber = 2 ; ParamNumber < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) {
1229 CurrentParam = ShellCommandLineGetRawValue(Package, ParamNumber);
1230 if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"dump") == 0) {
1231 CurrentOperation.Type = BcfgTypeDump;
1232 } else if (ShellCommandLineGetFlag(Package, L"-v")) {
1233 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"-v (without dump)");
1234 ShellStatus = SHELL_INVALID_PARAMETER;
1235 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"add") == 0) {
1236 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
1237 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
1238 ShellStatus = SHELL_INVALID_PARAMETER;
1239 }
1240 CurrentOperation.Type = BcfgTypeAdd;
1241 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1242 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1243 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1244 ShellStatus = SHELL_INVALID_PARAMETER;
1245 } else {
1246 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1247 CurrentOperation.Number1 = (UINT16)Intermediate;
1248 ASSERT(CurrentOperation.FileName == NULL);
1249 CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1250 ASSERT(CurrentOperation.Description == NULL);
1251 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1252 }
1253 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addp") == 0) {
1254 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
1255 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
1256 ShellStatus = SHELL_INVALID_PARAMETER;
1257 }
1258 CurrentOperation.Type = BcfgTypeAddp;
1259 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1260 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1261 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1262 ShellStatus = SHELL_INVALID_PARAMETER;
1263 } else {
1264 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1265 CurrentOperation.Number1 = (UINT16)Intermediate;
1266 ASSERT(CurrentOperation.FileName == NULL);
1267 CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1268 ASSERT(CurrentOperation.Description == NULL);
1269 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1270 }
1271 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addh") == 0) {
1272 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
1273 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
1274 ShellStatus = SHELL_INVALID_PARAMETER;
1275 }
1276 CurrentOperation.Type = BcfgTypeAddh;
1277 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1278 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1279 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1280 ShellStatus = SHELL_INVALID_PARAMETER;
1281 } else {
1282 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1283 CurrentOperation.Number1 = (UINT16)Intermediate;
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.HandleIndex = (UINT16)Intermediate;
1291 ASSERT(CurrentOperation.Description == NULL);
1292 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1293 }
1294 }
1295 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"rm") == 0) {
1296 if ((ParamNumber + 1) >= ShellCommandLineGetCount(Package)) {
1297 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
1298 ShellStatus = SHELL_INVALID_PARAMETER;
1299 }
1300 CurrentOperation.Type = BcfgTypeRm;
1301 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1302 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1303 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1304 ShellStatus = SHELL_INVALID_PARAMETER;
1305 } else {
1306 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1307 CurrentOperation.Number1 = (UINT16)Intermediate;
1308 if (CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))){
1309 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellDebug1HiiHandle, Length / sizeof(CurrentOperation.Order[0]));
1310 ShellStatus = SHELL_INVALID_PARAMETER;
1311 }
1312 }
1313 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"mv") == 0) {
1314 if ((ParamNumber + 2) >= ShellCommandLineGetCount(Package)) {
1315 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
1316 ShellStatus = SHELL_INVALID_PARAMETER;
1317 }
1318 CurrentOperation.Type = BcfgTypeMv;
1319 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1320 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1321 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1322 ShellStatus = SHELL_INVALID_PARAMETER;
1323 } else {
1324 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1325 CurrentOperation.Number1 = (UINT16)Intermediate;
1326 if (CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))){
1327 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellDebug1HiiHandle, Length / sizeof(CurrentOperation.Order[0]));
1328 ShellStatus = SHELL_INVALID_PARAMETER;
1329 }
1330 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1331 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1332 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1333 ShellStatus = SHELL_INVALID_PARAMETER;
1334 } else {
1335 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1336 CurrentOperation.Number2 = (UINT16)Intermediate;
1337 }
1338 if (CurrentOperation.Number2 == CurrentOperation.Number1
1339 ||CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))
1340 ||CurrentOperation.Number2 > (Length / sizeof(CurrentOperation.Order[0]))
1341 ){
1342 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellDebug1HiiHandle, Length / sizeof(CurrentOperation.Order[0]));
1343 ShellStatus = SHELL_INVALID_PARAMETER;
1344 }
1345 }
1346 } else {
1347 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1348 ShellStatus = SHELL_INVALID_PARAMETER;
1349 }
1350 }
1351 }
1352 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type < BcfgTypeMax) {
1353 //
1354 // we have all the info. Do the work
1355 //
1356 switch (CurrentOperation.Type) {
1357 case BcfgTypeDump:
1358 ShellStatus = BcfgDisplayDumpDebug1(
1359 CurrentOperation.Target == BcfgTargetBootOrder?L"Boot":L"Driver",
1360 Length / sizeof(CurrentOperation.Order[0]),
1361 CurrentOperation.Order,
1362 ShellCommandLineGetFlag(Package, L"-v"));
1363 break;
1364 case BcfgTypeMv:
1365 ShellStatus = BcfgMoveDebug1(
1366 CurrentOperation.Target,
1367 CurrentOperation.Order,
1368 Length / sizeof(CurrentOperation.Order[0]),
1369 CurrentOperation.Number1,
1370 CurrentOperation.Number2);
1371 break;
1372 case BcfgTypeRm:
1373 ShellStatus = BcfgRemoveDebug1(
1374 CurrentOperation.Target,
1375 CurrentOperation.Order,
1376 Length / sizeof(CurrentOperation.Order[0]),
1377 CurrentOperation.Number1);
1378 break;
1379 case BcfgTypeAdd:
1380 case BcfgTypeAddp:
1381 case BcfgTypeAddh:
1382 ShellStatus = BcfgAddDebug1(
1383 CurrentOperation.Number1,
1384 CurrentOperation.FileName,
1385 CurrentOperation.Description==NULL?L"":CurrentOperation.Description,
1386 CurrentOperation.Order,
1387 Length / sizeof(CurrentOperation.Order[0]),
1388 CurrentOperation.Target,
1389 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh),
1390 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp),
1391 CurrentOperation.HandleIndex);
1392 break;
1393 case BcfgTypeOpt:
1394 ShellStatus = BcfgAddOptDebug1(
1395 CurrentOperation.OptData,
1396 CurrentOperation.Order,
1397 Length / sizeof(CurrentOperation.Order[0]),
1398 CurrentOperation.Target);
1399 break;
1400 default:
1401 ASSERT(FALSE);
1402 }
1403 }
1404 }
1405
1406 if (Package != NULL) {
1407 ShellCommandLineFreeVarList (Package);
1408 }
1409 if (CurrentOperation.FileName != NULL) {
1410 FreePool(CurrentOperation.FileName);
1411 }
1412 if (CurrentOperation.Description != NULL) {
1413 FreePool(CurrentOperation.Description);
1414 }
1415 if (CurrentOperation.Order != NULL) {
1416 FreePool(CurrentOperation.Order);
1417 }
1418
1419 return (ShellStatus);
1420 }