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