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