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