]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Application/Shell/ShellParametersProtocol.c
1) Removing ASSERTs for proper return values.
[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 if ((*NewShellParameters) == NULL) {
284 return (EFI_OUT_OF_RESOURCES);
285 }
286
287 //
288 // get loaded image protocol
289 //
290 Status = gBS->OpenProtocol (
291 gImageHandle,
292 &gEfiLoadedImageProtocolGuid,
293 (VOID **) &LoadedImage,
294 gImageHandle,
295 NULL,
296 EFI_OPEN_PROTOCOL_GET_PROTOCOL
297 );
298 ASSERT_EFI_ERROR(Status);
299 //
300 // Build the full command line
301 //
302 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);
303 if (Status == EFI_BUFFER_TOO_SMALL) {
304 FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);
305 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);
306 }
307 if (Status == EFI_NOT_FOUND) {
308 //
309 // no parameters via environment... ok
310 //
311 } else {
312 if (EFI_ERROR(Status)) {
313 return (Status);
314 }
315 }
316 if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {
317 ASSERT(FullCommandLine == NULL);
318 //
319 // Now we need to include a NULL terminator in the size.
320 //
321 Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]);
322 FullCommandLine = AllocateZeroPool(Size);
323 }
324 if (FullCommandLine != NULL) {
325 if (LoadedImage->LoadOptionsSize != 0){
326 StrCpy(FullCommandLine, LoadedImage->LoadOptions);
327 }
328 //
329 // Populate Argc and Argv
330 //
331 Status = ParseCommandLineToArgs(FullCommandLine,
332 &(*NewShellParameters)->Argv,
333 &(*NewShellParameters)->Argc);
334
335 FreePool(FullCommandLine);
336
337 ASSERT_EFI_ERROR(Status);
338 } else {
339 (*NewShellParameters)->Argv = NULL;
340 (*NewShellParameters)->Argc = 0;
341 }
342
343 //
344 // Populate the 3 faked file systems...
345 //
346 if (*RootShellInstance) {
347 (*NewShellParameters)->StdIn = &FileInterfaceStdIn;
348 (*NewShellParameters)->StdOut = &FileInterfaceStdOut;
349 (*NewShellParameters)->StdErr = &FileInterfaceStdErr;
350 Status = gBS->InstallProtocolInterface(&gImageHandle,
351 &gEfiShellParametersProtocolGuid,
352 EFI_NATIVE_INTERFACE,
353 (VOID*)(*NewShellParameters));
354 } else {
355 //
356 // copy from the existing ones
357 //
358 (*NewShellParameters)->StdIn = ShellInfoObject.OldShellParameters->StdIn;
359 (*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut;
360 (*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr;
361 Status = gBS->ReinstallProtocolInterface(gImageHandle,
362 &gEfiShellParametersProtocolGuid,
363 (VOID*)ShellInfoObject.OldShellParameters,
364 (VOID*)(*NewShellParameters));
365 }
366
367 return (Status);
368 }
369
370 /**
371 frees all memory used by createion and installation of shell parameters protocol
372 and if there was an old version installed it will restore that one.
373
374 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is
375 being cleaned up.
376
377 @retval EFI_SUCCESS the cleanup was successful
378 @return other the cleanup failed
379 @sa ReinstallProtocolInterface
380 @sa UninstallProtocolInterface
381 **/
382 EFI_STATUS
383 EFIAPI
384 CleanUpShellParametersProtocol (
385 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters
386 )
387 {
388 EFI_STATUS Status;
389 UINTN LoopCounter;
390
391 //
392 // If the old exists we need to restore it
393 //
394 if (ShellInfoObject.OldShellParameters != NULL) {
395 Status = gBS->ReinstallProtocolInterface(gImageHandle,
396 &gEfiShellParametersProtocolGuid,
397 (VOID*)NewShellParameters,
398 (VOID*)ShellInfoObject.OldShellParameters);
399 DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;);
400 } else {
401 //
402 // No old one, just uninstall us...
403 //
404 Status = gBS->UninstallProtocolInterface(gImageHandle,
405 &gEfiShellParametersProtocolGuid,
406 (VOID*)NewShellParameters);
407 }
408 if (NewShellParameters->Argv != NULL) {
409 for ( LoopCounter = 0
410 ; LoopCounter < NewShellParameters->Argc
411 ; LoopCounter++
412 ){
413 FreePool(NewShellParameters->Argv[LoopCounter]);
414 }
415 FreePool(NewShellParameters->Argv);
416 }
417 FreePool(NewShellParameters);
418 return (Status);
419 }
420
421 /**
422 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
423 structure by parsing NewCommandLine. The current values are returned to the
424 user.
425
426 If OldStdIn or OldStdOut is NULL then that value is not returned.
427
428 @param[in,out] ShellParameters Pointer to parameter structure to modify.
429 @param[in] NewCommandLine The new command line to parse and use.
430 @param[out] OldStdIn Pointer to old StdIn.
431 @param[out] OldStdOut Pointer to old StdOut.
432 @param[out] OldStdErr Pointer to old StdErr.
433
434 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
435 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
436 **/
437 EFI_STATUS
438 EFIAPI
439 UpdateStdInStdOutStdErr(
440 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
441 IN CONST CHAR16 *NewCommandLine,
442 OUT SHELL_FILE_HANDLE *OldStdIn,
443 OUT SHELL_FILE_HANDLE *OldStdOut,
444 OUT SHELL_FILE_HANDLE *OldStdErr
445 )
446 {
447 CHAR16 *CommandLineCopy;
448 CHAR16 *CommandLineWalker;
449 CHAR16 *StdErrFileName;
450 CHAR16 *StdOutFileName;
451 CHAR16 *StdInFileName;
452 CHAR16 *StdInVarName;
453 CHAR16 *StdOutVarName;
454 CHAR16 *StdErrVarName;
455 EFI_STATUS Status;
456 SHELL_FILE_HANDLE TempHandle;
457 UINT64 FileSize;
458 BOOLEAN OutUnicode;
459 BOOLEAN InUnicode;
460 BOOLEAN ErrUnicode;
461 BOOLEAN OutAppend;
462 BOOLEAN ErrAppend;
463 UINTN Size;
464 CHAR16 TagBuffer[2];
465 SPLIT_LIST *Split;
466
467 ASSERT(ShellParameters != NULL);
468 OutUnicode = TRUE;
469 InUnicode = TRUE;
470 ErrUnicode = TRUE;
471 StdInVarName = NULL;
472 StdOutVarName = NULL;
473 StdErrVarName = NULL;
474 StdErrFileName = NULL;
475 StdInFileName = NULL;
476 StdOutFileName = NULL;
477 ErrAppend = FALSE;
478 OutAppend = FALSE;
479 CommandLineCopy = NULL;
480
481 if (OldStdIn != NULL) {
482 *OldStdIn = ShellParameters->StdIn;
483 }
484 if (OldStdOut != NULL) {
485 *OldStdOut = ShellParameters->StdOut;
486 }
487 if (OldStdErr != NULL) {
488 *OldStdErr = ShellParameters->StdErr;
489 }
490
491 if (NewCommandLine == NULL) {
492 return (EFI_SUCCESS);
493 }
494
495 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);
496 Status = EFI_SUCCESS;
497 Split = NULL;
498
499 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {
500 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);
501 if (Split != NULL && Split->SplitStdIn != NULL) {
502 ShellParameters->StdIn = Split->SplitStdIn;
503 }
504 if (Split != NULL && Split->SplitStdOut != NULL) {
505 ShellParameters->StdOut = Split->SplitStdOut;
506 }
507 }
508
509 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {
510 StdErrVarName = CommandLineWalker += 6;
511 ErrAppend = TRUE;
512 }
513 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {
514 StdOutVarName = CommandLineWalker += 6;
515 OutAppend = TRUE;
516 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {
517 StdOutVarName = CommandLineWalker += 5;
518 OutAppend = TRUE;
519 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {
520 StdOutVarName = CommandLineWalker += 4;
521 OutAppend = FALSE;
522 }
523 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {
524 StdOutFileName = CommandLineWalker += 6;
525 OutAppend = TRUE;
526 OutUnicode = FALSE;
527 }
528 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {
529 if (StdOutFileName != NULL) {
530 Status = EFI_INVALID_PARAMETER;
531 } else {
532 StdOutFileName = CommandLineWalker += 5;
533 OutAppend = TRUE;
534 }
535 }
536 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {
537 if (StdOutFileName != NULL) {
538 Status = EFI_INVALID_PARAMETER;
539 } else {
540 StdOutFileName = CommandLineWalker += 4;
541 OutAppend = TRUE;
542 }
543 }
544 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {
545 if (StdOutFileName != NULL) {
546 Status = EFI_INVALID_PARAMETER;
547 } else {
548 StdOutFileName = CommandLineWalker += 5;
549 OutAppend = TRUE;
550 OutUnicode = FALSE;
551 }
552 }
553 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {
554 if (StdOutFileName != NULL) {
555 Status = EFI_INVALID_PARAMETER;
556 } else {
557 StdOutFileName = CommandLineWalker += 5;
558 OutAppend = FALSE;
559 OutUnicode = FALSE;
560 }
561 }
562 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {
563 if (StdOutFileName != NULL) {
564 Status = EFI_INVALID_PARAMETER;
565 } else {
566 StdOutFileName = CommandLineWalker += 4;
567 OutAppend = FALSE;
568 OutUnicode = FALSE;
569 }
570 }
571 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {
572 if (StdErrFileName != NULL) {
573 Status = EFI_INVALID_PARAMETER;
574 } else {
575 StdErrFileName = CommandLineWalker += 5;
576 ErrAppend = TRUE;
577 }
578 }
579
580 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {
581 if (StdErrVarName != NULL) {
582 Status = EFI_INVALID_PARAMETER;
583 } else {
584 StdErrVarName = CommandLineWalker += 5;
585 ErrAppend = FALSE;
586 }
587 }
588 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {
589 if (StdOutVarName != NULL) {
590 Status = EFI_INVALID_PARAMETER;
591 } else {
592 StdOutVarName = CommandLineWalker += 5;
593 OutAppend = FALSE;
594 }
595 }
596 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {
597 if (StdErrFileName != NULL) {
598 Status = EFI_INVALID_PARAMETER;
599 } else {
600 StdErrFileName = CommandLineWalker += 5;
601 ErrAppend = FALSE;
602 ErrUnicode = FALSE;
603 }
604 }
605 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {
606 if (StdErrFileName != NULL) {
607 Status = EFI_INVALID_PARAMETER;
608 } else {
609 StdErrFileName = CommandLineWalker += 4;
610 ErrAppend = FALSE;
611 }
612 }
613
614 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {
615 if (StdOutFileName != NULL) {
616 Status = EFI_INVALID_PARAMETER;
617 } else {
618 StdOutFileName = CommandLineWalker += 4;
619 OutAppend = FALSE;
620 }
621 }
622
623 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {
624 if (StdOutFileName != NULL) {
625 Status = EFI_INVALID_PARAMETER;
626 } else {
627 StdOutFileName = CommandLineWalker += 3;
628 OutAppend = FALSE;
629 }
630 }
631
632 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {
633 if (StdInFileName != NULL) {
634 Status = EFI_INVALID_PARAMETER;
635 } else {
636 StdInFileName = CommandLineWalker += 3;
637 OutAppend = FALSE;
638 }
639 }
640 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {
641 if (StdInFileName != NULL) {
642 Status = EFI_INVALID_PARAMETER;
643 } else {
644 StdInFileName = CommandLineWalker += 4;
645 OutAppend = FALSE;
646 }
647 }
648 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {
649 if (StdInVarName != NULL) {
650 Status = EFI_INVALID_PARAMETER;
651 } else {
652 StdInVarName = CommandLineWalker += 4;
653 OutAppend = FALSE;
654 }
655 }
656
657 if (!EFI_ERROR(Status)) {
658 if (StdErrFileName != NULL && (CommandLineWalker = StrStr(StdErrFileName, L" ")) != NULL) {
659 CommandLineWalker[0] = CHAR_NULL;
660 }
661 if (StdOutFileName != NULL && (CommandLineWalker = StrStr(StdOutFileName, L" ")) != NULL) {
662 CommandLineWalker[0] = CHAR_NULL;
663 }
664 if (StdInFileName != NULL && (CommandLineWalker = StrStr(StdInFileName , L" ")) != NULL) {
665 CommandLineWalker[0] = CHAR_NULL;
666 }
667 if (StdErrVarName != NULL && (CommandLineWalker = StrStr(StdErrVarName , L" ")) != NULL) {
668 CommandLineWalker[0] = CHAR_NULL;
669 }
670 if (StdOutVarName != NULL && (CommandLineWalker = StrStr(StdOutVarName , L" ")) != NULL) {
671 CommandLineWalker[0] = CHAR_NULL;
672 }
673 if (StdInVarName != NULL && (CommandLineWalker = StrStr(StdInVarName , L" ")) != NULL) {
674 CommandLineWalker[0] = CHAR_NULL;
675 }
676
677 //
678 // Verify not the same and not duplicating something from a split
679 //
680 if ((StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)
681 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)
682 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)
683 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)
684 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)
685 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)
686 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))
687 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))
688 ||(StdErrFileName != NULL && StdErrVarName != NULL)
689 ||(StdOutFileName != NULL && StdOutVarName != NULL)
690 ||(StdInFileName != NULL && StdInVarName != NULL)
691 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))
692 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))
693 ||(StrStr(NewCommandLine, L"connect -r") != NULL
694 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))
695 ){
696 Status = EFI_INVALID_PARAMETER;
697 } else {
698 //
699 // Open the Std<Whatever> and we should not have conflicts here...
700 //
701
702 //
703 // StdErr to a file
704 //
705 if (StdErrFileName != NULL) {
706 if (!ErrAppend) {
707 //
708 // delete existing file.
709 //
710 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);
711 }
712 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);
713 ASSERT(TempHandle != NULL);
714 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {
715 //
716 // Write out the UnicodeFileTag
717 //
718 Size = sizeof(CHAR16);
719 TagBuffer[0] = UnicodeFileTag;
720 TagBuffer[1] = CHAR_NULL;
721 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);
722 }
723 if (!ErrUnicode && !EFI_ERROR(Status)) {
724 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
725 ASSERT(TempHandle != NULL);
726 }
727 if (!EFI_ERROR(Status)) {
728 ShellParameters->StdErr = TempHandle;
729 }
730 }
731
732 //
733 // StdOut to a file
734 //
735 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {
736 if (!OutAppend) {
737 //
738 // delete existing file.
739 //
740 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);
741 }
742 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);
743 if (TempHandle == NULL) {
744 Status = EFI_INVALID_PARAMETER;
745 } else {
746 if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {
747 //
748 // Write out the UnicodeFileTag
749 //
750 Size = sizeof(CHAR16);
751 TagBuffer[0] = UnicodeFileTag;
752 TagBuffer[1] = CHAR_NULL;
753 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);
754 } else if (OutAppend) {
755 //
756 // Move to end of file
757 //
758 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);
759 if (!EFI_ERROR(Status)) {
760 Status = ShellInfoObject.NewEfiShellProtocol->SetFilePosition(TempHandle, FileSize);
761 }
762 }
763 if (!OutUnicode && !EFI_ERROR(Status)) {
764 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
765 ASSERT(TempHandle != NULL);
766 }
767 if (!EFI_ERROR(Status)) {
768 ShellParameters->StdOut = TempHandle;
769 }
770 }
771 }
772
773 //
774 // StdOut to a var
775 //
776 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {
777 if (!OutAppend) {
778 //
779 // delete existing variable.
780 //
781 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");
782 }
783 TempHandle = CreateFileInterfaceEnv(StdOutVarName);
784 ASSERT(TempHandle != NULL);
785 if (!OutUnicode) {
786 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
787 ASSERT(TempHandle != NULL);
788 }
789 ShellParameters->StdOut = TempHandle;
790 }
791
792 //
793 // StdErr to a var
794 //
795 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {
796 if (!ErrAppend) {
797 //
798 // delete existing variable.
799 //
800 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");
801 }
802 TempHandle = CreateFileInterfaceEnv(StdErrVarName);
803 ASSERT(TempHandle != NULL);
804 if (!ErrUnicode) {
805 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
806 ASSERT(TempHandle != NULL);
807 }
808 ShellParameters->StdErr = TempHandle;
809 }
810
811 //
812 // StdIn from a var
813 //
814 if (!EFI_ERROR(Status) && StdInVarName != NULL) {
815 TempHandle = CreateFileInterfaceEnv(StdInVarName);
816 if (!InUnicode) {
817 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
818 }
819 Size = 0;
820 ASSERT(TempHandle != NULL);
821 if (((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {
822 Status = EFI_INVALID_PARAMETER;
823 } else {
824 ShellParameters->StdIn = TempHandle;
825 }
826 }
827
828 //
829 // StdIn from a file
830 //
831 if (!EFI_ERROR(Status) && StdInFileName != NULL) {
832 Status = ShellOpenFileByName(
833 StdInFileName,
834 &TempHandle,
835 EFI_FILE_MODE_READ,
836 0);
837 if (!InUnicode && !EFI_ERROR(Status)) {
838 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
839 }
840 if (!EFI_ERROR(Status)) {
841 ShellParameters->StdIn = TempHandle;
842 }
843 }
844 }
845 }
846 FreePool(CommandLineCopy);
847 return (Status);
848 }
849
850 /**
851 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
852 structure with StdIn and StdOut. The current values are de-allocated.
853
854 @param[in,out] ShellParameters pointer to parameter structure to modify
855 @param[out] OldStdIn Pointer to old StdIn.
856 @param[out] OldStdOut Pointer to old StdOut.
857 @param[out] OldStdErr Pointer to old StdErr.
858 **/
859 EFI_STATUS
860 EFIAPI
861 RestoreStdInStdOutStdErr (
862 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
863 OUT SHELL_FILE_HANDLE *OldStdIn OPTIONAL,
864 OUT SHELL_FILE_HANDLE *OldStdOut OPTIONAL,
865 OUT SHELL_FILE_HANDLE *OldStdErr OPTIONAL
866 )
867 {
868 SPLIT_LIST *Split;
869 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {
870 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);
871 } else {
872 Split = NULL;
873 }
874 if (OldStdIn != NULL && ShellParameters->StdIn != *OldStdIn) {
875 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {
876 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);
877 }
878 ShellParameters->StdIn = OldStdIn==NULL?NULL:*OldStdIn;
879 }
880 if (OldStdOut != NULL && ShellParameters->StdOut != *OldStdOut) {
881 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {
882 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);
883 }
884 ShellParameters->StdOut = OldStdOut==NULL?NULL:*OldStdOut;
885 }
886 return (EFI_SUCCESS);
887 }
888 /**
889 Funcion will replace the current Argc and Argv in the ShellParameters protocol
890 structure by parsing NewCommandLine. The current values are returned to the
891 user.
892
893 If OldArgv or OldArgc is NULL then that value is not returned.
894
895 @param[in,out] ShellParameters Pointer to parameter structure to modify.
896 @param[in] NewCommandLine The new command line to parse and use.
897 @param[out] OldArgv Pointer to old list of parameters.
898 @param[out] OldArgc Pointer to old number of items in Argv list.
899
900 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
901 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
902 **/
903 EFI_STATUS
904 EFIAPI
905 UpdateArgcArgv(
906 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
907 IN CONST CHAR16 *NewCommandLine,
908 OUT CHAR16 ***OldArgv OPTIONAL,
909 OUT UINTN *OldArgc OPTIONAL
910 )
911 {
912 ASSERT(ShellParameters != NULL);
913
914 if (OldArgc != NULL) {
915 *OldArgc = ShellParameters->Argc;
916 }
917 if (OldArgc != NULL) {
918 *OldArgv = ShellParameters->Argv;
919 }
920
921 return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));
922 }
923
924 /**
925 Funcion will replace the current Argc and Argv in the ShellParameters protocol
926 structure with Argv and Argc. The current values are de-allocated and the
927 OldArgv must not be deallocated by the caller.
928
929 @param[in,out] ShellParameters pointer to parameter structure to modify
930 @param[in] OldArgv pointer to old list of parameters
931 @param[in] OldArgc pointer to old number of items in Argv list
932 **/
933 VOID
934 EFIAPI
935 RestoreArgcArgv(
936 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
937 IN CHAR16 ***OldArgv,
938 IN UINTN *OldArgc
939 )
940 {
941 UINTN LoopCounter;
942 ASSERT(ShellParameters != NULL);
943 ASSERT(OldArgv != NULL);
944 ASSERT(OldArgc != NULL);
945
946 if (ShellParameters->Argv != NULL) {
947 for ( LoopCounter = 0
948 ; LoopCounter < ShellParameters->Argc
949 ; LoopCounter++
950 ){
951 FreePool(ShellParameters->Argv[LoopCounter]);
952 }
953 FreePool(ShellParameters->Argv);
954 }
955 ShellParameters->Argv = *OldArgv;
956 *OldArgv = NULL;
957 ShellParameters->Argc = *OldArgc;
958 *OldArgc = 0;
959 }