Update the comments in function headers to follow Doxygen special documentation block...
[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
dcf9b428 5 Copyright (c) 2013 Hewlett-Packard Development Company, L.P.\r
49bb76ff 6 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
a405b86d 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
0406a571 17#include "Shell.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
4ff7e37b 29 @param[in, out] Walker pointer to string of command line. Adjusted to\r
a405b86d 30 reminaing command line on return\r
4ff7e37b 31 @param[in, out] TempParameter pointer to string of command line item extracted.\r
a405b86d 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
d8f8021c 72 if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {\r
a405b86d 73 TempLoc++;\r
a405b86d 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
d8f8021c 97 if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {\r
a405b86d 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
d8f8021c 121 }\r
a405b86d 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
733f138d 134 Function to populate Argc and Argv.\r
a405b86d 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
4ff7e37b
ED
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
a405b86d 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
3f869579 195 SHELL_FREE_NON_NULL(TempParameter);\r
a405b86d 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
3f869579 211 SHELL_FREE_NON_NULL(TempParameter);\r
a405b86d 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
4ff7e37b 220 @param[in, out] NewShellParameters on a successful return, a pointer to pointer\r
a405b86d 221 to the newly installed interface.\r
4ff7e37b 222 @param[in, out] RootShellInstance on a successful return, pointer to boolean.\r
a405b86d 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
3c865f20 275 if ((*NewShellParameters) == NULL) {\r
276 return (EFI_OUT_OF_RESOURCES);\r
277 }\r
a405b86d 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
e886b675 294 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);\r
a405b86d 295 if (Status == EFI_BUFFER_TOO_SMALL) {\r
296 FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);\r
e886b675 297 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);\r
a405b86d 298 }\r
299 if (Status == EFI_NOT_FOUND) {\r
300 //\r
301 // no parameters via environment... ok\r
302 //\r
303 } else {\r
3c865f20 304 if (EFI_ERROR(Status)) {\r
305 return (Status);\r
306 }\r
a405b86d 307 }\r
308 if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {\r
3c865f20 309 ASSERT(FullCommandLine == NULL);\r
a405b86d 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
a405b86d 316 if (FullCommandLine != NULL) {\r
2c5a8aed 317 CopyMem (FullCommandLine, LoadedImage->LoadOptions, LoadedImage->LoadOptionsSize);\r
a405b86d 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
ae724571 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
733f138d 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
fb84495a 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
a1d4bfcc 451\r
4ff7e37b 452 @param[in, out] TheString A pointer to the string to update.\r
fb84495a 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
cf6a8f14 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
031acf63 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
f9aefb6a 526 while(Copy[0] == L' ') {\r
527 Copy++;\r
528 }\r
031acf63 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
6813ba40
JC
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
49bb76ff
JC
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
f614ce7e
SQ
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
49bb76ff
JC
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
a405b86d 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
8be0ba36 601 This will also update the system table.\r
a405b86d 602\r
4ff7e37b
ED
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
a405b86d 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
fb84495a 617 IN CHAR16 *NewCommandLine,\r
a405b86d 618 OUT SHELL_FILE_HANDLE *OldStdIn,\r
619 OUT SHELL_FILE_HANDLE *OldStdOut,\r
8be0ba36 620 OUT SHELL_FILE_HANDLE *OldStdErr,\r
621 OUT SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 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
fb84495a 643 CHAR16 *FirstLocation;\r
a405b86d 644\r
a405b86d 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
5f2915f5 657 FirstLocation = NULL;\r
a405b86d 658\r
8be0ba36 659 if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {\r
660 return (EFI_INVALID_PARAMETER);\r
a405b86d 661 }\r
662\r
8be0ba36 663 SystemTableInfo->ConIn = gST->ConIn;\r
664 SystemTableInfo->ConInHandle = gST->ConsoleInHandle;\r
665 SystemTableInfo->ConOut = gST->ConOut;\r
666 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;\r
4ccd9214
ED
667 SystemTableInfo->ErrOut = gST->StdErr;\r
668 SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle;\r
8be0ba36 669 *OldStdIn = ShellParameters->StdIn;\r
670 *OldStdOut = ShellParameters->StdOut;\r
671 *OldStdErr = ShellParameters->StdErr;\r
672\r
a405b86d 673 if (NewCommandLine == NULL) {\r
674 return (EFI_SUCCESS);\r
675 }\r
676\r
677 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
532691c8 678 if (CommandLineCopy == NULL) {\r
679 return (EFI_OUT_OF_RESOURCES);\r
680 }\r
a405b86d 681 Status = EFI_SUCCESS;\r
682 Split = NULL;\r
5f2915f5 683 FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);\r
a405b86d 684\r
fb84495a 685 StripQuotes(CommandLineCopy);\r
686\r
a405b86d 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
fb84495a 698 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 699 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 700 StdErrVarName = CommandLineWalker += 6;\r
701 ErrAppend = TRUE;\r
733f138d 702 if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {\r
703 Status = EFI_NOT_FOUND;\r
704 }\r
a405b86d 705 }\r
706 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
fb84495a 707 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 708 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 709 StdOutVarName = CommandLineWalker += 6;\r
710 OutAppend = TRUE;\r
733f138d 711 if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {\r
712 Status = EFI_NOT_FOUND;\r
713 }\r
a405b86d 714 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
fb84495a 715 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 716 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 717 StdOutVarName = CommandLineWalker += 5;\r
718 OutAppend = TRUE;\r
733f138d 719 if (StrStr(CommandLineWalker, L" >>v ") != NULL) {\r
720 Status = EFI_NOT_FOUND;\r
721 }\r
a405b86d 722 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
fb84495a 723 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 724 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 725 StdOutVarName = CommandLineWalker += 4;\r
726 OutAppend = FALSE;\r
733f138d 727 if (StrStr(CommandLineWalker, L" >v ") != NULL) {\r
728 Status = EFI_NOT_FOUND;\r
729 }\r
a405b86d 730 }\r
731 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
fb84495a 732 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 733 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 734 StdOutFileName = CommandLineWalker += 6;\r
735 OutAppend = TRUE;\r
736 OutUnicode = FALSE;\r
733f138d 737 if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {\r
738 Status = EFI_NOT_FOUND;\r
739 }\r
a405b86d 740 }\r
741 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
fb84495a 742 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 743 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 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
733f138d 750 if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
751 Status = EFI_NOT_FOUND;\r
752 }\r
a405b86d 753 } \r
754 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
fb84495a 755 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 756 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 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
733f138d 763 if (StrStr(CommandLineWalker, L" >> ") != NULL) {\r
764 Status = EFI_NOT_FOUND;\r
765 }\r
a405b86d 766 }\r
767 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {\r
fb84495a 768 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 769 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 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
733f138d 777 if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
778 Status = EFI_NOT_FOUND;\r
779 }\r
a405b86d 780 } \r
781 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
fb84495a 782 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 783 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 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
733f138d 791 if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
792 Status = EFI_NOT_FOUND;\r
793 }\r
a405b86d 794 } \r
795 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
fb84495a 796 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 797 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 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
733f138d 805 if (StrStr(CommandLineWalker, L" >a ") != NULL) {\r
806 Status = EFI_NOT_FOUND;\r
807 }\r
a405b86d 808 }\r
809 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
fb84495a 810 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 811 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 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
733f138d 818 if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {\r
819 Status = EFI_NOT_FOUND;\r
820 }\r
a405b86d 821 }\r
822\r
823 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
fb84495a 824 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 825 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 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
733f138d 832 if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {\r
833 Status = EFI_NOT_FOUND;\r
834 }\r
a405b86d 835 }\r
836 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
fb84495a 837 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 838 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 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
733f138d 845 if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {\r
846 Status = EFI_NOT_FOUND;\r
847 }\r
a405b86d 848 }\r
849 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
fb84495a 850 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 851 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 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
733f138d 859 if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {\r
860 Status = EFI_NOT_FOUND;\r
861 }\r
a405b86d 862 }\r
863 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
fb84495a 864 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 865 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 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
733f138d 872 if (StrStr(CommandLineWalker, L" 2> ") != NULL) {\r
873 Status = EFI_NOT_FOUND;\r
874 }\r
a405b86d 875 }\r
876\r
877 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
fb84495a 878 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 879 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 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
733f138d 886 if (StrStr(CommandLineWalker, L" 1> ") != NULL) {\r
887 Status = EFI_NOT_FOUND;\r
888 }\r
a405b86d 889 }\r
890\r
891 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
fb84495a 892 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 893 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 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
733f138d 900 if (StrStr(CommandLineWalker, L" > ") != NULL) {\r
901 Status = EFI_NOT_FOUND;\r
902 }\r
a405b86d 903 }\r
904\r
905 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
fb84495a 906 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 907 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 908 if (StdInFileName != NULL) {\r
909 Status = EFI_INVALID_PARAMETER;\r
910 } else {\r
911 StdInFileName = CommandLineWalker += 3;\r
733f138d 912 }\r
913 if (StrStr(CommandLineWalker, L" < ") != NULL) {\r
914 Status = EFI_NOT_FOUND;\r
a405b86d 915 }\r
916 }\r
917 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
fb84495a 918 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 919 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 920 if (StdInFileName != NULL) {\r
921 Status = EFI_INVALID_PARAMETER;\r
922 } else {\r
733f138d 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
a405b86d 928 }\r
929 }\r
930 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {\r
fb84495a 931 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 932 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 933 if (StdInVarName != NULL) {\r
934 Status = EFI_INVALID_PARAMETER;\r
935 } else {\r
936 StdInVarName = CommandLineWalker += 4;\r
733f138d 937 }\r
938 if (StrStr(CommandLineWalker, L" <v ") != NULL) {\r
939 Status = EFI_NOT_FOUND;\r
a405b86d 940 }\r
941 }\r
942\r
031acf63 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
5f2915f5 948 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
fb84495a 949 && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))\r
950 ){\r
951 *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;\r
952 }\r
953\r
a405b86d 954 if (!EFI_ERROR(Status)) {\r
031acf63 955\r
956 if (StdErrFileName != NULL) {\r
957 if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {\r
958 Status = EFI_INVALID_PARAMETER;\r
959 }\r
a405b86d 960 }\r
031acf63 961 if (StdOutFileName != NULL) {\r
962 if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {\r
963 Status = EFI_INVALID_PARAMETER;\r
964 }\r
a405b86d 965 }\r
031acf63 966 if (StdInFileName != NULL) {\r
967 if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {\r
968 Status = EFI_INVALID_PARAMETER;\r
969 }\r
a405b86d 970 }\r
031acf63 971 if (StdErrVarName != NULL) {\r
6813ba40 972 if ((StdErrVarName = FixVarName(StdErrVarName)) == NULL) {\r
031acf63 973 Status = EFI_INVALID_PARAMETER;\r
974 }\r
a405b86d 975 }\r
031acf63 976 if (StdOutVarName != NULL) {\r
6813ba40 977 if ((StdOutVarName = FixVarName(StdOutVarName)) == NULL) {\r
031acf63 978 Status = EFI_INVALID_PARAMETER;\r
979 }\r
a405b86d 980 }\r
031acf63 981 if (StdInVarName != NULL) {\r
6813ba40 982 if ((StdInVarName = FixVarName(StdInVarName)) == NULL) {\r
031acf63 983 Status = EFI_INVALID_PARAMETER;\r
984 }\r
a405b86d 985 }\r
986\r
0c956e0d 987 //\r
988 // Verify not the same and not duplicating something from a split\r
989 //\r
733f138d 990 if (\r
991 //\r
992 // Check that no 2 filenames are the same\r
993 //\r
fb84495a 994 (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
a405b86d 995 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
996 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
733f138d 997 //\r
998 // Check that no 2 variable names are the same\r
999 //\r
a405b86d 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
733f138d 1003 //\r
1004 // When a split (using | operator) is in place some are not allowed\r
1005 //\r
a405b86d 1006 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))\r
1007 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
733f138d 1008 //\r
1009 // Check that nothing is trying to be output to 2 locations.\r
1010 //\r
a405b86d 1011 ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
1012 ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
1013 ||(StdInFileName != NULL && StdInVarName != NULL)\r
733f138d 1014 //\r
733f138d 1015 // Check for no volatile environment variables\r
1016 //\r
a405b86d 1017 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))\r
1018 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))\r
733f138d 1019 //\r
1020 // Cant redirect during a reconnect operation.\r
1021 //\r
3c865f20 1022 ||(StrStr(NewCommandLine, L"connect -r") != NULL \r
1023 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
733f138d 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
a405b86d 1031 ){\r
1032 Status = EFI_INVALID_PARAMETER;\r
a9ca0684 1033 ShellParameters->StdIn = *OldStdIn;\r
1034 ShellParameters->StdOut = *OldStdOut;\r
1035 ShellParameters->StdErr = *OldStdErr;\r
fb84495a 1036 } else if (!EFI_ERROR(Status)){\r
a405b86d 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
a405b86d 1052 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
1053 //\r
733f138d 1054 // Write out the gUnicodeFileTag\r
a405b86d 1055 //\r
1056 Size = sizeof(CHAR16);\r
733f138d 1057 TagBuffer[0] = gUnicodeFileTag;\r
a405b86d 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
dcf9b428 1067 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);\r
a405b86d 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
3c865f20 1082 if (TempHandle == NULL) {\r
1083 Status = EFI_INVALID_PARAMETER;\r
1084 } else {\r
733f138d 1085 if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {\r
1086 //no-op\r
1087 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
3c865f20 1088 //\r
733f138d 1089 // Write out the gUnicodeFileTag\r
3c865f20 1090 //\r
1091 Size = sizeof(CHAR16);\r
733f138d 1092 TagBuffer[0] = gUnicodeFileTag;\r
3c865f20 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
a405b86d 1108 if (!EFI_ERROR(Status)) {\r
3c865f20 1109 ShellParameters->StdOut = TempHandle;\r
dcf9b428 1110 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);\r
a405b86d 1111 }\r
1112 }\r
a405b86d 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
a405b86d 1127 ShellParameters->StdOut = TempHandle;\r
dcf9b428 1128 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);\r
a405b86d 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
a405b86d 1143 ShellParameters->StdErr = TempHandle;\r
dcf9b428 1144 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);\r
a405b86d 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
532691c8 1152 if (TempHandle == NULL) {\r
1153 Status = EFI_OUT_OF_RESOURCES;\r
a405b86d 1154 } else {\r
532691c8 1155 if (!InUnicode) {\r
1156 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1157 }\r
1158 Size = 0;\r
96962f0a 1159 if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
532691c8 1160 Status = EFI_INVALID_PARAMETER;\r
1161 } else {\r
1162 ShellParameters->StdIn = TempHandle;\r
1163 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1164 }\r
a405b86d 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
49bb76ff
JC
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
a405b86d 1186 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1187 }\r
1188 if (!EFI_ERROR(Status)) {\r
1189 ShellParameters->StdIn = TempHandle;\r
8be0ba36 1190 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
a405b86d 1191 }\r
1192 }\r
1193 }\r
1194 }\r
1195 FreePool(CommandLineCopy);\r
8be0ba36 1196\r
cf6a8f14 1197 CalculateEfiHdrCrc(&gST->Hdr);\r
1198\r
8be0ba36 1199 if (gST->ConIn == NULL ||gST->ConOut == NULL) {\r
cc31ac1e 1200 Status = EFI_OUT_OF_RESOURCES;\r
8be0ba36 1201 }\r
cc31ac1e
JC
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
a405b86d 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
4ff7e37b
ED
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
a405b86d 1221**/\r
1222EFI_STATUS\r
1223EFIAPI\r
1224RestoreStdInStdOutStdErr (\r
1225 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
8be0ba36 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
a405b86d 1230 )\r
1231{\r
1232 SPLIT_LIST *Split;\r
8be0ba36 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
a405b86d 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
8be0ba36 1246 if (ShellParameters->StdIn != *OldStdIn) {\r
a405b86d 1247 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
1248 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
1249 }\r
8be0ba36 1250 ShellParameters->StdIn = *OldStdIn;\r
a405b86d 1251 }\r
8be0ba36 1252 if (ShellParameters->StdOut != *OldStdOut) {\r
a405b86d 1253 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
1254 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
1255 }\r
8be0ba36 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
a405b86d 1267 }\r
8be0ba36 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
4ccd9214 1273 if (gST->StdErr != SystemTableInfo->ErrOut) {\r
8be0ba36 1274 CloseSimpleTextOutOnFile(gST->StdErr);\r
4ccd9214
ED
1275 gST->StdErr = SystemTableInfo->ErrOut;\r
1276 gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle;\r
8be0ba36 1277 }\r
1278\r
cf6a8f14 1279 CalculateEfiHdrCrc(&gST->Hdr);\r
1280\r
a405b86d 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
4ff7e37b
ED
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
a405b86d 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
4ff7e37b
ED
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
a405b86d 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