VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/ShellPkg/Application/Shell/ShellParametersProtocol.c@ 108794

Last change on this file since 108794 was 108794, checked in by vboxsync, 2 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette