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