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