]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Application/Shell/ShellParametersProtocol.c
ShellPkg: leave quotes around params
[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 STATIC
613 EFI_STATUS
614 WriteFileTag (
615 IN SHELL_FILE_HANDLE FileHandle
616 )
617 {
618 CHAR16 FileTag;
619 UINTN Size;
620 EFI_STATUS Status;
621
622 FileTag = gUnicodeFileTag;
623 Size = sizeof FileTag;
624 Status = ShellInfoObject.NewEfiShellProtocol->WriteFile (FileHandle, &Size,
625 &FileTag);
626 ASSERT (EFI_ERROR (Status) || Size == sizeof FileTag);
627 return Status;
628 }
629
630
631 /**
632 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
633 structure by parsing NewCommandLine. The current values are returned to the
634 user.
635
636 This will also update the system table.
637
638 @param[in, out] ShellParameters Pointer to parameter structure to modify.
639 @param[in] NewCommandLine The new command line to parse and use.
640 @param[out] OldStdIn Pointer to old StdIn.
641 @param[out] OldStdOut Pointer to old StdOut.
642 @param[out] OldStdErr Pointer to old StdErr.
643 @param[out] SystemTableInfo Pointer to old system table information.
644
645 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
646 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
647 **/
648 EFI_STATUS
649 EFIAPI
650 UpdateStdInStdOutStdErr(
651 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
652 IN CHAR16 *NewCommandLine,
653 OUT SHELL_FILE_HANDLE *OldStdIn,
654 OUT SHELL_FILE_HANDLE *OldStdOut,
655 OUT SHELL_FILE_HANDLE *OldStdErr,
656 OUT SYSTEM_TABLE_INFO *SystemTableInfo
657 )
658 {
659 CHAR16 *CommandLineCopy;
660 CHAR16 *CommandLineWalker;
661 CHAR16 *StdErrFileName;
662 CHAR16 *StdOutFileName;
663 CHAR16 *StdInFileName;
664 CHAR16 *StdInVarName;
665 CHAR16 *StdOutVarName;
666 CHAR16 *StdErrVarName;
667 EFI_STATUS Status;
668 SHELL_FILE_HANDLE TempHandle;
669 UINT64 FileSize;
670 BOOLEAN OutUnicode;
671 BOOLEAN InUnicode;
672 BOOLEAN ErrUnicode;
673 BOOLEAN OutAppend;
674 BOOLEAN ErrAppend;
675 UINTN Size;
676 SPLIT_LIST *Split;
677 CHAR16 *FirstLocation;
678
679 OutUnicode = TRUE;
680 InUnicode = TRUE;
681 ErrUnicode = TRUE;
682 StdInVarName = NULL;
683 StdOutVarName = NULL;
684 StdErrVarName = NULL;
685 StdErrFileName = NULL;
686 StdInFileName = NULL;
687 StdOutFileName = NULL;
688 ErrAppend = FALSE;
689 OutAppend = FALSE;
690 CommandLineCopy = NULL;
691 FirstLocation = NULL;
692
693 if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {
694 return (EFI_INVALID_PARAMETER);
695 }
696
697 SystemTableInfo->ConIn = gST->ConIn;
698 SystemTableInfo->ConInHandle = gST->ConsoleInHandle;
699 SystemTableInfo->ConOut = gST->ConOut;
700 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;
701 SystemTableInfo->ErrOut = gST->StdErr;
702 SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle;
703 *OldStdIn = ShellParameters->StdIn;
704 *OldStdOut = ShellParameters->StdOut;
705 *OldStdErr = ShellParameters->StdErr;
706
707 if (NewCommandLine == NULL) {
708 return (EFI_SUCCESS);
709 }
710
711 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);
712 if (CommandLineCopy == NULL) {
713 return (EFI_OUT_OF_RESOURCES);
714 }
715 Status = EFI_SUCCESS;
716 Split = NULL;
717 FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);
718
719 StripQuotes(CommandLineCopy);
720
721 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {
722 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);
723 if (Split != NULL && Split->SplitStdIn != NULL) {
724 ShellParameters->StdIn = Split->SplitStdIn;
725 }
726 if (Split != NULL && Split->SplitStdOut != NULL) {
727 ShellParameters->StdOut = Split->SplitStdOut;
728 }
729 }
730
731 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {
732 FirstLocation = MIN(CommandLineWalker, FirstLocation);
733 SetMem16(CommandLineWalker, 12, L' ');
734 StdErrVarName = CommandLineWalker += 6;
735 ErrAppend = TRUE;
736 if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {
737 Status = EFI_NOT_FOUND;
738 }
739 }
740 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {
741 FirstLocation = MIN(CommandLineWalker, FirstLocation);
742 SetMem16(CommandLineWalker, 12, L' ');
743 StdOutVarName = CommandLineWalker += 6;
744 OutAppend = TRUE;
745 if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {
746 Status = EFI_NOT_FOUND;
747 }
748 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {
749 FirstLocation = MIN(CommandLineWalker, FirstLocation);
750 SetMem16(CommandLineWalker, 10, L' ');
751 StdOutVarName = CommandLineWalker += 5;
752 OutAppend = TRUE;
753 if (StrStr(CommandLineWalker, L" >>v ") != NULL) {
754 Status = EFI_NOT_FOUND;
755 }
756 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {
757 FirstLocation = MIN(CommandLineWalker, FirstLocation);
758 SetMem16(CommandLineWalker, 8, L' ');
759 StdOutVarName = CommandLineWalker += 4;
760 OutAppend = FALSE;
761 if (StrStr(CommandLineWalker, L" >v ") != NULL) {
762 Status = EFI_NOT_FOUND;
763 }
764 }
765 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {
766 FirstLocation = MIN(CommandLineWalker, FirstLocation);
767 SetMem16(CommandLineWalker, 12, L' ');
768 StdOutFileName = CommandLineWalker += 6;
769 OutAppend = TRUE;
770 OutUnicode = FALSE;
771 if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {
772 Status = EFI_NOT_FOUND;
773 }
774 }
775 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {
776 FirstLocation = MIN(CommandLineWalker, FirstLocation);
777 SetMem16(CommandLineWalker, 10, L' ');
778 if (StdOutFileName != NULL) {
779 Status = EFI_INVALID_PARAMETER;
780 } else {
781 StdOutFileName = CommandLineWalker += 5;
782 OutAppend = TRUE;
783 }
784 if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {
785 Status = EFI_NOT_FOUND;
786 }
787 }
788 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {
789 FirstLocation = MIN(CommandLineWalker, FirstLocation);
790 SetMem16(CommandLineWalker, 8, L' ');
791 if (StdOutFileName != NULL) {
792 Status = EFI_INVALID_PARAMETER;
793 } else {
794 StdOutFileName = CommandLineWalker += 4;
795 OutAppend = TRUE;
796 }
797 if (StrStr(CommandLineWalker, L" >> ") != NULL) {
798 Status = EFI_NOT_FOUND;
799 }
800 }
801 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {
802 FirstLocation = MIN(CommandLineWalker, FirstLocation);
803 SetMem16(CommandLineWalker, 10, L' ');
804 if (StdOutFileName != NULL) {
805 Status = EFI_INVALID_PARAMETER;
806 } else {
807 StdOutFileName = CommandLineWalker += 5;
808 OutAppend = TRUE;
809 OutUnicode = FALSE;
810 }
811 if (StrStr(CommandLineWalker, L" >>a ") != NULL) {
812 Status = EFI_NOT_FOUND;
813 }
814 }
815 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {
816 FirstLocation = MIN(CommandLineWalker, FirstLocation);
817 SetMem16(CommandLineWalker, 10, L' ');
818 if (StdOutFileName != NULL) {
819 Status = EFI_INVALID_PARAMETER;
820 } else {
821 StdOutFileName = CommandLineWalker += 5;
822 OutAppend = FALSE;
823 OutUnicode = FALSE;
824 }
825 if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {
826 Status = EFI_NOT_FOUND;
827 }
828 }
829 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {
830 FirstLocation = MIN(CommandLineWalker, FirstLocation);
831 SetMem16(CommandLineWalker, 8, L' ');
832 if (StdOutFileName != NULL) {
833 Status = EFI_INVALID_PARAMETER;
834 } else {
835 StdOutFileName = CommandLineWalker += 4;
836 OutAppend = FALSE;
837 OutUnicode = FALSE;
838 }
839 if (StrStr(CommandLineWalker, L" >a ") != NULL) {
840 Status = EFI_NOT_FOUND;
841 }
842 }
843 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {
844 FirstLocation = MIN(CommandLineWalker, FirstLocation);
845 SetMem16(CommandLineWalker, 10, L' ');
846 if (StdErrFileName != NULL) {
847 Status = EFI_INVALID_PARAMETER;
848 } else {
849 StdErrFileName = CommandLineWalker += 5;
850 ErrAppend = TRUE;
851 }
852 if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {
853 Status = EFI_NOT_FOUND;
854 }
855 }
856
857 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {
858 FirstLocation = MIN(CommandLineWalker, FirstLocation);
859 SetMem16(CommandLineWalker, 10, L' ');
860 if (StdErrVarName != NULL) {
861 Status = EFI_INVALID_PARAMETER;
862 } else {
863 StdErrVarName = CommandLineWalker += 5;
864 ErrAppend = FALSE;
865 }
866 if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {
867 Status = EFI_NOT_FOUND;
868 }
869 }
870 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {
871 FirstLocation = MIN(CommandLineWalker, FirstLocation);
872 SetMem16(CommandLineWalker, 10, L' ');
873 if (StdOutVarName != NULL) {
874 Status = EFI_INVALID_PARAMETER;
875 } else {
876 StdOutVarName = CommandLineWalker += 5;
877 OutAppend = FALSE;
878 }
879 if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {
880 Status = EFI_NOT_FOUND;
881 }
882 }
883 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {
884 FirstLocation = MIN(CommandLineWalker, FirstLocation);
885 SetMem16(CommandLineWalker, 10, L' ');
886 if (StdErrFileName != NULL) {
887 Status = EFI_INVALID_PARAMETER;
888 } else {
889 StdErrFileName = CommandLineWalker += 5;
890 ErrAppend = FALSE;
891 ErrUnicode = FALSE;
892 }
893 if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {
894 Status = EFI_NOT_FOUND;
895 }
896 }
897 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {
898 FirstLocation = MIN(CommandLineWalker, FirstLocation);
899 SetMem16(CommandLineWalker, 8, L' ');
900 if (StdErrFileName != NULL) {
901 Status = EFI_INVALID_PARAMETER;
902 } else {
903 StdErrFileName = CommandLineWalker += 4;
904 ErrAppend = FALSE;
905 }
906 if (StrStr(CommandLineWalker, L" 2> ") != NULL) {
907 Status = EFI_NOT_FOUND;
908 }
909 }
910
911 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {
912 FirstLocation = MIN(CommandLineWalker, FirstLocation);
913 SetMem16(CommandLineWalker, 8, L' ');
914 if (StdOutFileName != NULL) {
915 Status = EFI_INVALID_PARAMETER;
916 } else {
917 StdOutFileName = CommandLineWalker += 4;
918 OutAppend = FALSE;
919 }
920 if (StrStr(CommandLineWalker, L" 1> ") != NULL) {
921 Status = EFI_NOT_FOUND;
922 }
923 }
924
925 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {
926 FirstLocation = MIN(CommandLineWalker, FirstLocation);
927 SetMem16(CommandLineWalker, 6, L' ');
928 if (StdOutFileName != NULL) {
929 Status = EFI_INVALID_PARAMETER;
930 } else {
931 StdOutFileName = CommandLineWalker += 3;
932 OutAppend = FALSE;
933 }
934 if (StrStr(CommandLineWalker, L" > ") != NULL) {
935 Status = EFI_NOT_FOUND;
936 }
937 }
938
939 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {
940 FirstLocation = MIN(CommandLineWalker, FirstLocation);
941 SetMem16(CommandLineWalker, 6, L' ');
942 if (StdInFileName != NULL) {
943 Status = EFI_INVALID_PARAMETER;
944 } else {
945 StdInFileName = CommandLineWalker += 3;
946 }
947 if (StrStr(CommandLineWalker, L" < ") != NULL) {
948 Status = EFI_NOT_FOUND;
949 }
950 }
951 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {
952 FirstLocation = MIN(CommandLineWalker, FirstLocation);
953 SetMem16(CommandLineWalker, 8, L' ');
954 if (StdInFileName != NULL) {
955 Status = EFI_INVALID_PARAMETER;
956 } else {
957 StdInFileName = CommandLineWalker += 4;
958 InUnicode = FALSE;
959 }
960 if (StrStr(CommandLineWalker, L" <a ") != NULL) {
961 Status = EFI_NOT_FOUND;
962 }
963 }
964 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {
965 FirstLocation = MIN(CommandLineWalker, FirstLocation);
966 SetMem16(CommandLineWalker, 8, L' ');
967 if (StdInVarName != NULL) {
968 Status = EFI_INVALID_PARAMETER;
969 } else {
970 StdInVarName = CommandLineWalker += 4;
971 }
972 if (StrStr(CommandLineWalker, L" <v ") != NULL) {
973 Status = EFI_NOT_FOUND;
974 }
975 }
976
977 //
978 // re-populate the string to support any filenames that were in quotes.
979 //
980 StrCpy(CommandLineCopy, NewCommandLine);
981
982 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)
983 && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))
984 ){
985 *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;
986 }
987
988 if (!EFI_ERROR(Status)) {
989
990 if (StdErrFileName != NULL) {
991 if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {
992 Status = EFI_INVALID_PARAMETER;
993 }
994 }
995 if (StdOutFileName != NULL) {
996 if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {
997 Status = EFI_INVALID_PARAMETER;
998 }
999 }
1000 if (StdInFileName != NULL) {
1001 if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {
1002 Status = EFI_INVALID_PARAMETER;
1003 }
1004 }
1005 if (StdErrVarName != NULL) {
1006 if ((StdErrVarName = FixVarName(StdErrVarName)) == NULL) {
1007 Status = EFI_INVALID_PARAMETER;
1008 }
1009 }
1010 if (StdOutVarName != NULL) {
1011 if ((StdOutVarName = FixVarName(StdOutVarName)) == NULL) {
1012 Status = EFI_INVALID_PARAMETER;
1013 }
1014 }
1015 if (StdInVarName != NULL) {
1016 if ((StdInVarName = FixVarName(StdInVarName)) == NULL) {
1017 Status = EFI_INVALID_PARAMETER;
1018 }
1019 }
1020
1021 //
1022 // Verify not the same and not duplicating something from a split
1023 //
1024 if (
1025 //
1026 // Check that no 2 filenames are the same
1027 //
1028 (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)
1029 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)
1030 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)
1031 //
1032 // Check that no 2 variable names are the same
1033 //
1034 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)
1035 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)
1036 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)
1037 //
1038 // When a split (using | operator) is in place some are not allowed
1039 //
1040 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))
1041 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))
1042 //
1043 // Check that nothing is trying to be output to 2 locations.
1044 //
1045 ||(StdErrFileName != NULL && StdErrVarName != NULL)
1046 ||(StdOutFileName != NULL && StdOutVarName != NULL)
1047 ||(StdInFileName != NULL && StdInVarName != NULL)
1048 //
1049 // Check for no volatile environment variables
1050 //
1051 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))
1052 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))
1053 //
1054 // Cant redirect during a reconnect operation.
1055 //
1056 ||(StrStr(NewCommandLine, L"connect -r") != NULL
1057 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))
1058 //
1059 // Check that filetypes (Unicode/Ascii) do not change during an append
1060 //
1061 ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName))))
1062 ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName))))
1063 ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))
1064 ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))
1065 ){
1066 Status = EFI_INVALID_PARAMETER;
1067 ShellParameters->StdIn = *OldStdIn;
1068 ShellParameters->StdOut = *OldStdOut;
1069 ShellParameters->StdErr = *OldStdErr;
1070 } else if (!EFI_ERROR(Status)){
1071 //
1072 // Open the Std<Whatever> and we should not have conflicts here...
1073 //
1074
1075 //
1076 // StdErr to a file
1077 //
1078 if (StdErrFileName != NULL) {
1079 if (!ErrAppend) {
1080 //
1081 // delete existing file.
1082 //
1083 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);
1084 }
1085 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);
1086 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {
1087 Status = WriteFileTag (TempHandle);
1088 }
1089 if (!ErrUnicode && !EFI_ERROR(Status)) {
1090 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
1091 ASSERT(TempHandle != NULL);
1092 }
1093 if (!EFI_ERROR(Status)) {
1094 ShellParameters->StdErr = TempHandle;
1095 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);
1096 }
1097 }
1098
1099 //
1100 // StdOut to a file
1101 //
1102 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {
1103 if (!OutAppend) {
1104 //
1105 // delete existing file.
1106 //
1107 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);
1108 }
1109 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);
1110 if (TempHandle == NULL) {
1111 Status = EFI_INVALID_PARAMETER;
1112 } else {
1113 if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {
1114 //no-op
1115 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {
1116 Status = WriteFileTag (TempHandle);
1117 } else if (OutAppend) {
1118 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);
1119 if (!EFI_ERROR(Status)) {
1120 //
1121 // When appending to a new unicode file, write the file tag.
1122 // Otherwise (ie. when appending to a new ASCII file, or an
1123 // existent file with any encoding), just seek to the end.
1124 //
1125 Status = (FileSize == 0 && OutUnicode) ?
1126 WriteFileTag (TempHandle) :
1127 ShellInfoObject.NewEfiShellProtocol->SetFilePosition (
1128 TempHandle,
1129 FileSize);
1130 }
1131 }
1132 if (!OutUnicode && !EFI_ERROR(Status)) {
1133 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
1134 ASSERT(TempHandle != NULL);
1135 }
1136 if (!EFI_ERROR(Status)) {
1137 ShellParameters->StdOut = TempHandle;
1138 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);
1139 }
1140 }
1141 }
1142
1143 //
1144 // StdOut to a var
1145 //
1146 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {
1147 if (!OutAppend) {
1148 //
1149 // delete existing variable.
1150 //
1151 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");
1152 }
1153 TempHandle = CreateFileInterfaceEnv(StdOutVarName);
1154 ASSERT(TempHandle != NULL);
1155 ShellParameters->StdOut = TempHandle;
1156 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);
1157 }
1158
1159 //
1160 // StdErr to a var
1161 //
1162 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {
1163 if (!ErrAppend) {
1164 //
1165 // delete existing variable.
1166 //
1167 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");
1168 }
1169 TempHandle = CreateFileInterfaceEnv(StdErrVarName);
1170 ASSERT(TempHandle != NULL);
1171 ShellParameters->StdErr = TempHandle;
1172 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);
1173 }
1174
1175 //
1176 // StdIn from a var
1177 //
1178 if (!EFI_ERROR(Status) && StdInVarName != NULL) {
1179 TempHandle = CreateFileInterfaceEnv(StdInVarName);
1180 if (TempHandle == NULL) {
1181 Status = EFI_OUT_OF_RESOURCES;
1182 } else {
1183 if (!InUnicode) {
1184 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
1185 }
1186 Size = 0;
1187 if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {
1188 Status = EFI_INVALID_PARAMETER;
1189 } else {
1190 ShellParameters->StdIn = TempHandle;
1191 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);
1192 }
1193 }
1194 }
1195
1196 //
1197 // StdIn from a file
1198 //
1199 if (!EFI_ERROR(Status) && StdInFileName != NULL) {
1200 Status = ShellOpenFileByName(
1201 StdInFileName,
1202 &TempHandle,
1203 EFI_FILE_MODE_READ,
1204 0);
1205 if (InUnicode) {
1206 //
1207 // Chop off the 0xFEFF if it's there...
1208 //
1209 RemoveFileTag(&TempHandle);
1210 } else if (!EFI_ERROR(Status)) {
1211 //
1212 // Create the ASCII->Unicode conversion layer
1213 //
1214 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
1215 }
1216 if (!EFI_ERROR(Status)) {
1217 ShellParameters->StdIn = TempHandle;
1218 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);
1219 }
1220 }
1221 }
1222 }
1223 FreePool(CommandLineCopy);
1224
1225 CalculateEfiHdrCrc(&gST->Hdr);
1226
1227 if (gST->ConIn == NULL ||gST->ConOut == NULL) {
1228 Status = EFI_OUT_OF_RESOURCES;
1229 }
1230
1231 if (Status == EFI_NOT_FOUND) {
1232 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle);
1233 } else if (EFI_ERROR(Status)) {
1234 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);
1235 }
1236
1237 return (Status);
1238 }
1239
1240 /**
1241 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
1242 structure with StdIn and StdOut. The current values are de-allocated.
1243
1244 @param[in, out] ShellParameters Pointer to parameter structure to modify.
1245 @param[in] OldStdIn Pointer to old StdIn.
1246 @param[in] OldStdOut Pointer to old StdOut.
1247 @param[in] OldStdErr Pointer to old StdErr.
1248 @param[in] SystemTableInfo Pointer to old system table information.
1249 **/
1250 EFI_STATUS
1251 EFIAPI
1252 RestoreStdInStdOutStdErr (
1253 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
1254 IN SHELL_FILE_HANDLE *OldStdIn,
1255 IN SHELL_FILE_HANDLE *OldStdOut,
1256 IN SHELL_FILE_HANDLE *OldStdErr,
1257 IN SYSTEM_TABLE_INFO *SystemTableInfo
1258 )
1259 {
1260 SPLIT_LIST *Split;
1261
1262 if (ShellParameters == NULL
1263 ||OldStdIn == NULL
1264 ||OldStdOut == NULL
1265 ||OldStdErr == NULL
1266 ||SystemTableInfo == NULL) {
1267 return (EFI_INVALID_PARAMETER);
1268 }
1269 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {
1270 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);
1271 } else {
1272 Split = NULL;
1273 }
1274 if (ShellParameters->StdIn != *OldStdIn) {
1275 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {
1276 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);
1277 }
1278 ShellParameters->StdIn = *OldStdIn;
1279 }
1280 if (ShellParameters->StdOut != *OldStdOut) {
1281 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {
1282 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);
1283 }
1284 ShellParameters->StdOut = *OldStdOut;
1285 }
1286 if (ShellParameters->StdErr != *OldStdErr) {
1287 gEfiShellProtocol->CloseFile(ShellParameters->StdErr);
1288 ShellParameters->StdErr = *OldStdErr;
1289 }
1290
1291 if (gST->ConIn != SystemTableInfo->ConIn) {
1292 CloseSimpleTextInOnFile(gST->ConIn);
1293 gST->ConIn = SystemTableInfo->ConIn;
1294 gST->ConsoleInHandle = SystemTableInfo->ConInHandle;
1295 }
1296 if (gST->ConOut != SystemTableInfo->ConOut) {
1297 CloseSimpleTextOutOnFile(gST->ConOut);
1298 gST->ConOut = SystemTableInfo->ConOut;
1299 gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;
1300 }
1301 if (gST->StdErr != SystemTableInfo->ErrOut) {
1302 CloseSimpleTextOutOnFile(gST->StdErr);
1303 gST->StdErr = SystemTableInfo->ErrOut;
1304 gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle;
1305 }
1306
1307 CalculateEfiHdrCrc(&gST->Hdr);
1308
1309 return (EFI_SUCCESS);
1310 }
1311 /**
1312 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1313 structure by parsing NewCommandLine. The current values are returned to the
1314 user.
1315
1316 If OldArgv or OldArgc is NULL then that value is not returned.
1317
1318 @param[in, out] ShellParameters Pointer to parameter structure to modify.
1319 @param[in] NewCommandLine The new command line to parse and use.
1320 @param[out] OldArgv Pointer to old list of parameters.
1321 @param[out] OldArgc Pointer to old number of items in Argv list.
1322
1323 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
1324 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1325 **/
1326 EFI_STATUS
1327 EFIAPI
1328 UpdateArgcArgv(
1329 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
1330 IN CONST CHAR16 *NewCommandLine,
1331 OUT CHAR16 ***OldArgv OPTIONAL,
1332 OUT UINTN *OldArgc OPTIONAL
1333 )
1334 {
1335 ASSERT(ShellParameters != NULL);
1336
1337 if (OldArgc != NULL) {
1338 *OldArgc = ShellParameters->Argc;
1339 }
1340 if (OldArgc != NULL) {
1341 *OldArgv = ShellParameters->Argv;
1342 }
1343
1344 return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));
1345 }
1346
1347 /**
1348 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1349 structure with Argv and Argc. The current values are de-allocated and the
1350 OldArgv must not be deallocated by the caller.
1351
1352 @param[in, out] ShellParameters pointer to parameter structure to modify
1353 @param[in] OldArgv pointer to old list of parameters
1354 @param[in] OldArgc pointer to old number of items in Argv list
1355 **/
1356 VOID
1357 EFIAPI
1358 RestoreArgcArgv(
1359 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
1360 IN CHAR16 ***OldArgv,
1361 IN UINTN *OldArgc
1362 )
1363 {
1364 UINTN LoopCounter;
1365 ASSERT(ShellParameters != NULL);
1366 ASSERT(OldArgv != NULL);
1367 ASSERT(OldArgc != NULL);
1368
1369 if (ShellParameters->Argv != NULL) {
1370 for ( LoopCounter = 0
1371 ; LoopCounter < ShellParameters->Argc
1372 ; LoopCounter++
1373 ){
1374 FreePool(ShellParameters->Argv[LoopCounter]);
1375 }
1376 FreePool(ShellParameters->Argv);
1377 }
1378 ShellParameters->Argv = *OldArgv;
1379 *OldArgv = NULL;
1380 ShellParameters->Argc = *OldArgc;
1381 *OldArgc = 0;
1382 }