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