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