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