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