]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Application/Shell/ShellParametersProtocol.c
ShellPkg: Add support for adding optional data to the bcfg command in debug profile.
[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
733f138d 5 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
a405b86d 6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "ShellParametersProtocol.h"\r
8be0ba36 17#include "ConsoleWrappers.h"\r
a405b86d 18\r
19/**\r
20 return the next parameter from a command line string;\r
21\r
22 This function moves the next parameter from Walker into TempParameter and moves\r
23 Walker up past that parameter for recursive calling. When the final parameter\r
24 is moved *Walker will be set to NULL;\r
25\r
26 Temp Parameter must be large enough to hold the parameter before calling this\r
27 function.\r
28\r
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
195 return (EFI_OUT_OF_RESOURCES);\r
196 }\r
197\r
198 *Argc = 0;\r
199 Walker = (CHAR16*)CommandLine;\r
200 while(Walker != NULL && *Walker != CHAR_NULL) {\r
201 SetMem16(TempParameter, Size, CHAR_NULL);\r
202 GetNextParameter(&Walker, &TempParameter);\r
203 NewParam = AllocateZeroPool(StrSize(TempParameter));\r
204 ASSERT(NewParam != NULL);\r
205 StrCpy(NewParam, TempParameter);\r
206 ((CHAR16**)(*Argv))[(*Argc)] = NewParam;\r
207 (*Argc)++;\r
208 }\r
209 ASSERT(Count >= (*Argc));\r
210 return (EFI_SUCCESS);\r
211}\r
212\r
213/**\r
214 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then\r
215 installs it on our handle and if there is an existing version of the protocol\r
216 that one is cached for removal later.\r
217\r
4ff7e37b 218 @param[in, out] NewShellParameters on a successful return, a pointer to pointer\r
a405b86d 219 to the newly installed interface.\r
4ff7e37b 220 @param[in, out] RootShellInstance on a successful return, pointer to boolean.\r
a405b86d 221 TRUE if this is the root shell instance.\r
222\r
223 @retval EFI_SUCCESS the operation completed successfully.\r
224 @return other the operation failed.\r
225 @sa ReinstallProtocolInterface\r
226 @sa InstallProtocolInterface\r
227 @sa ParseCommandLineToArgs\r
228**/\r
229EFI_STATUS\r
230EFIAPI\r
231CreatePopulateInstallShellParametersProtocol (\r
232 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters,\r
233 IN OUT BOOLEAN *RootShellInstance\r
234 )\r
235{\r
236 EFI_STATUS Status;\r
237 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
238 CHAR16 *FullCommandLine;\r
239 UINTN Size;\r
240\r
241 Size = 0;\r
242 FullCommandLine = NULL;\r
243 LoadedImage = NULL;\r
244\r
245 //\r
246 // Assert for valid parameters\r
247 //\r
248 ASSERT(NewShellParameters != NULL);\r
249 ASSERT(RootShellInstance != NULL);\r
250\r
251 //\r
252 // See if we have a shell parameters placed on us\r
253 //\r
254 Status = gBS->OpenProtocol (\r
255 gImageHandle,\r
256 &gEfiShellParametersProtocolGuid,\r
257 (VOID **) &ShellInfoObject.OldShellParameters,\r
258 gImageHandle,\r
259 NULL,\r
260 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
261 );\r
262 //\r
263 // if we don't then we must be the root shell (error is expected)\r
264 //\r
265 if (EFI_ERROR (Status)) {\r
266 *RootShellInstance = TRUE;\r
267 }\r
268\r
269 //\r
270 // Allocate the new structure\r
271 //\r
272 *NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));\r
3c865f20 273 if ((*NewShellParameters) == NULL) {\r
274 return (EFI_OUT_OF_RESOURCES);\r
275 }\r
a405b86d 276\r
277 //\r
278 // get loaded image protocol\r
279 //\r
280 Status = gBS->OpenProtocol (\r
281 gImageHandle,\r
282 &gEfiLoadedImageProtocolGuid,\r
283 (VOID **) &LoadedImage,\r
284 gImageHandle,\r
285 NULL,\r
286 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
287 );\r
288 ASSERT_EFI_ERROR(Status);\r
289 //\r
290 // Build the full command line\r
291 //\r
292 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);\r
293 if (Status == EFI_BUFFER_TOO_SMALL) {\r
294 FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);\r
295 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);\r
296 }\r
297 if (Status == EFI_NOT_FOUND) {\r
298 //\r
299 // no parameters via environment... ok\r
300 //\r
301 } else {\r
3c865f20 302 if (EFI_ERROR(Status)) {\r
303 return (Status);\r
304 }\r
a405b86d 305 }\r
306 if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {\r
3c865f20 307 ASSERT(FullCommandLine == NULL);\r
a405b86d 308 //\r
309 // Now we need to include a NULL terminator in the size.\r
310 //\r
311 Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]);\r
312 FullCommandLine = AllocateZeroPool(Size);\r
313 }\r
a405b86d 314 if (FullCommandLine != NULL) {\r
3c865f20 315 if (LoadedImage->LoadOptionsSize != 0){\r
316 StrCpy(FullCommandLine, LoadedImage->LoadOptions);\r
317 }\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
526 if ((TempLocation = StrStr(Copy , L" ")) != NULL) {\r
527 TempLocation[0] = CHAR_NULL;\r
528 } \r
529 }\r
530\r
531 if (Copy[0] == CHAR_NULL) {\r
532 return (NULL);\r
533 }\r
534\r
535 return (Copy);\r
536}\r
537\r
a405b86d 538/**\r
539 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
540 structure by parsing NewCommandLine. The current values are returned to the\r
541 user.\r
542\r
8be0ba36 543 This will also update the system table.\r
a405b86d 544\r
4ff7e37b
ED
545 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
546 @param[in] NewCommandLine The new command line to parse and use.\r
547 @param[out] OldStdIn Pointer to old StdIn.\r
548 @param[out] OldStdOut Pointer to old StdOut.\r
549 @param[out] OldStdErr Pointer to old StdErr.\r
550 @param[out] SystemTableInfo Pointer to old system table information.\r
a405b86d 551\r
552 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
553 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
554**/\r
555EFI_STATUS\r
556EFIAPI\r
557UpdateStdInStdOutStdErr(\r
558 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
fb84495a 559 IN CHAR16 *NewCommandLine,\r
a405b86d 560 OUT SHELL_FILE_HANDLE *OldStdIn,\r
561 OUT SHELL_FILE_HANDLE *OldStdOut,\r
8be0ba36 562 OUT SHELL_FILE_HANDLE *OldStdErr,\r
563 OUT SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 564 )\r
565{\r
566 CHAR16 *CommandLineCopy;\r
567 CHAR16 *CommandLineWalker;\r
568 CHAR16 *StdErrFileName;\r
569 CHAR16 *StdOutFileName;\r
570 CHAR16 *StdInFileName;\r
571 CHAR16 *StdInVarName;\r
572 CHAR16 *StdOutVarName;\r
573 CHAR16 *StdErrVarName;\r
574 EFI_STATUS Status;\r
575 SHELL_FILE_HANDLE TempHandle;\r
576 UINT64 FileSize;\r
577 BOOLEAN OutUnicode;\r
578 BOOLEAN InUnicode;\r
579 BOOLEAN ErrUnicode;\r
580 BOOLEAN OutAppend;\r
581 BOOLEAN ErrAppend;\r
582 UINTN Size;\r
583 CHAR16 TagBuffer[2];\r
584 SPLIT_LIST *Split;\r
fb84495a 585 CHAR16 *FirstLocation;\r
a405b86d 586\r
a405b86d 587 OutUnicode = TRUE;\r
588 InUnicode = TRUE;\r
589 ErrUnicode = TRUE;\r
590 StdInVarName = NULL;\r
591 StdOutVarName = NULL;\r
592 StdErrVarName = NULL;\r
593 StdErrFileName = NULL;\r
594 StdInFileName = NULL;\r
595 StdOutFileName = NULL;\r
596 ErrAppend = FALSE;\r
597 OutAppend = FALSE;\r
598 CommandLineCopy = NULL;\r
5f2915f5 599 FirstLocation = NULL;\r
a405b86d 600\r
8be0ba36 601 if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {\r
602 return (EFI_INVALID_PARAMETER);\r
a405b86d 603 }\r
604\r
8be0ba36 605 SystemTableInfo->ConIn = gST->ConIn;\r
606 SystemTableInfo->ConInHandle = gST->ConsoleInHandle;\r
607 SystemTableInfo->ConOut = gST->ConOut;\r
608 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;\r
609 SystemTableInfo->ConErr = gST->StdErr;\r
610 SystemTableInfo->ConErrHandle = gST->StandardErrorHandle;\r
611 *OldStdIn = ShellParameters->StdIn;\r
612 *OldStdOut = ShellParameters->StdOut;\r
613 *OldStdErr = ShellParameters->StdErr;\r
614\r
a405b86d 615 if (NewCommandLine == NULL) {\r
616 return (EFI_SUCCESS);\r
617 }\r
618\r
619 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
532691c8 620 if (CommandLineCopy == NULL) {\r
621 return (EFI_OUT_OF_RESOURCES);\r
622 }\r
a405b86d 623 Status = EFI_SUCCESS;\r
624 Split = NULL;\r
5f2915f5 625 FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);\r
a405b86d 626\r
fb84495a 627 StripQuotes(CommandLineCopy);\r
628\r
a405b86d 629 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
630 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
631 if (Split != NULL && Split->SplitStdIn != NULL) {\r
632 ShellParameters->StdIn = Split->SplitStdIn;\r
633 }\r
634 if (Split != NULL && Split->SplitStdOut != NULL) {\r
635 ShellParameters->StdOut = Split->SplitStdOut;\r
636 }\r
637 }\r
638\r
639 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {\r
fb84495a 640 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 641 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 642 StdErrVarName = CommandLineWalker += 6;\r
643 ErrAppend = TRUE;\r
733f138d 644 if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {\r
645 Status = EFI_NOT_FOUND;\r
646 }\r
a405b86d 647 }\r
648 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
fb84495a 649 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 650 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 651 StdOutVarName = CommandLineWalker += 6;\r
652 OutAppend = TRUE;\r
733f138d 653 if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {\r
654 Status = EFI_NOT_FOUND;\r
655 }\r
a405b86d 656 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
fb84495a 657 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 658 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 659 StdOutVarName = CommandLineWalker += 5;\r
660 OutAppend = TRUE;\r
733f138d 661 if (StrStr(CommandLineWalker, L" >>v ") != NULL) {\r
662 Status = EFI_NOT_FOUND;\r
663 }\r
a405b86d 664 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
fb84495a 665 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 666 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 667 StdOutVarName = CommandLineWalker += 4;\r
668 OutAppend = FALSE;\r
733f138d 669 if (StrStr(CommandLineWalker, L" >v ") != NULL) {\r
670 Status = EFI_NOT_FOUND;\r
671 }\r
a405b86d 672 }\r
673 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
fb84495a 674 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 675 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 676 StdOutFileName = CommandLineWalker += 6;\r
677 OutAppend = TRUE;\r
678 OutUnicode = FALSE;\r
733f138d 679 if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {\r
680 Status = EFI_NOT_FOUND;\r
681 }\r
a405b86d 682 }\r
683 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
fb84495a 684 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 685 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 686 if (StdOutFileName != NULL) {\r
687 Status = EFI_INVALID_PARAMETER;\r
688 } else {\r
689 StdOutFileName = CommandLineWalker += 5;\r
690 OutAppend = TRUE;\r
691 }\r
733f138d 692 if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
693 Status = EFI_NOT_FOUND;\r
694 }\r
a405b86d 695 } \r
696 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
fb84495a 697 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 698 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 699 if (StdOutFileName != NULL) {\r
700 Status = EFI_INVALID_PARAMETER;\r
701 } else {\r
702 StdOutFileName = CommandLineWalker += 4;\r
703 OutAppend = TRUE;\r
704 }\r
733f138d 705 if (StrStr(CommandLineWalker, L" >> ") != NULL) {\r
706 Status = EFI_NOT_FOUND;\r
707 }\r
a405b86d 708 }\r
709 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {\r
fb84495a 710 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 711 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 712 if (StdOutFileName != NULL) {\r
713 Status = EFI_INVALID_PARAMETER;\r
714 } else {\r
715 StdOutFileName = CommandLineWalker += 5;\r
716 OutAppend = TRUE;\r
717 OutUnicode = FALSE;\r
718 }\r
733f138d 719 if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
720 Status = EFI_NOT_FOUND;\r
721 }\r
a405b86d 722 } \r
723 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
fb84495a 724 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 725 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 726 if (StdOutFileName != NULL) {\r
727 Status = EFI_INVALID_PARAMETER;\r
728 } else {\r
729 StdOutFileName = CommandLineWalker += 5;\r
730 OutAppend = FALSE;\r
731 OutUnicode = FALSE;\r
732 }\r
733f138d 733 if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
734 Status = EFI_NOT_FOUND;\r
735 }\r
a405b86d 736 } \r
737 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
fb84495a 738 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 739 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 740 if (StdOutFileName != NULL) {\r
741 Status = EFI_INVALID_PARAMETER;\r
742 } else {\r
743 StdOutFileName = CommandLineWalker += 4;\r
744 OutAppend = FALSE;\r
745 OutUnicode = FALSE;\r
746 }\r
733f138d 747 if (StrStr(CommandLineWalker, L" >a ") != NULL) {\r
748 Status = EFI_NOT_FOUND;\r
749 }\r
a405b86d 750 }\r
751 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
fb84495a 752 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 753 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 754 if (StdErrFileName != NULL) {\r
755 Status = EFI_INVALID_PARAMETER;\r
756 } else {\r
757 StdErrFileName = CommandLineWalker += 5;\r
758 ErrAppend = TRUE;\r
759 }\r
733f138d 760 if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {\r
761 Status = EFI_NOT_FOUND;\r
762 }\r
a405b86d 763 }\r
764\r
765 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
fb84495a 766 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 767 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 768 if (StdErrVarName != NULL) {\r
769 Status = EFI_INVALID_PARAMETER;\r
770 } else {\r
771 StdErrVarName = CommandLineWalker += 5;\r
772 ErrAppend = FALSE;\r
773 }\r
733f138d 774 if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {\r
775 Status = EFI_NOT_FOUND;\r
776 }\r
a405b86d 777 }\r
778 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
fb84495a 779 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 780 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 781 if (StdOutVarName != NULL) {\r
782 Status = EFI_INVALID_PARAMETER;\r
783 } else {\r
784 StdOutVarName = CommandLineWalker += 5;\r
785 OutAppend = FALSE;\r
786 }\r
733f138d 787 if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {\r
788 Status = EFI_NOT_FOUND;\r
789 }\r
a405b86d 790 }\r
791 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
fb84495a 792 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 793 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 794 if (StdErrFileName != NULL) {\r
795 Status = EFI_INVALID_PARAMETER;\r
796 } else {\r
797 StdErrFileName = CommandLineWalker += 5;\r
798 ErrAppend = FALSE;\r
799 ErrUnicode = FALSE;\r
800 }\r
733f138d 801 if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {\r
802 Status = EFI_NOT_FOUND;\r
803 }\r
a405b86d 804 }\r
805 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
fb84495a 806 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 807 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 808 if (StdErrFileName != NULL) {\r
809 Status = EFI_INVALID_PARAMETER;\r
810 } else {\r
811 StdErrFileName = CommandLineWalker += 4;\r
812 ErrAppend = FALSE;\r
813 }\r
733f138d 814 if (StrStr(CommandLineWalker, L" 2> ") != NULL) {\r
815 Status = EFI_NOT_FOUND;\r
816 }\r
a405b86d 817 }\r
818\r
819 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
fb84495a 820 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 821 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 822 if (StdOutFileName != NULL) {\r
823 Status = EFI_INVALID_PARAMETER;\r
824 } else {\r
825 StdOutFileName = CommandLineWalker += 4;\r
826 OutAppend = FALSE;\r
827 }\r
733f138d 828 if (StrStr(CommandLineWalker, L" 1> ") != NULL) {\r
829 Status = EFI_NOT_FOUND;\r
830 }\r
a405b86d 831 }\r
832\r
833 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
fb84495a 834 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 835 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 836 if (StdOutFileName != NULL) {\r
837 Status = EFI_INVALID_PARAMETER;\r
838 } else {\r
839 StdOutFileName = CommandLineWalker += 3;\r
840 OutAppend = FALSE;\r
841 }\r
733f138d 842 if (StrStr(CommandLineWalker, L" > ") != NULL) {\r
843 Status = EFI_NOT_FOUND;\r
844 }\r
a405b86d 845 }\r
846\r
847 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
fb84495a 848 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 849 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 850 if (StdInFileName != NULL) {\r
851 Status = EFI_INVALID_PARAMETER;\r
852 } else {\r
853 StdInFileName = CommandLineWalker += 3;\r
733f138d 854 }\r
855 if (StrStr(CommandLineWalker, L" < ") != NULL) {\r
856 Status = EFI_NOT_FOUND;\r
a405b86d 857 }\r
858 }\r
859 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
fb84495a 860 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 861 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 862 if (StdInFileName != NULL) {\r
863 Status = EFI_INVALID_PARAMETER;\r
864 } else {\r
733f138d 865 StdInFileName = CommandLineWalker += 4;\r
866 InUnicode = FALSE;\r
867 }\r
868 if (StrStr(CommandLineWalker, L" <a ") != NULL) {\r
869 Status = EFI_NOT_FOUND;\r
a405b86d 870 }\r
871 }\r
872 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {\r
fb84495a 873 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 874 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 875 if (StdInVarName != NULL) {\r
876 Status = EFI_INVALID_PARAMETER;\r
877 } else {\r
878 StdInVarName = CommandLineWalker += 4;\r
733f138d 879 }\r
880 if (StrStr(CommandLineWalker, L" <v ") != NULL) {\r
881 Status = EFI_NOT_FOUND;\r
a405b86d 882 }\r
883 }\r
884\r
031acf63 885 //\r
886 // re-populate the string to support any filenames that were in quotes.\r
887 //\r
888 StrCpy(CommandLineCopy, NewCommandLine);\r
889\r
5f2915f5 890 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
fb84495a 891 && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))\r
892 ){\r
893 *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;\r
894 }\r
895\r
a405b86d 896 if (!EFI_ERROR(Status)) {\r
031acf63 897\r
898 if (StdErrFileName != NULL) {\r
899 if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {\r
900 Status = EFI_INVALID_PARAMETER;\r
901 }\r
a405b86d 902 }\r
031acf63 903 if (StdOutFileName != NULL) {\r
904 if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {\r
905 Status = EFI_INVALID_PARAMETER;\r
906 }\r
a405b86d 907 }\r
031acf63 908 if (StdInFileName != NULL) {\r
909 if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {\r
910 Status = EFI_INVALID_PARAMETER;\r
911 }\r
a405b86d 912 }\r
031acf63 913 if (StdErrVarName != NULL) {\r
914 if ((StdErrVarName = FixFileName(StdErrVarName)) == NULL) {\r
915 Status = EFI_INVALID_PARAMETER;\r
916 }\r
a405b86d 917 }\r
031acf63 918 if (StdOutVarName != NULL) {\r
919 if ((StdOutVarName = FixFileName(StdOutVarName)) == NULL) {\r
920 Status = EFI_INVALID_PARAMETER;\r
921 }\r
a405b86d 922 }\r
031acf63 923 if (StdInVarName != NULL) {\r
924 if ((StdInVarName = FixFileName(StdInVarName)) == NULL) {\r
925 Status = EFI_INVALID_PARAMETER;\r
926 }\r
a405b86d 927 }\r
928\r
0c956e0d 929 //\r
930 // Verify not the same and not duplicating something from a split\r
931 //\r
733f138d 932 if (\r
933 //\r
934 // Check that no 2 filenames are the same\r
935 //\r
fb84495a 936 (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
a405b86d 937 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
938 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
733f138d 939 //\r
940 // Check that no 2 variable names are the same\r
941 //\r
a405b86d 942 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)\r
943 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)\r
944 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)\r
733f138d 945 //\r
946 // When a split (using | operator) is in place some are not allowed\r
947 //\r
a405b86d 948 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))\r
949 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
733f138d 950 //\r
951 // Check that nothing is trying to be output to 2 locations.\r
952 //\r
a405b86d 953 ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
954 ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
955 ||(StdInFileName != NULL && StdInVarName != NULL)\r
733f138d 956 //\r
733f138d 957 // Check for no volatile environment variables\r
958 //\r
a405b86d 959 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))\r
960 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))\r
733f138d 961 //\r
962 // Cant redirect during a reconnect operation.\r
963 //\r
3c865f20 964 ||(StrStr(NewCommandLine, L"connect -r") != NULL \r
965 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
733f138d 966 //\r
967 // Check that filetypes (Unicode/Ascii) do not change during an append\r
968 //\r
969 ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
970 ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
971 ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
972 ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
a405b86d 973 ){\r
974 Status = EFI_INVALID_PARAMETER;\r
a9ca0684 975 ShellParameters->StdIn = *OldStdIn;\r
976 ShellParameters->StdOut = *OldStdOut;\r
977 ShellParameters->StdErr = *OldStdErr;\r
fb84495a 978 } else if (!EFI_ERROR(Status)){\r
a405b86d 979 //\r
980 // Open the Std<Whatever> and we should not have conflicts here...\r
981 //\r
982\r
983 //\r
984 // StdErr to a file\r
985 //\r
986 if (StdErrFileName != NULL) {\r
987 if (!ErrAppend) {\r
988 //\r
989 // delete existing file.\r
990 //\r
991 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);\r
992 }\r
993 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
a405b86d 994 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
995 //\r
733f138d 996 // Write out the gUnicodeFileTag\r
a405b86d 997 //\r
998 Size = sizeof(CHAR16);\r
733f138d 999 TagBuffer[0] = gUnicodeFileTag;\r
a405b86d 1000 TagBuffer[1] = CHAR_NULL;\r
1001 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
1002 }\r
1003 if (!ErrUnicode && !EFI_ERROR(Status)) {\r
1004 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1005 ASSERT(TempHandle != NULL);\r
1006 }\r
1007 if (!EFI_ERROR(Status)) {\r
1008 ShellParameters->StdErr = TempHandle;\r
8be0ba36 1009 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);\r
a405b86d 1010 }\r
1011 }\r
1012\r
1013 //\r
1014 // StdOut to a file\r
1015 //\r
1016 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {\r
1017 if (!OutAppend) {\r
1018 //\r
1019 // delete existing file.\r
1020 //\r
1021 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);\r
1022 }\r
1023 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
3c865f20 1024 if (TempHandle == NULL) {\r
1025 Status = EFI_INVALID_PARAMETER;\r
1026 } else {\r
733f138d 1027 if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {\r
1028 //no-op\r
1029 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
3c865f20 1030 //\r
733f138d 1031 // Write out the gUnicodeFileTag\r
3c865f20 1032 //\r
1033 Size = sizeof(CHAR16);\r
733f138d 1034 TagBuffer[0] = gUnicodeFileTag;\r
3c865f20 1035 TagBuffer[1] = CHAR_NULL;\r
1036 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
1037 } else if (OutAppend) {\r
1038 //\r
1039 // Move to end of file\r
1040 //\r
1041 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);\r
1042 if (!EFI_ERROR(Status)) {\r
1043 Status = ShellInfoObject.NewEfiShellProtocol->SetFilePosition(TempHandle, FileSize);\r
1044 }\r
1045 }\r
1046 if (!OutUnicode && !EFI_ERROR(Status)) {\r
1047 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1048 ASSERT(TempHandle != NULL);\r
1049 }\r
a405b86d 1050 if (!EFI_ERROR(Status)) {\r
3c865f20 1051 ShellParameters->StdOut = TempHandle;\r
8be0ba36 1052 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);\r
a405b86d 1053 }\r
1054 }\r
a405b86d 1055 }\r
1056\r
1057 //\r
1058 // StdOut to a var\r
1059 //\r
1060 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {\r
1061 if (!OutAppend) {\r
1062 //\r
1063 // delete existing variable.\r
1064 //\r
1065 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");\r
1066 }\r
1067 TempHandle = CreateFileInterfaceEnv(StdOutVarName);\r
1068 ASSERT(TempHandle != NULL);\r
a405b86d 1069 ShellParameters->StdOut = TempHandle;\r
8be0ba36 1070 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);\r
a405b86d 1071 }\r
1072\r
1073 //\r
1074 // StdErr to a var\r
1075 //\r
1076 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {\r
1077 if (!ErrAppend) {\r
1078 //\r
1079 // delete existing variable.\r
1080 //\r
1081 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");\r
1082 }\r
1083 TempHandle = CreateFileInterfaceEnv(StdErrVarName);\r
1084 ASSERT(TempHandle != NULL);\r
a405b86d 1085 ShellParameters->StdErr = TempHandle;\r
8be0ba36 1086 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);\r
a405b86d 1087 }\r
1088\r
1089 //\r
1090 // StdIn from a var\r
1091 //\r
1092 if (!EFI_ERROR(Status) && StdInVarName != NULL) {\r
1093 TempHandle = CreateFileInterfaceEnv(StdInVarName);\r
532691c8 1094 if (TempHandle == NULL) {\r
1095 Status = EFI_OUT_OF_RESOURCES;\r
a405b86d 1096 } else {\r
532691c8 1097 if (!InUnicode) {\r
1098 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1099 }\r
1100 Size = 0;\r
96962f0a 1101 if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
532691c8 1102 Status = EFI_INVALID_PARAMETER;\r
1103 } else {\r
1104 ShellParameters->StdIn = TempHandle;\r
1105 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1106 }\r
a405b86d 1107 }\r
1108 }\r
1109\r
1110 //\r
1111 // StdIn from a file\r
1112 //\r
1113 if (!EFI_ERROR(Status) && StdInFileName != NULL) {\r
1114 Status = ShellOpenFileByName(\r
1115 StdInFileName,\r
1116 &TempHandle,\r
1117 EFI_FILE_MODE_READ,\r
1118 0);\r
1119 if (!InUnicode && !EFI_ERROR(Status)) {\r
1120 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1121 }\r
1122 if (!EFI_ERROR(Status)) {\r
1123 ShellParameters->StdIn = TempHandle;\r
8be0ba36 1124 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
a405b86d 1125 }\r
1126 }\r
1127 }\r
1128 }\r
1129 FreePool(CommandLineCopy);\r
8be0ba36 1130\r
cf6a8f14 1131 CalculateEfiHdrCrc(&gST->Hdr);\r
1132\r
8be0ba36 1133 if (gST->ConIn == NULL ||gST->ConOut == NULL) {\r
1134 return (EFI_OUT_OF_RESOURCES);\r
1135 }\r
a405b86d 1136 return (Status);\r
1137}\r
1138\r
1139/**\r
1140 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
1141 structure with StdIn and StdOut. The current values are de-allocated.\r
1142\r
4ff7e37b
ED
1143 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1144 @param[in] OldStdIn Pointer to old StdIn.\r
1145 @param[in] OldStdOut Pointer to old StdOut.\r
1146 @param[in] OldStdErr Pointer to old StdErr.\r
1147 @param[in] SystemTableInfo Pointer to old system table information.\r
a405b86d 1148**/\r
1149EFI_STATUS\r
1150EFIAPI\r
1151RestoreStdInStdOutStdErr (\r
1152 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
8be0ba36 1153 IN SHELL_FILE_HANDLE *OldStdIn,\r
1154 IN SHELL_FILE_HANDLE *OldStdOut,\r
1155 IN SHELL_FILE_HANDLE *OldStdErr,\r
1156 IN SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 1157 )\r
1158{\r
1159 SPLIT_LIST *Split;\r
8be0ba36 1160\r
1161 if (ShellParameters == NULL \r
1162 ||OldStdIn == NULL\r
1163 ||OldStdOut == NULL\r
1164 ||OldStdErr == NULL\r
1165 ||SystemTableInfo == NULL) {\r
1166 return (EFI_INVALID_PARAMETER);\r
1167 }\r
a405b86d 1168 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
1169 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
1170 } else {\r
1171 Split = NULL;\r
1172 }\r
8be0ba36 1173 if (ShellParameters->StdIn != *OldStdIn) {\r
a405b86d 1174 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
1175 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
1176 }\r
8be0ba36 1177 ShellParameters->StdIn = *OldStdIn;\r
a405b86d 1178 }\r
8be0ba36 1179 if (ShellParameters->StdOut != *OldStdOut) {\r
a405b86d 1180 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
1181 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
1182 }\r
8be0ba36 1183 ShellParameters->StdOut = *OldStdOut;\r
1184 }\r
1185 if (ShellParameters->StdErr != *OldStdErr) {\r
1186 gEfiShellProtocol->CloseFile(ShellParameters->StdErr);\r
1187 ShellParameters->StdErr = *OldStdErr;\r
1188 }\r
1189\r
1190 if (gST->ConIn != SystemTableInfo->ConIn) {\r
1191 CloseSimpleTextInOnFile(gST->ConIn);\r
1192 gST->ConIn = SystemTableInfo->ConIn;\r
1193 gST->ConsoleInHandle = SystemTableInfo->ConInHandle;\r
a405b86d 1194 }\r
8be0ba36 1195 if (gST->ConOut != SystemTableInfo->ConOut) {\r
1196 CloseSimpleTextOutOnFile(gST->ConOut);\r
1197 gST->ConOut = SystemTableInfo->ConOut;\r
1198 gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;\r
1199 }\r
1200 if (gST->StdErr != SystemTableInfo->ConErr) {\r
1201 CloseSimpleTextOutOnFile(gST->StdErr);\r
1202 gST->StdErr = SystemTableInfo->ConErr;\r
1203 gST->StandardErrorHandle = SystemTableInfo->ConErrHandle;\r
1204 }\r
1205\r
cf6a8f14 1206 CalculateEfiHdrCrc(&gST->Hdr);\r
1207\r
a405b86d 1208 return (EFI_SUCCESS);\r
1209}\r
1210/**\r
1211 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1212 structure by parsing NewCommandLine. The current values are returned to the\r
1213 user.\r
1214\r
1215 If OldArgv or OldArgc is NULL then that value is not returned.\r
1216\r
4ff7e37b
ED
1217 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1218 @param[in] NewCommandLine The new command line to parse and use.\r
1219 @param[out] OldArgv Pointer to old list of parameters.\r
1220 @param[out] OldArgc Pointer to old number of items in Argv list.\r
a405b86d 1221\r
1222 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
1223 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1224**/\r
1225EFI_STATUS\r
1226EFIAPI\r
1227UpdateArgcArgv(\r
1228 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1229 IN CONST CHAR16 *NewCommandLine,\r
1230 OUT CHAR16 ***OldArgv OPTIONAL,\r
1231 OUT UINTN *OldArgc OPTIONAL\r
1232 )\r
1233{\r
1234 ASSERT(ShellParameters != NULL);\r
1235\r
1236 if (OldArgc != NULL) {\r
1237 *OldArgc = ShellParameters->Argc;\r
1238 }\r
1239 if (OldArgc != NULL) {\r
1240 *OldArgv = ShellParameters->Argv;\r
1241 }\r
1242\r
1243 return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));\r
1244}\r
1245\r
1246/**\r
1247 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1248 structure with Argv and Argc. The current values are de-allocated and the\r
1249 OldArgv must not be deallocated by the caller.\r
1250\r
4ff7e37b
ED
1251 @param[in, out] ShellParameters pointer to parameter structure to modify\r
1252 @param[in] OldArgv pointer to old list of parameters\r
1253 @param[in] OldArgc pointer to old number of items in Argv list\r
a405b86d 1254**/\r
1255VOID\r
1256EFIAPI\r
1257RestoreArgcArgv(\r
1258 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1259 IN CHAR16 ***OldArgv,\r
1260 IN UINTN *OldArgc\r
1261 )\r
1262{\r
1263 UINTN LoopCounter;\r
1264 ASSERT(ShellParameters != NULL);\r
1265 ASSERT(OldArgv != NULL);\r
1266 ASSERT(OldArgc != NULL);\r
1267\r
1268 if (ShellParameters->Argv != NULL) {\r
1269 for ( LoopCounter = 0\r
1270 ; LoopCounter < ShellParameters->Argc\r
1271 ; LoopCounter++\r
1272 ){\r
1273 FreePool(ShellParameters->Argv[LoopCounter]);\r
1274 }\r
1275 FreePool(ShellParameters->Argv);\r
1276 }\r
1277 ShellParameters->Argv = *OldArgv;\r
1278 *OldArgv = NULL;\r
1279 ShellParameters->Argc = *OldArgc;\r
1280 *OldArgc = 0;\r
1281}\r