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