]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLib/UefiShellLib.c
NetworkPkg: Fix MSFT C4255 warning
[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
583448b4 4 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
9ed21946 5 Copyright 2016 Dell Inc.\r
22454f10 6 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
1e6e84c7 7 This program and the accompanying materials\r
b3011f40 8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
94b17fa1 11\r
b3011f40 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
94b17fa1 14\r
15**/\r
16\r
b1f95a06 17#include "UefiShellLib.h"\r
252d9457 18#include <Library/SortLib.h>\r
3fe23dc6 19#include <Library/BaseLib.h>\r
d2b4564b 20\r
d2b4564b 21//\r
a405b86d 22// globals...\r
d2b4564b 23//\r
24SHELL_PARAM_ITEM EmptyParamList[] = {\r
25 {NULL, TypeMax}\r
26 };\r
a405b86d 27SHELL_PARAM_ITEM SfoParamList[] = {\r
28 {L"-sfo", TypeFlag},\r
29 {NULL, TypeMax}\r
30 };\r
31EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2;\r
32EFI_SHELL_INTERFACE *mEfiShellInterface;\r
366f81a0 33EFI_SHELL_PROTOCOL *gEfiShellProtocol;\r
34EFI_SHELL_PARAMETERS_PROTOCOL *gEfiShellParametersProtocol;\r
a405b86d 35EFI_HANDLE mEfiShellEnvironment2Handle;\r
36FILE_HANDLE_FUNCTION_MAP FileFunctionMap;\r
583448b4 37EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollationProtocol;\r
b3011f40 38\r
2247dde4 39/**\r
40 Check if a Unicode character is a hexadecimal character.\r
41\r
1e6e84c7 42 This internal function checks if a Unicode character is a\r
a405b86d 43 numeric character. The valid hexadecimal characters are\r
2247dde4 44 L'0' to L'9', L'a' to L'f', or L'A' to L'F'.\r
45\r
2247dde4 46 @param Char The character to check against.\r
47\r
48 @retval TRUE If the Char is a hexadecmial character.\r
49 @retval FALSE If the Char is not a hexadecmial character.\r
50\r
51**/\r
52BOOLEAN\r
53EFIAPI\r
969c783b 54ShellIsHexaDecimalDigitCharacter (\r
2247dde4 55 IN CHAR16 Char\r
a405b86d 56 )\r
57{\r
2247dde4 58 return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f'));\r
59}\r
94b17fa1 60\r
61/**\r
a405b86d 62 Check if a Unicode character is a decimal character.\r
63\r
64 This internal function checks if a Unicode character is a\r
65 decimal character. The valid characters are\r
66 L'0' to L'9'.\r
67\r
68\r
69 @param Char The character to check against.\r
70\r
71 @retval TRUE If the Char is a hexadecmial character.\r
72 @retval FALSE If the Char is not a hexadecmial character.\r
73\r
74**/\r
75BOOLEAN\r
76EFIAPI\r
77ShellIsDecimalDigitCharacter (\r
78 IN CHAR16 Char\r
79 )\r
80{\r
81 return (BOOLEAN) (Char >= L'0' && Char <= L'9');\r
82}\r
83\r
84/**\r
85 Helper function to find ShellEnvironment2 for constructor.\r
86\r
87 @param[in] ImageHandle A copy of the calling image's handle.\r
beab0fc5 88\r
89 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
94b17fa1 90**/\r
91EFI_STATUS\r
94b17fa1 92ShellFindSE2 (\r
93 IN EFI_HANDLE ImageHandle\r
a405b86d 94 )\r
95{\r
94b17fa1 96 EFI_STATUS Status;\r
97 EFI_HANDLE *Buffer;\r
98 UINTN BufferSize;\r
99 UINTN HandleIndex;\r
100\r
101 BufferSize = 0;\r
102 Buffer = NULL;\r
1e6e84c7 103 Status = gBS->OpenProtocol(ImageHandle,\r
94b17fa1 104 &gEfiShellEnvironment2Guid,\r
105 (VOID **)&mEfiShellEnvironment2,\r
106 ImageHandle,\r
107 NULL,\r
108 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
a405b86d 109 );\r
94b17fa1 110 //\r
111 // look for the mEfiShellEnvironment2 protocol at a higher level\r
112 //\r
a405b86d 113 if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid))){\r
94b17fa1 114 //\r
115 // figure out how big of a buffer we need.\r
116 //\r
117 Status = gBS->LocateHandle (ByProtocol,\r
118 &gEfiShellEnvironment2Guid,\r
119 NULL, // ignored for ByProtocol\r
120 &BufferSize,\r
121 Buffer\r
a405b86d 122 );\r
2247dde4 123 //\r
124 // maybe it's not there???\r
125 //\r
126 if (Status == EFI_BUFFER_TOO_SMALL) {\r
252d9457 127 Buffer = (EFI_HANDLE*)AllocateZeroPool(BufferSize);\r
beab0fc5 128 if (Buffer == NULL) {\r
129 return (EFI_OUT_OF_RESOURCES);\r
130 }\r
2247dde4 131 Status = gBS->LocateHandle (ByProtocol,\r
132 &gEfiShellEnvironment2Guid,\r
133 NULL, // ignored for ByProtocol\r
134 &BufferSize,\r
135 Buffer\r
a405b86d 136 );\r
2247dde4 137 }\r
1cd45e78 138 if (!EFI_ERROR (Status) && Buffer != NULL) {\r
94b17fa1 139 //\r
140 // now parse the list of returned handles\r
141 //\r
142 Status = EFI_NOT_FOUND;\r
143 for (HandleIndex = 0; HandleIndex < (BufferSize/sizeof(Buffer[0])); HandleIndex++) {\r
1e6e84c7 144 Status = gBS->OpenProtocol(Buffer[HandleIndex],\r
94b17fa1 145 &gEfiShellEnvironment2Guid,\r
146 (VOID **)&mEfiShellEnvironment2,\r
147 ImageHandle,\r
148 NULL,\r
149 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
a405b86d 150 );\r
151 if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid)) {\r
94b17fa1 152 mEfiShellEnvironment2Handle = Buffer[HandleIndex];\r
153 Status = EFI_SUCCESS;\r
154 break;\r
155 }\r
156 }\r
157 }\r
158 }\r
159 if (Buffer != NULL) {\r
160 FreePool (Buffer);\r
161 }\r
162 return (Status);\r
163}\r
164\r
252d9457 165/**\r
b0934ac4 166 Function to do most of the work of the constructor. Allows for calling\r
a405b86d 167 multiple times without complete re-initialization.\r
168\r
169 @param[in] ImageHandle A copy of the ImageHandle.\r
170 @param[in] SystemTable A pointer to the SystemTable for the application.\r
252d9457 171\r
172 @retval EFI_SUCCESS The operationw as successful.\r
a405b86d 173**/\r
94b17fa1 174EFI_STATUS\r
d2b4564b 175ShellLibConstructorWorker (\r
94b17fa1 176 IN EFI_HANDLE ImageHandle,\r
177 IN EFI_SYSTEM_TABLE *SystemTable\r
a405b86d 178 )\r
179{\r
180 EFI_STATUS Status;\r
ecd3d59f 181\r
94b17fa1 182 //\r
183 // UEFI 2.0 shell interfaces (used preferentially)\r
184 //\r
a405b86d 185 Status = gBS->OpenProtocol(\r
186 ImageHandle,\r
187 &gEfiShellProtocolGuid,\r
366f81a0 188 (VOID **)&gEfiShellProtocol,\r
a405b86d 189 ImageHandle,\r
190 NULL,\r
191 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
192 );\r
94b17fa1 193 if (EFI_ERROR(Status)) {\r
a405b86d 194 //\r
195 // Search for the shell protocol\r
196 //\r
197 Status = gBS->LocateProtocol(\r
198 &gEfiShellProtocolGuid,\r
199 NULL,\r
366f81a0 200 (VOID **)&gEfiShellProtocol\r
a405b86d 201 );\r
202 if (EFI_ERROR(Status)) {\r
366f81a0 203 gEfiShellProtocol = NULL;\r
a405b86d 204 }\r
94b17fa1 205 }\r
a405b86d 206 Status = gBS->OpenProtocol(\r
207 ImageHandle,\r
208 &gEfiShellParametersProtocolGuid,\r
366f81a0 209 (VOID **)&gEfiShellParametersProtocol,\r
a405b86d 210 ImageHandle,\r
211 NULL,\r
212 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
213 );\r
94b17fa1 214 if (EFI_ERROR(Status)) {\r
366f81a0 215 gEfiShellParametersProtocol = NULL;\r
94b17fa1 216 }\r
217\r
366f81a0 218 if (gEfiShellParametersProtocol == NULL || gEfiShellProtocol == NULL) {\r
94b17fa1 219 //\r
220 // Moved to seperate function due to complexity\r
221 //\r
222 Status = ShellFindSE2(ImageHandle);\r
223\r
224 if (EFI_ERROR(Status)) {\r
225 DEBUG((DEBUG_ERROR, "Status: 0x%08x\r\n", Status));\r
226 mEfiShellEnvironment2 = NULL;\r
227 }\r
1e6e84c7 228 Status = gBS->OpenProtocol(ImageHandle,\r
94b17fa1 229 &gEfiShellInterfaceGuid,\r
230 (VOID **)&mEfiShellInterface,\r
231 ImageHandle,\r
232 NULL,\r
233 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
a405b86d 234 );\r
94b17fa1 235 if (EFI_ERROR(Status)) {\r
236 mEfiShellInterface = NULL;\r
237 }\r
238 }\r
c9d92df0 239\r
94b17fa1 240 //\r
241 // only success getting 2 of either the old or new, but no 1/2 and 1/2\r
242 //\r
1e6e84c7 243 if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface != NULL) ||\r
366f81a0 244 (gEfiShellProtocol != NULL && gEfiShellParametersProtocol != NULL) ) {\r
245 if (gEfiShellProtocol != NULL) {\r
246 FileFunctionMap.GetFileInfo = gEfiShellProtocol->GetFileInfo;\r
247 FileFunctionMap.SetFileInfo = gEfiShellProtocol->SetFileInfo;\r
248 FileFunctionMap.ReadFile = gEfiShellProtocol->ReadFile;\r
249 FileFunctionMap.WriteFile = gEfiShellProtocol->WriteFile;\r
250 FileFunctionMap.CloseFile = gEfiShellProtocol->CloseFile;\r
251 FileFunctionMap.DeleteFile = gEfiShellProtocol->DeleteFile;\r
252 FileFunctionMap.GetFilePosition = gEfiShellProtocol->GetFilePosition;\r
253 FileFunctionMap.SetFilePosition = gEfiShellProtocol->SetFilePosition;\r
254 FileFunctionMap.FlushFile = gEfiShellProtocol->FlushFile;\r
255 FileFunctionMap.GetFileSize = gEfiShellProtocol->GetFileSize;\r
d2b4564b 256 } else {\r
a405b86d 257 FileFunctionMap.GetFileInfo = (EFI_SHELL_GET_FILE_INFO)FileHandleGetInfo;\r
258 FileFunctionMap.SetFileInfo = (EFI_SHELL_SET_FILE_INFO)FileHandleSetInfo;\r
259 FileFunctionMap.ReadFile = (EFI_SHELL_READ_FILE)FileHandleRead;\r
260 FileFunctionMap.WriteFile = (EFI_SHELL_WRITE_FILE)FileHandleWrite;\r
261 FileFunctionMap.CloseFile = (EFI_SHELL_CLOSE_FILE)FileHandleClose;\r
262 FileFunctionMap.DeleteFile = (EFI_SHELL_DELETE_FILE)FileHandleDelete;\r
263 FileFunctionMap.GetFilePosition = (EFI_SHELL_GET_FILE_POSITION)FileHandleGetPosition;\r
264 FileFunctionMap.SetFilePosition = (EFI_SHELL_SET_FILE_POSITION)FileHandleSetPosition;\r
265 FileFunctionMap.FlushFile = (EFI_SHELL_FLUSH_FILE)FileHandleFlush;\r
266 FileFunctionMap.GetFileSize = (EFI_SHELL_GET_FILE_SIZE)FileHandleGetSize;\r
d2b4564b 267 }\r
94b17fa1 268 return (EFI_SUCCESS);\r
269 }\r
270 return (EFI_NOT_FOUND);\r
271}\r
d2b4564b 272/**\r
273 Constructor for the Shell library.\r
274\r
275 Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell.\r
276\r
277 @param ImageHandle the image handle of the process\r
278 @param SystemTable the EFI System Table pointer\r
279\r
280 @retval EFI_SUCCESS the initialization was complete sucessfully\r
281 @return others an error ocurred during initialization\r
282**/\r
283EFI_STATUS\r
284EFIAPI\r
285ShellLibConstructor (\r
286 IN EFI_HANDLE ImageHandle,\r
287 IN EFI_SYSTEM_TABLE *SystemTable\r
a405b86d 288 )\r
289{\r
d2b4564b 290 mEfiShellEnvironment2 = NULL;\r
366f81a0 291 gEfiShellProtocol = NULL;\r
292 gEfiShellParametersProtocol = NULL;\r
d2b4564b 293 mEfiShellInterface = NULL;\r
294 mEfiShellEnvironment2Handle = NULL;\r
2cf9ecd2 295 mUnicodeCollationProtocol = NULL;\r
583448b4 296\r
d2b4564b 297 //\r
298 // verify that auto initialize is not set false\r
1e6e84c7 299 //\r
d2b4564b 300 if (PcdGetBool(PcdShellLibAutoInitialize) == 0) {\r
301 return (EFI_SUCCESS);\r
302 }\r
1e6e84c7 303\r
d2b4564b 304 return (ShellLibConstructorWorker(ImageHandle, SystemTable));\r
305}\r
94b17fa1 306\r
307/**\r
a405b86d 308 Destructor for the library. free any resources.\r
309\r
310 @param[in] ImageHandle A copy of the ImageHandle.\r
311 @param[in] SystemTable A pointer to the SystemTable for the application.\r
312\r
313 @retval EFI_SUCCESS The operation was successful.\r
314 @return An error from the CloseProtocol function.\r
94b17fa1 315**/\r
316EFI_STATUS\r
317EFIAPI\r
318ShellLibDestructor (\r
319 IN EFI_HANDLE ImageHandle,\r
320 IN EFI_SYSTEM_TABLE *SystemTable\r
a405b86d 321 )\r
322{\r
94b17fa1 323 if (mEfiShellEnvironment2 != NULL) {\r
324 gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle,\r
325 &gEfiShellEnvironment2Guid,\r
326 ImageHandle,\r
327 NULL);\r
d2b4564b 328 mEfiShellEnvironment2 = NULL;\r
94b17fa1 329 }\r
330 if (mEfiShellInterface != NULL) {\r
331 gBS->CloseProtocol(ImageHandle,\r
332 &gEfiShellInterfaceGuid,\r
333 ImageHandle,\r
1e6e84c7 334 NULL);\r
d2b4564b 335 mEfiShellInterface = NULL;\r
94b17fa1 336 }\r
366f81a0 337 if (gEfiShellProtocol != NULL) {\r
94b17fa1 338 gBS->CloseProtocol(ImageHandle,\r
339 &gEfiShellProtocolGuid,\r
340 ImageHandle,\r
1e6e84c7 341 NULL);\r
366f81a0 342 gEfiShellProtocol = NULL;\r
94b17fa1 343 }\r
366f81a0 344 if (gEfiShellParametersProtocol != NULL) {\r
94b17fa1 345 gBS->CloseProtocol(ImageHandle,\r
346 &gEfiShellParametersProtocolGuid,\r
347 ImageHandle,\r
1e6e84c7 348 NULL);\r
366f81a0 349 gEfiShellParametersProtocol = NULL;\r
94b17fa1 350 }\r
d2b4564b 351 mEfiShellEnvironment2Handle = NULL;\r
ecd3d59f 352\r
94b17fa1 353 return (EFI_SUCCESS);\r
354}\r
d2b4564b 355\r
356/**\r
357 This function causes the shell library to initialize itself. If the shell library\r
358 is already initialized it will de-initialize all the current protocol poitners and\r
359 re-populate them again.\r
360\r
361 When the library is used with PcdShellLibAutoInitialize set to true this function\r
362 will return EFI_SUCCESS and perform no actions.\r
363\r
364 This function is intended for internal access for shell commands only.\r
365\r
366 @retval EFI_SUCCESS the initialization was complete sucessfully\r
367\r
368**/\r
369EFI_STATUS\r
370EFIAPI\r
371ShellInitialize (\r
a405b86d 372 )\r
373{\r
4a7518d3
LE
374 EFI_STATUS Status;\r
375\r
d2b4564b 376 //\r
377 // if auto initialize is not false then skip\r
378 //\r
379 if (PcdGetBool(PcdShellLibAutoInitialize) != 0) {\r
380 return (EFI_SUCCESS);\r
381 }\r
382\r
383 //\r
384 // deinit the current stuff\r
385 //\r
4a7518d3
LE
386 Status = ShellLibDestructor (gImageHandle, gST);\r
387 ASSERT_EFI_ERROR (Status);\r
d2b4564b 388\r
389 //\r
390 // init the new stuff\r
391 //\r
392 return (ShellLibConstructorWorker(gImageHandle, gST));\r
393}\r
394\r
94b17fa1 395/**\r
1e6e84c7 396 This function will retrieve the information about the file for the handle\r
94b17fa1 397 specified and store it in allocated pool memory.\r
398\r
1e6e84c7 399 This function allocates a buffer to store the file's information. It is the\r
69817bf8 400 caller's responsibility to free the buffer\r
94b17fa1 401\r
1e6e84c7 402 @param FileHandle The file handle of the file for which information is\r
94b17fa1 403 being requested.\r
404\r
405 @retval NULL information could not be retrieved.\r
406\r
407 @return the information about the file\r
408**/\r
409EFI_FILE_INFO*\r
410EFIAPI\r
411ShellGetFileInfo (\r
a405b86d 412 IN SHELL_FILE_HANDLE FileHandle\r
413 )\r
414{\r
d2b4564b 415 return (FileFunctionMap.GetFileInfo(FileHandle));\r
94b17fa1 416}\r
417\r
418/**\r
a405b86d 419 This function sets the information about the file for the opened handle\r
94b17fa1 420 specified.\r
421\r
a405b86d 422 @param[in] FileHandle The file handle of the file for which information\r
423 is being set.\r
94b17fa1 424\r
a405b86d 425 @param[in] FileInfo The information to set.\r
94b17fa1 426\r
b0934ac4 427 @retval EFI_SUCCESS The information was set.\r
a405b86d 428 @retval EFI_INVALID_PARAMETER A parameter was out of range or invalid.\r
429 @retval EFI_UNSUPPORTED The FileHandle does not support FileInfo.\r
b0934ac4 430 @retval EFI_NO_MEDIA The device has no medium.\r
431 @retval EFI_DEVICE_ERROR The device reported an error.\r
432 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
433 @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
a405b86d 434 @retval EFI_ACCESS_DENIED The file was opened read only.\r
435 @retval EFI_VOLUME_FULL The volume is full.\r
94b17fa1 436**/\r
437EFI_STATUS\r
438EFIAPI\r
439ShellSetFileInfo (\r
b0934ac4 440 IN SHELL_FILE_HANDLE FileHandle,\r
94b17fa1 441 IN EFI_FILE_INFO *FileInfo\r
a405b86d 442 )\r
443{\r
d2b4564b 444 return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo));\r
1e6e84c7 445}\r
446\r
94b17fa1 447 /**\r
448 This function will open a file or directory referenced by DevicePath.\r
449\r
1e6e84c7 450 This function opens a file with the open mode according to the file path. The\r
94b17fa1 451 Attributes is valid only for EFI_FILE_MODE_CREATE.\r
452\r
b0934ac4 453 @param FilePath on input the device path to the file. On output\r
94b17fa1 454 the remaining device path.\r
b0934ac4 455 @param DeviceHandle pointer to the system device handle.\r
456 @param FileHandle pointer to the file handle.\r
457 @param OpenMode the mode to open the file with.\r
458 @param Attributes the file's file attributes.\r
459\r
460 @retval EFI_SUCCESS The information was set.\r
461 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
462 @retval EFI_UNSUPPORTED Could not open the file path.\r
463 @retval EFI_NOT_FOUND The specified file could not be found on the\r
1e6e84c7 464 device or the file system could not be found on\r
94b17fa1 465 the device.\r
b0934ac4 466 @retval EFI_NO_MEDIA The device has no medium.\r
467 @retval EFI_MEDIA_CHANGED The device has a different medium in it or the\r
94b17fa1 468 medium is no longer supported.\r
b0934ac4 469 @retval EFI_DEVICE_ERROR The device reported an error.\r
470 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
471 @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
472 @retval EFI_ACCESS_DENIED The file was opened read only.\r
473 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
94b17fa1 474 file.\r
b0934ac4 475 @retval EFI_VOLUME_FULL The volume is full.\r
94b17fa1 476**/\r
477EFI_STATUS\r
478EFIAPI\r
479ShellOpenFileByDevicePath(\r
b0934ac4 480 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,\r
481 OUT EFI_HANDLE *DeviceHandle,\r
a405b86d 482 OUT SHELL_FILE_HANDLE *FileHandle,\r
b0934ac4 483 IN UINT64 OpenMode,\r
484 IN UINT64 Attributes\r
a405b86d 485 )\r
486{\r
487 CHAR16 *FileName;\r
488 EFI_STATUS Status;\r
94b17fa1 489 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;\r
a405b86d 490 EFI_FILE_PROTOCOL *Handle1;\r
491 EFI_FILE_PROTOCOL *Handle2;\r
0b6cb335
ED
492 CHAR16 *FnafPathName;\r
493 UINTN PathLen;\r
94b17fa1 494\r
92a5447e 495 if (FilePath == NULL || FileHandle == NULL || DeviceHandle == NULL) {\r
496 return (EFI_INVALID_PARAMETER);\r
497 }\r
498\r
1e6e84c7 499 //\r
94b17fa1 500 // which shell interface should we use\r
501 //\r
366f81a0 502 if (gEfiShellProtocol != NULL) {\r
94b17fa1 503 //\r
504 // use UEFI Shell 2.0 method.\r
505 //\r
366f81a0 506 FileName = gEfiShellProtocol->GetFilePathFromDevicePath(*FilePath);\r
94b17fa1 507 if (FileName == NULL) {\r
508 return (EFI_INVALID_PARAMETER);\r
509 }\r
510 Status = ShellOpenFileByName(FileName, FileHandle, OpenMode, Attributes);\r
511 FreePool(FileName);\r
512 return (Status);\r
1e6e84c7 513 }\r
d2b4564b 514\r
515\r
516 //\r
517 // use old shell method.\r
518 //\r
1e6e84c7 519 Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid,\r
520 FilePath,\r
d2b4564b 521 DeviceHandle);\r
522 if (EFI_ERROR (Status)) {\r
523 return Status;\r
524 }\r
525 Status = gBS->OpenProtocol(*DeviceHandle,\r
526 &gEfiSimpleFileSystemProtocolGuid,\r
b1f95a06 527 (VOID**)&EfiSimpleFileSystemProtocol,\r
d2b4564b 528 gImageHandle,\r
529 NULL,\r
530 EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
531 if (EFI_ERROR (Status)) {\r
532 return Status;\r
533 }\r
a405b86d 534 Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);\r
d2b4564b 535 if (EFI_ERROR (Status)) {\r
536 FileHandle = NULL;\r
537 return Status;\r
538 }\r
539\r
540 //\r
541 // go down directories one node at a time.\r
542 //\r
543 while (!IsDevicePathEnd (*FilePath)) {\r
94b17fa1 544 //\r
d2b4564b 545 // For file system access each node should be a file path component\r
94b17fa1 546 //\r
d2b4564b 547 if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||\r
548 DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP\r
a405b86d 549 ) {\r
94b17fa1 550 FileHandle = NULL;\r
d2b4564b 551 return (EFI_INVALID_PARAMETER);\r
94b17fa1 552 }\r
d2b4564b 553 //\r
554 // Open this file path node\r
555 //\r
a405b86d 556 Handle2 = Handle1;\r
557 Handle1 = NULL;\r
94b17fa1 558\r
0b6cb335
ED
559 //\r
560 // File Name Alignment Fix (FNAF)\r
561 // Handle2->Open may be incapable of handling a unaligned CHAR16 data.\r
562 // The structure pointed to by FilePath may be not CHAR16 aligned.\r
563 // This code copies the potentially unaligned PathName data from the\r
564 // FilePath structure to the aligned FnafPathName for use in the\r
565 // calls to Handl2->Open.\r
566 //\r
567\r
568 //\r
569 // Determine length of PathName, in bytes.\r
570 //\r
571 PathLen = DevicePathNodeLength (*FilePath) - SIZE_OF_FILEPATH_DEVICE_PATH;\r
572\r
573 //\r
574 // Allocate memory for the aligned copy of the string Extra allocation is to allow for forced alignment\r
575 // Copy bytes from possibly unaligned location to aligned location\r
576 //\r
577 FnafPathName = AllocateCopyPool(PathLen, (UINT8 *)((FILEPATH_DEVICE_PATH*)*FilePath)->PathName);\r
578 if (FnafPathName == NULL) {\r
579 return EFI_OUT_OF_RESOURCES;\r
580 }\r
581\r
94b17fa1 582 //\r
d2b4564b 583 // Try to test opening an existing file\r
94b17fa1 584 //\r
a405b86d 585 Status = Handle2->Open (\r
586 Handle2,\r
587 &Handle1,\r
0b6cb335 588 FnafPathName,\r
d2b4564b 589 OpenMode &~EFI_FILE_MODE_CREATE,\r
590 0\r
a405b86d 591 );\r
94b17fa1 592\r
d2b4564b 593 //\r
594 // see if the error was that it needs to be created\r
595 //\r
596 if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {\r
a405b86d 597 Status = Handle2->Open (\r
598 Handle2,\r
599 &Handle1,\r
0b6cb335 600 FnafPathName,\r
d2b4564b 601 OpenMode,\r
602 Attributes\r
a405b86d 603 );\r
d2b4564b 604 }\r
0b6cb335
ED
605\r
606 //\r
607 // Free the alignment buffer\r
608 //\r
609 FreePool(FnafPathName);\r
610\r
d2b4564b 611 //\r
612 // Close the last node\r
613 //\r
a405b86d 614 Handle2->Close (Handle2);\r
94b17fa1 615\r
d2b4564b 616 if (EFI_ERROR(Status)) {\r
617 return (Status);\r
94b17fa1 618 }\r
d2b4564b 619\r
620 //\r
621 // Get the next node\r
622 //\r
623 *FilePath = NextDevicePathNode (*FilePath);\r
94b17fa1 624 }\r
a405b86d 625\r
626 //\r
627 // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!\r
628 //\r
629 *FileHandle = (VOID*)Handle1;\r
d2b4564b 630 return (EFI_SUCCESS);\r
94b17fa1 631}\r
632\r
633/**\r
634 This function will open a file or directory referenced by filename.\r
635\r
1e6e84c7 636 If return is EFI_SUCCESS, the Filehandle is the opened file's handle;\r
637 otherwise, the Filehandle is NULL. The Attributes is valid only for\r
94b17fa1 638 EFI_FILE_MODE_CREATE.\r
639\r
92a5447e 640 if FileName is NULL then ASSERT()\r
94b17fa1 641\r
b0934ac4 642 @param FileName pointer to file name\r
643 @param FileHandle pointer to the file handle.\r
644 @param OpenMode the mode to open the file with.\r
645 @param Attributes the file's file attributes.\r
94b17fa1 646\r
b0934ac4 647 @retval EFI_SUCCESS The information was set.\r
648 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
649 @retval EFI_UNSUPPORTED Could not open the file path.\r
650 @retval EFI_NOT_FOUND The specified file could not be found on the\r
1e6e84c7 651 device or the file system could not be found\r
94b17fa1 652 on the device.\r
b0934ac4 653 @retval EFI_NO_MEDIA The device has no medium.\r
654 @retval EFI_MEDIA_CHANGED The device has a different medium in it or the\r
94b17fa1 655 medium is no longer supported.\r
b0934ac4 656 @retval EFI_DEVICE_ERROR The device reported an error.\r
657 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
658 @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
659 @retval EFI_ACCESS_DENIED The file was opened read only.\r
660 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
94b17fa1 661 file.\r
b0934ac4 662 @retval EFI_VOLUME_FULL The volume is full.\r
94b17fa1 663**/\r
664EFI_STATUS\r
665EFIAPI\r
666ShellOpenFileByName(\r
b0934ac4 667 IN CONST CHAR16 *FileName,\r
a405b86d 668 OUT SHELL_FILE_HANDLE *FileHandle,\r
94b17fa1 669 IN UINT64 OpenMode,\r
b0934ac4 670 IN UINT64 Attributes\r
a405b86d 671 )\r
672{\r
94b17fa1 673 EFI_HANDLE DeviceHandle;\r
674 EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
b1f95a06 675 EFI_STATUS Status;\r
676 EFI_FILE_INFO *FileInfo;\r
21a86a7d 677 CHAR16 *FileNameCopy;\r
dd17e3fe 678 EFI_STATUS Status2;\r
94b17fa1 679\r
680 //\r
681 // ASSERT if FileName is NULL\r
682 //\r
683 ASSERT(FileName != NULL);\r
684\r
a405b86d 685 if (FileName == NULL) {\r
686 return (EFI_INVALID_PARAMETER);\r
687 }\r
688\r
366f81a0 689 if (gEfiShellProtocol != NULL) {\r
21a86a7d 690 if ((OpenMode & EFI_FILE_MODE_CREATE) == EFI_FILE_MODE_CREATE) {\r
691\r
692 //\r
693 // Create only a directory\r
694 //\r
695 if ((Attributes & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {\r
696 return ShellCreateDirectory(FileName, FileHandle);\r
697 }\r
698\r
699 //\r
700 // Create the directory to create the file in\r
701 //\r
702 FileNameCopy = AllocateCopyPool (StrSize (FileName), FileName);\r
52208978 703 if (FileNameCopy == NULL) {\r
21a86a7d 704 return (EFI_OUT_OF_RESOURCES);\r
705 }\r
706 PathCleanUpDirectories (FileNameCopy);\r
707 if (PathRemoveLastItem (FileNameCopy)) {\r
983fffd4
JC
708 if (!EFI_ERROR(ShellCreateDirectory (FileNameCopy, FileHandle))) {\r
709 ShellCloseFile (FileHandle);\r
710 }\r
21a86a7d 711 }\r
712 SHELL_FREE_NON_NULL (FileNameCopy);\r
a405b86d 713 }\r
21a86a7d 714\r
94b17fa1 715 //\r
21a86a7d 716 // Use UEFI Shell 2.0 method to create the file\r
94b17fa1 717 //\r
366f81a0 718 Status = gEfiShellProtocol->OpenFileByName(FileName,\r
b1f95a06 719 FileHandle,\r
720 OpenMode);\r
f9c3b1b5
VO
721 if (EFI_ERROR(Status)) {\r
722 return Status;\r
723 }\r
583448b4 724\r
2cf9ecd2
TS
725 if (mUnicodeCollationProtocol == NULL) {\r
726 Status = gBS->LocateProtocol (&gEfiUnicodeCollation2ProtocolGuid, NULL, (VOID**)&mUnicodeCollationProtocol);\r
727 if (EFI_ERROR (Status)) {\r
728 gEfiShellProtocol->CloseFile (*FileHandle);\r
729 return Status;\r
730 }\r
731 }\r
732\r
583448b4
TS
733 if ((mUnicodeCollationProtocol->StriColl (mUnicodeCollationProtocol, (CHAR16*)FileName, L"NUL") != 0) &&\r
734 (mUnicodeCollationProtocol->StriColl (mUnicodeCollationProtocol, (CHAR16*)FileName, L"NULL") != 0) &&\r
735 !EFI_ERROR(Status) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)){\r
2247dde4 736 FileInfo = FileFunctionMap.GetFileInfo(*FileHandle);\r
b1f95a06 737 ASSERT(FileInfo != NULL);\r
738 FileInfo->Attribute = Attributes;\r
dd17e3fe 739 Status2 = FileFunctionMap.SetFileInfo(*FileHandle, FileInfo);\r
2247dde4 740 FreePool(FileInfo);\r
dd17e3fe
JY
741 if (EFI_ERROR (Status2)) {\r
742 gEfiShellProtocol->CloseFile(*FileHandle);\r
743 }\r
744 Status = Status2;\r
b1f95a06 745 }\r
746 return (Status);\r
1e6e84c7 747 }\r
94b17fa1 748 //\r
749 // Using EFI Shell version\r
750 // this means convert name to path and call that function\r
751 // since this will use EFI method again that will open it.\r
752 //\r
753 ASSERT(mEfiShellEnvironment2 != NULL);\r
b82bfcc1 754 FilePath = mEfiShellEnvironment2->NameToPath ((CHAR16*)FileName);\r
90bfa227 755 if (FilePath != NULL) {\r
94b17fa1 756 return (ShellOpenFileByDevicePath(&FilePath,\r
757 &DeviceHandle,\r
758 FileHandle,\r
759 OpenMode,\r
a405b86d 760 Attributes));\r
94b17fa1 761 }\r
762 return (EFI_DEVICE_ERROR);\r
763}\r
764/**\r
765 This function create a directory\r
766\r
1e6e84c7 767 If return is EFI_SUCCESS, the Filehandle is the opened directory's handle;\r
768 otherwise, the Filehandle is NULL. If the directory already existed, this\r
94b17fa1 769 function opens the existing directory.\r
770\r
b0934ac4 771 @param DirectoryName pointer to directory name\r
772 @param FileHandle pointer to the file handle.\r
94b17fa1 773\r
b0934ac4 774 @retval EFI_SUCCESS The information was set.\r
775 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
776 @retval EFI_UNSUPPORTED Could not open the file path.\r
777 @retval EFI_NOT_FOUND The specified file could not be found on the\r
1e6e84c7 778 device or the file system could not be found\r
94b17fa1 779 on the device.\r
b0934ac4 780 @retval EFI_NO_MEDIA The device has no medium.\r
781 @retval EFI_MEDIA_CHANGED The device has a different medium in it or the\r
94b17fa1 782 medium is no longer supported.\r
b0934ac4 783 @retval EFI_DEVICE_ERROR The device reported an error.\r
784 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
785 @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
786 @retval EFI_ACCESS_DENIED The file was opened read only.\r
787 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
94b17fa1 788 file.\r
b0934ac4 789 @retval EFI_VOLUME_FULL The volume is full.\r
94b17fa1 790 @sa ShellOpenFileByName\r
791**/\r
792EFI_STATUS\r
793EFIAPI\r
794ShellCreateDirectory(\r
b82bfcc1 795 IN CONST CHAR16 *DirectoryName,\r
a405b86d 796 OUT SHELL_FILE_HANDLE *FileHandle\r
797 )\r
798{\r
366f81a0 799 if (gEfiShellProtocol != NULL) {\r
2247dde4 800 //\r
801 // Use UEFI Shell 2.0 method\r
802 //\r
366f81a0 803 return (gEfiShellProtocol->CreateFile(DirectoryName,\r
2247dde4 804 EFI_FILE_DIRECTORY,\r
805 FileHandle\r
a405b86d 806 ));\r
2247dde4 807 } else {\r
808 return (ShellOpenFileByName(DirectoryName,\r
809 FileHandle,\r
810 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,\r
811 EFI_FILE_DIRECTORY\r
a405b86d 812 ));\r
2247dde4 813 }\r
94b17fa1 814}\r
815\r
816/**\r
817 This function reads information from an opened file.\r
818\r
1e6e84c7 819 If FileHandle is not a directory, the function reads the requested number of\r
820 bytes from the file at the file's current position and returns them in Buffer.\r
94b17fa1 821 If the read goes beyond the end of the file, the read length is truncated to the\r
1e6e84c7 822 end of the file. The file's current position is increased by the number of bytes\r
823 returned. If FileHandle is a directory, the function reads the directory entry\r
824 at the file's current position and returns the entry in Buffer. If the Buffer\r
825 is not large enough to hold the current directory entry, then\r
826 EFI_BUFFER_TOO_SMALL is returned and the current file position is not updated.\r
827 BufferSize is set to be the size of the buffer needed to read the entry. On\r
828 success, the current position is updated to the next directory entry. If there\r
829 are no more directory entries, the read returns a zero-length buffer.\r
94b17fa1 830 EFI_FILE_INFO is the structure returned as the directory entry.\r
831\r
832 @param FileHandle the opened file handle\r
1e6e84c7 833 @param BufferSize on input the size of buffer in bytes. on return\r
94b17fa1 834 the number of bytes written.\r
835 @param Buffer the buffer to put read data into.\r
836\r
b0934ac4 837 @retval EFI_SUCCESS Data was read.\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_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required\r
94b17fa1 842 size.\r
843\r
844**/\r
845EFI_STATUS\r
846EFIAPI\r
847ShellReadFile(\r
a405b86d 848 IN SHELL_FILE_HANDLE FileHandle,\r
94b17fa1 849 IN OUT UINTN *BufferSize,\r
850 OUT VOID *Buffer\r
a405b86d 851 )\r
852{\r
d2b4564b 853 return (FileFunctionMap.ReadFile(FileHandle, BufferSize, Buffer));\r
94b17fa1 854}\r
855\r
856\r
857/**\r
858 Write data to a file.\r
859\r
1e6e84c7 860 This function writes the specified number of bytes to the file at the current\r
861 file position. The current file position is advanced the actual number of bytes\r
862 written, which is returned in BufferSize. Partial writes only occur when there\r
863 has been a data error during the write attempt (such as "volume space full").\r
864 The file is automatically grown to hold the data if required. Direct writes to\r
94b17fa1 865 opened directories are not supported.\r
866\r
867 @param FileHandle The opened file for writing\r
868 @param BufferSize on input the number of bytes in Buffer. On output\r
869 the number of bytes written.\r
870 @param Buffer the buffer containing data to write is stored.\r
871\r
b0934ac4 872 @retval EFI_SUCCESS Data was written.\r
873 @retval EFI_UNSUPPORTED Writes to an open directory are not supported.\r
874 @retval EFI_NO_MEDIA The device has no media.\r
875 @retval EFI_DEVICE_ERROR The device reported an error.\r
876 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
877 @retval EFI_WRITE_PROTECTED The device is write-protected.\r
878 @retval EFI_ACCESS_DENIED The file was open for read only.\r
879 @retval EFI_VOLUME_FULL The volume is full.\r
94b17fa1 880**/\r
881EFI_STATUS\r
882EFIAPI\r
883ShellWriteFile(\r
252d9457 884 IN SHELL_FILE_HANDLE FileHandle,\r
94b17fa1 885 IN OUT UINTN *BufferSize,\r
886 IN VOID *Buffer\r
a405b86d 887 )\r
888{\r
d2b4564b 889 return (FileFunctionMap.WriteFile(FileHandle, BufferSize, Buffer));\r
94b17fa1 890}\r
891\r
1e6e84c7 892/**\r
94b17fa1 893 Close an open file handle.\r
894\r
1e6e84c7 895 This function closes a specified file handle. All "dirty" cached file data is\r
896 flushed to the device, and the file is closed. In all cases the handle is\r
94b17fa1 897 closed.\r
898\r
899@param FileHandle the file handle to close.\r
900\r
901@retval EFI_SUCCESS the file handle was closed sucessfully.\r
902**/\r
903EFI_STATUS\r
904EFIAPI\r
905ShellCloseFile (\r
a405b86d 906 IN SHELL_FILE_HANDLE *FileHandle\r
907 )\r
908{\r
d2b4564b 909 return (FileFunctionMap.CloseFile(*FileHandle));\r
94b17fa1 910}\r
911\r
912/**\r
913 Delete a file and close the handle\r
914\r
915 This function closes and deletes a file. In all cases the file handle is closed.\r
1e6e84c7 916 If the file cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is\r
94b17fa1 917 returned, but the handle is still closed.\r
918\r
919 @param FileHandle the file handle to delete\r
920\r
921 @retval EFI_SUCCESS the file was closed sucessfully\r
1e6e84c7 922 @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not\r
94b17fa1 923 deleted\r
b0934ac4 924 @retval INVALID_PARAMETER One of the parameters has an invalid value.\r
94b17fa1 925**/\r
926EFI_STATUS\r
927EFIAPI\r
928ShellDeleteFile (\r
b0934ac4 929 IN SHELL_FILE_HANDLE *FileHandle\r
a405b86d 930 )\r
931{\r
d2b4564b 932 return (FileFunctionMap.DeleteFile(*FileHandle));\r
94b17fa1 933}\r
934\r
935/**\r
936 Set the current position in a file.\r
937\r
1e6e84c7 938 This function sets the current file position for the handle to the position\r
94b17fa1 939 supplied. With the exception of seeking to position 0xFFFFFFFFFFFFFFFF, only\r
1e6e84c7 940 absolute positioning is supported, and seeking past the end of the file is\r
941 allowed (a subsequent write would grow the file). Seeking to position\r
94b17fa1 942 0xFFFFFFFFFFFFFFFF causes the current position to be set to the end of the file.\r
1e6e84c7 943 If FileHandle is a directory, the only position that may be set is zero. This\r
94b17fa1 944 has the effect of starting the read process of the directory entries over.\r
945\r
946 @param FileHandle The file handle on which the position is being set\r
947 @param Position Byte position from begining of file\r
948\r
949 @retval EFI_SUCCESS Operation completed sucessfully.\r
1e6e84c7 950 @retval EFI_UNSUPPORTED the seek request for non-zero is not valid on\r
94b17fa1 951 directories.\r
952 @retval INVALID_PARAMETER One of the parameters has an invalid value.\r
953**/\r
954EFI_STATUS\r
955EFIAPI\r
956ShellSetFilePosition (\r
b0934ac4 957 IN SHELL_FILE_HANDLE FileHandle,\r
958 IN UINT64 Position\r
a405b86d 959 )\r
960{\r
d2b4564b 961 return (FileFunctionMap.SetFilePosition(FileHandle, Position));\r
94b17fa1 962}\r
963\r
1e6e84c7 964/**\r
94b17fa1 965 Gets a file's current position\r
966\r
1e6e84c7 967 This function retrieves the current file position for the file handle. For\r
968 directories, the current file position has no meaning outside of the file\r
94b17fa1 969 system driver and as such the operation is not supported. An error is returned\r
970 if FileHandle is a directory.\r
971\r
972 @param FileHandle The open file handle on which to get the position.\r
973 @param Position Byte position from begining of file.\r
974\r
975 @retval EFI_SUCCESS the operation completed sucessfully.\r
976 @retval INVALID_PARAMETER One of the parameters has an invalid value.\r
977 @retval EFI_UNSUPPORTED the request is not valid on directories.\r
978**/\r
979EFI_STATUS\r
980EFIAPI\r
981ShellGetFilePosition (\r
a405b86d 982 IN SHELL_FILE_HANDLE FileHandle,\r
94b17fa1 983 OUT UINT64 *Position\r
a405b86d 984 )\r
985{\r
d2b4564b 986 return (FileFunctionMap.GetFilePosition(FileHandle, Position));\r
94b17fa1 987}\r
988/**\r
989 Flushes data on a file\r
1e6e84c7 990\r
94b17fa1 991 This function flushes all modified data associated with a file to a device.\r
992\r
993 @param FileHandle The file handle on which to flush data\r
994\r
995 @retval EFI_SUCCESS The data was flushed.\r
996 @retval EFI_NO_MEDIA The device has no media.\r
997 @retval EFI_DEVICE_ERROR The device reported an error.\r
998 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
999 @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
1000 @retval EFI_ACCESS_DENIED The file was opened for read only.\r
1001**/\r
1002EFI_STATUS\r
1003EFIAPI\r
1004ShellFlushFile (\r
a405b86d 1005 IN SHELL_FILE_HANDLE FileHandle\r
1006 )\r
1007{\r
d2b4564b 1008 return (FileFunctionMap.FlushFile(FileHandle));\r
94b17fa1 1009}\r
1010\r
b0934ac4 1011/** Retrieve first entry from a directory.\r
94b17fa1 1012\r
b0934ac4 1013 This function takes an open directory handle and gets information from the\r
1014 first entry in the directory. A buffer is allocated to contain\r
1015 the information and a pointer to the buffer is returned in *Buffer. The\r
1016 caller can use ShellFindNextFile() to get subsequent directory entries.\r
94b17fa1 1017\r
b0934ac4 1018 The buffer will be freed by ShellFindNextFile() when the last directory\r
1019 entry is read. Otherwise, the caller must free the buffer, using FreePool,\r
1020 when finished with it.\r
1021\r
1022 @param[in] DirHandle The file handle of the directory to search.\r
1023 @param[out] Buffer The pointer to the buffer for the file's information.\r
94b17fa1 1024\r
1025 @retval EFI_SUCCESS Found the first file.\r
1026 @retval EFI_NOT_FOUND Cannot find the directory.\r
1027 @retval EFI_NO_MEDIA The device has no media.\r
1028 @retval EFI_DEVICE_ERROR The device reported an error.\r
1029 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
1030 @return Others status of ShellGetFileInfo, ShellSetFilePosition,\r
1031 or ShellReadFile\r
1032**/\r
1033EFI_STATUS\r
1034EFIAPI\r
1035ShellFindFirstFile (\r
a405b86d 1036 IN SHELL_FILE_HANDLE DirHandle,\r
d2b4564b 1037 OUT EFI_FILE_INFO **Buffer\r
a405b86d 1038 )\r
1039{\r
94b17fa1 1040 //\r
d2b4564b 1041 // pass to file handle lib\r
94b17fa1 1042 //\r
d2b4564b 1043 return (FileHandleFindFirstFile(DirHandle, Buffer));\r
94b17fa1 1044}\r
b0934ac4 1045/** Retrieve next entries from a directory.\r
94b17fa1 1046\r
b0934ac4 1047 To use this function, the caller must first call the ShellFindFirstFile()\r
1048 function to get the first directory entry. Subsequent directory entries are\r
1049 retrieved by using the ShellFindNextFile() function. This function can\r
1050 be called several times to get each entry from the directory. If the call of\r
1051 ShellFindNextFile() retrieved the last directory entry, the next call of\r
1052 this function will set *NoFile to TRUE and free the buffer.\r
94b17fa1 1053\r
b0934ac4 1054 @param[in] DirHandle The file handle of the directory.\r
1055 @param[out] Buffer The pointer to buffer for file's information.\r
1056 @param[out] NoFile The pointer to boolean when last file is found.\r
94b17fa1 1057\r
1058 @retval EFI_SUCCESS Found the next file, or reached last file\r
1059 @retval EFI_NO_MEDIA The device has no media.\r
1060 @retval EFI_DEVICE_ERROR The device reported an error.\r
1061 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
1062**/\r
1063EFI_STATUS\r
1064EFIAPI\r
1065ShellFindNextFile(\r
a405b86d 1066 IN SHELL_FILE_HANDLE DirHandle,\r
94b17fa1 1067 OUT EFI_FILE_INFO *Buffer,\r
1068 OUT BOOLEAN *NoFile\r
a405b86d 1069 )\r
1070{\r
94b17fa1 1071 //\r
d2b4564b 1072 // pass to file handle lib\r
94b17fa1 1073 //\r
d2b4564b 1074 return (FileHandleFindNextFile(DirHandle, Buffer, NoFile));\r
94b17fa1 1075}\r
1076/**\r
1077 Retrieve the size of a file.\r
1078\r
1079 if FileHandle is NULL then ASSERT()\r
1080 if Size is NULL then ASSERT()\r
1081\r
1e6e84c7 1082 This function extracts the file size info from the FileHandle's EFI_FILE_INFO\r
94b17fa1 1083 data.\r
1084\r
1085 @param FileHandle file handle from which size is retrieved\r
1086 @param Size pointer to size\r
1087\r
1088 @retval EFI_SUCCESS operation was completed sucessfully\r
1089 @retval EFI_DEVICE_ERROR cannot access the file\r
1090**/\r
1091EFI_STATUS\r
1092EFIAPI\r
1093ShellGetFileSize (\r
a405b86d 1094 IN SHELL_FILE_HANDLE FileHandle,\r
94b17fa1 1095 OUT UINT64 *Size\r
a405b86d 1096 )\r
1097{\r
d2b4564b 1098 return (FileFunctionMap.GetFileSize(FileHandle, Size));\r
94b17fa1 1099}\r
1100/**\r
1101 Retrieves the status of the break execution flag\r
1102\r
1103 this function is useful to check whether the application is being asked to halt by the shell.\r
1104\r
1105 @retval TRUE the execution break is enabled\r
1106 @retval FALSE the execution break is not enabled\r
1107**/\r
1108BOOLEAN\r
1109EFIAPI\r
1110ShellGetExecutionBreakFlag(\r
1111 VOID\r
1112 )\r
1113{\r
1e6e84c7 1114 //\r
94b17fa1 1115 // Check for UEFI Shell 2.0 protocols\r
1116 //\r
366f81a0 1117 if (gEfiShellProtocol != NULL) {\r
94b17fa1 1118\r
1119 //\r
1120 // We are using UEFI Shell 2.0; see if the event has been triggered\r
1121 //\r
366f81a0 1122 if (gBS->CheckEvent(gEfiShellProtocol->ExecutionBreak) != EFI_SUCCESS) {\r
94b17fa1 1123 return (FALSE);\r
1124 }\r
1125 return (TRUE);\r
1e6e84c7 1126 }\r
94b17fa1 1127\r
1128 //\r
1129 // using EFI Shell; call the function to check\r
1130 //\r
92a5447e 1131 if (mEfiShellEnvironment2 != NULL) {\r
1132 return (mEfiShellEnvironment2->GetExecutionBreak());\r
1133 }\r
1134\r
1135 return (FALSE);\r
94b17fa1 1136}\r
1137/**\r
1138 return the value of an environment variable\r
1139\r
1e6e84c7 1140 this function gets the value of the environment variable set by the\r
94b17fa1 1141 ShellSetEnvironmentVariable function\r
1142\r
1143 @param EnvKey The key name of the environment variable.\r
1144\r
1145 @retval NULL the named environment variable does not exist.\r
1146 @return != NULL pointer to the value of the environment variable\r
1147**/\r
1148CONST CHAR16*\r
1149EFIAPI\r
1150ShellGetEnvironmentVariable (\r
9b3bf083 1151 IN CONST CHAR16 *EnvKey\r
94b17fa1 1152 )\r
1153{\r
1e6e84c7 1154 //\r
94b17fa1 1155 // Check for UEFI Shell 2.0 protocols\r
1156 //\r
366f81a0 1157 if (gEfiShellProtocol != NULL) {\r
1158 return (gEfiShellProtocol->GetEnv(EnvKey));\r
94b17fa1 1159 }\r
1160\r
1161 //\r
92a5447e 1162 // Check for EFI shell\r
94b17fa1 1163 //\r
92a5447e 1164 if (mEfiShellEnvironment2 != NULL) {\r
1165 return (mEfiShellEnvironment2->GetEnv((CHAR16*)EnvKey));\r
1166 }\r
94b17fa1 1167\r
92a5447e 1168 return NULL;\r
94b17fa1 1169}\r
1170/**\r
1171 set the value of an environment variable\r
1172\r
1173This function changes the current value of the specified environment variable. If the\r
1174environment variable exists and the Value is an empty string, then the environment\r
1175variable is deleted. If the environment variable exists and the Value is not an empty\r
1176string, then the value of the environment variable is changed. If the environment\r
1177variable does not exist and the Value is an empty string, there is no action. If the\r
1178environment variable does not exist and the Value is a non-empty string, then the\r
1179environment variable is created and assigned the specified value.\r
1180\r
1181 This is not supported pre-UEFI Shell 2.0.\r
1182\r
1183 @param EnvKey The key name of the environment variable.\r
1184 @param EnvVal The Value of the environment variable\r
1185 @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE).\r
1186\r
1187 @retval EFI_SUCCESS the operation was completed sucessfully\r
1188 @retval EFI_UNSUPPORTED This operation is not allowed in pre UEFI 2.0 Shell environments\r
1189**/\r
1190EFI_STATUS\r
1191EFIAPI\r
1192ShellSetEnvironmentVariable (\r
1193 IN CONST CHAR16 *EnvKey,\r
1194 IN CONST CHAR16 *EnvVal,\r
1195 IN BOOLEAN Volatile\r
1196 )\r
1197{\r
1e6e84c7 1198 //\r
94b17fa1 1199 // Check for UEFI Shell 2.0 protocols\r
1200 //\r
366f81a0 1201 if (gEfiShellProtocol != NULL) {\r
1202 return (gEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile));\r
1e6e84c7 1203 }\r
94b17fa1 1204\r
1205 //\r
1206 // This feature does not exist under EFI shell\r
1207 //\r
1208 return (EFI_UNSUPPORTED);\r
1209}\r
a405b86d 1210\r
94b17fa1 1211/**\r
a405b86d 1212 Cause the shell to parse and execute a command line.\r
94b17fa1 1213\r
1214 This function creates a nested instance of the shell and executes the specified\r
a405b86d 1215 command (CommandLine) with the specified environment (Environment). Upon return,\r
1216 the status code returned by the specified command is placed in StatusCode.\r
1217 If Environment is NULL, then the current environment is used and all changes made\r
1218 by the commands executed will be reflected in the current environment. If the\r
1219 Environment is non-NULL, then the changes made will be discarded.\r
1220 The CommandLine is executed from the current working directory on the current\r
1221 device.\r
1222\r
3877d0f5 1223 The EnvironmentVariables pararemeter is ignored in a pre-UEFI Shell 2.0\r
a405b86d 1224 environment. The values pointed to by the parameters will be unchanged by the\r
1225 ShellExecute() function. The Output parameter has no effect in a\r
1226 UEFI Shell 2.0 environment.\r
1227\r
1228 @param[in] ParentHandle The parent image starting the operation.\r
1229 @param[in] CommandLine The pointer to a NULL terminated command line.\r
1230 @param[in] Output True to display debug output. False to hide it.\r
1231 @param[in] EnvironmentVariables Optional pointer to array of environment variables\r
1232 in the form "x=y". If NULL, the current set is used.\r
1233 @param[out] Status The status of the run command line.\r
1234\r
1235 @retval EFI_SUCCESS The operation completed sucessfully. Status\r
1236 contains the status code returned.\r
1237 @retval EFI_INVALID_PARAMETER A parameter contains an invalid value.\r
1238 @retval EFI_OUT_OF_RESOURCES Out of resources.\r
1239 @retval EFI_UNSUPPORTED The operation is not allowed.\r
94b17fa1 1240**/\r
1241EFI_STATUS\r
1242EFIAPI\r
1243ShellExecute (\r
1244 IN EFI_HANDLE *ParentHandle,\r
1245 IN CHAR16 *CommandLine OPTIONAL,\r
1246 IN BOOLEAN Output OPTIONAL,\r
1247 IN CHAR16 **EnvironmentVariables OPTIONAL,\r
1248 OUT EFI_STATUS *Status OPTIONAL\r
1249 )\r
1250{\r
3877d0f5 1251 EFI_STATUS CmdStatus;\r
1e6e84c7 1252 //\r
94b17fa1 1253 // Check for UEFI Shell 2.0 protocols\r
1254 //\r
366f81a0 1255 if (gEfiShellProtocol != NULL) {\r
94b17fa1 1256 //\r
1257 // Call UEFI Shell 2.0 version (not using Output parameter)\r
1258 //\r
366f81a0 1259 return (gEfiShellProtocol->Execute(ParentHandle,\r
94b17fa1 1260 CommandLine,\r
1261 EnvironmentVariables,\r
1262 Status));\r
1e6e84c7 1263 }\r
92a5447e 1264\r
94b17fa1 1265 //\r
92a5447e 1266 // Check for EFI shell\r
94b17fa1 1267 //\r
92a5447e 1268 if (mEfiShellEnvironment2 != NULL) {\r
1269 //\r
3877d0f5 1270 // Call EFI Shell version.\r
92a5447e 1271 // Due to oddity in the EFI shell we want to dereference the ParentHandle here\r
1272 //\r
3877d0f5 1273 CmdStatus = (mEfiShellEnvironment2->Execute(*ParentHandle,\r
92a5447e 1274 CommandLine,\r
1275 Output));\r
3877d0f5
BJ
1276 //\r
1277 // No Status output parameter so just use the returned status\r
1278 //\r
1279 if (Status != NULL) {\r
1280 *Status = CmdStatus;\r
1281 }\r
1282 //\r
1283 // If there was an error, we can't tell if it was from the command or from\r
1284 // the Execute() function, so we'll just assume the shell ran successfully\r
1285 // and the error came from the command.\r
1286 //\r
1287 return EFI_SUCCESS;\r
92a5447e 1288 }\r
1289\r
1290 return (EFI_UNSUPPORTED);\r
94b17fa1 1291}\r
3877d0f5 1292\r
94b17fa1 1293/**\r
1294 Retreives the current directory path\r
1295\r
1e6e84c7 1296 If the DeviceName is NULL, it returns the current device's current directory\r
1297 name. If the DeviceName is not NULL, it returns the current directory name\r
94b17fa1 1298 on specified drive.\r
1299\r
fbd2dfad
QS
1300 Note that the current directory string should exclude the tailing backslash character.\r
1301\r
94b17fa1 1302 @param DeviceName the name of the drive to get directory on\r
1303\r
1304 @retval NULL the directory does not exist\r
1305 @return != NULL the directory\r
1306**/\r
1307CONST CHAR16*\r
1308EFIAPI\r
1309ShellGetCurrentDir (\r
a405b86d 1310 IN CHAR16 * CONST DeviceName OPTIONAL\r
94b17fa1 1311 )\r
1312{\r
1e6e84c7 1313 //\r
94b17fa1 1314 // Check for UEFI Shell 2.0 protocols\r
1315 //\r
366f81a0 1316 if (gEfiShellProtocol != NULL) {\r
1317 return (gEfiShellProtocol->GetCurDir(DeviceName));\r
1e6e84c7 1318 }\r
92a5447e 1319\r
94b17fa1 1320 //\r
8bd282be 1321 // Check for EFI shell\r
94b17fa1 1322 //\r
8bd282be 1323 if (mEfiShellEnvironment2 != NULL) {\r
1324 return (mEfiShellEnvironment2->CurDir(DeviceName));\r
1325 }\r
1326\r
1327 return (NULL);\r
94b17fa1 1328}\r
1329/**\r
1330 sets (enabled or disabled) the page break mode\r
1331\r
1e6e84c7 1332 when page break mode is enabled the screen will stop scrolling\r
94b17fa1 1333 and wait for operator input before scrolling a subsequent screen.\r
1334\r
1335 @param CurrentState TRUE to enable and FALSE to disable\r
1336**/\r
1e6e84c7 1337VOID\r
94b17fa1 1338EFIAPI\r
1339ShellSetPageBreakMode (\r
1340 IN BOOLEAN CurrentState\r
1341 )\r
1342{\r
1343 //\r
1344 // check for enabling\r
1345 //\r
1346 if (CurrentState != 0x00) {\r
1e6e84c7 1347 //\r
94b17fa1 1348 // check for UEFI Shell 2.0\r
1349 //\r
366f81a0 1350 if (gEfiShellProtocol != NULL) {\r
94b17fa1 1351 //\r
1352 // Enable with UEFI 2.0 Shell\r
1353 //\r
366f81a0 1354 gEfiShellProtocol->EnablePageBreak();\r
94b17fa1 1355 return;\r
1356 } else {\r
1e6e84c7 1357 //\r
92a5447e 1358 // Check for EFI shell\r
94b17fa1 1359 //\r
92a5447e 1360 if (mEfiShellEnvironment2 != NULL) {\r
1361 //\r
1362 // Enable with EFI Shell\r
1363 //\r
1364 mEfiShellEnvironment2->EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);\r
1365 return;\r
1366 }\r
94b17fa1 1367 }\r
1368 } else {\r
1e6e84c7 1369 //\r
94b17fa1 1370 // check for UEFI Shell 2.0\r
1371 //\r
366f81a0 1372 if (gEfiShellProtocol != NULL) {\r
94b17fa1 1373 //\r
1374 // Disable with UEFI 2.0 Shell\r
1375 //\r
366f81a0 1376 gEfiShellProtocol->DisablePageBreak();\r
94b17fa1 1377 return;\r
1378 } else {\r
1e6e84c7 1379 //\r
92a5447e 1380 // Check for EFI shell\r
94b17fa1 1381 //\r
92a5447e 1382 if (mEfiShellEnvironment2 != NULL) {\r
1383 //\r
1384 // Disable with EFI Shell\r
1385 //\r
1386 mEfiShellEnvironment2->DisablePageBreak ();\r
1387 return;\r
1388 }\r
94b17fa1 1389 }\r
1390 }\r
1391}\r
1392\r
1393///\r
1394/// version of EFI_SHELL_FILE_INFO struct, except has no CONST pointers.\r
1395/// This allows for the struct to be populated.\r
1396///\r
1397typedef struct {\r
d2b4564b 1398 LIST_ENTRY Link;\r
94b17fa1 1399 EFI_STATUS Status;\r
1400 CHAR16 *FullName;\r
1401 CHAR16 *FileName;\r
a405b86d 1402 SHELL_FILE_HANDLE Handle;\r
94b17fa1 1403 EFI_FILE_INFO *Info;\r
1404} EFI_SHELL_FILE_INFO_NO_CONST;\r
1405\r
1406/**\r
1407 Converts a EFI shell list of structures to the coresponding UEFI Shell 2.0 type of list.\r
1408\r
1409 if OldStyleFileList is NULL then ASSERT()\r
1410\r
1e6e84c7 1411 this function will convert a SHELL_FILE_ARG based list into a callee allocated\r
94b17fa1 1412 EFI_SHELL_FILE_INFO based list. it is up to the caller to free the memory via\r
1413 the ShellCloseFileMetaArg function.\r
1414\r
4ff7e37b
ED
1415 @param[in] FileList the EFI shell list type\r
1416 @param[in, out] ListHead the list to add to\r
94b17fa1 1417\r
1418 @retval the resultant head of the double linked new format list;\r
1419**/\r
1420LIST_ENTRY*\r
94b17fa1 1421InternalShellConvertFileListType (\r
9b3bf083 1422 IN LIST_ENTRY *FileList,\r
1423 IN OUT LIST_ENTRY *ListHead\r
125c2cf4 1424 )\r
1425{\r
94b17fa1 1426 SHELL_FILE_ARG *OldInfo;\r
9b3bf083 1427 LIST_ENTRY *Link;\r
94b17fa1 1428 EFI_SHELL_FILE_INFO_NO_CONST *NewInfo;\r
1429\r
1430 //\r
9b3bf083 1431 // ASSERTs\r
94b17fa1 1432 //\r
9b3bf083 1433 ASSERT(FileList != NULL);\r
1434 ASSERT(ListHead != NULL);\r
94b17fa1 1435\r
1436 //\r
1437 // enumerate through each member of the old list and copy\r
1438 //\r
d2b4564b 1439 for (Link = FileList->ForwardLink; Link != FileList; Link = Link->ForwardLink) {\r
94b17fa1 1440 OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);\r
a405b86d 1441 ASSERT(OldInfo != NULL);\r
1442\r
1443 //\r
1444 // Skip ones that failed to open...\r
1445 //\r
1446 if (OldInfo->Status != EFI_SUCCESS) {\r
1447 continue;\r
1448 }\r
94b17fa1 1449\r
1450 //\r
1451 // make sure the old list was valid\r
1452 //\r
94b17fa1 1453 ASSERT(OldInfo->Info != NULL);\r
1454 ASSERT(OldInfo->FullName != NULL);\r
1455 ASSERT(OldInfo->FileName != NULL);\r
1456\r
1457 //\r
1458 // allocate a new EFI_SHELL_FILE_INFO object\r
1459 //\r
1460 NewInfo = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
c9d92df0 1461 if (NewInfo == NULL) {\r
7a95efda 1462 ShellCloseFileMetaArg((EFI_SHELL_FILE_INFO**)(&ListHead));\r
beab0fc5 1463 ListHead = NULL;\r
c9d92df0 1464 break;\r
1465 }\r
1e6e84c7 1466\r
1467 //\r
94b17fa1 1468 // copy the simple items\r
1469 //\r
1470 NewInfo->Handle = OldInfo->Handle;\r
1471 NewInfo->Status = OldInfo->Status;\r
1472\r
d2b4564b 1473 // old shell checks for 0 not NULL\r
1474 OldInfo->Handle = 0;\r
1475\r
94b17fa1 1476 //\r
1477 // allocate new space to copy strings and structure\r
1478 //\r
98c16be5
JC
1479 NewInfo->FullName = AllocateCopyPool(StrSize(OldInfo->FullName), OldInfo->FullName);\r
1480 NewInfo->FileName = AllocateCopyPool(StrSize(OldInfo->FileName), OldInfo->FileName);\r
1481 NewInfo->Info = AllocateCopyPool((UINTN)OldInfo->Info->Size, OldInfo->Info);\r
1e6e84c7 1482\r
94b17fa1 1483 //\r
1484 // make sure all the memory allocations were sucessful\r
1485 //\r
beab0fc5 1486 if (NULL == NewInfo->FullName || NewInfo->FileName == NULL || NewInfo->Info == NULL) {\r
98c16be5
JC
1487 //\r
1488 // Free the partially allocated new node\r
1489 //\r
1490 SHELL_FREE_NON_NULL(NewInfo->FullName);\r
1491 SHELL_FREE_NON_NULL(NewInfo->FileName);\r
1492 SHELL_FREE_NON_NULL(NewInfo->Info);\r
1493 SHELL_FREE_NON_NULL(NewInfo);\r
1494\r
1495 //\r
1496 // Free the previously converted stuff\r
1497 //\r
7a95efda 1498 ShellCloseFileMetaArg((EFI_SHELL_FILE_INFO**)(&ListHead));\r
beab0fc5 1499 ListHead = NULL;\r
1500 break;\r
1501 }\r
94b17fa1 1502\r
94b17fa1 1503 //\r
1504 // add that to the list\r
1505 //\r
9b3bf083 1506 InsertTailList(ListHead, &NewInfo->Link);\r
94b17fa1 1507 }\r
1508 return (ListHead);\r
1509}\r
1510/**\r
1511 Opens a group of files based on a path.\r
1512\r
1e6e84c7 1513 This function uses the Arg to open all the matching files. Each matched\r
70879314
BJ
1514 file has a SHELL_FILE_INFO structure to record the file information. These\r
1515 structures are placed on the list ListHead. Users can get the SHELL_FILE_INFO\r
94b17fa1 1516 structures from ListHead to access each file. This function supports wildcards\r
1e6e84c7 1517 and will process '?' and '*' as such. the list must be freed with a call to\r
94b17fa1 1518 ShellCloseFileMetaArg().\r
1519\r
1e6e84c7 1520 If you are NOT appending to an existing list *ListHead must be NULL. If\r
5f7431d0 1521 *ListHead is NULL then it must be callee freed.\r
94b17fa1 1522\r
1523 @param Arg pointer to path string\r
1524 @param OpenMode mode to open files with\r
1525 @param ListHead head of linked list of results\r
1526\r
1e6e84c7 1527 @retval EFI_SUCCESS the operation was sucessful and the list head\r
94b17fa1 1528 contains the list of opened files\r
94b17fa1 1529 @return != EFI_SUCCESS the operation failed\r
1530\r
1531 @sa InternalShellConvertFileListType\r
1532**/\r
1533EFI_STATUS\r
1534EFIAPI\r
1535ShellOpenFileMetaArg (\r
1536 IN CHAR16 *Arg,\r
1537 IN UINT64 OpenMode,\r
1538 IN OUT EFI_SHELL_FILE_INFO **ListHead\r
1539 )\r
1540{\r
1541 EFI_STATUS Status;\r
9b3bf083 1542 LIST_ENTRY mOldStyleFileList;\r
0960ba17 1543 CHAR16 *CleanFilePathStr;\r
1e6e84c7 1544\r
94b17fa1 1545 //\r
1546 // ASSERT that Arg and ListHead are not NULL\r
1547 //\r
1548 ASSERT(Arg != NULL);\r
1549 ASSERT(ListHead != NULL);\r
1550\r
715096c2
QS
1551 CleanFilePathStr = NULL;\r
1552\r
0960ba17
QS
1553 Status = InternalShellStripQuotes (Arg, &CleanFilePathStr);\r
1554 if (EFI_ERROR (Status)) {\r
1555 return Status;\r
1556 }\r
1557\r
1e6e84c7 1558 //\r
94b17fa1 1559 // Check for UEFI Shell 2.0 protocols\r
1560 //\r
366f81a0 1561 if (gEfiShellProtocol != NULL) {\r
5f7431d0 1562 if (*ListHead == NULL) {\r
1563 *ListHead = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
1564 if (*ListHead == NULL) {\r
0960ba17 1565 FreePool(CleanFilePathStr);\r
5f7431d0 1566 return (EFI_OUT_OF_RESOURCES);\r
1567 }\r
1568 InitializeListHead(&((*ListHead)->Link));\r
1e6e84c7 1569 }\r
0960ba17 1570 Status = gEfiShellProtocol->OpenFileList(CleanFilePathStr,\r
1e6e84c7 1571 OpenMode,\r
2247dde4 1572 ListHead);\r
1573 if (EFI_ERROR(Status)) {\r
366f81a0 1574 gEfiShellProtocol->RemoveDupInFileList(ListHead);\r
2247dde4 1575 } else {\r
366f81a0 1576 Status = gEfiShellProtocol->RemoveDupInFileList(ListHead);\r
2247dde4 1577 }\r
a405b86d 1578 if (*ListHead != NULL && IsListEmpty(&(*ListHead)->Link)) {\r
1579 FreePool(*ListHead);\r
0960ba17 1580 FreePool(CleanFilePathStr);\r
a405b86d 1581 *ListHead = NULL;\r
1582 return (EFI_NOT_FOUND);\r
1583 }\r
0960ba17 1584 FreePool(CleanFilePathStr);\r
2247dde4 1585 return (Status);\r
1e6e84c7 1586 }\r
94b17fa1 1587\r
1588 //\r
92a5447e 1589 // Check for EFI shell\r
94b17fa1 1590 //\r
92a5447e 1591 if (mEfiShellEnvironment2 != NULL) {\r
1592 //\r
1593 // make sure the list head is initialized\r
1594 //\r
1595 InitializeListHead(&mOldStyleFileList);\r
94b17fa1 1596\r
92a5447e 1597 //\r
1598 // Get the EFI Shell list of files\r
1599 //\r
0960ba17 1600 Status = mEfiShellEnvironment2->FileMetaArg(CleanFilePathStr, &mOldStyleFileList);\r
92a5447e 1601 if (EFI_ERROR(Status)) {\r
1602 *ListHead = NULL;\r
0960ba17 1603 FreePool(CleanFilePathStr);\r
92a5447e 1604 return (Status);\r
1605 }\r
94b17fa1 1606\r
9b3bf083 1607 if (*ListHead == NULL) {\r
92a5447e 1608 *ListHead = (EFI_SHELL_FILE_INFO *)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
1609 if (*ListHead == NULL) {\r
0960ba17 1610 FreePool(CleanFilePathStr);\r
92a5447e 1611 return (EFI_OUT_OF_RESOURCES);\r
1612 }\r
1613 InitializeListHead(&((*ListHead)->Link));\r
9b3bf083 1614 }\r
9b3bf083 1615\r
92a5447e 1616 //\r
1617 // Convert that to equivalent of UEFI Shell 2.0 structure\r
1618 //\r
1619 InternalShellConvertFileListType(&mOldStyleFileList, &(*ListHead)->Link);\r
94b17fa1 1620\r
92a5447e 1621 //\r
1622 // Free the EFI Shell version that was converted.\r
1623 //\r
1624 mEfiShellEnvironment2->FreeFileList(&mOldStyleFileList);\r
94b17fa1 1625\r
92a5447e 1626 if ((*ListHead)->Link.ForwardLink == (*ListHead)->Link.BackLink && (*ListHead)->Link.BackLink == &((*ListHead)->Link)) {\r
1627 FreePool(*ListHead);\r
1628 *ListHead = NULL;\r
1629 Status = EFI_NOT_FOUND;\r
1630 }\r
0960ba17 1631 FreePool(CleanFilePathStr);\r
92a5447e 1632 return (Status);\r
a405b86d 1633 }\r
1634\r
0960ba17 1635 FreePool(CleanFilePathStr);\r
92a5447e 1636 return (EFI_UNSUPPORTED);\r
94b17fa1 1637}\r
1638/**\r
a405b86d 1639 Free the linked list returned from ShellOpenFileMetaArg.\r
94b17fa1 1640\r
a405b86d 1641 if ListHead is NULL then ASSERT().\r
94b17fa1 1642\r
a405b86d 1643 @param ListHead the pointer to free.\r
94b17fa1 1644\r
a405b86d 1645 @retval EFI_SUCCESS the operation was sucessful.\r
94b17fa1 1646**/\r
1647EFI_STATUS\r
1648EFIAPI\r
1649ShellCloseFileMetaArg (\r
1650 IN OUT EFI_SHELL_FILE_INFO **ListHead\r
1651 )\r
1652{\r
1653 LIST_ENTRY *Node;\r
1654\r
1655 //\r
1656 // ASSERT that ListHead is not NULL\r
1657 //\r
1658 ASSERT(ListHead != NULL);\r
1659\r
1e6e84c7 1660 //\r
94b17fa1 1661 // Check for UEFI Shell 2.0 protocols\r
1662 //\r
366f81a0 1663 if (gEfiShellProtocol != NULL) {\r
1664 return (gEfiShellProtocol->FreeFileList(ListHead));\r
92a5447e 1665 } else if (mEfiShellEnvironment2 != NULL) {\r
94b17fa1 1666 //\r
1e6e84c7 1667 // Since this is EFI Shell version we need to free our internally made copy\r
94b17fa1 1668 // of the list\r
1669 //\r
1e6e84c7 1670 for ( Node = GetFirstNode(&(*ListHead)->Link)\r
a405b86d 1671 ; *ListHead != NULL && !IsListEmpty(&(*ListHead)->Link)\r
9b3bf083 1672 ; Node = GetFirstNode(&(*ListHead)->Link)) {\r
94b17fa1 1673 RemoveEntryList(Node);\r
a405b86d 1674 ((EFI_FILE_PROTOCOL*)((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle)->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle);\r
94b17fa1 1675 FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FullName);\r
1676 FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FileName);\r
1677 FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Info);\r
1678 FreePool((EFI_SHELL_FILE_INFO_NO_CONST*)Node);\r
1679 }\r
75a5e2ef 1680 SHELL_FREE_NON_NULL(*ListHead);\r
94b17fa1 1681 return EFI_SUCCESS;\r
1682 }\r
92a5447e 1683\r
1684 return (EFI_UNSUPPORTED);\r
94b17fa1 1685}\r
1686\r
125c2cf4 1687/**\r
1688 Find a file by searching the CWD and then the path.\r
1689\r
b3011f40 1690 If FileName is NULL then ASSERT.\r
125c2cf4 1691\r
b3011f40 1692 If the return value is not NULL then the memory must be caller freed.\r
125c2cf4 1693\r
1694 @param FileName Filename string.\r
1695\r
1696 @retval NULL the file was not found\r
1697 @return !NULL the full path to the file.\r
1698**/\r
1699CHAR16 *\r
1700EFIAPI\r
1701ShellFindFilePath (\r
1702 IN CONST CHAR16 *FileName\r
1703 )\r
1704{\r
1705 CONST CHAR16 *Path;\r
a405b86d 1706 SHELL_FILE_HANDLE Handle;\r
125c2cf4 1707 EFI_STATUS Status;\r
1708 CHAR16 *RetVal;\r
1709 CHAR16 *TestPath;\r
1710 CONST CHAR16 *Walker;\r
36a9d672 1711 UINTN Size;\r
1cd45e78 1712 CHAR16 *TempChar;\r
125c2cf4 1713\r
1714 RetVal = NULL;\r
1715\r
a405b86d 1716 //\r
1717 // First make sure its not an absolute path.\r
1718 //\r
1719 Status = ShellOpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ, 0);\r
1720 if (!EFI_ERROR(Status)){\r
1721 if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {\r
1722 ASSERT(RetVal == NULL);\r
1723 RetVal = StrnCatGrow(&RetVal, NULL, FileName, 0);\r
1724 ShellCloseFile(&Handle);\r
1725 return (RetVal);\r
1726 } else {\r
1727 ShellCloseFile(&Handle);\r
1728 }\r
1729 }\r
1730\r
125c2cf4 1731 Path = ShellGetEnvironmentVariable(L"cwd");\r
1732 if (Path != NULL) {\r
fbd2dfad 1733 Size = StrSize(Path) + sizeof(CHAR16);\r
36a9d672 1734 Size += StrSize(FileName);\r
1735 TestPath = AllocateZeroPool(Size);\r
c9d92df0 1736 if (TestPath == NULL) {\r
1737 return (NULL);\r
1738 }\r
e75390f0 1739 StrCpyS(TestPath, Size/sizeof(CHAR16), Path);\r
fbd2dfad 1740 StrCatS(TestPath, Size/sizeof(CHAR16), L"\\");\r
e75390f0 1741 StrCatS(TestPath, Size/sizeof(CHAR16), FileName);\r
125c2cf4 1742 Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);\r
1743 if (!EFI_ERROR(Status)){\r
a405b86d 1744 if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {\r
1745 ASSERT(RetVal == NULL);\r
1746 RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);\r
1747 ShellCloseFile(&Handle);\r
1748 FreePool(TestPath);\r
1749 return (RetVal);\r
1750 } else {\r
1751 ShellCloseFile(&Handle);\r
1752 }\r
125c2cf4 1753 }\r
1754 FreePool(TestPath);\r
1755 }\r
1756 Path = ShellGetEnvironmentVariable(L"path");\r
1757 if (Path != NULL) {\r
a405b86d 1758 Size = StrSize(Path)+sizeof(CHAR16);\r
36a9d672 1759 Size += StrSize(FileName);\r
1760 TestPath = AllocateZeroPool(Size);\r
3e082d58 1761 if (TestPath == NULL) {\r
1762 return (NULL);\r
1763 }\r
1e6e84c7 1764 Walker = (CHAR16*)Path;\r
125c2cf4 1765 do {\r
1766 CopyMem(TestPath, Walker, StrSize(Walker));\r
3e082d58 1767 if (TestPath != NULL) {\r
1768 TempChar = StrStr(TestPath, L";");\r
1769 if (TempChar != NULL) {\r
1770 *TempChar = CHAR_NULL;\r
1771 }\r
1772 if (TestPath[StrLen(TestPath)-1] != L'\\') {\r
e75390f0 1773 StrCatS(TestPath, Size/sizeof(CHAR16), L"\\");\r
3e082d58 1774 }\r
89e8537a 1775 if (FileName[0] == L'\\') {\r
1776 FileName++;\r
1777 }\r
e75390f0 1778 StrCatS(TestPath, Size/sizeof(CHAR16), FileName);\r
3e082d58 1779 if (StrStr(Walker, L";") != NULL) {\r
1780 Walker = StrStr(Walker, L";") + 1;\r
a405b86d 1781 } else {\r
3e082d58 1782 Walker = NULL;\r
1783 }\r
1784 Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);\r
1785 if (!EFI_ERROR(Status)){\r
1786 if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {\r
1787 ASSERT(RetVal == NULL);\r
1788 RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);\r
1789 ShellCloseFile(&Handle);\r
1790 break;\r
1791 } else {\r
1792 ShellCloseFile(&Handle);\r
1793 }\r
a405b86d 1794 }\r
125c2cf4 1795 }\r
1796 } while (Walker != NULL && Walker[0] != CHAR_NULL);\r
1797 FreePool(TestPath);\r
1798 }\r
1799 return (RetVal);\r
1800}\r
1801\r
b3011f40 1802/**\r
1e6e84c7 1803 Find a file by searching the CWD and then the path with a variable set of file\r
1804 extensions. If the file is not found it will append each extension in the list\r
b3011f40 1805 in the order provided and return the first one that is successful.\r
1806\r
1807 If FileName is NULL, then ASSERT.\r
1808 If FileExtension is NULL, then behavior is identical to ShellFindFilePath.\r
1809\r
1810 If the return value is not NULL then the memory must be caller freed.\r
1811\r
1812 @param[in] FileName Filename string.\r
1813 @param[in] FileExtension Semi-colon delimeted list of possible extensions.\r
1814\r
1815 @retval NULL The file was not found.\r
1816 @retval !NULL The path to the file.\r
1817**/\r
1818CHAR16 *\r
1819EFIAPI\r
1820ShellFindFilePathEx (\r
1821 IN CONST CHAR16 *FileName,\r
1822 IN CONST CHAR16 *FileExtension\r
1823 )\r
1824{\r
1825 CHAR16 *TestPath;\r
1826 CHAR16 *RetVal;\r
1827 CONST CHAR16 *ExtensionWalker;\r
9e926b69 1828 UINTN Size;\r
1cd45e78 1829 CHAR16 *TempChar;\r
c9d92df0 1830 CHAR16 *TempChar2;\r
1cd45e78 1831\r
b3011f40 1832 ASSERT(FileName != NULL);\r
1833 if (FileExtension == NULL) {\r
1834 return (ShellFindFilePath(FileName));\r
1835 }\r
1836 RetVal = ShellFindFilePath(FileName);\r
1837 if (RetVal != NULL) {\r
1838 return (RetVal);\r
1839 }\r
9e926b69 1840 Size = StrSize(FileName);\r
1841 Size += StrSize(FileExtension);\r
1842 TestPath = AllocateZeroPool(Size);\r
c9d92df0 1843 if (TestPath == NULL) {\r
1844 return (NULL);\r
1845 }\r
a405b86d 1846 for (ExtensionWalker = FileExtension, TempChar2 = (CHAR16*)FileExtension; TempChar2 != NULL ; ExtensionWalker = TempChar2 + 1){\r
e75390f0 1847 StrCpyS(TestPath, Size/sizeof(CHAR16), FileName);\r
a405b86d 1848 if (ExtensionWalker != NULL) {\r
e75390f0 1849 StrCatS(TestPath, Size/sizeof(CHAR16), ExtensionWalker);\r
a405b86d 1850 }\r
1cd45e78 1851 TempChar = StrStr(TestPath, L";");\r
1852 if (TempChar != NULL) {\r
1853 *TempChar = CHAR_NULL;\r
b3011f40 1854 }\r
1855 RetVal = ShellFindFilePath(TestPath);\r
1856 if (RetVal != NULL) {\r
1857 break;\r
1858 }\r
a405b86d 1859 ASSERT(ExtensionWalker != NULL);\r
c9d92df0 1860 TempChar2 = StrStr(ExtensionWalker, L";");\r
b3011f40 1861 }\r
1862 FreePool(TestPath);\r
1863 return (RetVal);\r
1864}\r
1865\r
94b17fa1 1866typedef struct {\r
9b3bf083 1867 LIST_ENTRY Link;\r
94b17fa1 1868 CHAR16 *Name;\r
a405b86d 1869 SHELL_PARAM_TYPE Type;\r
94b17fa1 1870 CHAR16 *Value;\r
1871 UINTN OriginalPosition;\r
1872} SHELL_PARAM_PACKAGE;\r
1873\r
1874/**\r
1e6e84c7 1875 Checks the list of valid arguments and returns TRUE if the item was found. If the\r
94b17fa1 1876 return value is TRUE then the type parameter is set also.\r
1e6e84c7 1877\r
94b17fa1 1878 if CheckList is NULL then ASSERT();\r
1879 if Name is NULL then ASSERT();\r
1880 if Type is NULL then ASSERT();\r
1881\r
94b17fa1 1882 @param Name pointer to Name of parameter found\r
1883 @param CheckList List to check against\r
a405b86d 1884 @param Type pointer to type of parameter if it was found\r
94b17fa1 1885\r
1886 @retval TRUE the Parameter was found. Type is valid.\r
1887 @retval FALSE the Parameter was not found. Type is not valid.\r
1888**/\r
1889BOOLEAN\r
d2b4564b 1890InternalIsOnCheckList (\r
94b17fa1 1891 IN CONST CHAR16 *Name,\r
1892 IN CONST SHELL_PARAM_ITEM *CheckList,\r
252d9457 1893 OUT SHELL_PARAM_TYPE *Type\r
a405b86d 1894 )\r
1895{\r
94b17fa1 1896 SHELL_PARAM_ITEM *TempListItem;\r
252d9457 1897 CHAR16 *TempString;\r
94b17fa1 1898\r
1899 //\r
1900 // ASSERT that all 3 pointer parameters aren't NULL\r
1901 //\r
1902 ASSERT(CheckList != NULL);\r
1903 ASSERT(Type != NULL);\r
1904 ASSERT(Name != NULL);\r
1905\r
d2b4564b 1906 //\r
1907 // question mark and page break mode are always supported\r
1908 //\r
1909 if ((StrCmp(Name, L"-?") == 0) ||\r
1910 (StrCmp(Name, L"-b") == 0)\r
a405b86d 1911 ) {\r
252d9457 1912 *Type = TypeFlag;\r
d2b4564b 1913 return (TRUE);\r
1914 }\r
1915\r
94b17fa1 1916 //\r
1917 // Enumerate through the list\r
1918 //\r
1919 for (TempListItem = (SHELL_PARAM_ITEM*)CheckList ; TempListItem->Name != NULL ; TempListItem++) {\r
1920 //\r
9eb53ac3 1921 // If the Type is TypeStart only check the first characters of the passed in param\r
1922 // If it matches set the type and return TRUE\r
94b17fa1 1923 //\r
b0934ac4 1924 if (TempListItem->Type == TypeStart) {\r
252d9457 1925 if (StrnCmp(Name, TempListItem->Name, StrLen(TempListItem->Name)) == 0) {\r
1926 *Type = TempListItem->Type;\r
1927 return (TRUE);\r
1928 }\r
1929 TempString = NULL;\r
1930 TempString = StrnCatGrow(&TempString, NULL, Name, StrLen(TempListItem->Name));\r
1931 if (TempString != NULL) {\r
1932 if (StringNoCaseCompare(&TempString, &TempListItem->Name) == 0) {\r
1933 *Type = TempListItem->Type;\r
1934 FreePool(TempString);\r
1935 return (TRUE);\r
1936 }\r
1937 FreePool(TempString);\r
1938 }\r
1939 } else if (StringNoCaseCompare(&Name, &TempListItem->Name) == 0) {\r
94b17fa1 1940 *Type = TempListItem->Type;\r
1941 return (TRUE);\r
1942 }\r
1943 }\r
2247dde4 1944\r
94b17fa1 1945 return (FALSE);\r
1946}\r
1947/**\r
d2b4564b 1948 Checks the string for indicators of "flag" status. this is a leading '/', '-', or '+'\r
94b17fa1 1949\r
a405b86d 1950 @param[in] Name pointer to Name of parameter found\r
1951 @param[in] AlwaysAllowNumbers TRUE to allow numbers, FALSE to not.\r
658bf43e 1952 @param[in] TimeNumbers TRUE to allow numbers with ":", FALSE otherwise.\r
94b17fa1 1953\r
1954 @retval TRUE the Parameter is a flag.\r
a405b86d 1955 @retval FALSE the Parameter not a flag.\r
94b17fa1 1956**/\r
1957BOOLEAN\r
d2b4564b 1958InternalIsFlag (\r
2247dde4 1959 IN CONST CHAR16 *Name,\r
658bf43e 1960 IN CONST BOOLEAN AlwaysAllowNumbers,\r
1961 IN CONST BOOLEAN TimeNumbers\r
94b17fa1 1962 )\r
1963{\r
1964 //\r
1965 // ASSERT that Name isn't NULL\r
1966 //\r
1967 ASSERT(Name != NULL);\r
1968\r
2247dde4 1969 //\r
1970 // If we accept numbers then dont return TRUE. (they will be values)\r
1971 //\r
658bf43e 1972 if (((Name[0] == L'-' || Name[0] == L'+') && InternalShellIsHexOrDecimalNumber(Name+1, FALSE, FALSE, TimeNumbers)) && AlwaysAllowNumbers) {\r
2247dde4 1973 return (FALSE);\r
1974 }\r
1975\r
94b17fa1 1976 //\r
a405b86d 1977 // If the Name has a /, +, or - as the first character return TRUE\r
94b17fa1 1978 //\r
1e6e84c7 1979 if ((Name[0] == L'/') ||\r
d2b4564b 1980 (Name[0] == L'-') ||\r
1981 (Name[0] == L'+')\r
a405b86d 1982 ) {\r
94b17fa1 1983 return (TRUE);\r
1984 }\r
1985 return (FALSE);\r
1986}\r
1987\r
1988/**\r
1e6e84c7 1989 Checks the command line arguments passed against the list of valid ones.\r
94b17fa1 1990\r
1991 If no initialization is required, then return RETURN_SUCCESS.\r
1e6e84c7 1992\r
a405b86d 1993 @param[in] CheckList pointer to list of parameters to check\r
1994 @param[out] CheckPackage pointer to pointer to list checked values\r
1995 @param[out] ProblemParam optional pointer to pointer to unicode string for\r
d2b4564b 1996 the paramater that caused failure. If used then the\r
1997 caller is responsible for freeing the memory.\r
a405b86d 1998 @param[in] AutoPageBreak will automatically set PageBreakEnabled for "b" parameter\r
1999 @param[in] Argv pointer to array of parameters\r
2000 @param[in] Argc Count of parameters in Argv\r
2001 @param[in] AlwaysAllowNumbers TRUE to allow numbers always, FALSE otherwise.\r
94b17fa1 2002\r
2003 @retval EFI_SUCCESS The operation completed sucessfully.\r
2004 @retval EFI_OUT_OF_RESOURCES A memory allocation failed\r
2005 @retval EFI_INVALID_PARAMETER A parameter was invalid\r
1e6e84c7 2006 @retval EFI_VOLUME_CORRUPTED the command line was corrupt. an argument was\r
2007 duplicated. the duplicated command line argument\r
94b17fa1 2008 was returned in ProblemParam if provided.\r
1e6e84c7 2009 @retval EFI_NOT_FOUND a argument required a value that was missing.\r
94b17fa1 2010 the invalid command line argument was returned in\r
2011 ProblemParam if provided.\r
2012**/\r
2013EFI_STATUS\r
94b17fa1 2014InternalCommandLineParse (\r
2015 IN CONST SHELL_PARAM_ITEM *CheckList,\r
2016 OUT LIST_ENTRY **CheckPackage,\r
2017 OUT CHAR16 **ProblemParam OPTIONAL,\r
2018 IN BOOLEAN AutoPageBreak,\r
2019 IN CONST CHAR16 **Argv,\r
2247dde4 2020 IN UINTN Argc,\r
2021 IN BOOLEAN AlwaysAllowNumbers\r
a405b86d 2022 )\r
2023{\r
94b17fa1 2024 UINTN LoopCounter;\r
252d9457 2025 SHELL_PARAM_TYPE CurrentItemType;\r
94b17fa1 2026 SHELL_PARAM_PACKAGE *CurrentItemPackage;\r
125c2cf4 2027 UINTN GetItemValue;\r
2028 UINTN ValueSize;\r
a405b86d 2029 UINTN Count;\r
252d9457 2030 CONST CHAR16 *TempPointer;\r
98c16be5 2031 UINTN CurrentValueSize;\r
2efafabf 2032 CHAR16 *NewValue;\r
94b17fa1 2033\r
2034 CurrentItemPackage = NULL;\r
125c2cf4 2035 GetItemValue = 0;\r
2036 ValueSize = 0;\r
a405b86d 2037 Count = 0;\r
94b17fa1 2038\r
2039 //\r
2040 // If there is only 1 item we dont need to do anything\r
2041 //\r
a405b86d 2042 if (Argc < 1) {\r
94b17fa1 2043 *CheckPackage = NULL;\r
2044 return (EFI_SUCCESS);\r
2045 }\r
2046\r
2247dde4 2047 //\r
2048 // ASSERTs\r
2049 //\r
2050 ASSERT(CheckList != NULL);\r
2051 ASSERT(Argv != NULL);\r
2052\r
94b17fa1 2053 //\r
2054 // initialize the linked list\r
2055 //\r
2056 *CheckPackage = (LIST_ENTRY*)AllocateZeroPool(sizeof(LIST_ENTRY));\r
02a758cb 2057 if (*CheckPackage == NULL) {\r
beab0fc5 2058 return (EFI_OUT_OF_RESOURCES);\r
02a758cb 2059 }\r
beab0fc5 2060\r
94b17fa1 2061 InitializeListHead(*CheckPackage);\r
2062\r
2063 //\r
2064 // loop through each of the arguments\r
2065 //\r
2066 for (LoopCounter = 0 ; LoopCounter < Argc ; ++LoopCounter) {\r
2067 if (Argv[LoopCounter] == NULL) {\r
2068 //\r
2069 // do nothing for NULL argv\r
2070 //\r
a405b86d 2071 } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType)) {\r
2247dde4 2072 //\r
2073 // We might have leftover if last parameter didnt have optional value\r
2074 //\r
125c2cf4 2075 if (GetItemValue != 0) {\r
2076 GetItemValue = 0;\r
2247dde4 2077 InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
2078 }\r
94b17fa1 2079 //\r
2080 // this is a flag\r
2081 //\r
252d9457 2082 CurrentItemPackage = AllocateZeroPool(sizeof(SHELL_PARAM_PACKAGE));\r
beab0fc5 2083 if (CurrentItemPackage == NULL) {\r
2084 ShellCommandLineFreeVarList(*CheckPackage);\r
2085 *CheckPackage = NULL;\r
2086 return (EFI_OUT_OF_RESOURCES);\r
2087 }\r
98c16be5 2088 CurrentItemPackage->Name = AllocateCopyPool(StrSize(Argv[LoopCounter]), Argv[LoopCounter]);\r
beab0fc5 2089 if (CurrentItemPackage->Name == NULL) {\r
2090 ShellCommandLineFreeVarList(*CheckPackage);\r
2091 *CheckPackage = NULL;\r
2092 return (EFI_OUT_OF_RESOURCES);\r
2093 }\r
94b17fa1 2094 CurrentItemPackage->Type = CurrentItemType;\r
2095 CurrentItemPackage->OriginalPosition = (UINTN)(-1);\r
b1f95a06 2096 CurrentItemPackage->Value = NULL;\r
94b17fa1 2097\r
2098 //\r
2099 // Does this flag require a value\r
2100 //\r
125c2cf4 2101 switch (CurrentItemPackage->Type) {\r
94b17fa1 2102 //\r
125c2cf4 2103 // possibly trigger the next loop(s) to populate the value of this item\r
1e6e84c7 2104 //\r
125c2cf4 2105 case TypeValue:\r
658bf43e 2106 case TypeTimeValue:\r
1e6e84c7 2107 GetItemValue = 1;\r
125c2cf4 2108 ValueSize = 0;\r
2109 break;\r
2110 case TypeDoubleValue:\r
2111 GetItemValue = 2;\r
2112 ValueSize = 0;\r
2113 break;\r
2114 case TypeMaxValue:\r
2115 GetItemValue = (UINTN)(-1);\r
2116 ValueSize = 0;\r
2117 break;\r
2118 default:\r
2119 //\r
2120 // this item has no value expected; we are done\r
2121 //\r
2122 InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
2123 ASSERT(GetItemValue == 0);\r
2124 break;\r
94b17fa1 2125 }\r
af7a3a54 2126 } else if (GetItemValue != 0 && CurrentItemPackage != NULL && !InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers, (BOOLEAN)(CurrentItemPackage->Type == TypeTimeValue))) {\r
b1f95a06 2127 //\r
125c2cf4 2128 // get the item VALUE for a previous flag\r
b1f95a06 2129 //\r
484dd08c 2130 CurrentValueSize = ValueSize + StrSize(Argv[LoopCounter]) + sizeof(CHAR16);\r
2efafabf
RN
2131 NewValue = ReallocatePool(ValueSize, CurrentValueSize, CurrentItemPackage->Value);\r
2132 if (NewValue == NULL) {\r
2133 SHELL_FREE_NON_NULL (CurrentItemPackage->Value);\r
2134 SHELL_FREE_NON_NULL (CurrentItemPackage);\r
2135 ShellCommandLineFreeVarList (*CheckPackage);\r
2136 *CheckPackage = NULL;\r
2137 return EFI_OUT_OF_RESOURCES;\r
2138 }\r
2139 CurrentItemPackage->Value = NewValue;\r
484dd08c 2140 if (ValueSize == 0) {\r
e75390f0
QS
2141 StrCpyS( CurrentItemPackage->Value, \r
2142 CurrentValueSize/sizeof(CHAR16), \r
2143 Argv[LoopCounter]\r
2144 );\r
125c2cf4 2145 } else {\r
e75390f0
QS
2146 StrCatS( CurrentItemPackage->Value, \r
2147 CurrentValueSize/sizeof(CHAR16), \r
2148 L" "\r
2149 );\r
2150 StrCatS( CurrentItemPackage->Value, \r
2151 CurrentValueSize/sizeof(CHAR16), \r
2152 Argv[LoopCounter]\r
2153 );\r
125c2cf4 2154 }\r
484dd08c
QS
2155 ValueSize += StrSize(Argv[LoopCounter]) + sizeof(CHAR16);\r
2156 \r
125c2cf4 2157 GetItemValue--;\r
2158 if (GetItemValue == 0) {\r
2159 InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
2160 }\r
658bf43e 2161 } else if (!InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers, FALSE)){\r
b1f95a06 2162 //\r
2163 // add this one as a non-flag\r
2164 //\r
252d9457 2165\r
2166 TempPointer = Argv[LoopCounter];\r
b0934ac4 2167 if ((*TempPointer == L'^' && *(TempPointer+1) == L'-')\r
252d9457 2168 || (*TempPointer == L'^' && *(TempPointer+1) == L'/')\r
2169 || (*TempPointer == L'^' && *(TempPointer+1) == L'+')\r
2170 ){\r
2171 TempPointer++;\r
2172 }\r
2173 CurrentItemPackage = AllocateZeroPool(sizeof(SHELL_PARAM_PACKAGE));\r
beab0fc5 2174 if (CurrentItemPackage == NULL) {\r
2175 ShellCommandLineFreeVarList(*CheckPackage);\r
2176 *CheckPackage = NULL;\r
2177 return (EFI_OUT_OF_RESOURCES);\r
2178 }\r
b1f95a06 2179 CurrentItemPackage->Name = NULL;\r
2180 CurrentItemPackage->Type = TypePosition;\r
98c16be5 2181 CurrentItemPackage->Value = AllocateCopyPool(StrSize(TempPointer), TempPointer);\r
beab0fc5 2182 if (CurrentItemPackage->Value == NULL) {\r
2183 ShellCommandLineFreeVarList(*CheckPackage);\r
2184 *CheckPackage = NULL;\r
2185 return (EFI_OUT_OF_RESOURCES);\r
2186 }\r
a405b86d 2187 CurrentItemPackage->OriginalPosition = Count++;\r
9b3bf083 2188 InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
252d9457 2189 } else {\r
94b17fa1 2190 //\r
2191 // this was a non-recognised flag... error!\r
2192 //\r
252d9457 2193 if (ProblemParam != NULL) {\r
98c16be5 2194 *ProblemParam = AllocateCopyPool(StrSize(Argv[LoopCounter]), Argv[LoopCounter]);\r
252d9457 2195 }\r
94b17fa1 2196 ShellCommandLineFreeVarList(*CheckPackage);\r
2197 *CheckPackage = NULL;\r
2198 return (EFI_VOLUME_CORRUPTED);\r
94b17fa1 2199 }\r
2200 }\r
125c2cf4 2201 if (GetItemValue != 0) {\r
2202 GetItemValue = 0;\r
2203 InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
2204 }\r
94b17fa1 2205 //\r
2206 // support for AutoPageBreak\r
2207 //\r
2208 if (AutoPageBreak && ShellCommandLineGetFlag(*CheckPackage, L"-b")) {\r
2209 ShellSetPageBreakMode(TRUE);\r
2210 }\r
2211 return (EFI_SUCCESS);\r
2212}\r
2213\r
2214/**\r
1e6e84c7 2215 Checks the command line arguments passed against the list of valid ones.\r
94b17fa1 2216 Optionally removes NULL values first.\r
1e6e84c7 2217\r
94b17fa1 2218 If no initialization is required, then return RETURN_SUCCESS.\r
1e6e84c7 2219\r
a405b86d 2220 @param[in] CheckList The pointer to list of parameters to check.\r
2221 @param[out] CheckPackage The package of checked values.\r
2222 @param[out] ProblemParam Optional pointer to pointer to unicode string for\r
94b17fa1 2223 the paramater that caused failure.\r
a405b86d 2224 @param[in] AutoPageBreak Will automatically set PageBreakEnabled.\r
2225 @param[in] AlwaysAllowNumbers Will never fail for number based flags.\r
94b17fa1 2226\r
2227 @retval EFI_SUCCESS The operation completed sucessfully.\r
a405b86d 2228 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
2229 @retval EFI_INVALID_PARAMETER A parameter was invalid.\r
2230 @retval EFI_VOLUME_CORRUPTED The command line was corrupt.\r
2231 @retval EFI_DEVICE_ERROR The commands contained 2 opposing arguments. One\r
1e6e84c7 2232 of the command line arguments was returned in\r
94b17fa1 2233 ProblemParam if provided.\r
a405b86d 2234 @retval EFI_NOT_FOUND A argument required a value that was missing.\r
2235 The invalid command line argument was returned in\r
94b17fa1 2236 ProblemParam if provided.\r
2237**/\r
2238EFI_STATUS\r
2239EFIAPI\r
2247dde4 2240ShellCommandLineParseEx (\r
94b17fa1 2241 IN CONST SHELL_PARAM_ITEM *CheckList,\r
2242 OUT LIST_ENTRY **CheckPackage,\r
2243 OUT CHAR16 **ProblemParam OPTIONAL,\r
2247dde4 2244 IN BOOLEAN AutoPageBreak,\r
2245 IN BOOLEAN AlwaysAllowNumbers\r
a405b86d 2246 )\r
2247{\r
1e6e84c7 2248 //\r
94b17fa1 2249 // ASSERT that CheckList and CheckPackage aren't NULL\r
2250 //\r
2251 ASSERT(CheckList != NULL);\r
2252 ASSERT(CheckPackage != NULL);\r
2253\r
1e6e84c7 2254 //\r
94b17fa1 2255 // Check for UEFI Shell 2.0 protocols\r
2256 //\r
366f81a0 2257 if (gEfiShellParametersProtocol != NULL) {\r
1e6e84c7 2258 return (InternalCommandLineParse(CheckList,\r
2259 CheckPackage,\r
2260 ProblemParam,\r
2261 AutoPageBreak,\r
366f81a0 2262 (CONST CHAR16**) gEfiShellParametersProtocol->Argv,\r
2263 gEfiShellParametersProtocol->Argc,\r
2247dde4 2264 AlwaysAllowNumbers));\r
94b17fa1 2265 }\r
2266\r
1e6e84c7 2267 //\r
94b17fa1 2268 // ASSERT That EFI Shell is not required\r
2269 //\r
2270 ASSERT (mEfiShellInterface != NULL);\r
1e6e84c7 2271 return (InternalCommandLineParse(CheckList,\r
2272 CheckPackage,\r
2273 ProblemParam,\r
2274 AutoPageBreak,\r
08d7f8e8 2275 (CONST CHAR16**) mEfiShellInterface->Argv,\r
2247dde4 2276 mEfiShellInterface->Argc,\r
2277 AlwaysAllowNumbers));\r
94b17fa1 2278}\r
2279\r
2280/**\r
2281 Frees shell variable list that was returned from ShellCommandLineParse.\r
2282\r
2283 This function will free all the memory that was used for the CheckPackage\r
2284 list of postprocessed shell arguments.\r
2285\r
2286 this function has no return value.\r
2287\r
2288 if CheckPackage is NULL, then return\r
2289\r
2290 @param CheckPackage the list to de-allocate\r
2291 **/\r
2292VOID\r
2293EFIAPI\r
2294ShellCommandLineFreeVarList (\r
2295 IN LIST_ENTRY *CheckPackage\r
a405b86d 2296 )\r
2297{\r
94b17fa1 2298 LIST_ENTRY *Node;\r
2299\r
2300 //\r
2301 // check for CheckPackage == NULL\r
2302 //\r
2303 if (CheckPackage == NULL) {\r
2304 return;\r
2305 }\r
2306\r
2307 //\r
2308 // for each node in the list\r
2309 //\r
9eb53ac3 2310 for ( Node = GetFirstNode(CheckPackage)\r
a405b86d 2311 ; !IsListEmpty(CheckPackage)\r
9eb53ac3 2312 ; Node = GetFirstNode(CheckPackage)\r
a405b86d 2313 ){\r
94b17fa1 2314 //\r
2315 // Remove it from the list\r
2316 //\r
2317 RemoveEntryList(Node);\r
2318\r
2319 //\r
2320 // if it has a name free the name\r
2321 //\r
2322 if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
2323 FreePool(((SHELL_PARAM_PACKAGE*)Node)->Name);\r
2324 }\r
2325\r
2326 //\r
2327 // if it has a value free the value\r
2328 //\r
2329 if (((SHELL_PARAM_PACKAGE*)Node)->Value != NULL) {\r
2330 FreePool(((SHELL_PARAM_PACKAGE*)Node)->Value);\r
2331 }\r
1e6e84c7 2332\r
94b17fa1 2333 //\r
2334 // free the node structure\r
2335 //\r
2336 FreePool((SHELL_PARAM_PACKAGE*)Node);\r
2337 }\r
2338 //\r
2339 // free the list head node\r
2340 //\r
2341 FreePool(CheckPackage);\r
2342}\r
2343/**\r
2344 Checks for presence of a flag parameter\r
2345\r
2346 flag arguments are in the form of "-<Key>" or "/<Key>", but do not have a value following the key\r
2347\r
2348 if CheckPackage is NULL then return FALSE.\r
2349 if KeyString is NULL then ASSERT()\r
1e6e84c7 2350\r
94b17fa1 2351 @param CheckPackage The package of parsed command line arguments\r
2352 @param KeyString the Key of the command line argument to check for\r
2353\r
2354 @retval TRUE the flag is on the command line\r
2355 @retval FALSE the flag is not on the command line\r
2356 **/\r
2357BOOLEAN\r
2358EFIAPI\r
2359ShellCommandLineGetFlag (\r
a405b86d 2360 IN CONST LIST_ENTRY * CONST CheckPackage,\r
2361 IN CONST CHAR16 * CONST KeyString\r
2362 )\r
2363{\r
94b17fa1 2364 LIST_ENTRY *Node;\r
252d9457 2365 CHAR16 *TempString;\r
94b17fa1 2366\r
2367 //\r
0c1950ba 2368 // return FALSE for no package or KeyString is NULL\r
94b17fa1 2369 //\r
0c1950ba 2370 if (CheckPackage == NULL || KeyString == NULL) {\r
94b17fa1 2371 return (FALSE);\r
2372 }\r
2373\r
2374 //\r
2375 // enumerate through the list of parametrs\r
2376 //\r
1e6e84c7 2377 for ( Node = GetFirstNode(CheckPackage)\r
2378 ; !IsNull (CheckPackage, Node)\r
2379 ; Node = GetNextNode(CheckPackage, Node)\r
252d9457 2380 ){\r
94b17fa1 2381 //\r
2382 // If the Name matches, return TRUE (and there may be NULL name)\r
2383 //\r
2384 if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
9eb53ac3 2385 //\r
2386 // If Type is TypeStart then only compare the begining of the strings\r
2387 //\r
252d9457 2388 if (((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart) {\r
2389 if (StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0) {\r
2390 return (TRUE);\r
2391 }\r
2392 TempString = NULL;\r
2393 TempString = StrnCatGrow(&TempString, NULL, KeyString, StrLen(((SHELL_PARAM_PACKAGE*)Node)->Name));\r
2394 if (TempString != NULL) {\r
2395 if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
2396 FreePool(TempString);\r
2397 return (TRUE);\r
2398 }\r
2399 FreePool(TempString);\r
2400 }\r
2401 } else if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
94b17fa1 2402 return (TRUE);\r
2403 }\r
2404 }\r
2405 }\r
2406 return (FALSE);\r
2407}\r
2408/**\r
a405b86d 2409 Returns value from command line argument.\r
94b17fa1 2410\r
a405b86d 2411 Value parameters are in the form of "-<Key> value" or "/<Key> value".\r
1e6e84c7 2412\r
a405b86d 2413 If CheckPackage is NULL, then return NULL.\r
94b17fa1 2414\r
a405b86d 2415 @param[in] CheckPackage The package of parsed command line arguments.\r
2416 @param[in] KeyString The Key of the command line argument to check for.\r
94b17fa1 2417\r
a405b86d 2418 @retval NULL The flag is not on the command line.\r
2419 @retval !=NULL The pointer to unicode string of the value.\r
2420**/\r
94b17fa1 2421CONST CHAR16*\r
2422EFIAPI\r
2423ShellCommandLineGetValue (\r
2424 IN CONST LIST_ENTRY *CheckPackage,\r
2425 IN CHAR16 *KeyString\r
a405b86d 2426 )\r
2427{\r
94b17fa1 2428 LIST_ENTRY *Node;\r
252d9457 2429 CHAR16 *TempString;\r
94b17fa1 2430\r
2431 //\r
0c1950ba 2432 // return NULL for no package or KeyString is NULL\r
94b17fa1 2433 //\r
0c1950ba 2434 if (CheckPackage == NULL || KeyString == NULL) {\r
94b17fa1 2435 return (NULL);\r
2436 }\r
2437\r
2438 //\r
2439 // enumerate through the list of parametrs\r
2440 //\r
1e6e84c7 2441 for ( Node = GetFirstNode(CheckPackage)\r
2442 ; !IsNull (CheckPackage, Node)\r
2443 ; Node = GetNextNode(CheckPackage, Node)\r
252d9457 2444 ){\r
94b17fa1 2445 //\r
252d9457 2446 // If the Name matches, return TRUE (and there may be NULL name)\r
94b17fa1 2447 //\r
2448 if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
9eb53ac3 2449 //\r
2450 // If Type is TypeStart then only compare the begining of the strings\r
2451 //\r
252d9457 2452 if (((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart) {\r
2453 if (StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0) {\r
2454 return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString));\r
2455 }\r
2456 TempString = NULL;\r
2457 TempString = StrnCatGrow(&TempString, NULL, KeyString, StrLen(((SHELL_PARAM_PACKAGE*)Node)->Name));\r
2458 if (TempString != NULL) {\r
2459 if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
2460 FreePool(TempString);\r
2461 return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString));\r
2462 }\r
2463 FreePool(TempString);\r
2464 }\r
2465 } else if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
94b17fa1 2466 return (((SHELL_PARAM_PACKAGE*)Node)->Value);\r
2467 }\r
2468 }\r
2469 }\r
2470 return (NULL);\r
2471}\r
a405b86d 2472\r
94b17fa1 2473/**\r
a405b86d 2474 Returns raw value from command line argument.\r
94b17fa1 2475\r
a405b86d 2476 Raw value parameters are in the form of "value" in a specific position in the list.\r
1e6e84c7 2477\r
a405b86d 2478 If CheckPackage is NULL, then return NULL.\r
94b17fa1 2479\r
a405b86d 2480 @param[in] CheckPackage The package of parsed command line arguments.\r
2481 @param[in] Position The position of the value.\r
94b17fa1 2482\r
a405b86d 2483 @retval NULL The flag is not on the command line.\r
2484 @retval !=NULL The pointer to unicode string of the value.\r
94b17fa1 2485 **/\r
2486CONST CHAR16*\r
2487EFIAPI\r
2488ShellCommandLineGetRawValue (\r
a405b86d 2489 IN CONST LIST_ENTRY * CONST CheckPackage,\r
2490 IN UINTN Position\r
2491 )\r
2492{\r
94b17fa1 2493 LIST_ENTRY *Node;\r
2494\r
2495 //\r
2496 // check for CheckPackage == NULL\r
2497 //\r
2498 if (CheckPackage == NULL) {\r
2499 return (NULL);\r
2500 }\r
2501\r
2502 //\r
2503 // enumerate through the list of parametrs\r
2504 //\r
1e6e84c7 2505 for ( Node = GetFirstNode(CheckPackage)\r
2506 ; !IsNull (CheckPackage, Node)\r
2507 ; Node = GetNextNode(CheckPackage, Node)\r
a405b86d 2508 ){\r
94b17fa1 2509 //\r
2510 // If the position matches, return the value\r
2511 //\r
2512 if (((SHELL_PARAM_PACKAGE*)Node)->OriginalPosition == Position) {\r
2513 return (((SHELL_PARAM_PACKAGE*)Node)->Value);\r
2514 }\r
2515 }\r
2516 return (NULL);\r
b1f95a06 2517}\r
2247dde4 2518\r
2519/**\r
1e6e84c7 2520 returns the number of command line value parameters that were parsed.\r
2521\r
2247dde4 2522 this will not include flags.\r
2523\r
a405b86d 2524 @param[in] CheckPackage The package of parsed command line arguments.\r
2525\r
2247dde4 2526 @retval (UINTN)-1 No parsing has ocurred\r
2527 @return other The number of value parameters found\r
2528**/\r
2529UINTN\r
2530EFIAPI\r
2531ShellCommandLineGetCount(\r
a405b86d 2532 IN CONST LIST_ENTRY *CheckPackage\r
125c2cf4 2533 )\r
2534{\r
a405b86d 2535 LIST_ENTRY *Node1;\r
2536 UINTN Count;\r
2537\r
2538 if (CheckPackage == NULL) {\r
2539 return (0);\r
2540 }\r
2541 for ( Node1 = GetFirstNode(CheckPackage), Count = 0\r
2542 ; !IsNull (CheckPackage, Node1)\r
2543 ; Node1 = GetNextNode(CheckPackage, Node1)\r
2544 ){\r
2545 if (((SHELL_PARAM_PACKAGE*)Node1)->Name == NULL) {\r
2546 Count++;\r
2547 }\r
2548 }\r
2549 return (Count);\r
2247dde4 2550}\r
2551\r
36a9d672 2552/**\r
cceb4ebd 2553 Determines if a parameter is duplicated.\r
36a9d672 2554\r
1e6e84c7 2555 If Param is not NULL then it will point to a callee allocated string buffer\r
36a9d672 2556 with the parameter value if a duplicate is found.\r
2557\r
2558 If CheckPackage is NULL, then ASSERT.\r
2559\r
2560 @param[in] CheckPackage The package of parsed command line arguments.\r
2561 @param[out] Param Upon finding one, a pointer to the duplicated parameter.\r
2562\r
2563 @retval EFI_SUCCESS No parameters were duplicated.\r
2564 @retval EFI_DEVICE_ERROR A duplicate was found.\r
2565 **/\r
2566EFI_STATUS\r
2567EFIAPI\r
2568ShellCommandLineCheckDuplicate (\r
2569 IN CONST LIST_ENTRY *CheckPackage,\r
2570 OUT CHAR16 **Param\r
2571 )\r
2572{\r
2573 LIST_ENTRY *Node1;\r
2574 LIST_ENTRY *Node2;\r
1e6e84c7 2575\r
36a9d672 2576 ASSERT(CheckPackage != NULL);\r
2577\r
1e6e84c7 2578 for ( Node1 = GetFirstNode(CheckPackage)\r
2579 ; !IsNull (CheckPackage, Node1)\r
2580 ; Node1 = GetNextNode(CheckPackage, Node1)\r
a405b86d 2581 ){\r
1e6e84c7 2582 for ( Node2 = GetNextNode(CheckPackage, Node1)\r
2583 ; !IsNull (CheckPackage, Node2)\r
2584 ; Node2 = GetNextNode(CheckPackage, Node2)\r
a405b86d 2585 ){\r
2586 if ((((SHELL_PARAM_PACKAGE*)Node1)->Name != NULL) && (((SHELL_PARAM_PACKAGE*)Node2)->Name != NULL) && StrCmp(((SHELL_PARAM_PACKAGE*)Node1)->Name, ((SHELL_PARAM_PACKAGE*)Node2)->Name) == 0) {\r
36a9d672 2587 if (Param != NULL) {\r
2588 *Param = NULL;\r
2589 *Param = StrnCatGrow(Param, NULL, ((SHELL_PARAM_PACKAGE*)Node1)->Name, 0);\r
2590 }\r
2591 return (EFI_DEVICE_ERROR);\r
2592 }\r
2593 }\r
2594 }\r
2595 return (EFI_SUCCESS);\r
2596}\r
2597\r
975136ab 2598/**\r
1e6e84c7 2599 This is a find and replace function. Upon successful return the NewString is a copy of\r
975136ab 2600 SourceString with each instance of FindTarget replaced with ReplaceWith.\r
2601\r
b3011f40 2602 If SourceString and NewString overlap the behavior is undefined.\r
2603\r
975136ab 2604 If the string would grow bigger than NewSize it will halt and return error.\r
2605\r
4ff7e37b
ED
2606 @param[in] SourceString The string with source buffer.\r
2607 @param[in, out] NewString The string with resultant buffer.\r
2608 @param[in] NewSize The size in bytes of NewString.\r
2609 @param[in] FindTarget The string to look for.\r
2610 @param[in] ReplaceWith The string to replace FindTarget with.\r
2611 @param[in] SkipPreCarrot If TRUE will skip a FindTarget that has a '^'\r
2612 immediately before it.\r
2613 @param[in] ParameterReplacing If TRUE will add "" around items with spaces.\r
969c783b 2614\r
2615 @retval EFI_INVALID_PARAMETER SourceString was NULL.\r
2616 @retval EFI_INVALID_PARAMETER NewString was NULL.\r
2617 @retval EFI_INVALID_PARAMETER FindTarget was NULL.\r
2618 @retval EFI_INVALID_PARAMETER ReplaceWith was NULL.\r
2619 @retval EFI_INVALID_PARAMETER FindTarget had length < 1.\r
2620 @retval EFI_INVALID_PARAMETER SourceString had length < 1.\r
1e6e84c7 2621 @retval EFI_BUFFER_TOO_SMALL NewSize was less than the minimum size to hold\r
969c783b 2622 the new string (truncation occurred).\r
a405b86d 2623 @retval EFI_SUCCESS The string was successfully copied with replacement.\r
975136ab 2624**/\r
975136ab 2625EFI_STATUS\r
2626EFIAPI\r
a405b86d 2627ShellCopySearchAndReplace(\r
975136ab 2628 IN CHAR16 CONST *SourceString,\r
a405b86d 2629 IN OUT CHAR16 *NewString,\r
975136ab 2630 IN UINTN NewSize,\r
2631 IN CONST CHAR16 *FindTarget,\r
969c783b 2632 IN CONST CHAR16 *ReplaceWith,\r
a405b86d 2633 IN CONST BOOLEAN SkipPreCarrot,\r
2634 IN CONST BOOLEAN ParameterReplacing\r
1e6e84c7 2635 )\r
2247dde4 2636{\r
0158294b 2637 UINTN Size;\r
a405b86d 2638 CHAR16 *Replace;\r
2639\r
975136ab 2640 if ( (SourceString == NULL)\r
2641 || (NewString == NULL)\r
2642 || (FindTarget == NULL)\r
2643 || (ReplaceWith == NULL)\r
2644 || (StrLen(FindTarget) < 1)\r
2645 || (StrLen(SourceString) < 1)\r
a405b86d 2646 ){\r
975136ab 2647 return (EFI_INVALID_PARAMETER);\r
2648 }\r
a405b86d 2649 Replace = NULL;\r
2650 if (StrStr(ReplaceWith, L" ") == NULL || !ParameterReplacing) {\r
2651 Replace = StrnCatGrow(&Replace, NULL, ReplaceWith, 0);\r
2652 } else {\r
2653 Replace = AllocateZeroPool(StrSize(ReplaceWith) + 2*sizeof(CHAR16));\r
beab0fc5 2654 if (Replace != NULL) {\r
2655 UnicodeSPrint(Replace, StrSize(ReplaceWith) + 2*sizeof(CHAR16), L"\"%s\"", ReplaceWith);\r
2656 }\r
a405b86d 2657 }\r
3e082d58 2658 if (Replace == NULL) {\r
2659 return (EFI_OUT_OF_RESOURCES);\r
2660 }\r
98c16be5 2661 NewString = ZeroMem(NewString, NewSize);\r
2247dde4 2662 while (*SourceString != CHAR_NULL) {\r
969c783b 2663 //\r
a405b86d 2664 // if we find the FindTarget and either Skip == FALSE or Skip and we\r
969c783b 2665 // dont have a carrot do a replace...\r
2666 //\r
1e6e84c7 2667 if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0\r
a405b86d 2668 && ((SkipPreCarrot && *(SourceString-1) != L'^') || !SkipPreCarrot)\r
2669 ){\r
975136ab 2670 SourceString += StrLen(FindTarget);\r
0158294b 2671 Size = StrSize(NewString);\r
a405b86d 2672 if ((Size + (StrLen(Replace)*sizeof(CHAR16))) > NewSize) {\r
2673 FreePool(Replace);\r
975136ab 2674 return (EFI_BUFFER_TOO_SMALL);\r
2675 }\r
e75390f0 2676 StrCatS(NewString, NewSize/sizeof(CHAR16), Replace);\r
975136ab 2677 } else {\r
0158294b 2678 Size = StrSize(NewString);\r
2679 if (Size + sizeof(CHAR16) > NewSize) {\r
a405b86d 2680 FreePool(Replace);\r
975136ab 2681 return (EFI_BUFFER_TOO_SMALL);\r
2682 }\r
e75390f0 2683 StrnCatS(NewString, NewSize/sizeof(CHAR16), SourceString, 1);\r
975136ab 2684 SourceString++;\r
2685 }\r
2686 }\r
a405b86d 2687 FreePool(Replace);\r
975136ab 2688 return (EFI_SUCCESS);\r
2689}\r
b1f95a06 2690\r
e2f8297f 2691/**\r
2692 Internal worker function to output a string.\r
2693\r
2694 This function will output a string to the correct StdOut.\r
2695\r
2696 @param[in] String The string to print out.\r
2697\r
2698 @retval EFI_SUCCESS The operation was sucessful.\r
2699 @retval !EFI_SUCCESS The operation failed.\r
2700**/\r
2701EFI_STATUS\r
e2f8297f 2702InternalPrintTo (\r
2703 IN CONST CHAR16 *String\r
2704 )\r
2705{\r
2706 UINTN Size;\r
2707 Size = StrSize(String) - sizeof(CHAR16);\r
a405b86d 2708 if (Size == 0) {\r
2709 return (EFI_SUCCESS);\r
2710 }\r
366f81a0 2711 if (gEfiShellParametersProtocol != NULL) {\r
2712 return (gEfiShellProtocol->WriteFile(gEfiShellParametersProtocol->StdOut, &Size, (VOID*)String));\r
e2f8297f 2713 }\r
2714 if (mEfiShellInterface != NULL) {\r
06c355b4 2715 if (mEfiShellInterface->RedirArgc == 0) { \r
49bd498d 2716 //\r
2717 // Divide in half for old shell. Must be string length not size.\r
06c355b4 2718 // \r
2719 Size /=2; // Divide in half only when no redirection.\r
2720 }\r
a405b86d 2721 return (mEfiShellInterface->StdOut->Write(mEfiShellInterface->StdOut, &Size, (VOID*)String));\r
e2f8297f 2722 }\r
2723 ASSERT(FALSE);\r
2724 return (EFI_UNSUPPORTED);\r
2725}\r
2726\r
b1f95a06 2727/**\r
2728 Print at a specific location on the screen.\r
2729\r
f1b87e7a 2730 This function will move the cursor to a given screen location and print the specified string\r
1e6e84c7 2731\r
2732 If -1 is specified for either the Row or Col the current screen location for BOTH\r
f1b87e7a 2733 will be used.\r
b1f95a06 2734\r
2735 if either Row or Col is out of range for the current console, then ASSERT\r
2736 if Format is NULL, then ASSERT\r
2737\r
1e6e84c7 2738 In addition to the standard %-based flags as supported by UefiLib Print() this supports\r
b1f95a06 2739 the following additional flags:\r
2740 %N - Set output attribute to normal\r
2741 %H - Set output attribute to highlight\r
2742 %E - Set output attribute to error\r
2743 %B - Set output attribute to blue color\r
2744 %V - Set output attribute to green color\r
2745\r
2746 Note: The background color is controlled by the shell command cls.\r
2747\r
b1f95a06 2748 @param[in] Col the column to print at\r
252d9457 2749 @param[in] Row the row to print at\r
b1f95a06 2750 @param[in] Format the format string\r
2247dde4 2751 @param[in] Marker the marker for the variable argument list\r
b1f95a06 2752\r
a405b86d 2753 @return EFI_SUCCESS The operation was successful.\r
2754 @return EFI_DEVICE_ERROR The console device reported an error.\r
b1f95a06 2755**/\r
a405b86d 2756EFI_STATUS\r
2247dde4 2757InternalShellPrintWorker(\r
b1f95a06 2758 IN INT32 Col OPTIONAL,\r
2759 IN INT32 Row OPTIONAL,\r
2760 IN CONST CHAR16 *Format,\r
252d9457 2761 IN VA_LIST Marker\r
1e6e84c7 2762 )\r
2247dde4 2763{\r
b1f95a06 2764 EFI_STATUS Status;\r
975136ab 2765 CHAR16 *ResumeLocation;\r
2766 CHAR16 *FormatWalker;\r
a405b86d 2767 UINTN OriginalAttribute;\r
89e8537a 2768 CHAR16 *mPostReplaceFormat;\r
2769 CHAR16 *mPostReplaceFormat2;\r
2770\r
2771 mPostReplaceFormat = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));\r
2772 mPostReplaceFormat2 = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));\r
a405b86d 2773\r
f8d3e689 2774 if (mPostReplaceFormat == NULL || mPostReplaceFormat2 == NULL) {\r
2775 SHELL_FREE_NON_NULL(mPostReplaceFormat);\r
2776 SHELL_FREE_NON_NULL(mPostReplaceFormat2);\r
2777 return (EFI_OUT_OF_RESOURCES);\r
2778 }\r
2779\r
a405b86d 2780 Status = EFI_SUCCESS;\r
2781 OriginalAttribute = gST->ConOut->Mode->Attribute;\r
1e6e84c7 2782\r
975136ab 2783 //\r
2784 // Back and forth each time fixing up 1 of our flags...\r
2785 //\r
a405b86d 2786 Status = ShellCopySearchAndReplace(Format, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%N", L"%%N", FALSE, FALSE);\r
975136ab 2787 ASSERT_EFI_ERROR(Status);\r
a405b86d 2788 Status = ShellCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%E", L"%%E", FALSE, FALSE);\r
975136ab 2789 ASSERT_EFI_ERROR(Status);\r
a405b86d 2790 Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%H", L"%%H", FALSE, FALSE);\r
975136ab 2791 ASSERT_EFI_ERROR(Status);\r
a405b86d 2792 Status = ShellCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%B", L"%%B", FALSE, FALSE);\r
975136ab 2793 ASSERT_EFI_ERROR(Status);\r
a405b86d 2794 Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%V", L"%%V", FALSE, FALSE);\r
975136ab 2795 ASSERT_EFI_ERROR(Status);\r
2796\r
2797 //\r
2798 // Use the last buffer from replacing to print from...\r
2799 //\r
a405b86d 2800 UnicodeVSPrint (mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), mPostReplaceFormat, Marker);\r
b1f95a06 2801\r
2802 if (Col != -1 && Row != -1) {\r
b1f95a06 2803 Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);\r
975136ab 2804 }\r
2805\r
ecd3d59f 2806 FormatWalker = mPostReplaceFormat2;\r
2247dde4 2807 while (*FormatWalker != CHAR_NULL) {\r
975136ab 2808 //\r
2809 // Find the next attribute change request\r
2810 //\r
2811 ResumeLocation = StrStr(FormatWalker, L"%");\r
2812 if (ResumeLocation != NULL) {\r
2247dde4 2813 *ResumeLocation = CHAR_NULL;\r
975136ab 2814 }\r
2815 //\r
2816 // print the current FormatWalker string\r
2817 //\r
a405b86d 2818 if (StrLen(FormatWalker)>0) {\r
2819 Status = InternalPrintTo(FormatWalker);\r
2820 if (EFI_ERROR(Status)) {\r
2821 break;\r
2822 }\r
2823 }\r
2824\r
975136ab 2825 //\r
2826 // update the attribute\r
2827 //\r
2828 if (ResumeLocation != NULL) {\r
d727614c 2829 if ((ResumeLocation != mPostReplaceFormat2) && (*(ResumeLocation-1) == L'^')) {\r
8bb7441e 2830 //\r
2831 // Move cursor back 1 position to overwrite the ^\r
2832 //\r
2833 gST->ConOut->SetCursorPosition(gST->ConOut, gST->ConOut->Mode->CursorColumn - 1, gST->ConOut->Mode->CursorRow);\r
2834\r
5d46f17b 2835 //\r
2836 // Print a simple '%' symbol\r
2837 //\r
2838 Status = InternalPrintTo(L"%");\r
2839 ResumeLocation = ResumeLocation - 1;\r
2840 } else {\r
2841 switch (*(ResumeLocation+1)) {\r
2842 case (L'N'):\r
2843 gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute);\r
a405b86d 2844 break;\r
5d46f17b 2845 case (L'E'):\r
2846 gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
2847 break;\r
2848 case (L'H'):\r
2849 gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
2850 break;\r
2851 case (L'B'):\r
e2ac374f 2852 gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_LIGHTBLUE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
5d46f17b 2853 break;\r
2854 case (L'V'):\r
e2ac374f 2855 gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_LIGHTGREEN, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
5d46f17b 2856 break;\r
2857 default:\r
2858 //\r
2859 // Print a simple '%' symbol\r
2860 //\r
2861 Status = InternalPrintTo(L"%");\r
2862 if (EFI_ERROR(Status)) {\r
2863 break;\r
2864 }\r
2865 ResumeLocation = ResumeLocation - 1;\r
2866 break;\r
2867 }\r
975136ab 2868 }\r
2869 } else {\r
2870 //\r
2871 // reset to normal now...\r
2872 //\r
975136ab 2873 break;\r
2874 }\r
2875\r
2876 //\r
2877 // update FormatWalker to Resume + 2 (skip the % and the indicator)\r
2878 //\r
2879 FormatWalker = ResumeLocation + 2;\r
2880 }\r
b1f95a06 2881\r
a405b86d 2882 gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute);\r
89e8537a 2883\r
2884 SHELL_FREE_NON_NULL(mPostReplaceFormat);\r
2885 SHELL_FREE_NON_NULL(mPostReplaceFormat2);\r
a405b86d 2886 return (Status);\r
5f7431d0 2887}\r
2247dde4 2888\r
2889/**\r
2890 Print at a specific location on the screen.\r
2891\r
e2f8297f 2892 This function will move the cursor to a given screen location and print the specified string.\r
1e6e84c7 2893\r
2894 If -1 is specified for either the Row or Col the current screen location for BOTH\r
2247dde4 2895 will be used.\r
2896\r
e2f8297f 2897 If either Row or Col is out of range for the current console, then ASSERT.\r
2898 If Format is NULL, then ASSERT.\r
2247dde4 2899\r
1e6e84c7 2900 In addition to the standard %-based flags as supported by UefiLib Print() this supports\r
2247dde4 2901 the following additional flags:\r
2902 %N - Set output attribute to normal\r
2903 %H - Set output attribute to highlight\r
2904 %E - Set output attribute to error\r
2905 %B - Set output attribute to blue color\r
2906 %V - Set output attribute to green color\r
2907\r
2908 Note: The background color is controlled by the shell command cls.\r
2909\r
2247dde4 2910 @param[in] Col the column to print at\r
a405b86d 2911 @param[in] Row the row to print at\r
2247dde4 2912 @param[in] Format the format string\r
a405b86d 2913 @param[in] ... The variable argument list.\r
2247dde4 2914\r
a405b86d 2915 @return EFI_SUCCESS The printing was successful.\r
2916 @return EFI_DEVICE_ERROR The console device reported an error.\r
2247dde4 2917**/\r
a405b86d 2918EFI_STATUS\r
2247dde4 2919EFIAPI\r
2920ShellPrintEx(\r
2921 IN INT32 Col OPTIONAL,\r
2922 IN INT32 Row OPTIONAL,\r
2923 IN CONST CHAR16 *Format,\r
2924 ...\r
1e6e84c7 2925 )\r
2247dde4 2926{\r
2927 VA_LIST Marker;\r
a405b86d 2928 EFI_STATUS RetVal;\r
3e082d58 2929 if (Format == NULL) {\r
2930 return (EFI_INVALID_PARAMETER);\r
2931 }\r
2247dde4 2932 VA_START (Marker, Format);\r
a405b86d 2933 RetVal = InternalShellPrintWorker(Col, Row, Format, Marker);\r
e2f8297f 2934 VA_END(Marker);\r
a405b86d 2935 return(RetVal);\r
2247dde4 2936}\r
2937\r
2938/**\r
2939 Print at a specific location on the screen.\r
2940\r
e2f8297f 2941 This function will move the cursor to a given screen location and print the specified string.\r
1e6e84c7 2942\r
2943 If -1 is specified for either the Row or Col the current screen location for BOTH\r
e2f8297f 2944 will be used.\r
2247dde4 2945\r
e2f8297f 2946 If either Row or Col is out of range for the current console, then ASSERT.\r
2947 If Format is NULL, then ASSERT.\r
2247dde4 2948\r
1e6e84c7 2949 In addition to the standard %-based flags as supported by UefiLib Print() this supports\r
2247dde4 2950 the following additional flags:\r
1e6e84c7 2951 %N - Set output attribute to normal.\r
2952 %H - Set output attribute to highlight.\r
2953 %E - Set output attribute to error.\r
2954 %B - Set output attribute to blue color.\r
2955 %V - Set output attribute to green color.\r
2247dde4 2956\r
2957 Note: The background color is controlled by the shell command cls.\r
2958\r
1e6e84c7 2959 @param[in] Col The column to print at.\r
a405b86d 2960 @param[in] Row The row to print at.\r
1e6e84c7 2961 @param[in] Language The language of the string to retrieve. If this parameter\r
2962 is NULL, then the current platform language is used.\r
2963 @param[in] HiiFormatStringId The format string Id for getting from Hii.\r
2964 @param[in] HiiFormatHandle The format string Handle for getting from Hii.\r
a405b86d 2965 @param[in] ... The variable argument list.\r
2247dde4 2966\r
a405b86d 2967 @return EFI_SUCCESS The printing was successful.\r
2968 @return EFI_DEVICE_ERROR The console device reported an error.\r
2247dde4 2969**/\r
a405b86d 2970EFI_STATUS\r
2247dde4 2971EFIAPI\r
2972ShellPrintHiiEx(\r
2973 IN INT32 Col OPTIONAL,\r
2974 IN INT32 Row OPTIONAL,\r
1e6e84c7 2975 IN CONST CHAR8 *Language OPTIONAL,\r
2247dde4 2976 IN CONST EFI_STRING_ID HiiFormatStringId,\r
2977 IN CONST EFI_HANDLE HiiFormatHandle,\r
2978 ...\r
2979 )\r
2980{\r
2981 VA_LIST Marker;\r
2982 CHAR16 *HiiFormatString;\r
a405b86d 2983 EFI_STATUS RetVal;\r
2247dde4 2984\r
eeb9744e
RN
2985 RetVal = EFI_DEVICE_ERROR;\r
2986\r
2247dde4 2987 VA_START (Marker, HiiFormatHandle);\r
1e6e84c7 2988 HiiFormatString = HiiGetString(HiiFormatHandle, HiiFormatStringId, Language);\r
eeb9744e
RN
2989 if (HiiFormatString != NULL) {\r
2990 RetVal = InternalShellPrintWorker (Col, Row, HiiFormatString, Marker);\r
2991 SHELL_FREE_NON_NULL (HiiFormatString);\r
2992 }\r
e2f8297f 2993 VA_END(Marker);\r
2247dde4 2994\r
2995 return (RetVal);\r
2996}\r
2997\r
2998/**\r
2999 Function to determine if a given filename represents a file or a directory.\r
3000\r
3001 @param[in] DirName Path to directory to test.\r
3002\r
c8c22591 3003 @retval EFI_SUCCESS The Path represents a directory\r
3004 @retval EFI_NOT_FOUND The Path does not represent a directory\r
3005 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
3006 @return The path failed to open\r
2247dde4 3007**/\r
3008EFI_STATUS\r
3009EFIAPI\r
3010ShellIsDirectory(\r
3011 IN CONST CHAR16 *DirName\r
3012 )\r
3013{\r
3014 EFI_STATUS Status;\r
a405b86d 3015 SHELL_FILE_HANDLE Handle;\r
3e082d58 3016 CHAR16 *TempLocation;\r
3017 CHAR16 *TempLocation2;\r
2247dde4 3018\r
ecd3d59f 3019 ASSERT(DirName != NULL);\r
3020\r
a405b86d 3021 Handle = NULL;\r
3022 TempLocation = NULL;\r
2247dde4 3023\r
3024 Status = ShellOpenFileByName(DirName, &Handle, EFI_FILE_MODE_READ, 0);\r
3025 if (EFI_ERROR(Status)) {\r
a405b86d 3026 //\r
3027 // try good logic first.\r
3028 //\r
366f81a0 3029 if (gEfiShellProtocol != NULL) {\r
3e082d58 3030 TempLocation = StrnCatGrow(&TempLocation, NULL, DirName, 0);\r
c8c22591 3031 if (TempLocation == NULL) {\r
3032 ShellCloseFile(&Handle);\r
3033 return (EFI_OUT_OF_RESOURCES);\r
3034 }\r
3e082d58 3035 TempLocation2 = StrStr(TempLocation, L":");\r
3036 if (TempLocation2 != NULL && StrLen(StrStr(TempLocation, L":")) == 2) {\r
3037 *(TempLocation2+1) = CHAR_NULL;\r
a405b86d 3038 }\r
366f81a0 3039 if (gEfiShellProtocol->GetDevicePathFromMap(TempLocation) != NULL) {\r
a405b86d 3040 FreePool(TempLocation);\r
3041 return (EFI_SUCCESS);\r
3042 }\r
3043 FreePool(TempLocation);\r
3044 } else {\r
3045 //\r
3046 // probably a map name?!?!!?\r
3047 //\r
3048 TempLocation = StrStr(DirName, L"\\");\r
3049 if (TempLocation != NULL && *(TempLocation+1) == CHAR_NULL) {\r
3050 return (EFI_SUCCESS);\r
3051 }\r
3052 }\r
2247dde4 3053 return (Status);\r
3054 }\r
3055\r
3056 if (FileHandleIsDirectory(Handle) == EFI_SUCCESS) {\r
3057 ShellCloseFile(&Handle);\r
3058 return (EFI_SUCCESS);\r
3059 }\r
3060 ShellCloseFile(&Handle);\r
3061 return (EFI_NOT_FOUND);\r
3062}\r
3063\r
36a9d672 3064/**\r
3065 Function to determine if a given filename represents a file.\r
3066\r
3067 @param[in] Name Path to file to test.\r
3068\r
3069 @retval EFI_SUCCESS The Path represents a file.\r
3070 @retval EFI_NOT_FOUND The Path does not represent a file.\r
3071 @retval other The path failed to open.\r
3072**/\r
3073EFI_STATUS\r
3074EFIAPI\r
3075ShellIsFile(\r
3076 IN CONST CHAR16 *Name\r
3077 )\r
3078{\r
3079 EFI_STATUS Status;\r
a405b86d 3080 SHELL_FILE_HANDLE Handle;\r
36a9d672 3081\r
ecd3d59f 3082 ASSERT(Name != NULL);\r
3083\r
36a9d672 3084 Handle = NULL;\r
3085\r
3086 Status = ShellOpenFileByName(Name, &Handle, EFI_FILE_MODE_READ, 0);\r
3087 if (EFI_ERROR(Status)) {\r
3088 return (Status);\r
3089 }\r
3090\r
3091 if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {\r
3092 ShellCloseFile(&Handle);\r
3093 return (EFI_SUCCESS);\r
3094 }\r
3095 ShellCloseFile(&Handle);\r
3096 return (EFI_NOT_FOUND);\r
3097}\r
3098\r
b3011f40 3099/**\r
3100 Function to determine if a given filename represents a file.\r
3101\r
3102 This will search the CWD and then the Path.\r
3103\r
3104 If Name is NULL, then ASSERT.\r
3105\r
3106 @param[in] Name Path to file to test.\r
3107\r
3108 @retval EFI_SUCCESS The Path represents a file.\r
3109 @retval EFI_NOT_FOUND The Path does not represent a file.\r
3110 @retval other The path failed to open.\r
3111**/\r
3112EFI_STATUS\r
3113EFIAPI\r
3114ShellIsFileInPath(\r
3115 IN CONST CHAR16 *Name\r
a405b86d 3116 )\r
3117{\r
b3011f40 3118 CHAR16 *NewName;\r
3119 EFI_STATUS Status;\r
3120\r
3121 if (!EFI_ERROR(ShellIsFile(Name))) {\r
a405b86d 3122 return (EFI_SUCCESS);\r
b3011f40 3123 }\r
3124\r
3125 NewName = ShellFindFilePath(Name);\r
3126 if (NewName == NULL) {\r
3127 return (EFI_NOT_FOUND);\r
3128 }\r
3129 Status = ShellIsFile(NewName);\r
3130 FreePool(NewName);\r
3131 return (Status);\r
3132}\r
252d9457 3133\r
74b0fb8c
JC
3134/**\r
3135 Function return the number converted from a hex representation of a number.\r
3136\r
3137 Note: this function cannot be used when (UINTN)(-1), (0xFFFFFFFF) may be a valid\r
3138 result. Use ShellConvertStringToUint64 instead.\r
3139\r
3140 @param[in] String String representation of a number.\r
3141\r
3142 @return The unsigned integer result of the conversion.\r
3143 @retval (UINTN)(-1) An error occured.\r
3144**/\r
3145UINTN\r
3146EFIAPI\r
3147ShellHexStrToUintn(\r
3148 IN CONST CHAR16 *String\r
3149 )\r
3150{\r
3151 UINT64 RetVal;\r
3152\r
3153 if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, TRUE, TRUE))) {\r
3154 return ((UINTN)RetVal);\r
3155 }\r
3156 \r
3157 return ((UINTN)(-1));\r
3158}\r
3159\r
125c2cf4 3160/**\r
1e6e84c7 3161 Function to determine whether a string is decimal or hex representation of a number\r
d59fc244 3162 and return the number converted from the string. Spaces are always skipped.\r
125c2cf4 3163\r
3164 @param[in] String String representation of a number\r
3165\r
252d9457 3166 @return the number\r
3167 @retval (UINTN)(-1) An error ocurred.\r
125c2cf4 3168**/\r
3169UINTN\r
3170EFIAPI\r
3171ShellStrToUintn(\r
3172 IN CONST CHAR16 *String\r
3173 )\r
3174{\r
252d9457 3175 UINT64 RetVal;\r
3176 BOOLEAN Hex;\r
3177\r
3178 Hex = FALSE;\r
3179\r
658bf43e 3180 if (!InternalShellIsHexOrDecimalNumber(String, Hex, TRUE, FALSE)) {\r
252d9457 3181 Hex = TRUE;\r
125c2cf4 3182 }\r
252d9457 3183\r
3184 if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, Hex, TRUE))) {\r
3185 return ((UINTN)RetVal);\r
3186 }\r
3187 return ((UINTN)(-1));\r
125c2cf4 3188}\r
3189\r
3190/**\r
3191 Safely append with automatic string resizing given length of Destination and\r
3192 desired length of copy from Source.\r
3193\r
3194 append the first D characters of Source to the end of Destination, where D is\r
3195 the lesser of Count and the StrLen() of Source. If appending those D characters\r
3196 will fit within Destination (whose Size is given as CurrentSize) and\r
1e6e84c7 3197 still leave room for a NULL terminator, then those characters are appended,\r
3198 starting at the original terminating NULL of Destination, and a new terminating\r
3199 NULL is appended.\r
125c2cf4 3200\r
3201 If appending D characters onto Destination will result in a overflow of the size\r
3202 given in CurrentSize the string will be grown such that the copy can be performed\r
3203 and CurrentSize will be updated to the new size.\r
3204\r
3205 If Source is NULL, there is nothing to append, just return the current buffer in\r
3206 Destination.\r
3207\r
3208 if Destination is NULL, then ASSERT()\r
3209 if Destination's current length (including NULL terminator) is already more then\r
3210 CurrentSize, then ASSERT()\r
3211\r
4ff7e37b
ED
3212 @param[in, out] Destination The String to append onto\r
3213 @param[in, out] CurrentSize on call the number of bytes in Destination. On\r
125c2cf4 3214 return possibly the new size (still in bytes). if NULL\r
3215 then allocate whatever is needed.\r
3216 @param[in] Source The String to append from\r
3217 @param[in] Count Maximum number of characters to append. if 0 then\r
3218 all are appended.\r
3219\r
3220 @return Destination return the resultant string.\r
3221**/\r
3222CHAR16*\r
3223EFIAPI\r
3224StrnCatGrow (\r
3225 IN OUT CHAR16 **Destination,\r
3226 IN OUT UINTN *CurrentSize,\r
3227 IN CONST CHAR16 *Source,\r
3228 IN UINTN Count\r
3229 )\r
3230{\r
3231 UINTN DestinationStartSize;\r
3232 UINTN NewSize;\r
3233\r
3234 //\r
3235 // ASSERTs\r
3236 //\r
3237 ASSERT(Destination != NULL);\r
3238\r
3239 //\r
3240 // If there's nothing to do then just return Destination\r
3241 //\r
3242 if (Source == NULL) {\r
3243 return (*Destination);\r
3244 }\r
3245\r
3246 //\r
3247 // allow for un-initialized pointers, based on size being 0\r
3248 //\r
3249 if (CurrentSize != NULL && *CurrentSize == 0) {\r
3250 *Destination = NULL;\r
3251 }\r
3252\r
3253 //\r
3254 // allow for NULL pointers address as Destination\r
3255 //\r
3256 if (*Destination != NULL) {\r
3257 ASSERT(CurrentSize != 0);\r
3258 DestinationStartSize = StrSize(*Destination);\r
3259 ASSERT(DestinationStartSize <= *CurrentSize);\r
3260 } else {\r
3261 DestinationStartSize = 0;\r
3262// ASSERT(*CurrentSize == 0);\r
3263 }\r
3264\r
3265 //\r
3266 // Append all of Source?\r
3267 //\r
3268 if (Count == 0) {\r
3269 Count = StrLen(Source);\r
3270 }\r
3271\r
3272 //\r
3273 // Test and grow if required\r
3274 //\r
3275 if (CurrentSize != NULL) {\r
3276 NewSize = *CurrentSize;\r
f480fdc0
ED
3277 if (NewSize < DestinationStartSize + (Count * sizeof(CHAR16))) {\r
3278 while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) {\r
3279 NewSize += 2 * Count * sizeof(CHAR16);\r
3280 }\r
3281 *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);\r
3282 *CurrentSize = NewSize;\r
125c2cf4 3283 }\r
125c2cf4 3284 } else {\r
c587fd3e
QS
3285 NewSize = (Count+1)*sizeof(CHAR16);\r
3286 *Destination = AllocateZeroPool(NewSize);\r
125c2cf4 3287 }\r
3288\r
3289 //\r
3290 // Now use standard StrnCat on a big enough buffer\r
3291 //\r
c9d92df0 3292 if (*Destination == NULL) {\r
3293 return (NULL);\r
3294 }\r
e75390f0 3295 \r
c587fd3e 3296 StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, Count);\r
e75390f0 3297 return *Destination;\r
125c2cf4 3298}\r
c9d92df0 3299\r
3300/**\r
3301 Prompt the user and return the resultant answer to the requestor.\r
3302\r
3303 This function will display the requested question on the shell prompt and then\r
1d322461 3304 wait for an appropriate answer to be input from the console.\r
c9d92df0 3305\r
a405b86d 3306 if the SHELL_PROMPT_REQUEST_TYPE is SHELL_PROMPT_REQUEST_TYPE_YESNO, ShellPromptResponseTypeQuitContinue\r
c9d92df0 3307 or SHELL_PROMPT_REQUEST_TYPE_YESNOCANCEL then *Response is of type SHELL_PROMPT_RESPONSE.\r
3308\r
a405b86d 3309 if the SHELL_PROMPT_REQUEST_TYPE is ShellPromptResponseTypeFreeform then *Response is of type\r
c9d92df0 3310 CHAR16*.\r
3311\r
3312 In either case *Response must be callee freed if Response was not NULL;\r
3313\r
3314 @param Type What type of question is asked. This is used to filter the input\r
3315 to prevent invalid answers to question.\r
3316 @param Prompt Pointer to string prompt to use to request input.\r
3317 @param Response Pointer to Response which will be populated upon return.\r
3318\r
3319 @retval EFI_SUCCESS The operation was sucessful.\r
3320 @retval EFI_UNSUPPORTED The operation is not supported as requested.\r
3321 @retval EFI_INVALID_PARAMETER A parameter was invalid.\r
3322 @return other The operation failed.\r
3323**/\r
3324EFI_STATUS\r
3325EFIAPI\r
3326ShellPromptForResponse (\r
3327 IN SHELL_PROMPT_REQUEST_TYPE Type,\r
3328 IN CHAR16 *Prompt OPTIONAL,\r
3329 IN OUT VOID **Response OPTIONAL\r
3330 )\r
3331{\r
3332 EFI_STATUS Status;\r
3333 EFI_INPUT_KEY Key;\r
3334 UINTN EventIndex;\r
3335 SHELL_PROMPT_RESPONSE *Resp;\r
a405b86d 3336 UINTN Size;\r
3337 CHAR16 *Buffer;\r
c9d92df0 3338\r
a405b86d 3339 Status = EFI_UNSUPPORTED;\r
3340 Resp = NULL;\r
3341 Buffer = NULL;\r
3342 Size = 0;\r
3343 if (Type != ShellPromptResponseTypeFreeform) {\r
252d9457 3344 Resp = (SHELL_PROMPT_RESPONSE*)AllocateZeroPool(sizeof(SHELL_PROMPT_RESPONSE));\r
3e082d58 3345 if (Resp == NULL) {\r
3346 return (EFI_OUT_OF_RESOURCES);\r
3347 }\r
90bfa227 3348 }\r
c9d92df0 3349\r
3350 switch(Type) {\r
a405b86d 3351 case ShellPromptResponseTypeQuitContinue:\r
c9d92df0 3352 if (Prompt != NULL) {\r
3353 ShellPrintEx(-1, -1, L"%s", Prompt);\r
3354 }\r
3355 //\r
3356 // wait for valid response\r
3357 //\r
3358 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
3359 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
31b018a6
JC
3360 if (EFI_ERROR(Status)) {\r
3361 break;\r
3362 }\r
c9d92df0 3363 ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
3364 if (Key.UnicodeChar == L'Q' || Key.UnicodeChar ==L'q') {\r
a405b86d 3365 *Resp = ShellPromptResponseQuit;\r
c9d92df0 3366 } else {\r
a405b86d 3367 *Resp = ShellPromptResponseContinue;\r
c9d92df0 3368 }\r
3369 break;\r
a405b86d 3370 case ShellPromptResponseTypeYesNoCancel:\r
c9d92df0 3371 if (Prompt != NULL) {\r
3372 ShellPrintEx(-1, -1, L"%s", Prompt);\r
3373 }\r
3374 //\r
3375 // wait for valid response\r
3376 //\r
a405b86d 3377 *Resp = ShellPromptResponseMax;\r
3378 while (*Resp == ShellPromptResponseMax) {\r
194ae48d
JC
3379 if (ShellGetExecutionBreakFlag()) {\r
3380 Status = EFI_ABORTED;\r
3381 break;\r
3382 }\r
c9d92df0 3383 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
3384 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
31b018a6
JC
3385 if (EFI_ERROR(Status)) {\r
3386 break;\r
3387 }\r
c9d92df0 3388 ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
3389 switch (Key.UnicodeChar) {\r
3390 case L'Y':\r
3391 case L'y':\r
a405b86d 3392 *Resp = ShellPromptResponseYes;\r
c9d92df0 3393 break;\r
3394 case L'N':\r
3395 case L'n':\r
a405b86d 3396 *Resp = ShellPromptResponseNo;\r
3397 break;\r
3398 case L'C':\r
3399 case L'c':\r
3400 *Resp = ShellPromptResponseCancel;\r
3401 break;\r
3402 }\r
3403 }\r
ac55b925
TS
3404 break;\r
3405 case ShellPromptResponseTypeYesNoAllCancel:\r
a405b86d 3406 if (Prompt != NULL) {\r
3407 ShellPrintEx(-1, -1, L"%s", Prompt);\r
3408 }\r
3409 //\r
3410 // wait for valid response\r
3411 //\r
3412 *Resp = ShellPromptResponseMax;\r
3413 while (*Resp == ShellPromptResponseMax) {\r
194ae48d
JC
3414 if (ShellGetExecutionBreakFlag()) {\r
3415 Status = EFI_ABORTED;\r
3416 break;\r
3417 }\r
a405b86d 3418 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
3419 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
31b018a6
JC
3420 if (EFI_ERROR(Status)) {\r
3421 break;\r
3422 }\r
ac55b925
TS
3423\r
3424 if (Key.UnicodeChar <= 127 && Key.UnicodeChar >= 32) {\r
3425 ShellPrintEx (-1, -1, L"%c", Key.UnicodeChar);\r
3426 }\r
3427\r
a405b86d 3428 switch (Key.UnicodeChar) {\r
3429 case L'Y':\r
3430 case L'y':\r
3431 *Resp = ShellPromptResponseYes;\r
3432 break;\r
3433 case L'N':\r
3434 case L'n':\r
3435 *Resp = ShellPromptResponseNo;\r
c9d92df0 3436 break;\r
3437 case L'A':\r
3438 case L'a':\r
a405b86d 3439 *Resp = ShellPromptResponseAll;\r
c9d92df0 3440 break;\r
3441 case L'C':\r
3442 case L'c':\r
a405b86d 3443 *Resp = ShellPromptResponseCancel;\r
c9d92df0 3444 break;\r
3445 }\r
3446 }\r
3447 break;\r
a405b86d 3448 case ShellPromptResponseTypeEnterContinue:\r
3449 case ShellPromptResponseTypeAnyKeyContinue:\r
c9d92df0 3450 if (Prompt != NULL) {\r
3451 ShellPrintEx(-1, -1, L"%s", Prompt);\r
3452 }\r
3453 //\r
3454 // wait for valid response\r
3455 //\r
a405b86d 3456 *Resp = ShellPromptResponseMax;\r
3457 while (*Resp == ShellPromptResponseMax) {\r
194ae48d
JC
3458 if (ShellGetExecutionBreakFlag()) {\r
3459 Status = EFI_ABORTED;\r
3460 break;\r
3461 }\r
c9d92df0 3462 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
a405b86d 3463 if (Type == ShellPromptResponseTypeEnterContinue) {\r
c9d92df0 3464 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
31b018a6
JC
3465 if (EFI_ERROR(Status)) {\r
3466 break;\r
3467 }\r
c9d92df0 3468 ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
3469 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
a405b86d 3470 *Resp = ShellPromptResponseContinue;\r
c9d92df0 3471 break;\r
3472 }\r
3473 }\r
a405b86d 3474 if (Type == ShellPromptResponseTypeAnyKeyContinue) {\r
3475 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
3476 ASSERT_EFI_ERROR(Status);\r
3477 *Resp = ShellPromptResponseContinue;\r
3478 break;\r
3479 }\r
3480 }\r
3481 break;\r
3482 case ShellPromptResponseTypeYesNo:\r
3483 if (Prompt != NULL) {\r
3484 ShellPrintEx(-1, -1, L"%s", Prompt);\r
3485 }\r
3486 //\r
3487 // wait for valid response\r
3488 //\r
3489 *Resp = ShellPromptResponseMax;\r
3490 while (*Resp == ShellPromptResponseMax) {\r
194ae48d
JC
3491 if (ShellGetExecutionBreakFlag()) {\r
3492 Status = EFI_ABORTED;\r
3493 break;\r
3494 }\r
a405b86d 3495 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
3496 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
31b018a6
JC
3497 if (EFI_ERROR(Status)) {\r
3498 break;\r
3499 }\r
a405b86d 3500 ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
3501 switch (Key.UnicodeChar) {\r
3502 case L'Y':\r
3503 case L'y':\r
3504 *Resp = ShellPromptResponseYes;\r
3505 break;\r
3506 case L'N':\r
3507 case L'n':\r
3508 *Resp = ShellPromptResponseNo;\r
3509 break;\r
3510 }\r
3511 }\r
3512 break;\r
3513 case ShellPromptResponseTypeFreeform:\r
3514 if (Prompt != NULL) {\r
3515 ShellPrintEx(-1, -1, L"%s", Prompt);\r
3516 }\r
3517 while(1) {\r
194ae48d
JC
3518 if (ShellGetExecutionBreakFlag()) {\r
3519 Status = EFI_ABORTED;\r
3520 break;\r
3521 }\r
a405b86d 3522 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
3523 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
31b018a6
JC
3524 if (EFI_ERROR(Status)) {\r
3525 break;\r
3526 }\r
a405b86d 3527 ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
3528 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
c9d92df0 3529 break;\r
3530 }\r
a405b86d 3531 ASSERT((Buffer == NULL && Size == 0) || (Buffer != NULL));\r
3532 StrnCatGrow(&Buffer, &Size, &Key.UnicodeChar, 1);\r
c9d92df0 3533 }\r
3534 break;\r
a405b86d 3535 //\r
3536 // This is the location to add new prompt types.\r
194ae48d 3537 // If your new type loops remember to add ExecutionBreak support.\r
a405b86d 3538 //\r
c9d92df0 3539 default:\r
a405b86d 3540 ASSERT(FALSE);\r
c9d92df0 3541 }\r
3542\r
3543 if (Response != NULL) {\r
a405b86d 3544 if (Resp != NULL) {\r
3545 *Response = Resp;\r
3546 } else if (Buffer != NULL) {\r
3547 *Response = Buffer;\r
3548 }\r
c9d92df0 3549 } else {\r
a405b86d 3550 if (Resp != NULL) {\r
3551 FreePool(Resp);\r
3552 }\r
3553 if (Buffer != NULL) {\r
3554 FreePool(Buffer);\r
3555 }\r
c9d92df0 3556 }\r
3557\r
a405b86d 3558 ShellPrintEx(-1, -1, L"\r\n");\r
c9d92df0 3559 return (Status);\r
3560}\r
3561\r
3562/**\r
3563 Prompt the user and return the resultant answer to the requestor.\r
3564\r
3565 This function is the same as ShellPromptForResponse, except that the prompt is\r
3566 automatically pulled from HII.\r
3567\r
3568 @param Type What type of question is asked. This is used to filter the input\r
3569 to prevent invalid answers to question.\r
a405b86d 3570 @param[in] HiiFormatStringId The format string Id for getting from Hii.\r
3571 @param[in] HiiFormatHandle The format string Handle for getting from Hii.\r
3572 @param Response Pointer to Response which will be populated upon return.\r
c9d92df0 3573\r
3574 @retval EFI_SUCCESS the operation was sucessful.\r
3575 @return other the operation failed.\r
3576\r
3577 @sa ShellPromptForResponse\r
3578**/\r
3579EFI_STATUS\r
3580EFIAPI\r
3581ShellPromptForResponseHii (\r
3582 IN SHELL_PROMPT_REQUEST_TYPE Type,\r
3583 IN CONST EFI_STRING_ID HiiFormatStringId,\r
3584 IN CONST EFI_HANDLE HiiFormatHandle,\r
3585 IN OUT VOID **Response\r
3586 )\r
3587{\r
3588 CHAR16 *Prompt;\r
3589 EFI_STATUS Status;\r
3590\r
3591 Prompt = HiiGetString(HiiFormatHandle, HiiFormatStringId, NULL);\r
3592 Status = ShellPromptForResponse(Type, Prompt, Response);\r
3593 FreePool(Prompt);\r
3594 return (Status);\r
3595}\r
3596\r
a405b86d 3597/**\r
3598 Function to determin if an entire string is a valid number.\r
3599\r
3600 If Hex it must be preceeded with a 0x or has ForceHex, set TRUE.\r
c9d92df0 3601\r
a405b86d 3602 @param[in] String The string to evaluate.\r
3603 @param[in] ForceHex TRUE - always assume hex.\r
3604 @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going.\r
658bf43e 3605 @param[in] TimeNumbers TRUE to allow numbers with ":", FALSE otherwise.\r
a405b86d 3606\r
3607 @retval TRUE It is all numeric (dec/hex) characters.\r
3608 @retval FALSE There is a non-numeric character.\r
3609**/\r
3610BOOLEAN\r
252d9457 3611InternalShellIsHexOrDecimalNumber (\r
a405b86d 3612 IN CONST CHAR16 *String,\r
3613 IN CONST BOOLEAN ForceHex,\r
658bf43e 3614 IN CONST BOOLEAN StopAtSpace,\r
3615 IN CONST BOOLEAN TimeNumbers\r
a405b86d 3616 )\r
3617{\r
3618 BOOLEAN Hex;\r
3619\r
3620 //\r
3621 // chop off a single negative sign\r
3622 //\r
3623 if (String != NULL && *String == L'-') {\r
3624 String++;\r
3625 }\r
b0934ac4 3626\r
a405b86d 3627 if (String == NULL) {\r
3628 return (FALSE);\r
3629 }\r
3630\r
3631 //\r
3632 // chop leading zeroes\r
3633 //\r
3634 while(String != NULL && *String == L'0'){\r
3635 String++;\r
3636 }\r
3637 //\r
3638 // allow '0x' or '0X', but not 'x' or 'X'\r
3639 //\r
3640 if (String != NULL && (*String == L'x' || *String == L'X')) {\r
3641 if (*(String-1) != L'0') {\r
3642 //\r
3643 // we got an x without a preceeding 0\r
3644 //\r
3645 return (FALSE);\r
3646 }\r
3647 String++;\r
3648 Hex = TRUE;\r
3649 } else if (ForceHex) {\r
3650 Hex = TRUE;\r
3651 } else {\r
3652 Hex = FALSE;\r
3653 }\r
3654\r
3655 //\r
3656 // loop through the remaining characters and use the lib function\r
3657 //\r
3658 for ( ; String != NULL && *String != CHAR_NULL && !(StopAtSpace && *String == L' ') ; String++){\r
658bf43e 3659 if (TimeNumbers && (String[0] == L':')) {\r
3660 continue;\r
3661 }\r
a405b86d 3662 if (Hex) {\r
3663 if (!ShellIsHexaDecimalDigitCharacter(*String)) {\r
3664 return (FALSE);\r
3665 }\r
3666 } else {\r
3667 if (!ShellIsDecimalDigitCharacter(*String)) {\r
3668 return (FALSE);\r
3669 }\r
3670 }\r
3671 }\r
252d9457 3672\r
a405b86d 3673 return (TRUE);\r
3674}\r
3675\r
3676/**\r
3677 Function to determine if a given filename exists.\r
3678\r
3679 @param[in] Name Path to test.\r
3680\r
3681 @retval EFI_SUCCESS The Path represents a file.\r
3682 @retval EFI_NOT_FOUND The Path does not represent a file.\r
3683 @retval other The path failed to open.\r
3684**/\r
3685EFI_STATUS\r
3686EFIAPI\r
3687ShellFileExists(\r
3688 IN CONST CHAR16 *Name\r
3689 )\r
3690{\r
3691 EFI_STATUS Status;\r
3692 EFI_SHELL_FILE_INFO *List;\r
3693\r
3694 ASSERT(Name != NULL);\r
3695\r
3696 List = NULL;\r
3697 Status = ShellOpenFileMetaArg((CHAR16*)Name, EFI_FILE_MODE_READ, &List);\r
3698 if (EFI_ERROR(Status)) {\r
3699 return (Status);\r
3700 }\r
3701\r
3702 ShellCloseFileMetaArg(&List);\r
3703\r
3704 return (EFI_SUCCESS);\r
3705}\r
252d9457 3706\r
3707/**\r
b0934ac4 3708 Convert a Unicode character to upper case only if\r
252d9457 3709 it maps to a valid small-case ASCII character.\r
3710\r
3711 This internal function only deal with Unicode character\r
3712 which maps to a valid small-case ASCII character, i.e.\r
3713 L'a' to L'z'. For other Unicode character, the input character\r
3714 is returned directly.\r
3715\r
3716 @param Char The character to convert.\r
3717\r
3718 @retval LowerCharacter If the Char is with range L'a' to L'z'.\r
3719 @retval Unchanged Otherwise.\r
3720\r
3721**/\r
3722CHAR16\r
252d9457 3723InternalShellCharToUpper (\r
3724 IN CHAR16 Char\r
3725 )\r
3726{\r
3727 if (Char >= L'a' && Char <= L'z') {\r
3728 return (CHAR16) (Char - (L'a' - L'A'));\r
3729 }\r
3730\r
3731 return Char;\r
3732}\r
3733\r
3734/**\r
3735 Convert a Unicode character to numerical value.\r
3736\r
3737 This internal function only deal with Unicode character\r
3738 which maps to a valid hexadecimal ASII character, i.e.\r
b0934ac4 3739 L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other\r
252d9457 3740 Unicode character, the value returned does not make sense.\r
3741\r
3742 @param Char The character to convert.\r
3743\r
3744 @return The numerical value converted.\r
3745\r
3746**/\r
3747UINTN\r
252d9457 3748InternalShellHexCharToUintn (\r
3749 IN CHAR16 Char\r
3750 )\r
3751{\r
3752 if (ShellIsDecimalDigitCharacter (Char)) {\r
3753 return Char - L'0';\r
3754 }\r
3755\r
22454f10 3756 return (10 + InternalShellCharToUpper (Char) - L'A');\r
252d9457 3757}\r
3758\r
3759/**\r
3760 Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64.\r
3761\r
80f3e34f 3762 This function returns a value of type UINT64 by interpreting the contents\r
252d9457 3763 of the Unicode string specified by String as a hexadecimal number.\r
3764 The format of the input Unicode string String is:\r
3765\r
3766 [spaces][zeros][x][hexadecimal digits].\r
3767\r
3768 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
3769 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
3770 If "x" appears in the input string, it must be prefixed with at least one 0.\r
3771 The function will ignore the pad space, which includes spaces or tab characters,\r
3772 before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or\r
3773 [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the\r
3774 first valid hexadecimal digit. Then, the function stops at the first character that is\r
3775 a not a valid hexadecimal character or NULL, whichever one comes first.\r
3776\r
3777 If String has only pad spaces, then zero is returned.\r
3778 If String has no leading pad spaces, leading zeros or valid hexadecimal digits,\r
3779 then zero is returned.\r
3780\r
3781 @param[in] String A pointer to a Null-terminated Unicode string.\r
3782 @param[out] Value Upon a successful return the value of the conversion.\r
3783 @param[in] StopAtSpace FALSE to skip spaces.\r
3784\r
3785 @retval EFI_SUCCESS The conversion was successful.\r
3786 @retval EFI_INVALID_PARAMETER A parameter was NULL or invalid.\r
3787 @retval EFI_DEVICE_ERROR An overflow occured.\r
3788**/\r
3789EFI_STATUS\r
252d9457 3790InternalShellStrHexToUint64 (\r
3791 IN CONST CHAR16 *String,\r
3792 OUT UINT64 *Value,\r
3793 IN CONST BOOLEAN StopAtSpace\r
3794 )\r
3795{\r
3796 UINT64 Result;\r
3797\r
3798 if (String == NULL || StrSize(String) == 0 || Value == NULL) {\r
3799 return (EFI_INVALID_PARAMETER);\r
3800 }\r
b0934ac4 3801\r
252d9457 3802 //\r
b0934ac4 3803 // Ignore the pad spaces (space or tab)\r
252d9457 3804 //\r
3805 while ((*String == L' ') || (*String == L'\t')) {\r
3806 String++;\r
3807 }\r
3808\r
3809 //\r
3810 // Ignore leading Zeros after the spaces\r
3811 //\r
3812 while (*String == L'0') {\r
3813 String++;\r
3814 }\r
3815\r
3816 if (InternalShellCharToUpper (*String) == L'X') {\r
3817 if (*(String - 1) != L'0') {\r
3818 return 0;\r
3819 }\r
3820 //\r
3821 // Skip the 'X'\r
3822 //\r
3823 String++;\r
3824 }\r
3825\r
3826 Result = 0;\r
b0934ac4 3827\r
252d9457 3828 //\r
80f3e34f 3829 // there is a space where there should't be\r
252d9457 3830 //\r
80f3e34f
JC
3831 if (*String == L' ') {\r
3832 return (EFI_INVALID_PARAMETER);\r
252d9457 3833 }\r
b0934ac4 3834\r
252d9457 3835 while (ShellIsHexaDecimalDigitCharacter (*String)) {\r
3836 //\r
b0934ac4 3837 // If the Hex Number represented by String overflows according\r
80f3e34f 3838 // to the range defined by UINT64, then return EFI_DEVICE_ERROR.\r
252d9457 3839 //\r
3840 if (!(Result <= (RShiftU64((((UINT64) ~0) - InternalShellHexCharToUintn (*String)), 4)))) {\r
3841// if (!(Result <= ((((UINT64) ~0) - InternalShellHexCharToUintn (*String)) >> 4))) {\r
3842 return (EFI_DEVICE_ERROR);\r
3843 }\r
3844\r
3845 Result = (LShiftU64(Result, 4));\r
3846 Result += InternalShellHexCharToUintn (*String);\r
3847 String++;\r
3848\r
3849 //\r
49bd498d 3850 // stop at spaces if requested\r
252d9457 3851 //\r
49bd498d 3852 if (StopAtSpace && *String == L' ') {\r
3853 break;\r
252d9457 3854 }\r
3855 }\r
3856\r
3857 *Value = Result;\r
3858 return (EFI_SUCCESS);\r
3859}\r
3860\r
3861/**\r
3862 Convert a Null-terminated Unicode decimal string to a value of\r
3863 type UINT64.\r
3864\r
3865 This function returns a value of type UINT64 by interpreting the contents\r
3866 of the Unicode string specified by String as a decimal number. The format\r
3867 of the input Unicode string String is:\r
3868\r
3869 [spaces] [decimal digits].\r
3870\r
3871 The valid decimal digit character is in the range [0-9]. The\r
3872 function will ignore the pad space, which includes spaces or\r
3873 tab characters, before [decimal digits]. The running zero in the\r
3874 beginning of [decimal digits] will be ignored. Then, the function\r
3875 stops at the first character that is a not a valid decimal character\r
3876 or a Null-terminator, whichever one comes first.\r
3877\r
3878 If String has only pad spaces, then 0 is returned.\r
3879 If String has no pad spaces or valid decimal digits,\r
3880 then 0 is returned.\r
3881\r
3882 @param[in] String A pointer to a Null-terminated Unicode string.\r
3883 @param[out] Value Upon a successful return the value of the conversion.\r
3884 @param[in] StopAtSpace FALSE to skip spaces.\r
3885\r
3886 @retval EFI_SUCCESS The conversion was successful.\r
3887 @retval EFI_INVALID_PARAMETER A parameter was NULL or invalid.\r
3888 @retval EFI_DEVICE_ERROR An overflow occured.\r
3889**/\r
3890EFI_STATUS\r
252d9457 3891InternalShellStrDecimalToUint64 (\r
3892 IN CONST CHAR16 *String,\r
3893 OUT UINT64 *Value,\r
3894 IN CONST BOOLEAN StopAtSpace\r
3895 )\r
3896{\r
3897 UINT64 Result;\r
3898\r
3899 if (String == NULL || StrSize (String) == 0 || Value == NULL) {\r
3900 return (EFI_INVALID_PARAMETER);\r
3901 }\r
3902\r
3903 //\r
3904 // Ignore the pad spaces (space or tab)\r
3905 //\r
3906 while ((*String == L' ') || (*String == L'\t')) {\r
3907 String++;\r
3908 }\r
3909\r
3910 //\r
3911 // Ignore leading Zeros after the spaces\r
3912 //\r
3913 while (*String == L'0') {\r
3914 String++;\r
3915 }\r
3916\r
3917 Result = 0;\r
3918\r
3919 //\r
80f3e34f
JC
3920 // Stop upon space if requested \r
3921 // (if the whole value was 0)\r
252d9457 3922 //\r
80f3e34f
JC
3923 if (StopAtSpace && *String == L' ') {\r
3924 *Value = Result;\r
3925 return (EFI_SUCCESS);\r
252d9457 3926 }\r
80f3e34f 3927\r
252d9457 3928 while (ShellIsDecimalDigitCharacter (*String)) {\r
3929 //\r
b0934ac4 3930 // If the number represented by String overflows according\r
80f3e34f 3931 // to the range defined by UINT64, then return EFI_DEVICE_ERROR.\r
252d9457 3932 //\r
b0934ac4 3933\r
252d9457 3934 if (!(Result <= (DivU64x32((((UINT64) ~0) - (*String - L'0')),10)))) {\r
3935 return (EFI_DEVICE_ERROR);\r
3936 }\r
3937\r
3938 Result = MultU64x32(Result, 10) + (*String - L'0');\r
3939 String++;\r
3940\r
3941 //\r
3942 // Stop at spaces if requested\r
3943 //\r
3944 if (StopAtSpace && *String == L' ') {\r
3945 break;\r
3946 }\r
3947 }\r
3948\r
3949 *Value = Result;\r
b0934ac4 3950\r
252d9457 3951 return (EFI_SUCCESS);\r
3952}\r
3953\r
3954/**\r
3955 Function to verify and convert a string to its numerical value.\r
3956\r
3957 If Hex it must be preceeded with a 0x, 0X, or has ForceHex set TRUE.\r
3958\r
3959 @param[in] String The string to evaluate.\r
3960 @param[out] Value Upon a successful return the value of the conversion.\r
3961 @param[in] ForceHex TRUE - always assume hex.\r
3962 @param[in] StopAtSpace FALSE to skip spaces.\r
b0934ac4 3963\r
252d9457 3964 @retval EFI_SUCCESS The conversion was successful.\r
3965 @retval EFI_INVALID_PARAMETER String contained an invalid character.\r
3966 @retval EFI_NOT_FOUND String was a number, but Value was NULL.\r
3967**/\r
3968EFI_STATUS\r
3969EFIAPI\r
3970ShellConvertStringToUint64(\r
3971 IN CONST CHAR16 *String,\r
3972 OUT UINT64 *Value,\r
3973 IN CONST BOOLEAN ForceHex,\r
3974 IN CONST BOOLEAN StopAtSpace\r
3975 )\r
3976{\r
3977 UINT64 RetVal;\r
3978 CONST CHAR16 *Walker;\r
3979 EFI_STATUS Status;\r
3980 BOOLEAN Hex;\r
3981\r
3982 Hex = ForceHex;\r
3983\r
658bf43e 3984 if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace, FALSE)) {\r
252d9457 3985 if (!Hex) {\r
3986 Hex = TRUE;\r
658bf43e 3987 if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace, FALSE)) {\r
252d9457 3988 return (EFI_INVALID_PARAMETER);\r
3989 }\r
3990 } else {\r
3991 return (EFI_INVALID_PARAMETER);\r
3992 }\r
3993 }\r
3994\r
3995 //\r
3996 // Chop off leading spaces\r
3997 //\r
3998 for (Walker = String; Walker != NULL && *Walker != CHAR_NULL && *Walker == L' '; Walker++);\r
3999\r
4000 //\r
4001 // make sure we have something left that is numeric.\r
4002 //\r
658bf43e 4003 if (Walker == NULL || *Walker == CHAR_NULL || !InternalShellIsHexOrDecimalNumber(Walker, Hex, StopAtSpace, FALSE)) {\r
252d9457 4004 return (EFI_INVALID_PARAMETER);\r
b0934ac4 4005 }\r
252d9457 4006\r
4007 //\r
4008 // do the conversion.\r
4009 //\r
4010 if (Hex || StrnCmp(Walker, L"0x", 2) == 0 || StrnCmp(Walker, L"0X", 2) == 0){\r
4011 Status = InternalShellStrHexToUint64(Walker, &RetVal, StopAtSpace);\r
4012 } else {\r
4013 Status = InternalShellStrDecimalToUint64(Walker, &RetVal, StopAtSpace);\r
4014 }\r
4015\r
4016 if (Value == NULL && !EFI_ERROR(Status)) {\r
4017 return (EFI_NOT_FOUND);\r
4018 }\r
4019\r
4020 if (Value != NULL) {\r
4021 *Value = RetVal;\r
4022 }\r
4023\r
4024 return (Status);\r
4025}\r
4026\r
4027/**\r
4028 Function to determin if an entire string is a valid number.\r
4029\r
4030 If Hex it must be preceeded with a 0x or has ForceHex, set TRUE.\r
4031\r
4032 @param[in] String The string to evaluate.\r
4033 @param[in] ForceHex TRUE - always assume hex.\r
4034 @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going.\r
4035\r
4036 @retval TRUE It is all numeric (dec/hex) characters.\r
4037 @retval FALSE There is a non-numeric character.\r
4038**/\r
4039BOOLEAN\r
4040EFIAPI\r
4041ShellIsHexOrDecimalNumber (\r
4042 IN CONST CHAR16 *String,\r
4043 IN CONST BOOLEAN ForceHex,\r
4044 IN CONST BOOLEAN StopAtSpace\r
4045 )\r
4046{\r
4047 if (ShellConvertStringToUint64(String, NULL, ForceHex, StopAtSpace) == EFI_NOT_FOUND) {\r
4048 return (TRUE);\r
4049 }\r
4050 return (FALSE);\r
4051}\r
4d0a4fce 4052\r
4053/**\r
4054 Function to read a single line from a SHELL_FILE_HANDLE. The \n is not included in the returned\r
4055 buffer. The returned buffer must be callee freed.\r
4056\r
4057 If the position upon start is 0, then the Ascii Boolean will be set. This should be\r
4058 maintained and not changed for all operations with the same file.\r
4059\r
4ff7e37b
ED
4060 @param[in] Handle SHELL_FILE_HANDLE to read from.\r
4061 @param[in, out] Ascii Boolean value for indicating whether the file is\r
4062 Ascii (TRUE) or UCS2 (FALSE).\r
4d0a4fce 4063\r
beab0fc5 4064 @return The line of text from the file.\r
4065 @retval NULL There was not enough memory available.\r
4d0a4fce 4066\r
4067 @sa ShellFileHandleReadLine\r
4068**/\r
4069CHAR16*\r
4070EFIAPI\r
4071ShellFileHandleReturnLine(\r
4072 IN SHELL_FILE_HANDLE Handle,\r
4073 IN OUT BOOLEAN *Ascii\r
4074 )\r
4075{\r
4076 CHAR16 *RetVal;\r
4077 UINTN Size;\r
4078 EFI_STATUS Status;\r
4079\r
4080 Size = 0;\r
4081 RetVal = NULL;\r
4082\r
4083 Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);\r
4084 if (Status == EFI_BUFFER_TOO_SMALL) {\r
4085 RetVal = AllocateZeroPool(Size);\r
beab0fc5 4086 if (RetVal == NULL) {\r
4087 return (NULL);\r
4088 }\r
4d0a4fce 4089 Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);\r
b0934ac4 4090\r
4d0a4fce 4091 }\r
e3b76f3b 4092 if (Status == EFI_END_OF_FILE && RetVal != NULL && *RetVal != CHAR_NULL) {\r
f79d7b62
QS
4093 Status = EFI_SUCCESS;\r
4094 }\r
4d0a4fce 4095 if (EFI_ERROR(Status) && (RetVal != NULL)) {\r
4096 FreePool(RetVal);\r
4097 RetVal = NULL;\r
4098 }\r
4099 return (RetVal);\r
4100}\r
4101\r
4102/**\r
4103 Function to read a single line (up to but not including the \n) from a SHELL_FILE_HANDLE.\r
4104\r
4105 If the position upon start is 0, then the Ascii Boolean will be set. This should be\r
4106 maintained and not changed for all operations with the same file.\r
4107\r
2dda8a12
JD
4108 NOTE: LINES THAT ARE RETURNED BY THIS FUNCTION ARE UCS2, EVEN IF THE FILE BEING READ\r
4109 IS IN ASCII FORMAT.\r
4110\r
4ff7e37b 4111 @param[in] Handle SHELL_FILE_HANDLE to read from.\r
2dda8a12
JD
4112 @param[in, out] Buffer The pointer to buffer to read into. If this function\r
4113 returns EFI_SUCCESS, then on output Buffer will\r
4114 contain a UCS2 string, even if the file being\r
4115 read is ASCII.\r
4116 @param[in, out] Size On input, pointer to number of bytes in Buffer.\r
4117 On output, unchanged unless Buffer is too small\r
4118 to contain the next line of the file. In that\r
4119 case Size is set to the number of bytes needed\r
4120 to hold the next line of the file (as a UCS2\r
4121 string, even if it is an ASCII file).\r
4ff7e37b
ED
4122 @param[in] Truncate If the buffer is large enough, this has no effect.\r
4123 If the buffer is is too small and Truncate is TRUE,\r
4124 the line will be truncated.\r
4125 If the buffer is is too small and Truncate is FALSE,\r
4126 then no read will occur.\r
4127\r
4128 @param[in, out] Ascii Boolean value for indicating whether the file is\r
4129 Ascii (TRUE) or UCS2 (FALSE).\r
4d0a4fce 4130\r
4131 @retval EFI_SUCCESS The operation was successful. The line is stored in\r
4132 Buffer.\r
9ed21946 4133 @retval EFI_END_OF_FILE There are no more lines in the file.\r
4d0a4fce 4134 @retval EFI_INVALID_PARAMETER Handle was NULL.\r
4135 @retval EFI_INVALID_PARAMETER Size was NULL.\r
4136 @retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line.\r
4137 Size was updated to the minimum space required.\r
4138**/\r
4139EFI_STATUS\r
4140EFIAPI\r
4141ShellFileHandleReadLine(\r
4142 IN SHELL_FILE_HANDLE Handle,\r
4143 IN OUT CHAR16 *Buffer,\r
4144 IN OUT UINTN *Size,\r
4145 IN BOOLEAN Truncate,\r
4146 IN OUT BOOLEAN *Ascii\r
4147 )\r
4148{\r
4149 EFI_STATUS Status;\r
4150 CHAR16 CharBuffer;\r
4151 UINTN CharSize;\r
4152 UINTN CountSoFar;\r
4153 UINT64 OriginalFilePosition;\r
4154\r
4155\r
4156 if (Handle == NULL\r
4157 ||Size == NULL\r
4158 ){\r
4159 return (EFI_INVALID_PARAMETER);\r
4160 }\r
4161 if (Buffer == NULL) {\r
4162 ASSERT(*Size == 0);\r
4163 } else {\r
4164 *Buffer = CHAR_NULL;\r
4165 }\r
4166 gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);\r
4167 if (OriginalFilePosition == 0) {\r
4168 CharSize = sizeof(CHAR16);\r
4169 Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
4170 ASSERT_EFI_ERROR(Status);\r
4171 if (CharBuffer == gUnicodeFileTag) {\r
4172 *Ascii = FALSE;\r
4173 } else {\r
4174 *Ascii = TRUE;\r
4175 gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
4176 }\r
4177 }\r
4178\r
9ed21946 4179 if (*Ascii) {\r
4180 CharSize = sizeof(CHAR8);\r
4181 } else {\r
4182 CharSize = sizeof(CHAR16);\r
4183 }\r
4d0a4fce 4184 for (CountSoFar = 0;;CountSoFar++){\r
4185 CharBuffer = 0;\r
4d0a4fce 4186 Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
4187 if ( EFI_ERROR(Status)\r
4188 || CharSize == 0\r
4189 || (CharBuffer == L'\n' && !(*Ascii))\r
4190 || (CharBuffer == '\n' && *Ascii)\r
4191 ){\r
9ed21946 4192 if (CharSize == 0) {\r
4193 Status = EFI_END_OF_FILE;\r
4194 }\r
4d0a4fce 4195 break;\r
4196 }\r
4197 //\r
4198 // if we have space save it...\r
4199 //\r
1095b432 4200 if ((CountSoFar+1)*sizeof(CHAR16) < *Size){\r
4d0a4fce 4201 ASSERT(Buffer != NULL);\r
1095b432
JD
4202 ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;\r
4203 ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;\r
4d0a4fce 4204 }\r
4205 }\r
4206\r
4207 //\r
4208 // if we ran out of space tell when...\r
4209 //\r
1095b432
JD
4210 if ((CountSoFar+1)*sizeof(CHAR16) > *Size){\r
4211 *Size = (CountSoFar+1)*sizeof(CHAR16);\r
4212 if (!Truncate) {\r
4213 gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
4214 } else {\r
4215 DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine"));\r
4d0a4fce 4216 }\r
1095b432
JD
4217 return (EFI_BUFFER_TOO_SMALL);\r
4218 }\r
4219 while(Buffer[StrLen(Buffer)-1] == L'\r') {\r
4220 Buffer[StrLen(Buffer)-1] = CHAR_NULL;\r
4d0a4fce 4221 }\r
4222\r
4223 return (Status);\r
4224}\r
fb5278ef 4225\r
365aa98a 4226/**\r
4227 Function to print help file / man page content in the spec from the UEFI Shell protocol GetHelpText function.\r
4228\r
4229 @param[in] CommandToGetHelpOn Pointer to a string containing the command name of help file to be printed.\r
4230 @param[in] SectionToGetHelpOn Pointer to the section specifier(s).\r
4231 @param[in] PrintCommandText If TRUE, prints the command followed by the help content, otherwise prints \r
4232 the help content only.\r
4233 @retval EFI_DEVICE_ERROR The help data format was incorrect.\r
4234 @retval EFI_NOT_FOUND The help data could not be found.\r
4235 @retval EFI_SUCCESS The operation was successful.\r
4236**/\r
4237EFI_STATUS\r
4238EFIAPI\r
4239ShellPrintHelp (\r
4240 IN CONST CHAR16 *CommandToGetHelpOn,\r
4241 IN CONST CHAR16 *SectionToGetHelpOn,\r
4242 IN BOOLEAN PrintCommandText\r
4243 )\r
4244{\r
4245 EFI_STATUS Status;\r
4246 CHAR16 *OutText;\r
4247 \r
4248 OutText = NULL;\r
4249 \r
4250 //\r
4251 // Get the string to print based\r
4252 //\r
4253 Status = gEfiShellProtocol->GetHelpText (CommandToGetHelpOn, SectionToGetHelpOn, &OutText);\r
4254 \r
4255 //\r
4256 // make sure we got a valid string\r
4257 //\r
4258 if (EFI_ERROR(Status)){\r
4259 return Status;\r
4260 } \r
4261 if (OutText == NULL || StrLen(OutText) == 0) {\r
4262 return EFI_NOT_FOUND; \r
4263 }\r
4264 \r
4265 //\r
4266 // Chop off trailing stuff we dont need\r
4267 //\r
4268 while (OutText[StrLen(OutText)-1] == L'\r' || OutText[StrLen(OutText)-1] == L'\n' || OutText[StrLen(OutText)-1] == L' ') {\r
4269 OutText[StrLen(OutText)-1] = CHAR_NULL;\r
4270 }\r
4271 \r
4272 //\r
4273 // Print this out to the console\r
4274 //\r
4275 if (PrintCommandText) {\r
4276 ShellPrintEx(-1, -1, L"%H%-14s%N- %s\r\n", CommandToGetHelpOn, OutText);\r
4277 } else {\r
4278 ShellPrintEx(-1, -1, L"%N%s\r\n", OutText);\r
4279 }\r
4280 \r
4281 SHELL_FREE_NON_NULL(OutText);\r
4282\r
4283 return EFI_SUCCESS;\r
4284}\r
4285\r
fb5278ef 4286/**\r
4287 Function to delete a file by name\r
4288 \r
4289 @param[in] FileName Pointer to file name to delete.\r
4290 \r
4291 @retval EFI_SUCCESS the file was deleted sucessfully\r
4292 @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not\r
4293 deleted\r
4294 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
4295 @retval EFI_NOT_FOUND The specified file could not be found on the\r
4296 device or the file system could not be found\r
4297 on the device.\r
4298 @retval EFI_NO_MEDIA The device has no medium.\r
4299 @retval EFI_MEDIA_CHANGED The device has a different medium in it or the\r
4300 medium is no longer supported.\r
4301 @retval EFI_DEVICE_ERROR The device reported an error.\r
4302 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
4303 @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
4304 @retval EFI_ACCESS_DENIED The file was opened read only.\r
4305 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
4306 file.\r
4307 @retval other The file failed to open\r
4308**/\r
4309EFI_STATUS\r
4310EFIAPI\r
4311ShellDeleteFileByName(\r
4312 IN CONST CHAR16 *FileName\r
4313 )\r
4314{\r
4315 EFI_STATUS Status;\r
4316 SHELL_FILE_HANDLE FileHandle;\r
4317 \r
4318 Status = ShellFileExists(FileName);\r
4319 \r
4320 if (Status == EFI_SUCCESS){\r
4321 Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0x0);\r
4322 if (Status == EFI_SUCCESS){\r
4323 Status = ShellDeleteFile(&FileHandle);\r
4324 }\r
4325 } \r
4326\r
4327 return(Status);\r
4328 \r
4329}\r
0960ba17
QS
4330\r
4331/**\r
4332 Cleans off all the quotes in the string.\r
4333\r
4334 @param[in] OriginalString pointer to the string to be cleaned.\r
4335 @param[out] CleanString The new string with all quotes removed. \r
4336 Memory allocated in the function and free \r
4337 by caller.\r
4338\r
4339 @retval EFI_SUCCESS The operation was successful.\r
4340**/\r
4341EFI_STATUS\r
0960ba17
QS
4342InternalShellStripQuotes (\r
4343 IN CONST CHAR16 *OriginalString,\r
4344 OUT CHAR16 **CleanString\r
4345 )\r
4346{\r
4347 CHAR16 *Walker;\r
4348 \r
4349 if (OriginalString == NULL || CleanString == NULL) {\r
4350 return EFI_INVALID_PARAMETER;\r
4351 }\r
4352\r
4353 *CleanString = AllocateCopyPool (StrSize (OriginalString), OriginalString);\r
4354 if (*CleanString == NULL) {\r
4355 return EFI_OUT_OF_RESOURCES;\r
4356 }\r
4357\r
4358 for (Walker = *CleanString; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {\r
4359 if (*Walker == L'\"') {\r
4360 CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));\r
4361 }\r
4362 }\r
4363\r
4364 return EFI_SUCCESS;\r
4365}\r
4366\r