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