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