]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLib/UefiShellLib.c
fixed color printing in ShellPrintEx function
[mirror_edk2.git] / ShellPkg / Library / UefiShellLib / UefiShellLib.c
CommitLineData
94b17fa1 1/** @file\r
2 Provides interface to shell functionality for shell commands and applications.\r
3\r
4Copyright (c) 2006 - 2009, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <Uefi.h>\r
16#include <Library/ShellLib.h>\r
17#include <Library/UefiBootServicesTableLib.h>\r
18#include <Library/BaseLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/MemoryAllocationLib.h>\r
22#include <Library/DevicePathLib.h>\r
d2b4564b 23#include <Library/PcdLib.h>\r
24#include <Library/FileHandleLib.h>\r
b1f95a06 25#include <Library/PrintLib.h>\r
26#include <Library/UefiLib.h>\r
27\r
94b17fa1 28#include <Protocol/EfiShellEnvironment2.h>\r
29#include <Protocol/EfiShellInterface.h>\r
30#include <Protocol/EfiShell.h>\r
31#include <Protocol/EfiShellParameters.h>\r
32#include <Protocol/SimpleFileSystem.h>\r
33\r
b1f95a06 34#include "UefiShellLib.h"\r
d2b4564b 35\r
94b17fa1 36#define MAX_FILE_NAME_LEN 522 // (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)\r
37#define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN)\r
38\r
d2b4564b 39//\r
40// This is not static since it's extern in the .h file\r
41//\r
42SHELL_PARAM_ITEM EmptyParamList[] = {\r
43 {NULL, TypeMax}\r
44 };\r
45\r
46//\r
47// Static file globals for the shell library\r
48//\r
49STATIC EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2;\r
50STATIC EFI_SHELL_INTERFACE *mEfiShellInterface;\r
51STATIC EFI_SHELL_PROTOCOL *mEfiShellProtocol;\r
52STATIC EFI_SHELL_PARAMETERS_PROTOCOL *mEfiShellParametersProtocol;\r
53STATIC EFI_HANDLE mEfiShellEnvironment2Handle;\r
54STATIC FILE_HANDLE_FUNCTION_MAP FileFunctionMap;\r
94b17fa1 55\r
56/**\r
57 helper function to find ShellEnvironment2 for constructor\r
58**/\r
59EFI_STATUS\r
60EFIAPI\r
61ShellFindSE2 (\r
62 IN EFI_HANDLE ImageHandle\r
63 )\r
64{\r
65 EFI_STATUS Status;\r
66 EFI_HANDLE *Buffer;\r
67 UINTN BufferSize;\r
68 UINTN HandleIndex;\r
69\r
70 BufferSize = 0;\r
71 Buffer = NULL;\r
72 Status = gBS->OpenProtocol(ImageHandle, \r
73 &gEfiShellEnvironment2Guid,\r
74 (VOID **)&mEfiShellEnvironment2,\r
75 ImageHandle,\r
76 NULL,\r
77 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
78 );\r
79 //\r
80 // look for the mEfiShellEnvironment2 protocol at a higher level\r
81 //\r
82 if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE &&\r
83 (mEfiShellEnvironment2->MajorVersion > EFI_SHELL_MAJOR_VER ||\r
84 (mEfiShellEnvironment2->MajorVersion == EFI_SHELL_MAJOR_VER && mEfiShellEnvironment2->MinorVersion >= EFI_SHELL_MINOR_VER)))) {\r
85 //\r
86 // figure out how big of a buffer we need.\r
87 //\r
88 Status = gBS->LocateHandle (ByProtocol,\r
89 &gEfiShellEnvironment2Guid,\r
90 NULL, // ignored for ByProtocol\r
91 &BufferSize,\r
92 Buffer\r
93 );\r
94 ASSERT(Status == EFI_BUFFER_TOO_SMALL);\r
95 Buffer = (EFI_HANDLE*)AllocatePool(BufferSize);\r
96 ASSERT(Buffer != NULL);\r
97 Status = gBS->LocateHandle (ByProtocol,\r
98 &gEfiShellEnvironment2Guid,\r
99 NULL, // ignored for ByProtocol\r
100 &BufferSize,\r
101 Buffer\r
102 );\r
103 if (!EFI_ERROR (Status)) {\r
104 //\r
105 // now parse the list of returned handles\r
106 //\r
107 Status = EFI_NOT_FOUND;\r
108 for (HandleIndex = 0; HandleIndex < (BufferSize/sizeof(Buffer[0])); HandleIndex++) {\r
109 Status = gBS->OpenProtocol(Buffer[HandleIndex], \r
110 &gEfiShellEnvironment2Guid,\r
111 (VOID **)&mEfiShellEnvironment2,\r
112 ImageHandle,\r
113 NULL,\r
114 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
115 );\r
116 if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE &&\r
117 (mEfiShellEnvironment2->MajorVersion > EFI_SHELL_MAJOR_VER ||\r
118 (mEfiShellEnvironment2->MajorVersion == EFI_SHELL_MAJOR_VER && mEfiShellEnvironment2->MinorVersion >= EFI_SHELL_MINOR_VER))) {\r
119 mEfiShellEnvironment2Handle = Buffer[HandleIndex];\r
120 Status = EFI_SUCCESS;\r
121 break;\r
122 }\r
123 }\r
124 }\r
125 }\r
126 if (Buffer != NULL) {\r
127 FreePool (Buffer);\r
128 }\r
129 return (Status);\r
130}\r
131\r
94b17fa1 132EFI_STATUS\r
133EFIAPI\r
d2b4564b 134ShellLibConstructorWorker (\r
94b17fa1 135 IN EFI_HANDLE ImageHandle,\r
136 IN EFI_SYSTEM_TABLE *SystemTable\r
d2b4564b 137){\r
94b17fa1 138 EFI_STATUS Status;\r
139\r
94b17fa1 140 //\r
141 // UEFI 2.0 shell interfaces (used preferentially)\r
142 //\r
143 Status = gBS->OpenProtocol(ImageHandle, \r
144 &gEfiShellProtocolGuid,\r
145 (VOID **)&mEfiShellProtocol,\r
146 ImageHandle,\r
147 NULL,\r
148 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
149 );\r
150 if (EFI_ERROR(Status)) {\r
151 mEfiShellProtocol = NULL;\r
152 }\r
153 Status = gBS->OpenProtocol(ImageHandle, \r
154 &gEfiShellParametersProtocolGuid,\r
155 (VOID **)&mEfiShellParametersProtocol,\r
156 ImageHandle,\r
157 NULL,\r
158 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
159 );\r
160 if (EFI_ERROR(Status)) {\r
161 mEfiShellParametersProtocol = NULL;\r
162 }\r
163\r
164 if (mEfiShellParametersProtocol == NULL || mEfiShellProtocol == NULL) {\r
165 //\r
166 // Moved to seperate function due to complexity\r
167 //\r
168 Status = ShellFindSE2(ImageHandle);\r
169\r
170 if (EFI_ERROR(Status)) {\r
171 DEBUG((DEBUG_ERROR, "Status: 0x%08x\r\n", Status));\r
172 mEfiShellEnvironment2 = NULL;\r
173 }\r
174 Status = gBS->OpenProtocol(ImageHandle, \r
175 &gEfiShellInterfaceGuid,\r
176 (VOID **)&mEfiShellInterface,\r
177 ImageHandle,\r
178 NULL,\r
179 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
180 );\r
181 if (EFI_ERROR(Status)) {\r
182 mEfiShellInterface = NULL;\r
183 }\r
184 }\r
185 //\r
186 // only success getting 2 of either the old or new, but no 1/2 and 1/2\r
187 //\r
188 if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface != NULL) || \r
189 (mEfiShellProtocol != NULL && mEfiShellParametersProtocol != NULL) ) {\r
d2b4564b 190 if (mEfiShellProtocol != NULL) {\r
191 FileFunctionMap.GetFileInfo = mEfiShellProtocol->GetFileInfo;\r
192 FileFunctionMap.SetFileInfo = mEfiShellProtocol->SetFileInfo;\r
193 FileFunctionMap.ReadFile = mEfiShellProtocol->ReadFile;\r
194 FileFunctionMap.WriteFile = mEfiShellProtocol->WriteFile;\r
195 FileFunctionMap.CloseFile = mEfiShellProtocol->CloseFile;\r
196 FileFunctionMap.DeleteFile = mEfiShellProtocol->DeleteFile;\r
197 FileFunctionMap.GetFilePosition = mEfiShellProtocol->GetFilePosition;\r
198 FileFunctionMap.SetFilePosition = mEfiShellProtocol->SetFilePosition;\r
199 FileFunctionMap.FlushFile = mEfiShellProtocol->FlushFile;\r
200 FileFunctionMap.GetFileSize = mEfiShellProtocol->GetFileSize;\r
201 } else {\r
202 FileFunctionMap.GetFileInfo = FileHandleGetInfo;\r
203 FileFunctionMap.SetFileInfo = FileHandleSetInfo;\r
204 FileFunctionMap.ReadFile = FileHandleRead;\r
205 FileFunctionMap.WriteFile = FileHandleWrite;\r
206 FileFunctionMap.CloseFile = FileHandleClose;\r
207 FileFunctionMap.DeleteFile = FileHandleDelete;\r
208 FileFunctionMap.GetFilePosition = FileHandleGetPosition;\r
209 FileFunctionMap.SetFilePosition = FileHandleSetPosition;\r
210 FileFunctionMap.FlushFile = FileHandleFlush;\r
211 FileFunctionMap.GetFileSize = FileHandleGetSize;\r
212 }\r
94b17fa1 213 return (EFI_SUCCESS);\r
214 }\r
215 return (EFI_NOT_FOUND);\r
216}\r
d2b4564b 217/**\r
218 Constructor for the Shell library.\r
219\r
220 Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell.\r
221\r
222 @param ImageHandle the image handle of the process\r
223 @param SystemTable the EFI System Table pointer\r
224\r
225 @retval EFI_SUCCESS the initialization was complete sucessfully\r
226 @return others an error ocurred during initialization\r
227**/\r
228EFI_STATUS\r
229EFIAPI\r
230ShellLibConstructor (\r
231 IN EFI_HANDLE ImageHandle,\r
232 IN EFI_SYSTEM_TABLE *SystemTable\r
233 )\r
234{\r
235\r
236\r
237 mEfiShellEnvironment2 = NULL;\r
238 mEfiShellProtocol = NULL;\r
239 mEfiShellParametersProtocol = NULL;\r
240 mEfiShellInterface = NULL;\r
241 mEfiShellEnvironment2Handle = NULL;\r
242\r
d2b4564b 243 //\r
244 // verify that auto initialize is not set false\r
245 // \r
246 if (PcdGetBool(PcdShellLibAutoInitialize) == 0) {\r
247 return (EFI_SUCCESS);\r
248 }\r
249 \r
250 return (ShellLibConstructorWorker(ImageHandle, SystemTable));\r
251}\r
94b17fa1 252\r
253/**\r
254 Destructory for the library. free any resources.\r
255**/\r
256EFI_STATUS\r
257EFIAPI\r
258ShellLibDestructor (\r
259 IN EFI_HANDLE ImageHandle,\r
260 IN EFI_SYSTEM_TABLE *SystemTable\r
261 )\r
262{\r
263 if (mEfiShellEnvironment2 != NULL) {\r
264 gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle,\r
265 &gEfiShellEnvironment2Guid,\r
266 ImageHandle,\r
267 NULL);\r
d2b4564b 268 mEfiShellEnvironment2 = NULL;\r
94b17fa1 269 }\r
270 if (mEfiShellInterface != NULL) {\r
271 gBS->CloseProtocol(ImageHandle,\r
272 &gEfiShellInterfaceGuid,\r
273 ImageHandle,\r
274 NULL); \r
d2b4564b 275 mEfiShellInterface = NULL;\r
94b17fa1 276 }\r
277 if (mEfiShellProtocol != NULL) {\r
278 gBS->CloseProtocol(ImageHandle,\r
279 &gEfiShellProtocolGuid,\r
280 ImageHandle,\r
d2b4564b 281 NULL); \r
282 mEfiShellProtocol = NULL;\r
94b17fa1 283 }\r
284 if (mEfiShellParametersProtocol != NULL) {\r
285 gBS->CloseProtocol(ImageHandle,\r
286 &gEfiShellParametersProtocolGuid,\r
287 ImageHandle,\r
288 NULL); \r
d2b4564b 289 mEfiShellParametersProtocol = NULL;\r
94b17fa1 290 }\r
d2b4564b 291 mEfiShellEnvironment2Handle = NULL;\r
94b17fa1 292 return (EFI_SUCCESS);\r
293}\r
d2b4564b 294\r
295/**\r
296 This function causes the shell library to initialize itself. If the shell library\r
297 is already initialized it will de-initialize all the current protocol poitners and\r
298 re-populate them again.\r
299\r
300 When the library is used with PcdShellLibAutoInitialize set to true this function\r
301 will return EFI_SUCCESS and perform no actions.\r
302\r
303 This function is intended for internal access for shell commands only.\r
304\r
305 @retval EFI_SUCCESS the initialization was complete sucessfully\r
306\r
307**/\r
308EFI_STATUS\r
309EFIAPI\r
310ShellInitialize (\r
311 ) {\r
312 //\r
313 // if auto initialize is not false then skip\r
314 //\r
315 if (PcdGetBool(PcdShellLibAutoInitialize) != 0) {\r
316 return (EFI_SUCCESS);\r
317 }\r
318\r
319 //\r
320 // deinit the current stuff\r
321 //\r
322 ASSERT_EFI_ERROR(ShellLibDestructor(gImageHandle, gST));\r
323\r
324 //\r
325 // init the new stuff\r
326 //\r
327 return (ShellLibConstructorWorker(gImageHandle, gST));\r
328}\r
329\r
94b17fa1 330/**\r
331 This function will retrieve the information about the file for the handle \r
332 specified and store it in allocated pool memory.\r
333\r
69817bf8 334 This function allocates a buffer to store the file's information. It is the \r
335 caller's responsibility to free the buffer\r
94b17fa1 336\r
337 @param FileHandle The file handle of the file for which information is \r
338 being requested.\r
339\r
340 @retval NULL information could not be retrieved.\r
341\r
342 @return the information about the file\r
343**/\r
344EFI_FILE_INFO*\r
345EFIAPI\r
346ShellGetFileInfo (\r
347 IN EFI_FILE_HANDLE FileHandle\r
348 )\r
349{\r
d2b4564b 350 return (FileFunctionMap.GetFileInfo(FileHandle));\r
94b17fa1 351}\r
352\r
353/**\r
354 This function will set the information about the file for the opened handle \r
355 specified.\r
356\r
357 @param FileHandle The file handle of the file for which information \r
358 is being set\r
359\r
360 @param FileInfo The infotmation to set.\r
361\r
362 @retval EFI_SUCCESS The information was set.\r
363 @retval EFI_UNSUPPORTED The InformationType is not known.\r
364 @retval EFI_NO_MEDIA The device has no medium.\r
365 @retval EFI_DEVICE_ERROR The device reported an error.\r
366 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
367 @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
368 @retval EFI_ACCESS_DENIED The file was opened read only.\r
369 @retval EFI_VOLUME_FULL The volume is full.\r
370**/\r
371EFI_STATUS\r
372EFIAPI\r
373ShellSetFileInfo (\r
374 IN EFI_FILE_HANDLE FileHandle,\r
375 IN EFI_FILE_INFO *FileInfo\r
376 )\r
377{\r
d2b4564b 378 return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo));\r
94b17fa1 379} \r
380 \r
381 /**\r
382 This function will open a file or directory referenced by DevicePath.\r
383\r
384 This function opens a file with the open mode according to the file path. The \r
385 Attributes is valid only for EFI_FILE_MODE_CREATE.\r
386\r
387 @param FilePath on input the device path to the file. On output \r
388 the remaining device path.\r
389 @param DeviceHandle pointer to the system device handle.\r
390 @param FileHandle pointer to the file handle.\r
391 @param OpenMode the mode to open the file with.\r
392 @param Attributes the file's file attributes.\r
393\r
394 @retval EFI_SUCCESS The information was set.\r
395 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
396 @retval EFI_UNSUPPORTED Could not open the file path. \r
397 @retval EFI_NOT_FOUND The specified file could not be found on the \r
398 device or the file system could not be found on \r
399 the device.\r
400 @retval EFI_NO_MEDIA The device has no medium.\r
401 @retval EFI_MEDIA_CHANGED The device has a different medium in it or the \r
402 medium is no longer supported.\r
403 @retval EFI_DEVICE_ERROR The device reported an error.\r
404 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
405 @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
406 @retval EFI_ACCESS_DENIED The file was opened read only.\r
407 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the \r
408 file.\r
409 @retval EFI_VOLUME_FULL The volume is full.\r
410**/\r
411EFI_STATUS\r
412EFIAPI\r
413ShellOpenFileByDevicePath(\r
414 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,\r
415 OUT EFI_HANDLE *DeviceHandle,\r
416 OUT EFI_FILE_HANDLE *FileHandle,\r
417 IN UINT64 OpenMode,\r
418 IN UINT64 Attributes\r
419 )\r
420{\r
421 CHAR16 *FileName;\r
422 EFI_STATUS Status;\r
423 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;\r
424 EFI_FILE_HANDLE LastHandle;\r
425\r
426 //\r
427 // ASERT for FileHandle, FilePath, and DeviceHandle being NULL\r
428 //\r
429 ASSERT(FilePath != NULL);\r
430 ASSERT(FileHandle != NULL);\r
431 ASSERT(DeviceHandle != NULL);\r
432 // \r
433 // which shell interface should we use\r
434 //\r
435 if (mEfiShellProtocol != NULL) {\r
436 //\r
437 // use UEFI Shell 2.0 method.\r
438 //\r
439 FileName = mEfiShellProtocol->GetFilePathFromDevicePath(*FilePath);\r
440 if (FileName == NULL) {\r
441 return (EFI_INVALID_PARAMETER);\r
442 }\r
443 Status = ShellOpenFileByName(FileName, FileHandle, OpenMode, Attributes);\r
444 FreePool(FileName);\r
445 return (Status);\r
d2b4564b 446 } \r
447\r
448\r
449 //\r
450 // use old shell method.\r
451 //\r
452 Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, \r
453 FilePath, \r
454 DeviceHandle);\r
455 if (EFI_ERROR (Status)) {\r
456 return Status;\r
457 }\r
458 Status = gBS->OpenProtocol(*DeviceHandle,\r
459 &gEfiSimpleFileSystemProtocolGuid,\r
b1f95a06 460 (VOID**)&EfiSimpleFileSystemProtocol,\r
d2b4564b 461 gImageHandle,\r
462 NULL,\r
463 EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
464 if (EFI_ERROR (Status)) {\r
465 return Status;\r
466 }\r
467 Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, FileHandle);\r
468 if (EFI_ERROR (Status)) {\r
469 FileHandle = NULL;\r
470 return Status;\r
471 }\r
472\r
473 //\r
474 // go down directories one node at a time.\r
475 //\r
476 while (!IsDevicePathEnd (*FilePath)) {\r
94b17fa1 477 //\r
d2b4564b 478 // For file system access each node should be a file path component\r
94b17fa1 479 //\r
d2b4564b 480 if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||\r
481 DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP\r
482 ) {\r
94b17fa1 483 FileHandle = NULL;\r
d2b4564b 484 return (EFI_INVALID_PARAMETER);\r
94b17fa1 485 }\r
d2b4564b 486 //\r
487 // Open this file path node\r
488 //\r
489 LastHandle = *FileHandle;\r
490 *FileHandle = NULL;\r
94b17fa1 491\r
492 //\r
d2b4564b 493 // Try to test opening an existing file\r
94b17fa1 494 //\r
d2b4564b 495 Status = LastHandle->Open (\r
496 LastHandle,\r
497 FileHandle,\r
498 ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
499 OpenMode &~EFI_FILE_MODE_CREATE,\r
500 0\r
501 );\r
94b17fa1 502\r
d2b4564b 503 //\r
504 // see if the error was that it needs to be created\r
505 //\r
506 if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {\r
94b17fa1 507 Status = LastHandle->Open (\r
508 LastHandle,\r
509 FileHandle,\r
510 ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
d2b4564b 511 OpenMode,\r
512 Attributes\r
94b17fa1 513 );\r
d2b4564b 514 }\r
515 //\r
516 // Close the last node\r
517 //\r
518 LastHandle->Close (LastHandle);\r
94b17fa1 519\r
d2b4564b 520 if (EFI_ERROR(Status)) {\r
521 return (Status);\r
94b17fa1 522 }\r
d2b4564b 523\r
524 //\r
525 // Get the next node\r
526 //\r
527 *FilePath = NextDevicePathNode (*FilePath);\r
94b17fa1 528 }\r
d2b4564b 529 return (EFI_SUCCESS);\r
94b17fa1 530}\r
531\r
532/**\r
533 This function will open a file or directory referenced by filename.\r
534\r
69817bf8 535 If return is EFI_SUCCESS, the Filehandle is the opened file's handle; \r
94b17fa1 536 otherwise, the Filehandle is NULL. The Attributes is valid only for \r
537 EFI_FILE_MODE_CREATE.\r
538\r
539 if FileNAme is NULL then ASSERT()\r
540\r
541 @param FileName pointer to file name\r
542 @param FileHandle pointer to the file handle.\r
543 @param OpenMode the mode to open the file with.\r
544 @param Attributes the file's file attributes.\r
545\r
546 @retval EFI_SUCCESS The information was set.\r
547 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
548 @retval EFI_UNSUPPORTED Could not open the file path. \r
549 @retval EFI_NOT_FOUND The specified file could not be found on the \r
550 device or the file system could not be found \r
551 on the device.\r
552 @retval EFI_NO_MEDIA The device has no medium.\r
553 @retval EFI_MEDIA_CHANGED The device has a different medium in it or the \r
554 medium is no longer supported.\r
555 @retval EFI_DEVICE_ERROR The device reported an error.\r
556 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
557 @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
558 @retval EFI_ACCESS_DENIED The file was opened read only.\r
559 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the \r
560 file.\r
561 @retval EFI_VOLUME_FULL The volume is full.\r
562**/\r
563EFI_STATUS\r
564EFIAPI\r
565ShellOpenFileByName(\r
566 IN CHAR16 *FileName,\r
567 OUT EFI_FILE_HANDLE *FileHandle,\r
568 IN UINT64 OpenMode,\r
569 IN UINT64 Attributes\r
570 )\r
571{\r
572 EFI_HANDLE DeviceHandle;\r
573 EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
b1f95a06 574 EFI_STATUS Status;\r
575 EFI_FILE_INFO *FileInfo;\r
94b17fa1 576\r
577 //\r
578 // ASSERT if FileName is NULL\r
579 //\r
580 ASSERT(FileName != NULL);\r
581\r
582 if (mEfiShellProtocol != NULL) {\r
583 //\r
584 // Use UEFI Shell 2.0 method\r
585 //\r
b1f95a06 586 Status = mEfiShellProtocol->OpenFileByName(FileName,\r
587 FileHandle,\r
588 OpenMode);\r
589 if (!EFI_ERROR(Status)){\r
590 FileInfo = FileHandleGetInfo(*FileHandle);\r
591 ASSERT(FileInfo != NULL);\r
592 FileInfo->Attribute = Attributes;\r
593 Status = FileHandleSetInfo(*FileHandle, FileInfo);\r
594 }\r
595 return (Status);\r
94b17fa1 596 } \r
597 //\r
598 // Using EFI Shell version\r
599 // this means convert name to path and call that function\r
600 // since this will use EFI method again that will open it.\r
601 //\r
602 ASSERT(mEfiShellEnvironment2 != NULL);\r
603 FilePath = mEfiShellEnvironment2->NameToPath (FileName);\r
604 if (FileDevicePath != NULL) {\r
605 return (ShellOpenFileByDevicePath(&FilePath,\r
606 &DeviceHandle,\r
607 FileHandle,\r
608 OpenMode,\r
609 Attributes ));\r
610 }\r
611 return (EFI_DEVICE_ERROR);\r
612}\r
613/**\r
614 This function create a directory\r
615\r
616 If return is EFI_SUCCESS, the Filehandle is the opened directory's handle; \r
617 otherwise, the Filehandle is NULL. If the directory already existed, this \r
618 function opens the existing directory.\r
619\r
620 @param DirectoryName pointer to directory name\r
621 @param FileHandle pointer to the file handle.\r
622\r
623 @retval EFI_SUCCESS The information was set.\r
624 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
625 @retval EFI_UNSUPPORTED Could not open the file path. \r
626 @retval EFI_NOT_FOUND The specified file could not be found on the \r
627 device or the file system could not be found \r
628 on the device.\r
629 @retval EFI_NO_MEDIA The device has no medium.\r
630 @retval EFI_MEDIA_CHANGED The device has a different medium in it or the \r
631 medium is no longer supported.\r
632 @retval EFI_DEVICE_ERROR The device reported an error.\r
633 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
634 @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
635 @retval EFI_ACCESS_DENIED The file was opened read only.\r
636 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the \r
637 file.\r
638 @retval EFI_VOLUME_FULL The volume is full.\r
639 @sa ShellOpenFileByName\r
640**/\r
641EFI_STATUS\r
642EFIAPI\r
643ShellCreateDirectory(\r
644 IN CHAR16 *DirectoryName,\r
645 OUT EFI_FILE_HANDLE *FileHandle\r
646 )\r
647{\r
648 //\r
649 // this is a pass thru to the open file function with sepcific open mode and attributes\r
650 //\r
651 return (ShellOpenFileByName(DirectoryName,\r
652 FileHandle,\r
653 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,\r
654 EFI_FILE_DIRECTORY\r
655 ));\r
656}\r
657\r
658/**\r
659 This function reads information from an opened file.\r
660\r
661 If FileHandle is not a directory, the function reads the requested number of \r
69817bf8 662 bytes from the file at the file's current position and returns them in Buffer. \r
94b17fa1 663 If the read goes beyond the end of the file, the read length is truncated to the\r
69817bf8 664 end of the file. The file's current position is increased by the number of bytes \r
94b17fa1 665 returned. If FileHandle is a directory, the function reads the directory entry \r
69817bf8 666 at the file's current position and returns the entry in Buffer. If the Buffer \r
94b17fa1 667 is not large enough to hold the current directory entry, then \r
668 EFI_BUFFER_TOO_SMALL is returned and the current file position is not updated. \r
669 BufferSize is set to be the size of the buffer needed to read the entry. On \r
670 success, the current position is updated to the next directory entry. If there \r
671 are no more directory entries, the read returns a zero-length buffer. \r
672 EFI_FILE_INFO is the structure returned as the directory entry.\r
673\r
674 @param FileHandle the opened file handle\r
675 @param BufferSize on input the size of buffer in bytes. on return \r
676 the number of bytes written.\r
677 @param Buffer the buffer to put read data into.\r
678\r
679 @retval EFI_SUCCESS Data was read.\r
680 @retval EFI_NO_MEDIA The device has no media.\r
681 @retval EFI_DEVICE_ERROR The device reported an error.\r
682 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
683 @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required \r
684 size.\r
685\r
686**/\r
687EFI_STATUS\r
688EFIAPI\r
689ShellReadFile(\r
690 IN EFI_FILE_HANDLE FileHandle,\r
691 IN OUT UINTN *BufferSize,\r
692 OUT VOID *Buffer\r
693 )\r
694{\r
d2b4564b 695 return (FileFunctionMap.ReadFile(FileHandle, BufferSize, Buffer));\r
94b17fa1 696}\r
697\r
698\r
699/**\r
700 Write data to a file.\r
701\r
702 This function writes the specified number of bytes to the file at the current \r
703 file position. The current file position is advanced the actual number of bytes \r
704 written, which is returned in BufferSize. Partial writes only occur when there \r
69817bf8 705 has been a data error during the write attempt (such as "volume space full"). \r
94b17fa1 706 The file is automatically grown to hold the data if required. Direct writes to \r
707 opened directories are not supported.\r
708\r
709 @param FileHandle The opened file for writing\r
710 @param BufferSize on input the number of bytes in Buffer. On output\r
711 the number of bytes written.\r
712 @param Buffer the buffer containing data to write is stored.\r
713\r
714 @retval EFI_SUCCESS Data was written.\r
715 @retval EFI_UNSUPPORTED Writes to an open directory are not supported.\r
716 @retval EFI_NO_MEDIA The device has no media.\r
717 @retval EFI_DEVICE_ERROR The device reported an error.\r
718 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
719 @retval EFI_WRITE_PROTECTED The device is write-protected.\r
720 @retval EFI_ACCESS_DENIED The file was open for read only.\r
721 @retval EFI_VOLUME_FULL The volume is full.\r
722**/\r
723EFI_STATUS\r
724EFIAPI\r
725ShellWriteFile(\r
726 IN EFI_FILE_HANDLE FileHandle,\r
727 IN OUT UINTN *BufferSize,\r
728 IN VOID *Buffer\r
729 )\r
730{\r
d2b4564b 731 return (FileFunctionMap.WriteFile(FileHandle, BufferSize, Buffer));\r
94b17fa1 732}\r
733\r
734/** \r
735 Close an open file handle.\r
736\r
69817bf8 737 This function closes a specified file handle. All "dirty" cached file data is \r
94b17fa1 738 flushed to the device, and the file is closed. In all cases the handle is \r
739 closed.\r
740\r
741@param FileHandle the file handle to close.\r
742\r
743@retval EFI_SUCCESS the file handle was closed sucessfully.\r
744**/\r
745EFI_STATUS\r
746EFIAPI\r
747ShellCloseFile (\r
748 IN EFI_FILE_HANDLE *FileHandle\r
749 )\r
750{\r
d2b4564b 751 return (FileFunctionMap.CloseFile(*FileHandle));\r
94b17fa1 752}\r
753\r
754/**\r
755 Delete a file and close the handle\r
756\r
757 This function closes and deletes a file. In all cases the file handle is closed.\r
758 If the file cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is \r
759 returned, but the handle is still closed.\r
760\r
761 @param FileHandle the file handle to delete\r
762\r
763 @retval EFI_SUCCESS the file was closed sucessfully\r
764 @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not \r
765 deleted\r
766 @retval INVALID_PARAMETER One of the parameters has an invalid value.\r
767**/\r
768EFI_STATUS\r
769EFIAPI\r
770ShellDeleteFile (\r
771 IN EFI_FILE_HANDLE *FileHandle\r
772 )\r
773{\r
d2b4564b 774 return (FileFunctionMap.DeleteFile(*FileHandle));\r
94b17fa1 775}\r
776\r
777/**\r
778 Set the current position in a file.\r
779\r
780 This function sets the current file position for the handle to the position \r
781 supplied. With the exception of seeking to position 0xFFFFFFFFFFFFFFFF, only\r
782 absolute positioning is supported, and seeking past the end of the file is \r
783 allowed (a subsequent write would grow the file). Seeking to position \r
784 0xFFFFFFFFFFFFFFFF causes the current position to be set to the end of the file.\r
785 If FileHandle is a directory, the only position that may be set is zero. This \r
786 has the effect of starting the read process of the directory entries over.\r
787\r
788 @param FileHandle The file handle on which the position is being set\r
789 @param Position Byte position from begining of file\r
790\r
791 @retval EFI_SUCCESS Operation completed sucessfully.\r
792 @retval EFI_UNSUPPORTED the seek request for non-zero is not valid on \r
793 directories.\r
794 @retval INVALID_PARAMETER One of the parameters has an invalid value.\r
795**/\r
796EFI_STATUS\r
797EFIAPI\r
798ShellSetFilePosition (\r
799 IN EFI_FILE_HANDLE FileHandle,\r
800 IN UINT64 Position\r
801 )\r
802{\r
d2b4564b 803 return (FileFunctionMap.SetFilePosition(FileHandle, Position));\r
94b17fa1 804}\r
805\r
806/** \r
807 Gets a file's current position\r
808\r
809 This function retrieves the current file position for the file handle. For \r
810 directories, the current file position has no meaning outside of the file \r
811 system driver and as such the operation is not supported. An error is returned\r
812 if FileHandle is a directory.\r
813\r
814 @param FileHandle The open file handle on which to get the position.\r
815 @param Position Byte position from begining of file.\r
816\r
817 @retval EFI_SUCCESS the operation completed sucessfully.\r
818 @retval INVALID_PARAMETER One of the parameters has an invalid value.\r
819 @retval EFI_UNSUPPORTED the request is not valid on directories.\r
820**/\r
821EFI_STATUS\r
822EFIAPI\r
823ShellGetFilePosition (\r
824 IN EFI_FILE_HANDLE FileHandle,\r
825 OUT UINT64 *Position\r
826 )\r
827{\r
d2b4564b 828 return (FileFunctionMap.GetFilePosition(FileHandle, Position));\r
94b17fa1 829}\r
830/**\r
831 Flushes data on a file\r
832 \r
833 This function flushes all modified data associated with a file to a device.\r
834\r
835 @param FileHandle The file handle on which to flush data\r
836\r
837 @retval EFI_SUCCESS The data was flushed.\r
838 @retval EFI_NO_MEDIA The device has no media.\r
839 @retval EFI_DEVICE_ERROR The device reported an error.\r
840 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
841 @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
842 @retval EFI_ACCESS_DENIED The file was opened for read only.\r
843**/\r
844EFI_STATUS\r
845EFIAPI\r
846ShellFlushFile (\r
847 IN EFI_FILE_HANDLE FileHandle\r
848 )\r
849{\r
d2b4564b 850 return (FileFunctionMap.FlushFile(FileHandle));\r
94b17fa1 851}\r
852\r
853/**\r
854 Retrieves the first file from a directory\r
855\r
69817bf8 856 This function opens a directory and gets the first file's info in the \r
94b17fa1 857 directory. Caller can use ShellFindNextFile() to get other files. When \r
858 complete the caller is responsible for calling FreePool() on Buffer.\r
859\r
860 @param DirHandle The file handle of the directory to search\r
861 @param Buffer Pointer to buffer for file's information\r
862\r
863 @retval EFI_SUCCESS Found the first file.\r
864 @retval EFI_NOT_FOUND Cannot find the directory.\r
865 @retval EFI_NO_MEDIA The device has no media.\r
866 @retval EFI_DEVICE_ERROR The device reported an error.\r
867 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
868 @return Others status of ShellGetFileInfo, ShellSetFilePosition,\r
869 or ShellReadFile\r
870**/\r
871EFI_STATUS\r
872EFIAPI\r
873ShellFindFirstFile (\r
874 IN EFI_FILE_HANDLE DirHandle,\r
d2b4564b 875 OUT EFI_FILE_INFO **Buffer\r
94b17fa1 876 )\r
877{\r
94b17fa1 878 //\r
d2b4564b 879 // pass to file handle lib\r
94b17fa1 880 //\r
d2b4564b 881 return (FileHandleFindFirstFile(DirHandle, Buffer));\r
94b17fa1 882}\r
883/**\r
884 Retrieves the next file in a directory.\r
885\r
886 To use this function, caller must call the LibFindFirstFile() to get the \r
887 first file, and then use this function get other files. This function can be \r
888 called for several times to get each file's information in the directory. If \r
889 the call of ShellFindNextFile() got the last file in the directory, the next \r
890 call of this function has no file to get. *NoFile will be set to TRUE and the \r
891 Buffer memory will be automatically freed. \r
892\r
893 @param DirHandle the file handle of the directory\r
894 @param Buffer pointer to buffer for file's information\r
895 @param NoFile pointer to boolean when last file is found\r
896\r
897 @retval EFI_SUCCESS Found the next file, or reached last file\r
898 @retval EFI_NO_MEDIA The device has no media.\r
899 @retval EFI_DEVICE_ERROR The device reported an error.\r
900 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
901**/\r
902EFI_STATUS\r
903EFIAPI\r
904ShellFindNextFile(\r
905 IN EFI_FILE_HANDLE DirHandle,\r
906 OUT EFI_FILE_INFO *Buffer,\r
907 OUT BOOLEAN *NoFile\r
908 )\r
909{\r
94b17fa1 910 //\r
d2b4564b 911 // pass to file handle lib\r
94b17fa1 912 //\r
d2b4564b 913 return (FileHandleFindNextFile(DirHandle, Buffer, NoFile));\r
94b17fa1 914}\r
915/**\r
916 Retrieve the size of a file.\r
917\r
918 if FileHandle is NULL then ASSERT()\r
919 if Size is NULL then ASSERT()\r
920\r
69817bf8 921 This function extracts the file size info from the FileHandle's EFI_FILE_INFO \r
94b17fa1 922 data.\r
923\r
924 @param FileHandle file handle from which size is retrieved\r
925 @param Size pointer to size\r
926\r
927 @retval EFI_SUCCESS operation was completed sucessfully\r
928 @retval EFI_DEVICE_ERROR cannot access the file\r
929**/\r
930EFI_STATUS\r
931EFIAPI\r
932ShellGetFileSize (\r
933 IN EFI_FILE_HANDLE FileHandle,\r
934 OUT UINT64 *Size\r
935 )\r
936{\r
d2b4564b 937 return (FileFunctionMap.GetFileSize(FileHandle, Size));\r
94b17fa1 938}\r
939/**\r
940 Retrieves the status of the break execution flag\r
941\r
942 this function is useful to check whether the application is being asked to halt by the shell.\r
943\r
944 @retval TRUE the execution break is enabled\r
945 @retval FALSE the execution break is not enabled\r
946**/\r
947BOOLEAN\r
948EFIAPI\r
949ShellGetExecutionBreakFlag(\r
950 VOID\r
951 )\r
952{\r
953 // \r
954 // Check for UEFI Shell 2.0 protocols\r
955 //\r
956 if (mEfiShellProtocol != NULL) {\r
957\r
958 //\r
959 // We are using UEFI Shell 2.0; see if the event has been triggered\r
960 //\r
961 if (gBS->CheckEvent(mEfiShellProtocol->ExecutionBreak) != EFI_SUCCESS) {\r
962 return (FALSE);\r
963 }\r
964 return (TRUE);\r
965 } \r
966\r
967 //\r
968 // using EFI Shell; call the function to check\r
969 //\r
970 ASSERT(mEfiShellEnvironment2 != NULL);\r
971 return (mEfiShellEnvironment2->GetExecutionBreak());\r
972}\r
973/**\r
974 return the value of an environment variable\r
975\r
976 this function gets the value of the environment variable set by the \r
977 ShellSetEnvironmentVariable function\r
978\r
979 @param EnvKey The key name of the environment variable.\r
980\r
981 @retval NULL the named environment variable does not exist.\r
982 @return != NULL pointer to the value of the environment variable\r
983**/\r
984CONST CHAR16*\r
985EFIAPI\r
986ShellGetEnvironmentVariable (\r
987 IN CHAR16 *EnvKey\r
988 )\r
989{\r
990 // \r
991 // Check for UEFI Shell 2.0 protocols\r
992 //\r
993 if (mEfiShellProtocol != NULL) {\r
994 return (mEfiShellProtocol->GetEnv(EnvKey));\r
995 }\r
996\r
997 //\r
998 // ASSERT that we must have EFI shell\r
999 //\r
1000 ASSERT(mEfiShellEnvironment2 != NULL);\r
1001\r
1002 //\r
1003 // using EFI Shell\r
1004 //\r
1005 return (mEfiShellEnvironment2->GetEnv(EnvKey));\r
1006}\r
1007/**\r
1008 set the value of an environment variable\r
1009\r
1010This function changes the current value of the specified environment variable. If the\r
1011environment variable exists and the Value is an empty string, then the environment\r
1012variable is deleted. If the environment variable exists and the Value is not an empty\r
1013string, then the value of the environment variable is changed. If the environment\r
1014variable does not exist and the Value is an empty string, there is no action. If the\r
1015environment variable does not exist and the Value is a non-empty string, then the\r
1016environment variable is created and assigned the specified value.\r
1017\r
1018 This is not supported pre-UEFI Shell 2.0.\r
1019\r
1020 @param EnvKey The key name of the environment variable.\r
1021 @param EnvVal The Value of the environment variable\r
1022 @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE).\r
1023\r
1024 @retval EFI_SUCCESS the operation was completed sucessfully\r
1025 @retval EFI_UNSUPPORTED This operation is not allowed in pre UEFI 2.0 Shell environments\r
1026**/\r
1027EFI_STATUS\r
1028EFIAPI\r
1029ShellSetEnvironmentVariable (\r
1030 IN CONST CHAR16 *EnvKey,\r
1031 IN CONST CHAR16 *EnvVal,\r
1032 IN BOOLEAN Volatile\r
1033 )\r
1034{\r
1035 // \r
1036 // Check for UEFI Shell 2.0 protocols\r
1037 //\r
1038 if (mEfiShellProtocol != NULL) {\r
1039 return (mEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile));\r
1040 } \r
1041\r
1042 //\r
1043 // This feature does not exist under EFI shell\r
1044 //\r
1045 return (EFI_UNSUPPORTED);\r
1046}\r
1047/**\r
1048 cause the shell to parse and execute a command line.\r
1049\r
1050 This function creates a nested instance of the shell and executes the specified\r
1051command (CommandLine) with the specified environment (Environment). Upon return,\r
1052the status code returned by the specified command is placed in StatusCode.\r
1053If Environment is NULL, then the current environment is used and all changes made\r
1054by the commands executed will be reflected in the current environment. If the\r
1055Environment is non-NULL, then the changes made will be discarded.\r
1056The CommandLine is executed from the current working directory on the current\r
1057device.\r
1058\r
1059EnvironmentVariables and Status are only supported for UEFI Shell 2.0.\r
1060Output is only supported for pre-UEFI Shell 2.0\r
1061\r
1062 @param ImageHandle Parent image that is starting the operation\r
1063 @param CommandLine pointer to null terminated command line.\r
1064 @param Output true to display debug output. false to hide it.\r
1065 @param EnvironmentVariables optional pointer to array of environment variables\r
1066 in the form "x=y". if NULL current set is used.\r
1067 @param Status the status of the run command line.\r
1068\r
1069 @retval EFI_SUCCESS the operation completed sucessfully. Status\r
1070 contains the status code returned.\r
1071 @retval EFI_INVALID_PARAMETER a parameter contains an invalid value\r
1072 @retval EFI_OUT_OF_RESOURCES out of resources\r
1073 @retval EFI_UNSUPPORTED the operation is not allowed.\r
1074**/\r
1075EFI_STATUS\r
1076EFIAPI\r
1077ShellExecute (\r
1078 IN EFI_HANDLE *ParentHandle,\r
1079 IN CHAR16 *CommandLine OPTIONAL,\r
1080 IN BOOLEAN Output OPTIONAL,\r
1081 IN CHAR16 **EnvironmentVariables OPTIONAL,\r
1082 OUT EFI_STATUS *Status OPTIONAL\r
1083 )\r
1084{\r
1085 // \r
1086 // Check for UEFI Shell 2.0 protocols\r
1087 //\r
1088 if (mEfiShellProtocol != NULL) {\r
1089 //\r
1090 // Call UEFI Shell 2.0 version (not using Output parameter)\r
1091 //\r
1092 return (mEfiShellProtocol->Execute(ParentHandle,\r
1093 CommandLine,\r
1094 EnvironmentVariables,\r
1095 Status));\r
1096 } \r
1097 //\r
1098 // ASSERT that we must have EFI shell\r
1099 //\r
1100 ASSERT(mEfiShellEnvironment2 != NULL);\r
1101 //\r
1102 // Call EFI Shell version (not using EnvironmentVariables or Status parameters)\r
1103 // Due to oddity in the EFI shell we want to dereference the ParentHandle here\r
1104 //\r
1105 return (mEfiShellEnvironment2->Execute(*ParentHandle, \r
1106 CommandLine, \r
1107 Output));\r
1108}\r
1109/**\r
1110 Retreives the current directory path\r
1111\r
69817bf8 1112 If the DeviceName is NULL, it returns the current device's current directory \r
94b17fa1 1113 name. If the DeviceName is not NULL, it returns the current directory name \r
1114 on specified drive.\r
1115\r
1116 @param DeviceName the name of the drive to get directory on\r
1117\r
1118 @retval NULL the directory does not exist\r
1119 @return != NULL the directory\r
1120**/\r
1121CONST CHAR16*\r
1122EFIAPI\r
1123ShellGetCurrentDir (\r
1124 IN CHAR16 *DeviceName OPTIONAL\r
1125 )\r
1126{\r
1127 // \r
1128 // Check for UEFI Shell 2.0 protocols\r
1129 //\r
1130 if (mEfiShellProtocol != NULL) {\r
1131 return (mEfiShellProtocol->GetCurDir(DeviceName));\r
1132 } \r
1133 //\r
1134 // ASSERT that we must have EFI shell\r
1135 //\r
1136 ASSERT(mEfiShellEnvironment2 != NULL);\r
1137 return (mEfiShellEnvironment2->CurDir(DeviceName));\r
1138}\r
1139/**\r
1140 sets (enabled or disabled) the page break mode\r
1141\r
1142 when page break mode is enabled the screen will stop scrolling \r
1143 and wait for operator input before scrolling a subsequent screen.\r
1144\r
1145 @param CurrentState TRUE to enable and FALSE to disable\r
1146**/\r
1147VOID \r
1148EFIAPI\r
1149ShellSetPageBreakMode (\r
1150 IN BOOLEAN CurrentState\r
1151 )\r
1152{\r
1153 //\r
1154 // check for enabling\r
1155 //\r
1156 if (CurrentState != 0x00) {\r
1157 // \r
1158 // check for UEFI Shell 2.0\r
1159 //\r
1160 if (mEfiShellProtocol != NULL) {\r
1161 //\r
1162 // Enable with UEFI 2.0 Shell\r
1163 //\r
1164 mEfiShellProtocol->EnablePageBreak();\r
1165 return;\r
1166 } else {\r
1167 // \r
1168 // ASSERT that must have EFI Shell\r
1169 //\r
1170 ASSERT(mEfiShellEnvironment2 != NULL);\r
1171 //\r
1172 // Enable with EFI Shell\r
1173 //\r
1174 mEfiShellEnvironment2->EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);\r
1175 return;\r
1176 }\r
1177 } else {\r
1178 // \r
1179 // check for UEFI Shell 2.0\r
1180 //\r
1181 if (mEfiShellProtocol != NULL) {\r
1182 //\r
1183 // Disable with UEFI 2.0 Shell\r
1184 //\r
1185 mEfiShellProtocol->DisablePageBreak();\r
1186 return;\r
1187 } else {\r
1188 // \r
1189 // ASSERT that must have EFI Shell\r
1190 //\r
1191 ASSERT(mEfiShellEnvironment2 != NULL);\r
1192 //\r
1193 // Disable with EFI Shell\r
1194 //\r
1195 mEfiShellEnvironment2->DisablePageBreak ();\r
1196 return;\r
1197 }\r
1198 }\r
1199}\r
1200\r
1201///\r
1202/// version of EFI_SHELL_FILE_INFO struct, except has no CONST pointers.\r
1203/// This allows for the struct to be populated.\r
1204///\r
1205typedef struct {\r
d2b4564b 1206 LIST_ENTRY Link;\r
94b17fa1 1207 EFI_STATUS Status;\r
1208 CHAR16 *FullName;\r
1209 CHAR16 *FileName;\r
1210 EFI_FILE_HANDLE Handle;\r
1211 EFI_FILE_INFO *Info;\r
1212} EFI_SHELL_FILE_INFO_NO_CONST;\r
1213\r
1214/**\r
1215 Converts a EFI shell list of structures to the coresponding UEFI Shell 2.0 type of list.\r
1216\r
1217 if OldStyleFileList is NULL then ASSERT()\r
1218\r
1219 this function will convert a SHELL_FILE_ARG based list into a callee allocated \r
1220 EFI_SHELL_FILE_INFO based list. it is up to the caller to free the memory via\r
1221 the ShellCloseFileMetaArg function.\r
1222\r
1223 @param FileList the EFI shell list type\r
1224\r
1225 @retval the resultant head of the double linked new format list;\r
1226**/\r
1227LIST_ENTRY*\r
1228EFIAPI\r
1229InternalShellConvertFileListType (\r
d2b4564b 1230 LIST_ENTRY *FileList\r
94b17fa1 1231 )\r
1232{\r
1233 LIST_ENTRY *ListHead;\r
1234 SHELL_FILE_ARG *OldInfo;\r
d2b4564b 1235 LIST_ENTRY *Link;\r
94b17fa1 1236 EFI_SHELL_FILE_INFO_NO_CONST *NewInfo;\r
1237\r
1238 //\r
1239 // ASSERT that FileList is not NULL\r
1240 //\r
1241 ASSERT(FileList != NULL);\r
1242\r
1243 //\r
1244 // Allocate our list head and initialize the list\r
1245 //\r
d2b4564b 1246 ListHead = AllocateZeroPool(sizeof(LIST_ENTRY));\r
94b17fa1 1247 ASSERT (ListHead != NULL);\r
1248 ListHead = InitializeListHead (ListHead);\r
1249\r
1250 //\r
1251 // enumerate through each member of the old list and copy\r
1252 //\r
d2b4564b 1253 for (Link = FileList->ForwardLink; Link != FileList; Link = Link->ForwardLink) {\r
94b17fa1 1254 OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);\r
1255\r
1256 //\r
1257 // make sure the old list was valid\r
1258 //\r
1259 ASSERT(OldInfo != NULL); \r
1260 ASSERT(OldInfo->Info != NULL);\r
1261 ASSERT(OldInfo->FullName != NULL);\r
1262 ASSERT(OldInfo->FileName != NULL);\r
1263\r
1264 //\r
1265 // allocate a new EFI_SHELL_FILE_INFO object\r
1266 //\r
1267 NewInfo = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
1268 \r
1269 // \r
1270 // copy the simple items\r
1271 //\r
1272 NewInfo->Handle = OldInfo->Handle;\r
1273 NewInfo->Status = OldInfo->Status;\r
1274\r
d2b4564b 1275 // old shell checks for 0 not NULL\r
1276 OldInfo->Handle = 0;\r
1277\r
94b17fa1 1278 //\r
1279 // allocate new space to copy strings and structure\r
1280 //\r
1281 NewInfo->FullName = AllocateZeroPool(StrSize(OldInfo->FullName));\r
1282 NewInfo->FileName = AllocateZeroPool(StrSize(OldInfo->FileName));\r
1283 NewInfo->Info = AllocateZeroPool((UINTN)OldInfo->Info->Size);\r
1284 \r
1285 //\r
1286 // make sure all the memory allocations were sucessful\r
1287 //\r
1288 ASSERT(NewInfo->FullName != NULL);\r
1289 ASSERT(NewInfo->FileName != NULL);\r
1290 ASSERT(NewInfo->Info != NULL);\r
1291\r
1292 //\r
1293 // Copt the strings and structure\r
1294 //\r
1295 StrCpy(NewInfo->FullName, OldInfo->FullName);\r
1296 StrCpy(NewInfo->FileName, OldInfo->FileName);\r
1297 gBS->CopyMem (NewInfo->Info, OldInfo->Info, (UINTN)OldInfo->Info->Size);\r
1298\r
1299 //\r
1300 // add that to the list\r
1301 //\r
1302 InsertTailList(ListHead, (LIST_ENTRY*)NewInfo);\r
1303 }\r
1304 return (ListHead);\r
1305}\r
1306/**\r
1307 Opens a group of files based on a path.\r
1308\r
1309 This function uses the Arg to open all the matching files. Each matched \r
1310 file has a SHELL_FILE_ARG structure to record the file information. These \r
1311 structures are placed on the list ListHead. Users can get the SHELL_FILE_ARG \r
1312 structures from ListHead to access each file. This function supports wildcards\r
1313 and will process '?' and '*' as such. the list must be freed with a call to \r
1314 ShellCloseFileMetaArg().\r
1315\r
1316 This function will fail if called sequentially without freeing the list in the middle.\r
1317\r
1318 @param Arg pointer to path string\r
1319 @param OpenMode mode to open files with\r
1320 @param ListHead head of linked list of results\r
1321\r
1322 @retval EFI_SUCCESS the operation was sucessful and the list head \r
1323 contains the list of opened files\r
1324 #retval EFI_UNSUPPORTED a previous ShellOpenFileMetaArg must be closed first.\r
1325 *ListHead is set to NULL.\r
1326 @return != EFI_SUCCESS the operation failed\r
1327\r
1328 @sa InternalShellConvertFileListType\r
1329**/\r
1330EFI_STATUS\r
1331EFIAPI\r
1332ShellOpenFileMetaArg (\r
1333 IN CHAR16 *Arg,\r
1334 IN UINT64 OpenMode,\r
1335 IN OUT EFI_SHELL_FILE_INFO **ListHead\r
1336 )\r
1337{\r
1338 EFI_STATUS Status;\r
1339 LIST_ENTRY *EmptyNode;\r
d2b4564b 1340 LIST_ENTRY *mOldStyleFileList;\r
1341 \r
94b17fa1 1342 //\r
1343 // ASSERT that Arg and ListHead are not NULL\r
1344 //\r
1345 ASSERT(Arg != NULL);\r
1346 ASSERT(ListHead != NULL);\r
1347\r
1348 // \r
1349 // Check for UEFI Shell 2.0 protocols\r
1350 //\r
1351 if (mEfiShellProtocol != NULL) {\r
1352 return (mEfiShellProtocol->OpenFileList(Arg, \r
1353 OpenMode, \r
1354 ListHead));\r
1355 } \r
1356\r
1357 //\r
1358 // ASSERT that we must have EFI shell\r
1359 //\r
1360 ASSERT(mEfiShellEnvironment2 != NULL);\r
1361\r
1362 //\r
1363 // allocate memory for old list head\r
1364 //\r
d2b4564b 1365 mOldStyleFileList = (LIST_ENTRY*)AllocatePool(sizeof(LIST_ENTRY));\r
94b17fa1 1366 ASSERT(mOldStyleFileList != NULL);\r
1367\r
1368 //\r
1369 // make sure the list head is initialized\r
1370 //\r
1371 InitializeListHead((LIST_ENTRY*)mOldStyleFileList);\r
1372\r
1373 //\r
1374 // Get the EFI Shell list of files\r
1375 //\r
1376 Status = mEfiShellEnvironment2->FileMetaArg(Arg, mOldStyleFileList);\r
1377 if (EFI_ERROR(Status)) {\r
1378 *ListHead = NULL;\r
1379 return (Status);\r
1380 }\r
1381\r
1382 //\r
1383 // Convert that to equivalent of UEFI Shell 2.0 structure\r
1384 //\r
1385 EmptyNode = InternalShellConvertFileListType(mOldStyleFileList);\r
1386\r
d2b4564b 1387 //\r
1388 // Free the EFI Shell version that was converted.\r
1389 //\r
1390 ASSERT_EFI_ERROR(mEfiShellEnvironment2->FreeFileList(mOldStyleFileList));\r
1391 FreePool(mOldStyleFileList);\r
1392 mOldStyleFileList = NULL;\r
1393\r
94b17fa1 1394 //\r
1395 // remove the empty head of the list\r
1396 //\r
1397 *ListHead = (EFI_SHELL_FILE_INFO*)RemoveEntryList(EmptyNode);\r
1398 FreePool(EmptyNode); \r
1399\r
1400 return (Status);\r
1401}\r
1402/**\r
1403 Free the linked list returned from ShellOpenFileMetaArg\r
1404\r
1405 if ListHead is NULL then ASSERT()\r
1406\r
1407 @param ListHead the pointer to free\r
1408\r
1409 @retval EFI_SUCCESS the operation was sucessful\r
1410**/\r
1411EFI_STATUS\r
1412EFIAPI\r
1413ShellCloseFileMetaArg (\r
1414 IN OUT EFI_SHELL_FILE_INFO **ListHead\r
1415 )\r
1416{\r
1417 LIST_ENTRY *Node;\r
1418\r
1419 //\r
1420 // ASSERT that ListHead is not NULL\r
1421 //\r
1422 ASSERT(ListHead != NULL);\r
1423\r
1424 // \r
1425 // Check for UEFI Shell 2.0 protocols\r
1426 //\r
1427 if (mEfiShellProtocol != NULL) {\r
1428 return (mEfiShellProtocol->FreeFileList(ListHead));\r
1429 } else {\r
94b17fa1 1430 //\r
1431 // Since this is EFI Shell version we need to free our internally made copy \r
1432 // of the list\r
1433 //\r
1434 for (Node = GetFirstNode((LIST_ENTRY*)*ListHead) ; IsListEmpty((LIST_ENTRY*)*ListHead) == FALSE ; Node = GetFirstNode((LIST_ENTRY*)*ListHead)) {\r
1435 RemoveEntryList(Node);\r
d2b4564b 1436 ((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle);\r
94b17fa1 1437 FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FullName);\r
1438 FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FileName);\r
1439 FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Info);\r
1440 FreePool((EFI_SHELL_FILE_INFO_NO_CONST*)Node);\r
1441 }\r
1442 return EFI_SUCCESS;\r
1443 }\r
1444}\r
1445\r
1446typedef struct {\r
d2b4564b 1447 LIST_ENTRY List;\r
94b17fa1 1448 CHAR16 *Name;\r
1449 ParamType Type;\r
1450 CHAR16 *Value;\r
1451 UINTN OriginalPosition;\r
1452} SHELL_PARAM_PACKAGE;\r
1453\r
1454/**\r
1455 Checks the list of valid arguments and returns TRUE if the item was found. If the \r
1456 return value is TRUE then the type parameter is set also.\r
1457 \r
1458 if CheckList is NULL then ASSERT();\r
1459 if Name is NULL then ASSERT();\r
1460 if Type is NULL then ASSERT();\r
1461\r
1462 @param Type pointer to type of parameter if it was found\r
1463 @param Name pointer to Name of parameter found\r
1464 @param CheckList List to check against\r
1465\r
1466 @retval TRUE the Parameter was found. Type is valid.\r
1467 @retval FALSE the Parameter was not found. Type is not valid.\r
1468**/\r
1469BOOLEAN\r
1470EFIAPI\r
d2b4564b 1471InternalIsOnCheckList (\r
94b17fa1 1472 IN CONST CHAR16 *Name,\r
1473 IN CONST SHELL_PARAM_ITEM *CheckList,\r
1474 OUT ParamType *Type\r
1475 )\r
1476{\r
1477 SHELL_PARAM_ITEM *TempListItem;\r
1478\r
1479 //\r
1480 // ASSERT that all 3 pointer parameters aren't NULL\r
1481 //\r
1482 ASSERT(CheckList != NULL);\r
1483 ASSERT(Type != NULL);\r
1484 ASSERT(Name != NULL);\r
1485\r
d2b4564b 1486 //\r
1487 // question mark and page break mode are always supported\r
1488 //\r
1489 if ((StrCmp(Name, L"-?") == 0) ||\r
1490 (StrCmp(Name, L"-b") == 0)\r
1491 ) {\r
1492 return (TRUE);\r
1493 }\r
1494\r
94b17fa1 1495 //\r
1496 // Enumerate through the list\r
1497 //\r
1498 for (TempListItem = (SHELL_PARAM_ITEM*)CheckList ; TempListItem->Name != NULL ; TempListItem++) {\r
1499 //\r
1500 // If the Name matches set the type and return TRUE\r
1501 //\r
1502 if (StrCmp(Name, TempListItem->Name) == 0) {\r
1503 *Type = TempListItem->Type;\r
1504 return (TRUE);\r
1505 }\r
1506 }\r
1507 return (FALSE);\r
1508}\r
1509/**\r
d2b4564b 1510 Checks the string for indicators of "flag" status. this is a leading '/', '-', or '+'\r
94b17fa1 1511\r
1512 @param Name pointer to Name of parameter found\r
1513\r
1514 @retval TRUE the Parameter is a flag.\r
1515 @retval FALSE the Parameter not a flag\r
1516**/\r
1517BOOLEAN\r
1518EFIAPI\r
d2b4564b 1519InternalIsFlag (\r
94b17fa1 1520 IN CONST CHAR16 *Name\r
1521 )\r
1522{\r
1523 //\r
1524 // ASSERT that Name isn't NULL\r
1525 //\r
1526 ASSERT(Name != NULL);\r
1527\r
1528 //\r
1529 // If the Name has a / or - as the first character return TRUE\r
1530 //\r
d2b4564b 1531 if ((Name[0] == L'/') || \r
1532 (Name[0] == L'-') ||\r
1533 (Name[0] == L'+')\r
1534 ) {\r
94b17fa1 1535 return (TRUE);\r
1536 }\r
1537 return (FALSE);\r
1538}\r
1539\r
1540/**\r
1541 Checks the command line arguments passed against the list of valid ones. \r
1542\r
1543 If no initialization is required, then return RETURN_SUCCESS.\r
1544 \r
1545 @param CheckList pointer to list of parameters to check\r
1546 @param CheckPackage pointer to pointer to list checked values\r
1547 @param ProblemParam optional pointer to pointer to unicode string for \r
d2b4564b 1548 the paramater that caused failure. If used then the\r
1549 caller is responsible for freeing the memory.\r
94b17fa1 1550 @param AutoPageBreak will automatically set PageBreakEnabled for "b" parameter\r
1551 @param Argc Count of parameters in Argv\r
1552 @param Argv pointer to array of parameters\r
1553\r
1554 @retval EFI_SUCCESS The operation completed sucessfully.\r
1555 @retval EFI_OUT_OF_RESOURCES A memory allocation failed\r
1556 @retval EFI_INVALID_PARAMETER A parameter was invalid\r
1557 @retval EFI_VOLUME_CORRUPTED the command line was corrupt. an argument was \r
1558 duplicated. the duplicated command line argument \r
1559 was returned in ProblemParam if provided.\r
1560 @retval EFI_NOT_FOUND a argument required a value that was missing. \r
1561 the invalid command line argument was returned in\r
1562 ProblemParam if provided.\r
1563**/\r
1564EFI_STATUS\r
1565EFIAPI\r
1566InternalCommandLineParse (\r
1567 IN CONST SHELL_PARAM_ITEM *CheckList,\r
1568 OUT LIST_ENTRY **CheckPackage,\r
1569 OUT CHAR16 **ProblemParam OPTIONAL,\r
1570 IN BOOLEAN AutoPageBreak,\r
1571 IN CONST CHAR16 **Argv,\r
1572 IN UINTN Argc\r
1573 )\r
1574{\r
1575 UINTN LoopCounter;\r
1576 UINTN Count;\r
1577 ParamType CurrentItemType;\r
1578 SHELL_PARAM_PACKAGE *CurrentItemPackage;\r
1579 BOOLEAN GetItemValue;\r
1580\r
1581 CurrentItemPackage = NULL;\r
1582\r
1583 //\r
1584 // ASSERTs\r
1585 //\r
1586 ASSERT(CheckList != NULL);\r
1587 ASSERT(Argv != NULL);\r
1588\r
1589 Count = 0;\r
1590 GetItemValue = FALSE;\r
1591\r
1592 //\r
1593 // If there is only 1 item we dont need to do anything\r
1594 //\r
1595 if (Argc <= 1) {\r
1596 *CheckPackage = NULL;\r
1597 return (EFI_SUCCESS);\r
1598 }\r
1599\r
1600 //\r
1601 // initialize the linked list\r
1602 //\r
1603 *CheckPackage = (LIST_ENTRY*)AllocateZeroPool(sizeof(LIST_ENTRY));\r
1604 InitializeListHead(*CheckPackage);\r
1605\r
1606 //\r
1607 // loop through each of the arguments\r
1608 //\r
1609 for (LoopCounter = 0 ; LoopCounter < Argc ; ++LoopCounter) {\r
1610 if (Argv[LoopCounter] == NULL) {\r
1611 //\r
1612 // do nothing for NULL argv\r
1613 //\r
d2b4564b 1614 } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) == TRUE) {\r
94b17fa1 1615 //\r
1616 // this is a flag\r
1617 //\r
1618 CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE));\r
1619 ASSERT(CurrentItemPackage != NULL);\r
1620 CurrentItemPackage->Name = AllocatePool(StrSize(Argv[LoopCounter]));\r
1621 ASSERT(CurrentItemPackage->Name != NULL);\r
1622 StrCpy(CurrentItemPackage->Name, Argv[LoopCounter]);\r
1623 CurrentItemPackage->Type = CurrentItemType;\r
1624 CurrentItemPackage->OriginalPosition = (UINTN)(-1);\r
b1f95a06 1625 CurrentItemPackage->Value = NULL;\r
94b17fa1 1626\r
1627 //\r
1628 // Does this flag require a value\r
1629 //\r
1630 if (CurrentItemPackage->Type == TypeValue) {\r
1631 //\r
1632 // trigger the next loop to populate the value of this item\r
1633 //\r
1634 GetItemValue = TRUE; \r
1635 } else {\r
1636 //\r
1637 // this item has no value expected; we are done\r
1638 //\r
b1f95a06 1639 InsertHeadList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);\r
94b17fa1 1640 }\r
b1f95a06 1641 } else if (GetItemValue == TRUE && InternalIsFlag(Argv[LoopCounter]) == FALSE) {\r
1642 ASSERT(CurrentItemPackage != NULL);\r
1643 //\r
1644 // get the item VALUE for the previous flag\r
1645 //\r
1646 GetItemValue = FALSE;\r
1647 CurrentItemPackage->Value = AllocateZeroPool(StrSize(Argv[LoopCounter]));\r
1648 ASSERT(CurrentItemPackage->Value != NULL);\r
1649 StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
1650 InsertHeadList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);\r
1651 } else if (InternalIsFlag(Argv[LoopCounter]) == FALSE) {\r
1652 //\r
1653 // add this one as a non-flag\r
1654 //\r
1655 CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE));\r
1656 ASSERT(CurrentItemPackage != NULL);\r
1657 CurrentItemPackage->Name = NULL;\r
1658 CurrentItemPackage->Type = TypePosition;\r
1659 CurrentItemPackage->Value = AllocatePool(StrSize(Argv[LoopCounter]));\r
1660 ASSERT(CurrentItemPackage->Value != NULL);\r
1661 StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
1662 CurrentItemPackage->OriginalPosition = Count++;\r
1663 InsertHeadList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);\r
94b17fa1 1664 } else if (ProblemParam) {\r
1665 //\r
1666 // this was a non-recognised flag... error!\r
1667 //\r
d2b4564b 1668 *ProblemParam = AllocatePool(StrSize(Argv[LoopCounter]));\r
1669 ASSERT(*ProblemParam != NULL);\r
1670 StrCpy(*ProblemParam, Argv[LoopCounter]);\r
94b17fa1 1671 ShellCommandLineFreeVarList(*CheckPackage);\r
1672 *CheckPackage = NULL;\r
1673 return (EFI_VOLUME_CORRUPTED);\r
1674 } else {\r
1675 ShellCommandLineFreeVarList(*CheckPackage);\r
1676 *CheckPackage = NULL;\r
1677 return (EFI_VOLUME_CORRUPTED);\r
1678 }\r
1679 }\r
1680 //\r
1681 // support for AutoPageBreak\r
1682 //\r
1683 if (AutoPageBreak && ShellCommandLineGetFlag(*CheckPackage, L"-b")) {\r
1684 ShellSetPageBreakMode(TRUE);\r
1685 }\r
1686 return (EFI_SUCCESS);\r
1687}\r
1688\r
1689/**\r
1690 Checks the command line arguments passed against the list of valid ones. \r
1691 Optionally removes NULL values first.\r
1692 \r
1693 If no initialization is required, then return RETURN_SUCCESS.\r
1694 \r
1695 @param CheckList pointer to list of parameters to check\r
1696 @param CheckPackage pointer to pointer to list checked values\r
1697 @param ProblemParam optional pointer to pointer to unicode string for \r
1698 the paramater that caused failure.\r
1699 @param AutoPageBreak will automatically set PageBreakEnabled for "b" parameter\r
1700\r
1701 @retval EFI_SUCCESS The operation completed sucessfully.\r
1702 @retval EFI_OUT_OF_RESOURCES A memory allocation failed\r
1703 @retval EFI_INVALID_PARAMETER A parameter was invalid\r
1704 @retval EFI_VOLUME_CORRUPTED the command line was corrupt. an argument was \r
1705 duplicated. the duplicated command line argument \r
1706 was returned in ProblemParam if provided.\r
1707 @retval EFI_DEVICE_ERROR the commands contained 2 opposing arguments. one\r
1708 of the command line arguments was returned in \r
1709 ProblemParam if provided.\r
1710 @retval EFI_NOT_FOUND a argument required a value that was missing. \r
1711 the invalid command line argument was returned in\r
1712 ProblemParam if provided.\r
1713**/\r
1714EFI_STATUS\r
1715EFIAPI\r
1716ShellCommandLineParse (\r
1717 IN CONST SHELL_PARAM_ITEM *CheckList,\r
1718 OUT LIST_ENTRY **CheckPackage,\r
1719 OUT CHAR16 **ProblemParam OPTIONAL,\r
1720 IN BOOLEAN AutoPageBreak\r
1721 )\r
1722{\r
1723 // \r
1724 // ASSERT that CheckList and CheckPackage aren't NULL\r
1725 //\r
1726 ASSERT(CheckList != NULL);\r
1727 ASSERT(CheckPackage != NULL);\r
1728\r
1729 // \r
1730 // Check for UEFI Shell 2.0 protocols\r
1731 //\r
1732 if (mEfiShellParametersProtocol != NULL) {\r
1733 return (InternalCommandLineParse(CheckList, \r
1734 CheckPackage, \r
1735 ProblemParam, \r
1736 AutoPageBreak, \r
08d7f8e8 1737 (CONST CHAR16**) mEfiShellParametersProtocol->Argv,\r
94b17fa1 1738 mEfiShellParametersProtocol->Argc ));\r
1739 }\r
1740\r
1741 // \r
1742 // ASSERT That EFI Shell is not required\r
1743 //\r
1744 ASSERT (mEfiShellInterface != NULL);\r
1745 return (InternalCommandLineParse(CheckList, \r
1746 CheckPackage, \r
1747 ProblemParam, \r
1748 AutoPageBreak, \r
08d7f8e8 1749 (CONST CHAR16**) mEfiShellInterface->Argv,\r
94b17fa1 1750 mEfiShellInterface->Argc ));\r
1751}\r
1752\r
1753/**\r
1754 Frees shell variable list that was returned from ShellCommandLineParse.\r
1755\r
1756 This function will free all the memory that was used for the CheckPackage\r
1757 list of postprocessed shell arguments.\r
1758\r
1759 this function has no return value.\r
1760\r
1761 if CheckPackage is NULL, then return\r
1762\r
1763 @param CheckPackage the list to de-allocate\r
1764 **/\r
1765VOID\r
1766EFIAPI\r
1767ShellCommandLineFreeVarList (\r
1768 IN LIST_ENTRY *CheckPackage\r
1769 )\r
1770{\r
1771 LIST_ENTRY *Node;\r
1772\r
1773 //\r
1774 // check for CheckPackage == NULL\r
1775 //\r
1776 if (CheckPackage == NULL) {\r
1777 return;\r
1778 }\r
1779\r
1780 //\r
1781 // for each node in the list\r
1782 //\r
1783 for (Node = GetFirstNode(CheckPackage); Node != CheckPackage ; Node = GetFirstNode(CheckPackage)) {\r
1784 //\r
1785 // Remove it from the list\r
1786 //\r
1787 RemoveEntryList(Node);\r
1788\r
1789 //\r
1790 // if it has a name free the name\r
1791 //\r
1792 if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
1793 FreePool(((SHELL_PARAM_PACKAGE*)Node)->Name);\r
1794 }\r
1795\r
1796 //\r
1797 // if it has a value free the value\r
1798 //\r
1799 if (((SHELL_PARAM_PACKAGE*)Node)->Value != NULL) {\r
1800 FreePool(((SHELL_PARAM_PACKAGE*)Node)->Value);\r
1801 }\r
1802 \r
1803 //\r
1804 // free the node structure\r
1805 //\r
1806 FreePool((SHELL_PARAM_PACKAGE*)Node);\r
1807 }\r
1808 //\r
1809 // free the list head node\r
1810 //\r
1811 FreePool(CheckPackage);\r
1812}\r
1813/**\r
1814 Checks for presence of a flag parameter\r
1815\r
1816 flag arguments are in the form of "-<Key>" or "/<Key>", but do not have a value following the key\r
1817\r
1818 if CheckPackage is NULL then return FALSE.\r
1819 if KeyString is NULL then ASSERT()\r
1820 \r
1821 @param CheckPackage The package of parsed command line arguments\r
1822 @param KeyString the Key of the command line argument to check for\r
1823\r
1824 @retval TRUE the flag is on the command line\r
1825 @retval FALSE the flag is not on the command line\r
1826 **/\r
1827BOOLEAN\r
1828EFIAPI\r
1829ShellCommandLineGetFlag (\r
1830 IN CONST LIST_ENTRY *CheckPackage,\r
1831 IN CHAR16 *KeyString\r
1832 )\r
1833{\r
1834 LIST_ENTRY *Node;\r
1835\r
1836 //\r
1837 // ASSERT that both CheckPackage and KeyString aren't NULL\r
1838 //\r
1839 ASSERT(KeyString != NULL);\r
1840\r
1841 //\r
1842 // return FALSE for no package\r
1843 //\r
1844 if (CheckPackage == NULL) {\r
1845 return (FALSE);\r
1846 }\r
1847\r
1848 //\r
1849 // enumerate through the list of parametrs\r
1850 //\r
323f53ff 1851 for (Node = GetFirstNode(CheckPackage) ; !IsNull (CheckPackage, Node) ; Node = GetNextNode(CheckPackage, Node) ) {\r
94b17fa1 1852 //\r
1853 // If the Name matches, return TRUE (and there may be NULL name)\r
1854 //\r
1855 if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
1856 if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
1857 return (TRUE);\r
1858 }\r
1859 }\r
1860 }\r
1861 return (FALSE);\r
1862}\r
1863/**\r
1864 returns value from command line argument\r
1865\r
1866 value parameters are in the form of "-<Key> value" or "/<Key> value"\r
1867 \r
1868 if CheckPackage is NULL, then return NULL;\r
1869\r
1870 @param CheckPackage The package of parsed command line arguments\r
1871 @param KeyString the Key of the command line argument to check for\r
1872\r
1873 @retval NULL the flag is not on the command line\r
1874 @return !=NULL pointer to unicode string of the value\r
1875 **/\r
1876CONST CHAR16*\r
1877EFIAPI\r
1878ShellCommandLineGetValue (\r
1879 IN CONST LIST_ENTRY *CheckPackage,\r
1880 IN CHAR16 *KeyString\r
1881 )\r
1882{\r
1883 LIST_ENTRY *Node;\r
1884\r
1885 //\r
1886 // check for CheckPackage == NULL\r
1887 //\r
1888 if (CheckPackage == NULL) {\r
1889 return (NULL);\r
1890 }\r
1891\r
1892 //\r
1893 // enumerate through the list of parametrs\r
1894 //\r
323f53ff 1895 for (Node = GetFirstNode(CheckPackage) ; !IsNull (CheckPackage, Node) ; Node = GetNextNode(CheckPackage, Node) ) {\r
94b17fa1 1896 //\r
1897 // If the Name matches, return the value (name can be NULL)\r
1898 //\r
1899 if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
1900 if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
1901 return (((SHELL_PARAM_PACKAGE*)Node)->Value);\r
1902 }\r
1903 }\r
1904 }\r
1905 return (NULL);\r
1906}\r
1907/**\r
1908 returns raw value from command line argument\r
1909\r
1910 raw value parameters are in the form of "value" in a specific position in the list\r
1911 \r
1912 if CheckPackage is NULL, then return NULL;\r
1913\r
1914 @param CheckPackage The package of parsed command line arguments\r
1915 @param Position the position of the value \r
1916\r
1917 @retval NULL the flag is not on the command line\r
1918 @return !=NULL pointer to unicode string of the value\r
1919 **/\r
1920CONST CHAR16*\r
1921EFIAPI\r
1922ShellCommandLineGetRawValue (\r
1923 IN CONST LIST_ENTRY *CheckPackage,\r
1924 IN UINT32 Position\r
1925 )\r
1926{\r
1927 LIST_ENTRY *Node;\r
1928\r
1929 //\r
1930 // check for CheckPackage == NULL\r
1931 //\r
1932 if (CheckPackage == NULL) {\r
1933 return (NULL);\r
1934 }\r
1935\r
1936 //\r
1937 // enumerate through the list of parametrs\r
1938 //\r
323f53ff 1939 for (Node = GetFirstNode(CheckPackage) ; !IsNull (CheckPackage, Node) ; Node = GetNextNode(CheckPackage, Node) ) {\r
94b17fa1 1940 //\r
1941 // If the position matches, return the value\r
1942 //\r
1943 if (((SHELL_PARAM_PACKAGE*)Node)->OriginalPosition == Position) {\r
1944 return (((SHELL_PARAM_PACKAGE*)Node)->Value);\r
1945 }\r
1946 }\r
1947 return (NULL);\r
b1f95a06 1948}\r
975136ab 1949/**\r
1950 This is a find and replace function. it will return the NewString as a copy of \r
1951 SourceString with each instance of FindTarget replaced with ReplaceWith.\r
1952\r
1953 If the string would grow bigger than NewSize it will halt and return error.\r
1954\r
1955 @param[in] SourceString String with source buffer\r
1956 @param[in][out] NewString String with resultant buffer\r
1957 @param[in] NewSize Size in bytes of NewString\r
1958 @param[in] FindTarget String to look for\r
1959 @param[in[ ReplaceWith String to replace FindTarget with\r
1960\r
1961 @retval EFI_INVALID_PARAMETER SourceString was NULL\r
1962 @retval EFI_INVALID_PARAMETER NewString was NULL\r
1963 @retval EFI_INVALID_PARAMETER FindTarget was NULL\r
1964 @retval EFI_INVALID_PARAMETER ReplaceWith was NULL\r
1965 @retval EFI_INVALID_PARAMETER FindTarget had length < 1\r
1966 @retval EFI_INVALID_PARAMETER SourceString had length < 1\r
1967 @retval EFI_BUFFER_TOO_SMALL NewSize was less than the minimum size to hold \r
1968 the new string (truncation occurred)\r
1969 @retval EFI_SUCCESS the string was sucessfully copied with replacement\r
1970**/\r
1971\r
1972EFI_STATUS\r
1973EFIAPI\r
1974CopyReplace(\r
1975 IN CHAR16 CONST *SourceString,\r
1976 IN CHAR16 *NewString,\r
1977 IN UINTN NewSize,\r
1978 IN CONST CHAR16 *FindTarget,\r
1979 IN CONST CHAR16 *ReplaceWith\r
1980 ){\r
1981 if ( (SourceString == NULL)\r
1982 || (NewString == NULL)\r
1983 || (FindTarget == NULL)\r
1984 || (ReplaceWith == NULL)\r
1985 || (StrLen(FindTarget) < 1)\r
1986 || (StrLen(SourceString) < 1)\r
1987 ){\r
1988 return (EFI_INVALID_PARAMETER);\r
1989 }\r
1990 NewString = SetMem16(NewString, NewSize, L'\0');\r
1991 while (*SourceString != L'\0') {\r
1992 if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0) {\r
1993 SourceString += StrLen(FindTarget);\r
1994 if (StrSize(NewString) + (StrLen(ReplaceWith)*sizeof(CHAR16)) > NewSize) {\r
1995 return (EFI_BUFFER_TOO_SMALL);\r
1996 }\r
1997 StrCat(NewString, ReplaceWith);\r
1998 } else {\r
1999 if (StrSize(NewString) + sizeof(CHAR16) > NewSize) {\r
2000 return (EFI_BUFFER_TOO_SMALL);\r
2001 }\r
2002 StrnCat(NewString, SourceString, 1);\r
2003 SourceString++;\r
2004 }\r
2005 }\r
2006 return (EFI_SUCCESS);\r
2007}\r
b1f95a06 2008\r
2009/**\r
2010 Print at a specific location on the screen.\r
2011\r
2012 This function will move the cursor to a given screen location, print the specified string, \r
2013 and return the cursor to the original locaiton. \r
2014 \r
2015 If -1 is specified for either the Row or Col the current screen location for BOTH \r
2016 will be used and the cursor's position will not be moved back to an original location.\r
2017\r
2018 if either Row or Col is out of range for the current console, then ASSERT\r
2019 if Format is NULL, then ASSERT\r
2020\r
2021 In addition to the standard %-based flags as supported by UefiLib Print() this supports \r
2022 the following additional flags:\r
2023 %N - Set output attribute to normal\r
2024 %H - Set output attribute to highlight\r
2025 %E - Set output attribute to error\r
2026 %B - Set output attribute to blue color\r
2027 %V - Set output attribute to green color\r
2028\r
2029 Note: The background color is controlled by the shell command cls.\r
2030\r
2031 @param[in] Row the row to print at\r
2032 @param[in] Col the column to print at\r
2033 @param[in] Format the format string\r
2034\r
2035 @return the number of characters printed to the screen\r
2036**/\r
2037\r
2038UINTN\r
2039EFIAPI\r
2040ShellPrintEx(\r
2041 IN INT32 Col OPTIONAL,\r
2042 IN INT32 Row OPTIONAL,\r
2043 IN CONST CHAR16 *Format,\r
2044 ...\r
2045 ){\r
2046 VA_LIST Marker;\r
2047 UINTN BufferSize;\r
975136ab 2048 CHAR16 *PostReplaceFormat;\r
2049 CHAR16 *PostReplaceFormat2;\r
b1f95a06 2050 UINTN Return;\r
2051 INT32 CurrentCol;\r
2052 INT32 CurrentRow;\r
2053 EFI_STATUS Status;\r
975136ab 2054 UINTN NormalAttribute;\r
2055 CHAR16 *ResumeLocation;\r
2056 CHAR16 *FormatWalker;\r
2057\r
2058 VA_START (Marker, Format);\r
b1f95a06 2059 \r
2060 BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16);\r
975136ab 2061 PostReplaceFormat = AllocateZeroPool (BufferSize);\r
2062 ASSERT (PostReplaceFormat != NULL);\r
2063 PostReplaceFormat2 = AllocateZeroPool (BufferSize);\r
2064 ASSERT (PostReplaceFormat2 != NULL);\r
b1f95a06 2065\r
975136ab 2066 //\r
2067 // Back and forth each time fixing up 1 of our flags...\r
2068 //\r
2069 Status = CopyReplace(Format, PostReplaceFormat, BufferSize, L"%N", L"%%N");\r
2070 ASSERT_EFI_ERROR(Status);\r
2071 Status = CopyReplace(PostReplaceFormat, PostReplaceFormat2, BufferSize, L"%E", L"%%E");\r
2072 ASSERT_EFI_ERROR(Status);\r
2073 Status = CopyReplace(PostReplaceFormat2, PostReplaceFormat, BufferSize, L"%H", L"%%H");\r
2074 ASSERT_EFI_ERROR(Status);\r
2075 Status = CopyReplace(PostReplaceFormat, PostReplaceFormat2, BufferSize, L"%B", L"%%B");\r
2076 ASSERT_EFI_ERROR(Status);\r
2077 Status = CopyReplace(PostReplaceFormat2, PostReplaceFormat, BufferSize, L"%V", L"%%V");\r
2078 ASSERT_EFI_ERROR(Status);\r
2079\r
2080 //\r
2081 // Use the last buffer from replacing to print from...\r
2082 //\r
2083 Return = UnicodeVSPrint (PostReplaceFormat2, BufferSize, PostReplaceFormat, Marker);\r
2084\r
2085 FreePool(PostReplaceFormat);\r
b1f95a06 2086\r
2087 if (Col != -1 && Row != -1) {\r
2088 CurrentCol = gST->ConOut->Mode->CursorColumn;\r
2089 CurrentRow = gST->ConOut->Mode->CursorRow;\r
2090 Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);\r
2091 ASSERT_EFI_ERROR(Status);\r
975136ab 2092 } else {\r
2093 CurrentCol = 0;\r
2094 CurrentRow = 0;\r
2095 }\r
2096\r
2097 NormalAttribute = gST->ConOut->Mode->Attribute;\r
2098 FormatWalker = PostReplaceFormat2;\r
2099 while (*FormatWalker != L'\0') {\r
2100 //\r
2101 // Find the next attribute change request\r
2102 //\r
2103 ResumeLocation = StrStr(FormatWalker, L"%");\r
2104 if (ResumeLocation != NULL) {\r
2105 *ResumeLocation = L'\0';\r
2106 }\r
2107 //\r
2108 // print the current FormatWalker string\r
2109 //\r
2110 Status = gST->ConOut->OutputString(gST->ConOut, FormatWalker);\r
b1f95a06 2111 ASSERT_EFI_ERROR(Status);\r
975136ab 2112 //\r
2113 // update the attribute\r
2114 //\r
2115 if (ResumeLocation != NULL) {\r
2116 switch (*(ResumeLocation+1)) {\r
2117 case (L'N'):\r
2118 gST->ConOut->SetAttribute(gST->ConOut, NormalAttribute);\r
2119 break;\r
2120 case (L'E'):\r
2121 gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
2122 break;\r
2123 case (L'H'):\r
2124 gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
2125 break;\r
2126 case (L'B'):\r
2127 gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_BLUE, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
2128 break;\r
2129 case (L'V'):\r
2130 gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_GREEN, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
2131 break;\r
2132 default:\r
2133 ASSERT(FALSE);\r
2134 break;\r
2135 }\r
2136 } else {\r
2137 //\r
2138 // reset to normal now...\r
2139 //\r
2140 gST->ConOut->SetAttribute(gST->ConOut, NormalAttribute);\r
2141 break;\r
2142 }\r
2143\r
2144 //\r
2145 // update FormatWalker to Resume + 2 (skip the % and the indicator)\r
2146 //\r
2147 FormatWalker = ResumeLocation + 2;\r
2148 }\r
2149 \r
2150 if (Col != -1 && Row != -1) {\r
b1f95a06 2151 Status = gST->ConOut->SetCursorPosition(gST->ConOut, CurrentCol, CurrentRow);\r
2152 ASSERT_EFI_ERROR(Status);\r
b1f95a06 2153 }\r
2154\r
975136ab 2155 FreePool(PostReplaceFormat2);\r
2156\r
b1f95a06 2157 return (Return);\r
94b17fa1 2158}