]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Application/Shell/ShellParametersProtocol.c
ShellPkg: Stop running command when page break quit
[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
2c5a8aed 5 Copyright (c) 2009 - 2013, 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
0406a571 16#include "Shell.h"\r
a405b86d 17\r
18/**\r
19 return the next parameter from a command line string;\r
20\r
21 This function moves the next parameter from Walker into TempParameter and moves\r
22 Walker up past that parameter for recursive calling. When the final parameter\r
23 is moved *Walker will be set to NULL;\r
24\r
25 Temp Parameter must be large enough to hold the parameter before calling this\r
26 function.\r
27\r
4ff7e37b 28 @param[in, out] Walker pointer to string of command line. Adjusted to\r
a405b86d 29 reminaing command line on return\r
4ff7e37b 30 @param[in, out] TempParameter pointer to string of command line item extracted.\r
a405b86d 31\r
32**/\r
33VOID\r
34EFIAPI\r
35GetNextParameter(\r
36 CHAR16 **Walker,\r
37 CHAR16 **TempParameter\r
38 )\r
39{\r
40 CHAR16 *NextDelim;\r
41 CHAR16 *TempLoc;\r
42\r
43 ASSERT(Walker != NULL);\r
44 ASSERT(*Walker != NULL);\r
45 ASSERT(TempParameter != NULL);\r
46 ASSERT(*TempParameter != NULL);\r
47\r
48 //\r
49 // make sure we dont have any leading spaces\r
50 //\r
51 while ((*Walker)[0] == L' ') {\r
52 (*Walker)++;\r
53 }\r
54\r
55 //\r
56 // make sure we still have some params now...\r
57 //\r
58 if (StrLen(*Walker) == 0) {\r
59 ASSERT((*Walker)[0] == CHAR_NULL);\r
60 *Walker = NULL;\r
61 return;\r
62 }\r
63\r
64 //\r
65 // we have a quoted parameter\r
66 // could be the last parameter, but SHOULD have a trailing quote\r
67 //\r
68 if ((*Walker)[0] == L'\"') {\r
69 NextDelim = NULL;\r
70 for (TempLoc = *Walker + 1 ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {\r
d8f8021c 71 if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {\r
a405b86d 72 TempLoc++;\r
a405b86d 73 } else if (*TempLoc == L'\"') {\r
74 NextDelim = TempLoc;\r
75 break;\r
76 }\r
77 }\r
78\r
79 if (NextDelim - ((*Walker)+1) == 0) {\r
80 //\r
81 // found ""\r
82 //\r
83 StrCpy(*TempParameter, L"");\r
84 *Walker = NextDelim + 1;\r
85 } else if (NextDelim != NULL) {\r
86 StrnCpy(*TempParameter, (*Walker)+1, NextDelim - ((*Walker)+1));\r
87 *Walker = NextDelim + 1;\r
88 } else {\r
89 //\r
90 // last one... someone forgot the training quote!\r
91 //\r
92 StrCpy(*TempParameter, *Walker);\r
93 *Walker = NULL;\r
94 }\r
95 for (TempLoc = *TempParameter ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {\r
d8f8021c 96 if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {\r
a405b86d 97 CopyMem(TempLoc, TempLoc+1, StrSize(TempLoc) - sizeof(TempLoc[0]));\r
98 }\r
99 }\r
100 } else {\r
101 //\r
102 // we have a regular parameter (no quote) OR\r
103 // we have the final parameter (no trailing space)\r
104 //\r
105 NextDelim = StrStr((*Walker), L" ");\r
106 if (NextDelim != NULL) {\r
107 StrnCpy(*TempParameter, *Walker, NextDelim - (*Walker));\r
108 (*TempParameter)[NextDelim - (*Walker)] = CHAR_NULL;\r
109 *Walker = NextDelim+1;\r
110 } else {\r
111 //\r
112 // last one.\r
113 //\r
114 StrCpy(*TempParameter, *Walker);\r
115 *Walker = NULL;\r
116 }\r
117 for (NextDelim = *TempParameter ; NextDelim != NULL && *NextDelim != CHAR_NULL ; NextDelim++) {\r
118 if (*NextDelim == L'^' && *(NextDelim+1) == L'^') {\r
119 CopyMem(NextDelim, NextDelim+1, StrSize(NextDelim) - sizeof(NextDelim[0]));\r
d8f8021c 120 }\r
a405b86d 121 }\r
122 while ((*TempParameter)[StrLen(*TempParameter)-1] == L' ') {\r
123 (*TempParameter)[StrLen(*TempParameter)-1] = CHAR_NULL;\r
124 }\r
125 while ((*TempParameter)[0] == L' ') {\r
126 CopyMem(*TempParameter, (*TempParameter)+1, StrSize(*TempParameter) - sizeof((*TempParameter)[0]));\r
127 }\r
128 }\r
129 return;\r
130}\r
131\r
132/**\r
733f138d 133 Function to populate Argc and Argv.\r
a405b86d 134\r
135 This function parses the CommandLine and divides it into standard C style Argc/Argv\r
136 parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space\r
137 delimited and quote surrounded parameter definition.\r
138\r
4ff7e37b
ED
139 @param[in] CommandLine String of command line to parse\r
140 @param[in, out] Argv pointer to array of strings; one for each parameter\r
141 @param[in, out] Argc pointer to number of strings in Argv array\r
a405b86d 142\r
143 @return EFI_SUCCESS the operation was sucessful\r
144 @return EFI_OUT_OF_RESOURCES a memory allocation failed.\r
145**/\r
146EFI_STATUS\r
147EFIAPI\r
148ParseCommandLineToArgs(\r
149 IN CONST CHAR16 *CommandLine,\r
150 IN OUT CHAR16 ***Argv,\r
151 IN OUT UINTN *Argc\r
152 )\r
153{\r
154 UINTN Count;\r
155 CHAR16 *TempParameter;\r
156 CHAR16 *Walker;\r
157 CHAR16 *NewParam;\r
158 UINTN Size;\r
159\r
160 ASSERT(Argc != NULL);\r
161 ASSERT(Argv != NULL);\r
162\r
163 if (CommandLine == NULL || StrLen(CommandLine)==0) {\r
164 (*Argc) = 0;\r
165 (*Argv) = NULL;\r
166 return (EFI_SUCCESS);\r
167 }\r
168\r
169 Size = StrSize(CommandLine);\r
170 TempParameter = AllocateZeroPool(Size);\r
171 if (TempParameter == NULL) {\r
172 return (EFI_OUT_OF_RESOURCES);\r
173 }\r
174\r
175 for ( Count = 0\r
176 , Walker = (CHAR16*)CommandLine\r
177 ; Walker != NULL && *Walker != CHAR_NULL\r
178 ; GetNextParameter(&Walker, &TempParameter)\r
179 , Count++\r
180 );\r
181\r
182/* Count = 0;\r
183 Walker = (CHAR16*)CommandLine;\r
184 while(Walker != NULL) {\r
185 GetNextParameter(&Walker, &TempParameter);\r
186 Count++;\r
187 }\r
188*/\r
189 //\r
190 // lets allocate the pointer array\r
191 //\r
192 (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*));\r
193 if (*Argv == NULL) {\r
3f869579 194 SHELL_FREE_NON_NULL(TempParameter);\r
a405b86d 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
3f869579 210 SHELL_FREE_NON_NULL(TempParameter);\r
a405b86d 211 return (EFI_SUCCESS);\r
212}\r
213\r
214/**\r
215 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then\r
216 installs it on our handle and if there is an existing version of the protocol\r
217 that one is cached for removal later.\r
218\r
4ff7e37b 219 @param[in, out] NewShellParameters on a successful return, a pointer to pointer\r
a405b86d 220 to the newly installed interface.\r
4ff7e37b 221 @param[in, out] RootShellInstance on a successful return, pointer to boolean.\r
a405b86d 222 TRUE if this is the root shell instance.\r
223\r
224 @retval EFI_SUCCESS the operation completed successfully.\r
225 @return other the operation failed.\r
226 @sa ReinstallProtocolInterface\r
227 @sa InstallProtocolInterface\r
228 @sa ParseCommandLineToArgs\r
229**/\r
230EFI_STATUS\r
231EFIAPI\r
232CreatePopulateInstallShellParametersProtocol (\r
233 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters,\r
234 IN OUT BOOLEAN *RootShellInstance\r
235 )\r
236{\r
237 EFI_STATUS Status;\r
238 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
239 CHAR16 *FullCommandLine;\r
240 UINTN Size;\r
241\r
242 Size = 0;\r
243 FullCommandLine = NULL;\r
244 LoadedImage = NULL;\r
245\r
246 //\r
247 // Assert for valid parameters\r
248 //\r
249 ASSERT(NewShellParameters != NULL);\r
250 ASSERT(RootShellInstance != NULL);\r
251\r
252 //\r
253 // See if we have a shell parameters placed on us\r
254 //\r
255 Status = gBS->OpenProtocol (\r
256 gImageHandle,\r
257 &gEfiShellParametersProtocolGuid,\r
258 (VOID **) &ShellInfoObject.OldShellParameters,\r
259 gImageHandle,\r
260 NULL,\r
261 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
262 );\r
263 //\r
264 // if we don't then we must be the root shell (error is expected)\r
265 //\r
266 if (EFI_ERROR (Status)) {\r
267 *RootShellInstance = TRUE;\r
268 }\r
269\r
270 //\r
271 // Allocate the new structure\r
272 //\r
273 *NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));\r
3c865f20 274 if ((*NewShellParameters) == NULL) {\r
275 return (EFI_OUT_OF_RESOURCES);\r
276 }\r
a405b86d 277\r
278 //\r
279 // get loaded image protocol\r
280 //\r
281 Status = gBS->OpenProtocol (\r
282 gImageHandle,\r
283 &gEfiLoadedImageProtocolGuid,\r
284 (VOID **) &LoadedImage,\r
285 gImageHandle,\r
286 NULL,\r
287 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
288 );\r
289 ASSERT_EFI_ERROR(Status);\r
290 //\r
291 // Build the full command line\r
292 //\r
e886b675 293 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);\r
a405b86d 294 if (Status == EFI_BUFFER_TOO_SMALL) {\r
295 FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);\r
e886b675 296 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);\r
a405b86d 297 }\r
298 if (Status == EFI_NOT_FOUND) {\r
299 //\r
300 // no parameters via environment... ok\r
301 //\r
302 } else {\r
3c865f20 303 if (EFI_ERROR(Status)) {\r
304 return (Status);\r
305 }\r
a405b86d 306 }\r
307 if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {\r
3c865f20 308 ASSERT(FullCommandLine == NULL);\r
a405b86d 309 //\r
310 // Now we need to include a NULL terminator in the size.\r
311 //\r
312 Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]);\r
313 FullCommandLine = AllocateZeroPool(Size);\r
314 }\r
a405b86d 315 if (FullCommandLine != NULL) {\r
2c5a8aed 316 CopyMem (FullCommandLine, LoadedImage->LoadOptions, LoadedImage->LoadOptionsSize);\r
a405b86d 317 //\r
318 // Populate Argc and Argv\r
319 //\r
320 Status = ParseCommandLineToArgs(FullCommandLine,\r
321 &(*NewShellParameters)->Argv,\r
322 &(*NewShellParameters)->Argc);\r
323\r
324 FreePool(FullCommandLine);\r
325\r
326 ASSERT_EFI_ERROR(Status);\r
327 } else {\r
328 (*NewShellParameters)->Argv = NULL;\r
329 (*NewShellParameters)->Argc = 0;\r
330 }\r
331\r
332 //\r
333 // Populate the 3 faked file systems...\r
334 //\r
335 if (*RootShellInstance) {\r
336 (*NewShellParameters)->StdIn = &FileInterfaceStdIn;\r
337 (*NewShellParameters)->StdOut = &FileInterfaceStdOut;\r
338 (*NewShellParameters)->StdErr = &FileInterfaceStdErr;\r
339 Status = gBS->InstallProtocolInterface(&gImageHandle,\r
340 &gEfiShellParametersProtocolGuid,\r
341 EFI_NATIVE_INTERFACE,\r
342 (VOID*)(*NewShellParameters));\r
343 } else {\r
344 //\r
345 // copy from the existing ones\r
346 //\r
347 (*NewShellParameters)->StdIn = ShellInfoObject.OldShellParameters->StdIn;\r
348 (*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut;\r
349 (*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr;\r
350 Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
351 &gEfiShellParametersProtocolGuid,\r
352 (VOID*)ShellInfoObject.OldShellParameters,\r
353 (VOID*)(*NewShellParameters));\r
354 }\r
355\r
356 return (Status);\r
357}\r
358\r
359/**\r
360 frees all memory used by createion and installation of shell parameters protocol\r
361 and if there was an old version installed it will restore that one.\r
362\r
363 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is\r
364 being cleaned up.\r
365\r
366 @retval EFI_SUCCESS the cleanup was successful\r
367 @return other the cleanup failed\r
368 @sa ReinstallProtocolInterface\r
369 @sa UninstallProtocolInterface\r
370**/\r
371EFI_STATUS\r
372EFIAPI\r
373CleanUpShellParametersProtocol (\r
374 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters\r
375 )\r
376{\r
377 EFI_STATUS Status;\r
378 UINTN LoopCounter;\r
379\r
380 //\r
381 // If the old exists we need to restore it\r
382 //\r
383 if (ShellInfoObject.OldShellParameters != NULL) {\r
384 Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
385 &gEfiShellParametersProtocolGuid,\r
386 (VOID*)NewShellParameters,\r
387 (VOID*)ShellInfoObject.OldShellParameters);\r
388 DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;);\r
389 } else {\r
390 //\r
391 // No old one, just uninstall us...\r
392 //\r
393 Status = gBS->UninstallProtocolInterface(gImageHandle,\r
394 &gEfiShellParametersProtocolGuid,\r
395 (VOID*)NewShellParameters);\r
396 }\r
397 if (NewShellParameters->Argv != NULL) {\r
398 for ( LoopCounter = 0\r
399 ; LoopCounter < NewShellParameters->Argc\r
400 ; LoopCounter++\r
401 ){\r
402 FreePool(NewShellParameters->Argv[LoopCounter]);\r
403 }\r
404 FreePool(NewShellParameters->Argv);\r
405 }\r
406 FreePool(NewShellParameters);\r
407 return (Status);\r
408}\r
409\r
ae724571 410/**\r
411 Determin if a file name represents a unicode file.\r
412\r
413 @param[in] FileName Pointer to the filename to open.\r
414\r
415 @retval EFI_SUCCESS The file is a unicode file.\r
416 @return An error upon failure.\r
417**/\r
733f138d 418EFI_STATUS\r
419EFIAPI\r
420IsUnicodeFile(\r
421 IN CONST CHAR16 *FileName\r
422 )\r
423{\r
424 SHELL_FILE_HANDLE Handle;\r
425 EFI_STATUS Status;\r
426 UINT64 OriginalFilePosition;\r
427 UINTN CharSize;\r
428 CHAR16 CharBuffer;\r
429\r
430 Status = gEfiShellProtocol->OpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ);\r
431 if (EFI_ERROR(Status)) {\r
432 return (Status);\r
433 }\r
434 gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);\r
435 gEfiShellProtocol->SetFilePosition(Handle, 0);\r
436 CharSize = sizeof(CHAR16);\r
437 Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
438 if (EFI_ERROR(Status) || CharBuffer != gUnicodeFileTag) {\r
439 Status = EFI_BUFFER_TOO_SMALL;\r
440 }\r
441 gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
442 gEfiShellProtocol->CloseFile(Handle);\r
443 return (Status); \r
444}\r
445\r
fb84495a 446/**\r
447 Strips out quotes sections of a string.\r
448\r
449 All of the characters between quotes is replaced with spaces.\r
a1d4bfcc 450\r
4ff7e37b 451 @param[in, out] TheString A pointer to the string to update.\r
fb84495a 452**/\r
453VOID\r
454EFIAPI\r
455StripQuotes (\r
456 IN OUT CHAR16 *TheString\r
457 )\r
458{\r
459 BOOLEAN RemoveNow;\r
460\r
461 for (RemoveNow = FALSE ; TheString != NULL && *TheString != CHAR_NULL ; TheString++) {\r
462 if (*TheString == L'^' && *(TheString + 1) == L'\"') {\r
463 TheString++;\r
464 } else if (*TheString == L'\"') {\r
465 RemoveNow = (BOOLEAN)!RemoveNow;\r
466 } else if (RemoveNow) {\r
467 *TheString = L' ';\r
468 }\r
469 }\r
470}\r
471\r
cf6a8f14 472/**\r
473 Calcualte the 32-bit CRC in a EFI table using the service provided by the\r
474 gRuntime service.\r
475\r
476 @param Hdr Pointer to an EFI standard header\r
477\r
478**/\r
479VOID\r
480CalculateEfiHdrCrc (\r
481 IN OUT EFI_TABLE_HEADER *Hdr\r
482 )\r
483{\r
484 UINT32 Crc;\r
485\r
486 Hdr->CRC32 = 0;\r
487\r
488 //\r
489 // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then\r
490 // Crc will come back as zero if we set it to zero here\r
491 //\r
492 Crc = 0;\r
493 gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc);\r
494 Hdr->CRC32 = Crc;\r
495}\r
496\r
031acf63 497/**\r
498 Fix a string to only have the file name, removing starting at the first space of whatever is quoted.\r
499\r
500 @param[in] FileName The filename to start with.\r
501\r
502 @retval NULL FileName was invalid.\r
503 @return The modified FileName.\r
504**/\r
505CHAR16*\r
506EFIAPI\r
507FixFileName (\r
508 IN CHAR16 *FileName\r
509 )\r
510{\r
511 CHAR16 *Copy;\r
512 CHAR16 *TempLocation;\r
513\r
514 if (FileName == NULL) {\r
515 return (NULL);\r
516 }\r
517\r
518 if (FileName[0] == L'\"') {\r
519 Copy = FileName+1;\r
520 if ((TempLocation = StrStr(Copy , L"\"")) != NULL) {\r
521 TempLocation[0] = CHAR_NULL;\r
522 } \r
523 } else {\r
524 Copy = FileName;\r
f9aefb6a 525 while(Copy[0] == L' ') {\r
526 Copy++;\r
527 }\r
031acf63 528 if ((TempLocation = StrStr(Copy , L" ")) != NULL) {\r
529 TempLocation[0] = CHAR_NULL;\r
530 } \r
531 }\r
532\r
533 if (Copy[0] == CHAR_NULL) {\r
534 return (NULL);\r
535 }\r
536\r
537 return (Copy);\r
538}\r
539\r
a405b86d 540/**\r
541 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
542 structure by parsing NewCommandLine. The current values are returned to the\r
543 user.\r
544\r
8be0ba36 545 This will also update the system table.\r
a405b86d 546\r
4ff7e37b
ED
547 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
548 @param[in] NewCommandLine The new command line to parse and use.\r
549 @param[out] OldStdIn Pointer to old StdIn.\r
550 @param[out] OldStdOut Pointer to old StdOut.\r
551 @param[out] OldStdErr Pointer to old StdErr.\r
552 @param[out] SystemTableInfo Pointer to old system table information.\r
a405b86d 553\r
554 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
555 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
556**/\r
557EFI_STATUS\r
558EFIAPI\r
559UpdateStdInStdOutStdErr(\r
560 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
fb84495a 561 IN CHAR16 *NewCommandLine,\r
a405b86d 562 OUT SHELL_FILE_HANDLE *OldStdIn,\r
563 OUT SHELL_FILE_HANDLE *OldStdOut,\r
8be0ba36 564 OUT SHELL_FILE_HANDLE *OldStdErr,\r
565 OUT SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 566 )\r
567{\r
568 CHAR16 *CommandLineCopy;\r
569 CHAR16 *CommandLineWalker;\r
570 CHAR16 *StdErrFileName;\r
571 CHAR16 *StdOutFileName;\r
572 CHAR16 *StdInFileName;\r
573 CHAR16 *StdInVarName;\r
574 CHAR16 *StdOutVarName;\r
575 CHAR16 *StdErrVarName;\r
576 EFI_STATUS Status;\r
577 SHELL_FILE_HANDLE TempHandle;\r
578 UINT64 FileSize;\r
579 BOOLEAN OutUnicode;\r
580 BOOLEAN InUnicode;\r
581 BOOLEAN ErrUnicode;\r
582 BOOLEAN OutAppend;\r
583 BOOLEAN ErrAppend;\r
584 UINTN Size;\r
585 CHAR16 TagBuffer[2];\r
586 SPLIT_LIST *Split;\r
fb84495a 587 CHAR16 *FirstLocation;\r
a405b86d 588\r
a405b86d 589 OutUnicode = TRUE;\r
590 InUnicode = TRUE;\r
591 ErrUnicode = TRUE;\r
592 StdInVarName = NULL;\r
593 StdOutVarName = NULL;\r
594 StdErrVarName = NULL;\r
595 StdErrFileName = NULL;\r
596 StdInFileName = NULL;\r
597 StdOutFileName = NULL;\r
598 ErrAppend = FALSE;\r
599 OutAppend = FALSE;\r
600 CommandLineCopy = NULL;\r
5f2915f5 601 FirstLocation = NULL;\r
a405b86d 602\r
8be0ba36 603 if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {\r
604 return (EFI_INVALID_PARAMETER);\r
a405b86d 605 }\r
606\r
8be0ba36 607 SystemTableInfo->ConIn = gST->ConIn;\r
608 SystemTableInfo->ConInHandle = gST->ConsoleInHandle;\r
609 SystemTableInfo->ConOut = gST->ConOut;\r
610 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;\r
4ccd9214
ED
611 SystemTableInfo->ErrOut = gST->StdErr;\r
612 SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle;\r
8be0ba36 613 *OldStdIn = ShellParameters->StdIn;\r
614 *OldStdOut = ShellParameters->StdOut;\r
615 *OldStdErr = ShellParameters->StdErr;\r
616\r
a405b86d 617 if (NewCommandLine == NULL) {\r
618 return (EFI_SUCCESS);\r
619 }\r
620\r
621 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
532691c8 622 if (CommandLineCopy == NULL) {\r
623 return (EFI_OUT_OF_RESOURCES);\r
624 }\r
a405b86d 625 Status = EFI_SUCCESS;\r
626 Split = NULL;\r
5f2915f5 627 FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);\r
a405b86d 628\r
fb84495a 629 StripQuotes(CommandLineCopy);\r
630\r
a405b86d 631 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
632 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
633 if (Split != NULL && Split->SplitStdIn != NULL) {\r
634 ShellParameters->StdIn = Split->SplitStdIn;\r
635 }\r
636 if (Split != NULL && Split->SplitStdOut != NULL) {\r
637 ShellParameters->StdOut = Split->SplitStdOut;\r
638 }\r
639 }\r
640\r
641 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {\r
fb84495a 642 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 643 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 644 StdErrVarName = CommandLineWalker += 6;\r
645 ErrAppend = TRUE;\r
733f138d 646 if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {\r
647 Status = EFI_NOT_FOUND;\r
648 }\r
a405b86d 649 }\r
650 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
fb84495a 651 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 652 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 653 StdOutVarName = CommandLineWalker += 6;\r
654 OutAppend = TRUE;\r
733f138d 655 if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {\r
656 Status = EFI_NOT_FOUND;\r
657 }\r
a405b86d 658 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
fb84495a 659 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 660 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 661 StdOutVarName = CommandLineWalker += 5;\r
662 OutAppend = TRUE;\r
733f138d 663 if (StrStr(CommandLineWalker, L" >>v ") != NULL) {\r
664 Status = EFI_NOT_FOUND;\r
665 }\r
a405b86d 666 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
fb84495a 667 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 668 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 669 StdOutVarName = CommandLineWalker += 4;\r
670 OutAppend = FALSE;\r
733f138d 671 if (StrStr(CommandLineWalker, L" >v ") != NULL) {\r
672 Status = EFI_NOT_FOUND;\r
673 }\r
a405b86d 674 }\r
675 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
fb84495a 676 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 677 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 678 StdOutFileName = CommandLineWalker += 6;\r
679 OutAppend = TRUE;\r
680 OutUnicode = FALSE;\r
733f138d 681 if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {\r
682 Status = EFI_NOT_FOUND;\r
683 }\r
a405b86d 684 }\r
685 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
fb84495a 686 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 687 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 688 if (StdOutFileName != NULL) {\r
689 Status = EFI_INVALID_PARAMETER;\r
690 } else {\r
691 StdOutFileName = CommandLineWalker += 5;\r
692 OutAppend = TRUE;\r
693 }\r
733f138d 694 if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
695 Status = EFI_NOT_FOUND;\r
696 }\r
a405b86d 697 } \r
698 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
fb84495a 699 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 700 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 701 if (StdOutFileName != NULL) {\r
702 Status = EFI_INVALID_PARAMETER;\r
703 } else {\r
704 StdOutFileName = CommandLineWalker += 4;\r
705 OutAppend = TRUE;\r
706 }\r
733f138d 707 if (StrStr(CommandLineWalker, L" >> ") != NULL) {\r
708 Status = EFI_NOT_FOUND;\r
709 }\r
a405b86d 710 }\r
711 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {\r
fb84495a 712 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 713 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 714 if (StdOutFileName != NULL) {\r
715 Status = EFI_INVALID_PARAMETER;\r
716 } else {\r
717 StdOutFileName = CommandLineWalker += 5;\r
718 OutAppend = TRUE;\r
719 OutUnicode = FALSE;\r
720 }\r
733f138d 721 if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
722 Status = EFI_NOT_FOUND;\r
723 }\r
a405b86d 724 } \r
725 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
fb84495a 726 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 727 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 728 if (StdOutFileName != NULL) {\r
729 Status = EFI_INVALID_PARAMETER;\r
730 } else {\r
731 StdOutFileName = CommandLineWalker += 5;\r
732 OutAppend = FALSE;\r
733 OutUnicode = FALSE;\r
734 }\r
733f138d 735 if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
736 Status = EFI_NOT_FOUND;\r
737 }\r
a405b86d 738 } \r
739 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
fb84495a 740 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 741 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 742 if (StdOutFileName != NULL) {\r
743 Status = EFI_INVALID_PARAMETER;\r
744 } else {\r
745 StdOutFileName = CommandLineWalker += 4;\r
746 OutAppend = FALSE;\r
747 OutUnicode = FALSE;\r
748 }\r
733f138d 749 if (StrStr(CommandLineWalker, L" >a ") != NULL) {\r
750 Status = EFI_NOT_FOUND;\r
751 }\r
a405b86d 752 }\r
753 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
fb84495a 754 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 755 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 756 if (StdErrFileName != NULL) {\r
757 Status = EFI_INVALID_PARAMETER;\r
758 } else {\r
759 StdErrFileName = CommandLineWalker += 5;\r
760 ErrAppend = TRUE;\r
761 }\r
733f138d 762 if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {\r
763 Status = EFI_NOT_FOUND;\r
764 }\r
a405b86d 765 }\r
766\r
767 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
fb84495a 768 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 769 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 770 if (StdErrVarName != NULL) {\r
771 Status = EFI_INVALID_PARAMETER;\r
772 } else {\r
773 StdErrVarName = CommandLineWalker += 5;\r
774 ErrAppend = FALSE;\r
775 }\r
733f138d 776 if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {\r
777 Status = EFI_NOT_FOUND;\r
778 }\r
a405b86d 779 }\r
780 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
fb84495a 781 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 782 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 783 if (StdOutVarName != NULL) {\r
784 Status = EFI_INVALID_PARAMETER;\r
785 } else {\r
786 StdOutVarName = CommandLineWalker += 5;\r
787 OutAppend = FALSE;\r
788 }\r
733f138d 789 if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {\r
790 Status = EFI_NOT_FOUND;\r
791 }\r
a405b86d 792 }\r
793 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
fb84495a 794 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 795 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 796 if (StdErrFileName != NULL) {\r
797 Status = EFI_INVALID_PARAMETER;\r
798 } else {\r
799 StdErrFileName = CommandLineWalker += 5;\r
800 ErrAppend = FALSE;\r
801 ErrUnicode = FALSE;\r
802 }\r
733f138d 803 if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {\r
804 Status = EFI_NOT_FOUND;\r
805 }\r
a405b86d 806 }\r
807 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
fb84495a 808 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 809 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 810 if (StdErrFileName != NULL) {\r
811 Status = EFI_INVALID_PARAMETER;\r
812 } else {\r
813 StdErrFileName = CommandLineWalker += 4;\r
814 ErrAppend = FALSE;\r
815 }\r
733f138d 816 if (StrStr(CommandLineWalker, L" 2> ") != NULL) {\r
817 Status = EFI_NOT_FOUND;\r
818 }\r
a405b86d 819 }\r
820\r
821 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
fb84495a 822 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 823 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 824 if (StdOutFileName != NULL) {\r
825 Status = EFI_INVALID_PARAMETER;\r
826 } else {\r
827 StdOutFileName = CommandLineWalker += 4;\r
828 OutAppend = FALSE;\r
829 }\r
733f138d 830 if (StrStr(CommandLineWalker, L" 1> ") != NULL) {\r
831 Status = EFI_NOT_FOUND;\r
832 }\r
a405b86d 833 }\r
834\r
835 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
fb84495a 836 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 837 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 838 if (StdOutFileName != NULL) {\r
839 Status = EFI_INVALID_PARAMETER;\r
840 } else {\r
841 StdOutFileName = CommandLineWalker += 3;\r
842 OutAppend = FALSE;\r
843 }\r
733f138d 844 if (StrStr(CommandLineWalker, L" > ") != NULL) {\r
845 Status = EFI_NOT_FOUND;\r
846 }\r
a405b86d 847 }\r
848\r
849 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
fb84495a 850 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 851 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 852 if (StdInFileName != NULL) {\r
853 Status = EFI_INVALID_PARAMETER;\r
854 } else {\r
855 StdInFileName = CommandLineWalker += 3;\r
733f138d 856 }\r
857 if (StrStr(CommandLineWalker, L" < ") != NULL) {\r
858 Status = EFI_NOT_FOUND;\r
a405b86d 859 }\r
860 }\r
861 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
fb84495a 862 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 863 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 864 if (StdInFileName != NULL) {\r
865 Status = EFI_INVALID_PARAMETER;\r
866 } else {\r
733f138d 867 StdInFileName = CommandLineWalker += 4;\r
868 InUnicode = FALSE;\r
869 }\r
870 if (StrStr(CommandLineWalker, L" <a ") != NULL) {\r
871 Status = EFI_NOT_FOUND;\r
a405b86d 872 }\r
873 }\r
874 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {\r
fb84495a 875 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 876 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 877 if (StdInVarName != NULL) {\r
878 Status = EFI_INVALID_PARAMETER;\r
879 } else {\r
880 StdInVarName = CommandLineWalker += 4;\r
733f138d 881 }\r
882 if (StrStr(CommandLineWalker, L" <v ") != NULL) {\r
883 Status = EFI_NOT_FOUND;\r
a405b86d 884 }\r
885 }\r
886\r
031acf63 887 //\r
888 // re-populate the string to support any filenames that were in quotes.\r
889 //\r
890 StrCpy(CommandLineCopy, NewCommandLine);\r
891\r
5f2915f5 892 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
fb84495a 893 && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))\r
894 ){\r
895 *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;\r
896 }\r
897\r
a405b86d 898 if (!EFI_ERROR(Status)) {\r
031acf63 899\r
900 if (StdErrFileName != NULL) {\r
901 if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {\r
902 Status = EFI_INVALID_PARAMETER;\r
903 }\r
a405b86d 904 }\r
031acf63 905 if (StdOutFileName != NULL) {\r
906 if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {\r
907 Status = EFI_INVALID_PARAMETER;\r
908 }\r
a405b86d 909 }\r
031acf63 910 if (StdInFileName != NULL) {\r
911 if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {\r
912 Status = EFI_INVALID_PARAMETER;\r
913 }\r
a405b86d 914 }\r
031acf63 915 if (StdErrVarName != NULL) {\r
916 if ((StdErrVarName = FixFileName(StdErrVarName)) == NULL) {\r
917 Status = EFI_INVALID_PARAMETER;\r
918 }\r
a405b86d 919 }\r
031acf63 920 if (StdOutVarName != NULL) {\r
921 if ((StdOutVarName = FixFileName(StdOutVarName)) == NULL) {\r
922 Status = EFI_INVALID_PARAMETER;\r
923 }\r
a405b86d 924 }\r
031acf63 925 if (StdInVarName != NULL) {\r
926 if ((StdInVarName = FixFileName(StdInVarName)) == NULL) {\r
927 Status = EFI_INVALID_PARAMETER;\r
928 }\r
a405b86d 929 }\r
930\r
0c956e0d 931 //\r
932 // Verify not the same and not duplicating something from a split\r
933 //\r
733f138d 934 if (\r
935 //\r
936 // Check that no 2 filenames are the same\r
937 //\r
fb84495a 938 (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
a405b86d 939 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
940 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
733f138d 941 //\r
942 // Check that no 2 variable names are the same\r
943 //\r
a405b86d 944 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)\r
945 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)\r
946 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)\r
733f138d 947 //\r
948 // When a split (using | operator) is in place some are not allowed\r
949 //\r
a405b86d 950 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))\r
951 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
733f138d 952 //\r
953 // Check that nothing is trying to be output to 2 locations.\r
954 //\r
a405b86d 955 ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
956 ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
957 ||(StdInFileName != NULL && StdInVarName != NULL)\r
733f138d 958 //\r
733f138d 959 // Check for no volatile environment variables\r
960 //\r
a405b86d 961 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))\r
962 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))\r
733f138d 963 //\r
964 // Cant redirect during a reconnect operation.\r
965 //\r
3c865f20 966 ||(StrStr(NewCommandLine, L"connect -r") != NULL \r
967 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
733f138d 968 //\r
969 // Check that filetypes (Unicode/Ascii) do not change during an append\r
970 //\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
973 ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
974 ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
a405b86d 975 ){\r
976 Status = EFI_INVALID_PARAMETER;\r
a9ca0684 977 ShellParameters->StdIn = *OldStdIn;\r
978 ShellParameters->StdOut = *OldStdOut;\r
979 ShellParameters->StdErr = *OldStdErr;\r
fb84495a 980 } else if (!EFI_ERROR(Status)){\r
a405b86d 981 //\r
982 // Open the Std<Whatever> and we should not have conflicts here...\r
983 //\r
984\r
985 //\r
986 // StdErr to a file\r
987 //\r
988 if (StdErrFileName != NULL) {\r
989 if (!ErrAppend) {\r
990 //\r
991 // delete existing file.\r
992 //\r
993 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);\r
994 }\r
995 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
a405b86d 996 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
997 //\r
733f138d 998 // Write out the gUnicodeFileTag\r
a405b86d 999 //\r
1000 Size = sizeof(CHAR16);\r
733f138d 1001 TagBuffer[0] = gUnicodeFileTag;\r
a405b86d 1002 TagBuffer[1] = CHAR_NULL;\r
1003 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
1004 }\r
1005 if (!ErrUnicode && !EFI_ERROR(Status)) {\r
1006 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1007 ASSERT(TempHandle != NULL);\r
1008 }\r
1009 if (!EFI_ERROR(Status)) {\r
1010 ShellParameters->StdErr = TempHandle;\r
8be0ba36 1011 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);\r
a405b86d 1012 }\r
1013 }\r
1014\r
1015 //\r
1016 // StdOut to a file\r
1017 //\r
1018 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {\r
1019 if (!OutAppend) {\r
1020 //\r
1021 // delete existing file.\r
1022 //\r
1023 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);\r
1024 }\r
1025 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
3c865f20 1026 if (TempHandle == NULL) {\r
1027 Status = EFI_INVALID_PARAMETER;\r
1028 } else {\r
733f138d 1029 if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {\r
1030 //no-op\r
1031 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
3c865f20 1032 //\r
733f138d 1033 // Write out the gUnicodeFileTag\r
3c865f20 1034 //\r
1035 Size = sizeof(CHAR16);\r
733f138d 1036 TagBuffer[0] = gUnicodeFileTag;\r
3c865f20 1037 TagBuffer[1] = CHAR_NULL;\r
1038 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
1039 } else if (OutAppend) {\r
1040 //\r
1041 // Move to end of file\r
1042 //\r
1043 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);\r
1044 if (!EFI_ERROR(Status)) {\r
1045 Status = ShellInfoObject.NewEfiShellProtocol->SetFilePosition(TempHandle, FileSize);\r
1046 }\r
1047 }\r
1048 if (!OutUnicode && !EFI_ERROR(Status)) {\r
1049 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1050 ASSERT(TempHandle != NULL);\r
1051 }\r
a405b86d 1052 if (!EFI_ERROR(Status)) {\r
3c865f20 1053 ShellParameters->StdOut = TempHandle;\r
8be0ba36 1054 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);\r
a405b86d 1055 }\r
1056 }\r
a405b86d 1057 }\r
1058\r
1059 //\r
1060 // StdOut to a var\r
1061 //\r
1062 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {\r
1063 if (!OutAppend) {\r
1064 //\r
1065 // delete existing variable.\r
1066 //\r
1067 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");\r
1068 }\r
1069 TempHandle = CreateFileInterfaceEnv(StdOutVarName);\r
1070 ASSERT(TempHandle != NULL);\r
a405b86d 1071 ShellParameters->StdOut = TempHandle;\r
8be0ba36 1072 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);\r
a405b86d 1073 }\r
1074\r
1075 //\r
1076 // StdErr to a var\r
1077 //\r
1078 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {\r
1079 if (!ErrAppend) {\r
1080 //\r
1081 // delete existing variable.\r
1082 //\r
1083 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");\r
1084 }\r
1085 TempHandle = CreateFileInterfaceEnv(StdErrVarName);\r
1086 ASSERT(TempHandle != NULL);\r
a405b86d 1087 ShellParameters->StdErr = TempHandle;\r
8be0ba36 1088 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);\r
a405b86d 1089 }\r
1090\r
1091 //\r
1092 // StdIn from a var\r
1093 //\r
1094 if (!EFI_ERROR(Status) && StdInVarName != NULL) {\r
1095 TempHandle = CreateFileInterfaceEnv(StdInVarName);\r
532691c8 1096 if (TempHandle == NULL) {\r
1097 Status = EFI_OUT_OF_RESOURCES;\r
a405b86d 1098 } else {\r
532691c8 1099 if (!InUnicode) {\r
1100 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1101 }\r
1102 Size = 0;\r
96962f0a 1103 if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
532691c8 1104 Status = EFI_INVALID_PARAMETER;\r
1105 } else {\r
1106 ShellParameters->StdIn = TempHandle;\r
1107 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1108 }\r
a405b86d 1109 }\r
1110 }\r
1111\r
1112 //\r
1113 // StdIn from a file\r
1114 //\r
1115 if (!EFI_ERROR(Status) && StdInFileName != NULL) {\r
1116 Status = ShellOpenFileByName(\r
1117 StdInFileName,\r
1118 &TempHandle,\r
1119 EFI_FILE_MODE_READ,\r
1120 0);\r
1121 if (!InUnicode && !EFI_ERROR(Status)) {\r
1122 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1123 }\r
1124 if (!EFI_ERROR(Status)) {\r
1125 ShellParameters->StdIn = TempHandle;\r
8be0ba36 1126 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
a405b86d 1127 }\r
1128 }\r
1129 }\r
1130 }\r
1131 FreePool(CommandLineCopy);\r
8be0ba36 1132\r
cf6a8f14 1133 CalculateEfiHdrCrc(&gST->Hdr);\r
1134\r
8be0ba36 1135 if (gST->ConIn == NULL ||gST->ConOut == NULL) {\r
1136 return (EFI_OUT_OF_RESOURCES);\r
1137 }\r
a405b86d 1138 return (Status);\r
1139}\r
1140\r
1141/**\r
1142 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
1143 structure with StdIn and StdOut. The current values are de-allocated.\r
1144\r
4ff7e37b
ED
1145 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1146 @param[in] OldStdIn Pointer to old StdIn.\r
1147 @param[in] OldStdOut Pointer to old StdOut.\r
1148 @param[in] OldStdErr Pointer to old StdErr.\r
1149 @param[in] SystemTableInfo Pointer to old system table information.\r
a405b86d 1150**/\r
1151EFI_STATUS\r
1152EFIAPI\r
1153RestoreStdInStdOutStdErr (\r
1154 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
8be0ba36 1155 IN SHELL_FILE_HANDLE *OldStdIn,\r
1156 IN SHELL_FILE_HANDLE *OldStdOut,\r
1157 IN SHELL_FILE_HANDLE *OldStdErr,\r
1158 IN SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 1159 )\r
1160{\r
1161 SPLIT_LIST *Split;\r
8be0ba36 1162\r
1163 if (ShellParameters == NULL \r
1164 ||OldStdIn == NULL\r
1165 ||OldStdOut == NULL\r
1166 ||OldStdErr == NULL\r
1167 ||SystemTableInfo == NULL) {\r
1168 return (EFI_INVALID_PARAMETER);\r
1169 }\r
a405b86d 1170 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
1171 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
1172 } else {\r
1173 Split = NULL;\r
1174 }\r
8be0ba36 1175 if (ShellParameters->StdIn != *OldStdIn) {\r
a405b86d 1176 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
1177 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
1178 }\r
8be0ba36 1179 ShellParameters->StdIn = *OldStdIn;\r
a405b86d 1180 }\r
8be0ba36 1181 if (ShellParameters->StdOut != *OldStdOut) {\r
a405b86d 1182 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
1183 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
1184 }\r
8be0ba36 1185 ShellParameters->StdOut = *OldStdOut;\r
1186 }\r
1187 if (ShellParameters->StdErr != *OldStdErr) {\r
1188 gEfiShellProtocol->CloseFile(ShellParameters->StdErr);\r
1189 ShellParameters->StdErr = *OldStdErr;\r
1190 }\r
1191\r
1192 if (gST->ConIn != SystemTableInfo->ConIn) {\r
1193 CloseSimpleTextInOnFile(gST->ConIn);\r
1194 gST->ConIn = SystemTableInfo->ConIn;\r
1195 gST->ConsoleInHandle = SystemTableInfo->ConInHandle;\r
a405b86d 1196 }\r
8be0ba36 1197 if (gST->ConOut != SystemTableInfo->ConOut) {\r
1198 CloseSimpleTextOutOnFile(gST->ConOut);\r
1199 gST->ConOut = SystemTableInfo->ConOut;\r
1200 gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;\r
1201 }\r
4ccd9214 1202 if (gST->StdErr != SystemTableInfo->ErrOut) {\r
8be0ba36 1203 CloseSimpleTextOutOnFile(gST->StdErr);\r
4ccd9214
ED
1204 gST->StdErr = SystemTableInfo->ErrOut;\r
1205 gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle;\r
8be0ba36 1206 }\r
1207\r
cf6a8f14 1208 CalculateEfiHdrCrc(&gST->Hdr);\r
1209\r
a405b86d 1210 return (EFI_SUCCESS);\r
1211}\r
1212/**\r
1213 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1214 structure by parsing NewCommandLine. The current values are returned to the\r
1215 user.\r
1216\r
1217 If OldArgv or OldArgc is NULL then that value is not returned.\r
1218\r
4ff7e37b
ED
1219 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1220 @param[in] NewCommandLine The new command line to parse and use.\r
1221 @param[out] OldArgv Pointer to old list of parameters.\r
1222 @param[out] OldArgc Pointer to old number of items in Argv list.\r
a405b86d 1223\r
1224 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
1225 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1226**/\r
1227EFI_STATUS\r
1228EFIAPI\r
1229UpdateArgcArgv(\r
1230 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1231 IN CONST CHAR16 *NewCommandLine,\r
1232 OUT CHAR16 ***OldArgv OPTIONAL,\r
1233 OUT UINTN *OldArgc OPTIONAL\r
1234 )\r
1235{\r
1236 ASSERT(ShellParameters != NULL);\r
1237\r
1238 if (OldArgc != NULL) {\r
1239 *OldArgc = ShellParameters->Argc;\r
1240 }\r
1241 if (OldArgc != NULL) {\r
1242 *OldArgv = ShellParameters->Argv;\r
1243 }\r
1244\r
1245 return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));\r
1246}\r
1247\r
1248/**\r
1249 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1250 structure with Argv and Argc. The current values are de-allocated and the\r
1251 OldArgv must not be deallocated by the caller.\r
1252\r
4ff7e37b
ED
1253 @param[in, out] ShellParameters pointer to parameter structure to modify\r
1254 @param[in] OldArgv pointer to old list of parameters\r
1255 @param[in] OldArgc pointer to old number of items in Argv list\r
a405b86d 1256**/\r
1257VOID\r
1258EFIAPI\r
1259RestoreArgcArgv(\r
1260 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1261 IN CHAR16 ***OldArgv,\r
1262 IN UINTN *OldArgc\r
1263 )\r
1264{\r
1265 UINTN LoopCounter;\r
1266 ASSERT(ShellParameters != NULL);\r
1267 ASSERT(OldArgv != NULL);\r
1268 ASSERT(OldArgc != NULL);\r
1269\r
1270 if (ShellParameters->Argv != NULL) {\r
1271 for ( LoopCounter = 0\r
1272 ; LoopCounter < ShellParameters->Argc\r
1273 ; LoopCounter++\r
1274 ){\r
1275 FreePool(ShellParameters->Argv[LoopCounter]);\r
1276 }\r
1277 FreePool(ShellParameters->Argv);\r
1278 }\r
1279 ShellParameters->Argv = *OldArgv;\r
1280 *OldArgv = NULL;\r
1281 ShellParameters->Argc = *OldArgc;\r
1282 *OldArgc = 0;\r
1283}\r