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