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