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