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