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