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