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