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