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