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