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