]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c
ShellPkg: Fix misuses of AllocateCopyPool
[mirror_edk2.git] / ShellPkg / Library / UefiShellBcfgCommandLib / UefiShellBcfgCommandLib.c
1 /** @file
2 Main file for BCFG command.
3
4 (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include <Uefi.h>
18
19 #include <Guid/GlobalVariable.h>
20 #include <Guid/ShellLibHiiGuid.h>
21
22 #include <Protocol/Shell.h>
23 #include <Protocol/ShellParameters.h>
24 #include <Protocol/DevicePath.h>
25 #include <Protocol/LoadedImage.h>
26 #include <Protocol/UnicodeCollation.h>
27
28 #include <Library/BaseLib.h>
29 #include <Library/BaseMemoryLib.h>
30 #include <Library/DebugLib.h>
31 #include <Library/MemoryAllocationLib.h>
32 #include <Library/PcdLib.h>
33 #include <Library/ShellCommandLib.h>
34 #include <Library/ShellLib.h>
35 #include <Library/SortLib.h>
36 #include <Library/UefiLib.h>
37 #include <Library/UefiRuntimeServicesTableLib.h>
38 #include <Library/UefiBootServicesTableLib.h>
39 #include <Library/HiiLib.h>
40 #include <Library/FileHandleLib.h>
41 #include <Library/PrintLib.h>
42 #include <Library/HandleParsingLib.h>
43 #include <Library/DevicePathLib.h>
44 #include <Library/UefiBootManagerLib.h>
45
46 STATIC CONST CHAR16 mFileName[] = L"ShellCommands";
47 STATIC EFI_HANDLE gShellBcfgHiiHandle = NULL;
48
49 typedef enum {
50 BcfgTargetBootOrder = 0,
51 BcfgTargetDriverOrder = 1,
52 BcfgTargetMax = 2
53 } BCFG_OPERATION_TARGET;
54
55 typedef enum {
56 BcfgTypeDump = 0,
57 BcfgTypeAdd = 1,
58 BcfgTypeAddp = 2,
59 BcfgTypeAddh = 3,
60 BcfgTypeRm = 4,
61 BcfgTypeMv = 5,
62 BcfgTypeOpt = 6,
63 BcfgTypeMod = 7,
64 BcfgTypeModf = 8,
65 BcfgTypeModp = 9,
66 BcfgTypeModh = 10,
67 BcfgTypeMax = 11
68 } BCFG_OPERATION_TYPE;
69
70 typedef struct {
71 BCFG_OPERATION_TARGET Target;
72 BCFG_OPERATION_TYPE Type;
73 UINT16 Number1;
74 UINT16 Number2;
75 UINTN HandleIndex;
76 CHAR16 *FileName;
77 CHAR16 *Description;
78 UINT16 *Order;
79 CONST CHAR16 *OptData;
80 } BGFG_OPERATION;
81
82 /**
83 Update the optional data for a boot or driver option.
84
85 If optional data exists it will be changed.
86
87 @param[in] Index The boot or driver option index update.
88 @param[in] DataSize The size in bytes of Data.
89 @param[in] Data The buffer for the optioanl data.
90 @param[in] Target The target of the operation.
91
92 @retval EFI_SUCCESS The data was sucessfully updated.
93 @retval other A error occured.
94 **/
95 EFI_STATUS
96 UpdateOptionalData(
97 UINT16 Index,
98 UINTN DataSize,
99 UINT8 *Data,
100 IN CONST BCFG_OPERATION_TARGET Target
101 )
102 {
103 EFI_STATUS Status;
104 CHAR16 VariableName[12];
105 UINTN OriginalSize;
106 UINT8 *OriginalData;
107 UINTN NewSize;
108 UINT8 *NewData;
109 UINTN OriginalOptionDataSize;
110
111 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", Index);
112
113 OriginalSize = 0;
114 OriginalData = NULL;
115 NewData = NULL;
116 NewSize = 0;
117
118 Status = gRT->GetVariable(
119 VariableName,
120 (EFI_GUID*)&gEfiGlobalVariableGuid,
121 NULL,
122 &OriginalSize,
123 OriginalData);
124 if (Status == EFI_BUFFER_TOO_SMALL) {
125 OriginalData = AllocateZeroPool(OriginalSize);
126 if (OriginalData == NULL) {
127 return (EFI_OUT_OF_RESOURCES);
128 }
129 Status = gRT->GetVariable(
130 VariableName,
131 (EFI_GUID*)&gEfiGlobalVariableGuid,
132 NULL,
133 &OriginalSize,
134 OriginalData);
135 }
136
137 if (!EFI_ERROR(Status)) {
138 //
139 // Allocate new struct and discard old optional data.
140 //
141 ASSERT (OriginalData != NULL);
142 OriginalOptionDataSize = sizeof(UINT32) + sizeof(UINT16) + StrSize(((CHAR16*)(OriginalData + sizeof(UINT32) + sizeof(UINT16))));
143 OriginalOptionDataSize += (*(UINT16*)(OriginalData + sizeof(UINT32)));
144 OriginalOptionDataSize -= OriginalSize;
145 NewSize = OriginalSize - OriginalOptionDataSize + DataSize;
146 NewData = AllocatePool(NewSize);
147 if (NewData == NULL) {
148 Status = EFI_OUT_OF_RESOURCES;
149 } else {
150 CopyMem (NewData, OriginalData, OriginalSize - OriginalOptionDataSize);
151 CopyMem(NewData + OriginalSize - OriginalOptionDataSize, Data, DataSize);
152 }
153 }
154
155 if (!EFI_ERROR(Status)) {
156 //
157 // put the data back under the variable
158 //
159 Status = gRT->SetVariable(
160 VariableName,
161 (EFI_GUID*)&gEfiGlobalVariableGuid,
162 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
163 NewSize,
164 NewData);
165 }
166
167 SHELL_FREE_NON_NULL(OriginalData);
168 SHELL_FREE_NON_NULL(NewData);
169 return (Status);
170 }
171
172 /**
173 This function will get a CRC for a boot option.
174
175 @param[in, out] Crc The CRC value to return.
176 @param[in] BootIndex The boot option index to CRC.
177
178 @retval EFI_SUCCESS The CRC was sucessfully returned.
179 @retval other A error occured.
180 **/
181 EFI_STATUS
182 GetBootOptionCrc(
183 UINT32 *Crc,
184 UINT16 BootIndex
185 )
186 {
187 CHAR16 VariableName[12];
188 EFI_STATUS Status;
189 UINT8 *Buffer;
190 UINTN BufferSize;
191
192 Buffer = NULL;
193 BufferSize = 0;
194
195 //
196 // Get the data Buffer
197 //
198 UnicodeSPrint(VariableName, sizeof(VariableName), L"%Boot%04x", BootIndex);
199 Status = gRT->GetVariable(
200 VariableName,
201 (EFI_GUID*)&gEfiGlobalVariableGuid,
202 NULL,
203 &BufferSize,
204 NULL);
205 if (Status == EFI_BUFFER_TOO_SMALL) {
206 Buffer = AllocateZeroPool(BufferSize);
207 Status = gRT->GetVariable(
208 VariableName,
209 (EFI_GUID*)&gEfiGlobalVariableGuid,
210 NULL,
211 &BufferSize,
212 Buffer);
213 }
214
215 //
216 // Get the CRC computed
217 //
218 if (!EFI_ERROR(Status)) {
219 Status = gBS->CalculateCrc32 (Buffer, BufferSize, Crc);
220 }
221
222 SHELL_FREE_NON_NULL(Buffer);
223 return EFI_SUCCESS;
224 }
225
226 /**
227 This function will populate the device path protocol parameter based on TheHandle.
228
229 @param[in] TheHandle Driver handle.
230 @param[in, out] FilePath On a sucessful return the device path to the handle.
231
232 @retval EFI_SUCCESS The device path was sucessfully returned.
233 @retval other A error from gBS->HandleProtocol.
234
235 @sa HandleProtocol
236 **/
237 EFI_STATUS
238 GetDevicePathForDriverHandle (
239 IN EFI_HANDLE TheHandle,
240 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
241 )
242 {
243 EFI_STATUS Status;
244 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
245 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
246
247 Status = gBS->OpenProtocol (
248 TheHandle,
249 &gEfiLoadedImageProtocolGuid,
250 (VOID**)&LoadedImage,
251 gImageHandle,
252 NULL,
253 EFI_OPEN_PROTOCOL_GET_PROTOCOL
254 );
255 if (!EFI_ERROR (Status)) {
256 Status = gBS->OpenProtocol (
257 LoadedImage->DeviceHandle,
258 &gEfiDevicePathProtocolGuid,
259 (VOID**)&ImageDevicePath,
260 gImageHandle,
261 NULL,
262 EFI_OPEN_PROTOCOL_GET_PROTOCOL
263 );
264 if (!EFI_ERROR (Status)) {
265 // *DevPath = DuplicateDevicePath (ImageDevicePath);
266 // *FilePath = DuplicateDevicePath (LoadedImage->FilePath);
267 *FilePath = AppendDevicePath(ImageDevicePath,LoadedImage->FilePath);
268 gBS->CloseProtocol(
269 LoadedImage->DeviceHandle,
270 &gEfiDevicePathProtocolGuid,
271 gImageHandle,
272 NULL);
273 }
274 gBS->CloseProtocol(
275 TheHandle,
276 &gEfiLoadedImageProtocolGuid,
277 gImageHandle,
278 NULL);
279 }
280 return (Status);
281 }
282
283 /**
284 Functino to get Device Path by a handle.
285
286 @param[in] TheHandle Use it to get DevicePath.
287 @param[in] Target Boot option target.
288 @param[in, out] DevicePath On a sucessful return the device path to the handle.
289
290 @retval SHELL_INVALID_PARAMETER The handle was NULL.
291 @retval SHELL_NOT_FOUND Not found device path by handle.
292 @retval SHELL_SUCCESS Get device path successfully.
293 **/
294 SHELL_STATUS
295 GetDevicePathByHandle(
296 IN EFI_HANDLE TheHandle,
297 IN BCFG_OPERATION_TARGET Target,
298 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
299 )
300 {
301 EFI_STATUS Status;
302 SHELL_STATUS ShellStatus;
303
304 UINTN DriverBindingHandleCount;
305 UINTN ParentControllerHandleCount;
306 UINTN ChildControllerHandleCount;
307
308 ShellStatus = SHELL_SUCCESS;
309
310 if (TheHandle == NULL) {
311 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
312 return SHELL_INVALID_PARAMETER;
313 }
314
315 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (TheHandle, &DriverBindingHandleCount, NULL);
316 if (EFI_ERROR(Status)) {
317 DriverBindingHandleCount = 0;
318 }
319
320 Status = PARSE_HANDLE_DATABASE_PARENTS (TheHandle, &ParentControllerHandleCount, NULL);
321 if (EFI_ERROR (Status)) {
322 ParentControllerHandleCount = 0;
323 }
324
325 Status = ParseHandleDatabaseForChildControllers (TheHandle, &ChildControllerHandleCount, NULL);
326 if (EFI_ERROR (Status)) {
327 ChildControllerHandleCount = 0;
328 }
329
330 Status = gBS->HandleProtocol (TheHandle, &gEfiDevicePathProtocolGuid, (VOID**)DevicePath);
331
332 if ( DriverBindingHandleCount > 0 ||
333 ParentControllerHandleCount > 0 ||
334 ChildControllerHandleCount > 0 ||
335 !EFI_ERROR(Status)
336 ) {
337 //
338 // The handle points to a real controller which has a device path.
339 //
340 if (Target == BcfgTargetDriverOrder) {
341 ShellPrintHiiEx (
342 -1,
343 -1,
344 NULL,STRING_TOKEN (STR_GEN_PARAM_INV),
345 gShellBcfgHiiHandle,
346 L"bcfg",
347 L"Handle should point to driver image."
348 );
349 ShellStatus = SHELL_NOT_FOUND;
350 }
351 } else {
352 //
353 // The handle points to a driver image.
354 //
355 if (Target == BcfgTargetBootOrder) {
356 ShellPrintHiiEx (
357 -1,
358 -1,
359 NULL,
360 STRING_TOKEN (STR_GEN_PARAM_INV),
361 gShellBcfgHiiHandle,
362 L"bcfg",
363 L"Handle should point to controller."
364 );
365 ShellStatus = SHELL_NOT_FOUND;
366 } else {
367 if (EFI_ERROR (GetDevicePathForDriverHandle (TheHandle, DevicePath))) {
368 ShellStatus = SHELL_NOT_FOUND;
369 }
370 }
371 }
372
373 return (ShellStatus);
374 }
375
376 /**
377 Function to modify an option.
378
379 @param[in] BcfgOperation Pointer to BCFG operation.
380 @param[in] OrderCount The number if items in CurrentOrder.
381
382 @retval SHELL_SUCCESS The operation was successful.
383 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
384 @retval SHELL_OUT_OF_RESOUCES A memory allocation failed.
385 **/
386 SHELL_STATUS
387 BcfgMod (
388 IN CONST BGFG_OPERATION *BcfgOperation,
389 IN CONST UINTN OrderCount
390 )
391 {
392 EFI_STATUS Status;
393 EFI_HANDLE CurHandle;
394 SHELL_STATUS ShellStatus;
395 CHAR16 OptionStr[40];
396 EFI_SHELL_FILE_INFO *FileList;
397 EFI_SHELL_FILE_INFO *Arg;
398 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
399 EFI_DEVICE_PATH_PROTOCOL *DevicePathBuffer;
400 EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker;
401 EFI_BOOT_MANAGER_LOAD_OPTION LoadOption;
402
403 ShellStatus = SHELL_SUCCESS;
404 FileList = NULL;
405 DevicePath = NULL;
406 DevicePathBuffer = NULL;
407
408 ZeroMem (&LoadOption, sizeof(EFI_BOOT_MANAGER_LOAD_OPTION));
409
410 if ( (BcfgOperation->Type == BcfgTypeMod && BcfgOperation->Description == NULL) ||
411 (BcfgOperation->Type == BcfgTypeModf && BcfgOperation->FileName == NULL) ||
412 (BcfgOperation->Type == BcfgTypeModp && BcfgOperation->FileName == NULL) ||
413 (BcfgOperation->Type == BcfgTypeModh && BcfgOperation->HandleIndex == 0) ||
414 (BcfgOperation->Number1 > OrderCount)
415 ) {
416 return (SHELL_INVALID_PARAMETER);
417 }
418
419 if (BcfgOperation->Type == BcfgTypeModh) {
420 CurHandle = ConvertHandleIndexToHandle (BcfgOperation->HandleIndex);
421 ShellStatus = GetDevicePathByHandle (CurHandle, BcfgOperation->Target, &DevicePathBuffer);
422 if (ShellStatus == SHELL_SUCCESS) {
423 DevicePath = DuplicateDevicePath (DevicePathBuffer);
424 }
425 } else if (BcfgOperation->Type == BcfgTypeModf || BcfgOperation->Type == BcfgTypeModp) {
426 //
427 // Get Device Path by FileName.
428 //
429 ShellOpenFileMetaArg ((CHAR16 *)BcfgOperation->FileName, EFI_FILE_MODE_READ, &FileList);
430 if (FileList == NULL) {
431 //
432 // The name of file matched nothing.
433 //
434 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName);
435 ShellStatus = SHELL_INVALID_PARAMETER;
436 }
437 else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {
438 //
439 // If the name of file expanded to multiple names, it's fail.
440 //
441 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName);
442 ShellStatus = SHELL_INVALID_PARAMETER;
443 } else {
444 Arg = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link);
445 if (EFI_ERROR (Arg->Status)) {
446 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName);
447 ShellStatus = SHELL_INVALID_PARAMETER;
448 } else {
449 DevicePathBuffer = gEfiShellProtocol->GetDevicePathFromFilePath (Arg->FullName);
450 if (DevicePathBuffer == NULL) {
451 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName);
452 ShellStatus = SHELL_UNSUPPORTED;
453 }
454 }
455 }
456
457 if (ShellStatus == SHELL_SUCCESS) {
458 if (BcfgOperation->Type == BcfgTypeModp) {
459 ShellStatus = SHELL_INVALID_PARAMETER;
460 DevicePathWalker = DevicePathBuffer;
461 while (!IsDevicePathEnd (DevicePathWalker)) {
462 if ( DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH &&
463 DevicePathSubType (DevicePathWalker) == MEDIA_HARDDRIVE_DP
464 ) {
465 //
466 // We found the portion of device path starting with the hard driver partition.
467 //
468 ShellStatus = SHELL_SUCCESS;
469 DevicePath = DuplicateDevicePath (DevicePathWalker);
470 break;
471 } else {
472 DevicePathWalker = NextDevicePathNode (DevicePathWalker);
473 }
474 }
475 } else {
476 DevicePath = DuplicateDevicePath (DevicePathBuffer);
477 }
478
479 FreePool (DevicePathBuffer);
480 }
481 }
482
483 if (ShellStatus == SHELL_SUCCESS) {
484 if (BcfgOperation->Target == BcfgTargetBootOrder) {
485 UnicodeSPrint (OptionStr, sizeof (OptionStr), L"Boot%04x", BcfgOperation->Order[BcfgOperation->Number1]);
486 } else {
487 UnicodeSPrint (OptionStr, sizeof (OptionStr), L"Driver%04x", BcfgOperation->Order[BcfgOperation->Number1]);
488 }
489 Status = EfiBootManagerVariableToLoadOption (OptionStr, &LoadOption);
490 if (EFI_ERROR(Status)) {
491 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NONE), gShellBcfgHiiHandle);
492 ShellStatus = SHELL_NOT_FOUND;
493 }
494 }
495
496 if (ShellStatus == SHELL_SUCCESS) {
497 if (BcfgOperation->Type == BcfgTypeMod) {
498 SHELL_FREE_NON_NULL (LoadOption.Description);
499 LoadOption.Description = AllocateCopyPool (StrSize (BcfgOperation->Description), BcfgOperation->Description);
500 } else {
501 SHELL_FREE_NON_NULL (LoadOption.FilePath);
502 LoadOption.FilePath = DuplicateDevicePath (DevicePath);
503 }
504
505 Status = EfiBootManagerLoadOptionToVariable (&LoadOption);
506 if (EFI_ERROR(Status)) {
507 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr);
508 ShellStatus = SHELL_INVALID_PARAMETER;
509 }
510 }
511
512 EfiBootManagerFreeLoadOption (&LoadOption);
513
514 if (DevicePath != NULL) {
515 FreePool (DevicePath);
516 }
517
518 if (FileList != NULL) {
519 ShellCloseFileMetaArg (&FileList);
520 }
521
522 return (ShellStatus);
523 }
524
525 /**
526 Function to add a option.
527
528 @param[in] Position The position to add Target at.
529 @param[in] File The file to make the target.
530 @param[in] Desc The description text.
531 @param[in] CurrentOrder The pointer to the current order of items.
532 @param[in] OrderCount The number if items in CurrentOrder.
533 @param[in] Target The info on the option to add.
534 @param[in] UseHandle TRUE to use HandleNumber, FALSE to use File and Desc.
535 @param[in] UsePath TRUE to convert to devicepath.
536 @param[in] HandleNumber The handle number to add.
537
538 @retval SHELL_SUCCESS The operation was successful.
539 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
540 **/
541 SHELL_STATUS
542 BcfgAdd(
543 IN UINTN Position,
544 IN CONST CHAR16 *File,
545 IN CONST CHAR16 *Desc,
546 IN CONST UINT16 *CurrentOrder,
547 IN CONST UINTN OrderCount,
548 IN CONST BCFG_OPERATION_TARGET Target,
549 IN CONST BOOLEAN UseHandle,
550 IN CONST BOOLEAN UsePath,
551 IN CONST UINTN HandleNumber
552 )
553 {
554 EFI_STATUS Status;
555 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
556 EFI_DEVICE_PATH_PROTOCOL *DevPath;
557 EFI_DEVICE_PATH_PROTOCOL *FilePath;
558 CHAR16 *Str;
559 UINT8 *TempByteBuffer;
560 UINT8 *TempByteStart;
561 EFI_SHELL_FILE_INFO *Arg;
562 EFI_SHELL_FILE_INFO *FileList;
563 CHAR16 OptionStr[40];
564 UINTN DescSize, FilePathSize;
565 BOOLEAN Found;
566 UINTN TargetLocation;
567 UINTN Index;
568 EFI_HANDLE *Handles;
569 EFI_HANDLE CurHandle;
570 UINTN DriverBindingHandleCount;
571 UINTN ParentControllerHandleCount;
572 UINTN ChildControllerHandleCount;
573 SHELL_STATUS ShellStatus;
574 UINT16 *NewOrder;
575
576 if (!UseHandle) {
577 if (File == NULL || Desc == NULL) {
578 return (SHELL_INVALID_PARAMETER);
579 }
580 } else {
581 if (HandleNumber == 0) {
582 return (SHELL_INVALID_PARAMETER);
583 }
584 }
585
586 if (Position > OrderCount) {
587 Position = OrderCount;
588 }
589
590 Str = NULL;
591 FilePath = NULL;
592 FileList = NULL;
593 Handles = NULL;
594 ShellStatus = SHELL_SUCCESS;
595 TargetLocation = 0xFFFF;
596
597 if (UseHandle) {
598 CurHandle = ConvertHandleIndexToHandle(HandleNumber);
599 if (CurHandle == NULL) {
600 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
601 ShellStatus = SHELL_INVALID_PARAMETER;
602 } else {
603 if (Target == BcfgTargetBootOrder) {
604 //
605 //Make sure that the handle should point to a real controller
606 //
607 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
608 CurHandle,
609 &DriverBindingHandleCount,
610 NULL);
611
612 Status = PARSE_HANDLE_DATABASE_PARENTS (
613 CurHandle,
614 &ParentControllerHandleCount,
615 NULL);
616
617 Status = ParseHandleDatabaseForChildControllers (
618 CurHandle,
619 &ChildControllerHandleCount,
620 NULL);
621
622 if (DriverBindingHandleCount > 0
623 || ParentControllerHandleCount > 0
624 || ChildControllerHandleCount > 0) {
625 FilePath = NULL;
626 Status = gBS->HandleProtocol (
627 CurHandle,
628 &gEfiDevicePathProtocolGuid,
629 (VOID**)&FilePath);
630 }
631 if (EFI_ERROR (Status)) {
632 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellBcfgHiiHandle, L"bcfg", HandleNumber);
633 ShellStatus = SHELL_INVALID_PARAMETER;
634 }
635 } else {
636 //
637 //Make sure that the handle should point to driver, not a controller.
638 //
639 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
640 CurHandle,
641 &DriverBindingHandleCount,
642 NULL);
643
644 Status = PARSE_HANDLE_DATABASE_PARENTS (
645 CurHandle,
646 &ParentControllerHandleCount,
647 NULL);
648
649 Status = ParseHandleDatabaseForChildControllers (
650 CurHandle,
651 &ChildControllerHandleCount,
652 NULL);
653
654 Status = gBS->HandleProtocol (
655 CurHandle,
656 &gEfiDevicePathProtocolGuid,
657 (VOID**)&FilePath);
658
659 if (DriverBindingHandleCount > 0
660 || ParentControllerHandleCount > 0
661 || ChildControllerHandleCount > 0
662 || !EFI_ERROR(Status) ) {
663 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
664 ShellStatus = SHELL_INVALID_PARAMETER;
665 } else {
666 //
667 // Get the DevicePath from the loaded image information.
668 //
669 Status = GetDevicePathForDriverHandle(CurHandle, &FilePath);
670 }
671 }
672 }
673 } else {
674 //
675 // Get file info
676 //
677 ShellOpenFileMetaArg ((CHAR16*)File, EFI_FILE_MODE_READ, &FileList);
678
679 if (FileList == NULL) {
680 //
681 // If filename matched nothing fail
682 //
683 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", File);
684 ShellStatus = SHELL_INVALID_PARAMETER;
685 } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {
686 //
687 // If filename expanded to multiple names, fail
688 //
689 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", File);
690 ShellStatus = SHELL_INVALID_PARAMETER;
691 } else {
692 Arg = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link);
693 if (EFI_ERROR(Arg->Status)) {
694 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", File);
695 ShellStatus = SHELL_INVALID_PARAMETER;
696 } else {
697 //
698 // Build FilePath to the filename
699 //
700
701 //
702 // get the device path
703 //
704 DevicePath = gEfiShellProtocol->GetDevicePathFromFilePath(Arg->FullName);
705 if (DevicePath == NULL) {
706 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName);
707 ShellStatus = SHELL_UNSUPPORTED;
708 } else {
709 if (UsePath) {
710 DevPath = DevicePath;
711 ShellStatus = SHELL_INVALID_PARAMETER;
712 while (!IsDevicePathEnd(DevPath)) {
713 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
714 (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
715
716 //
717 // If we find it use it instead
718 //
719 ShellStatus = SHELL_SUCCESS;
720 FilePath = DuplicateDevicePath (DevPath);
721 break;
722 }
723 DevPath = NextDevicePathNode(DevPath);
724 }
725 } else {
726 FilePath = DuplicateDevicePath(DevicePath);
727 }
728 FreePool(DevicePath);
729 }
730 }
731 }
732 }
733
734
735 if (ShellStatus == SHELL_SUCCESS) {
736 //
737 // Find a free target ,a brute force implementation
738 //
739 Found = FALSE;
740 for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) {
741 Found = TRUE;
742 for (Index=0; Index < OrderCount; Index++) {
743 if (CurrentOrder[Index] == TargetLocation) {
744 Found = FALSE;
745 break;
746 }
747 }
748
749 if (Found) {
750 break;
751 }
752 }
753
754 if (TargetLocation == 0xFFFF) {
755 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellBcfgHiiHandle, L"bcfg");
756 } else {
757 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellBcfgHiiHandle, TargetLocation);
758 }
759 }
760
761 if (ShellStatus == SHELL_SUCCESS) {
762 //
763 // Add the option
764 //
765 DescSize = StrSize(Desc);
766 FilePathSize = GetDevicePathSize (FilePath);
767
768 TempByteBuffer = AllocateZeroPool(sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize);
769 if (TempByteBuffer != NULL) {
770 TempByteStart = TempByteBuffer;
771 *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes
772 TempByteBuffer += sizeof (UINT32);
773
774 *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength
775 TempByteBuffer += sizeof (UINT16);
776
777 CopyMem (TempByteBuffer, Desc, DescSize);
778 TempByteBuffer += DescSize;
779 ASSERT (FilePath != NULL);
780 CopyMem (TempByteBuffer, FilePath, FilePathSize);
781
782 UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", TargetLocation);
783 Status = gRT->SetVariable (
784 OptionStr,
785 &gEfiGlobalVariableGuid,
786 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
787 sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize,
788 TempByteStart
789 );
790
791 FreePool(TempByteStart);
792 } else {
793 Status = EFI_OUT_OF_RESOURCES;
794 }
795
796 if (EFI_ERROR(Status)) {
797 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr);
798 } else {
799 NewOrder = AllocateZeroPool ((OrderCount + 1) * sizeof (NewOrder[0]));
800 if (NewOrder != NULL) {
801 CopyMem (NewOrder, CurrentOrder, (OrderCount) * sizeof (NewOrder[0]));
802
803 //
804 // Insert target into order list
805 //
806 for (Index = OrderCount; Index > Position; Index--) {
807 NewOrder[Index] = NewOrder[Index - 1];
808 }
809
810 NewOrder[Position] = (UINT16) TargetLocation;
811 Status = gRT->SetVariable (
812 Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder",
813 &gEfiGlobalVariableGuid,
814 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
815 (OrderCount + 1) * sizeof (UINT16),
816 NewOrder
817 );
818
819 FreePool (NewOrder);
820
821 if (EFI_ERROR (Status)) {
822 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder");
823 ShellStatus = SHELL_INVALID_PARAMETER;
824 } else {
825 Print (L"bcfg: Add %s as %x\n", OptionStr, Position);
826 }
827 }
828 }
829 }
830
831 //
832 //If always Free FilePath, will free devicepath in system when use "addh"
833 //
834 if (FilePath!=NULL && !UseHandle) {
835 FreePool (FilePath);
836 }
837
838 if (Str != NULL) {
839 FreePool(Str);
840 }
841
842 if (Handles != NULL) {
843 FreePool (Handles);
844 }
845
846 if (FileList != NULL) {
847 ShellCloseFileMetaArg (&FileList);
848 }
849
850 return (ShellStatus);
851 }
852
853 /**
854 Funciton to remove an item.
855
856 @param[in] Target The target item to move.
857 @param[in] CurrentOrder The pointer to the current order of items.
858 @param[in] OrderCount The number if items in CurrentOrder.
859 @param[in] Location The current location of the Target.
860
861 @retval SHELL_SUCCESS The operation was successful.
862 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
863 **/
864 SHELL_STATUS
865 BcfgRemove(
866 IN CONST BCFG_OPERATION_TARGET Target,
867 IN CONST UINT16 *CurrentOrder,
868 IN CONST UINTN OrderCount,
869 IN CONST UINT16 Location
870 )
871 {
872 CHAR16 VariableName[12];
873 UINT16 *NewOrder;
874 EFI_STATUS Status;
875 UINTN NewCount;
876
877 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", CurrentOrder[Location]);
878 Status = gRT->SetVariable(
879 VariableName,
880 (EFI_GUID*)&gEfiGlobalVariableGuid,
881 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
882 0,
883 NULL);
884 if (EFI_ERROR(Status)) {
885 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
886 return (SHELL_INVALID_PARAMETER);
887 }
888 NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0]));
889 if (NewOrder != NULL) {
890 NewCount = OrderCount;
891 CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0]));
892 CopyMem(NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof(CurrentOrder[0]));
893 NewCount--;
894
895 Status = gRT->SetVariable(
896 Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
897 (EFI_GUID*)&gEfiGlobalVariableGuid,
898 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
899 NewCount*sizeof(NewOrder[0]),
900 NewOrder);
901 FreePool(NewOrder);
902 } else {
903 Status = EFI_OUT_OF_RESOURCES;
904 }
905 if (EFI_ERROR(Status)) {
906 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder");
907 return (SHELL_INVALID_PARAMETER);
908 }
909 return (SHELL_SUCCESS);
910 }
911
912 /**
913 Funciton to move a item to another location.
914
915 @param[in] Target The target item to move.
916 @param[in] CurrentOrder The pointer to the current order of items.
917 @param[in] OrderCount The number if items in CurrentOrder.
918 @param[in] OldLocation The current location of the Target.
919 @param[in] NewLocation The desired location of the Target.
920
921 @retval SHELL_SUCCESS The operation was successful.
922 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
923 **/
924 SHELL_STATUS
925 BcfgMove(
926 IN CONST BCFG_OPERATION_TARGET Target,
927 IN CONST UINT16 *CurrentOrder,
928 IN CONST UINTN OrderCount,
929 IN CONST UINT16 OldLocation,
930 IN UINT16 NewLocation
931 )
932 {
933 UINT16 *NewOrder;
934 EFI_STATUS Status;
935 UINT16 Temp;
936
937 NewOrder = AllocateCopyPool(OrderCount*sizeof(CurrentOrder[0]), CurrentOrder);
938 if (NewOrder == NULL) {
939 return (SHELL_OUT_OF_RESOURCES);
940 }
941
942 //
943 // correct the new location
944 //
945 if (NewLocation >= OrderCount) {
946 if (OrderCount > 0) {
947 NewLocation = (UINT16)OrderCount - 1;
948 } else {
949 NewLocation = 0;
950 }
951 }
952
953 Temp = CurrentOrder[OldLocation];
954 CopyMem(NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof(CurrentOrder[0]));
955 CopyMem(NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof(CurrentOrder[0]));
956 NewOrder[NewLocation] = Temp;
957
958 Status = gRT->SetVariable(
959 Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
960 (EFI_GUID*)&gEfiGlobalVariableGuid,
961 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
962 OrderCount*sizeof(CurrentOrder[0]),
963 NewOrder);
964
965 FreePool(NewOrder);
966
967 if (EFI_ERROR(Status)) {
968 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder");
969 return (SHELL_INVALID_PARAMETER);
970 }
971 return (SHELL_SUCCESS);
972 }
973
974 /**
975 Function to add optional data to an option.
976
977 @param[in] OptData The optional data to add.
978 @param[in] CurrentOrder The pointer to the current order of items.
979 @param[in] OrderCount The number if items in CurrentOrder.
980 @param[in] Target The target of the operation.
981
982 @retval SHELL_SUCCESS The operation was succesful.
983 **/
984 SHELL_STATUS
985 BcfgAddOpt(
986 IN CONST CHAR16 *OptData,
987 IN CONST UINT16 *CurrentOrder,
988 IN CONST UINTN OrderCount,
989 IN CONST BCFG_OPERATION_TARGET Target
990 )
991 {
992 EFI_KEY_OPTION NewKeyOption;
993 EFI_KEY_OPTION *KeyOptionBuffer;
994 SHELL_STATUS ShellStatus;
995 EFI_STATUS Status;
996 UINT16 OptionIndex;
997 UINT16 LoopCounter;
998 UINT64 Intermediate;
999 CONST CHAR16 *Temp;
1000 CONST CHAR16 *Walker;
1001 CHAR16 *FileName;
1002 CHAR16 *Temp2;
1003 CHAR16 *Data;
1004 UINT32 KeyIndex;
1005 CHAR16 VariableName[12];
1006 VOID *VariableData;
1007
1008 SHELL_FILE_HANDLE FileHandle;
1009
1010 Status = EFI_SUCCESS;
1011 ShellStatus = SHELL_SUCCESS;
1012 Walker = OptData;
1013 FileName = NULL;
1014 Data = NULL;
1015 KeyOptionBuffer = NULL;
1016 VariableData = NULL;
1017
1018 ZeroMem(&NewKeyOption, sizeof(EFI_KEY_OPTION));
1019 ZeroMem(VariableName, sizeof(VariableName));
1020
1021 while(Walker[0] == L' ') {
1022 Walker++;
1023 }
1024
1025 //
1026 // Get the index of the variable we are changing.
1027 //
1028 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
1029 if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL || ((UINT16)Intermediate) > ((UINT16)OrderCount)) {
1030 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index");
1031 ShellStatus = SHELL_INVALID_PARAMETER;
1032 return (ShellStatus);
1033 }
1034 OptionIndex = (UINT16)Intermediate;
1035
1036 Temp = StrStr(Walker, L" ");
1037 if (Temp != NULL) {
1038 Walker = Temp;
1039 }
1040 while(Walker[0] == L' ') {
1041 Walker++;
1042 }
1043
1044 //
1045 // determine whether we have file with data, quote delimited information, or a hot-key
1046 //
1047 if (Walker[0] == L'\"') {
1048 //
1049 // quoted filename or quoted information.
1050 //
1051 Temp = StrStr(Walker+1, L"\"");
1052 if (Temp == NULL || StrLen(Temp) != 1) {
1053 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
1054 ShellStatus = SHELL_INVALID_PARAMETER;
1055 } else {
1056 FileName = StrnCatGrow(&FileName, NULL, Walker+1, 0);
1057 if (FileName == NULL) {
1058 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellBcfgHiiHandle, L"bcfg");
1059 ShellStatus = SHELL_OUT_OF_RESOURCES;
1060 return (ShellStatus);
1061 }
1062 Temp2 = StrStr(FileName, L"\"");
1063 ASSERT(Temp2 != NULL);
1064 Temp2[0] = CHAR_NULL;
1065 Temp2++;
1066 if (StrLen(Temp2)>0) {
1067 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
1068 ShellStatus = SHELL_INVALID_PARAMETER;
1069 }
1070 if (EFI_ERROR(ShellFileExists(Walker))) {
1071 //
1072 // Not a file. must be misc information.
1073 //
1074 Data = FileName;
1075 FileName = NULL;
1076 } else {
1077 FileName = StrnCatGrow(&FileName, NULL, Walker, 0);
1078 }
1079 }
1080 } else {
1081 //
1082 // filename or hot key information.
1083 //
1084 if (StrStr(Walker, L" ") == NULL) {
1085 //
1086 // filename
1087 //
1088 if (EFI_ERROR(ShellFileExists(Walker))) {
1089 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellBcfgHiiHandle, L"bcfg", Walker);
1090 ShellStatus = SHELL_INVALID_PARAMETER;
1091 } else {
1092 FileName = StrnCatGrow(&FileName, NULL, Walker, 0);
1093 }
1094 } else {
1095 if (Target != BcfgTargetBootOrder) {
1096 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_BOOT_ONLY), gShellBcfgHiiHandle, L"bcfg");
1097 ShellStatus = SHELL_INVALID_PARAMETER;
1098 }
1099
1100 if (ShellStatus == SHELL_SUCCESS) {
1101 //
1102 // Get hot key information
1103 //
1104 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
1105 if (EFI_ERROR(Status) || (((UINT32)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) {
1106 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
1107 ShellStatus = SHELL_INVALID_PARAMETER;
1108 }
1109 NewKeyOption.KeyData.PackedValue = (UINT32)Intermediate;
1110 Temp = StrStr(Walker, L" ");
1111 if (Temp != NULL) {
1112 Walker = Temp;
1113 }
1114 while(Walker[0] == L' ') {
1115 Walker++;
1116 }
1117 }
1118
1119 if (ShellStatus == SHELL_SUCCESS) {
1120 //
1121 // Now we know how many EFI_INPUT_KEY structs we need to attach to the end of the EFI_KEY_OPTION struct.
1122 // Re-allocate with the added information.
1123 //
1124 KeyOptionBuffer = AllocatePool (sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount));
1125 if (KeyOptionBuffer == NULL) {
1126 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg");
1127 ShellStatus = SHELL_OUT_OF_RESOURCES;
1128 return ShellStatus;
1129 }
1130 CopyMem (KeyOptionBuffer, &NewKeyOption, sizeof(EFI_KEY_OPTION));
1131 }
1132 for (LoopCounter = 0 ; ShellStatus == SHELL_SUCCESS && LoopCounter < NewKeyOption.KeyData.Options.InputKeyCount; LoopCounter++) {
1133 //
1134 // ScanCode
1135 //
1136 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
1137 if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) {
1138 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
1139 ShellStatus = SHELL_INVALID_PARAMETER;
1140 }
1141 ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].ScanCode = (UINT16)Intermediate;
1142 Temp = StrStr(Walker, L" ");
1143 if (Temp != NULL) {
1144 Walker = Temp;
1145 }
1146 while(Walker[0] == L' ') {
1147 Walker++;
1148 }
1149
1150 //
1151 // UnicodeChar
1152 //
1153 Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
1154 if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate)) {
1155 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
1156 ShellStatus = SHELL_INVALID_PARAMETER;
1157 }
1158 ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].UnicodeChar = (UINT16)Intermediate;
1159 Temp = StrStr(Walker, L" ");
1160 if (Temp != NULL) {
1161 Walker = Temp;
1162 }
1163 while(Walker[0] == L' ') {
1164 Walker++;
1165 }
1166 }
1167
1168 if (ShellStatus == SHELL_SUCCESS) {
1169 //
1170 // Now do the BootOption / BootOptionCrc
1171 //
1172 ASSERT (OptionIndex <= OrderCount);
1173 KeyOptionBuffer->BootOption = CurrentOrder[OptionIndex];
1174 Status = GetBootOptionCrc(&(KeyOptionBuffer->BootOptionCrc), KeyOptionBuffer->BootOption);
1175 if (EFI_ERROR(Status)) {
1176 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index");
1177 ShellStatus = SHELL_INVALID_PARAMETER;
1178 }
1179 }
1180
1181 if (ShellStatus == SHELL_SUCCESS) {
1182 for (Temp2 = NULL, KeyIndex = 0 ; KeyIndex <= 0xFFFF ; KeyIndex++) {
1183 UnicodeSPrint(VariableName, sizeof(VariableName), L"Key%04x", KeyIndex);
1184 Status = GetEfiGlobalVariable2 (VariableName, &VariableData, NULL);
1185 if (Status == EFI_NOT_FOUND) {
1186 break;
1187 }
1188 if (!EFI_ERROR(Status)) {
1189 SHELL_FREE_NON_NULL(VariableData);
1190 }
1191 }
1192 if (KeyIndex <= 0xFFFF) {
1193 Status = gRT->SetVariable(
1194 VariableName,
1195 (EFI_GUID*)&gEfiGlobalVariableGuid,
1196 EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
1197 sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount),
1198 KeyOptionBuffer);
1199 if (EFI_ERROR(Status)) {
1200 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
1201 ShellStatus = SHELL_INVALID_PARAMETER;
1202 }
1203 } else {
1204 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_VAR_NO_NUM), gShellBcfgHiiHandle, L"bcfg");
1205 ShellStatus = SHELL_INVALID_PARAMETER;
1206 }
1207 ASSERT(FileName == NULL && Data == NULL);
1208 }
1209 }
1210 }
1211
1212 //
1213 // Shouldn't be possible to have have both. Neither is ok though.
1214 //
1215 ASSERT(FileName == NULL || Data == NULL);
1216
1217 if (ShellStatus == SHELL_SUCCESS && (FileName != NULL || Data != NULL)) {
1218 if (FileName != NULL) {
1219 //
1220 // Open the file and populate the data buffer.
1221 //
1222 Status = ShellOpenFileByName(
1223 FileName,
1224 &FileHandle,
1225 EFI_FILE_MODE_READ,
1226 0);
1227 if (!EFI_ERROR(Status)) {
1228 Status = ShellGetFileSize(FileHandle, &Intermediate);
1229 }
1230 Data = AllocateZeroPool((UINTN)Intermediate);
1231 if (Data == NULL) {
1232 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg");
1233 ShellStatus = SHELL_OUT_OF_RESOURCES;
1234 }
1235 if (!EFI_ERROR(Status)) {
1236 Status = ShellReadFile(FileHandle, (UINTN *)&Intermediate, Data);
1237 }
1238 } else {
1239 Intermediate = StrSize(Data);
1240 }
1241
1242 if (!EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS && Data != NULL) {
1243 Status = UpdateOptionalData(CurrentOrder[OptionIndex], (UINTN)Intermediate, (UINT8*)Data, Target);
1244 if (EFI_ERROR(Status)) {
1245 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
1246 ShellStatus = SHELL_INVALID_PARAMETER;
1247 }
1248 }
1249 if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
1250 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
1251 ShellStatus = SHELL_INVALID_PARAMETER;
1252 }
1253 }
1254
1255 SHELL_FREE_NON_NULL(Data);
1256 SHELL_FREE_NON_NULL(KeyOptionBuffer);
1257 SHELL_FREE_NON_NULL(FileName);
1258 return ShellStatus;
1259 }
1260
1261 /**
1262 Function to dump the Bcfg information.
1263
1264 @param[in] Op The operation.
1265 @param[in] OrderCount How many to dump.
1266 @param[in] CurrentOrder The pointer to the current order of items.
1267 @param[in] VerboseOutput TRUE for extra output. FALSE otherwise.
1268
1269 @retval SHELL_SUCCESS The dump was successful.
1270 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
1271 **/
1272 SHELL_STATUS
1273 BcfgDisplayDump(
1274 IN CONST CHAR16 *Op,
1275 IN CONST UINTN OrderCount,
1276 IN CONST UINT16 *CurrentOrder,
1277 IN CONST BOOLEAN VerboseOutput
1278 )
1279 {
1280 EFI_STATUS Status;
1281 UINT8 *Buffer;
1282 UINTN BufferSize;
1283 CHAR16 VariableName[12];
1284 UINTN LoopVar;
1285 CHAR16 *DevPathString;
1286 VOID *FilePathList;
1287 UINTN Errors;
1288 EFI_LOAD_OPTION *LoadOption;
1289 CHAR16 *Description;
1290 UINTN DescriptionSize;
1291 UINTN OptionalDataOffset;
1292
1293 if (OrderCount == 0) {
1294 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_BCFG_NONE), gShellBcfgHiiHandle, L"bcfg");
1295 return (SHELL_SUCCESS);
1296 }
1297
1298 Errors = 0;
1299
1300 for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++) {
1301 Buffer = NULL;
1302 BufferSize = 0;
1303 DevPathString = NULL;
1304
1305 UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]);
1306
1307 Status = gRT->GetVariable(
1308 VariableName,
1309 (EFI_GUID*)&gEfiGlobalVariableGuid,
1310 NULL,
1311 &BufferSize,
1312 Buffer);
1313 if (Status == EFI_BUFFER_TOO_SMALL) {
1314 Buffer = AllocateZeroPool(BufferSize);
1315 Status = gRT->GetVariable(
1316 VariableName,
1317 (EFI_GUID*)&gEfiGlobalVariableGuid,
1318 NULL,
1319 &BufferSize,
1320 Buffer);
1321 }
1322
1323 if (EFI_ERROR(Status) || Buffer == NULL) {
1324 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
1325 ++Errors;
1326 goto Cleanup;
1327 }
1328
1329 //
1330 // We expect the Attributes, FilePathListLength, and L'\0'-terminated
1331 // Description fields to be present.
1332 //
1333 if (BufferSize < sizeof *LoadOption + sizeof (CHAR16)) {
1334 ShellPrintHiiEx (
1335 -1,
1336 -1,
1337 NULL,
1338 STRING_TOKEN (STR_BCFG_VAR_CORRUPT),
1339 gShellBcfgHiiHandle,
1340 L"bcfg",
1341 VariableName
1342 );
1343 ++Errors;
1344 goto Cleanup;
1345 }
1346
1347 LoadOption = (EFI_LOAD_OPTION *)Buffer;
1348 Description = (CHAR16*)(Buffer + sizeof (EFI_LOAD_OPTION));
1349 DescriptionSize = StrSize (Description);
1350
1351 if (LoadOption->FilePathListLength != 0) {
1352 FilePathList = (UINT8 *)Description + DescriptionSize;
1353 DevPathString = ConvertDevicePathToText(FilePathList, TRUE, FALSE);
1354 }
1355
1356 OptionalDataOffset = sizeof *LoadOption + DescriptionSize +
1357 LoadOption->FilePathListLength;
1358
1359 ShellPrintHiiEx(
1360 -1,
1361 -1,
1362 NULL,
1363 STRING_TOKEN(STR_BCFG_LOAD_OPTIONS),
1364 gShellBcfgHiiHandle,
1365 LoopVar,
1366 VariableName,
1367 Description,
1368 DevPathString,
1369 OptionalDataOffset >= BufferSize ? L'N' : L'Y'
1370 );
1371 if (VerboseOutput && (OptionalDataOffset < BufferSize)) {
1372 DumpHex (
1373 2, // Indent
1374 0, // Offset (displayed)
1375 BufferSize - OptionalDataOffset, // DataSize
1376 Buffer + OptionalDataOffset // UserData
1377 );
1378 }
1379
1380 Cleanup:
1381 if (Buffer != NULL) {
1382 FreePool(Buffer);
1383 }
1384 if (DevPathString != NULL) {
1385 FreePool(DevPathString);
1386 }
1387 }
1388 return (Errors > 0) ? SHELL_INVALID_PARAMETER : SHELL_SUCCESS;
1389 }
1390
1391 /**
1392 Function to initialize the BCFG operation structure.
1393
1394 @param[in] Struct The stuct to initialize.
1395 **/
1396 VOID
1397 InitBcfgStruct(
1398 IN BGFG_OPERATION *Struct
1399 )
1400 {
1401 ASSERT(Struct != NULL);
1402 Struct->Target = BcfgTargetMax;
1403 Struct->Type = BcfgTypeMax;
1404 Struct->Number1 = 0;
1405 Struct->Number2 = 0;
1406 Struct->HandleIndex = 0;
1407 Struct->FileName = NULL;
1408 Struct->Description = NULL;
1409 Struct->Order = NULL;
1410 Struct->OptData = NULL;
1411 }
1412
1413
1414 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
1415 {L"-v", TypeFlag},
1416 {L"-opt", TypeMaxValue},
1417 {NULL, TypeMax}
1418 };
1419
1420 /**
1421 Function for 'bcfg' command.
1422
1423 @param[in] ImageHandle Handle to the Image (NULL if Internal).
1424 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
1425 **/
1426 SHELL_STATUS
1427 EFIAPI
1428 ShellCommandRunBcfg (
1429 IN EFI_HANDLE ImageHandle,
1430 IN EFI_SYSTEM_TABLE *SystemTable
1431 )
1432 {
1433 EFI_STATUS Status;
1434 LIST_ENTRY *Package;
1435 CHAR16 *ProblemParam;
1436 SHELL_STATUS ShellStatus;
1437 UINTN ParamNumber;
1438 CONST CHAR16 *CurrentParam;
1439 BGFG_OPERATION CurrentOperation;
1440 UINTN Length;
1441 UINT64 Intermediate;
1442 UINT16 Count;
1443
1444 Length = 0;
1445 ProblemParam = NULL;
1446 Package = NULL;
1447 ShellStatus = SHELL_SUCCESS;
1448
1449 InitBcfgStruct(&CurrentOperation);
1450
1451 //
1452 // initialize the shell lib (we must be in non-auto-init...)
1453 //
1454 Status = ShellInitialize();
1455 ASSERT_EFI_ERROR(Status);
1456
1457 Status = CommandInit();
1458 ASSERT_EFI_ERROR(Status);
1459
1460 //
1461 // parse the command line
1462 //
1463 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
1464 if (EFI_ERROR(Status)) {
1465 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
1466 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"bcfg", ProblemParam);
1467 FreePool(ProblemParam);
1468 ShellStatus = SHELL_INVALID_PARAMETER;
1469 } else {
1470 ASSERT(FALSE);
1471 }
1472 } else {
1473 //
1474 // Read in if we are doing -OPT
1475 //
1476 if (ShellCommandLineGetFlag(Package, L"-opt")) {
1477 CurrentOperation.OptData = ShellCommandLineGetValue(Package, L"-opt");
1478 if (CurrentOperation.OptData == NULL) {
1479 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellBcfgHiiHandle, L"bcfg", L"-opt");
1480 ShellStatus = SHELL_INVALID_PARAMETER;
1481 }
1482 CurrentOperation.Type = BcfgTypeOpt;
1483 }
1484
1485 //
1486 // small block to read the target of the operation
1487 //
1488 if ((ShellCommandLineGetCount(Package) < 3 && CurrentOperation.Type != BcfgTypeOpt) ||
1489 (ShellCommandLineGetCount(Package) < 2 && CurrentOperation.Type == BcfgTypeOpt)
1490 ){
1491 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1492 ShellStatus = SHELL_INVALID_PARAMETER;
1493 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"driver") == 0) {
1494 CurrentOperation.Target = BcfgTargetDriverOrder;
1495 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"boot") == 0) {
1496 CurrentOperation.Target = BcfgTargetBootOrder;
1497 } else {
1498 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellBcfgHiiHandle, L"bcfg");
1499 ShellStatus = SHELL_INVALID_PARAMETER;
1500 }
1501
1502
1503 //
1504 // Read in the boot or driver order environment variable (not needed for opt)
1505 //
1506 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {
1507 Length = 0;
1508 Status = gRT->GetVariable(
1509 CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
1510 (EFI_GUID*)&gEfiGlobalVariableGuid,
1511 NULL,
1512 &Length,
1513 CurrentOperation.Order);
1514 if (Status == EFI_BUFFER_TOO_SMALL) {
1515 CurrentOperation.Order = AllocateZeroPool(Length+(4*sizeof(CurrentOperation.Order[0])));
1516 if (CurrentOperation.Order == NULL) {
1517 ShellStatus = SHELL_OUT_OF_RESOURCES;
1518 } else {
1519 Status = gRT->GetVariable(
1520 CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
1521 (EFI_GUID*)&gEfiGlobalVariableGuid,
1522 NULL,
1523 &Length,
1524 CurrentOperation.Order);
1525 }
1526 }
1527 }
1528
1529 Count = (UINT16) (Length / sizeof(CurrentOperation.Order[0]));
1530
1531 //
1532 // large block to read the type of operation and verify parameter types for the info.
1533 //
1534 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {
1535 for (ParamNumber = 2 ; ParamNumber < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) {
1536 CurrentParam = ShellCommandLineGetRawValue(Package, ParamNumber);
1537 if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"dump") == 0) {
1538 CurrentOperation.Type = BcfgTypeDump;
1539 if (ShellCommandLineGetCount(Package) > 3) {
1540 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellBcfgHiiHandle, L"bcfg");
1541 ShellStatus = SHELL_INVALID_PARAMETER;
1542 }
1543 } else if (ShellCommandLineGetFlag(Package, L"-v")) {
1544 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"-v (without dump)");
1545 ShellStatus = SHELL_INVALID_PARAMETER;
1546 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"add") == 0) {
1547 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
1548 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1549 ShellStatus = SHELL_INVALID_PARAMETER;
1550 }
1551 CurrentOperation.Type = BcfgTypeAdd;
1552 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1553 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1554 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1555 ShellStatus = SHELL_INVALID_PARAMETER;
1556 } else {
1557 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1558 CurrentOperation.Number1 = (UINT16)Intermediate;
1559 ASSERT(CurrentOperation.FileName == NULL);
1560 CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1561 ASSERT(CurrentOperation.Description == NULL);
1562 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1563 }
1564 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addp") == 0) {
1565 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
1566 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1567 ShellStatus = SHELL_INVALID_PARAMETER;
1568 }
1569 CurrentOperation.Type = BcfgTypeAddp;
1570 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1571 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1572 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1573 ShellStatus = SHELL_INVALID_PARAMETER;
1574 } else {
1575 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1576 CurrentOperation.Number1 = (UINT16)Intermediate;
1577 ASSERT(CurrentOperation.FileName == NULL);
1578 CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1579 ASSERT(CurrentOperation.Description == NULL);
1580 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1581 }
1582 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addh") == 0) {
1583 if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
1584 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1585 ShellStatus = SHELL_INVALID_PARAMETER;
1586 }
1587 CurrentOperation.Type = BcfgTypeAddh;
1588 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1589 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1590 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1591 ShellStatus = SHELL_INVALID_PARAMETER;
1592 } else {
1593 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1594 CurrentOperation.Number1 = (UINT16)Intermediate;
1595 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1596 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1597 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1598 ShellStatus = SHELL_INVALID_PARAMETER;
1599 } else {
1600 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1601 CurrentOperation.HandleIndex = (UINT16)Intermediate;
1602 ASSERT(CurrentOperation.Description == NULL);
1603 CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
1604 }
1605 }
1606 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"rm") == 0) {
1607 if ((ParamNumber + 1) >= ShellCommandLineGetCount(Package)) {
1608 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1609 ShellStatus = SHELL_INVALID_PARAMETER;
1610 }
1611 CurrentOperation.Type = BcfgTypeRm;
1612 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1613 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1614 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1615 ShellStatus = SHELL_INVALID_PARAMETER;
1616 } else {
1617 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1618 CurrentOperation.Number1 = (UINT16)Intermediate;
1619 if (CurrentOperation.Number1 >= Count){
1620 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1621 ShellStatus = SHELL_INVALID_PARAMETER;
1622 }
1623 }
1624 } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"mv") == 0) {
1625 if ((ParamNumber + 2) >= ShellCommandLineGetCount(Package)) {
1626 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1627 ShellStatus = SHELL_INVALID_PARAMETER;
1628 }
1629 CurrentOperation.Type = BcfgTypeMv;
1630 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1631 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1632 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1633 ShellStatus = SHELL_INVALID_PARAMETER;
1634 } else {
1635 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1636 CurrentOperation.Number1 = (UINT16)Intermediate;
1637 if (CurrentOperation.Number1 >= Count){
1638 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1639 ShellStatus = SHELL_INVALID_PARAMETER;
1640 } else {
1641 CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
1642 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
1643 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1644 ShellStatus = SHELL_INVALID_PARAMETER;
1645 } else {
1646 Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
1647 CurrentOperation.Number2 = (UINT16)Intermediate;
1648 }
1649 if (CurrentOperation.Number2 == CurrentOperation.Number1
1650 ||CurrentOperation.Number2 >= Count
1651 ){
1652 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1653 ShellStatus = SHELL_INVALID_PARAMETER;
1654 }
1655 }
1656 }
1657 }
1658 else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)CurrentParam, L"mod") == 0) {
1659 if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
1660 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1661 ShellStatus = SHELL_INVALID_PARAMETER;
1662 } else {
1663 CurrentOperation.Type = BcfgTypeMod;
1664 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1665 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1666 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1667 ShellStatus = SHELL_INVALID_PARAMETER;
1668 } else {
1669 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1670 CurrentOperation.Number1 = (UINT16)Intermediate;
1671 if (CurrentOperation.Number1 >= Count) {
1672 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1673 ShellStatus = SHELL_INVALID_PARAMETER;
1674 } else {
1675 ASSERT (CurrentOperation.Description == NULL);
1676 CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
1677 }
1678 }
1679 }
1680 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)CurrentParam, L"modf") == 0) {
1681 if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
1682 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1683 ShellStatus = SHELL_INVALID_PARAMETER;
1684 } else {
1685 CurrentOperation.Type = BcfgTypeModf;
1686 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1687 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1688 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1689 ShellStatus = SHELL_INVALID_PARAMETER;
1690 } else {
1691 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1692 CurrentOperation.Number1 = (UINT16)Intermediate;
1693 if (CurrentOperation.Number1 >= Count) {
1694 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1695 ShellStatus = SHELL_INVALID_PARAMETER;
1696 } else {
1697 ASSERT (CurrentOperation.FileName == NULL);
1698 CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
1699 }
1700 }
1701 }
1702 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)CurrentParam, L"modp") == 0) {
1703 if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
1704 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1705 ShellStatus = SHELL_INVALID_PARAMETER;
1706 } else {
1707 CurrentOperation.Type = BcfgTypeModp;
1708 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1709 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1710 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1711 ShellStatus = SHELL_INVALID_PARAMETER;
1712 } else {
1713 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1714 CurrentOperation.Number1 = (UINT16)Intermediate;
1715 if (CurrentOperation.Number1 >= Count) {
1716 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1717 ShellStatus = SHELL_INVALID_PARAMETER;
1718 } else {
1719 ASSERT (CurrentOperation.FileName == NULL);
1720 CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
1721 }
1722 }
1723 }
1724 } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)CurrentParam, L"modh") == 0) {
1725 if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
1726 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
1727 ShellStatus = SHELL_INVALID_PARAMETER;
1728 } else {
1729 CurrentOperation.Type = BcfgTypeModh;
1730 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1731 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1732 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1733 ShellStatus = SHELL_INVALID_PARAMETER;
1734 }
1735 else {
1736 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1737 CurrentOperation.Number1 = (UINT16)Intermediate;
1738 if (CurrentOperation.Number1 >= Count) {
1739 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
1740 ShellStatus = SHELL_INVALID_PARAMETER;
1741 } else {
1742 CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
1743 if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
1744 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1745 ShellStatus = SHELL_INVALID_PARAMETER;
1746 } else {
1747 Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
1748 CurrentOperation.HandleIndex = (UINT16)Intermediate;
1749 }
1750 }
1751 }
1752 }
1753 } else {
1754 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
1755 ShellStatus = SHELL_INVALID_PARAMETER;
1756 }
1757 }
1758 }
1759 if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type < BcfgTypeMax) {
1760 //
1761 // we have all the info. Do the work
1762 //
1763 switch (CurrentOperation.Type) {
1764 case BcfgTypeDump:
1765 ShellStatus = BcfgDisplayDump(
1766 CurrentOperation.Target == BcfgTargetBootOrder?L"Boot":L"Driver",
1767 Count,
1768 CurrentOperation.Order,
1769 ShellCommandLineGetFlag(Package, L"-v"));
1770 break;
1771 case BcfgTypeMv:
1772 ShellStatus = BcfgMove(
1773 CurrentOperation.Target,
1774 CurrentOperation.Order,
1775 Count,
1776 CurrentOperation.Number1,
1777 CurrentOperation.Number2);
1778 break;
1779 case BcfgTypeRm:
1780 ShellStatus = BcfgRemove(
1781 CurrentOperation.Target,
1782 CurrentOperation.Order,
1783 Count,
1784 CurrentOperation.Number1);
1785 break;
1786 case BcfgTypeAdd:
1787 case BcfgTypeAddp:
1788 case BcfgTypeAddh:
1789 ShellStatus = BcfgAdd(
1790 CurrentOperation.Number1,
1791 CurrentOperation.FileName,
1792 CurrentOperation.Description==NULL?L"":CurrentOperation.Description,
1793 CurrentOperation.Order,
1794 Count,
1795 CurrentOperation.Target,
1796 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh),
1797 (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp),
1798 CurrentOperation.HandleIndex);
1799 break;
1800 case BcfgTypeMod:
1801 case BcfgTypeModf:
1802 case BcfgTypeModp:
1803 case BcfgTypeModh:
1804 ShellStatus = BcfgMod (&CurrentOperation, Count);
1805 break;
1806 case BcfgTypeOpt:
1807 ShellStatus = BcfgAddOpt(
1808 CurrentOperation.OptData,
1809 CurrentOperation.Order,
1810 Count,
1811 CurrentOperation.Target);
1812 break;
1813 default:
1814 ASSERT(FALSE);
1815 }
1816 }
1817 }
1818
1819 if (Package != NULL) {
1820 ShellCommandLineFreeVarList (Package);
1821 }
1822 if (CurrentOperation.FileName != NULL) {
1823 FreePool(CurrentOperation.FileName);
1824 }
1825 if (CurrentOperation.Description != NULL) {
1826 FreePool(CurrentOperation.Description);
1827 }
1828 if (CurrentOperation.Order != NULL) {
1829 FreePool(CurrentOperation.Order);
1830 }
1831
1832 return (ShellStatus);
1833 }
1834
1835
1836 /**
1837 Function to get the filename with help context if HII will not be used.
1838
1839 @return The filename with help text in it.
1840 **/
1841 CONST CHAR16*
1842 EFIAPI
1843 ShellCommandGetManFileNameBcfg (
1844 VOID
1845 )
1846 {
1847 return (mFileName);
1848 }
1849
1850 /**
1851 "Constructor" for the library.
1852
1853 This will register the handler for the bcfg command.
1854
1855 @param[in] ImageHandle the image handle of the process
1856 @param[in] SystemTable the EFI System Table pointer
1857 @param[in] Name the profile name to use
1858
1859 @retval EFI_SUCCESS the shell command handlers were installed sucessfully
1860 @retval EFI_UNSUPPORTED the shell level required was not found.
1861 **/
1862 EFI_STATUS
1863 EFIAPI
1864 BcfgLibraryRegisterBcfgCommand (
1865 IN EFI_HANDLE ImageHandle,
1866 IN EFI_SYSTEM_TABLE *SystemTable,
1867 IN CONST CHAR16 *Name
1868 )
1869 {
1870 if (gShellBcfgHiiHandle != NULL) {
1871 return (EFI_SUCCESS);
1872 }
1873
1874 gShellBcfgHiiHandle = HiiAddPackages (&gShellBcfgHiiGuid, gImageHandle, UefiShellBcfgCommandLibStrings, NULL);
1875 if (gShellBcfgHiiHandle == NULL) {
1876 return (EFI_DEVICE_ERROR);
1877 }
1878
1879 //
1880 // install our shell command handler
1881 //
1882 ShellCommandRegisterCommandName(L"bcfg", ShellCommandRunBcfg , ShellCommandGetManFileNameBcfg, 0, Name, FALSE, gShellBcfgHiiHandle, STRING_TOKEN(STR_GET_HELP_BCFG));
1883
1884 return (EFI_SUCCESS);
1885 }
1886
1887 /**
1888 Destructor for the library. free any resources.
1889
1890 @param ImageHandle The image handle of the process.
1891 @param SystemTable The EFI System Table pointer.
1892 **/
1893 EFI_STATUS
1894 EFIAPI
1895 BcfgLibraryUnregisterBcfgCommand (
1896 IN EFI_HANDLE ImageHandle,
1897 IN EFI_SYSTEM_TABLE *SystemTable
1898 )
1899 {
1900 if (gShellBcfgHiiHandle != NULL) {
1901 HiiRemovePackages(gShellBcfgHiiHandle);
1902 }
1903 gShellBcfgHiiHandle = NULL;
1904 return (EFI_SUCCESS);
1905 }
1906