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