]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellInstall1CommandsLib/Bcfg.c
update Bcfg to correctly remove by option index not variable name and add driver...
[mirror_edk2.git] / ShellPkg / Library / UefiShellInstall1CommandsLib / Bcfg.c
1 /** @file
2 Main file for bcfg shell Install1 function.
3
4 Copyright (c) 2010 - 2011, 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 This function will populate the device path protocol parameter based on TheHandle.
52
53 @param[in,out] DevPath On a sucessful return the device path to the handle.
54
55 @retval EFI_SUCCESS The device path was sucessfully returned.
56 @retval other A error from gBS->HandleProtocol.
57
58 @sa HandleProtocol
59 **/
60 EFI_STATUS
61 EFIAPI
62 GetDevicePathForDriverHandleInstall1 (
63 IN EFI_HANDLE TheHandle,
64 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
65 )
66 {
67 EFI_STATUS Status;
68 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
69 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
70
71 Status = gBS->OpenProtocol (
72 TheHandle,
73 &gEfiLoadedImageProtocolGuid,
74 (VOID**)&LoadedImage,
75 gImageHandle,
76 NULL,
77 EFI_OPEN_PROTOCOL_GET_PROTOCOL
78 );
79 if (!EFI_ERROR (Status)) {
80 Status = gBS->OpenProtocol (
81 LoadedImage->DeviceHandle,
82 &gEfiDevicePathProtocolGuid,
83 (VOID**)&ImageDevicePath,
84 gImageHandle,
85 NULL,
86 EFI_OPEN_PROTOCOL_GET_PROTOCOL
87 );
88 if (!EFI_ERROR (Status)) {
89 // *DevPath = DuplicateDevicePath (ImageDevicePath);
90 // *FilePath = DuplicateDevicePath (LoadedImage->FilePath);
91 *FilePath = AppendDevicePath(ImageDevicePath,LoadedImage->FilePath);
92 gBS->CloseProtocol(
93 LoadedImage->DeviceHandle,
94 &gEfiDevicePathProtocolGuid,
95 gImageHandle,
96 NULL);
97 }
98 gBS->CloseProtocol(
99 TheHandle,
100 &gEfiLoadedImageProtocolGuid,
101 gImageHandle,
102 NULL);
103 }
104 return (Status);
105 }
106
107 /**
108 Function to add a option.
109
110 @param[in] Position The position to add Target at.
111 @param[in] File The file to make the target.
112 @param[in] Desc The description text.
113 @param[in] CurrentOrder The pointer to the current order of items.
114 @param[in] OrderCount The number if items in CurrentOrder.
115 @param[in] Target The info on the option to add.
116 @param[in] UseHandle TRUE to use HandleNumber, FALSE to use File and Desc.
117 @param[in] UsePath TRUE to convert to devicepath.
118 @param[in] HandleNumber The handle number to add.
119
120 @retval SHELL_SUCCESS The operation was successful.
121 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
122 **/
123 SHELL_STATUS
124 EFIAPI
125 BcfgAddInstall1(
126 IN UINTN Position,
127 IN CONST CHAR16 *File,
128 IN CONST CHAR16 *Desc,
129 IN CONST UINT16 *CurrentOrder,
130 IN CONST UINTN OrderCount,
131 IN CONST BCFG_OPERATION_TARGET Target,
132 IN CONST BOOLEAN UseHandle,
133 IN CONST BOOLEAN UsePath,
134 IN CONST UINTN HandleNumber
135 )
136 {
137 EFI_STATUS Status;
138 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
139 EFI_DEVICE_PATH_PROTOCOL *FilePath;
140 EFI_DEVICE_PATH_PROTOCOL *FileNode;
141 // EFI_DEVICE_PATH_PROTOCOL *DevPath;
142 CHAR16 *Str;
143 // CONST CHAR16 *StringWalker;
144 UINT8 *TempByteBuffer;
145 UINT8 *TempByteStart;
146 EFI_SHELL_FILE_INFO *Arg;
147 EFI_SHELL_FILE_INFO *FileList;
148 CHAR16 OptionStr[40];
149 UINTN DescSize, FilePathSize;
150 BOOLEAN Found;
151 UINTN TargetLocation;
152 UINTN Index;
153 EFI_HANDLE *Handles;
154 EFI_HANDLE CurHandle;
155 UINTN DriverBindingHandleCount;
156 UINTN ParentControllerHandleCount;
157 UINTN ChildControllerHandleCount;
158 SHELL_STATUS ShellStatus;
159 UINT16 *NewOrder;
160
161 if (!UseHandle) {
162 if (File == NULL || Desc == NULL) {
163 return (SHELL_INVALID_PARAMETER);
164 }
165 } else {
166 if (HandleNumber == 0) {
167 return (SHELL_INVALID_PARAMETER);
168 }
169 }
170
171 if (Position > OrderCount) {
172 Position = OrderCount;
173 }
174
175 Str = NULL;
176 FilePath = NULL;
177 FileNode = NULL;
178 FileList = NULL;
179 Handles = NULL;
180 ShellStatus = SHELL_SUCCESS;
181 TargetLocation = 0xFFFF;
182
183 if (UseHandle) {
184 CurHandle = ConvertHandleIndexToHandle(HandleNumber);
185 if (CurHandle == NULL) {
186 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, L"Handle Number");
187 ShellStatus = SHELL_INVALID_PARAMETER;
188 } else {
189 if (Target == BcfgTargetBootOrder) {
190 //
191 //Make sure that the handle should point to a real controller
192 //
193 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
194 CurHandle,
195 &DriverBindingHandleCount,
196 NULL);
197
198 Status = PARSE_HANDLE_DATABASE_PARENTS (
199 CurHandle,
200 &ParentControllerHandleCount,
201 NULL);
202
203 Status = ParseHandleDatabaseForChildControllers (
204 CurHandle,
205 &ChildControllerHandleCount,
206 NULL);
207
208 if (DriverBindingHandleCount > 0
209 || ParentControllerHandleCount > 0
210 || ChildControllerHandleCount > 0) {
211 FilePath = NULL;
212 Status = gBS->HandleProtocol (
213 CurHandle,
214 &gEfiDevicePathProtocolGuid,
215 (VOID**)&FilePath);
216 }
217 if (EFI_ERROR (Status)) {
218 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellInstall1HiiHandle, HandleNumber);
219 ShellStatus = SHELL_INVALID_PARAMETER;
220 }
221 } else {
222 //
223 //Make sure that the handle should point to driver, not a controller.
224 //
225 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
226 CurHandle,
227 &DriverBindingHandleCount,
228 NULL);
229
230 Status = PARSE_HANDLE_DATABASE_PARENTS (
231 CurHandle,
232 &ParentControllerHandleCount,
233 NULL);
234
235 Status = ParseHandleDatabaseForChildControllers (
236 CurHandle,
237 &ChildControllerHandleCount,
238 NULL);
239
240 Status = gBS->HandleProtocol (
241 CurHandle,
242 &gEfiDevicePathProtocolGuid,
243 (VOID**)&FilePath);
244
245 if (DriverBindingHandleCount > 0
246 || ParentControllerHandleCount > 0
247 || ChildControllerHandleCount > 0
248 || !EFI_ERROR(Status) ) {
249 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, L"Handle Number");
250 ShellStatus = SHELL_INVALID_PARAMETER;
251 } else {
252 //
253 // Get the DevicePath from the loaded image information.
254 //
255 Status = GetDevicePathForDriverHandleInstall1(CurHandle, &FilePath);
256 }
257 }
258 }
259 } else {
260 //
261 // Get file info
262 //
263 ShellOpenFileMetaArg ((CHAR16*)File, EFI_FILE_MODE_READ, &FileList);
264
265 if (FileList == NULL) {
266 //
267 // If filename matched nothing fail
268 //
269 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellInstall1HiiHandle, File);
270 ShellStatus = SHELL_INVALID_PARAMETER;
271 } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {
272 //
273 // If filename expanded to multiple names, fail
274 //
275 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellInstall1HiiHandle, File);
276 ShellStatus = SHELL_INVALID_PARAMETER;
277 } else {
278 Arg = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link);
279 if (EFI_ERROR(Arg->Status)) {
280 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellInstall1HiiHandle, File, Arg->Status);
281 ShellStatus = SHELL_INVALID_PARAMETER;
282 } else {
283 //
284 // Build FilePath to the filename
285 //
286
287 //
288 // get the device path
289 //
290 DevicePath = mEfiShellProtocol->GetDevicePathFromFilePath(Arg->FullName);
291 if (DevicePath == NULL) {
292 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellInstall1HiiHandle, Arg->FullName);
293 ShellStatus = SHELL_UNSUPPORTED;
294 } else {
295 /*
296 if (UsePath) {
297 DevPath = DevicePath;
298 while (!IsDevicePathEnd(DevPath)) {
299 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
300 (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
301
302 //
303 // If we find it use it instead
304 //
305 DevicePath = DevPath;
306 break;
307 }
308 DevPath = NextDevicePathNode(DevPath);
309 }
310 //
311 // append the file
312 //
313 for(StringWalker=Arg->FullName; *StringWalker != CHAR_NULL && *StringWalker != ':'; StringWalker++);
314 FileNode = FileDevicePath(NULL, StringWalker+1);
315 FilePath = AppendDevicePath(DevicePath, FileNode);
316 FreePool(FileNode);
317 } else {
318 */
319 FilePath = DuplicateDevicePath(DevicePath);
320 /*
321 }
322 */
323 FreePool(DevicePath);
324 }
325 }
326 }
327 }
328
329
330 if (ShellStatus == SHELL_SUCCESS) {
331 //
332 // Find a free target ,a brute force implementation
333 //
334 Found = FALSE;
335 for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) {
336 Found = TRUE;
337 for (Index=0; Index < OrderCount; Index++) {
338 if (CurrentOrder[Index] == TargetLocation) {
339 Found = FALSE;
340 break;
341 }
342 }
343
344 if (Found) {
345 break;
346 }
347 }
348
349 if (TargetLocation == 0xFFFF) {
350 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellInstall1HiiHandle);
351 } else {
352 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellInstall1HiiHandle, TargetLocation);
353 }
354 }
355
356 if (ShellStatus == SHELL_SUCCESS) {
357 //
358 // Add the option
359 //
360 DescSize = StrSize(Desc);
361 FilePathSize = GetDevicePathSize (FilePath);
362
363 TempByteBuffer = AllocateZeroPool(sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize);
364 if (TempByteBuffer != NULL) {
365 TempByteStart = TempByteBuffer;
366 *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes
367 TempByteBuffer += sizeof (UINT32);
368
369 *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength
370 TempByteBuffer += sizeof (UINT16);
371
372 CopyMem (TempByteBuffer, Desc, DescSize);
373 TempByteBuffer += DescSize;
374 CopyMem (TempByteBuffer, FilePath, FilePathSize);
375
376 UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", TargetLocation);
377 Status = gRT->SetVariable (
378 OptionStr,
379 &gEfiGlobalVariableGuid,
380 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
381 sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize,
382 TempByteStart
383 );
384
385 FreePool(TempByteStart);
386 } else {
387 Status = EFI_OUT_OF_RESOURCES;
388 }
389
390 if (EFI_ERROR(Status)) {
391 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellInstall1HiiHandle, OptionStr, Status);
392 } else {
393 NewOrder = AllocateZeroPool((OrderCount+1)*sizeof(NewOrder[0]));
394 ASSERT(NewOrder != NULL);
395 CopyMem(NewOrder, CurrentOrder, (OrderCount)*sizeof(NewOrder[0]));
396
397 //
398 // Insert target into order list
399 //
400 for (Index=OrderCount; Index > Position; Index--) {
401 NewOrder[Index] = NewOrder[Index-1];
402 }
403
404 NewOrder[Position] = (UINT16) TargetLocation;
405 Status = gRT->SetVariable (
406 Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder",
407 &gEfiGlobalVariableGuid,
408 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
409 (OrderCount+1) * sizeof(UINT16),
410 NewOrder
411 );
412
413 FreePool(NewOrder);
414
415 if (EFI_ERROR(Status)) {
416 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellInstall1HiiHandle, Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder", Status);
417 ShellStatus = SHELL_INVALID_PARAMETER;
418 } else {
419 Print (L"bcfg: Add %s as %x\n", OptionStr, Position);
420 }
421 }
422 }
423
424 //
425 //If always Free FilePath, will free devicepath in system when use "addh"
426 //
427 if (FilePath!=NULL && !UseHandle) {
428 FreePool (FilePath);
429 }
430
431 if (Str != NULL) {
432 FreePool(Str);
433 }
434
435 if (Handles != NULL) {
436 FreePool (Handles);
437 }
438
439 if (FileList != NULL) {
440 ShellCloseFileMetaArg (&FileList);
441 }
442
443 return (ShellStatus);
444 }
445
446 /**
447 Funciton to remove an item.
448
449 @param[in] Target The target item to move.
450 @param[in] CurrentOrder The pointer to the current order of items.
451 @param[in] OrderCount The number if items in CurrentOrder.
452 @param[in] Location The current location of the Target.
453
454 @retval SHELL_SUCCESS The operation was successful.
455 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
456 **/
457 SHELL_STATUS
458 EFIAPI
459 BcfgRemoveInstall1(
460 IN CONST BCFG_OPERATION_TARGET Target,
461 IN CONST UINT16 *CurrentOrder,
462 IN CONST UINTN OrderCount,
463 IN CONST UINT16 Location
464 )
465 {
466 CHAR16 VariableName[12];
467 UINT16 *NewOrder;
468 EFI_STATUS Status;
469 UINTN NewCount;
470
471 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", CurrentOrder[Location]);
472 Status = gRT->SetVariable(
473 VariableName,
474 (EFI_GUID*)&gEfiGlobalVariableGuid,
475 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
476 0,
477 NULL);
478 if (EFI_ERROR(Status)) {
479 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellInstall1HiiHandle, VariableName, Status);
480 return (SHELL_INVALID_PARAMETER);
481 }
482 NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0]));
483 if (NewOrder != NULL) {
484 NewCount = OrderCount;
485 CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0]));
486 CopyMem(NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof(CurrentOrder[0]));
487 NewCount--;
488
489 Status = gRT->SetVariable(
490 Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
491 (EFI_GUID*)&gEfiGlobalVariableGuid,
492 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
493 NewCount*sizeof(NewOrder[0]),
494 NewOrder);
495 FreePool(NewOrder);
496 } else {
497 Status = EFI_OUT_OF_RESOURCES;
498 }
499 if (EFI_ERROR(Status)) {
500 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellInstall1HiiHandle, Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status);
501 return (SHELL_INVALID_PARAMETER);
502 }
503 return (SHELL_SUCCESS);
504 }
505
506 /**
507 Funciton to move a item to another location.
508
509 @param[in] Target The target item to move.
510 @param[in] CurrentOrder The pointer to the current order of items.
511 @param[in] OrderCount The number if items in CurrentOrder.
512 @param[in] OldLocation The current location of the Target.
513 @param[in] NewLocation The desired location of the Target.
514
515 @retval SHELL_SUCCESS The operation was successful.
516 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
517 **/
518 SHELL_STATUS
519 EFIAPI
520 BcfgMoveInstall1(
521 IN CONST BCFG_OPERATION_TARGET Target,
522 IN CONST UINT16 *CurrentOrder,
523 IN CONST UINTN OrderCount,
524 IN CONST UINT16 OldLocation,
525 IN CONST UINT16 NewLocation
526 )
527 {
528 UINT16 *NewOrder;
529 EFI_STATUS Status;
530 UINT16 Temp;
531
532 NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0]));
533 ASSERT(NewOrder != NULL);
534
535 Temp = CurrentOrder[OldLocation];
536 CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0]));
537 CopyMem(NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof(CurrentOrder[0]));
538 CopyMem(NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof(CurrentOrder[0]));
539 NewOrder[NewLocation] = Temp;
540
541
542 Status = gRT->SetVariable(
543 Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
544 (EFI_GUID*)&gEfiGlobalVariableGuid,
545 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
546 OrderCount*sizeof(CurrentOrder[0]),
547 NewOrder);
548
549 FreePool(NewOrder);
550
551 if (EFI_ERROR(Status)) {
552 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellInstall1HiiHandle, Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status);
553 return (SHELL_INVALID_PARAMETER);
554 }
555 return (SHELL_SUCCESS);
556 }
557
558 /**
559 Function to add optional data to an option.
560
561 @param[in] OptData The optional data to add.
562 @param[in] Target The target of the operation.
563
564 @retval SHELL_SUCCESS The operation was succesful.
565 **/
566 SHELL_STATUS
567 EFIAPI
568 BcfgAddOptInstall1(
569 IN CONST CHAR16 *OptData,
570 IN CONST BCFG_OPERATION_TARGET Target
571 )
572 {
573 ASSERT(OptData != NULL);
574 return SHELL_SUCCESS;
575 }
576
577 /**
578 Function to dump the Bcfg information.
579
580 @param[in] Op The operation.
581 @param[in] OrderCount How many to dump.
582 @param[in] CurrentOrder The pointer to the current order of items.
583 @param[in] VerboseOutput TRUE for extra output. FALSE otherwise.
584
585 @retval SHELL_SUCCESS The dump was successful.
586 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
587 **/
588 SHELL_STATUS
589 EFIAPI
590 BcfgDisplayDumpInstall1(
591 IN CONST CHAR16 *Op,
592 IN CONST UINTN OrderCount,
593 IN CONST UINT16 *CurrentOrder,
594 IN CONST BOOLEAN VerboseOutput
595 )
596 {
597 EFI_STATUS Status;
598 UINT8 *Buffer;
599 UINTN BufferSize;
600 CHAR16 VariableName[12];
601 UINTN LoopVar;
602 UINTN LoopVar2;
603 CHAR16 *DevPathString;
604 VOID *DevPath;
605
606 if (OrderCount == 0) {
607 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_BCFG_NONE), gShellInstall1HiiHandle);
608 return (SHELL_SUCCESS);
609 }
610
611 for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++) {
612 Buffer = NULL;
613 BufferSize = 0;
614 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]);
615
616 Status = gRT->GetVariable(
617 VariableName,
618 (EFI_GUID*)&gEfiGlobalVariableGuid,
619 NULL,
620 &BufferSize,
621 Buffer);
622 if (Status == EFI_BUFFER_TOO_SMALL) {
623 Buffer = AllocateZeroPool(BufferSize);
624 Status = gRT->GetVariable(
625 VariableName,
626 (EFI_GUID*)&gEfiGlobalVariableGuid,
627 NULL,
628 &BufferSize,
629 Buffer);
630 }
631
632 if (EFI_ERROR(Status) || Buffer == NULL) {
633 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellInstall1HiiHandle, VariableName, Status);
634 return (SHELL_INVALID_PARAMETER);
635 }
636
637 if ((*(UINT16*)(Buffer+4)) != 0) {
638 DevPath = AllocateZeroPool(*(UINT16*)(Buffer+4));
639 CopyMem(DevPath, Buffer+6+StrSize((CHAR16*)(Buffer+6)), *(UINT16*)(Buffer+4));
640 DevPathString = gDevPathToText->ConvertDevicePathToText(DevPath, TRUE, FALSE);
641 } else {
642 DevPath = NULL;
643 DevPathString = NULL;
644 }
645 ShellPrintHiiEx(
646 -1,
647 -1,
648 NULL,
649 STRING_TOKEN(STR_BCFG_LOAD_OPTIONS),
650 gShellInstall1HiiHandle,
651 LoopVar,
652 VariableName,
653 (CHAR16*)(Buffer+6),
654 DevPathString,
655 (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6) <= BufferSize?L'N':L'Y');
656 if (VerboseOutput) {
657 for (LoopVar2 = (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6);LoopVar2<BufferSize;LoopVar2++){
658 ShellPrintEx(
659 -1,
660 -1,
661 NULL,
662 L"%02x",
663 Buffer[LoopVar2]);
664 }
665 ShellPrintEx(
666 -1,
667 -1,
668 NULL,
669 L"\r\n");
670 }
671
672 if (Buffer != NULL) {
673 FreePool(Buffer);
674 }
675 if (DevPath != NULL) {
676 FreePool(DevPath);
677 }
678 if (DevPathString != NULL) {
679 FreePool(DevPathString);
680 }
681 }
682 return (SHELL_SUCCESS);
683 }
684
685 /**
686 Function to initialize the BCFG operation structure.
687
688 @param[in] Struct The stuct to initialize.
689 **/
690 VOID
691 EFIAPI
692 InitBcfgStructInstall1(
693 IN BGFG_OPERATION *Struct
694 )
695 {
696 ASSERT(Struct != NULL);
697 Struct->Target = BcfgTargetMax;
698 Struct->Type = BcfgTypeMax;
699 Struct->Number1 = 0;
700 Struct->Number2 = 0;
701 Struct->HandleIndex = 0;
702 Struct->FileName = NULL;
703 Struct->Description = NULL;
704 Struct->Order = NULL;
705 Struct->OptData = NULL;
706 }
707
708
709 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
710 {L"-v", TypeFlag},
711 {L"-opt", TypeMaxValue},
712 {NULL, TypeMax}
713 };
714
715 /**
716 Function for 'bcfg' command.
717
718 @param[in] ImageHandle Handle to the Image (NULL if Internal).
719 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
720 **/
721 SHELL_STATUS
722 EFIAPI
723 ShellCommandRunBcfgInstall (
724 IN EFI_HANDLE ImageHandle,
725 IN EFI_SYSTEM_TABLE *SystemTable
726 )
727 {
728 EFI_STATUS Status;
729 LIST_ENTRY *Package;
730 CHAR16 *ProblemParam;
731 SHELL_STATUS ShellStatus;
732 UINTN ParamNumber;
733 CONST CHAR16 *CurrentParam;
734 BGFG_OPERATION CurrentOperation;
735 UINTN Length;
736 UINT64 Intermediate;
737
738 Length = 0;
739 ProblemParam = NULL;
740 Package = NULL;
741 ShellStatus = SHELL_SUCCESS;
742
743 InitBcfgStructInstall1(&CurrentOperation);
744
745 //
746 // initialize the shell lib (we must be in non-auto-init...)
747 //
748 Status = ShellInitialize();
749 ASSERT_EFI_ERROR(Status);
750
751 Status = CommandInit();
752 ASSERT_EFI_ERROR(Status);
753
754 //
755 // parse the command line
756 //
757 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
758 if (EFI_ERROR(Status)) {
759 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
760 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, ProblemParam);
761 FreePool(ProblemParam);
762 ShellStatus = SHELL_INVALID_PARAMETER;
763 } else {
764 ASSERT(FALSE);
765 }
766 } else {
767 //
768 // Read in if we are doing -OPT
769 //
770 if (ShellCommandLineGetFlag(Package, L"-opt")) {
771 CurrentOperation.OptData = ShellCommandLineGetValue(Package, L"-opt");
772 if (CurrentOperation.OptData == NULL) {
773 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellInstall1HiiHandle, L"-opt");
774 ShellStatus = SHELL_INVALID_PARAMETER;
775 }
776 CurrentOperation.Type = BcfgTypeOpt;
777 }
778
779 //
780 // small block to read the target of the operation
781 //
782 if ((ShellCommandLineGetCount(Package) < 3 && CurrentOperation.Type != BcfgTypeOpt) ||
783 (ShellCommandLineGetCount(Package) < 2 && CurrentOperation.Type == BcfgTypeOpt)
784 ){
785 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle);
786 ShellStatus = SHELL_INVALID_PARAMETER;
787 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"driver") == 0) {
788 CurrentOperation.Target = BcfgTargetDriverOrder;
789 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"boot") == 0) {
790 CurrentOperation.Target = BcfgTargetBootOrder;
791 } else {
792 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellInstall1HiiHandle);
793 ShellStatus = SHELL_INVALID_PARAMETER;
794 }
795
796
797 //
798 // Read in the boot or driver order environment variable (not needed for opt)
799 //
800 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type != BcfgTypeOpt) {
801 Length = 0;
802 Status = gRT->GetVariable(
803 CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
804 (EFI_GUID*)&gEfiGlobalVariableGuid,
805 NULL,
806 &Length,
807 CurrentOperation.Order);
808 if (Status == EFI_BUFFER_TOO_SMALL) {
809 CurrentOperation.Order = AllocateZeroPool(Length+(4*sizeof(CurrentOperation.Order[0])));
810 Status = gRT->GetVariable(
811 CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
812 (EFI_GUID*)&gEfiGlobalVariableGuid,
813 NULL,
814 &Length,
815 CurrentOperation.Order);
816 }
817 }
818
819 //
820 // large block to read the type of operation and verify parameter types for the info.
821 //
822 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {
823 for (ParamNumber = 2 ; ParamNumber < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) {
824 CurrentParam = ShellCommandLineGetRawValue(Package, ParamNumber);
825 if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"dump") == 0) {
826 CurrentOperation.Type = BcfgTypeDump;
827 } else if (ShellCommandLineGetFlag(Package, L"-v")) {
828 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, L"-v (without dump)");
829 ShellStatus = SHELL_INVALID_PARAMETER;
830 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"add") == 0) {
831 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
832 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle);
833 ShellStatus = SHELL_INVALID_PARAMETER;
834 }
835 CurrentOperation.Type = BcfgTypeAdd;
836 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
837 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
838 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam);
839 ShellStatus = SHELL_INVALID_PARAMETER;
840 } else {
841 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
842 CurrentOperation.Number1 = (UINT16)Intermediate;
843 ASSERT(CurrentOperation.FileName == NULL);
844 CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
845 ASSERT(CurrentOperation.Description == NULL);
846 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
847 }
848 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addp") == 0) {
849 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
850 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle);
851 ShellStatus = SHELL_INVALID_PARAMETER;
852 }
853 CurrentOperation.Type = BcfgTypeAddp;
854 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
855 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
856 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam);
857 ShellStatus = SHELL_INVALID_PARAMETER;
858 } else {
859 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
860 CurrentOperation.Number1 = (UINT16)Intermediate;
861 ASSERT(CurrentOperation.FileName == NULL);
862 CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
863 ASSERT(CurrentOperation.Description == NULL);
864 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
865 }
866 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addh") == 0) {
867 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
868 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle);
869 ShellStatus = SHELL_INVALID_PARAMETER;
870 }
871 CurrentOperation.Type = BcfgTypeAddh;
872 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
873 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
874 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam);
875 ShellStatus = SHELL_INVALID_PARAMETER;
876 } else {
877 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
878 CurrentOperation.Number1 = (UINT16)Intermediate;
879 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
880 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
881 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam);
882 ShellStatus = SHELL_INVALID_PARAMETER;
883 } else {
884 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
885 CurrentOperation.HandleIndex = (UINT16)Intermediate;
886 ASSERT(CurrentOperation.Description == NULL);
887 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
888 }
889 }
890 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"rm") == 0) {
891 if ((ParamNumber + 1) >= ShellCommandLineGetCount(Package)) {
892 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle);
893 ShellStatus = SHELL_INVALID_PARAMETER;
894 }
895 CurrentOperation.Type = BcfgTypeRm;
896 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
897 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
898 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam);
899 ShellStatus = SHELL_INVALID_PARAMETER;
900 } else {
901 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
902 CurrentOperation.Number1 = (UINT16)Intermediate;
903 if (CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))){
904 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellInstall1HiiHandle, Length / sizeof(CurrentOperation.Order[0]));
905 ShellStatus = SHELL_INVALID_PARAMETER;
906 }
907 }
908 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"mv") == 0) {
909 if ((ParamNumber + 2) >= ShellCommandLineGetCount(Package)) {
910 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellInstall1HiiHandle);
911 ShellStatus = SHELL_INVALID_PARAMETER;
912 }
913 CurrentOperation.Type = BcfgTypeMv;
914 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
915 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
916 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam);
917 ShellStatus = SHELL_INVALID_PARAMETER;
918 } else {
919 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
920 CurrentOperation.Number1 = (UINT16)Intermediate;
921 if (CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))){
922 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellInstall1HiiHandle, Length / sizeof(CurrentOperation.Order[0]));
923 ShellStatus = SHELL_INVALID_PARAMETER;
924 }
925 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
926 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
927 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam);
928 ShellStatus = SHELL_INVALID_PARAMETER;
929 } else {
930 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
931 CurrentOperation.Number2 = (UINT16)Intermediate;
932 }
933 if (CurrentOperation.Number2 == CurrentOperation.Number1
934 ||CurrentOperation.Number1 > (Length / sizeof(CurrentOperation.Order[0]))
935 ||CurrentOperation.Number2 > (Length / sizeof(CurrentOperation.Order[0]))
936 ){
937 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellInstall1HiiHandle, Length / sizeof(CurrentOperation.Order[0]));
938 ShellStatus = SHELL_INVALID_PARAMETER;
939 }
940 }
941 } else {
942 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellInstall1HiiHandle, CurrentParam);
943 ShellStatus = SHELL_INVALID_PARAMETER;
944 }
945 }
946 }
947 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type < BcfgTypeMax) {
948 //
949 // we have all the info. Do the work
950 //
951 switch (CurrentOperation.Type) {
952 case BcfgTypeDump:
953 ShellStatus = BcfgDisplayDumpInstall1(
954 CurrentOperation.Target == BcfgTargetBootOrder?L"Boot":L"Driver",
955 Length / sizeof(CurrentOperation.Order[0]),
956 CurrentOperation.Order,
957 ShellCommandLineGetFlag(Package, L"-v"));
958 break;
959 case BcfgTypeMv:
960 ShellStatus = BcfgMoveInstall1(
961 CurrentOperation.Target,
962 CurrentOperation.Order,
963 Length / sizeof(CurrentOperation.Order[0]),
964 CurrentOperation.Number1,
965 CurrentOperation.Number2);
966 break;
967 case BcfgTypeRm:
968 ShellStatus = BcfgRemoveInstall1(
969 CurrentOperation.Target,
970 CurrentOperation.Order,
971 Length / sizeof(CurrentOperation.Order[0]),
972 CurrentOperation.Number1);
973 break;
974 case BcfgTypeAdd:
975 case BcfgTypeAddp:
976 case BcfgTypeAddh:
977 ShellStatus = BcfgAddInstall1(
978 CurrentOperation.Number1,
979 CurrentOperation.FileName,
980 CurrentOperation.Description,
981 CurrentOperation.Order,
982 Length / sizeof(CurrentOperation.Order[0]),
983 CurrentOperation.Target,
984 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh),
985 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp),
986 CurrentOperation.HandleIndex);
987 break;
988 case BcfgTypeOpt:
989 ShellStatus = BcfgAddOptInstall1(
990 CurrentOperation.OptData,
991 CurrentOperation.Target);
992 break;
993 default:
994 ASSERT(FALSE);
995 }
996 }
997 }
998
999 if (Package != NULL) {
1000 ShellCommandLineFreeVarList (Package);
1001 }
1002 if (CurrentOperation.FileName != NULL) {
1003 FreePool(CurrentOperation.FileName);
1004 }
1005 if (CurrentOperation.Description != NULL) {
1006 FreePool(CurrentOperation.Description);
1007 }
1008 if (CurrentOperation.Order != NULL) {
1009 FreePool(CurrentOperation.Order);
1010 }
1011
1012 return (ShellStatus);
1013 }