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