]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ShellPkg/Application/Shell/ShellParametersProtocol.c
ShellPkg: Don't strip BOM when piping UCS2 data to a UEFI app
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellParametersProtocol.c
... / ...
CommitLineData
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
5 Copyright (C) 2014, Red Hat, Inc.\r
6 (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>\r
7 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
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
18#include "Shell.h"\r
19\r
20BOOLEAN AsciiRedirection = FALSE;\r
21\r
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
178/**\r
179 Function to populate Argc and Argv.\r
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
185 All special character processing (alias, environment variable, redirection, \r
186 etc... must be complete before calling this API.\r
187\r
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
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
201 IN BOOLEAN StripQuotation,\r
202 IN OUT CHAR16 ***Argv,\r
203 IN OUT UINTN *Argc\r
204 )\r
205{\r
206 UINTN Count;\r
207 CHAR16 *TempParameter;\r
208 CHAR16 *Walker;\r
209 CHAR16 *NewParam;\r
210 CHAR16 *NewCommandLine;\r
211 UINTN Size;\r
212 EFI_STATUS Status;\r
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
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
230 TempParameter = AllocateZeroPool(Size);\r
231 if (TempParameter == NULL) {\r
232 SHELL_FREE_NON_NULL(NewCommandLine);\r
233 return (EFI_OUT_OF_RESOURCES);\r
234 }\r
235\r
236 for ( Count = 0\r
237 , Walker = (CHAR16*)NewCommandLine\r
238 ; Walker != NULL && *Walker != CHAR_NULL\r
239 ; Count++\r
240 ) {\r
241 if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size, TRUE))) {\r
242 break;\r
243 }\r
244 }\r
245\r
246 //\r
247 // lets allocate the pointer array\r
248 //\r
249 (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*));\r
250 if (*Argv == NULL) {\r
251 Status = EFI_OUT_OF_RESOURCES;\r
252 goto Done;\r
253 }\r
254\r
255 *Argc = 0;\r
256 Walker = (CHAR16*)NewCommandLine;\r
257 while(Walker != NULL && *Walker != CHAR_NULL) {\r
258 SetMem16(TempParameter, Size, CHAR_NULL);\r
259 if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size, StripQuotation))) {\r
260 Status = EFI_INVALID_PARAMETER;\r
261 goto Done;\r
262 }\r
263\r
264 NewParam = AllocateCopyPool(StrSize(TempParameter), TempParameter);\r
265 if (NewParam == NULL){\r
266 Status = EFI_OUT_OF_RESOURCES;\r
267 goto Done;\r
268 }\r
269 ((CHAR16**)(*Argv))[(*Argc)] = NewParam;\r
270 (*Argc)++;\r
271 }\r
272 ASSERT(Count >= (*Argc));\r
273 Status = EFI_SUCCESS;\r
274 \r
275Done:\r
276 SHELL_FREE_NON_NULL(TempParameter);\r
277 SHELL_FREE_NON_NULL(NewCommandLine);\r
278 return (Status);\r
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
286 @param[in, out] NewShellParameters on a successful return, a pointer to pointer\r
287 to the newly installed interface.\r
288 @param[in, out] RootShellInstance on a successful return, pointer to boolean.\r
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
341 if ((*NewShellParameters) == NULL) {\r
342 return (EFI_OUT_OF_RESOURCES);\r
343 }\r
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
360 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);\r
361 if (Status == EFI_BUFFER_TOO_SMALL) {\r
362 FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);\r
363 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);\r
364 }\r
365 if (Status == EFI_NOT_FOUND) {\r
366 //\r
367 // no parameters via environment... ok\r
368 //\r
369 } else {\r
370 if (EFI_ERROR(Status)) {\r
371 return (Status);\r
372 }\r
373 }\r
374 if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {\r
375 ASSERT(FullCommandLine == NULL);\r
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
382 if (FullCommandLine != NULL) {\r
383 CopyMem (FullCommandLine, LoadedImage->LoadOptions, LoadedImage->LoadOptionsSize);\r
384 //\r
385 // Populate Argc and Argv\r
386 //\r
387 Status = ParseCommandLineToArgs(FullCommandLine,\r
388 TRUE,\r
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
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
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
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
518\r
519 @param[in, out] TheString A pointer to the string to update.\r
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
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
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
593 while(Copy[0] == L' ') {\r
594 Copy++;\r
595 }\r
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
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
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
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
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
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
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
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
697 This will also update the system table.\r
698\r
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
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
713 IN CHAR16 *NewCommandLine,\r
714 OUT SHELL_FILE_HANDLE *OldStdIn,\r
715 OUT SHELL_FILE_HANDLE *OldStdOut,\r
716 OUT SHELL_FILE_HANDLE *OldStdErr,\r
717 OUT SYSTEM_TABLE_INFO *SystemTableInfo\r
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
737 SPLIT_LIST *Split;\r
738 CHAR16 *FirstLocation;\r
739\r
740 OutUnicode = TRUE;\r
741 InUnicode = TRUE;\r
742 AsciiRedirection = FALSE;\r
743 ErrUnicode = TRUE;\r
744 StdInVarName = NULL;\r
745 StdOutVarName = NULL;\r
746 StdErrVarName = NULL;\r
747 StdErrFileName = NULL;\r
748 StdInFileName = NULL;\r
749 StdOutFileName = NULL;\r
750 ErrAppend = FALSE;\r
751 OutAppend = FALSE;\r
752 CommandLineCopy = NULL;\r
753 FirstLocation = NULL;\r
754\r
755 if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {\r
756 return (EFI_INVALID_PARAMETER);\r
757 }\r
758\r
759 SystemTableInfo->ConIn = gST->ConIn;\r
760 SystemTableInfo->ConInHandle = gST->ConsoleInHandle;\r
761 SystemTableInfo->ConOut = gST->ConOut;\r
762 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;\r
763 SystemTableInfo->ErrOut = gST->StdErr;\r
764 SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle;\r
765 *OldStdIn = ShellParameters->StdIn;\r
766 *OldStdOut = ShellParameters->StdOut;\r
767 *OldStdErr = ShellParameters->StdErr;\r
768\r
769 if (NewCommandLine == NULL) {\r
770 return (EFI_SUCCESS);\r
771 }\r
772\r
773 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
774 if (CommandLineCopy == NULL) {\r
775 return (EFI_OUT_OF_RESOURCES);\r
776 }\r
777 Status = EFI_SUCCESS;\r
778 Split = NULL;\r
779 FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);\r
780\r
781 StripQuotes(CommandLineCopy);\r
782\r
783 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
784 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
785 if (Split != NULL && Split->SplitStdIn != NULL) {\r
786 ShellParameters->StdIn = Split->SplitStdIn;\r
787 }\r
788 if (Split != NULL && Split->SplitStdOut != NULL) {\r
789 ShellParameters->StdOut = Split->SplitStdOut;\r
790 }\r
791 }\r
792\r
793 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {\r
794 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
795 SetMem16(CommandLineWalker, 12, L' ');\r
796 StdErrVarName = CommandLineWalker += 6;\r
797 ErrAppend = TRUE;\r
798 if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {\r
799 Status = EFI_NOT_FOUND;\r
800 }\r
801 }\r
802 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
803 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
804 SetMem16(CommandLineWalker, 12, L' ');\r
805 StdOutVarName = CommandLineWalker += 6;\r
806 OutAppend = TRUE;\r
807 if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {\r
808 Status = EFI_NOT_FOUND;\r
809 }\r
810 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
811 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
812 SetMem16(CommandLineWalker, 10, L' ');\r
813 StdOutVarName = CommandLineWalker += 5;\r
814 OutAppend = TRUE;\r
815 if (StrStr(CommandLineWalker, L" >>v ") != NULL) {\r
816 Status = EFI_NOT_FOUND;\r
817 }\r
818 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
819 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
820 SetMem16(CommandLineWalker, 8, L' ');\r
821 StdOutVarName = CommandLineWalker += 4;\r
822 OutAppend = FALSE;\r
823 if (StrStr(CommandLineWalker, L" >v ") != NULL) {\r
824 Status = EFI_NOT_FOUND;\r
825 }\r
826 }\r
827 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
828 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
829 SetMem16(CommandLineWalker, 12, L' ');\r
830 StdOutFileName = CommandLineWalker += 6;\r
831 OutAppend = TRUE;\r
832 OutUnicode = FALSE;\r
833 if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {\r
834 Status = EFI_NOT_FOUND;\r
835 }\r
836 }\r
837 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
838 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
839 SetMem16(CommandLineWalker, 10, L' ');\r
840 if (StdOutFileName != NULL) {\r
841 Status = EFI_INVALID_PARAMETER;\r
842 } else {\r
843 StdOutFileName = CommandLineWalker += 5;\r
844 OutAppend = TRUE;\r
845 }\r
846 if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
847 Status = EFI_NOT_FOUND;\r
848 }\r
849 } \r
850 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
851 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
852 SetMem16(CommandLineWalker, 8, L' ');\r
853 if (StdOutFileName != NULL) {\r
854 Status = EFI_INVALID_PARAMETER;\r
855 } else {\r
856 StdOutFileName = CommandLineWalker += 4;\r
857 OutAppend = TRUE;\r
858 }\r
859 if (StrStr(CommandLineWalker, L" >> ") != NULL) {\r
860 Status = EFI_NOT_FOUND;\r
861 }\r
862 }\r
863 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {\r
864 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
865 SetMem16(CommandLineWalker, 10, L' ');\r
866 if (StdOutFileName != NULL) {\r
867 Status = EFI_INVALID_PARAMETER;\r
868 } else {\r
869 StdOutFileName = CommandLineWalker += 5;\r
870 OutAppend = TRUE;\r
871 OutUnicode = FALSE;\r
872 }\r
873 if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
874 Status = EFI_NOT_FOUND;\r
875 }\r
876 } \r
877 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
878 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
879 SetMem16(CommandLineWalker, 10, L' ');\r
880 if (StdOutFileName != NULL) {\r
881 Status = EFI_INVALID_PARAMETER;\r
882 } else {\r
883 StdOutFileName = CommandLineWalker += 5;\r
884 OutAppend = FALSE;\r
885 OutUnicode = FALSE;\r
886 }\r
887 if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
888 Status = EFI_NOT_FOUND;\r
889 }\r
890 } \r
891 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
892 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
893 SetMem16(CommandLineWalker, 8, L' ');\r
894 if (StdOutFileName != NULL) {\r
895 Status = EFI_INVALID_PARAMETER;\r
896 } else {\r
897 StdOutFileName = CommandLineWalker += 4;\r
898 OutAppend = FALSE;\r
899 OutUnicode = FALSE;\r
900 }\r
901 if (StrStr(CommandLineWalker, L" >a ") != NULL) {\r
902 Status = EFI_NOT_FOUND;\r
903 }\r
904 }\r
905 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
906 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
907 SetMem16(CommandLineWalker, 10, L' ');\r
908 if (StdErrFileName != NULL) {\r
909 Status = EFI_INVALID_PARAMETER;\r
910 } else {\r
911 StdErrFileName = CommandLineWalker += 5;\r
912 ErrAppend = TRUE;\r
913 }\r
914 if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {\r
915 Status = EFI_NOT_FOUND;\r
916 }\r
917 }\r
918\r
919 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
920 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
921 SetMem16(CommandLineWalker, 10, L' ');\r
922 if (StdErrVarName != NULL) {\r
923 Status = EFI_INVALID_PARAMETER;\r
924 } else {\r
925 StdErrVarName = CommandLineWalker += 5;\r
926 ErrAppend = FALSE;\r
927 }\r
928 if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {\r
929 Status = EFI_NOT_FOUND;\r
930 }\r
931 }\r
932 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
933 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
934 SetMem16(CommandLineWalker, 10, L' ');\r
935 if (StdOutVarName != NULL) {\r
936 Status = EFI_INVALID_PARAMETER;\r
937 } else {\r
938 StdOutVarName = CommandLineWalker += 5;\r
939 OutAppend = FALSE;\r
940 }\r
941 if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {\r
942 Status = EFI_NOT_FOUND;\r
943 }\r
944 }\r
945 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
946 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
947 SetMem16(CommandLineWalker, 10, L' ');\r
948 if (StdErrFileName != NULL) {\r
949 Status = EFI_INVALID_PARAMETER;\r
950 } else {\r
951 StdErrFileName = CommandLineWalker += 5;\r
952 ErrAppend = FALSE;\r
953 ErrUnicode = FALSE;\r
954 }\r
955 if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {\r
956 Status = EFI_NOT_FOUND;\r
957 }\r
958 }\r
959 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
960 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
961 SetMem16(CommandLineWalker, 8, L' ');\r
962 if (StdErrFileName != NULL) {\r
963 Status = EFI_INVALID_PARAMETER;\r
964 } else {\r
965 StdErrFileName = CommandLineWalker += 4;\r
966 ErrAppend = FALSE;\r
967 }\r
968 if (StrStr(CommandLineWalker, L" 2> ") != NULL) {\r
969 Status = EFI_NOT_FOUND;\r
970 }\r
971 }\r
972\r
973 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
974 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
975 SetMem16(CommandLineWalker, 8, L' ');\r
976 if (StdOutFileName != NULL) {\r
977 Status = EFI_INVALID_PARAMETER;\r
978 } else {\r
979 StdOutFileName = CommandLineWalker += 4;\r
980 OutAppend = FALSE;\r
981 }\r
982 if (StrStr(CommandLineWalker, L" 1> ") != NULL) {\r
983 Status = EFI_NOT_FOUND;\r
984 }\r
985 }\r
986\r
987 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
988 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
989 SetMem16(CommandLineWalker, 6, L' ');\r
990 if (StdOutFileName != NULL) {\r
991 Status = EFI_INVALID_PARAMETER;\r
992 } else {\r
993 StdOutFileName = CommandLineWalker += 3;\r
994 OutAppend = FALSE;\r
995 }\r
996 if (StrStr(CommandLineWalker, L" > ") != NULL) {\r
997 Status = EFI_NOT_FOUND;\r
998 }\r
999 }\r
1000\r
1001 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
1002 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
1003 SetMem16(CommandLineWalker, 6, L' ');\r
1004 if (StdInFileName != NULL) {\r
1005 Status = EFI_INVALID_PARAMETER;\r
1006 } else {\r
1007 StdInFileName = CommandLineWalker += 3;\r
1008 }\r
1009 if (StrStr(CommandLineWalker, L" < ") != NULL) {\r
1010 Status = EFI_NOT_FOUND;\r
1011 }\r
1012 }\r
1013 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
1014 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
1015 SetMem16(CommandLineWalker, 8, L' ');\r
1016 if (StdInFileName != NULL) {\r
1017 Status = EFI_INVALID_PARAMETER;\r
1018 } else {\r
1019 StdInFileName = CommandLineWalker += 4;\r
1020 InUnicode = FALSE;\r
1021 AsciiRedirection = TRUE;\r
1022 }\r
1023 if (StrStr(CommandLineWalker, L" <a ") != NULL) {\r
1024 Status = EFI_NOT_FOUND;\r
1025 }\r
1026 }\r
1027 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {\r
1028 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
1029 SetMem16(CommandLineWalker, 8, L' ');\r
1030 if (StdInVarName != NULL) {\r
1031 Status = EFI_INVALID_PARAMETER;\r
1032 } else {\r
1033 StdInVarName = CommandLineWalker += 4;\r
1034 }\r
1035 if (StrStr(CommandLineWalker, L" <v ") != NULL) {\r
1036 Status = EFI_NOT_FOUND;\r
1037 }\r
1038 }\r
1039\r
1040 //\r
1041 // re-populate the string to support any filenames that were in quotes.\r
1042 //\r
1043 StrnCpyS(CommandLineCopy, StrSize(CommandLineCopy)/sizeof(CHAR16), NewCommandLine, StrLen(NewCommandLine));\r
1044\r
1045 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
1046 && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))\r
1047 ){\r
1048 *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;\r
1049 }\r
1050\r
1051 if (!EFI_ERROR(Status)) {\r
1052\r
1053 if (StdErrFileName != NULL) {\r
1054 if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {\r
1055 Status = EFI_INVALID_PARAMETER;\r
1056 }\r
1057 }\r
1058 if (StdOutFileName != NULL) {\r
1059 if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {\r
1060 Status = EFI_INVALID_PARAMETER;\r
1061 }\r
1062 }\r
1063 if (StdInFileName != NULL) {\r
1064 if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {\r
1065 Status = EFI_INVALID_PARAMETER;\r
1066 }\r
1067 }\r
1068 if (StdErrVarName != NULL) {\r
1069 if ((StdErrVarName = FixVarName(StdErrVarName)) == NULL) {\r
1070 Status = EFI_INVALID_PARAMETER;\r
1071 }\r
1072 }\r
1073 if (StdOutVarName != NULL) {\r
1074 if ((StdOutVarName = FixVarName(StdOutVarName)) == NULL) {\r
1075 Status = EFI_INVALID_PARAMETER;\r
1076 }\r
1077 }\r
1078 if (StdInVarName != NULL) {\r
1079 if ((StdInVarName = FixVarName(StdInVarName)) == NULL) {\r
1080 Status = EFI_INVALID_PARAMETER;\r
1081 }\r
1082 }\r
1083\r
1084 //\r
1085 // Verify not the same and not duplicating something from a split\r
1086 //\r
1087 if (\r
1088 //\r
1089 // Check that no 2 filenames are the same\r
1090 //\r
1091 (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
1092 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
1093 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
1094 //\r
1095 // Check that no 2 variable names are the same\r
1096 //\r
1097 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)\r
1098 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)\r
1099 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)\r
1100 //\r
1101 // When a split (using | operator) is in place some are not allowed\r
1102 //\r
1103 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))\r
1104 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
1105 //\r
1106 // Check that nothing is trying to be output to 2 locations.\r
1107 //\r
1108 ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
1109 ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
1110 ||(StdInFileName != NULL && StdInVarName != NULL)\r
1111 //\r
1112 // Check for no volatile environment variables\r
1113 //\r
1114 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))\r
1115 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))\r
1116 //\r
1117 // Cant redirect during a reconnect operation.\r
1118 //\r
1119 ||(StrStr(NewCommandLine, L"connect -r") != NULL \r
1120 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
1121 //\r
1122 // Check that filetypes (Unicode/Ascii) do not change during an append\r
1123 //\r
1124 ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
1125 ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
1126 ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
1127 ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
1128 ){\r
1129 Status = EFI_INVALID_PARAMETER;\r
1130 ShellParameters->StdIn = *OldStdIn;\r
1131 ShellParameters->StdOut = *OldStdOut;\r
1132 ShellParameters->StdErr = *OldStdErr;\r
1133 } else if (!EFI_ERROR(Status)){\r
1134 //\r
1135 // Open the Std<Whatever> and we should not have conflicts here...\r
1136 //\r
1137\r
1138 //\r
1139 // StdErr to a file\r
1140 //\r
1141 if (StdErrFileName != NULL) {\r
1142 if (!ErrAppend) {\r
1143 //\r
1144 // delete existing file.\r
1145 //\r
1146 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);\r
1147 }\r
1148 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
1149 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
1150 Status = WriteFileTag (TempHandle);\r
1151 }\r
1152 if (!ErrUnicode && !EFI_ERROR(Status)) {\r
1153 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1154 ASSERT(TempHandle != NULL);\r
1155 }\r
1156 if (!EFI_ERROR(Status)) {\r
1157 ShellParameters->StdErr = TempHandle;\r
1158 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);\r
1159 }\r
1160 }\r
1161\r
1162 //\r
1163 // StdOut to a file\r
1164 //\r
1165 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {\r
1166 if (!OutAppend) {\r
1167 //\r
1168 // delete existing file.\r
1169 //\r
1170 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);\r
1171 }\r
1172 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
1173 if (TempHandle == NULL) {\r
1174 Status = EFI_INVALID_PARAMETER;\r
1175 } else {\r
1176 if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {\r
1177 //no-op\r
1178 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
1179 Status = WriteFileTag (TempHandle);\r
1180 } else if (OutAppend) {\r
1181 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);\r
1182 if (!EFI_ERROR(Status)) {\r
1183 //\r
1184 // When appending to a new unicode file, write the file tag.\r
1185 // Otherwise (ie. when appending to a new ASCII file, or an\r
1186 // existent file with any encoding), just seek to the end.\r
1187 //\r
1188 Status = (FileSize == 0 && OutUnicode) ?\r
1189 WriteFileTag (TempHandle) :\r
1190 ShellInfoObject.NewEfiShellProtocol->SetFilePosition (\r
1191 TempHandle,\r
1192 FileSize);\r
1193 }\r
1194 }\r
1195 if (!OutUnicode && !EFI_ERROR(Status)) {\r
1196 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1197 ASSERT(TempHandle != NULL);\r
1198 }\r
1199 if (!EFI_ERROR(Status)) {\r
1200 ShellParameters->StdOut = TempHandle;\r
1201 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);\r
1202 }\r
1203 }\r
1204 }\r
1205\r
1206 //\r
1207 // StdOut to a var\r
1208 //\r
1209 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {\r
1210 if (!OutAppend) {\r
1211 //\r
1212 // delete existing variable.\r
1213 //\r
1214 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");\r
1215 }\r
1216 TempHandle = CreateFileInterfaceEnv(StdOutVarName);\r
1217 ASSERT(TempHandle != NULL);\r
1218 ShellParameters->StdOut = TempHandle;\r
1219 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);\r
1220 }\r
1221\r
1222 //\r
1223 // StdErr to a var\r
1224 //\r
1225 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {\r
1226 if (!ErrAppend) {\r
1227 //\r
1228 // delete existing variable.\r
1229 //\r
1230 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");\r
1231 }\r
1232 TempHandle = CreateFileInterfaceEnv(StdErrVarName);\r
1233 ASSERT(TempHandle != NULL);\r
1234 ShellParameters->StdErr = TempHandle;\r
1235 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);\r
1236 }\r
1237\r
1238 //\r
1239 // StdIn from a var\r
1240 //\r
1241 if (!EFI_ERROR(Status) && StdInVarName != NULL) {\r
1242 TempHandle = CreateFileInterfaceEnv(StdInVarName);\r
1243 if (TempHandle == NULL) {\r
1244 Status = EFI_OUT_OF_RESOURCES;\r
1245 } else {\r
1246 if (!InUnicode) {\r
1247 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1248 }\r
1249 Size = 0;\r
1250 if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
1251 Status = EFI_INVALID_PARAMETER;\r
1252 } else {\r
1253 ShellParameters->StdIn = TempHandle;\r
1254 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1255 }\r
1256 }\r
1257 }\r
1258\r
1259 //\r
1260 // StdIn from a file\r
1261 //\r
1262 if (!EFI_ERROR(Status) && StdInFileName != NULL) {\r
1263 Status = ShellOpenFileByName(\r
1264 StdInFileName,\r
1265 &TempHandle,\r
1266 EFI_FILE_MODE_READ,\r
1267 0);\r
1268 if (!EFI_ERROR(Status)) {\r
1269 if (!InUnicode) {
1270 //
1271 // Create the ASCII->Unicode conversion layer
1272 //
1273 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
1274 }
1275 ShellParameters->StdIn = TempHandle;\r
1276 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1277 }\r
1278 }\r
1279 }\r
1280 }\r
1281 FreePool(CommandLineCopy);\r
1282\r
1283 CalculateEfiHdrCrc(&gST->Hdr);\r
1284\r
1285 if (gST->ConIn == NULL ||gST->ConOut == NULL) {\r
1286 Status = EFI_OUT_OF_RESOURCES;\r
1287 }\r
1288\r
1289 if (Status == EFI_NOT_FOUND) {\r
1290 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle);\r
1291 } else if (EFI_ERROR(Status)) {\r
1292 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);\r
1293 }\r
1294\r
1295 return (Status);\r
1296}\r
1297\r
1298/**\r
1299 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
1300 structure with StdIn and StdOut. The current values are de-allocated.\r
1301\r
1302 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1303 @param[in] OldStdIn Pointer to old StdIn.\r
1304 @param[in] OldStdOut Pointer to old StdOut.\r
1305 @param[in] OldStdErr Pointer to old StdErr.\r
1306 @param[in] SystemTableInfo Pointer to old system table information.\r
1307**/\r
1308EFI_STATUS\r
1309EFIAPI\r
1310RestoreStdInStdOutStdErr (\r
1311 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1312 IN SHELL_FILE_HANDLE *OldStdIn,\r
1313 IN SHELL_FILE_HANDLE *OldStdOut,\r
1314 IN SHELL_FILE_HANDLE *OldStdErr,\r
1315 IN SYSTEM_TABLE_INFO *SystemTableInfo\r
1316 )\r
1317{\r
1318 SPLIT_LIST *Split;\r
1319\r
1320 if (ShellParameters == NULL \r
1321 ||OldStdIn == NULL\r
1322 ||OldStdOut == NULL\r
1323 ||OldStdErr == NULL\r
1324 ||SystemTableInfo == NULL) {\r
1325 return (EFI_INVALID_PARAMETER);\r
1326 }\r
1327 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
1328 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
1329 } else {\r
1330 Split = NULL;\r
1331 }\r
1332 if (ShellParameters->StdIn != *OldStdIn) {\r
1333 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
1334 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
1335 }\r
1336 ShellParameters->StdIn = *OldStdIn;\r
1337 }\r
1338 if (ShellParameters->StdOut != *OldStdOut) {\r
1339 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
1340 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
1341 }\r
1342 ShellParameters->StdOut = *OldStdOut;\r
1343 }\r
1344 if (ShellParameters->StdErr != *OldStdErr) {\r
1345 gEfiShellProtocol->CloseFile(ShellParameters->StdErr);\r
1346 ShellParameters->StdErr = *OldStdErr;\r
1347 }\r
1348\r
1349 if (gST->ConIn != SystemTableInfo->ConIn) {\r
1350 CloseSimpleTextInOnFile(gST->ConIn);\r
1351 gST->ConIn = SystemTableInfo->ConIn;\r
1352 gST->ConsoleInHandle = SystemTableInfo->ConInHandle;\r
1353 }\r
1354 if (gST->ConOut != SystemTableInfo->ConOut) {\r
1355 CloseSimpleTextOutOnFile(gST->ConOut);\r
1356 gST->ConOut = SystemTableInfo->ConOut;\r
1357 gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;\r
1358 }\r
1359 if (gST->StdErr != SystemTableInfo->ErrOut) {\r
1360 CloseSimpleTextOutOnFile(gST->StdErr);\r
1361 gST->StdErr = SystemTableInfo->ErrOut;\r
1362 gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle;\r
1363 }\r
1364\r
1365 CalculateEfiHdrCrc(&gST->Hdr);\r
1366\r
1367 return (EFI_SUCCESS);\r
1368}\r
1369/**\r
1370 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1371 structure by parsing NewCommandLine. The current values are returned to the\r
1372 user.\r
1373\r
1374 If OldArgv or OldArgc is NULL then that value is not returned.\r
1375\r
1376 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1377 @param[in] NewCommandLine The new command line to parse and use.\r
1378 @param[in] Type The type of operation.\r
1379 @param[out] OldArgv Pointer to old list of parameters.\r
1380 @param[out] OldArgc Pointer to old number of items in Argv list.\r
1381\r
1382 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
1383 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1384**/\r
1385EFI_STATUS\r
1386EFIAPI\r
1387UpdateArgcArgv(\r
1388 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1389 IN CONST CHAR16 *NewCommandLine,\r
1390 IN SHELL_OPERATION_TYPES Type,\r
1391 OUT CHAR16 ***OldArgv OPTIONAL,\r
1392 OUT UINTN *OldArgc OPTIONAL\r
1393 )\r
1394{\r
1395 BOOLEAN StripParamQuotation;\r
1396 \r
1397 ASSERT(ShellParameters != NULL);\r
1398 StripParamQuotation = TRUE;\r
1399\r
1400 if (OldArgc != NULL) {\r
1401 *OldArgc = ShellParameters->Argc;\r
1402 }\r
1403 if (OldArgc != NULL) {\r
1404 *OldArgv = ShellParameters->Argv;\r
1405 }\r
1406\r
1407 if (Type == Script_File_Name) {\r
1408 StripParamQuotation = FALSE;\r
1409 }\r
1410 \r
1411 return ParseCommandLineToArgs( NewCommandLine, \r
1412 StripParamQuotation, \r
1413 &(ShellParameters->Argv), \r
1414 &(ShellParameters->Argc)\r
1415 );\r
1416}\r
1417\r
1418/**\r
1419 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1420 structure with Argv and Argc. The current values are de-allocated and the\r
1421 OldArgv must not be deallocated by the caller.\r
1422\r
1423 @param[in, out] ShellParameters pointer to parameter structure to modify\r
1424 @param[in] OldArgv pointer to old list of parameters\r
1425 @param[in] OldArgc pointer to old number of items in Argv list\r
1426**/\r
1427VOID\r
1428EFIAPI\r
1429RestoreArgcArgv(\r
1430 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1431 IN CHAR16 ***OldArgv,\r
1432 IN UINTN *OldArgc\r
1433 )\r
1434{\r
1435 UINTN LoopCounter;\r
1436 ASSERT(ShellParameters != NULL);\r
1437 ASSERT(OldArgv != NULL);\r
1438 ASSERT(OldArgc != NULL);\r
1439\r
1440 if (ShellParameters->Argv != NULL) {\r
1441 for ( LoopCounter = 0\r
1442 ; LoopCounter < ShellParameters->Argc\r
1443 ; LoopCounter++\r
1444 ){\r
1445 FreePool(ShellParameters->Argv[LoopCounter]);\r
1446 }\r
1447 FreePool(ShellParameters->Argv);\r
1448 }\r
1449 ShellParameters->Argv = *OldArgv;\r
1450 *OldArgv = NULL;\r
1451 ShellParameters->Argc = *OldArgc;\r
1452 *OldArgc = 0;\r
1453}\r