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