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