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