]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Application/Shell/ShellParametersProtocol.c
udk2010.up2.shell initial release.
[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 - 2010, 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
18 /**
19 return the next parameter from a command line string;
20
21 This function moves the next parameter from Walker into TempParameter and moves
22 Walker up past that parameter for recursive calling. When the final parameter
23 is moved *Walker will be set to NULL;
24
25 Temp Parameter must be large enough to hold the parameter before calling this
26 function.
27
28 @param[in,out] Walker pointer to string of command line. Adjusted to
29 reminaing command line on return
30 @param[in,out] TempParameter pointer to string of command line item extracted.
31
32 **/
33 VOID
34 EFIAPI
35 GetNextParameter(
36 CHAR16 **Walker,
37 CHAR16 **TempParameter
38 )
39 {
40 CHAR16 *NextDelim;
41 CHAR16 *TempLoc;
42
43 ASSERT(Walker != NULL);
44 ASSERT(*Walker != NULL);
45 ASSERT(TempParameter != NULL);
46 ASSERT(*TempParameter != NULL);
47
48 //
49 // make sure we dont have any leading spaces
50 //
51 while ((*Walker)[0] == L' ') {
52 (*Walker)++;
53 }
54
55 //
56 // make sure we still have some params now...
57 //
58 if (StrLen(*Walker) == 0) {
59 ASSERT((*Walker)[0] == CHAR_NULL);
60 *Walker = NULL;
61 return;
62 }
63
64 //
65 // we have a quoted parameter
66 // could be the last parameter, but SHOULD have a trailing quote
67 //
68 if ((*Walker)[0] == L'\"') {
69 NextDelim = NULL;
70 for (TempLoc = *Walker + 1 ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {
71 if (*TempLoc == L'^' && *(TempLoc+1) == L'^') {
72 TempLoc++;
73 } else if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {
74 TempLoc++;
75 } else if (*TempLoc == L'^' && *(TempLoc+1) == L'|') {
76 TempLoc++;
77 } else if (*TempLoc == L'^') {
78 *TempLoc = L' ';
79 } else if (*TempLoc == L'\"') {
80 NextDelim = TempLoc;
81 break;
82 }
83 }
84
85 if (NextDelim - ((*Walker)+1) == 0) {
86 //
87 // found ""
88 //
89 StrCpy(*TempParameter, L"");
90 *Walker = NextDelim + 1;
91 } else if (NextDelim != NULL) {
92 StrnCpy(*TempParameter, (*Walker)+1, NextDelim - ((*Walker)+1));
93 *Walker = NextDelim + 1;
94 } else {
95 //
96 // last one... someone forgot the training quote!
97 //
98 StrCpy(*TempParameter, *Walker);
99 *Walker = NULL;
100 }
101 for (TempLoc = *TempParameter ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {
102 if ((*TempLoc == L'^' && *(TempLoc+1) == L'^')
103 || (*TempLoc == L'^' && *(TempLoc+1) == L'|')
104 || (*TempLoc == L'^' && *(TempLoc+1) == L'\"')
105 ){
106 CopyMem(TempLoc, TempLoc+1, StrSize(TempLoc) - sizeof(TempLoc[0]));
107 }
108 }
109 } else {
110 //
111 // we have a regular parameter (no quote) OR
112 // we have the final parameter (no trailing space)
113 //
114 NextDelim = StrStr((*Walker), L" ");
115 if (NextDelim != NULL) {
116 StrnCpy(*TempParameter, *Walker, NextDelim - (*Walker));
117 (*TempParameter)[NextDelim - (*Walker)] = CHAR_NULL;
118 *Walker = NextDelim+1;
119 } else {
120 //
121 // last one.
122 //
123 StrCpy(*TempParameter, *Walker);
124 *Walker = NULL;
125 }
126 for (NextDelim = *TempParameter ; NextDelim != NULL && *NextDelim != CHAR_NULL ; NextDelim++) {
127 if (*NextDelim == L'^' && *(NextDelim+1) == L'^') {
128 CopyMem(NextDelim, NextDelim+1, StrSize(NextDelim) - sizeof(NextDelim[0]));
129 } else if (*NextDelim == L'^') {
130 *NextDelim = L' ';
131 }
132 }
133 while ((*TempParameter)[StrLen(*TempParameter)-1] == L' ') {
134 (*TempParameter)[StrLen(*TempParameter)-1] = CHAR_NULL;
135 }
136 while ((*TempParameter)[0] == L' ') {
137 CopyMem(*TempParameter, (*TempParameter)+1, StrSize(*TempParameter) - sizeof((*TempParameter)[0]));
138 }
139 }
140 return;
141 }
142
143 /**
144 function to populate Argc and Argv.
145
146 This function parses the CommandLine and divides it into standard C style Argc/Argv
147 parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space
148 delimited and quote surrounded parameter definition.
149
150 @param[in] CommandLine String of command line to parse
151 @param[in,out] Argv pointer to array of strings; one for each parameter
152 @param[in,out] Argc pointer to number of strings in Argv array
153
154 @return EFI_SUCCESS the operation was sucessful
155 @return EFI_OUT_OF_RESOURCES a memory allocation failed.
156 **/
157 EFI_STATUS
158 EFIAPI
159 ParseCommandLineToArgs(
160 IN CONST CHAR16 *CommandLine,
161 IN OUT CHAR16 ***Argv,
162 IN OUT UINTN *Argc
163 )
164 {
165 UINTN Count;
166 CHAR16 *TempParameter;
167 CHAR16 *Walker;
168 CHAR16 *NewParam;
169 UINTN Size;
170
171 ASSERT(Argc != NULL);
172 ASSERT(Argv != NULL);
173
174 if (CommandLine == NULL || StrLen(CommandLine)==0) {
175 (*Argc) = 0;
176 (*Argv) = NULL;
177 return (EFI_SUCCESS);
178 }
179
180 Size = StrSize(CommandLine);
181 TempParameter = AllocateZeroPool(Size);
182 if (TempParameter == NULL) {
183 return (EFI_OUT_OF_RESOURCES);
184 }
185
186 for ( Count = 0
187 , Walker = (CHAR16*)CommandLine
188 ; Walker != NULL && *Walker != CHAR_NULL
189 ; GetNextParameter(&Walker, &TempParameter)
190 , Count++
191 );
192
193 /* Count = 0;
194 Walker = (CHAR16*)CommandLine;
195 while(Walker != NULL) {
196 GetNextParameter(&Walker, &TempParameter);
197 Count++;
198 }
199 */
200 //
201 // lets allocate the pointer array
202 //
203 (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*));
204 if (*Argv == NULL) {
205 return (EFI_OUT_OF_RESOURCES);
206 }
207
208 *Argc = 0;
209 Walker = (CHAR16*)CommandLine;
210 while(Walker != NULL && *Walker != CHAR_NULL) {
211 SetMem16(TempParameter, Size, CHAR_NULL);
212 GetNextParameter(&Walker, &TempParameter);
213 NewParam = AllocateZeroPool(StrSize(TempParameter));
214 ASSERT(NewParam != NULL);
215 StrCpy(NewParam, TempParameter);
216 ((CHAR16**)(*Argv))[(*Argc)] = NewParam;
217 (*Argc)++;
218 }
219 ASSERT(Count >= (*Argc));
220 return (EFI_SUCCESS);
221 }
222
223 /**
224 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then
225 installs it on our handle and if there is an existing version of the protocol
226 that one is cached for removal later.
227
228 @param[in,out] NewShellParameters on a successful return, a pointer to pointer
229 to the newly installed interface.
230 @param[in,out] RootShellInstance on a successful return, pointer to boolean.
231 TRUE if this is the root shell instance.
232
233 @retval EFI_SUCCESS the operation completed successfully.
234 @return other the operation failed.
235 @sa ReinstallProtocolInterface
236 @sa InstallProtocolInterface
237 @sa ParseCommandLineToArgs
238 **/
239 EFI_STATUS
240 EFIAPI
241 CreatePopulateInstallShellParametersProtocol (
242 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters,
243 IN OUT BOOLEAN *RootShellInstance
244 )
245 {
246 EFI_STATUS Status;
247 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
248 CHAR16 *FullCommandLine;
249 UINTN Size;
250
251 Size = 0;
252 FullCommandLine = NULL;
253 LoadedImage = NULL;
254
255 //
256 // Assert for valid parameters
257 //
258 ASSERT(NewShellParameters != NULL);
259 ASSERT(RootShellInstance != NULL);
260
261 //
262 // See if we have a shell parameters placed on us
263 //
264 Status = gBS->OpenProtocol (
265 gImageHandle,
266 &gEfiShellParametersProtocolGuid,
267 (VOID **) &ShellInfoObject.OldShellParameters,
268 gImageHandle,
269 NULL,
270 EFI_OPEN_PROTOCOL_GET_PROTOCOL
271 );
272 //
273 // if we don't then we must be the root shell (error is expected)
274 //
275 if (EFI_ERROR (Status)) {
276 *RootShellInstance = TRUE;
277 }
278
279 //
280 // Allocate the new structure
281 //
282 *NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));
283 ASSERT(NewShellParameters != NULL);
284
285 //
286 // get loaded image protocol
287 //
288 Status = gBS->OpenProtocol (
289 gImageHandle,
290 &gEfiLoadedImageProtocolGuid,
291 (VOID **) &LoadedImage,
292 gImageHandle,
293 NULL,
294 EFI_OPEN_PROTOCOL_GET_PROTOCOL
295 );
296 ASSERT_EFI_ERROR(Status);
297 //
298 // Build the full command line
299 //
300 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);
301 if (Status == EFI_BUFFER_TOO_SMALL) {
302 FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);
303 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);
304 }
305 if (Status == EFI_NOT_FOUND) {
306 //
307 // no parameters via environment... ok
308 //
309 } else {
310 ASSERT_EFI_ERROR(Status);
311 }
312 if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {
313 //
314 // Now we need to include a NULL terminator in the size.
315 //
316 Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]);
317 FullCommandLine = AllocateZeroPool(Size);
318 }
319 if (LoadedImage->LoadOptionsSize != 0){
320 StrCpy(FullCommandLine, LoadedImage->LoadOptions);
321 }
322 if (FullCommandLine != NULL) {
323 //
324 // Populate Argc and Argv
325 //
326 Status = ParseCommandLineToArgs(FullCommandLine,
327 &(*NewShellParameters)->Argv,
328 &(*NewShellParameters)->Argc);
329
330 FreePool(FullCommandLine);
331
332 ASSERT_EFI_ERROR(Status);
333 } else {
334 (*NewShellParameters)->Argv = NULL;
335 (*NewShellParameters)->Argc = 0;
336 }
337
338 //
339 // Populate the 3 faked file systems...
340 //
341 if (*RootShellInstance) {
342 (*NewShellParameters)->StdIn = &FileInterfaceStdIn;
343 (*NewShellParameters)->StdOut = &FileInterfaceStdOut;
344 (*NewShellParameters)->StdErr = &FileInterfaceStdErr;
345 Status = gBS->InstallProtocolInterface(&gImageHandle,
346 &gEfiShellParametersProtocolGuid,
347 EFI_NATIVE_INTERFACE,
348 (VOID*)(*NewShellParameters));
349 } else {
350 //
351 // copy from the existing ones
352 //
353 (*NewShellParameters)->StdIn = ShellInfoObject.OldShellParameters->StdIn;
354 (*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut;
355 (*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr;
356 Status = gBS->ReinstallProtocolInterface(gImageHandle,
357 &gEfiShellParametersProtocolGuid,
358 (VOID*)ShellInfoObject.OldShellParameters,
359 (VOID*)(*NewShellParameters));
360 }
361
362 return (Status);
363 }
364
365 /**
366 frees all memory used by createion and installation of shell parameters protocol
367 and if there was an old version installed it will restore that one.
368
369 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is
370 being cleaned up.
371
372 @retval EFI_SUCCESS the cleanup was successful
373 @return other the cleanup failed
374 @sa ReinstallProtocolInterface
375 @sa UninstallProtocolInterface
376 **/
377 EFI_STATUS
378 EFIAPI
379 CleanUpShellParametersProtocol (
380 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters
381 )
382 {
383 EFI_STATUS Status;
384 UINTN LoopCounter;
385
386 //
387 // If the old exists we need to restore it
388 //
389 if (ShellInfoObject.OldShellParameters != NULL) {
390 Status = gBS->ReinstallProtocolInterface(gImageHandle,
391 &gEfiShellParametersProtocolGuid,
392 (VOID*)NewShellParameters,
393 (VOID*)ShellInfoObject.OldShellParameters);
394 DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;);
395 } else {
396 //
397 // No old one, just uninstall us...
398 //
399 Status = gBS->UninstallProtocolInterface(gImageHandle,
400 &gEfiShellParametersProtocolGuid,
401 (VOID*)NewShellParameters);
402 }
403 if (NewShellParameters->Argv != NULL) {
404 for ( LoopCounter = 0
405 ; LoopCounter < NewShellParameters->Argc
406 ; LoopCounter++
407 ){
408 FreePool(NewShellParameters->Argv[LoopCounter]);
409 }
410 FreePool(NewShellParameters->Argv);
411 }
412 FreePool(NewShellParameters);
413 return (Status);
414 }
415
416 /**
417 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
418 structure by parsing NewCommandLine. The current values are returned to the
419 user.
420
421 If OldStdIn or OldStdOut is NULL then that value is not returned.
422
423 @param[in,out] ShellParameters Pointer to parameter structure to modify.
424 @param[in] NewCommandLine The new command line to parse and use.
425 @param[out] OldStdIn Pointer to old StdIn.
426 @param[out] OldStdOut Pointer to old StdOut.
427 @param[out] OldStdErr Pointer to old StdErr.
428
429 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
430 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
431 **/
432 EFI_STATUS
433 EFIAPI
434 UpdateStdInStdOutStdErr(
435 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
436 IN CONST CHAR16 *NewCommandLine,
437 OUT SHELL_FILE_HANDLE *OldStdIn,
438 OUT SHELL_FILE_HANDLE *OldStdOut,
439 OUT SHELL_FILE_HANDLE *OldStdErr
440 )
441 {
442 CHAR16 *CommandLineCopy;
443 CHAR16 *CommandLineWalker;
444 CHAR16 *StdErrFileName;
445 CHAR16 *StdOutFileName;
446 CHAR16 *StdInFileName;
447 CHAR16 *StdInVarName;
448 CHAR16 *StdOutVarName;
449 CHAR16 *StdErrVarName;
450 EFI_STATUS Status;
451 SHELL_FILE_HANDLE TempHandle;
452 UINT64 FileSize;
453 BOOLEAN OutUnicode;
454 BOOLEAN InUnicode;
455 BOOLEAN ErrUnicode;
456 BOOLEAN OutAppend;
457 BOOLEAN ErrAppend;
458 UINTN Size;
459 CHAR16 TagBuffer[2];
460 SPLIT_LIST *Split;
461
462 ASSERT(ShellParameters != NULL);
463 OutUnicode = TRUE;
464 InUnicode = TRUE;
465 ErrUnicode = TRUE;
466 StdInVarName = NULL;
467 StdOutVarName = NULL;
468 StdErrVarName = NULL;
469 StdErrFileName = NULL;
470 StdInFileName = NULL;
471 StdOutFileName = NULL;
472 ErrAppend = FALSE;
473 OutAppend = FALSE;
474 CommandLineCopy = NULL;
475
476 if (OldStdIn != NULL) {
477 *OldStdIn = ShellParameters->StdIn;
478 }
479 if (OldStdOut != NULL) {
480 *OldStdOut = ShellParameters->StdOut;
481 }
482 if (OldStdErr != NULL) {
483 *OldStdErr = ShellParameters->StdErr;
484 }
485
486 if (NewCommandLine == NULL) {
487 return (EFI_SUCCESS);
488 }
489
490 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);
491 Status = EFI_SUCCESS;
492 Split = NULL;
493
494 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {
495 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);
496 if (Split != NULL && Split->SplitStdIn != NULL) {
497 ShellParameters->StdIn = Split->SplitStdIn;
498 }
499 if (Split != NULL && Split->SplitStdOut != NULL) {
500 ShellParameters->StdOut = Split->SplitStdOut;
501 }
502 }
503
504 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {
505 StdErrVarName = CommandLineWalker += 6;
506 ErrAppend = TRUE;
507 }
508 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {
509 StdOutVarName = CommandLineWalker += 6;
510 OutAppend = TRUE;
511 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {
512 StdOutVarName = CommandLineWalker += 5;
513 OutAppend = TRUE;
514 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {
515 StdOutVarName = CommandLineWalker += 4;
516 OutAppend = FALSE;
517 }
518 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {
519 StdOutFileName = CommandLineWalker += 6;
520 OutAppend = TRUE;
521 OutUnicode = FALSE;
522 }
523 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {
524 if (StdOutFileName != NULL) {
525 Status = EFI_INVALID_PARAMETER;
526 } else {
527 StdOutFileName = CommandLineWalker += 5;
528 OutAppend = TRUE;
529 }
530 }
531 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {
532 if (StdOutFileName != NULL) {
533 Status = EFI_INVALID_PARAMETER;
534 } else {
535 StdOutFileName = CommandLineWalker += 4;
536 OutAppend = TRUE;
537 }
538 }
539 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {
540 if (StdOutFileName != NULL) {
541 Status = EFI_INVALID_PARAMETER;
542 } else {
543 StdOutFileName = CommandLineWalker += 5;
544 OutAppend = TRUE;
545 OutUnicode = FALSE;
546 }
547 }
548 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {
549 if (StdOutFileName != NULL) {
550 Status = EFI_INVALID_PARAMETER;
551 } else {
552 StdOutFileName = CommandLineWalker += 5;
553 OutAppend = FALSE;
554 OutUnicode = FALSE;
555 }
556 }
557 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {
558 if (StdOutFileName != NULL) {
559 Status = EFI_INVALID_PARAMETER;
560 } else {
561 StdOutFileName = CommandLineWalker += 4;
562 OutAppend = FALSE;
563 OutUnicode = FALSE;
564 }
565 }
566 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {
567 if (StdErrFileName != NULL) {
568 Status = EFI_INVALID_PARAMETER;
569 } else {
570 StdErrFileName = CommandLineWalker += 5;
571 ErrAppend = TRUE;
572 }
573 }
574
575 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {
576 if (StdErrVarName != NULL) {
577 Status = EFI_INVALID_PARAMETER;
578 } else {
579 StdErrVarName = CommandLineWalker += 5;
580 ErrAppend = FALSE;
581 }
582 }
583 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {
584 if (StdOutVarName != NULL) {
585 Status = EFI_INVALID_PARAMETER;
586 } else {
587 StdOutVarName = CommandLineWalker += 5;
588 OutAppend = FALSE;
589 }
590 }
591 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {
592 if (StdErrFileName != NULL) {
593 Status = EFI_INVALID_PARAMETER;
594 } else {
595 StdErrFileName = CommandLineWalker += 5;
596 ErrAppend = FALSE;
597 ErrUnicode = FALSE;
598 }
599 }
600 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {
601 if (StdErrFileName != NULL) {
602 Status = EFI_INVALID_PARAMETER;
603 } else {
604 StdErrFileName = CommandLineWalker += 4;
605 ErrAppend = FALSE;
606 }
607 }
608
609 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {
610 if (StdOutFileName != NULL) {
611 Status = EFI_INVALID_PARAMETER;
612 } else {
613 StdOutFileName = CommandLineWalker += 4;
614 OutAppend = FALSE;
615 }
616 }
617
618 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {
619 if (StdOutFileName != NULL) {
620 Status = EFI_INVALID_PARAMETER;
621 } else {
622 StdOutFileName = CommandLineWalker += 3;
623 OutAppend = FALSE;
624 }
625 }
626
627 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {
628 if (StdInFileName != NULL) {
629 Status = EFI_INVALID_PARAMETER;
630 } else {
631 StdInFileName = CommandLineWalker += 3;
632 OutAppend = FALSE;
633 }
634 }
635 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {
636 if (StdInFileName != NULL) {
637 Status = EFI_INVALID_PARAMETER;
638 } else {
639 StdInFileName = CommandLineWalker += 4;
640 OutAppend = FALSE;
641 }
642 }
643 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {
644 if (StdInVarName != NULL) {
645 Status = EFI_INVALID_PARAMETER;
646 } else {
647 StdInVarName = CommandLineWalker += 4;
648 OutAppend = FALSE;
649 }
650 }
651
652 if (!EFI_ERROR(Status)) {
653 if (StdErrFileName != NULL && (CommandLineWalker = StrStr(StdErrFileName, L" ")) != NULL) {
654 CommandLineWalker[0] = CHAR_NULL;
655 }
656 if (StdOutFileName != NULL && (CommandLineWalker = StrStr(StdOutFileName, L" ")) != NULL) {
657 CommandLineWalker[0] = CHAR_NULL;
658 }
659 if (StdInFileName != NULL && (CommandLineWalker = StrStr(StdInFileName , L" ")) != NULL) {
660 CommandLineWalker[0] = CHAR_NULL;
661 }
662 if (StdErrVarName != NULL && (CommandLineWalker = StrStr(StdErrVarName , L" ")) != NULL) {
663 CommandLineWalker[0] = CHAR_NULL;
664 }
665 if (StdOutVarName != NULL && (CommandLineWalker = StrStr(StdOutVarName , L" ")) != NULL) {
666 CommandLineWalker[0] = CHAR_NULL;
667 }
668 if (StdInVarName != NULL && (CommandLineWalker = StrStr(StdInVarName , L" ")) != NULL) {
669 CommandLineWalker[0] = CHAR_NULL;
670 }
671
672 //
673 // Verify not the same and not duplicating something from a split
674 //
675 if ((StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)
676 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)
677 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)
678 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)
679 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)
680 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)
681 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))
682 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))
683 ||(StdErrFileName != NULL && StdErrVarName != NULL)
684 ||(StdOutFileName != NULL && StdOutVarName != NULL)
685 ||(StdInFileName != NULL && StdInVarName != NULL)
686 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))
687 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))
688 ){
689 Status = EFI_INVALID_PARAMETER;
690 } else {
691 //
692 // Open the Std<Whatever> and we should not have conflicts here...
693 //
694
695 //
696 // StdErr to a file
697 //
698 if (StdErrFileName != NULL) {
699 if (!ErrAppend) {
700 //
701 // delete existing file.
702 //
703 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);
704 }
705 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);
706 ASSERT(TempHandle != NULL);
707 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {
708 //
709 // Write out the UnicodeFileTag
710 //
711 Size = sizeof(CHAR16);
712 TagBuffer[0] = UnicodeFileTag;
713 TagBuffer[1] = CHAR_NULL;
714 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);
715 }
716 if (!ErrUnicode && !EFI_ERROR(Status)) {
717 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
718 ASSERT(TempHandle != NULL);
719 }
720 if (!EFI_ERROR(Status)) {
721 ShellParameters->StdErr = TempHandle;
722 }
723 }
724
725 //
726 // StdOut to a file
727 //
728 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {
729 if (!OutAppend) {
730 //
731 // delete existing file.
732 //
733 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);
734 }
735 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);
736 ASSERT(TempHandle != NULL);
737 if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {
738 //
739 // Write out the UnicodeFileTag
740 //
741 Size = sizeof(CHAR16);
742 TagBuffer[0] = UnicodeFileTag;
743 TagBuffer[1] = CHAR_NULL;
744 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);
745 } else if (OutAppend) {
746 //
747 // Move to end of file
748 //
749 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);
750 if (!EFI_ERROR(Status)) {
751 Status = ShellInfoObject.NewEfiShellProtocol->SetFilePosition(TempHandle, FileSize);
752 }
753 }
754 if (!OutUnicode && !EFI_ERROR(Status)) {
755 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
756 ASSERT(TempHandle != NULL);
757 }
758 if (!EFI_ERROR(Status)) {
759 ShellParameters->StdOut = TempHandle;
760 }
761 }
762
763 //
764 // StdOut to a var
765 //
766 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {
767 if (!OutAppend) {
768 //
769 // delete existing variable.
770 //
771 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");
772 }
773 TempHandle = CreateFileInterfaceEnv(StdOutVarName);
774 ASSERT(TempHandle != NULL);
775 if (!OutUnicode) {
776 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
777 ASSERT(TempHandle != NULL);
778 }
779 ShellParameters->StdOut = TempHandle;
780 }
781
782 //
783 // StdErr to a var
784 //
785 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {
786 if (!ErrAppend) {
787 //
788 // delete existing variable.
789 //
790 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");
791 }
792 TempHandle = CreateFileInterfaceEnv(StdErrVarName);
793 ASSERT(TempHandle != NULL);
794 if (!ErrUnicode) {
795 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
796 ASSERT(TempHandle != NULL);
797 }
798 ShellParameters->StdErr = TempHandle;
799 }
800
801 //
802 // StdIn from a var
803 //
804 if (!EFI_ERROR(Status) && StdInVarName != NULL) {
805 TempHandle = CreateFileInterfaceEnv(StdInVarName);
806 if (!InUnicode) {
807 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
808 }
809 Size = 0;
810 ASSERT(TempHandle != NULL);
811 if (((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {
812 Status = EFI_INVALID_PARAMETER;
813 } else {
814 ShellParameters->StdIn = TempHandle;
815 }
816 }
817
818 //
819 // StdIn from a file
820 //
821 if (!EFI_ERROR(Status) && StdInFileName != NULL) {
822 Status = ShellOpenFileByName(
823 StdInFileName,
824 &TempHandle,
825 EFI_FILE_MODE_READ,
826 0);
827 if (!InUnicode && !EFI_ERROR(Status)) {
828 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
829 }
830 if (!EFI_ERROR(Status)) {
831 ShellParameters->StdIn = TempHandle;
832 }
833 }
834 }
835 }
836 FreePool(CommandLineCopy);
837 return (Status);
838 }
839
840 /**
841 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
842 structure with StdIn and StdOut. The current values are de-allocated.
843
844 @param[in,out] ShellParameters pointer to parameter structure to modify
845 @param[out] OldStdIn Pointer to old StdIn.
846 @param[out] OldStdOut Pointer to old StdOut.
847 @param[out] OldStdErr Pointer to old StdErr.
848 **/
849 EFI_STATUS
850 EFIAPI
851 RestoreStdInStdOutStdErr (
852 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
853 OUT SHELL_FILE_HANDLE *OldStdIn OPTIONAL,
854 OUT SHELL_FILE_HANDLE *OldStdOut OPTIONAL,
855 OUT SHELL_FILE_HANDLE *OldStdErr OPTIONAL
856 )
857 {
858 SPLIT_LIST *Split;
859 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {
860 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);
861 } else {
862 Split = NULL;
863 }
864 if (OldStdIn != NULL && ShellParameters->StdIn != *OldStdIn) {
865 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {
866 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);
867 }
868 ShellParameters->StdIn = OldStdIn==NULL?NULL:*OldStdIn;
869 }
870 if (OldStdOut != NULL && ShellParameters->StdOut != *OldStdOut) {
871 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {
872 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);
873 }
874 ShellParameters->StdOut = OldStdOut==NULL?NULL:*OldStdOut;
875 }
876 return (EFI_SUCCESS);
877 }
878 /**
879 Funcion will replace the current Argc and Argv in the ShellParameters protocol
880 structure by parsing NewCommandLine. The current values are returned to the
881 user.
882
883 If OldArgv or OldArgc is NULL then that value is not returned.
884
885 @param[in,out] ShellParameters Pointer to parameter structure to modify.
886 @param[in] NewCommandLine The new command line to parse and use.
887 @param[out] OldArgv Pointer to old list of parameters.
888 @param[out] OldArgc Pointer to old number of items in Argv list.
889
890 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
891 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
892 **/
893 EFI_STATUS
894 EFIAPI
895 UpdateArgcArgv(
896 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
897 IN CONST CHAR16 *NewCommandLine,
898 OUT CHAR16 ***OldArgv OPTIONAL,
899 OUT UINTN *OldArgc OPTIONAL
900 )
901 {
902 ASSERT(ShellParameters != NULL);
903
904 if (OldArgc != NULL) {
905 *OldArgc = ShellParameters->Argc;
906 }
907 if (OldArgc != NULL) {
908 *OldArgv = ShellParameters->Argv;
909 }
910
911 return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));
912 }
913
914 /**
915 Funcion will replace the current Argc and Argv in the ShellParameters protocol
916 structure with Argv and Argc. The current values are de-allocated and the
917 OldArgv must not be deallocated by the caller.
918
919 @param[in,out] ShellParameters pointer to parameter structure to modify
920 @param[in] OldArgv pointer to old list of parameters
921 @param[in] OldArgc pointer to old number of items in Argv list
922 **/
923 VOID
924 EFIAPI
925 RestoreArgcArgv(
926 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
927 IN CHAR16 ***OldArgv,
928 IN UINTN *OldArgc
929 )
930 {
931 UINTN LoopCounter;
932 ASSERT(ShellParameters != NULL);
933 ASSERT(OldArgv != NULL);
934 ASSERT(OldArgc != NULL);
935
936 if (ShellParameters->Argv != NULL) {
937 for ( LoopCounter = 0
938 ; LoopCounter < ShellParameters->Argc
939 ; LoopCounter++
940 ){
941 FreePool(ShellParameters->Argv[LoopCounter]);
942 }
943 FreePool(ShellParameters->Argv);
944 }
945 ShellParameters->Argv = *OldArgv;
946 *OldArgv = NULL;
947 ShellParameters->Argc = *OldArgc;
948 *OldArgc = 0;
949 }