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