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