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