]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Application/Shell/ShellParametersProtocol.c
ShellPkg: Correct 3 places where memory was not being properly released by the shell.
[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
f9aefb6a 5 Copyright (c) 2009 - 2012, 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
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
294 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);\r
295 if (Status == EFI_BUFFER_TOO_SMALL) {\r
296 FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);\r
297 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);\r
298 }\r
299 if (Status == EFI_NOT_FOUND) {\r
300 //\r
301 // no parameters via environment... ok\r
302 //\r
303 } else {\r
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
3c865f20 317 if (LoadedImage->LoadOptionsSize != 0){\r
318 StrCpy(FullCommandLine, LoadedImage->LoadOptions);\r
319 }\r
a405b86d 320 //\r
321 // Populate Argc and Argv\r
322 //\r
323 Status = ParseCommandLineToArgs(FullCommandLine,\r
324 &(*NewShellParameters)->Argv,\r
325 &(*NewShellParameters)->Argc);\r
326\r
327 FreePool(FullCommandLine);\r
328\r
329 ASSERT_EFI_ERROR(Status);\r
330 } else {\r
331 (*NewShellParameters)->Argv = NULL;\r
332 (*NewShellParameters)->Argc = 0;\r
333 }\r
334\r
335 //\r
336 // Populate the 3 faked file systems...\r
337 //\r
338 if (*RootShellInstance) {\r
339 (*NewShellParameters)->StdIn = &FileInterfaceStdIn;\r
340 (*NewShellParameters)->StdOut = &FileInterfaceStdOut;\r
341 (*NewShellParameters)->StdErr = &FileInterfaceStdErr;\r
342 Status = gBS->InstallProtocolInterface(&gImageHandle,\r
343 &gEfiShellParametersProtocolGuid,\r
344 EFI_NATIVE_INTERFACE,\r
345 (VOID*)(*NewShellParameters));\r
346 } else {\r
347 //\r
348 // copy from the existing ones\r
349 //\r
350 (*NewShellParameters)->StdIn = ShellInfoObject.OldShellParameters->StdIn;\r
351 (*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut;\r
352 (*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr;\r
353 Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
354 &gEfiShellParametersProtocolGuid,\r
355 (VOID*)ShellInfoObject.OldShellParameters,\r
356 (VOID*)(*NewShellParameters));\r
357 }\r
358\r
359 return (Status);\r
360}\r
361\r
362/**\r
363 frees all memory used by createion and installation of shell parameters protocol\r
364 and if there was an old version installed it will restore that one.\r
365\r
366 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is\r
367 being cleaned up.\r
368\r
369 @retval EFI_SUCCESS the cleanup was successful\r
370 @return other the cleanup failed\r
371 @sa ReinstallProtocolInterface\r
372 @sa UninstallProtocolInterface\r
373**/\r
374EFI_STATUS\r
375EFIAPI\r
376CleanUpShellParametersProtocol (\r
377 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters\r
378 )\r
379{\r
380 EFI_STATUS Status;\r
381 UINTN LoopCounter;\r
382\r
383 //\r
384 // If the old exists we need to restore it\r
385 //\r
386 if (ShellInfoObject.OldShellParameters != NULL) {\r
387 Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
388 &gEfiShellParametersProtocolGuid,\r
389 (VOID*)NewShellParameters,\r
390 (VOID*)ShellInfoObject.OldShellParameters);\r
391 DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;);\r
392 } else {\r
393 //\r
394 // No old one, just uninstall us...\r
395 //\r
396 Status = gBS->UninstallProtocolInterface(gImageHandle,\r
397 &gEfiShellParametersProtocolGuid,\r
398 (VOID*)NewShellParameters);\r
399 }\r
400 if (NewShellParameters->Argv != NULL) {\r
401 for ( LoopCounter = 0\r
402 ; LoopCounter < NewShellParameters->Argc\r
403 ; LoopCounter++\r
404 ){\r
405 FreePool(NewShellParameters->Argv[LoopCounter]);\r
406 }\r
407 FreePool(NewShellParameters->Argv);\r
408 }\r
409 FreePool(NewShellParameters);\r
410 return (Status);\r
411}\r
412\r
ae724571 413/**\r
414 Determin if a file name represents a unicode file.\r
415\r
416 @param[in] FileName Pointer to the filename to open.\r
417\r
418 @retval EFI_SUCCESS The file is a unicode file.\r
419 @return An error upon failure.\r
420**/\r
733f138d 421EFI_STATUS\r
422EFIAPI\r
423IsUnicodeFile(\r
424 IN CONST CHAR16 *FileName\r
425 )\r
426{\r
427 SHELL_FILE_HANDLE Handle;\r
428 EFI_STATUS Status;\r
429 UINT64 OriginalFilePosition;\r
430 UINTN CharSize;\r
431 CHAR16 CharBuffer;\r
432\r
433 Status = gEfiShellProtocol->OpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ);\r
434 if (EFI_ERROR(Status)) {\r
435 return (Status);\r
436 }\r
437 gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);\r
438 gEfiShellProtocol->SetFilePosition(Handle, 0);\r
439 CharSize = sizeof(CHAR16);\r
440 Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
441 if (EFI_ERROR(Status) || CharBuffer != gUnicodeFileTag) {\r
442 Status = EFI_BUFFER_TOO_SMALL;\r
443 }\r
444 gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
445 gEfiShellProtocol->CloseFile(Handle);\r
446 return (Status); \r
447}\r
448\r
fb84495a 449/**\r
450 Strips out quotes sections of a string.\r
451\r
452 All of the characters between quotes is replaced with spaces.\r
a1d4bfcc 453\r
4ff7e37b 454 @param[in, out] TheString A pointer to the string to update.\r
fb84495a 455**/\r
456VOID\r
457EFIAPI\r
458StripQuotes (\r
459 IN OUT CHAR16 *TheString\r
460 )\r
461{\r
462 BOOLEAN RemoveNow;\r
463\r
464 for (RemoveNow = FALSE ; TheString != NULL && *TheString != CHAR_NULL ; TheString++) {\r
465 if (*TheString == L'^' && *(TheString + 1) == L'\"') {\r
466 TheString++;\r
467 } else if (*TheString == L'\"') {\r
468 RemoveNow = (BOOLEAN)!RemoveNow;\r
469 } else if (RemoveNow) {\r
470 *TheString = L' ';\r
471 }\r
472 }\r
473}\r
474\r
cf6a8f14 475/**\r
476 Calcualte the 32-bit CRC in a EFI table using the service provided by the\r
477 gRuntime service.\r
478\r
479 @param Hdr Pointer to an EFI standard header\r
480\r
481**/\r
482VOID\r
483CalculateEfiHdrCrc (\r
484 IN OUT EFI_TABLE_HEADER *Hdr\r
485 )\r
486{\r
487 UINT32 Crc;\r
488\r
489 Hdr->CRC32 = 0;\r
490\r
491 //\r
492 // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then\r
493 // Crc will come back as zero if we set it to zero here\r
494 //\r
495 Crc = 0;\r
496 gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc);\r
497 Hdr->CRC32 = Crc;\r
498}\r
499\r
031acf63 500/**\r
501 Fix a string to only have the file name, removing starting at the first space of whatever is quoted.\r
502\r
503 @param[in] FileName The filename to start with.\r
504\r
505 @retval NULL FileName was invalid.\r
506 @return The modified FileName.\r
507**/\r
508CHAR16*\r
509EFIAPI\r
510FixFileName (\r
511 IN CHAR16 *FileName\r
512 )\r
513{\r
514 CHAR16 *Copy;\r
515 CHAR16 *TempLocation;\r
516\r
517 if (FileName == NULL) {\r
518 return (NULL);\r
519 }\r
520\r
521 if (FileName[0] == L'\"') {\r
522 Copy = FileName+1;\r
523 if ((TempLocation = StrStr(Copy , L"\"")) != NULL) {\r
524 TempLocation[0] = CHAR_NULL;\r
525 } \r
526 } else {\r
527 Copy = FileName;\r
f9aefb6a 528 while(Copy[0] == L' ') {\r
529 Copy++;\r
530 }\r
031acf63 531 if ((TempLocation = StrStr(Copy , L" ")) != NULL) {\r
532 TempLocation[0] = CHAR_NULL;\r
533 } \r
534 }\r
535\r
536 if (Copy[0] == CHAR_NULL) {\r
537 return (NULL);\r
538 }\r
539\r
540 return (Copy);\r
541}\r
542\r
a405b86d 543/**\r
544 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
545 structure by parsing NewCommandLine. The current values are returned to the\r
546 user.\r
547\r
8be0ba36 548 This will also update the system table.\r
a405b86d 549\r
4ff7e37b
ED
550 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
551 @param[in] NewCommandLine The new command line to parse and use.\r
552 @param[out] OldStdIn Pointer to old StdIn.\r
553 @param[out] OldStdOut Pointer to old StdOut.\r
554 @param[out] OldStdErr Pointer to old StdErr.\r
555 @param[out] SystemTableInfo Pointer to old system table information.\r
a405b86d 556\r
557 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
558 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
559**/\r
560EFI_STATUS\r
561EFIAPI\r
562UpdateStdInStdOutStdErr(\r
563 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
fb84495a 564 IN CHAR16 *NewCommandLine,\r
a405b86d 565 OUT SHELL_FILE_HANDLE *OldStdIn,\r
566 OUT SHELL_FILE_HANDLE *OldStdOut,\r
8be0ba36 567 OUT SHELL_FILE_HANDLE *OldStdErr,\r
568 OUT SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 569 )\r
570{\r
571 CHAR16 *CommandLineCopy;\r
572 CHAR16 *CommandLineWalker;\r
573 CHAR16 *StdErrFileName;\r
574 CHAR16 *StdOutFileName;\r
575 CHAR16 *StdInFileName;\r
576 CHAR16 *StdInVarName;\r
577 CHAR16 *StdOutVarName;\r
578 CHAR16 *StdErrVarName;\r
579 EFI_STATUS Status;\r
580 SHELL_FILE_HANDLE TempHandle;\r
581 UINT64 FileSize;\r
582 BOOLEAN OutUnicode;\r
583 BOOLEAN InUnicode;\r
584 BOOLEAN ErrUnicode;\r
585 BOOLEAN OutAppend;\r
586 BOOLEAN ErrAppend;\r
587 UINTN Size;\r
588 CHAR16 TagBuffer[2];\r
589 SPLIT_LIST *Split;\r
fb84495a 590 CHAR16 *FirstLocation;\r
a405b86d 591\r
a405b86d 592 OutUnicode = TRUE;\r
593 InUnicode = TRUE;\r
594 ErrUnicode = TRUE;\r
595 StdInVarName = NULL;\r
596 StdOutVarName = NULL;\r
597 StdErrVarName = NULL;\r
598 StdErrFileName = NULL;\r
599 StdInFileName = NULL;\r
600 StdOutFileName = NULL;\r
601 ErrAppend = FALSE;\r
602 OutAppend = FALSE;\r
603 CommandLineCopy = NULL;\r
5f2915f5 604 FirstLocation = NULL;\r
a405b86d 605\r
8be0ba36 606 if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {\r
607 return (EFI_INVALID_PARAMETER);\r
a405b86d 608 }\r
609\r
8be0ba36 610 SystemTableInfo->ConIn = gST->ConIn;\r
611 SystemTableInfo->ConInHandle = gST->ConsoleInHandle;\r
612 SystemTableInfo->ConOut = gST->ConOut;\r
613 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;\r
4ccd9214
ED
614 SystemTableInfo->ErrOut = gST->StdErr;\r
615 SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle;\r
8be0ba36 616 *OldStdIn = ShellParameters->StdIn;\r
617 *OldStdOut = ShellParameters->StdOut;\r
618 *OldStdErr = ShellParameters->StdErr;\r
619\r
a405b86d 620 if (NewCommandLine == NULL) {\r
621 return (EFI_SUCCESS);\r
622 }\r
623\r
624 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
532691c8 625 if (CommandLineCopy == NULL) {\r
626 return (EFI_OUT_OF_RESOURCES);\r
627 }\r
a405b86d 628 Status = EFI_SUCCESS;\r
629 Split = NULL;\r
5f2915f5 630 FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);\r
a405b86d 631\r
fb84495a 632 StripQuotes(CommandLineCopy);\r
633\r
a405b86d 634 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
635 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
636 if (Split != NULL && Split->SplitStdIn != NULL) {\r
637 ShellParameters->StdIn = Split->SplitStdIn;\r
638 }\r
639 if (Split != NULL && Split->SplitStdOut != NULL) {\r
640 ShellParameters->StdOut = Split->SplitStdOut;\r
641 }\r
642 }\r
643\r
644 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {\r
fb84495a 645 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 646 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 647 StdErrVarName = CommandLineWalker += 6;\r
648 ErrAppend = TRUE;\r
733f138d 649 if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {\r
650 Status = EFI_NOT_FOUND;\r
651 }\r
a405b86d 652 }\r
653 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
fb84495a 654 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 655 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 656 StdOutVarName = CommandLineWalker += 6;\r
657 OutAppend = TRUE;\r
733f138d 658 if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {\r
659 Status = EFI_NOT_FOUND;\r
660 }\r
a405b86d 661 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
fb84495a 662 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 663 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 664 StdOutVarName = CommandLineWalker += 5;\r
665 OutAppend = TRUE;\r
733f138d 666 if (StrStr(CommandLineWalker, L" >>v ") != NULL) {\r
667 Status = EFI_NOT_FOUND;\r
668 }\r
a405b86d 669 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
fb84495a 670 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 671 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 672 StdOutVarName = CommandLineWalker += 4;\r
673 OutAppend = FALSE;\r
733f138d 674 if (StrStr(CommandLineWalker, L" >v ") != NULL) {\r
675 Status = EFI_NOT_FOUND;\r
676 }\r
a405b86d 677 }\r
678 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
fb84495a 679 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 680 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 681 StdOutFileName = CommandLineWalker += 6;\r
682 OutAppend = TRUE;\r
683 OutUnicode = FALSE;\r
733f138d 684 if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {\r
685 Status = EFI_NOT_FOUND;\r
686 }\r
a405b86d 687 }\r
688 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
fb84495a 689 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 690 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 691 if (StdOutFileName != NULL) {\r
692 Status = EFI_INVALID_PARAMETER;\r
693 } else {\r
694 StdOutFileName = CommandLineWalker += 5;\r
695 OutAppend = TRUE;\r
696 }\r
733f138d 697 if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
698 Status = EFI_NOT_FOUND;\r
699 }\r
a405b86d 700 } \r
701 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
fb84495a 702 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 703 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 704 if (StdOutFileName != NULL) {\r
705 Status = EFI_INVALID_PARAMETER;\r
706 } else {\r
707 StdOutFileName = CommandLineWalker += 4;\r
708 OutAppend = TRUE;\r
709 }\r
733f138d 710 if (StrStr(CommandLineWalker, L" >> ") != NULL) {\r
711 Status = EFI_NOT_FOUND;\r
712 }\r
a405b86d 713 }\r
714 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {\r
fb84495a 715 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 716 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 717 if (StdOutFileName != NULL) {\r
718 Status = EFI_INVALID_PARAMETER;\r
719 } else {\r
720 StdOutFileName = CommandLineWalker += 5;\r
721 OutAppend = TRUE;\r
722 OutUnicode = FALSE;\r
723 }\r
733f138d 724 if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
725 Status = EFI_NOT_FOUND;\r
726 }\r
a405b86d 727 } \r
728 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
fb84495a 729 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 730 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 731 if (StdOutFileName != NULL) {\r
732 Status = EFI_INVALID_PARAMETER;\r
733 } else {\r
734 StdOutFileName = CommandLineWalker += 5;\r
735 OutAppend = FALSE;\r
736 OutUnicode = FALSE;\r
737 }\r
733f138d 738 if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
739 Status = EFI_NOT_FOUND;\r
740 }\r
a405b86d 741 } \r
742 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
fb84495a 743 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 744 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 745 if (StdOutFileName != NULL) {\r
746 Status = EFI_INVALID_PARAMETER;\r
747 } else {\r
748 StdOutFileName = CommandLineWalker += 4;\r
749 OutAppend = FALSE;\r
750 OutUnicode = FALSE;\r
751 }\r
733f138d 752 if (StrStr(CommandLineWalker, L" >a ") != NULL) {\r
753 Status = EFI_NOT_FOUND;\r
754 }\r
a405b86d 755 }\r
756 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
fb84495a 757 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 758 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 759 if (StdErrFileName != NULL) {\r
760 Status = EFI_INVALID_PARAMETER;\r
761 } else {\r
762 StdErrFileName = CommandLineWalker += 5;\r
763 ErrAppend = TRUE;\r
764 }\r
733f138d 765 if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {\r
766 Status = EFI_NOT_FOUND;\r
767 }\r
a405b86d 768 }\r
769\r
770 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
fb84495a 771 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 772 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 773 if (StdErrVarName != NULL) {\r
774 Status = EFI_INVALID_PARAMETER;\r
775 } else {\r
776 StdErrVarName = CommandLineWalker += 5;\r
777 ErrAppend = FALSE;\r
778 }\r
733f138d 779 if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {\r
780 Status = EFI_NOT_FOUND;\r
781 }\r
a405b86d 782 }\r
783 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
fb84495a 784 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 785 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 786 if (StdOutVarName != NULL) {\r
787 Status = EFI_INVALID_PARAMETER;\r
788 } else {\r
789 StdOutVarName = CommandLineWalker += 5;\r
790 OutAppend = FALSE;\r
791 }\r
733f138d 792 if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {\r
793 Status = EFI_NOT_FOUND;\r
794 }\r
a405b86d 795 }\r
796 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
fb84495a 797 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 798 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 799 if (StdErrFileName != NULL) {\r
800 Status = EFI_INVALID_PARAMETER;\r
801 } else {\r
802 StdErrFileName = CommandLineWalker += 5;\r
803 ErrAppend = FALSE;\r
804 ErrUnicode = FALSE;\r
805 }\r
733f138d 806 if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {\r
807 Status = EFI_NOT_FOUND;\r
808 }\r
a405b86d 809 }\r
810 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
fb84495a 811 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 812 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 813 if (StdErrFileName != NULL) {\r
814 Status = EFI_INVALID_PARAMETER;\r
815 } else {\r
816 StdErrFileName = CommandLineWalker += 4;\r
817 ErrAppend = FALSE;\r
818 }\r
733f138d 819 if (StrStr(CommandLineWalker, L" 2> ") != NULL) {\r
820 Status = EFI_NOT_FOUND;\r
821 }\r
a405b86d 822 }\r
823\r
824 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
fb84495a 825 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 826 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 827 if (StdOutFileName != NULL) {\r
828 Status = EFI_INVALID_PARAMETER;\r
829 } else {\r
830 StdOutFileName = CommandLineWalker += 4;\r
831 OutAppend = FALSE;\r
832 }\r
733f138d 833 if (StrStr(CommandLineWalker, L" 1> ") != NULL) {\r
834 Status = EFI_NOT_FOUND;\r
835 }\r
a405b86d 836 }\r
837\r
838 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
fb84495a 839 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 840 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 841 if (StdOutFileName != NULL) {\r
842 Status = EFI_INVALID_PARAMETER;\r
843 } else {\r
844 StdOutFileName = CommandLineWalker += 3;\r
845 OutAppend = FALSE;\r
846 }\r
733f138d 847 if (StrStr(CommandLineWalker, L" > ") != NULL) {\r
848 Status = EFI_NOT_FOUND;\r
849 }\r
a405b86d 850 }\r
851\r
852 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
fb84495a 853 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 854 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 855 if (StdInFileName != NULL) {\r
856 Status = EFI_INVALID_PARAMETER;\r
857 } else {\r
858 StdInFileName = CommandLineWalker += 3;\r
733f138d 859 }\r
860 if (StrStr(CommandLineWalker, L" < ") != NULL) {\r
861 Status = EFI_NOT_FOUND;\r
a405b86d 862 }\r
863 }\r
864 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
fb84495a 865 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 866 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 867 if (StdInFileName != NULL) {\r
868 Status = EFI_INVALID_PARAMETER;\r
869 } else {\r
733f138d 870 StdInFileName = CommandLineWalker += 4;\r
871 InUnicode = FALSE;\r
872 }\r
873 if (StrStr(CommandLineWalker, L" <a ") != NULL) {\r
874 Status = EFI_NOT_FOUND;\r
a405b86d 875 }\r
876 }\r
877 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {\r
fb84495a 878 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 879 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 880 if (StdInVarName != NULL) {\r
881 Status = EFI_INVALID_PARAMETER;\r
882 } else {\r
883 StdInVarName = CommandLineWalker += 4;\r
733f138d 884 }\r
885 if (StrStr(CommandLineWalker, L" <v ") != NULL) {\r
886 Status = EFI_NOT_FOUND;\r
a405b86d 887 }\r
888 }\r
889\r
031acf63 890 //\r
891 // re-populate the string to support any filenames that were in quotes.\r
892 //\r
893 StrCpy(CommandLineCopy, NewCommandLine);\r
894\r
5f2915f5 895 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
fb84495a 896 && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))\r
897 ){\r
898 *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;\r
899 }\r
900\r
a405b86d 901 if (!EFI_ERROR(Status)) {\r
031acf63 902\r
903 if (StdErrFileName != NULL) {\r
904 if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {\r
905 Status = EFI_INVALID_PARAMETER;\r
906 }\r
a405b86d 907 }\r
031acf63 908 if (StdOutFileName != NULL) {\r
909 if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {\r
910 Status = EFI_INVALID_PARAMETER;\r
911 }\r
a405b86d 912 }\r
031acf63 913 if (StdInFileName != NULL) {\r
914 if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {\r
915 Status = EFI_INVALID_PARAMETER;\r
916 }\r
a405b86d 917 }\r
031acf63 918 if (StdErrVarName != NULL) {\r
919 if ((StdErrVarName = FixFileName(StdErrVarName)) == NULL) {\r
920 Status = EFI_INVALID_PARAMETER;\r
921 }\r
a405b86d 922 }\r
031acf63 923 if (StdOutVarName != NULL) {\r
924 if ((StdOutVarName = FixFileName(StdOutVarName)) == NULL) {\r
925 Status = EFI_INVALID_PARAMETER;\r
926 }\r
a405b86d 927 }\r
031acf63 928 if (StdInVarName != NULL) {\r
929 if ((StdInVarName = FixFileName(StdInVarName)) == NULL) {\r
930 Status = EFI_INVALID_PARAMETER;\r
931 }\r
a405b86d 932 }\r
933\r
0c956e0d 934 //\r
935 // Verify not the same and not duplicating something from a split\r
936 //\r
733f138d 937 if (\r
938 //\r
939 // Check that no 2 filenames are the same\r
940 //\r
fb84495a 941 (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
a405b86d 942 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
943 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
733f138d 944 //\r
945 // Check that no 2 variable names are the same\r
946 //\r
a405b86d 947 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)\r
948 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)\r
949 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)\r
733f138d 950 //\r
951 // When a split (using | operator) is in place some are not allowed\r
952 //\r
a405b86d 953 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))\r
954 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
733f138d 955 //\r
956 // Check that nothing is trying to be output to 2 locations.\r
957 //\r
a405b86d 958 ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
959 ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
960 ||(StdInFileName != NULL && StdInVarName != NULL)\r
733f138d 961 //\r
733f138d 962 // Check for no volatile environment variables\r
963 //\r
a405b86d 964 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))\r
965 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))\r
733f138d 966 //\r
967 // Cant redirect during a reconnect operation.\r
968 //\r
3c865f20 969 ||(StrStr(NewCommandLine, L"connect -r") != NULL \r
970 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
733f138d 971 //\r
972 // Check that filetypes (Unicode/Ascii) do not change during an append\r
973 //\r
974 ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
975 ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
976 ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
977 ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
a405b86d 978 ){\r
979 Status = EFI_INVALID_PARAMETER;\r
a9ca0684 980 ShellParameters->StdIn = *OldStdIn;\r
981 ShellParameters->StdOut = *OldStdOut;\r
982 ShellParameters->StdErr = *OldStdErr;\r
fb84495a 983 } else if (!EFI_ERROR(Status)){\r
a405b86d 984 //\r
985 // Open the Std<Whatever> and we should not have conflicts here...\r
986 //\r
987\r
988 //\r
989 // StdErr to a file\r
990 //\r
991 if (StdErrFileName != NULL) {\r
992 if (!ErrAppend) {\r
993 //\r
994 // delete existing file.\r
995 //\r
996 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);\r
997 }\r
998 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
a405b86d 999 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
1000 //\r
733f138d 1001 // Write out the gUnicodeFileTag\r
a405b86d 1002 //\r
1003 Size = sizeof(CHAR16);\r
733f138d 1004 TagBuffer[0] = gUnicodeFileTag;\r
a405b86d 1005 TagBuffer[1] = CHAR_NULL;\r
1006 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
1007 }\r
1008 if (!ErrUnicode && !EFI_ERROR(Status)) {\r
1009 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1010 ASSERT(TempHandle != NULL);\r
1011 }\r
1012 if (!EFI_ERROR(Status)) {\r
1013 ShellParameters->StdErr = TempHandle;\r
8be0ba36 1014 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);\r
a405b86d 1015 }\r
1016 }\r
1017\r
1018 //\r
1019 // StdOut to a file\r
1020 //\r
1021 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {\r
1022 if (!OutAppend) {\r
1023 //\r
1024 // delete existing file.\r
1025 //\r
1026 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);\r
1027 }\r
1028 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
3c865f20 1029 if (TempHandle == NULL) {\r
1030 Status = EFI_INVALID_PARAMETER;\r
1031 } else {\r
733f138d 1032 if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {\r
1033 //no-op\r
1034 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
3c865f20 1035 //\r
733f138d 1036 // Write out the gUnicodeFileTag\r
3c865f20 1037 //\r
1038 Size = sizeof(CHAR16);\r
733f138d 1039 TagBuffer[0] = gUnicodeFileTag;\r
3c865f20 1040 TagBuffer[1] = CHAR_NULL;\r
1041 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
1042 } else if (OutAppend) {\r
1043 //\r
1044 // Move to end of file\r
1045 //\r
1046 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);\r
1047 if (!EFI_ERROR(Status)) {\r
1048 Status = ShellInfoObject.NewEfiShellProtocol->SetFilePosition(TempHandle, FileSize);\r
1049 }\r
1050 }\r
1051 if (!OutUnicode && !EFI_ERROR(Status)) {\r
1052 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1053 ASSERT(TempHandle != NULL);\r
1054 }\r
a405b86d 1055 if (!EFI_ERROR(Status)) {\r
3c865f20 1056 ShellParameters->StdOut = TempHandle;\r
8be0ba36 1057 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);\r
a405b86d 1058 }\r
1059 }\r
a405b86d 1060 }\r
1061\r
1062 //\r
1063 // StdOut to a var\r
1064 //\r
1065 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {\r
1066 if (!OutAppend) {\r
1067 //\r
1068 // delete existing variable.\r
1069 //\r
1070 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");\r
1071 }\r
1072 TempHandle = CreateFileInterfaceEnv(StdOutVarName);\r
1073 ASSERT(TempHandle != NULL);\r
a405b86d 1074 ShellParameters->StdOut = TempHandle;\r
8be0ba36 1075 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);\r
a405b86d 1076 }\r
1077\r
1078 //\r
1079 // StdErr to a var\r
1080 //\r
1081 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {\r
1082 if (!ErrAppend) {\r
1083 //\r
1084 // delete existing variable.\r
1085 //\r
1086 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");\r
1087 }\r
1088 TempHandle = CreateFileInterfaceEnv(StdErrVarName);\r
1089 ASSERT(TempHandle != NULL);\r
a405b86d 1090 ShellParameters->StdErr = TempHandle;\r
8be0ba36 1091 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);\r
a405b86d 1092 }\r
1093\r
1094 //\r
1095 // StdIn from a var\r
1096 //\r
1097 if (!EFI_ERROR(Status) && StdInVarName != NULL) {\r
1098 TempHandle = CreateFileInterfaceEnv(StdInVarName);\r
532691c8 1099 if (TempHandle == NULL) {\r
1100 Status = EFI_OUT_OF_RESOURCES;\r
a405b86d 1101 } else {\r
532691c8 1102 if (!InUnicode) {\r
1103 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1104 }\r
1105 Size = 0;\r
96962f0a 1106 if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
532691c8 1107 Status = EFI_INVALID_PARAMETER;\r
1108 } else {\r
1109 ShellParameters->StdIn = TempHandle;\r
1110 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1111 }\r
a405b86d 1112 }\r
1113 }\r
1114\r
1115 //\r
1116 // StdIn from a file\r
1117 //\r
1118 if (!EFI_ERROR(Status) && StdInFileName != NULL) {\r
1119 Status = ShellOpenFileByName(\r
1120 StdInFileName,\r
1121 &TempHandle,\r
1122 EFI_FILE_MODE_READ,\r
1123 0);\r
1124 if (!InUnicode && !EFI_ERROR(Status)) {\r
1125 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1126 }\r
1127 if (!EFI_ERROR(Status)) {\r
1128 ShellParameters->StdIn = TempHandle;\r
8be0ba36 1129 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
a405b86d 1130 }\r
1131 }\r
1132 }\r
1133 }\r
1134 FreePool(CommandLineCopy);\r
8be0ba36 1135\r
cf6a8f14 1136 CalculateEfiHdrCrc(&gST->Hdr);\r
1137\r
8be0ba36 1138 if (gST->ConIn == NULL ||gST->ConOut == NULL) {\r
1139 return (EFI_OUT_OF_RESOURCES);\r
1140 }\r
a405b86d 1141 return (Status);\r
1142}\r
1143\r
1144/**\r
1145 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
1146 structure with StdIn and StdOut. The current values are de-allocated.\r
1147\r
4ff7e37b
ED
1148 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1149 @param[in] OldStdIn Pointer to old StdIn.\r
1150 @param[in] OldStdOut Pointer to old StdOut.\r
1151 @param[in] OldStdErr Pointer to old StdErr.\r
1152 @param[in] SystemTableInfo Pointer to old system table information.\r
a405b86d 1153**/\r
1154EFI_STATUS\r
1155EFIAPI\r
1156RestoreStdInStdOutStdErr (\r
1157 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
8be0ba36 1158 IN SHELL_FILE_HANDLE *OldStdIn,\r
1159 IN SHELL_FILE_HANDLE *OldStdOut,\r
1160 IN SHELL_FILE_HANDLE *OldStdErr,\r
1161 IN SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 1162 )\r
1163{\r
1164 SPLIT_LIST *Split;\r
8be0ba36 1165\r
1166 if (ShellParameters == NULL \r
1167 ||OldStdIn == NULL\r
1168 ||OldStdOut == NULL\r
1169 ||OldStdErr == NULL\r
1170 ||SystemTableInfo == NULL) {\r
1171 return (EFI_INVALID_PARAMETER);\r
1172 }\r
a405b86d 1173 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
1174 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
1175 } else {\r
1176 Split = NULL;\r
1177 }\r
8be0ba36 1178 if (ShellParameters->StdIn != *OldStdIn) {\r
a405b86d 1179 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
1180 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
1181 }\r
8be0ba36 1182 ShellParameters->StdIn = *OldStdIn;\r
a405b86d 1183 }\r
8be0ba36 1184 if (ShellParameters->StdOut != *OldStdOut) {\r
a405b86d 1185 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
1186 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
1187 }\r
8be0ba36 1188 ShellParameters->StdOut = *OldStdOut;\r
1189 }\r
1190 if (ShellParameters->StdErr != *OldStdErr) {\r
1191 gEfiShellProtocol->CloseFile(ShellParameters->StdErr);\r
1192 ShellParameters->StdErr = *OldStdErr;\r
1193 }\r
1194\r
1195 if (gST->ConIn != SystemTableInfo->ConIn) {\r
1196 CloseSimpleTextInOnFile(gST->ConIn);\r
1197 gST->ConIn = SystemTableInfo->ConIn;\r
1198 gST->ConsoleInHandle = SystemTableInfo->ConInHandle;\r
a405b86d 1199 }\r
8be0ba36 1200 if (gST->ConOut != SystemTableInfo->ConOut) {\r
1201 CloseSimpleTextOutOnFile(gST->ConOut);\r
1202 gST->ConOut = SystemTableInfo->ConOut;\r
1203 gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;\r
1204 }\r
4ccd9214 1205 if (gST->StdErr != SystemTableInfo->ErrOut) {\r
8be0ba36 1206 CloseSimpleTextOutOnFile(gST->StdErr);\r
4ccd9214
ED
1207 gST->StdErr = SystemTableInfo->ErrOut;\r
1208 gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle;\r
8be0ba36 1209 }\r
1210\r
cf6a8f14 1211 CalculateEfiHdrCrc(&gST->Hdr);\r
1212\r
a405b86d 1213 return (EFI_SUCCESS);\r
1214}\r
1215/**\r
1216 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1217 structure by parsing NewCommandLine. The current values are returned to the\r
1218 user.\r
1219\r
1220 If OldArgv or OldArgc is NULL then that value is not returned.\r
1221\r
4ff7e37b
ED
1222 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1223 @param[in] NewCommandLine The new command line to parse and use.\r
1224 @param[out] OldArgv Pointer to old list of parameters.\r
1225 @param[out] OldArgc Pointer to old number of items in Argv list.\r
a405b86d 1226\r
1227 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
1228 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1229**/\r
1230EFI_STATUS\r
1231EFIAPI\r
1232UpdateArgcArgv(\r
1233 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1234 IN CONST CHAR16 *NewCommandLine,\r
1235 OUT CHAR16 ***OldArgv OPTIONAL,\r
1236 OUT UINTN *OldArgc OPTIONAL\r
1237 )\r
1238{\r
1239 ASSERT(ShellParameters != NULL);\r
1240\r
1241 if (OldArgc != NULL) {\r
1242 *OldArgc = ShellParameters->Argc;\r
1243 }\r
1244 if (OldArgc != NULL) {\r
1245 *OldArgv = ShellParameters->Argv;\r
1246 }\r
1247\r
1248 return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));\r
1249}\r
1250\r
1251/**\r
1252 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1253 structure with Argv and Argc. The current values are de-allocated and the\r
1254 OldArgv must not be deallocated by the caller.\r
1255\r
4ff7e37b
ED
1256 @param[in, out] ShellParameters pointer to parameter structure to modify\r
1257 @param[in] OldArgv pointer to old list of parameters\r
1258 @param[in] OldArgc pointer to old number of items in Argv list\r
a405b86d 1259**/\r
1260VOID\r
1261EFIAPI\r
1262RestoreArgcArgv(\r
1263 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1264 IN CHAR16 ***OldArgv,\r
1265 IN UINTN *OldArgc\r
1266 )\r
1267{\r
1268 UINTN LoopCounter;\r
1269 ASSERT(ShellParameters != NULL);\r
1270 ASSERT(OldArgv != NULL);\r
1271 ASSERT(OldArgc != NULL);\r
1272\r
1273 if (ShellParameters->Argv != NULL) {\r
1274 for ( LoopCounter = 0\r
1275 ; LoopCounter < ShellParameters->Argc\r
1276 ; LoopCounter++\r
1277 ){\r
1278 FreePool(ShellParameters->Argv[LoopCounter]);\r
1279 }\r
1280 FreePool(ShellParameters->Argv);\r
1281 }\r
1282 ShellParameters->Argv = *OldArgv;\r
1283 *OldArgv = NULL;\r
1284 ShellParameters->Argc = *OldArgc;\r
1285 *OldArgc = 0;\r
1286}\r