]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/Bcfg.c
Rollback the change to EFI_BOOT_KEY_DATA structure since UEFI Spec adds the clarifica...
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / Bcfg.c
1 /** @file
2 Main file for bcfg shell Debug1 function.
3
4 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "UefiShellDebug1CommandsLib.h"
16 #include <Guid/GlobalVariable.h>
17 #include <Library/PrintLib.h>
18 #include <Library/HandleParsingLib.h>
19 #include <Library/DevicePathLib.h>
20
21 typedef enum {
22 BcfgTargetBootOrder = 0,
23 BcfgTargetDriverOrder = 1,
24 BcfgTargetMax = 2
25 } BCFG_OPERATION_TARGET;
26
27 typedef enum {
28 BcfgTypeDump = 0,
29 BcfgTypeAdd = 1,
30 BcfgTypeAddp = 2,
31 BcfgTypeAddh = 3,
32 BcfgTypeRm = 4,
33 BcfgTypeMv = 5,
34 BcfgTypeOpt = 6,
35 BcfgTypeMax = 7
36 } BCFG_OPERATION_TYPE;
37
38 typedef struct {
39 BCFG_OPERATION_TARGET Target;
40 BCFG_OPERATION_TYPE Type;
41 UINT16 Number1;
42 UINT16 Number2;
43 UINTN HandleIndex;
44 CHAR16 *FileName;
45 CHAR16 *Description;
46 UINT16 *Order;
47 CONST CHAR16 *OptData;
48 } BGFG_OPERATION;
49
50 /**
51 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 Status = gRT->GetVariable(
1031 VariableName,
1032 (EFI_GUID*)&gEfiGlobalVariableGuid,
1033 NULL,
1034 &BufferSize,
1035 Buffer);
1036 }
1037
1038 if (EFI_ERROR(Status) || Buffer == NULL) {
1039 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellDebug1HiiHandle, VariableName, Status);
1040 return (SHELL_INVALID_PARAMETER);
1041 }
1042
1043 if ((*(UINT16*)(Buffer+4)) != 0) {
1044 DevPath = AllocateZeroPool(*(UINT16*)(Buffer+4));
1045 CopyMem(DevPath, Buffer+6+StrSize((CHAR16*)(Buffer+6)), *(UINT16*)(Buffer+4));
1046 DevPathString = ConvertDevicePathToText(DevPath, TRUE, FALSE);
1047 } else {
1048 DevPath = NULL;
1049 DevPathString = NULL;
1050 }
1051 ShellPrintHiiEx(
1052 -1,
1053 -1,
1054 NULL,
1055 STRING_TOKEN(STR_BCFG_LOAD_OPTIONS),
1056 gShellDebug1HiiHandle,
1057 LoopVar,
1058 VariableName,
1059 (CHAR16*)(Buffer+6),
1060 DevPathString,
1061 (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6) <= BufferSize?L'N':L'Y');
1062 if (VerboseOutput) {
1063 for (LoopVar2 = (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6);LoopVar2<BufferSize;LoopVar2++){
1064 ShellPrintEx(
1065 -1,
1066 -1,
1067 NULL,
1068 L"%02x",
1069 Buffer[LoopVar2]);
1070 }
1071 ShellPrintEx(
1072 -1,
1073 -1,
1074 NULL,
1075 L"\r\n");
1076 }
1077
1078 if (Buffer != NULL) {
1079 FreePool(Buffer);
1080 }
1081 if (DevPath != NULL) {
1082 FreePool(DevPath);
1083 }
1084 if (DevPathString != NULL) {
1085 FreePool(DevPathString);
1086 }
1087 }
1088 return (SHELL_SUCCESS);
1089 }
1090
1091 /**
1092 Function to initialize the BCFG operation structure.
1093
1094 @param[in] Struct The stuct to initialize.
1095 **/
1096 VOID
1097 EFIAPI
1098 InitBcfgStructDebug1(
1099 IN BGFG_OPERATION *Struct
1100 )
1101 {
1102 ASSERT(Struct != NULL);
1103 Struct->Target = BcfgTargetMax;
1104 Struct->Type = BcfgTypeMax;
1105 Struct->Number1 = 0;
1106 Struct->Number2 = 0;
1107 Struct->HandleIndex = 0;
1108 Struct->FileName = NULL;
1109 Struct->Description = NULL;
1110 Struct->Order = NULL;
1111 Struct->OptData = NULL;
1112 }
1113
1114
1115 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
1116 {L"-v", TypeFlag},
1117 {L"-opt", TypeMaxValue},
1118 {NULL, TypeMax}
1119 };
1120
1121 /**
1122 Function for 'bcfg' command.
1123
1124 @param[in] ImageHandle Handle to the Image (NULL if Internal).
1125 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
1126 **/
1127 SHELL_STATUS
1128 EFIAPI
1129 ShellCommandRunBcfg (
1130 IN EFI_HANDLE ImageHandle,
1131 IN EFI_SYSTEM_TABLE *SystemTable
1132 )
1133 {
1134 EFI_STATUS Status;
1135 LIST_ENTRY *Package;
1136 CHAR16 *ProblemParam;
1137 SHELL_STATUS ShellStatus;
1138 UINTN ParamNumber;
1139 CONST CHAR16 *CurrentParam;
1140 BGFG_OPERATION CurrentOperation;
1141 UINTN Length;
1142 UINT64 Intermediate;
1143
1144 Length = 0;
1145 ProblemParam = NULL;
1146 Package = NULL;
1147 ShellStatus = SHELL_SUCCESS;
1148
1149 InitBcfgStructDebug1(&CurrentOperation);
1150
1151 //
1152 // initialize the shell lib (we must be in non-auto-init...)
1153 //
1154 Status = ShellInitialize();
1155 ASSERT_EFI_ERROR(Status);
1156
1157 Status = CommandInit();
1158 ASSERT_EFI_ERROR(Status);
1159
1160 //
1161 // parse the command line
1162 //
1163 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
1164 if (EFI_ERROR(Status)) {
1165 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
1166 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam);
1167 FreePool(ProblemParam);
1168 ShellStatus = SHELL_INVALID_PARAMETER;
1169 } else {
1170 ASSERT(FALSE);
1171 }
1172 } else {
1173 //
1174 // Read in if we are doing -OPT
1175 //
1176 if (ShellCommandLineGetFlag(Package, L"-opt")) {
1177 CurrentOperation.OptData = ShellCommandLineGetValue(Package, L"-opt");
1178 if (CurrentOperation.OptData == NULL) {
1179 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"-opt");
1180 ShellStatus = SHELL_INVALID_PARAMETER;
1181 }
1182 CurrentOperation.Type = BcfgTypeOpt;
1183 }
1184
1185 //
1186 // small block to read the target of the operation
1187 //
1188 if ((ShellCommandLineGetCount(Package) < 3 && CurrentOperation.Type != BcfgTypeOpt) ||
1189 (ShellCommandLineGetCount(Package) < 2 && CurrentOperation.Type == BcfgTypeOpt)
1190 ){
1191 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
1192 ShellStatus = SHELL_INVALID_PARAMETER;
1193 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"driver") == 0) {
1194 CurrentOperation.Target = BcfgTargetDriverOrder;
1195 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"boot") == 0) {
1196 CurrentOperation.Target = BcfgTargetBootOrder;
1197 } else {
1198 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellDebug1HiiHandle);
1199 ShellStatus = SHELL_INVALID_PARAMETER;
1200 }
1201
1202
1203 //
1204 // Read in the boot or driver order environment variable (not needed for opt)
1205 //
1206 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {
1207 Length = 0;
1208 Status = gRT->GetVariable(
1209 CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
1210 (EFI_GUID*)&gEfiGlobalVariableGuid,
1211 NULL,
1212 &Length,
1213 CurrentOperation.Order);
1214 if (Status == EFI_BUFFER_TOO_SMALL) {
1215 CurrentOperation.Order = AllocateZeroPool(Length+(4*sizeof(CurrentOperation.Order[0])));
1216 Status = gRT->GetVariable(
1217 CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
1218 (EFI_GUID*)&gEfiGlobalVariableGuid,
1219 NULL,
1220 &Length,
1221 CurrentOperation.Order);
1222 }
1223 }
1224
1225 //
1226 // large block to read the type of operation and verify parameter types for the info.
1227 //
1228 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {
1229 for (ParamNumber = 2 ; ParamNumber < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) {
1230 CurrentParam = ShellCommandLineGetRawValue(Package, ParamNumber);
1231 if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"dump") == 0) {
1232 CurrentOperation.Type = BcfgTypeDump;
1233 } else if (ShellCommandLineGetFlag(Package, L"-v")) {
1234 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"-v (without dump)");
1235 ShellStatus = SHELL_INVALID_PARAMETER;
1236 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"add") == 0) {
1237 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
1238 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
1239 ShellStatus = SHELL_INVALID_PARAMETER;
1240 }
1241 CurrentOperation.Type = BcfgTypeAdd;
1242 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1243 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1244 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1245 ShellStatus = SHELL_INVALID_PARAMETER;
1246 } else {
1247 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1248 CurrentOperation.Number1 = (UINT16)Intermediate;
1249 ASSERT(CurrentOperation.FileName == NULL);
1250 CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1251 ASSERT(CurrentOperation.Description == NULL);
1252 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1253 }
1254 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addp") == 0) {
1255 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
1256 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
1257 ShellStatus = SHELL_INVALID_PARAMETER;
1258 }
1259 CurrentOperation.Type = BcfgTypeAddp;
1260 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1261 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1262 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1263 ShellStatus = SHELL_INVALID_PARAMETER;
1264 } else {
1265 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1266 CurrentOperation.Number1 = (UINT16)Intermediate;
1267 ASSERT(CurrentOperation.FileName == NULL);
1268 CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1269 ASSERT(CurrentOperation.Description == NULL);
1270 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1271 }
1272 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addh") == 0) {
1273 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
1274 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
1275 ShellStatus = SHELL_INVALID_PARAMETER;
1276 }
1277 CurrentOperation.Type = BcfgTypeAddh;
1278 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1279 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1280 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1281 ShellStatus = SHELL_INVALID_PARAMETER;
1282 } else {
1283 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1284 CurrentOperation.Number1 = (UINT16)Intermediate;
1285 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1286 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1287 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1288 ShellStatus = SHELL_INVALID_PARAMETER;
1289 } else {
1290 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1291 CurrentOperation.HandleIndex = (UINT16)Intermediate;
1292 ASSERT(CurrentOperation.Description == NULL);
1293 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1294 }
1295 }
1296 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"rm") == 0) {
1297 if ((ParamNumber + 1) >= ShellCommandLineGetCount(Package)) {
1298 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
1299 ShellStatus = SHELL_INVALID_PARAMETER;
1300 }
1301 CurrentOperation.Type = BcfgTypeRm;
1302 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1303 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1304 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1305 ShellStatus = SHELL_INVALID_PARAMETER;
1306 } else {
1307 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1308 CurrentOperation.Number1 = (UINT16)Intermediate;
1309 if (CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))){
1310 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellDebug1HiiHandle, Length / sizeof(CurrentOperation.Order[0]));
1311 ShellStatus = SHELL_INVALID_PARAMETER;
1312 }
1313 }
1314 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"mv") == 0) {
1315 if ((ParamNumber + 2) >= ShellCommandLineGetCount(Package)) {
1316 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
1317 ShellStatus = SHELL_INVALID_PARAMETER;
1318 }
1319 CurrentOperation.Type = BcfgTypeMv;
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.Number1 = (UINT16)Intermediate;
1327 if (CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))){
1328 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellDebug1HiiHandle, Length / sizeof(CurrentOperation.Order[0]));
1329 ShellStatus = SHELL_INVALID_PARAMETER;
1330 }
1331 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1332 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1333 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1334 ShellStatus = SHELL_INVALID_PARAMETER;
1335 } else {
1336 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1337 CurrentOperation.Number2 = (UINT16)Intermediate;
1338 }
1339 if (CurrentOperation.Number2 == CurrentOperation.Number1
1340 ||CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))
1341 ||CurrentOperation.Number2 > (Length / sizeof(CurrentOperation.Order[0]))
1342 ){
1343 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellDebug1HiiHandle, Length / sizeof(CurrentOperation.Order[0]));
1344 ShellStatus = SHELL_INVALID_PARAMETER;
1345 }
1346 }
1347 } else {
1348 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, CurrentParam);
1349 ShellStatus = SHELL_INVALID_PARAMETER;
1350 }
1351 }
1352 }
1353 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type < BcfgTypeMax) {
1354 //
1355 // we have all the info. Do the work
1356 //
1357 switch (CurrentOperation.Type) {
1358 case BcfgTypeDump:
1359 ShellStatus = BcfgDisplayDumpDebug1(
1360 CurrentOperation.Target == BcfgTargetBootOrder?L"Boot":L"Driver",
1361 Length / sizeof(CurrentOperation.Order[0]),
1362 CurrentOperation.Order,
1363 ShellCommandLineGetFlag(Package, L"-v"));
1364 break;
1365 case BcfgTypeMv:
1366 ShellStatus = BcfgMoveDebug1(
1367 CurrentOperation.Target,
1368 CurrentOperation.Order,
1369 Length / sizeof(CurrentOperation.Order[0]),
1370 CurrentOperation.Number1,
1371 CurrentOperation.Number2);
1372 break;
1373 case BcfgTypeRm:
1374 ShellStatus = BcfgRemoveDebug1(
1375 CurrentOperation.Target,
1376 CurrentOperation.Order,
1377 Length / sizeof(CurrentOperation.Order[0]),
1378 CurrentOperation.Number1);
1379 break;
1380 case BcfgTypeAdd:
1381 case BcfgTypeAddp:
1382 case BcfgTypeAddh:
1383 ShellStatus = BcfgAddDebug1(
1384 CurrentOperation.Number1,
1385 CurrentOperation.FileName,
1386 CurrentOperation.Description==NULL?L"":CurrentOperation.Description,
1387 CurrentOperation.Order,
1388 Length / sizeof(CurrentOperation.Order[0]),
1389 CurrentOperation.Target,
1390 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh),
1391 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp),
1392 CurrentOperation.HandleIndex);
1393 break;
1394 case BcfgTypeOpt:
1395 ShellStatus = BcfgAddOptDebug1(
1396 CurrentOperation.OptData,
1397 CurrentOperation.Order,
1398 Length / sizeof(CurrentOperation.Order[0]),
1399 CurrentOperation.Target);
1400 break;
1401 default:
1402 ASSERT(FALSE);
1403 }
1404 }
1405 }
1406
1407 if (Package != NULL) {
1408 ShellCommandLineFreeVarList (Package);
1409 }
1410 if (CurrentOperation.FileName != NULL) {
1411 FreePool(CurrentOperation.FileName);
1412 }
1413 if (CurrentOperation.Description != NULL) {
1414 FreePool(CurrentOperation.Description);
1415 }
1416 if (CurrentOperation.Order != NULL) {
1417 FreePool(CurrentOperation.Order);
1418 }
1419
1420 return (ShellStatus);
1421 }