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