]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Application/Shell/ShellParametersProtocol.c
ShellPkg: remove unreachable break statements
[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
2c5a8aed 6 Copyright (c) 2009 - 2013, 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
a405b86d 570/**\r
571 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
572 structure by parsing NewCommandLine. The current values are returned to the\r
573 user.\r
574\r
8be0ba36 575 This will also update the system table.\r
a405b86d 576\r
4ff7e37b
ED
577 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
578 @param[in] NewCommandLine The new command line to parse and use.\r
579 @param[out] OldStdIn Pointer to old StdIn.\r
580 @param[out] OldStdOut Pointer to old StdOut.\r
581 @param[out] OldStdErr Pointer to old StdErr.\r
582 @param[out] SystemTableInfo Pointer to old system table information.\r
a405b86d 583\r
584 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
585 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
586**/\r
587EFI_STATUS\r
588EFIAPI\r
589UpdateStdInStdOutStdErr(\r
590 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
fb84495a 591 IN CHAR16 *NewCommandLine,\r
a405b86d 592 OUT SHELL_FILE_HANDLE *OldStdIn,\r
593 OUT SHELL_FILE_HANDLE *OldStdOut,\r
8be0ba36 594 OUT SHELL_FILE_HANDLE *OldStdErr,\r
595 OUT SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 596 )\r
597{\r
598 CHAR16 *CommandLineCopy;\r
599 CHAR16 *CommandLineWalker;\r
600 CHAR16 *StdErrFileName;\r
601 CHAR16 *StdOutFileName;\r
602 CHAR16 *StdInFileName;\r
603 CHAR16 *StdInVarName;\r
604 CHAR16 *StdOutVarName;\r
605 CHAR16 *StdErrVarName;\r
606 EFI_STATUS Status;\r
607 SHELL_FILE_HANDLE TempHandle;\r
608 UINT64 FileSize;\r
609 BOOLEAN OutUnicode;\r
610 BOOLEAN InUnicode;\r
611 BOOLEAN ErrUnicode;\r
612 BOOLEAN OutAppend;\r
613 BOOLEAN ErrAppend;\r
614 UINTN Size;\r
615 CHAR16 TagBuffer[2];\r
616 SPLIT_LIST *Split;\r
fb84495a 617 CHAR16 *FirstLocation;\r
a405b86d 618\r
a405b86d 619 OutUnicode = TRUE;\r
620 InUnicode = TRUE;\r
621 ErrUnicode = TRUE;\r
622 StdInVarName = NULL;\r
623 StdOutVarName = NULL;\r
624 StdErrVarName = NULL;\r
625 StdErrFileName = NULL;\r
626 StdInFileName = NULL;\r
627 StdOutFileName = NULL;\r
628 ErrAppend = FALSE;\r
629 OutAppend = FALSE;\r
630 CommandLineCopy = NULL;\r
5f2915f5 631 FirstLocation = NULL;\r
a405b86d 632\r
8be0ba36 633 if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {\r
634 return (EFI_INVALID_PARAMETER);\r
a405b86d 635 }\r
636\r
8be0ba36 637 SystemTableInfo->ConIn = gST->ConIn;\r
638 SystemTableInfo->ConInHandle = gST->ConsoleInHandle;\r
639 SystemTableInfo->ConOut = gST->ConOut;\r
640 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;\r
4ccd9214
ED
641 SystemTableInfo->ErrOut = gST->StdErr;\r
642 SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle;\r
8be0ba36 643 *OldStdIn = ShellParameters->StdIn;\r
644 *OldStdOut = ShellParameters->StdOut;\r
645 *OldStdErr = ShellParameters->StdErr;\r
646\r
a405b86d 647 if (NewCommandLine == NULL) {\r
648 return (EFI_SUCCESS);\r
649 }\r
650\r
651 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
532691c8 652 if (CommandLineCopy == NULL) {\r
653 return (EFI_OUT_OF_RESOURCES);\r
654 }\r
a405b86d 655 Status = EFI_SUCCESS;\r
656 Split = NULL;\r
5f2915f5 657 FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);\r
a405b86d 658\r
fb84495a 659 StripQuotes(CommandLineCopy);\r
660\r
a405b86d 661 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
662 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
663 if (Split != NULL && Split->SplitStdIn != NULL) {\r
664 ShellParameters->StdIn = Split->SplitStdIn;\r
665 }\r
666 if (Split != NULL && Split->SplitStdOut != NULL) {\r
667 ShellParameters->StdOut = Split->SplitStdOut;\r
668 }\r
669 }\r
670\r
671 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {\r
fb84495a 672 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 673 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 674 StdErrVarName = CommandLineWalker += 6;\r
675 ErrAppend = TRUE;\r
733f138d 676 if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {\r
677 Status = EFI_NOT_FOUND;\r
678 }\r
a405b86d 679 }\r
680 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
fb84495a 681 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 682 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 683 StdOutVarName = CommandLineWalker += 6;\r
684 OutAppend = TRUE;\r
733f138d 685 if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {\r
686 Status = EFI_NOT_FOUND;\r
687 }\r
a405b86d 688 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
fb84495a 689 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 690 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 691 StdOutVarName = CommandLineWalker += 5;\r
692 OutAppend = TRUE;\r
733f138d 693 if (StrStr(CommandLineWalker, L" >>v ") != NULL) {\r
694 Status = EFI_NOT_FOUND;\r
695 }\r
a405b86d 696 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
fb84495a 697 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 698 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 699 StdOutVarName = CommandLineWalker += 4;\r
700 OutAppend = FALSE;\r
733f138d 701 if (StrStr(CommandLineWalker, L" >v ") != NULL) {\r
702 Status = EFI_NOT_FOUND;\r
703 }\r
a405b86d 704 }\r
705 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
fb84495a 706 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 707 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 708 StdOutFileName = CommandLineWalker += 6;\r
709 OutAppend = TRUE;\r
710 OutUnicode = FALSE;\r
733f138d 711 if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {\r
712 Status = EFI_NOT_FOUND;\r
713 }\r
a405b86d 714 }\r
715 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
fb84495a 716 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 717 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 718 if (StdOutFileName != NULL) {\r
719 Status = EFI_INVALID_PARAMETER;\r
720 } else {\r
721 StdOutFileName = CommandLineWalker += 5;\r
722 OutAppend = TRUE;\r
723 }\r
733f138d 724 if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
725 Status = EFI_NOT_FOUND;\r
726 }\r
a405b86d 727 } \r
728 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
fb84495a 729 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 730 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 731 if (StdOutFileName != NULL) {\r
732 Status = EFI_INVALID_PARAMETER;\r
733 } else {\r
734 StdOutFileName = CommandLineWalker += 4;\r
735 OutAppend = TRUE;\r
736 }\r
733f138d 737 if (StrStr(CommandLineWalker, L" >> ") != NULL) {\r
738 Status = EFI_NOT_FOUND;\r
739 }\r
a405b86d 740 }\r
741 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != 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 OutUnicode = FALSE;\r
750 }\r
733f138d 751 if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
752 Status = EFI_NOT_FOUND;\r
753 }\r
a405b86d 754 } \r
755 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
fb84495a 756 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 757 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 758 if (StdOutFileName != NULL) {\r
759 Status = EFI_INVALID_PARAMETER;\r
760 } else {\r
761 StdOutFileName = CommandLineWalker += 5;\r
762 OutAppend = FALSE;\r
763 OutUnicode = FALSE;\r
764 }\r
733f138d 765 if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
766 Status = EFI_NOT_FOUND;\r
767 }\r
a405b86d 768 } \r
769 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
fb84495a 770 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 771 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 772 if (StdOutFileName != NULL) {\r
773 Status = EFI_INVALID_PARAMETER;\r
774 } else {\r
775 StdOutFileName = CommandLineWalker += 4;\r
776 OutAppend = FALSE;\r
777 OutUnicode = FALSE;\r
778 }\r
733f138d 779 if (StrStr(CommandLineWalker, L" >a ") != NULL) {\r
780 Status = EFI_NOT_FOUND;\r
781 }\r
a405b86d 782 }\r
783 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
fb84495a 784 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 785 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 786 if (StdErrFileName != NULL) {\r
787 Status = EFI_INVALID_PARAMETER;\r
788 } else {\r
789 StdErrFileName = CommandLineWalker += 5;\r
790 ErrAppend = TRUE;\r
791 }\r
733f138d 792 if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {\r
793 Status = EFI_NOT_FOUND;\r
794 }\r
a405b86d 795 }\r
796\r
797 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
fb84495a 798 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 799 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 800 if (StdErrVarName != NULL) {\r
801 Status = EFI_INVALID_PARAMETER;\r
802 } else {\r
803 StdErrVarName = CommandLineWalker += 5;\r
804 ErrAppend = FALSE;\r
805 }\r
733f138d 806 if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {\r
807 Status = EFI_NOT_FOUND;\r
808 }\r
a405b86d 809 }\r
810 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
fb84495a 811 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 812 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 813 if (StdOutVarName != NULL) {\r
814 Status = EFI_INVALID_PARAMETER;\r
815 } else {\r
816 StdOutVarName = CommandLineWalker += 5;\r
817 OutAppend = FALSE;\r
818 }\r
733f138d 819 if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {\r
820 Status = EFI_NOT_FOUND;\r
821 }\r
a405b86d 822 }\r
823 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
fb84495a 824 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 825 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 826 if (StdErrFileName != NULL) {\r
827 Status = EFI_INVALID_PARAMETER;\r
828 } else {\r
829 StdErrFileName = CommandLineWalker += 5;\r
830 ErrAppend = FALSE;\r
831 ErrUnicode = FALSE;\r
832 }\r
733f138d 833 if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {\r
834 Status = EFI_NOT_FOUND;\r
835 }\r
a405b86d 836 }\r
837 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
fb84495a 838 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 839 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 840 if (StdErrFileName != NULL) {\r
841 Status = EFI_INVALID_PARAMETER;\r
842 } else {\r
843 StdErrFileName = CommandLineWalker += 4;\r
844 ErrAppend = FALSE;\r
845 }\r
733f138d 846 if (StrStr(CommandLineWalker, L" 2> ") != NULL) {\r
847 Status = EFI_NOT_FOUND;\r
848 }\r
a405b86d 849 }\r
850\r
851 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
fb84495a 852 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 853 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 854 if (StdOutFileName != NULL) {\r
855 Status = EFI_INVALID_PARAMETER;\r
856 } else {\r
857 StdOutFileName = CommandLineWalker += 4;\r
858 OutAppend = FALSE;\r
859 }\r
733f138d 860 if (StrStr(CommandLineWalker, L" 1> ") != NULL) {\r
861 Status = EFI_NOT_FOUND;\r
862 }\r
a405b86d 863 }\r
864\r
865 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
fb84495a 866 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 867 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 868 if (StdOutFileName != NULL) {\r
869 Status = EFI_INVALID_PARAMETER;\r
870 } else {\r
871 StdOutFileName = CommandLineWalker += 3;\r
872 OutAppend = FALSE;\r
873 }\r
733f138d 874 if (StrStr(CommandLineWalker, L" > ") != NULL) {\r
875 Status = EFI_NOT_FOUND;\r
876 }\r
a405b86d 877 }\r
878\r
879 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
fb84495a 880 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 881 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 882 if (StdInFileName != NULL) {\r
883 Status = EFI_INVALID_PARAMETER;\r
884 } else {\r
885 StdInFileName = CommandLineWalker += 3;\r
733f138d 886 }\r
887 if (StrStr(CommandLineWalker, L" < ") != NULL) {\r
888 Status = EFI_NOT_FOUND;\r
a405b86d 889 }\r
890 }\r
891 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
fb84495a 892 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 893 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 894 if (StdInFileName != NULL) {\r
895 Status = EFI_INVALID_PARAMETER;\r
896 } else {\r
733f138d 897 StdInFileName = CommandLineWalker += 4;\r
898 InUnicode = FALSE;\r
899 }\r
900 if (StrStr(CommandLineWalker, L" <a ") != NULL) {\r
901 Status = EFI_NOT_FOUND;\r
a405b86d 902 }\r
903 }\r
904 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {\r
fb84495a 905 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 906 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 907 if (StdInVarName != NULL) {\r
908 Status = EFI_INVALID_PARAMETER;\r
909 } else {\r
910 StdInVarName = CommandLineWalker += 4;\r
733f138d 911 }\r
912 if (StrStr(CommandLineWalker, L" <v ") != NULL) {\r
913 Status = EFI_NOT_FOUND;\r
a405b86d 914 }\r
915 }\r
916\r
031acf63 917 //\r
918 // re-populate the string to support any filenames that were in quotes.\r
919 //\r
920 StrCpy(CommandLineCopy, NewCommandLine);\r
921\r
5f2915f5 922 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
fb84495a 923 && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))\r
924 ){\r
925 *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;\r
926 }\r
927\r
a405b86d 928 if (!EFI_ERROR(Status)) {\r
031acf63 929\r
930 if (StdErrFileName != NULL) {\r
931 if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {\r
932 Status = EFI_INVALID_PARAMETER;\r
933 }\r
a405b86d 934 }\r
031acf63 935 if (StdOutFileName != NULL) {\r
936 if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {\r
937 Status = EFI_INVALID_PARAMETER;\r
938 }\r
a405b86d 939 }\r
031acf63 940 if (StdInFileName != NULL) {\r
941 if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {\r
942 Status = EFI_INVALID_PARAMETER;\r
943 }\r
a405b86d 944 }\r
031acf63 945 if (StdErrVarName != NULL) {\r
6813ba40 946 if ((StdErrVarName = FixVarName(StdErrVarName)) == NULL) {\r
031acf63 947 Status = EFI_INVALID_PARAMETER;\r
948 }\r
a405b86d 949 }\r
031acf63 950 if (StdOutVarName != NULL) {\r
6813ba40 951 if ((StdOutVarName = FixVarName(StdOutVarName)) == NULL) {\r
031acf63 952 Status = EFI_INVALID_PARAMETER;\r
953 }\r
a405b86d 954 }\r
031acf63 955 if (StdInVarName != NULL) {\r
6813ba40 956 if ((StdInVarName = FixVarName(StdInVarName)) == NULL) {\r
031acf63 957 Status = EFI_INVALID_PARAMETER;\r
958 }\r
a405b86d 959 }\r
960\r
0c956e0d 961 //\r
962 // Verify not the same and not duplicating something from a split\r
963 //\r
733f138d 964 if (\r
965 //\r
966 // Check that no 2 filenames are the same\r
967 //\r
fb84495a 968 (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
a405b86d 969 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
970 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
733f138d 971 //\r
972 // Check that no 2 variable names are the same\r
973 //\r
a405b86d 974 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)\r
975 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)\r
976 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)\r
733f138d 977 //\r
978 // When a split (using | operator) is in place some are not allowed\r
979 //\r
a405b86d 980 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))\r
981 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
733f138d 982 //\r
983 // Check that nothing is trying to be output to 2 locations.\r
984 //\r
a405b86d 985 ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
986 ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
987 ||(StdInFileName != NULL && StdInVarName != NULL)\r
733f138d 988 //\r
733f138d 989 // Check for no volatile environment variables\r
990 //\r
a405b86d 991 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))\r
992 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))\r
733f138d 993 //\r
994 // Cant redirect during a reconnect operation.\r
995 //\r
3c865f20 996 ||(StrStr(NewCommandLine, L"connect -r") != NULL \r
997 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
733f138d 998 //\r
999 // Check that filetypes (Unicode/Ascii) do not change during an append\r
1000 //\r
1001 ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
1002 ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
1003 ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
1004 ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
a405b86d 1005 ){\r
1006 Status = EFI_INVALID_PARAMETER;\r
a9ca0684 1007 ShellParameters->StdIn = *OldStdIn;\r
1008 ShellParameters->StdOut = *OldStdOut;\r
1009 ShellParameters->StdErr = *OldStdErr;\r
fb84495a 1010 } else if (!EFI_ERROR(Status)){\r
a405b86d 1011 //\r
1012 // Open the Std<Whatever> and we should not have conflicts here...\r
1013 //\r
1014\r
1015 //\r
1016 // StdErr to a file\r
1017 //\r
1018 if (StdErrFileName != NULL) {\r
1019 if (!ErrAppend) {\r
1020 //\r
1021 // delete existing file.\r
1022 //\r
1023 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);\r
1024 }\r
1025 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
a405b86d 1026 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
1027 //\r
733f138d 1028 // Write out the gUnicodeFileTag\r
a405b86d 1029 //\r
1030 Size = sizeof(CHAR16);\r
733f138d 1031 TagBuffer[0] = gUnicodeFileTag;\r
a405b86d 1032 TagBuffer[1] = CHAR_NULL;\r
1033 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
1034 }\r
1035 if (!ErrUnicode && !EFI_ERROR(Status)) {\r
1036 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1037 ASSERT(TempHandle != NULL);\r
1038 }\r
1039 if (!EFI_ERROR(Status)) {\r
1040 ShellParameters->StdErr = TempHandle;\r
dcf9b428 1041 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);\r
a405b86d 1042 }\r
1043 }\r
1044\r
1045 //\r
1046 // StdOut to a file\r
1047 //\r
1048 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {\r
1049 if (!OutAppend) {\r
1050 //\r
1051 // delete existing file.\r
1052 //\r
1053 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);\r
1054 }\r
1055 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
3c865f20 1056 if (TempHandle == NULL) {\r
1057 Status = EFI_INVALID_PARAMETER;\r
1058 } else {\r
733f138d 1059 if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {\r
1060 //no-op\r
1061 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
3c865f20 1062 //\r
733f138d 1063 // Write out the gUnicodeFileTag\r
3c865f20 1064 //\r
1065 Size = sizeof(CHAR16);\r
733f138d 1066 TagBuffer[0] = gUnicodeFileTag;\r
3c865f20 1067 TagBuffer[1] = CHAR_NULL;\r
1068 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
1069 } else if (OutAppend) {\r
1070 //\r
1071 // Move to end of file\r
1072 //\r
1073 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);\r
1074 if (!EFI_ERROR(Status)) {\r
1075 Status = ShellInfoObject.NewEfiShellProtocol->SetFilePosition(TempHandle, FileSize);\r
1076 }\r
1077 }\r
1078 if (!OutUnicode && !EFI_ERROR(Status)) {\r
1079 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1080 ASSERT(TempHandle != NULL);\r
1081 }\r
a405b86d 1082 if (!EFI_ERROR(Status)) {\r
3c865f20 1083 ShellParameters->StdOut = TempHandle;\r
dcf9b428 1084 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);\r
a405b86d 1085 }\r
1086 }\r
a405b86d 1087 }\r
1088\r
1089 //\r
1090 // StdOut to a var\r
1091 //\r
1092 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {\r
1093 if (!OutAppend) {\r
1094 //\r
1095 // delete existing variable.\r
1096 //\r
1097 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");\r
1098 }\r
1099 TempHandle = CreateFileInterfaceEnv(StdOutVarName);\r
1100 ASSERT(TempHandle != NULL);\r
a405b86d 1101 ShellParameters->StdOut = TempHandle;\r
dcf9b428 1102 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);\r
a405b86d 1103 }\r
1104\r
1105 //\r
1106 // StdErr to a var\r
1107 //\r
1108 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {\r
1109 if (!ErrAppend) {\r
1110 //\r
1111 // delete existing variable.\r
1112 //\r
1113 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");\r
1114 }\r
1115 TempHandle = CreateFileInterfaceEnv(StdErrVarName);\r
1116 ASSERT(TempHandle != NULL);\r
a405b86d 1117 ShellParameters->StdErr = TempHandle;\r
dcf9b428 1118 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);\r
a405b86d 1119 }\r
1120\r
1121 //\r
1122 // StdIn from a var\r
1123 //\r
1124 if (!EFI_ERROR(Status) && StdInVarName != NULL) {\r
1125 TempHandle = CreateFileInterfaceEnv(StdInVarName);\r
532691c8 1126 if (TempHandle == NULL) {\r
1127 Status = EFI_OUT_OF_RESOURCES;\r
a405b86d 1128 } else {\r
532691c8 1129 if (!InUnicode) {\r
1130 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1131 }\r
1132 Size = 0;\r
96962f0a 1133 if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
532691c8 1134 Status = EFI_INVALID_PARAMETER;\r
1135 } else {\r
1136 ShellParameters->StdIn = TempHandle;\r
1137 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1138 }\r
a405b86d 1139 }\r
1140 }\r
1141\r
1142 //\r
1143 // StdIn from a file\r
1144 //\r
1145 if (!EFI_ERROR(Status) && StdInFileName != NULL) {\r
1146 Status = ShellOpenFileByName(\r
1147 StdInFileName,\r
1148 &TempHandle,\r
1149 EFI_FILE_MODE_READ,\r
1150 0);\r
1151 if (!InUnicode && !EFI_ERROR(Status)) {\r
1152 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1153 }\r
1154 if (!EFI_ERROR(Status)) {\r
1155 ShellParameters->StdIn = TempHandle;\r
8be0ba36 1156 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
a405b86d 1157 }\r
1158 }\r
1159 }\r
1160 }\r
1161 FreePool(CommandLineCopy);\r
8be0ba36 1162\r
cf6a8f14 1163 CalculateEfiHdrCrc(&gST->Hdr);\r
1164\r
8be0ba36 1165 if (gST->ConIn == NULL ||gST->ConOut == NULL) {\r
cc31ac1e 1166 Status = EFI_OUT_OF_RESOURCES;\r
8be0ba36 1167 }\r
cc31ac1e
JC
1168\r
1169 if (Status == EFI_NOT_FOUND) {\r
1170 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle);\r
1171 } else if (EFI_ERROR(Status)) {\r
1172 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);\r
1173 }\r
1174\r
a405b86d 1175 return (Status);\r
1176}\r
1177\r
1178/**\r
1179 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
1180 structure with StdIn and StdOut. The current values are de-allocated.\r
1181\r
4ff7e37b
ED
1182 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1183 @param[in] OldStdIn Pointer to old StdIn.\r
1184 @param[in] OldStdOut Pointer to old StdOut.\r
1185 @param[in] OldStdErr Pointer to old StdErr.\r
1186 @param[in] SystemTableInfo Pointer to old system table information.\r
a405b86d 1187**/\r
1188EFI_STATUS\r
1189EFIAPI\r
1190RestoreStdInStdOutStdErr (\r
1191 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
8be0ba36 1192 IN SHELL_FILE_HANDLE *OldStdIn,\r
1193 IN SHELL_FILE_HANDLE *OldStdOut,\r
1194 IN SHELL_FILE_HANDLE *OldStdErr,\r
1195 IN SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 1196 )\r
1197{\r
1198 SPLIT_LIST *Split;\r
8be0ba36 1199\r
1200 if (ShellParameters == NULL \r
1201 ||OldStdIn == NULL\r
1202 ||OldStdOut == NULL\r
1203 ||OldStdErr == NULL\r
1204 ||SystemTableInfo == NULL) {\r
1205 return (EFI_INVALID_PARAMETER);\r
1206 }\r
a405b86d 1207 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
1208 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
1209 } else {\r
1210 Split = NULL;\r
1211 }\r
8be0ba36 1212 if (ShellParameters->StdIn != *OldStdIn) {\r
a405b86d 1213 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
1214 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
1215 }\r
8be0ba36 1216 ShellParameters->StdIn = *OldStdIn;\r
a405b86d 1217 }\r
8be0ba36 1218 if (ShellParameters->StdOut != *OldStdOut) {\r
a405b86d 1219 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
1220 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
1221 }\r
8be0ba36 1222 ShellParameters->StdOut = *OldStdOut;\r
1223 }\r
1224 if (ShellParameters->StdErr != *OldStdErr) {\r
1225 gEfiShellProtocol->CloseFile(ShellParameters->StdErr);\r
1226 ShellParameters->StdErr = *OldStdErr;\r
1227 }\r
1228\r
1229 if (gST->ConIn != SystemTableInfo->ConIn) {\r
1230 CloseSimpleTextInOnFile(gST->ConIn);\r
1231 gST->ConIn = SystemTableInfo->ConIn;\r
1232 gST->ConsoleInHandle = SystemTableInfo->ConInHandle;\r
a405b86d 1233 }\r
8be0ba36 1234 if (gST->ConOut != SystemTableInfo->ConOut) {\r
1235 CloseSimpleTextOutOnFile(gST->ConOut);\r
1236 gST->ConOut = SystemTableInfo->ConOut;\r
1237 gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;\r
1238 }\r
4ccd9214 1239 if (gST->StdErr != SystemTableInfo->ErrOut) {\r
8be0ba36 1240 CloseSimpleTextOutOnFile(gST->StdErr);\r
4ccd9214
ED
1241 gST->StdErr = SystemTableInfo->ErrOut;\r
1242 gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle;\r
8be0ba36 1243 }\r
1244\r
cf6a8f14 1245 CalculateEfiHdrCrc(&gST->Hdr);\r
1246\r
a405b86d 1247 return (EFI_SUCCESS);\r
1248}\r
1249/**\r
1250 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1251 structure by parsing NewCommandLine. The current values are returned to the\r
1252 user.\r
1253\r
1254 If OldArgv or OldArgc is NULL then that value is not returned.\r
1255\r
4ff7e37b
ED
1256 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1257 @param[in] NewCommandLine The new command line to parse and use.\r
1258 @param[out] OldArgv Pointer to old list of parameters.\r
1259 @param[out] OldArgc Pointer to old number of items in Argv list.\r
a405b86d 1260\r
1261 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
1262 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1263**/\r
1264EFI_STATUS\r
1265EFIAPI\r
1266UpdateArgcArgv(\r
1267 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1268 IN CONST CHAR16 *NewCommandLine,\r
1269 OUT CHAR16 ***OldArgv OPTIONAL,\r
1270 OUT UINTN *OldArgc OPTIONAL\r
1271 )\r
1272{\r
1273 ASSERT(ShellParameters != NULL);\r
1274\r
1275 if (OldArgc != NULL) {\r
1276 *OldArgc = ShellParameters->Argc;\r
1277 }\r
1278 if (OldArgc != NULL) {\r
1279 *OldArgv = ShellParameters->Argv;\r
1280 }\r
1281\r
1282 return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));\r
1283}\r
1284\r
1285/**\r
1286 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1287 structure with Argv and Argc. The current values are de-allocated and the\r
1288 OldArgv must not be deallocated by the caller.\r
1289\r
4ff7e37b
ED
1290 @param[in, out] ShellParameters pointer to parameter structure to modify\r
1291 @param[in] OldArgv pointer to old list of parameters\r
1292 @param[in] OldArgc pointer to old number of items in Argv list\r
a405b86d 1293**/\r
1294VOID\r
1295EFIAPI\r
1296RestoreArgcArgv(\r
1297 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1298 IN CHAR16 ***OldArgv,\r
1299 IN UINTN *OldArgc\r
1300 )\r
1301{\r
1302 UINTN LoopCounter;\r
1303 ASSERT(ShellParameters != NULL);\r
1304 ASSERT(OldArgv != NULL);\r
1305 ASSERT(OldArgc != NULL);\r
1306\r
1307 if (ShellParameters->Argv != NULL) {\r
1308 for ( LoopCounter = 0\r
1309 ; LoopCounter < ShellParameters->Argc\r
1310 ; LoopCounter++\r
1311 ){\r
1312 FreePool(ShellParameters->Argv[LoopCounter]);\r
1313 }\r
1314 FreePool(ShellParameters->Argv);\r
1315 }\r
1316 ShellParameters->Argv = *OldArgv;\r
1317 *OldArgv = NULL;\r
1318 ShellParameters->Argc = *OldArgc;\r
1319 *OldArgc = 0;\r
1320}\r