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