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