]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ShellPkg/Application/Shell/ShellParametersProtocol.c
Update the comments in function headers to follow Doxygen special documentation block...
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellParametersProtocol.c
... / ...
CommitLineData
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) 2013 Hewlett-Packard Development Company, L.P.\r
6 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
7 This program and the accompanying materials\r
8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "Shell.h"\r
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'\"') {\r
75 NextDelim = TempLoc;\r
76 break;\r
77 }\r
78 }\r
79\r
80 if (NextDelim - ((*Walker)+1) == 0) {\r
81 //\r
82 // found ""\r
83 //\r
84 StrCpy(*TempParameter, L"");\r
85 *Walker = NextDelim + 1;\r
86 } else if (NextDelim != NULL) {\r
87 StrnCpy(*TempParameter, (*Walker)+1, NextDelim - ((*Walker)+1));\r
88 *Walker = NextDelim + 1;\r
89 } else {\r
90 //\r
91 // last one... someone forgot the training quote!\r
92 //\r
93 StrCpy(*TempParameter, *Walker);\r
94 *Walker = NULL;\r
95 }\r
96 for (TempLoc = *TempParameter ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {\r
97 if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {\r
98 CopyMem(TempLoc, TempLoc+1, StrSize(TempLoc) - sizeof(TempLoc[0]));\r
99 }\r
100 }\r
101 } else {\r
102 //\r
103 // we have a regular parameter (no quote) OR\r
104 // we have the final parameter (no trailing space)\r
105 //\r
106 NextDelim = StrStr((*Walker), L" ");\r
107 if (NextDelim != NULL) {\r
108 StrnCpy(*TempParameter, *Walker, NextDelim - (*Walker));\r
109 (*TempParameter)[NextDelim - (*Walker)] = CHAR_NULL;\r
110 *Walker = NextDelim+1;\r
111 } else {\r
112 //\r
113 // last one.\r
114 //\r
115 StrCpy(*TempParameter, *Walker);\r
116 *Walker = NULL;\r
117 }\r
118 for (NextDelim = *TempParameter ; NextDelim != NULL && *NextDelim != CHAR_NULL ; NextDelim++) {\r
119 if (*NextDelim == L'^' && *(NextDelim+1) == L'^') {\r
120 CopyMem(NextDelim, NextDelim+1, StrSize(NextDelim) - sizeof(NextDelim[0]));\r
121 }\r
122 }\r
123 while ((*TempParameter)[StrLen(*TempParameter)-1] == L' ') {\r
124 (*TempParameter)[StrLen(*TempParameter)-1] = CHAR_NULL;\r
125 }\r
126 while ((*TempParameter)[0] == L' ') {\r
127 CopyMem(*TempParameter, (*TempParameter)+1, StrSize(*TempParameter) - sizeof((*TempParameter)[0]));\r
128 }\r
129 }\r
130 return;\r
131}\r
132\r
133/**\r
134 Function to populate Argc and Argv.\r
135\r
136 This function parses the CommandLine and divides it into standard C style Argc/Argv\r
137 parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space\r
138 delimited and quote surrounded parameter definition.\r
139\r
140 @param[in] CommandLine String of command line to parse\r
141 @param[in, out] Argv pointer to array of strings; one for each parameter\r
142 @param[in, out] Argc pointer to number of strings in Argv array\r
143\r
144 @return EFI_SUCCESS the operation was sucessful\r
145 @return EFI_OUT_OF_RESOURCES a memory allocation failed.\r
146**/\r
147EFI_STATUS\r
148EFIAPI\r
149ParseCommandLineToArgs(\r
150 IN CONST CHAR16 *CommandLine,\r
151 IN OUT CHAR16 ***Argv,\r
152 IN OUT UINTN *Argc\r
153 )\r
154{\r
155 UINTN Count;\r
156 CHAR16 *TempParameter;\r
157 CHAR16 *Walker;\r
158 CHAR16 *NewParam;\r
159 UINTN Size;\r
160\r
161 ASSERT(Argc != NULL);\r
162 ASSERT(Argv != NULL);\r
163\r
164 if (CommandLine == NULL || StrLen(CommandLine)==0) {\r
165 (*Argc) = 0;\r
166 (*Argv) = NULL;\r
167 return (EFI_SUCCESS);\r
168 }\r
169\r
170 Size = StrSize(CommandLine);\r
171 TempParameter = AllocateZeroPool(Size);\r
172 if (TempParameter == NULL) {\r
173 return (EFI_OUT_OF_RESOURCES);\r
174 }\r
175\r
176 for ( Count = 0\r
177 , Walker = (CHAR16*)CommandLine\r
178 ; Walker != NULL && *Walker != CHAR_NULL\r
179 ; GetNextParameter(&Walker, &TempParameter)\r
180 , Count++\r
181 );\r
182\r
183/* Count = 0;\r
184 Walker = (CHAR16*)CommandLine;\r
185 while(Walker != NULL) {\r
186 GetNextParameter(&Walker, &TempParameter);\r
187 Count++;\r
188 }\r
189*/\r
190 //\r
191 // lets allocate the pointer array\r
192 //\r
193 (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*));\r
194 if (*Argv == NULL) {\r
195 SHELL_FREE_NON_NULL(TempParameter);\r
196 return (EFI_OUT_OF_RESOURCES);\r
197 }\r
198\r
199 *Argc = 0;\r
200 Walker = (CHAR16*)CommandLine;\r
201 while(Walker != NULL && *Walker != CHAR_NULL) {\r
202 SetMem16(TempParameter, Size, CHAR_NULL);\r
203 GetNextParameter(&Walker, &TempParameter);\r
204 NewParam = AllocateZeroPool(StrSize(TempParameter));\r
205 ASSERT(NewParam != NULL);\r
206 StrCpy(NewParam, TempParameter);\r
207 ((CHAR16**)(*Argv))[(*Argc)] = NewParam;\r
208 (*Argc)++;\r
209 }\r
210 ASSERT(Count >= (*Argc));\r
211 SHELL_FREE_NON_NULL(TempParameter);\r
212 return (EFI_SUCCESS);\r
213}\r
214\r
215/**\r
216 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then\r
217 installs it on our handle and if there is an existing version of the protocol\r
218 that one is cached for removal later.\r
219\r
220 @param[in, out] NewShellParameters on a successful return, a pointer to pointer\r
221 to the newly installed interface.\r
222 @param[in, out] RootShellInstance on a successful return, pointer to boolean.\r
223 TRUE if this is the root shell instance.\r
224\r
225 @retval EFI_SUCCESS the operation completed successfully.\r
226 @return other the operation failed.\r
227 @sa ReinstallProtocolInterface\r
228 @sa InstallProtocolInterface\r
229 @sa ParseCommandLineToArgs\r
230**/\r
231EFI_STATUS\r
232EFIAPI\r
233CreatePopulateInstallShellParametersProtocol (\r
234 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters,\r
235 IN OUT BOOLEAN *RootShellInstance\r
236 )\r
237{\r
238 EFI_STATUS Status;\r
239 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
240 CHAR16 *FullCommandLine;\r
241 UINTN Size;\r
242\r
243 Size = 0;\r
244 FullCommandLine = NULL;\r
245 LoadedImage = NULL;\r
246\r
247 //\r
248 // Assert for valid parameters\r
249 //\r
250 ASSERT(NewShellParameters != NULL);\r
251 ASSERT(RootShellInstance != NULL);\r
252\r
253 //\r
254 // See if we have a shell parameters placed on us\r
255 //\r
256 Status = gBS->OpenProtocol (\r
257 gImageHandle,\r
258 &gEfiShellParametersProtocolGuid,\r
259 (VOID **) &ShellInfoObject.OldShellParameters,\r
260 gImageHandle,\r
261 NULL,\r
262 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
263 );\r
264 //\r
265 // if we don't then we must be the root shell (error is expected)\r
266 //\r
267 if (EFI_ERROR (Status)) {\r
268 *RootShellInstance = TRUE;\r
269 }\r
270\r
271 //\r
272 // Allocate the new structure\r
273 //\r
274 *NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));\r
275 if ((*NewShellParameters) == NULL) {\r
276 return (EFI_OUT_OF_RESOURCES);\r
277 }\r
278\r
279 //\r
280 // get loaded image protocol\r
281 //\r
282 Status = gBS->OpenProtocol (\r
283 gImageHandle,\r
284 &gEfiLoadedImageProtocolGuid,\r
285 (VOID **) &LoadedImage,\r
286 gImageHandle,\r
287 NULL,\r
288 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
289 );\r
290 ASSERT_EFI_ERROR(Status);\r
291 //\r
292 // Build the full command line\r
293 //\r
294 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);\r
295 if (Status == EFI_BUFFER_TOO_SMALL) {\r
296 FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);\r
297 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);\r
298 }\r
299 if (Status == EFI_NOT_FOUND) {\r
300 //\r
301 // no parameters via environment... ok\r
302 //\r
303 } else {\r
304 if (EFI_ERROR(Status)) {\r
305 return (Status);\r
306 }\r
307 }\r
308 if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {\r
309 ASSERT(FullCommandLine == NULL);\r
310 //\r
311 // Now we need to include a NULL terminator in the size.\r
312 //\r
313 Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]);\r
314 FullCommandLine = AllocateZeroPool(Size);\r
315 }\r
316 if (FullCommandLine != NULL) {\r
317 CopyMem (FullCommandLine, LoadedImage->LoadOptions, LoadedImage->LoadOptionsSize);\r
318 //\r
319 // Populate Argc and Argv\r
320 //\r
321 Status = ParseCommandLineToArgs(FullCommandLine,\r
322 &(*NewShellParameters)->Argv,\r
323 &(*NewShellParameters)->Argc);\r
324\r
325 FreePool(FullCommandLine);\r
326\r
327 ASSERT_EFI_ERROR(Status);\r
328 } else {\r
329 (*NewShellParameters)->Argv = NULL;\r
330 (*NewShellParameters)->Argc = 0;\r
331 }\r
332\r
333 //\r
334 // Populate the 3 faked file systems...\r
335 //\r
336 if (*RootShellInstance) {\r
337 (*NewShellParameters)->StdIn = &FileInterfaceStdIn;\r
338 (*NewShellParameters)->StdOut = &FileInterfaceStdOut;\r
339 (*NewShellParameters)->StdErr = &FileInterfaceStdErr;\r
340 Status = gBS->InstallProtocolInterface(&gImageHandle,\r
341 &gEfiShellParametersProtocolGuid,\r
342 EFI_NATIVE_INTERFACE,\r
343 (VOID*)(*NewShellParameters));\r
344 } else {\r
345 //\r
346 // copy from the existing ones\r
347 //\r
348 (*NewShellParameters)->StdIn = ShellInfoObject.OldShellParameters->StdIn;\r
349 (*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut;\r
350 (*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr;\r
351 Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
352 &gEfiShellParametersProtocolGuid,\r
353 (VOID*)ShellInfoObject.OldShellParameters,\r
354 (VOID*)(*NewShellParameters));\r
355 }\r
356\r
357 return (Status);\r
358}\r
359\r
360/**\r
361 frees all memory used by createion and installation of shell parameters protocol\r
362 and if there was an old version installed it will restore that one.\r
363\r
364 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is\r
365 being cleaned up.\r
366\r
367 @retval EFI_SUCCESS the cleanup was successful\r
368 @return other the cleanup failed\r
369 @sa ReinstallProtocolInterface\r
370 @sa UninstallProtocolInterface\r
371**/\r
372EFI_STATUS\r
373EFIAPI\r
374CleanUpShellParametersProtocol (\r
375 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters\r
376 )\r
377{\r
378 EFI_STATUS Status;\r
379 UINTN LoopCounter;\r
380\r
381 //\r
382 // If the old exists we need to restore it\r
383 //\r
384 if (ShellInfoObject.OldShellParameters != NULL) {\r
385 Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
386 &gEfiShellParametersProtocolGuid,\r
387 (VOID*)NewShellParameters,\r
388 (VOID*)ShellInfoObject.OldShellParameters);\r
389 DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;);\r
390 } else {\r
391 //\r
392 // No old one, just uninstall us...\r
393 //\r
394 Status = gBS->UninstallProtocolInterface(gImageHandle,\r
395 &gEfiShellParametersProtocolGuid,\r
396 (VOID*)NewShellParameters);\r
397 }\r
398 if (NewShellParameters->Argv != NULL) {\r
399 for ( LoopCounter = 0\r
400 ; LoopCounter < NewShellParameters->Argc\r
401 ; LoopCounter++\r
402 ){\r
403 FreePool(NewShellParameters->Argv[LoopCounter]);\r
404 }\r
405 FreePool(NewShellParameters->Argv);\r
406 }\r
407 FreePool(NewShellParameters);\r
408 return (Status);\r
409}\r
410\r
411/**\r
412 Determin if a file name represents a unicode file.\r
413\r
414 @param[in] FileName Pointer to the filename to open.\r
415\r
416 @retval EFI_SUCCESS The file is a unicode file.\r
417 @return An error upon failure.\r
418**/\r
419EFI_STATUS\r
420EFIAPI\r
421IsUnicodeFile(\r
422 IN CONST CHAR16 *FileName\r
423 )\r
424{\r
425 SHELL_FILE_HANDLE Handle;\r
426 EFI_STATUS Status;\r
427 UINT64 OriginalFilePosition;\r
428 UINTN CharSize;\r
429 CHAR16 CharBuffer;\r
430\r
431 Status = gEfiShellProtocol->OpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ);\r
432 if (EFI_ERROR(Status)) {\r
433 return (Status);\r
434 }\r
435 gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);\r
436 gEfiShellProtocol->SetFilePosition(Handle, 0);\r
437 CharSize = sizeof(CHAR16);\r
438 Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
439 if (EFI_ERROR(Status) || CharBuffer != gUnicodeFileTag) {\r
440 Status = EFI_BUFFER_TOO_SMALL;\r
441 }\r
442 gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
443 gEfiShellProtocol->CloseFile(Handle);\r
444 return (Status); \r
445}\r
446\r
447/**\r
448 Strips out quotes sections of a string.\r
449\r
450 All of the characters between quotes is replaced with spaces.\r
451\r
452 @param[in, out] TheString A pointer to the string to update.\r
453**/\r
454VOID\r
455EFIAPI\r
456StripQuotes (\r
457 IN OUT CHAR16 *TheString\r
458 )\r
459{\r
460 BOOLEAN RemoveNow;\r
461\r
462 for (RemoveNow = FALSE ; TheString != NULL && *TheString != CHAR_NULL ; TheString++) {\r
463 if (*TheString == L'^' && *(TheString + 1) == L'\"') {\r
464 TheString++;\r
465 } else if (*TheString == L'\"') {\r
466 RemoveNow = (BOOLEAN)!RemoveNow;\r
467 } else if (RemoveNow) {\r
468 *TheString = L' ';\r
469 }\r
470 }\r
471}\r
472\r
473/**\r
474 Calcualte the 32-bit CRC in a EFI table using the service provided by the\r
475 gRuntime service.\r
476\r
477 @param Hdr Pointer to an EFI standard header\r
478\r
479**/\r
480VOID\r
481CalculateEfiHdrCrc (\r
482 IN OUT EFI_TABLE_HEADER *Hdr\r
483 )\r
484{\r
485 UINT32 Crc;\r
486\r
487 Hdr->CRC32 = 0;\r
488\r
489 //\r
490 // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then\r
491 // Crc will come back as zero if we set it to zero here\r
492 //\r
493 Crc = 0;\r
494 gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc);\r
495 Hdr->CRC32 = Crc;\r
496}\r
497\r
498/**\r
499 Fix a string to only have the file name, removing starting at the first space of whatever is quoted.\r
500\r
501 @param[in] FileName The filename to start with.\r
502\r
503 @retval NULL FileName was invalid.\r
504 @return The modified FileName.\r
505**/\r
506CHAR16*\r
507EFIAPI\r
508FixFileName (\r
509 IN CHAR16 *FileName\r
510 )\r
511{\r
512 CHAR16 *Copy;\r
513 CHAR16 *TempLocation;\r
514\r
515 if (FileName == NULL) {\r
516 return (NULL);\r
517 }\r
518\r
519 if (FileName[0] == L'\"') {\r
520 Copy = FileName+1;\r
521 if ((TempLocation = StrStr(Copy , L"\"")) != NULL) {\r
522 TempLocation[0] = CHAR_NULL;\r
523 } \r
524 } else {\r
525 Copy = FileName;\r
526 while(Copy[0] == L' ') {\r
527 Copy++;\r
528 }\r
529 if ((TempLocation = StrStr(Copy , L" ")) != NULL) {\r
530 TempLocation[0] = CHAR_NULL;\r
531 } \r
532 }\r
533\r
534 if (Copy[0] == CHAR_NULL) {\r
535 return (NULL);\r
536 }\r
537\r
538 return (Copy);\r
539}\r
540\r
541/**\r
542 Fix a string to only have the environment variable name, removing starting at the first space of whatever is quoted and removing the leading and trailing %.\r
543\r
544 @param[in] FileName The filename to start with.\r
545\r
546 @retval NULL FileName was invalid.\r
547 @return The modified FileName.\r
548**/\r
549CHAR16*\r
550EFIAPI\r
551FixVarName (\r
552 IN CHAR16 *FileName\r
553 )\r
554{\r
555 CHAR16 *Copy;\r
556 CHAR16 *TempLocation;\r
557\r
558 Copy = FileName;\r
559\r
560 if (FileName[0] == L'%') {\r
561 Copy = FileName+1;\r
562 if ((TempLocation = StrStr(Copy , L"%")) != NULL) {\r
563 TempLocation[0] = CHAR_NULL;\r
564 } \r
565 }\r
566\r
567 return (FixFileName(Copy));\r
568}\r
569\r
570/**\r
571 Remove the unicode file tag from the begining of the file buffer since that will not be\r
572 used by StdIn.\r
573 \r
574 @param[in] Handle Pointer to the handle of the file to be processed.\r
575 \r
576 @retval EFI_SUCCESS The unicode file tag has been moved successfully.\r
577**/\r
578EFI_STATUS\r
579EFIAPI\r
580RemoveFileTag(\r
581 IN SHELL_FILE_HANDLE *Handle\r
582 )\r
583{\r
584 UINTN CharSize;\r
585 CHAR16 CharBuffer;\r
586\r
587 CharSize = sizeof(CHAR16);\r
588 CharBuffer = 0;\r
589 gEfiShellProtocol->ReadFile(*Handle, &CharSize, &CharBuffer);\r
590 if (CharBuffer != gUnicodeFileTag) {\r
591 gEfiShellProtocol->SetFilePosition(*Handle, 0);\r
592 }\r
593 return (EFI_SUCCESS);\r
594}\r
595\r
596/**\r
597 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
598 structure by parsing NewCommandLine. The current values are returned to the\r
599 user.\r
600\r
601 This will also update the system table.\r
602\r
603 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
604 @param[in] NewCommandLine The new command line to parse and use.\r
605 @param[out] OldStdIn Pointer to old StdIn.\r
606 @param[out] OldStdOut Pointer to old StdOut.\r
607 @param[out] OldStdErr Pointer to old StdErr.\r
608 @param[out] SystemTableInfo Pointer to old system table information.\r
609\r
610 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
611 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
612**/\r
613EFI_STATUS\r
614EFIAPI\r
615UpdateStdInStdOutStdErr(\r
616 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
617 IN CHAR16 *NewCommandLine,\r
618 OUT SHELL_FILE_HANDLE *OldStdIn,\r
619 OUT SHELL_FILE_HANDLE *OldStdOut,\r
620 OUT SHELL_FILE_HANDLE *OldStdErr,\r
621 OUT SYSTEM_TABLE_INFO *SystemTableInfo\r
622 )\r
623{\r
624 CHAR16 *CommandLineCopy;\r
625 CHAR16 *CommandLineWalker;\r
626 CHAR16 *StdErrFileName;\r
627 CHAR16 *StdOutFileName;\r
628 CHAR16 *StdInFileName;\r
629 CHAR16 *StdInVarName;\r
630 CHAR16 *StdOutVarName;\r
631 CHAR16 *StdErrVarName;\r
632 EFI_STATUS Status;\r
633 SHELL_FILE_HANDLE TempHandle;\r
634 UINT64 FileSize;\r
635 BOOLEAN OutUnicode;\r
636 BOOLEAN InUnicode;\r
637 BOOLEAN ErrUnicode;\r
638 BOOLEAN OutAppend;\r
639 BOOLEAN ErrAppend;\r
640 UINTN Size;\r
641 CHAR16 TagBuffer[2];\r
642 SPLIT_LIST *Split;\r
643 CHAR16 *FirstLocation;\r
644\r
645 OutUnicode = TRUE;\r
646 InUnicode = TRUE;\r
647 ErrUnicode = TRUE;\r
648 StdInVarName = NULL;\r
649 StdOutVarName = NULL;\r
650 StdErrVarName = NULL;\r
651 StdErrFileName = NULL;\r
652 StdInFileName = NULL;\r
653 StdOutFileName = NULL;\r
654 ErrAppend = FALSE;\r
655 OutAppend = FALSE;\r
656 CommandLineCopy = NULL;\r
657 FirstLocation = NULL;\r
658\r
659 if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {\r
660 return (EFI_INVALID_PARAMETER);\r
661 }\r
662\r
663 SystemTableInfo->ConIn = gST->ConIn;\r
664 SystemTableInfo->ConInHandle = gST->ConsoleInHandle;\r
665 SystemTableInfo->ConOut = gST->ConOut;\r
666 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;\r
667 SystemTableInfo->ErrOut = gST->StdErr;\r
668 SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle;\r
669 *OldStdIn = ShellParameters->StdIn;\r
670 *OldStdOut = ShellParameters->StdOut;\r
671 *OldStdErr = ShellParameters->StdErr;\r
672\r
673 if (NewCommandLine == NULL) {\r
674 return (EFI_SUCCESS);\r
675 }\r
676\r
677 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
678 if (CommandLineCopy == NULL) {\r
679 return (EFI_OUT_OF_RESOURCES);\r
680 }\r
681 Status = EFI_SUCCESS;\r
682 Split = NULL;\r
683 FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);\r
684\r
685 StripQuotes(CommandLineCopy);\r
686\r
687 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
688 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
689 if (Split != NULL && Split->SplitStdIn != NULL) {\r
690 ShellParameters->StdIn = Split->SplitStdIn;\r
691 }\r
692 if (Split != NULL && Split->SplitStdOut != NULL) {\r
693 ShellParameters->StdOut = Split->SplitStdOut;\r
694 }\r
695 }\r
696\r
697 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {\r
698 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
699 SetMem16(CommandLineWalker, 12, L' ');\r
700 StdErrVarName = CommandLineWalker += 6;\r
701 ErrAppend = TRUE;\r
702 if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {\r
703 Status = EFI_NOT_FOUND;\r
704 }\r
705 }\r
706 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
707 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
708 SetMem16(CommandLineWalker, 12, L' ');\r
709 StdOutVarName = CommandLineWalker += 6;\r
710 OutAppend = TRUE;\r
711 if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {\r
712 Status = EFI_NOT_FOUND;\r
713 }\r
714 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
715 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
716 SetMem16(CommandLineWalker, 10, L' ');\r
717 StdOutVarName = CommandLineWalker += 5;\r
718 OutAppend = TRUE;\r
719 if (StrStr(CommandLineWalker, L" >>v ") != NULL) {\r
720 Status = EFI_NOT_FOUND;\r
721 }\r
722 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
723 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
724 SetMem16(CommandLineWalker, 8, L' ');\r
725 StdOutVarName = CommandLineWalker += 4;\r
726 OutAppend = FALSE;\r
727 if (StrStr(CommandLineWalker, L" >v ") != NULL) {\r
728 Status = EFI_NOT_FOUND;\r
729 }\r
730 }\r
731 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
732 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733 SetMem16(CommandLineWalker, 12, L' ');\r
734 StdOutFileName = CommandLineWalker += 6;\r
735 OutAppend = TRUE;\r
736 OutUnicode = FALSE;\r
737 if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {\r
738 Status = EFI_NOT_FOUND;\r
739 }\r
740 }\r
741 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
742 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
743 SetMem16(CommandLineWalker, 10, L' ');\r
744 if (StdOutFileName != NULL) {\r
745 Status = EFI_INVALID_PARAMETER;\r
746 } else {\r
747 StdOutFileName = CommandLineWalker += 5;\r
748 OutAppend = TRUE;\r
749 }\r
750 if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
751 Status = EFI_NOT_FOUND;\r
752 }\r
753 } \r
754 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
755 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
756 SetMem16(CommandLineWalker, 8, L' ');\r
757 if (StdOutFileName != NULL) {\r
758 Status = EFI_INVALID_PARAMETER;\r
759 } else {\r
760 StdOutFileName = CommandLineWalker += 4;\r
761 OutAppend = TRUE;\r
762 }\r
763 if (StrStr(CommandLineWalker, L" >> ") != NULL) {\r
764 Status = EFI_NOT_FOUND;\r
765 }\r
766 }\r
767 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {\r
768 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
769 SetMem16(CommandLineWalker, 10, L' ');\r
770 if (StdOutFileName != NULL) {\r
771 Status = EFI_INVALID_PARAMETER;\r
772 } else {\r
773 StdOutFileName = CommandLineWalker += 5;\r
774 OutAppend = TRUE;\r
775 OutUnicode = FALSE;\r
776 }\r
777 if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
778 Status = EFI_NOT_FOUND;\r
779 }\r
780 } \r
781 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
782 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
783 SetMem16(CommandLineWalker, 10, L' ');\r
784 if (StdOutFileName != NULL) {\r
785 Status = EFI_INVALID_PARAMETER;\r
786 } else {\r
787 StdOutFileName = CommandLineWalker += 5;\r
788 OutAppend = FALSE;\r
789 OutUnicode = FALSE;\r
790 }\r
791 if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
792 Status = EFI_NOT_FOUND;\r
793 }\r
794 } \r
795 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
796 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
797 SetMem16(CommandLineWalker, 8, L' ');\r
798 if (StdOutFileName != NULL) {\r
799 Status = EFI_INVALID_PARAMETER;\r
800 } else {\r
801 StdOutFileName = CommandLineWalker += 4;\r
802 OutAppend = FALSE;\r
803 OutUnicode = FALSE;\r
804 }\r
805 if (StrStr(CommandLineWalker, L" >a ") != NULL) {\r
806 Status = EFI_NOT_FOUND;\r
807 }\r
808 }\r
809 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
810 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
811 SetMem16(CommandLineWalker, 10, L' ');\r
812 if (StdErrFileName != NULL) {\r
813 Status = EFI_INVALID_PARAMETER;\r
814 } else {\r
815 StdErrFileName = CommandLineWalker += 5;\r
816 ErrAppend = TRUE;\r
817 }\r
818 if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {\r
819 Status = EFI_NOT_FOUND;\r
820 }\r
821 }\r
822\r
823 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
824 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
825 SetMem16(CommandLineWalker, 10, L' ');\r
826 if (StdErrVarName != NULL) {\r
827 Status = EFI_INVALID_PARAMETER;\r
828 } else {\r
829 StdErrVarName = CommandLineWalker += 5;\r
830 ErrAppend = FALSE;\r
831 }\r
832 if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {\r
833 Status = EFI_NOT_FOUND;\r
834 }\r
835 }\r
836 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
837 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
838 SetMem16(CommandLineWalker, 10, L' ');\r
839 if (StdOutVarName != NULL) {\r
840 Status = EFI_INVALID_PARAMETER;\r
841 } else {\r
842 StdOutVarName = CommandLineWalker += 5;\r
843 OutAppend = FALSE;\r
844 }\r
845 if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {\r
846 Status = EFI_NOT_FOUND;\r
847 }\r
848 }\r
849 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
850 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
851 SetMem16(CommandLineWalker, 10, L' ');\r
852 if (StdErrFileName != NULL) {\r
853 Status = EFI_INVALID_PARAMETER;\r
854 } else {\r
855 StdErrFileName = CommandLineWalker += 5;\r
856 ErrAppend = FALSE;\r
857 ErrUnicode = FALSE;\r
858 }\r
859 if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {\r
860 Status = EFI_NOT_FOUND;\r
861 }\r
862 }\r
863 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
864 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
865 SetMem16(CommandLineWalker, 8, L' ');\r
866 if (StdErrFileName != NULL) {\r
867 Status = EFI_INVALID_PARAMETER;\r
868 } else {\r
869 StdErrFileName = CommandLineWalker += 4;\r
870 ErrAppend = FALSE;\r
871 }\r
872 if (StrStr(CommandLineWalker, L" 2> ") != NULL) {\r
873 Status = EFI_NOT_FOUND;\r
874 }\r
875 }\r
876\r
877 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
878 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
879 SetMem16(CommandLineWalker, 8, L' ');\r
880 if (StdOutFileName != NULL) {\r
881 Status = EFI_INVALID_PARAMETER;\r
882 } else {\r
883 StdOutFileName = CommandLineWalker += 4;\r
884 OutAppend = FALSE;\r
885 }\r
886 if (StrStr(CommandLineWalker, L" 1> ") != NULL) {\r
887 Status = EFI_NOT_FOUND;\r
888 }\r
889 }\r
890\r
891 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
892 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
893 SetMem16(CommandLineWalker, 6, L' ');\r
894 if (StdOutFileName != NULL) {\r
895 Status = EFI_INVALID_PARAMETER;\r
896 } else {\r
897 StdOutFileName = CommandLineWalker += 3;\r
898 OutAppend = FALSE;\r
899 }\r
900 if (StrStr(CommandLineWalker, L" > ") != NULL) {\r
901 Status = EFI_NOT_FOUND;\r
902 }\r
903 }\r
904\r
905 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
906 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
907 SetMem16(CommandLineWalker, 6, L' ');\r
908 if (StdInFileName != NULL) {\r
909 Status = EFI_INVALID_PARAMETER;\r
910 } else {\r
911 StdInFileName = CommandLineWalker += 3;\r
912 }\r
913 if (StrStr(CommandLineWalker, L" < ") != NULL) {\r
914 Status = EFI_NOT_FOUND;\r
915 }\r
916 }\r
917 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
918 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
919 SetMem16(CommandLineWalker, 8, L' ');\r
920 if (StdInFileName != NULL) {\r
921 Status = EFI_INVALID_PARAMETER;\r
922 } else {\r
923 StdInFileName = CommandLineWalker += 4;\r
924 InUnicode = FALSE;\r
925 }\r
926 if (StrStr(CommandLineWalker, L" <a ") != NULL) {\r
927 Status = EFI_NOT_FOUND;\r
928 }\r
929 }\r
930 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {\r
931 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
932 SetMem16(CommandLineWalker, 8, L' ');\r
933 if (StdInVarName != NULL) {\r
934 Status = EFI_INVALID_PARAMETER;\r
935 } else {\r
936 StdInVarName = CommandLineWalker += 4;\r
937 }\r
938 if (StrStr(CommandLineWalker, L" <v ") != NULL) {\r
939 Status = EFI_NOT_FOUND;\r
940 }\r
941 }\r
942\r
943 //\r
944 // re-populate the string to support any filenames that were in quotes.\r
945 //\r
946 StrCpy(CommandLineCopy, NewCommandLine);\r
947\r
948 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
949 && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))\r
950 ){\r
951 *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;\r
952 }\r
953\r
954 if (!EFI_ERROR(Status)) {\r
955\r
956 if (StdErrFileName != NULL) {\r
957 if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {\r
958 Status = EFI_INVALID_PARAMETER;\r
959 }\r
960 }\r
961 if (StdOutFileName != NULL) {\r
962 if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {\r
963 Status = EFI_INVALID_PARAMETER;\r
964 }\r
965 }\r
966 if (StdInFileName != NULL) {\r
967 if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {\r
968 Status = EFI_INVALID_PARAMETER;\r
969 }\r
970 }\r
971 if (StdErrVarName != NULL) {\r
972 if ((StdErrVarName = FixVarName(StdErrVarName)) == NULL) {\r
973 Status = EFI_INVALID_PARAMETER;\r
974 }\r
975 }\r
976 if (StdOutVarName != NULL) {\r
977 if ((StdOutVarName = FixVarName(StdOutVarName)) == NULL) {\r
978 Status = EFI_INVALID_PARAMETER;\r
979 }\r
980 }\r
981 if (StdInVarName != NULL) {\r
982 if ((StdInVarName = FixVarName(StdInVarName)) == NULL) {\r
983 Status = EFI_INVALID_PARAMETER;\r
984 }\r
985 }\r
986\r
987 //\r
988 // Verify not the same and not duplicating something from a split\r
989 //\r
990 if (\r
991 //\r
992 // Check that no 2 filenames are the same\r
993 //\r
994 (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
995 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
996 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
997 //\r
998 // Check that no 2 variable names are the same\r
999 //\r
1000 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)\r
1001 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)\r
1002 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)\r
1003 //\r
1004 // When a split (using | operator) is in place some are not allowed\r
1005 //\r
1006 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))\r
1007 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
1008 //\r
1009 // Check that nothing is trying to be output to 2 locations.\r
1010 //\r
1011 ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
1012 ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
1013 ||(StdInFileName != NULL && StdInVarName != NULL)\r
1014 //\r
1015 // Check for no volatile environment variables\r
1016 //\r
1017 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))\r
1018 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))\r
1019 //\r
1020 // Cant redirect during a reconnect operation.\r
1021 //\r
1022 ||(StrStr(NewCommandLine, L"connect -r") != NULL \r
1023 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
1024 //\r
1025 // Check that filetypes (Unicode/Ascii) do not change during an append\r
1026 //\r
1027 ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
1028 ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
1029 ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
1030 ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
1031 ){\r
1032 Status = EFI_INVALID_PARAMETER;\r
1033 ShellParameters->StdIn = *OldStdIn;\r
1034 ShellParameters->StdOut = *OldStdOut;\r
1035 ShellParameters->StdErr = *OldStdErr;\r
1036 } else if (!EFI_ERROR(Status)){\r
1037 //\r
1038 // Open the Std<Whatever> and we should not have conflicts here...\r
1039 //\r
1040\r
1041 //\r
1042 // StdErr to a file\r
1043 //\r
1044 if (StdErrFileName != NULL) {\r
1045 if (!ErrAppend) {\r
1046 //\r
1047 // delete existing file.\r
1048 //\r
1049 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);\r
1050 }\r
1051 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
1052 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
1053 //\r
1054 // Write out the gUnicodeFileTag\r
1055 //\r
1056 Size = sizeof(CHAR16);\r
1057 TagBuffer[0] = gUnicodeFileTag;\r
1058 TagBuffer[1] = CHAR_NULL;\r
1059 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
1060 }\r
1061 if (!ErrUnicode && !EFI_ERROR(Status)) {\r
1062 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1063 ASSERT(TempHandle != NULL);\r
1064 }\r
1065 if (!EFI_ERROR(Status)) {\r
1066 ShellParameters->StdErr = TempHandle;\r
1067 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);\r
1068 }\r
1069 }\r
1070\r
1071 //\r
1072 // StdOut to a file\r
1073 //\r
1074 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {\r
1075 if (!OutAppend) {\r
1076 //\r
1077 // delete existing file.\r
1078 //\r
1079 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);\r
1080 }\r
1081 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
1082 if (TempHandle == NULL) {\r
1083 Status = EFI_INVALID_PARAMETER;\r
1084 } else {\r
1085 if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {\r
1086 //no-op\r
1087 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
1088 //\r
1089 // Write out the gUnicodeFileTag\r
1090 //\r
1091 Size = sizeof(CHAR16);\r
1092 TagBuffer[0] = gUnicodeFileTag;\r
1093 TagBuffer[1] = CHAR_NULL;\r
1094 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
1095 } else if (OutAppend) {\r
1096 //\r
1097 // Move to end of file\r
1098 //\r
1099 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);\r
1100 if (!EFI_ERROR(Status)) {\r
1101 Status = ShellInfoObject.NewEfiShellProtocol->SetFilePosition(TempHandle, FileSize);\r
1102 }\r
1103 }\r
1104 if (!OutUnicode && !EFI_ERROR(Status)) {\r
1105 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1106 ASSERT(TempHandle != NULL);\r
1107 }\r
1108 if (!EFI_ERROR(Status)) {\r
1109 ShellParameters->StdOut = TempHandle;\r
1110 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);\r
1111 }\r
1112 }\r
1113 }\r
1114\r
1115 //\r
1116 // StdOut to a var\r
1117 //\r
1118 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {\r
1119 if (!OutAppend) {\r
1120 //\r
1121 // delete existing variable.\r
1122 //\r
1123 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");\r
1124 }\r
1125 TempHandle = CreateFileInterfaceEnv(StdOutVarName);\r
1126 ASSERT(TempHandle != NULL);\r
1127 ShellParameters->StdOut = TempHandle;\r
1128 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);\r
1129 }\r
1130\r
1131 //\r
1132 // StdErr to a var\r
1133 //\r
1134 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {\r
1135 if (!ErrAppend) {\r
1136 //\r
1137 // delete existing variable.\r
1138 //\r
1139 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");\r
1140 }\r
1141 TempHandle = CreateFileInterfaceEnv(StdErrVarName);\r
1142 ASSERT(TempHandle != NULL);\r
1143 ShellParameters->StdErr = TempHandle;\r
1144 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);\r
1145 }\r
1146\r
1147 //\r
1148 // StdIn from a var\r
1149 //\r
1150 if (!EFI_ERROR(Status) && StdInVarName != NULL) {\r
1151 TempHandle = CreateFileInterfaceEnv(StdInVarName);\r
1152 if (TempHandle == NULL) {\r
1153 Status = EFI_OUT_OF_RESOURCES;\r
1154 } else {\r
1155 if (!InUnicode) {\r
1156 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1157 }\r
1158 Size = 0;\r
1159 if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
1160 Status = EFI_INVALID_PARAMETER;\r
1161 } else {\r
1162 ShellParameters->StdIn = TempHandle;\r
1163 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1164 }\r
1165 }\r
1166 }\r
1167\r
1168 //\r
1169 // StdIn from a file\r
1170 //\r
1171 if (!EFI_ERROR(Status) && StdInFileName != NULL) {\r
1172 Status = ShellOpenFileByName(\r
1173 StdInFileName,\r
1174 &TempHandle,\r
1175 EFI_FILE_MODE_READ,\r
1176 0);\r
1177 if (InUnicode) {\r
1178 //\r
1179 // Chop off the 0xFEFF if it's there...\r
1180 //\r
1181 RemoveFileTag(&TempHandle);\r
1182 } else if (!EFI_ERROR(Status)) {\r
1183 //\r
1184 // Create the ASCII->Unicode conversion layer\r
1185 //\r
1186 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1187 }\r
1188 if (!EFI_ERROR(Status)) {\r
1189 ShellParameters->StdIn = TempHandle;\r
1190 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1191 }\r
1192 }\r
1193 }\r
1194 }\r
1195 FreePool(CommandLineCopy);\r
1196\r
1197 CalculateEfiHdrCrc(&gST->Hdr);\r
1198\r
1199 if (gST->ConIn == NULL ||gST->ConOut == NULL) {\r
1200 Status = EFI_OUT_OF_RESOURCES;\r
1201 }\r
1202\r
1203 if (Status == EFI_NOT_FOUND) {\r
1204 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle);\r
1205 } else if (EFI_ERROR(Status)) {\r
1206 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);\r
1207 }\r
1208\r
1209 return (Status);\r
1210}\r
1211\r
1212/**\r
1213 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
1214 structure with StdIn and StdOut. The current values are de-allocated.\r
1215\r
1216 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1217 @param[in] OldStdIn Pointer to old StdIn.\r
1218 @param[in] OldStdOut Pointer to old StdOut.\r
1219 @param[in] OldStdErr Pointer to old StdErr.\r
1220 @param[in] SystemTableInfo Pointer to old system table information.\r
1221**/\r
1222EFI_STATUS\r
1223EFIAPI\r
1224RestoreStdInStdOutStdErr (\r
1225 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1226 IN SHELL_FILE_HANDLE *OldStdIn,\r
1227 IN SHELL_FILE_HANDLE *OldStdOut,\r
1228 IN SHELL_FILE_HANDLE *OldStdErr,\r
1229 IN SYSTEM_TABLE_INFO *SystemTableInfo\r
1230 )\r
1231{\r
1232 SPLIT_LIST *Split;\r
1233\r
1234 if (ShellParameters == NULL \r
1235 ||OldStdIn == NULL\r
1236 ||OldStdOut == NULL\r
1237 ||OldStdErr == NULL\r
1238 ||SystemTableInfo == NULL) {\r
1239 return (EFI_INVALID_PARAMETER);\r
1240 }\r
1241 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
1242 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
1243 } else {\r
1244 Split = NULL;\r
1245 }\r
1246 if (ShellParameters->StdIn != *OldStdIn) {\r
1247 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
1248 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
1249 }\r
1250 ShellParameters->StdIn = *OldStdIn;\r
1251 }\r
1252 if (ShellParameters->StdOut != *OldStdOut) {\r
1253 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
1254 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
1255 }\r
1256 ShellParameters->StdOut = *OldStdOut;\r
1257 }\r
1258 if (ShellParameters->StdErr != *OldStdErr) {\r
1259 gEfiShellProtocol->CloseFile(ShellParameters->StdErr);\r
1260 ShellParameters->StdErr = *OldStdErr;\r
1261 }\r
1262\r
1263 if (gST->ConIn != SystemTableInfo->ConIn) {\r
1264 CloseSimpleTextInOnFile(gST->ConIn);\r
1265 gST->ConIn = SystemTableInfo->ConIn;\r
1266 gST->ConsoleInHandle = SystemTableInfo->ConInHandle;\r
1267 }\r
1268 if (gST->ConOut != SystemTableInfo->ConOut) {\r
1269 CloseSimpleTextOutOnFile(gST->ConOut);\r
1270 gST->ConOut = SystemTableInfo->ConOut;\r
1271 gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;\r
1272 }\r
1273 if (gST->StdErr != SystemTableInfo->ErrOut) {\r
1274 CloseSimpleTextOutOnFile(gST->StdErr);\r
1275 gST->StdErr = SystemTableInfo->ErrOut;\r
1276 gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle;\r
1277 }\r
1278\r
1279 CalculateEfiHdrCrc(&gST->Hdr);\r
1280\r
1281 return (EFI_SUCCESS);\r
1282}\r
1283/**\r
1284 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1285 structure by parsing NewCommandLine. The current values are returned to the\r
1286 user.\r
1287\r
1288 If OldArgv or OldArgc is NULL then that value is not returned.\r
1289\r
1290 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1291 @param[in] NewCommandLine The new command line to parse and use.\r
1292 @param[out] OldArgv Pointer to old list of parameters.\r
1293 @param[out] OldArgc Pointer to old number of items in Argv list.\r
1294\r
1295 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
1296 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1297**/\r
1298EFI_STATUS\r
1299EFIAPI\r
1300UpdateArgcArgv(\r
1301 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1302 IN CONST CHAR16 *NewCommandLine,\r
1303 OUT CHAR16 ***OldArgv OPTIONAL,\r
1304 OUT UINTN *OldArgc OPTIONAL\r
1305 )\r
1306{\r
1307 ASSERT(ShellParameters != NULL);\r
1308\r
1309 if (OldArgc != NULL) {\r
1310 *OldArgc = ShellParameters->Argc;\r
1311 }\r
1312 if (OldArgc != NULL) {\r
1313 *OldArgv = ShellParameters->Argv;\r
1314 }\r
1315\r
1316 return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));\r
1317}\r
1318\r
1319/**\r
1320 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1321 structure with Argv and Argc. The current values are de-allocated and the\r
1322 OldArgv must not be deallocated by the caller.\r
1323\r
1324 @param[in, out] ShellParameters pointer to parameter structure to modify\r
1325 @param[in] OldArgv pointer to old list of parameters\r
1326 @param[in] OldArgc pointer to old number of items in Argv list\r
1327**/\r
1328VOID\r
1329EFIAPI\r
1330RestoreArgcArgv(\r
1331 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1332 IN CHAR16 ***OldArgv,\r
1333 IN UINTN *OldArgc\r
1334 )\r
1335{\r
1336 UINTN LoopCounter;\r
1337 ASSERT(ShellParameters != NULL);\r
1338 ASSERT(OldArgv != NULL);\r
1339 ASSERT(OldArgc != NULL);\r
1340\r
1341 if (ShellParameters->Argv != NULL) {\r
1342 for ( LoopCounter = 0\r
1343 ; LoopCounter < ShellParameters->Argc\r
1344 ; LoopCounter++\r
1345 ){\r
1346 FreePool(ShellParameters->Argv[LoopCounter]);\r
1347 }\r
1348 FreePool(ShellParameters->Argv);\r
1349 }\r
1350 ShellParameters->Argv = *OldArgv;\r
1351 *OldArgv = NULL;\r
1352 ShellParameters->Argc = *OldArgc;\r
1353 *OldArgc = 0;\r
1354}\r