]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Application/Shell/ShellParametersProtocol.c
ShellPkg: Document UpdateArgcArgv returns EFI_INVALID_PARAMETER
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellParametersProtocol.c
CommitLineData
a405b86d 1/** @file\r
2 Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation,\r
3 manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL.\r
4\r
583448b4 5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
94c2a044 6 Copyright (C) 2014, Red Hat, Inc.\r
c011b6c9 7 (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>\r
ba0014b9 8 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
56ba3746 9 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a405b86d 10\r
11**/\r
12\r
0406a571 13#include "Shell.h"\r
a405b86d 14\r
48cb33ec
QS
15BOOLEAN AsciiRedirection = FALSE;\r
16\r
1219c85d
RN
17/**\r
18 Return the next parameter's end from a command line string.\r
19\r
20 @param[in] String the string to parse\r
21**/\r
22CONST CHAR16*\r
1219c85d
RN
23FindEndOfParameter(\r
24 IN CONST CHAR16 *String\r
25 )\r
26{\r
27 CONST CHAR16 *First;\r
28 CONST CHAR16 *CloseQuote;\r
29\r
30 First = FindFirstCharacter(String, L" \"", L'^');\r
31\r
32 //\r
33 // nothing, all one parameter remaining\r
34 //\r
35 if (*First == CHAR_NULL) {\r
36 return (First);\r
37 }\r
38\r
39 //\r
40 // If space before a quote (or neither found, i.e. both CHAR_NULL),\r
41 // then that's the end.\r
42 //\r
43 if (*First == L' ') {\r
44 return (First);\r
45 }\r
46\r
47 CloseQuote = FindFirstCharacter (First+1, L"\"", L'^');\r
48\r
49 //\r
50 // We did not find a terminator...\r
51 //\r
52 if (*CloseQuote == CHAR_NULL) {\r
53 return (NULL);\r
54 }\r
55\r
56 return (FindEndOfParameter (CloseQuote+1));\r
57}\r
58\r
59/**\r
60 Return the next parameter from a command line string.\r
61\r
62 This function moves the next parameter from Walker into TempParameter and moves\r
63 Walker up past that parameter for recursive calling. When the final parameter\r
64 is moved *Walker will be set to NULL;\r
65\r
66 Temp Parameter must be large enough to hold the parameter before calling this\r
67 function.\r
68\r
69 This will also remove all remaining ^ characters after processing.\r
70\r
71 @param[in, out] Walker pointer to string of command line. Adjusted to\r
6a5033ca 72 remaining command line on return\r
1219c85d
RN
73 @param[in, out] TempParameter pointer to string of command line item extracted.\r
74 @param[in] Length buffer size of TempParameter.\r
75 @param[in] StripQuotation if TRUE then strip the quotation marks surrounding\r
76 the parameters.\r
77\r
6a5033ca 78 @return EFI_INVALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string.\r
1219c85d
RN
79 @return EFI_NOT_FOUND A closing " could not be found on the specified string\r
80**/\r
81EFI_STATUS\r
1219c85d
RN
82GetNextParameter(\r
83 IN OUT CHAR16 **Walker,\r
84 IN OUT CHAR16 **TempParameter,\r
85 IN CONST UINTN Length,\r
86 IN BOOLEAN StripQuotation\r
87 )\r
88{\r
89 CONST CHAR16 *NextDelim;\r
90\r
91 if (Walker == NULL\r
92 ||*Walker == NULL\r
93 ||TempParameter == NULL\r
94 ||*TempParameter == NULL\r
95 ){\r
96 return (EFI_INVALID_PARAMETER);\r
97 }\r
98\r
99\r
100 //\r
101 // make sure we dont have any leading spaces\r
102 //\r
103 while ((*Walker)[0] == L' ') {\r
104 (*Walker)++;\r
105 }\r
106\r
107 //\r
108 // make sure we still have some params now...\r
109 //\r
110 if (StrLen(*Walker) == 0) {\r
111DEBUG_CODE_BEGIN();\r
112 *Walker = NULL;\r
113DEBUG_CODE_END();\r
114 return (EFI_INVALID_PARAMETER);\r
115 }\r
116\r
117 NextDelim = FindEndOfParameter(*Walker);\r
118\r
119 if (NextDelim == NULL){\r
120DEBUG_CODE_BEGIN();\r
121 *Walker = NULL;\r
122DEBUG_CODE_END();\r
123 return (EFI_NOT_FOUND);\r
124 }\r
125\r
126 StrnCpyS(*TempParameter, Length / sizeof(CHAR16), (*Walker), NextDelim - *Walker);\r
127\r
128 //\r
6a5033ca 129 // Add a CHAR_NULL if we didn't get one via the copy\r
1219c85d
RN
130 //\r
131 if (*NextDelim != CHAR_NULL) {\r
132 (*TempParameter)[NextDelim - *Walker] = CHAR_NULL;\r
133 }\r
134\r
135 //\r
136 // Update Walker for the next iteration through the function\r
137 //\r
138 *Walker = (CHAR16*)NextDelim;\r
139\r
140 //\r
141 // Remove any non-escaped quotes in the string\r
142 // Remove any remaining escape characters in the string\r
143 //\r
ba0014b9
LG
144 for (NextDelim = FindFirstCharacter(*TempParameter, L"\"^", CHAR_NULL)\r
145 ; *NextDelim != CHAR_NULL\r
1219c85d
RN
146 ; NextDelim = FindFirstCharacter(NextDelim, L"\"^", CHAR_NULL)\r
147 ) {\r
148 if (*NextDelim == L'^') {\r
149\r
150 //\r
151 // eliminate the escape ^\r
152 //\r
153 CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1));\r
154 NextDelim++;\r
155 } else if (*NextDelim == L'\"') {\r
156\r
157 //\r
158 // eliminate the unescaped quote\r
159 //\r
160 if (StripQuotation) {\r
161 CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1));\r
ba0014b9 162 } else{\r
1219c85d 163 NextDelim++;\r
ba0014b9 164 }\r
1219c85d
RN
165 }\r
166 }\r
167\r
168 return EFI_SUCCESS;\r
169}\r
170\r
a405b86d 171/**\r
733f138d 172 Function to populate Argc and Argv.\r
a405b86d 173\r
174 This function parses the CommandLine and divides it into standard C style Argc/Argv\r
175 parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space\r
176 delimited and quote surrounded parameter definition.\r
177\r
ba0014b9 178 All special character processing (alias, environment variable, redirection,\r
14030c5c
JC
179 etc... must be complete before calling this API.\r
180\r
d1c275c6
QS
181 @param[in] CommandLine String of command line to parse\r
182 @param[in] StripQuotation if TRUE then strip the quotation marks surrounding\r
183 the parameters.\r
184 @param[in, out] Argv pointer to array of strings; one for each parameter\r
185 @param[in, out] Argc pointer to number of strings in Argv array\r
a405b86d 186\r
6a5033ca 187 @return EFI_SUCCESS the operation was successful\r
ddb7050c 188 @return EFI_INVALID_PARAMETER some parameters are invalid\r
a405b86d 189 @return EFI_OUT_OF_RESOURCES a memory allocation failed.\r
190**/\r
191EFI_STATUS\r
a405b86d 192ParseCommandLineToArgs(\r
193 IN CONST CHAR16 *CommandLine,\r
d1c275c6
QS
194 IN BOOLEAN StripQuotation,\r
195 IN OUT CHAR16 ***Argv,\r
196 IN OUT UINTN *Argc\r
a405b86d 197 )\r
198{\r
199 UINTN Count;\r
200 CHAR16 *TempParameter;\r
201 CHAR16 *Walker;\r
202 CHAR16 *NewParam;\r
1fab9176 203 CHAR16 *NewCommandLine;\r
a405b86d 204 UINTN Size;\r
1fab9176 205 EFI_STATUS Status;\r
a405b86d 206\r
207 ASSERT(Argc != NULL);\r
208 ASSERT(Argv != NULL);\r
209\r
210 if (CommandLine == NULL || StrLen(CommandLine)==0) {\r
211 (*Argc) = 0;\r
212 (*Argv) = NULL;\r
213 return (EFI_SUCCESS);\r
214 }\r
215\r
1fab9176
QS
216 NewCommandLine = AllocateCopyPool(StrSize(CommandLine), CommandLine);\r
217 if (NewCommandLine == NULL){\r
218 return (EFI_OUT_OF_RESOURCES);\r
219 }\r
220\r
221 TrimSpaces(&NewCommandLine);\r
222 Size = StrSize(NewCommandLine);\r
a405b86d 223 TempParameter = AllocateZeroPool(Size);\r
224 if (TempParameter == NULL) {\r
1fab9176 225 SHELL_FREE_NON_NULL(NewCommandLine);\r
a405b86d 226 return (EFI_OUT_OF_RESOURCES);\r
227 }\r
228\r
229 for ( Count = 0\r
1fab9176 230 , Walker = (CHAR16*)NewCommandLine\r
a405b86d 231 ; Walker != NULL && *Walker != CHAR_NULL\r
14030c5c
JC
232 ; Count++\r
233 ) {\r
1219c85d 234 if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size, TRUE))) {\r
14030c5c
JC
235 break;\r
236 }\r
237 }\r
a405b86d 238\r
a405b86d 239 //\r
240 // lets allocate the pointer array\r
241 //\r
242 (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*));\r
243 if (*Argv == NULL) {\r
1fab9176
QS
244 Status = EFI_OUT_OF_RESOURCES;\r
245 goto Done;\r
a405b86d 246 }\r
247\r
248 *Argc = 0;\r
1fab9176 249 Walker = (CHAR16*)NewCommandLine;\r
a405b86d 250 while(Walker != NULL && *Walker != CHAR_NULL) {\r
251 SetMem16(TempParameter, Size, CHAR_NULL);\r
1219c85d 252 if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size, StripQuotation))) {\r
1fab9176
QS
253 Status = EFI_INVALID_PARAMETER;\r
254 goto Done;\r
14030c5c
JC
255 }\r
256\r
7f79b01e
JC
257 NewParam = AllocateCopyPool(StrSize(TempParameter), TempParameter);\r
258 if (NewParam == NULL){\r
1fab9176
QS
259 Status = EFI_OUT_OF_RESOURCES;\r
260 goto Done;\r
7f79b01e 261 }\r
a405b86d 262 ((CHAR16**)(*Argv))[(*Argc)] = NewParam;\r
263 (*Argc)++;\r
264 }\r
265 ASSERT(Count >= (*Argc));\r
1fab9176 266 Status = EFI_SUCCESS;\r
ba0014b9 267\r
1fab9176 268Done:\r
3f869579 269 SHELL_FREE_NON_NULL(TempParameter);\r
1fab9176
QS
270 SHELL_FREE_NON_NULL(NewCommandLine);\r
271 return (Status);\r
a405b86d 272}\r
273\r
274/**\r
275 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then\r
276 installs it on our handle and if there is an existing version of the protocol\r
277 that one is cached for removal later.\r
278\r
4ff7e37b 279 @param[in, out] NewShellParameters on a successful return, a pointer to pointer\r
a405b86d 280 to the newly installed interface.\r
4ff7e37b 281 @param[in, out] RootShellInstance on a successful return, pointer to boolean.\r
a405b86d 282 TRUE if this is the root shell instance.\r
283\r
284 @retval EFI_SUCCESS the operation completed successfully.\r
285 @return other the operation failed.\r
286 @sa ReinstallProtocolInterface\r
287 @sa InstallProtocolInterface\r
288 @sa ParseCommandLineToArgs\r
289**/\r
290EFI_STATUS\r
a405b86d 291CreatePopulateInstallShellParametersProtocol (\r
292 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters,\r
293 IN OUT BOOLEAN *RootShellInstance\r
294 )\r
295{\r
296 EFI_STATUS Status;\r
297 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
298 CHAR16 *FullCommandLine;\r
299 UINTN Size;\r
300\r
301 Size = 0;\r
302 FullCommandLine = NULL;\r
303 LoadedImage = NULL;\r
304\r
305 //\r
306 // Assert for valid parameters\r
307 //\r
308 ASSERT(NewShellParameters != NULL);\r
309 ASSERT(RootShellInstance != NULL);\r
310\r
311 //\r
312 // See if we have a shell parameters placed on us\r
313 //\r
314 Status = gBS->OpenProtocol (\r
315 gImageHandle,\r
316 &gEfiShellParametersProtocolGuid,\r
317 (VOID **) &ShellInfoObject.OldShellParameters,\r
318 gImageHandle,\r
319 NULL,\r
320 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
321 );\r
322 //\r
323 // if we don't then we must be the root shell (error is expected)\r
324 //\r
325 if (EFI_ERROR (Status)) {\r
326 *RootShellInstance = TRUE;\r
327 }\r
328\r
329 //\r
330 // Allocate the new structure\r
331 //\r
332 *NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));\r
3c865f20 333 if ((*NewShellParameters) == NULL) {\r
334 return (EFI_OUT_OF_RESOURCES);\r
335 }\r
a405b86d 336\r
337 //\r
338 // get loaded image protocol\r
339 //\r
340 Status = gBS->OpenProtocol (\r
341 gImageHandle,\r
342 &gEfiLoadedImageProtocolGuid,\r
343 (VOID **) &LoadedImage,\r
344 gImageHandle,\r
345 NULL,\r
346 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
347 );\r
348 ASSERT_EFI_ERROR(Status);\r
349 //\r
350 // Build the full command line\r
351 //\r
e886b675 352 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);\r
a405b86d 353 if (Status == EFI_BUFFER_TOO_SMALL) {\r
354 FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);\r
e886b675 355 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);\r
a405b86d 356 }\r
357 if (Status == EFI_NOT_FOUND) {\r
358 //\r
359 // no parameters via environment... ok\r
360 //\r
361 } else {\r
3c865f20 362 if (EFI_ERROR(Status)) {\r
363 return (Status);\r
364 }\r
a405b86d 365 }\r
366 if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {\r
3c865f20 367 ASSERT(FullCommandLine == NULL);\r
a405b86d 368 //\r
369 // Now we need to include a NULL terminator in the size.\r
370 //\r
371 Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]);\r
372 FullCommandLine = AllocateZeroPool(Size);\r
373 }\r
a405b86d 374 if (FullCommandLine != NULL) {\r
2c5a8aed 375 CopyMem (FullCommandLine, LoadedImage->LoadOptions, LoadedImage->LoadOptionsSize);\r
a405b86d 376 //\r
377 // Populate Argc and Argv\r
378 //\r
379 Status = ParseCommandLineToArgs(FullCommandLine,\r
d1c275c6 380 TRUE,\r
a405b86d 381 &(*NewShellParameters)->Argv,\r
382 &(*NewShellParameters)->Argc);\r
383\r
384 FreePool(FullCommandLine);\r
385\r
386 ASSERT_EFI_ERROR(Status);\r
387 } else {\r
388 (*NewShellParameters)->Argv = NULL;\r
389 (*NewShellParameters)->Argc = 0;\r
390 }\r
391\r
392 //\r
393 // Populate the 3 faked file systems...\r
394 //\r
395 if (*RootShellInstance) {\r
396 (*NewShellParameters)->StdIn = &FileInterfaceStdIn;\r
397 (*NewShellParameters)->StdOut = &FileInterfaceStdOut;\r
398 (*NewShellParameters)->StdErr = &FileInterfaceStdErr;\r
399 Status = gBS->InstallProtocolInterface(&gImageHandle,\r
400 &gEfiShellParametersProtocolGuid,\r
401 EFI_NATIVE_INTERFACE,\r
402 (VOID*)(*NewShellParameters));\r
403 } else {\r
404 //\r
405 // copy from the existing ones\r
406 //\r
407 (*NewShellParameters)->StdIn = ShellInfoObject.OldShellParameters->StdIn;\r
408 (*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut;\r
409 (*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr;\r
410 Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
411 &gEfiShellParametersProtocolGuid,\r
412 (VOID*)ShellInfoObject.OldShellParameters,\r
413 (VOID*)(*NewShellParameters));\r
414 }\r
415\r
416 return (Status);\r
417}\r
418\r
419/**\r
6a5033ca 420 frees all memory used by creation and installation of shell parameters protocol\r
a405b86d 421 and if there was an old version installed it will restore that one.\r
422\r
423 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is\r
424 being cleaned up.\r
425\r
426 @retval EFI_SUCCESS the cleanup was successful\r
427 @return other the cleanup failed\r
428 @sa ReinstallProtocolInterface\r
429 @sa UninstallProtocolInterface\r
430**/\r
431EFI_STATUS\r
a405b86d 432CleanUpShellParametersProtocol (\r
433 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters\r
434 )\r
435{\r
436 EFI_STATUS Status;\r
437 UINTN LoopCounter;\r
438\r
439 //\r
440 // If the old exists we need to restore it\r
441 //\r
442 if (ShellInfoObject.OldShellParameters != NULL) {\r
443 Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
444 &gEfiShellParametersProtocolGuid,\r
445 (VOID*)NewShellParameters,\r
446 (VOID*)ShellInfoObject.OldShellParameters);\r
447 DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;);\r
448 } else {\r
449 //\r
450 // No old one, just uninstall us...\r
451 //\r
452 Status = gBS->UninstallProtocolInterface(gImageHandle,\r
453 &gEfiShellParametersProtocolGuid,\r
454 (VOID*)NewShellParameters);\r
455 }\r
456 if (NewShellParameters->Argv != NULL) {\r
457 for ( LoopCounter = 0\r
458 ; LoopCounter < NewShellParameters->Argc\r
459 ; LoopCounter++\r
460 ){\r
461 FreePool(NewShellParameters->Argv[LoopCounter]);\r
462 }\r
463 FreePool(NewShellParameters->Argv);\r
464 }\r
465 FreePool(NewShellParameters);\r
466 return (Status);\r
467}\r
468\r
ae724571 469/**\r
6a5033ca 470 Determine if a file name represents a unicode file.\r
ae724571 471\r
472 @param[in] FileName Pointer to the filename to open.\r
473\r
474 @retval EFI_SUCCESS The file is a unicode file.\r
475 @return An error upon failure.\r
476**/\r
733f138d 477EFI_STATUS\r
733f138d 478IsUnicodeFile(\r
479 IN CONST CHAR16 *FileName\r
480 )\r
481{\r
482 SHELL_FILE_HANDLE Handle;\r
483 EFI_STATUS Status;\r
484 UINT64 OriginalFilePosition;\r
485 UINTN CharSize;\r
486 CHAR16 CharBuffer;\r
487\r
488 Status = gEfiShellProtocol->OpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ);\r
489 if (EFI_ERROR(Status)) {\r
490 return (Status);\r
491 }\r
492 gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);\r
493 gEfiShellProtocol->SetFilePosition(Handle, 0);\r
494 CharSize = sizeof(CHAR16);\r
495 Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
496 if (EFI_ERROR(Status) || CharBuffer != gUnicodeFileTag) {\r
497 Status = EFI_BUFFER_TOO_SMALL;\r
498 }\r
499 gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
500 gEfiShellProtocol->CloseFile(Handle);\r
ba0014b9 501 return (Status);\r
733f138d 502}\r
503\r
fb84495a 504/**\r
505 Strips out quotes sections of a string.\r
506\r
507 All of the characters between quotes is replaced with spaces.\r
a1d4bfcc 508\r
4ff7e37b 509 @param[in, out] TheString A pointer to the string to update.\r
fb84495a 510**/\r
511VOID\r
fb84495a 512StripQuotes (\r
513 IN OUT CHAR16 *TheString\r
514 )\r
515{\r
516 BOOLEAN RemoveNow;\r
517\r
518 for (RemoveNow = FALSE ; TheString != NULL && *TheString != CHAR_NULL ; TheString++) {\r
519 if (*TheString == L'^' && *(TheString + 1) == L'\"') {\r
520 TheString++;\r
521 } else if (*TheString == L'\"') {\r
522 RemoveNow = (BOOLEAN)!RemoveNow;\r
523 } else if (RemoveNow) {\r
524 *TheString = L' ';\r
525 }\r
526 }\r
527}\r
528\r
cf6a8f14 529/**\r
6a5033ca 530 Calculate the 32-bit CRC in a EFI table using the service provided by the\r
cf6a8f14 531 gRuntime service.\r
532\r
533 @param Hdr Pointer to an EFI standard header\r
534\r
535**/\r
536VOID\r
537CalculateEfiHdrCrc (\r
538 IN OUT EFI_TABLE_HEADER *Hdr\r
539 )\r
540{\r
541 UINT32 Crc;\r
542\r
543 Hdr->CRC32 = 0;\r
544\r
545 //\r
546 // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then\r
547 // Crc will come back as zero if we set it to zero here\r
548 //\r
549 Crc = 0;\r
550 gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc);\r
551 Hdr->CRC32 = Crc;\r
552}\r
553\r
031acf63 554/**\r
555 Fix a string to only have the file name, removing starting at the first space of whatever is quoted.\r
556\r
557 @param[in] FileName The filename to start with.\r
558\r
559 @retval NULL FileName was invalid.\r
560 @return The modified FileName.\r
561**/\r
562CHAR16*\r
031acf63 563FixFileName (\r
564 IN CHAR16 *FileName\r
565 )\r
566{\r
567 CHAR16 *Copy;\r
568 CHAR16 *TempLocation;\r
569\r
570 if (FileName == NULL) {\r
571 return (NULL);\r
572 }\r
573\r
574 if (FileName[0] == L'\"') {\r
575 Copy = FileName+1;\r
576 if ((TempLocation = StrStr(Copy , L"\"")) != NULL) {\r
577 TempLocation[0] = CHAR_NULL;\r
ba0014b9 578 }\r
031acf63 579 } else {\r
580 Copy = FileName;\r
f9aefb6a 581 while(Copy[0] == L' ') {\r
582 Copy++;\r
583 }\r
031acf63 584 if ((TempLocation = StrStr(Copy , L" ")) != NULL) {\r
585 TempLocation[0] = CHAR_NULL;\r
ba0014b9 586 }\r
031acf63 587 }\r
588\r
589 if (Copy[0] == CHAR_NULL) {\r
590 return (NULL);\r
591 }\r
592\r
593 return (Copy);\r
594}\r
595\r
6813ba40
JC
596/**\r
597 Fix a string to only have the environment variable name, removing starting at the first space of whatever is quoted and removing the leading and trailing %.\r
598\r
599 @param[in] FileName The filename to start with.\r
600\r
601 @retval NULL FileName was invalid.\r
602 @return The modified FileName.\r
603**/\r
604CHAR16*\r
6813ba40
JC
605FixVarName (\r
606 IN CHAR16 *FileName\r
607 )\r
608{\r
609 CHAR16 *Copy;\r
610 CHAR16 *TempLocation;\r
611\r
612 Copy = FileName;\r
613\r
614 if (FileName[0] == L'%') {\r
615 Copy = FileName+1;\r
616 if ((TempLocation = StrStr(Copy , L"%")) != NULL) {\r
617 TempLocation[0] = CHAR_NULL;\r
ba0014b9 618 }\r
6813ba40
JC
619 }\r
620\r
621 return (FixFileName(Copy));\r
622}\r
623\r
49bb76ff 624\r
94c2a044
LE
625/**\r
626 Write the unicode file tag to the specified file.\r
627\r
628 It is the caller's responsibility to ensure that\r
629 ShellInfoObject.NewEfiShellProtocol has been initialized before calling this\r
630 function.\r
631\r
632 @param[in] FileHandle The file to write the unicode file tag to.\r
633\r
634 @return Status code from ShellInfoObject.NewEfiShellProtocol->WriteFile.\r
635**/\r
94c2a044
LE
636EFI_STATUS\r
637WriteFileTag (\r
638 IN SHELL_FILE_HANDLE FileHandle\r
639 )\r
640{\r
641 CHAR16 FileTag;\r
642 UINTN Size;\r
643 EFI_STATUS Status;\r
644\r
645 FileTag = gUnicodeFileTag;\r
646 Size = sizeof FileTag;\r
647 Status = ShellInfoObject.NewEfiShellProtocol->WriteFile (FileHandle, &Size,\r
648 &FileTag);\r
649 ASSERT (EFI_ERROR (Status) || Size == sizeof FileTag);\r
650 return Status;\r
651}\r
652\r
653\r
a405b86d 654/**\r
6a5033ca 655 Function will replace the current StdIn and StdOut in the ShellParameters protocol\r
a405b86d 656 structure by parsing NewCommandLine. The current values are returned to the\r
657 user.\r
658\r
8be0ba36 659 This will also update the system table.\r
a405b86d 660\r
4ff7e37b
ED
661 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
662 @param[in] NewCommandLine The new command line to parse and use.\r
663 @param[out] OldStdIn Pointer to old StdIn.\r
664 @param[out] OldStdOut Pointer to old StdOut.\r
665 @param[out] OldStdErr Pointer to old StdErr.\r
666 @param[out] SystemTableInfo Pointer to old system table information.\r
a405b86d 667\r
6a5033ca 668 @retval EFI_SUCCESS Operation was successful, Argv and Argc are valid.\r
a405b86d 669 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
670**/\r
671EFI_STATUS\r
a405b86d 672UpdateStdInStdOutStdErr(\r
673 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
fb84495a 674 IN CHAR16 *NewCommandLine,\r
a405b86d 675 OUT SHELL_FILE_HANDLE *OldStdIn,\r
676 OUT SHELL_FILE_HANDLE *OldStdOut,\r
8be0ba36 677 OUT SHELL_FILE_HANDLE *OldStdErr,\r
678 OUT SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 679 )\r
680{\r
681 CHAR16 *CommandLineCopy;\r
682 CHAR16 *CommandLineWalker;\r
683 CHAR16 *StdErrFileName;\r
684 CHAR16 *StdOutFileName;\r
685 CHAR16 *StdInFileName;\r
686 CHAR16 *StdInVarName;\r
687 CHAR16 *StdOutVarName;\r
688 CHAR16 *StdErrVarName;\r
689 EFI_STATUS Status;\r
690 SHELL_FILE_HANDLE TempHandle;\r
691 UINT64 FileSize;\r
692 BOOLEAN OutUnicode;\r
693 BOOLEAN InUnicode;\r
694 BOOLEAN ErrUnicode;\r
695 BOOLEAN OutAppend;\r
696 BOOLEAN ErrAppend;\r
697 UINTN Size;\r
a405b86d 698 SPLIT_LIST *Split;\r
fb84495a 699 CHAR16 *FirstLocation;\r
31e5b912 700 BOOLEAN Volatile;\r
a405b86d 701\r
a405b86d 702 OutUnicode = TRUE;\r
703 InUnicode = TRUE;\r
48cb33ec 704 AsciiRedirection = FALSE;\r
a405b86d 705 ErrUnicode = TRUE;\r
706 StdInVarName = NULL;\r
707 StdOutVarName = NULL;\r
708 StdErrVarName = NULL;\r
709 StdErrFileName = NULL;\r
710 StdInFileName = NULL;\r
711 StdOutFileName = NULL;\r
712 ErrAppend = FALSE;\r
713 OutAppend = FALSE;\r
714 CommandLineCopy = NULL;\r
5f2915f5 715 FirstLocation = NULL;\r
a405b86d 716\r
8be0ba36 717 if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {\r
718 return (EFI_INVALID_PARAMETER);\r
a405b86d 719 }\r
720\r
8be0ba36 721 SystemTableInfo->ConIn = gST->ConIn;\r
722 SystemTableInfo->ConInHandle = gST->ConsoleInHandle;\r
723 SystemTableInfo->ConOut = gST->ConOut;\r
724 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;\r
4ccd9214
ED
725 SystemTableInfo->ErrOut = gST->StdErr;\r
726 SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle;\r
8be0ba36 727 *OldStdIn = ShellParameters->StdIn;\r
728 *OldStdOut = ShellParameters->StdOut;\r
729 *OldStdErr = ShellParameters->StdErr;\r
730\r
a405b86d 731 if (NewCommandLine == NULL) {\r
732 return (EFI_SUCCESS);\r
733 }\r
734\r
735 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
532691c8 736 if (CommandLineCopy == NULL) {\r
737 return (EFI_OUT_OF_RESOURCES);\r
738 }\r
a405b86d 739 Status = EFI_SUCCESS;\r
740 Split = NULL;\r
5f2915f5 741 FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);\r
a405b86d 742\r
fb84495a 743 StripQuotes(CommandLineCopy);\r
744\r
a405b86d 745 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
746 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
747 if (Split != NULL && Split->SplitStdIn != NULL) {\r
748 ShellParameters->StdIn = Split->SplitStdIn;\r
749 }\r
750 if (Split != NULL && Split->SplitStdOut != NULL) {\r
751 ShellParameters->StdOut = Split->SplitStdOut;\r
752 }\r
753 }\r
754\r
755 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {\r
fb84495a 756 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 757 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 758 StdErrVarName = CommandLineWalker += 6;\r
759 ErrAppend = TRUE;\r
733f138d 760 if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {\r
761 Status = EFI_NOT_FOUND;\r
762 }\r
a405b86d 763 }\r
764 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
fb84495a 765 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 766 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 767 StdOutVarName = CommandLineWalker += 6;\r
768 OutAppend = TRUE;\r
733f138d 769 if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {\r
770 Status = EFI_NOT_FOUND;\r
771 }\r
a405b86d 772 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
fb84495a 773 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 774 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 775 StdOutVarName = CommandLineWalker += 5;\r
776 OutAppend = TRUE;\r
733f138d 777 if (StrStr(CommandLineWalker, L" >>v ") != NULL) {\r
778 Status = EFI_NOT_FOUND;\r
779 }\r
a405b86d 780 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
fb84495a 781 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 782 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 783 StdOutVarName = CommandLineWalker += 4;\r
784 OutAppend = FALSE;\r
733f138d 785 if (StrStr(CommandLineWalker, L" >v ") != NULL) {\r
786 Status = EFI_NOT_FOUND;\r
787 }\r
a405b86d 788 }\r
789 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
fb84495a 790 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 791 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 792 StdOutFileName = CommandLineWalker += 6;\r
793 OutAppend = TRUE;\r
794 OutUnicode = FALSE;\r
733f138d 795 if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {\r
796 Status = EFI_NOT_FOUND;\r
797 }\r
a405b86d 798 }\r
799 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
fb84495a 800 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 801 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 802 if (StdOutFileName != NULL) {\r
803 Status = EFI_INVALID_PARAMETER;\r
804 } else {\r
805 StdOutFileName = CommandLineWalker += 5;\r
806 OutAppend = TRUE;\r
807 }\r
733f138d 808 if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
809 Status = EFI_NOT_FOUND;\r
810 }\r
ba0014b9 811 }\r
a405b86d 812 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
fb84495a 813 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 814 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 815 if (StdOutFileName != NULL) {\r
816 Status = EFI_INVALID_PARAMETER;\r
817 } else {\r
818 StdOutFileName = CommandLineWalker += 4;\r
819 OutAppend = TRUE;\r
820 }\r
733f138d 821 if (StrStr(CommandLineWalker, L" >> ") != NULL) {\r
822 Status = EFI_NOT_FOUND;\r
823 }\r
a405b86d 824 }\r
825 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {\r
fb84495a 826 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 827 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 828 if (StdOutFileName != NULL) {\r
829 Status = EFI_INVALID_PARAMETER;\r
830 } else {\r
831 StdOutFileName = CommandLineWalker += 5;\r
832 OutAppend = TRUE;\r
833 OutUnicode = FALSE;\r
834 }\r
733f138d 835 if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
836 Status = EFI_NOT_FOUND;\r
837 }\r
ba0014b9 838 }\r
a405b86d 839 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
fb84495a 840 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 841 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 842 if (StdOutFileName != NULL) {\r
843 Status = EFI_INVALID_PARAMETER;\r
844 } else {\r
845 StdOutFileName = CommandLineWalker += 5;\r
846 OutAppend = FALSE;\r
847 OutUnicode = FALSE;\r
848 }\r
733f138d 849 if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
850 Status = EFI_NOT_FOUND;\r
851 }\r
ba0014b9 852 }\r
a405b86d 853 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
fb84495a 854 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 855 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 856 if (StdOutFileName != NULL) {\r
857 Status = EFI_INVALID_PARAMETER;\r
858 } else {\r
859 StdOutFileName = CommandLineWalker += 4;\r
860 OutAppend = FALSE;\r
861 OutUnicode = FALSE;\r
862 }\r
733f138d 863 if (StrStr(CommandLineWalker, L" >a ") != NULL) {\r
864 Status = EFI_NOT_FOUND;\r
865 }\r
a405b86d 866 }\r
867 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
fb84495a 868 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 869 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 870 if (StdErrFileName != NULL) {\r
871 Status = EFI_INVALID_PARAMETER;\r
872 } else {\r
873 StdErrFileName = CommandLineWalker += 5;\r
874 ErrAppend = TRUE;\r
875 }\r
733f138d 876 if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {\r
877 Status = EFI_NOT_FOUND;\r
878 }\r
a405b86d 879 }\r
880\r
881 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
fb84495a 882 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 883 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 884 if (StdErrVarName != NULL) {\r
885 Status = EFI_INVALID_PARAMETER;\r
886 } else {\r
887 StdErrVarName = CommandLineWalker += 5;\r
888 ErrAppend = FALSE;\r
889 }\r
733f138d 890 if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {\r
891 Status = EFI_NOT_FOUND;\r
892 }\r
a405b86d 893 }\r
894 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
fb84495a 895 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 896 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 897 if (StdOutVarName != NULL) {\r
898 Status = EFI_INVALID_PARAMETER;\r
899 } else {\r
900 StdOutVarName = CommandLineWalker += 5;\r
901 OutAppend = FALSE;\r
902 }\r
733f138d 903 if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {\r
904 Status = EFI_NOT_FOUND;\r
905 }\r
a405b86d 906 }\r
907 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
fb84495a 908 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 909 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 910 if (StdErrFileName != NULL) {\r
911 Status = EFI_INVALID_PARAMETER;\r
912 } else {\r
913 StdErrFileName = CommandLineWalker += 5;\r
914 ErrAppend = FALSE;\r
915 ErrUnicode = FALSE;\r
916 }\r
733f138d 917 if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {\r
918 Status = EFI_NOT_FOUND;\r
919 }\r
a405b86d 920 }\r
921 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
fb84495a 922 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 923 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 924 if (StdErrFileName != NULL) {\r
925 Status = EFI_INVALID_PARAMETER;\r
926 } else {\r
927 StdErrFileName = CommandLineWalker += 4;\r
928 ErrAppend = FALSE;\r
929 }\r
733f138d 930 if (StrStr(CommandLineWalker, L" 2> ") != NULL) {\r
931 Status = EFI_NOT_FOUND;\r
932 }\r
a405b86d 933 }\r
934\r
935 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
fb84495a 936 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 937 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 938 if (StdOutFileName != NULL) {\r
939 Status = EFI_INVALID_PARAMETER;\r
940 } else {\r
941 StdOutFileName = CommandLineWalker += 4;\r
942 OutAppend = FALSE;\r
943 }\r
733f138d 944 if (StrStr(CommandLineWalker, L" 1> ") != NULL) {\r
945 Status = EFI_NOT_FOUND;\r
946 }\r
a405b86d 947 }\r
948\r
949 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
fb84495a 950 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 951 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 952 if (StdOutFileName != NULL) {\r
953 Status = EFI_INVALID_PARAMETER;\r
954 } else {\r
955 StdOutFileName = CommandLineWalker += 3;\r
956 OutAppend = FALSE;\r
957 }\r
733f138d 958 if (StrStr(CommandLineWalker, L" > ") != NULL) {\r
959 Status = EFI_NOT_FOUND;\r
960 }\r
a405b86d 961 }\r
962\r
963 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
fb84495a 964 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 965 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 966 if (StdInFileName != NULL) {\r
967 Status = EFI_INVALID_PARAMETER;\r
968 } else {\r
969 StdInFileName = CommandLineWalker += 3;\r
733f138d 970 }\r
971 if (StrStr(CommandLineWalker, L" < ") != NULL) {\r
972 Status = EFI_NOT_FOUND;\r
a405b86d 973 }\r
974 }\r
975 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
fb84495a 976 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 977 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 978 if (StdInFileName != NULL) {\r
979 Status = EFI_INVALID_PARAMETER;\r
980 } else {\r
733f138d 981 StdInFileName = CommandLineWalker += 4;\r
982 InUnicode = FALSE;\r
48cb33ec 983 AsciiRedirection = TRUE;\r
733f138d 984 }\r
985 if (StrStr(CommandLineWalker, L" <a ") != NULL) {\r
986 Status = EFI_NOT_FOUND;\r
a405b86d 987 }\r
988 }\r
989 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {\r
fb84495a 990 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 991 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 992 if (StdInVarName != NULL) {\r
993 Status = EFI_INVALID_PARAMETER;\r
994 } else {\r
995 StdInVarName = CommandLineWalker += 4;\r
733f138d 996 }\r
997 if (StrStr(CommandLineWalker, L" <v ") != NULL) {\r
998 Status = EFI_NOT_FOUND;\r
a405b86d 999 }\r
1000 }\r
1001\r
031acf63 1002 //\r
1003 // re-populate the string to support any filenames that were in quotes.\r
1004 //\r
e75390f0 1005 StrnCpyS(CommandLineCopy, StrSize(CommandLineCopy)/sizeof(CHAR16), NewCommandLine, StrLen(NewCommandLine));\r
031acf63 1006\r
5f2915f5 1007 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
810c635d 1008 && (((UINTN)FirstLocation - (UINTN)CommandLineCopy)/sizeof(CHAR16) < StrLen(NewCommandLine))\r
fb84495a 1009 ){\r
810c635d 1010 *(NewCommandLine + ((UINTN)FirstLocation - (UINTN)CommandLineCopy)/sizeof(CHAR16)) = CHAR_NULL;\r
fb84495a 1011 }\r
1012\r
a405b86d 1013 if (!EFI_ERROR(Status)) {\r
031acf63 1014\r
1015 if (StdErrFileName != NULL) {\r
1016 if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {\r
1017 Status = EFI_INVALID_PARAMETER;\r
1018 }\r
a405b86d 1019 }\r
031acf63 1020 if (StdOutFileName != NULL) {\r
1021 if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {\r
1022 Status = EFI_INVALID_PARAMETER;\r
1023 }\r
a405b86d 1024 }\r
031acf63 1025 if (StdInFileName != NULL) {\r
1026 if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {\r
1027 Status = EFI_INVALID_PARAMETER;\r
1028 }\r
a405b86d 1029 }\r
031acf63 1030 if (StdErrVarName != NULL) {\r
6813ba40 1031 if ((StdErrVarName = FixVarName(StdErrVarName)) == NULL) {\r
031acf63 1032 Status = EFI_INVALID_PARAMETER;\r
1033 }\r
a405b86d 1034 }\r
031acf63 1035 if (StdOutVarName != NULL) {\r
6813ba40 1036 if ((StdOutVarName = FixVarName(StdOutVarName)) == NULL) {\r
031acf63 1037 Status = EFI_INVALID_PARAMETER;\r
1038 }\r
a405b86d 1039 }\r
031acf63 1040 if (StdInVarName != NULL) {\r
6813ba40 1041 if ((StdInVarName = FixVarName(StdInVarName)) == NULL) {\r
031acf63 1042 Status = EFI_INVALID_PARAMETER;\r
1043 }\r
a405b86d 1044 }\r
1045\r
0c956e0d 1046 //\r
1047 // Verify not the same and not duplicating something from a split\r
1048 //\r
733f138d 1049 if (\r
1050 //\r
1051 // Check that no 2 filenames are the same\r
1052 //\r
fb84495a 1053 (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
a405b86d 1054 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
1055 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
733f138d 1056 //\r
1057 // Check that no 2 variable names are the same\r
1058 //\r
a405b86d 1059 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)\r
1060 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)\r
1061 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)\r
733f138d 1062 //\r
1063 // When a split (using | operator) is in place some are not allowed\r
1064 //\r
a405b86d 1065 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))\r
1066 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
733f138d 1067 //\r
1068 // Check that nothing is trying to be output to 2 locations.\r
1069 //\r
a405b86d 1070 ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
1071 ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
1072 ||(StdInFileName != NULL && StdInVarName != NULL)\r
733f138d 1073 //\r
733f138d 1074 // Check for no volatile environment variables\r
1075 //\r
31e5b912
RN
1076 ||(StdErrVarName != NULL && !EFI_ERROR (IsVolatileEnv (StdErrVarName, &Volatile)) && !Volatile)\r
1077 ||(StdOutVarName != NULL && !EFI_ERROR (IsVolatileEnv (StdOutVarName, &Volatile)) && !Volatile)\r
733f138d 1078 //\r
1079 // Cant redirect during a reconnect operation.\r
1080 //\r
ba0014b9 1081 ||(StrStr(NewCommandLine, L"connect -r") != NULL\r
3c865f20 1082 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
733f138d 1083 //\r
1084 // Check that filetypes (Unicode/Ascii) do not change during an append\r
1085 //\r
1086 ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
1087 ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
1088 ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
1089 ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
a405b86d 1090 ){\r
1091 Status = EFI_INVALID_PARAMETER;\r
a9ca0684 1092 ShellParameters->StdIn = *OldStdIn;\r
1093 ShellParameters->StdOut = *OldStdOut;\r
1094 ShellParameters->StdErr = *OldStdErr;\r
fb84495a 1095 } else if (!EFI_ERROR(Status)){\r
a405b86d 1096 //\r
1097 // Open the Std<Whatever> and we should not have conflicts here...\r
1098 //\r
1099\r
1100 //\r
1101 // StdErr to a file\r
1102 //\r
1103 if (StdErrFileName != NULL) {\r
1104 if (!ErrAppend) {\r
1105 //\r
1106 // delete existing file.\r
1107 //\r
1108 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);\r
1109 }\r
1110 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
a405b86d 1111 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
94c2a044 1112 Status = WriteFileTag (TempHandle);\r
a405b86d 1113 }\r
1114 if (!ErrUnicode && !EFI_ERROR(Status)) {\r
1115 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1116 ASSERT(TempHandle != NULL);\r
1117 }\r
1118 if (!EFI_ERROR(Status)) {\r
1119 ShellParameters->StdErr = TempHandle;\r
dcf9b428 1120 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);\r
a405b86d 1121 }\r
1122 }\r
1123\r
1124 //\r
1125 // StdOut to a file\r
1126 //\r
1127 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {\r
1128 if (!OutAppend) {\r
1129 //\r
1130 // delete existing file.\r
1131 //\r
1132 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);\r
1133 }\r
1134 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
3c865f20 1135 if (TempHandle == NULL) {\r
1136 Status = EFI_INVALID_PARAMETER;\r
1137 } else {\r
583448b4 1138 if (gUnicodeCollation->MetaiMatch (gUnicodeCollation, StdOutFileName, L"NUL")) {\r
733f138d 1139 //no-op\r
1140 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
94c2a044 1141 Status = WriteFileTag (TempHandle);\r
3c865f20 1142 } else if (OutAppend) {\r
3c865f20 1143 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);\r
1144 if (!EFI_ERROR(Status)) {\r
5967886d
LE
1145 //\r
1146 // When appending to a new unicode file, write the file tag.\r
1147 // Otherwise (ie. when appending to a new ASCII file, or an\r
1148 // existent file with any encoding), just seek to the end.\r
1149 //\r
1150 Status = (FileSize == 0 && OutUnicode) ?\r
1151 WriteFileTag (TempHandle) :\r
1152 ShellInfoObject.NewEfiShellProtocol->SetFilePosition (\r
1153 TempHandle,\r
1154 FileSize);\r
3c865f20 1155 }\r
1156 }\r
1157 if (!OutUnicode && !EFI_ERROR(Status)) {\r
1158 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1159 ASSERT(TempHandle != NULL);\r
1160 }\r
a405b86d 1161 if (!EFI_ERROR(Status)) {\r
3c865f20 1162 ShellParameters->StdOut = TempHandle;\r
dcf9b428 1163 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);\r
a405b86d 1164 }\r
1165 }\r
a405b86d 1166 }\r
1167\r
1168 //\r
1169 // StdOut to a var\r
1170 //\r
1171 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {\r
1172 if (!OutAppend) {\r
1173 //\r
1174 // delete existing variable.\r
1175 //\r
1176 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");\r
1177 }\r
1178 TempHandle = CreateFileInterfaceEnv(StdOutVarName);\r
1179 ASSERT(TempHandle != NULL);\r
a405b86d 1180 ShellParameters->StdOut = TempHandle;\r
dcf9b428 1181 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);\r
a405b86d 1182 }\r
1183\r
1184 //\r
1185 // StdErr to a var\r
1186 //\r
1187 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {\r
1188 if (!ErrAppend) {\r
1189 //\r
1190 // delete existing variable.\r
1191 //\r
1192 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");\r
1193 }\r
1194 TempHandle = CreateFileInterfaceEnv(StdErrVarName);\r
1195 ASSERT(TempHandle != NULL);\r
a405b86d 1196 ShellParameters->StdErr = TempHandle;\r
dcf9b428 1197 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);\r
a405b86d 1198 }\r
1199\r
1200 //\r
1201 // StdIn from a var\r
1202 //\r
1203 if (!EFI_ERROR(Status) && StdInVarName != NULL) {\r
1204 TempHandle = CreateFileInterfaceEnv(StdInVarName);\r
532691c8 1205 if (TempHandle == NULL) {\r
1206 Status = EFI_OUT_OF_RESOURCES;\r
a405b86d 1207 } else {\r
532691c8 1208 if (!InUnicode) {\r
1209 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1210 }\r
1211 Size = 0;\r
96962f0a 1212 if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
532691c8 1213 Status = EFI_INVALID_PARAMETER;\r
1214 } else {\r
1215 ShellParameters->StdIn = TempHandle;\r
1216 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1217 }\r
a405b86d 1218 }\r
1219 }\r
1220\r
1221 //\r
1222 // StdIn from a file\r
1223 //\r
1224 if (!EFI_ERROR(Status) && StdInFileName != NULL) {\r
1225 Status = ShellOpenFileByName(\r
1226 StdInFileName,\r
1227 &TempHandle,\r
1228 EFI_FILE_MODE_READ,\r
1229 0);\r
a405b86d 1230 if (!EFI_ERROR(Status)) {\r
231ad7d8
QS
1231 if (!InUnicode) {\r
1232 //\r
1233 // Create the ASCII->Unicode conversion layer\r
1234 //\r
1235 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1236 }\r
a405b86d 1237 ShellParameters->StdIn = TempHandle;\r
8be0ba36 1238 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
a405b86d 1239 }\r
1240 }\r
1241 }\r
1242 }\r
1243 FreePool(CommandLineCopy);\r
8be0ba36 1244\r
cf6a8f14 1245 CalculateEfiHdrCrc(&gST->Hdr);\r
1246\r
8be0ba36 1247 if (gST->ConIn == NULL ||gST->ConOut == NULL) {\r
cc31ac1e 1248 Status = EFI_OUT_OF_RESOURCES;\r
8be0ba36 1249 }\r
cc31ac1e
JC
1250\r
1251 if (Status == EFI_NOT_FOUND) {\r
1252 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle);\r
1253 } else if (EFI_ERROR(Status)) {\r
1254 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);\r
1255 }\r
1256\r
a405b86d 1257 return (Status);\r
1258}\r
1259\r
1260/**\r
6a5033ca 1261 Function will replace the current StdIn and StdOut in the ShellParameters protocol\r
a405b86d 1262 structure with StdIn and StdOut. The current values are de-allocated.\r
1263\r
4ff7e37b
ED
1264 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1265 @param[in] OldStdIn Pointer to old StdIn.\r
1266 @param[in] OldStdOut Pointer to old StdOut.\r
1267 @param[in] OldStdErr Pointer to old StdErr.\r
1268 @param[in] SystemTableInfo Pointer to old system table information.\r
a405b86d 1269**/\r
1270EFI_STATUS\r
a405b86d 1271RestoreStdInStdOutStdErr (\r
1272 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
8be0ba36 1273 IN SHELL_FILE_HANDLE *OldStdIn,\r
1274 IN SHELL_FILE_HANDLE *OldStdOut,\r
1275 IN SHELL_FILE_HANDLE *OldStdErr,\r
1276 IN SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 1277 )\r
1278{\r
1279 SPLIT_LIST *Split;\r
8be0ba36 1280\r
ba0014b9 1281 if (ShellParameters == NULL\r
8be0ba36 1282 ||OldStdIn == NULL\r
1283 ||OldStdOut == NULL\r
1284 ||OldStdErr == NULL\r
1285 ||SystemTableInfo == NULL) {\r
1286 return (EFI_INVALID_PARAMETER);\r
1287 }\r
a405b86d 1288 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
1289 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
1290 } else {\r
1291 Split = NULL;\r
1292 }\r
8be0ba36 1293 if (ShellParameters->StdIn != *OldStdIn) {\r
a405b86d 1294 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
1295 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
1296 }\r
8be0ba36 1297 ShellParameters->StdIn = *OldStdIn;\r
a405b86d 1298 }\r
8be0ba36 1299 if (ShellParameters->StdOut != *OldStdOut) {\r
a405b86d 1300 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
1301 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
1302 }\r
8be0ba36 1303 ShellParameters->StdOut = *OldStdOut;\r
1304 }\r
1305 if (ShellParameters->StdErr != *OldStdErr) {\r
1306 gEfiShellProtocol->CloseFile(ShellParameters->StdErr);\r
1307 ShellParameters->StdErr = *OldStdErr;\r
1308 }\r
1309\r
1310 if (gST->ConIn != SystemTableInfo->ConIn) {\r
1311 CloseSimpleTextInOnFile(gST->ConIn);\r
1312 gST->ConIn = SystemTableInfo->ConIn;\r
1313 gST->ConsoleInHandle = SystemTableInfo->ConInHandle;\r
a405b86d 1314 }\r
8be0ba36 1315 if (gST->ConOut != SystemTableInfo->ConOut) {\r
1316 CloseSimpleTextOutOnFile(gST->ConOut);\r
1317 gST->ConOut = SystemTableInfo->ConOut;\r
1318 gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;\r
1319 }\r
4ccd9214 1320 if (gST->StdErr != SystemTableInfo->ErrOut) {\r
8be0ba36 1321 CloseSimpleTextOutOnFile(gST->StdErr);\r
4ccd9214
ED
1322 gST->StdErr = SystemTableInfo->ErrOut;\r
1323 gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle;\r
8be0ba36 1324 }\r
1325\r
cf6a8f14 1326 CalculateEfiHdrCrc(&gST->Hdr);\r
1327\r
a405b86d 1328 return (EFI_SUCCESS);\r
1329}\r
1330/**\r
6a5033ca 1331 Function will replace the current Argc and Argv in the ShellParameters protocol\r
a405b86d 1332 structure by parsing NewCommandLine. The current values are returned to the\r
1333 user.\r
1334\r
1335 If OldArgv or OldArgc is NULL then that value is not returned.\r
1336\r
4ff7e37b
ED
1337 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1338 @param[in] NewCommandLine The new command line to parse and use.\r
d1c275c6 1339 @param[in] Type The type of operation.\r
4ff7e37b
ED
1340 @param[out] OldArgv Pointer to old list of parameters.\r
1341 @param[out] OldArgc Pointer to old number of items in Argv list.\r
a405b86d 1342\r
7f9e354a 1343\r
6a5033ca 1344 @retval EFI_SUCCESS Operation was successful, Argv and Argc are valid.\r
7f9e354a 1345 @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
a405b86d 1346 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1347**/\r
1348EFI_STATUS\r
a405b86d 1349UpdateArgcArgv(\r
1350 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1351 IN CONST CHAR16 *NewCommandLine,\r
d1c275c6 1352 IN SHELL_OPERATION_TYPES Type,\r
a405b86d 1353 OUT CHAR16 ***OldArgv OPTIONAL,\r
1354 OUT UINTN *OldArgc OPTIONAL\r
1355 )\r
1356{\r
d1c275c6 1357 BOOLEAN StripParamQuotation;\r
ba0014b9 1358\r
a405b86d 1359 ASSERT(ShellParameters != NULL);\r
d1c275c6 1360 StripParamQuotation = TRUE;\r
a405b86d 1361\r
1362 if (OldArgc != NULL) {\r
1363 *OldArgc = ShellParameters->Argc;\r
1364 }\r
1365 if (OldArgc != NULL) {\r
1366 *OldArgv = ShellParameters->Argv;\r
1367 }\r
1368\r
d1c275c6
QS
1369 if (Type == Script_File_Name) {\r
1370 StripParamQuotation = FALSE;\r
1371 }\r
ba0014b9
LG
1372\r
1373 return ParseCommandLineToArgs( NewCommandLine,\r
1374 StripParamQuotation,\r
1375 &(ShellParameters->Argv),\r
d1c275c6
QS
1376 &(ShellParameters->Argc)\r
1377 );\r
a405b86d 1378}\r
1379\r
1380/**\r
6a5033ca 1381 Function will replace the current Argc and Argv in the ShellParameters protocol\r
a405b86d 1382 structure with Argv and Argc. The current values are de-allocated and the\r
1383 OldArgv must not be deallocated by the caller.\r
1384\r
4ff7e37b
ED
1385 @param[in, out] ShellParameters pointer to parameter structure to modify\r
1386 @param[in] OldArgv pointer to old list of parameters\r
1387 @param[in] OldArgc pointer to old number of items in Argv list\r
a405b86d 1388**/\r
1389VOID\r
a405b86d 1390RestoreArgcArgv(\r
1391 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1392 IN CHAR16 ***OldArgv,\r
1393 IN UINTN *OldArgc\r
1394 )\r
1395{\r
1396 UINTN LoopCounter;\r
1397 ASSERT(ShellParameters != NULL);\r
1398 ASSERT(OldArgv != NULL);\r
1399 ASSERT(OldArgc != NULL);\r
1400\r
1401 if (ShellParameters->Argv != NULL) {\r
1402 for ( LoopCounter = 0\r
1403 ; LoopCounter < ShellParameters->Argc\r
1404 ; LoopCounter++\r
1405 ){\r
1406 FreePool(ShellParameters->Argv[LoopCounter]);\r
1407 }\r
1408 FreePool(ShellParameters->Argv);\r
1409 }\r
1410 ShellParameters->Argv = *OldArgv;\r
1411 *OldArgv = NULL;\r
1412 ShellParameters->Argc = *OldArgc;\r
1413 *OldArgc = 0;\r
1414}\r