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