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