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