1 /** @file 2 EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables, 3 StdIn, StdOut, StdErr, etc...). 4 5 Copyright 2016 Dell Inc. 6 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR> 7 (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<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 #include "FileHandleInternal.h" 20 21 #define MEM_WRITE_REALLOC_OVERHEAD 1024 22 23 /** 24 File style interface for console (Open). 25 26 @param[in] This Ignored. 27 @param[out] NewHandle Ignored. 28 @param[in] FileName Ignored. 29 @param[in] OpenMode Ignored. 30 @param[in] Attributes Ignored. 31 32 @retval EFI_NOT_FOUND 33 **/ 34 EFI_STATUS 35 EFIAPI 36 FileInterfaceOpenNotFound( 37 IN EFI_FILE_PROTOCOL *This, 38 OUT EFI_FILE_PROTOCOL **NewHandle, 39 IN CHAR16 *FileName, 40 IN UINT64 OpenMode, 41 IN UINT64 Attributes 42 ) 43 { 44 return (EFI_NOT_FOUND); 45 } 46 47 /** 48 File style interface for console (Close, Delete, & Flush) 49 50 @param[in] This Ignored. 51 52 @retval EFI_SUCCESS 53 **/ 54 EFI_STATUS 55 EFIAPI 56 FileInterfaceNopGeneric( 57 IN EFI_FILE_PROTOCOL *This 58 ) 59 { 60 return (EFI_SUCCESS); 61 } 62 63 /** 64 File style interface for console (GetPosition). 65 66 @param[in] This Ignored. 67 @param[out] Position Ignored. 68 69 @retval EFI_UNSUPPORTED 70 **/ 71 EFI_STATUS 72 EFIAPI 73 FileInterfaceNopGetPosition( 74 IN EFI_FILE_PROTOCOL *This, 75 OUT UINT64 *Position 76 ) 77 { 78 return (EFI_UNSUPPORTED); 79 } 80 81 /** 82 File style interface for console (SetPosition). 83 84 @param[in] This Ignored. 85 @param[in] Position Ignored. 86 87 @retval EFI_UNSUPPORTED 88 **/ 89 EFI_STATUS 90 EFIAPI 91 FileInterfaceNopSetPosition( 92 IN EFI_FILE_PROTOCOL *This, 93 IN UINT64 Position 94 ) 95 { 96 return (EFI_UNSUPPORTED); 97 } 98 99 /** 100 File style interface for console (GetInfo). 101 102 @param[in] This Ignored. 103 @param[in] InformationType Ignored. 104 @param[in, out] BufferSize Ignored. 105 @param[out] Buffer Ignored. 106 107 @retval EFI_UNSUPPORTED 108 **/ 109 EFI_STATUS 110 EFIAPI 111 FileInterfaceNopGetInfo( 112 IN EFI_FILE_PROTOCOL *This, 113 IN EFI_GUID *InformationType, 114 IN OUT UINTN *BufferSize, 115 OUT VOID *Buffer 116 ) 117 { 118 return (EFI_UNSUPPORTED); 119 } 120 121 /** 122 File style interface for console (SetInfo). 123 124 @param[in] This Ignored. 125 @param[in] InformationType Ignored. 126 @param[in] BufferSize Ignored. 127 @param[in] Buffer Ignored. 128 129 @retval EFI_UNSUPPORTED 130 **/ 131 EFI_STATUS 132 EFIAPI 133 FileInterfaceNopSetInfo( 134 IN EFI_FILE_PROTOCOL *This, 135 IN EFI_GUID *InformationType, 136 IN UINTN BufferSize, 137 IN VOID *Buffer 138 ) 139 { 140 return (EFI_UNSUPPORTED); 141 } 142 143 /** 144 File style interface for StdOut (Write). 145 146 Writes data to the screen. 147 148 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 149 @param[in, out] BufferSize Size in bytes of Buffer. 150 @param[in] Buffer The pointer to the buffer to write. 151 152 @retval EFI_UNSUPPORTED No output console is supported. 153 @return A return value from gST->ConOut->OutputString. 154 **/ 155 EFI_STATUS 156 EFIAPI 157 FileInterfaceStdOutWrite( 158 IN EFI_FILE_PROTOCOL *This, 159 IN OUT UINTN *BufferSize, 160 IN VOID *Buffer 161 ) 162 { 163 if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) { 164 return (EFI_UNSUPPORTED); 165 } 166 if (*((CHAR16 *)Buffer) == gUnicodeFileTag) { 167 return (gST->ConOut->OutputString(gST->ConOut, (CHAR16 *)Buffer + 1)); 168 } 169 return (gST->ConOut->OutputString(gST->ConOut, Buffer)); 170 } 171 172 /** 173 File style interface for StdIn (Write). 174 175 @param[in] This Ignored. 176 @param[in, out] BufferSize Ignored. 177 @param[in] Buffer Ignored. 178 179 @retval EFI_UNSUPPORTED 180 **/ 181 EFI_STATUS 182 EFIAPI 183 FileInterfaceStdInWrite( 184 IN EFI_FILE_PROTOCOL *This, 185 IN OUT UINTN *BufferSize, 186 IN VOID *Buffer 187 ) 188 { 189 return (EFI_UNSUPPORTED); 190 } 191 192 /** 193 File style interface for console StdErr (Write). 194 195 Writes error to the error output. 196 197 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 198 @param[in, out] BufferSize Size in bytes of Buffer. 199 @param[in] Buffer The pointer to the buffer to write. 200 201 @return A return value from gST->StdErr->OutputString. 202 **/ 203 EFI_STATUS 204 EFIAPI 205 FileInterfaceStdErrWrite( 206 IN EFI_FILE_PROTOCOL *This, 207 IN OUT UINTN *BufferSize, 208 IN VOID *Buffer 209 ) 210 { 211 return (gST->StdErr->OutputString(gST->StdErr, Buffer)); 212 } 213 214 /** 215 File style interface for console StdOut (Read). 216 217 @param[in] This Ignored. 218 @param[in, out] BufferSize Ignored. 219 @param[out] Buffer Ignored. 220 221 @retval EFI_UNSUPPORTED 222 **/ 223 EFI_STATUS 224 EFIAPI 225 FileInterfaceStdOutRead( 226 IN EFI_FILE_PROTOCOL *This, 227 IN OUT UINTN *BufferSize, 228 OUT VOID *Buffer 229 ) 230 { 231 return (EFI_UNSUPPORTED); 232 } 233 234 /** 235 File style interface for console StdErr (Read). 236 237 @param[in] This Ignored. 238 @param[in, out] BufferSize Ignored. 239 @param[out] Buffer Ignored. 240 241 @retval EFI_UNSUPPORTED Always. 242 **/ 243 EFI_STATUS 244 EFIAPI 245 FileInterfaceStdErrRead( 246 IN EFI_FILE_PROTOCOL *This, 247 IN OUT UINTN *BufferSize, 248 OUT VOID *Buffer 249 ) 250 { 251 return (EFI_UNSUPPORTED); 252 } 253 254 /** 255 File style interface for NUL file (Read). 256 257 @param[in] This Ignored. 258 @param[in, out] BufferSize Poiner to 0 upon return. 259 @param[out] Buffer Ignored. 260 261 @retval EFI_SUCCESS Always. 262 **/ 263 EFI_STATUS 264 EFIAPI 265 FileInterfaceNulRead( 266 IN EFI_FILE_PROTOCOL *This, 267 IN OUT UINTN *BufferSize, 268 OUT VOID *Buffer 269 ) 270 { 271 *BufferSize = 0; 272 return (EFI_SUCCESS); 273 } 274 275 /** 276 File style interface for NUL file (Write). 277 278 @param[in] This Ignored. 279 @param[in, out] BufferSize Ignored. 280 @param[in] Buffer Ignored. 281 282 @retval EFI_SUCCESS 283 **/ 284 EFI_STATUS 285 EFIAPI 286 FileInterfaceNulWrite( 287 IN EFI_FILE_PROTOCOL *This, 288 IN OUT UINTN *BufferSize, 289 IN VOID *Buffer 290 ) 291 { 292 return (EFI_SUCCESS); 293 } 294 295 /** 296 Create the TAB completion list. 297 298 @param[in] InputString The command line to expand. 299 @param[in] StringLen Length of the command line. 300 @param[in] BufferSize Buffer size. 301 @param[in, out] TabCompletionList Return the TAB completion list. 302 @param[in, out] TabUpdatePos Return the TAB update position. 303 **/ 304 EFI_STATUS 305 CreateTabCompletionList ( 306 IN CONST CHAR16 *InputString, 307 IN CONST UINTN StringLen, 308 IN CONST UINTN BufferSize, 309 IN OUT EFI_SHELL_FILE_INFO **TabCompletionList, 310 IN OUT UINTN *TabUpdatePos 311 ) 312 { 313 BOOLEAN InQuotation; 314 UINTN TabPos; 315 UINTN Index; 316 CONST CHAR16 *Cwd; 317 EFI_STATUS Status; 318 CHAR16 *TabStr; 319 EFI_SHELL_FILE_INFO *FileList; 320 EFI_SHELL_FILE_INFO *FileInfo; 321 EFI_SHELL_FILE_INFO *TempFileInfo; 322 323 // 324 // Allocate buffers 325 // 326 TabStr = AllocateZeroPool (BufferSize); 327 if (TabStr == NULL) { 328 return EFI_OUT_OF_RESOURCES; 329 } 330 331 // 332 // handle auto complete of file and directory names... 333 // E.g.: cd fs0:\EFI\Bo<TAB> 334 // ^ ^ 335 // TabPos TabUpdatePos 336 // 337 TabPos = 0; 338 *TabUpdatePos = 0; 339 FileList = NULL; 340 InQuotation = FALSE; 341 for (Index = 0; Index < StringLen; Index++) { 342 switch (InputString[Index]) { 343 case L'\"': 344 InQuotation = (BOOLEAN) (!InQuotation); 345 break; 346 347 case L' ': 348 if (!InQuotation) { 349 TabPos = Index + 1; 350 *TabUpdatePos = TabPos; 351 } 352 break; 353 354 case L':': 355 // 356 // handle the case "fs0:<TAB>" 357 // Update the TabUpdatePos as well. 358 // 359 case L'\\': 360 *TabUpdatePos = Index + 1; 361 break; 362 363 default: 364 break; 365 } 366 } 367 368 if (StrStr (InputString + TabPos, L":") == NULL) { 369 // 370 // If file path doesn't contain ":", ... 371 // 372 Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir (NULL); 373 if (Cwd != NULL) { 374 if (InputString[TabPos] != L'\\') { 375 // 376 // and it doesn't begin with "\\", it's a path relative to current directory. 377 // TabStr = "<cwd>\\" 378 // 379 StrnCpyS (TabStr, BufferSize / sizeof (CHAR16), Cwd, (BufferSize) / sizeof (CHAR16) - 1); 380 StrCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"\\"); 381 } else { 382 // 383 // and it begins with "\\", it's a path pointing to root directory of current map. 384 // TabStr = "fsx:" 385 // 386 Index = StrStr (Cwd, L":") - Cwd + 1; 387 StrnCpyS (TabStr, BufferSize / sizeof (CHAR16), Cwd, Index); 388 } 389 } 390 } 391 StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), InputString + TabPos, StringLen - TabPos); 392 StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"*", (BufferSize) / sizeof (CHAR16) - 1 - StrLen (TabStr)); 393 Status = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FileList); 394 395 // 396 // Filter out the non-directory for "CD" command 397 // Filter "." and ".." for all 398 // 399 if (!EFI_ERROR (Status) && FileList != NULL) { 400 // 401 // Skip the spaces in the beginning 402 // 403 while (*InputString == L' ') { 404 InputString++; 405 } 406 407 for (FileInfo = (EFI_SHELL_FILE_INFO *) GetFirstNode (&FileList->Link); !IsNull (&FileList->Link, &FileInfo->Link); ) { 408 if (((StrCmp (FileInfo->FileName, L".") == 0) || (StrCmp (FileInfo->FileName, L"..") == 0)) || 409 (((InputString[0] == L'c' || InputString[0] == L'C') && (InputString[1] == L'd' || InputString[1] == L'D')) && 410 (ShellIsDirectory (FileInfo->FullName) != EFI_SUCCESS))) { 411 TempFileInfo = FileInfo; 412 FileInfo = (EFI_SHELL_FILE_INFO *) RemoveEntryList (&FileInfo->Link); 413 InternalFreeShellFileInfoNode (TempFileInfo); 414 } else { 415 FileInfo = (EFI_SHELL_FILE_INFO *) GetNextNode (&FileList->Link, &FileInfo->Link); 416 } 417 } 418 } 419 420 if (FileList != NULL && !IsListEmpty (&FileList->Link)) { 421 Status = EFI_SUCCESS; 422 } else { 423 ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FileList); 424 Status = EFI_NOT_FOUND; 425 } 426 427 FreePool (TabStr); 428 429 *TabCompletionList = FileList; 430 return Status; 431 } 432 433 /** 434 File style interface for console (Read). 435 436 This will return a single line of input from the console. 437 438 @param This A pointer to the EFI_FILE_PROTOCOL instance that is the 439 file handle to read data from. Not used. 440 @param BufferSize On input, the size of the Buffer. On output, the amount 441 of data returned in Buffer. In both cases, the size is 442 measured in bytes. 443 @param Buffer The buffer into which the data is read. 444 445 446 @retval EFI_SUCCESS The data was read. 447 @retval EFI_NO_MEDIA The device has no medium. 448 @retval EFI_DEVICE_ERROR The device reported an error. 449 @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file. 450 @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file. 451 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. 452 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory 453 entry. BufferSize has been updated with the size 454 needed to complete the request. 455 @retval EFI_OUT_OF_RESOURCES A memory allocation failed. 456 **/ 457 EFI_STATUS 458 EFIAPI 459 FileInterfaceStdInRead( 460 IN EFI_FILE_PROTOCOL *This, 461 IN OUT UINTN *BufferSize, 462 OUT VOID *Buffer 463 ) 464 { 465 CHAR16 *CurrentString; 466 BOOLEAN Done; 467 UINTN TabUpdatePos; // Start index of the string updated by TAB stroke 468 UINTN Column; // Column of current cursor 469 UINTN Row; // Row of current cursor 470 UINTN StartColumn; // Column at the beginning of the line 471 UINTN Update; // Line index for update 472 UINTN Delete; // Num of chars to delete from console after update 473 UINTN StringLen; // Total length of the line 474 UINTN StringCurPos; // Line index corresponding to the cursor 475 UINTN MaxStr; // Maximum possible line length 476 UINTN TotalColumn; // Num of columns in the console 477 UINTN TotalRow; // Num of rows in the console 478 UINTN SkipLength; 479 UINTN OutputLength; // Length of the update string 480 UINTN TailRow; // Row of end of line 481 UINTN TailColumn; // Column of end of line 482 EFI_INPUT_KEY Key; 483 484 BUFFER_LIST *LinePos; 485 BUFFER_LIST *NewPos; 486 BOOLEAN InScrolling; 487 EFI_STATUS Status; 488 BOOLEAN InTabScrolling; // Whether in TAB-completion state 489 EFI_SHELL_FILE_INFO *TabCompleteList; 490 EFI_SHELL_FILE_INFO *TabCurrent; 491 UINTN EventIndex; 492 CHAR16 *TabOutputStr; 493 494 // 495 // If buffer is not large enough to hold a CHAR16, return minimum buffer size 496 // 497 if (*BufferSize < sizeof (CHAR16) * 2) { 498 *BufferSize = sizeof (CHAR16) * 2; 499 return (EFI_BUFFER_TOO_SMALL); 500 } 501 502 Done = FALSE; 503 CurrentString = Buffer; 504 StringLen = 0; 505 StringCurPos = 0; 506 OutputLength = 0; 507 Update = 0; 508 Delete = 0; 509 LinePos = NewPos = (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory); 510 InScrolling = FALSE; 511 InTabScrolling = FALSE; 512 Status = EFI_SUCCESS; 513 TabOutputStr = NULL; 514 TabUpdatePos = 0; 515 TabCompleteList = NULL; 516 TabCurrent = NULL; 517 518 // 519 // Get the screen setting and the current cursor location 520 // 521 Column = StartColumn = gST->ConOut->Mode->CursorColumn; 522 Row = gST->ConOut->Mode->CursorRow; 523 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &TotalColumn, &TotalRow); 524 525 // 526 // Limit the line length to the buffer size or the minimun size of the 527 // screen. (The smaller takes effect) 528 // 529 MaxStr = TotalColumn * (TotalRow - 1) - StartColumn; 530 if (MaxStr > *BufferSize / sizeof (CHAR16)) { 531 MaxStr = *BufferSize / sizeof (CHAR16); 532 } 533 ZeroMem (CurrentString, MaxStr * sizeof (CHAR16)); 534 do { 535 // 536 // Read a key 537 // 538 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex); 539 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); 540 if (EFI_ERROR (Status)) { 541 542 if (Status == EFI_NOT_READY) 543 continue; 544 545 ZeroMem (CurrentString, MaxStr * sizeof(CHAR16)); 546 StringLen = 0; 547 break; 548 } 549 550 // 551 // Press PageUp or PageDown to scroll the history screen up or down. 552 // Press any other key to quit scrolling. 553 // 554 if (Key.UnicodeChar == 0 && (Key.ScanCode == SCAN_PAGE_UP || Key.ScanCode == SCAN_PAGE_DOWN)) { 555 if (Key.ScanCode == SCAN_PAGE_UP) { 556 ConsoleLoggerDisplayHistory(FALSE, 0, ShellInfoObject.ConsoleInfo); 557 } else if (Key.ScanCode == SCAN_PAGE_DOWN) { 558 ConsoleLoggerDisplayHistory(TRUE, 0, ShellInfoObject.ConsoleInfo); 559 } 560 561 InScrolling = TRUE; 562 } else { 563 if (InScrolling) { 564 ConsoleLoggerStopHistory(ShellInfoObject.ConsoleInfo); 565 InScrolling = FALSE; 566 } 567 } 568 569 // 570 // If we are quitting TAB scrolling... 571 // 572 if (InTabScrolling && Key.UnicodeChar != CHAR_TAB) { 573 if (TabCompleteList != NULL) { 574 ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList); 575 DEBUG_CODE(TabCompleteList = NULL;); 576 } 577 InTabScrolling = FALSE; 578 } 579 580 switch (Key.UnicodeChar) { 581 case CHAR_CARRIAGE_RETURN: 582 // 583 // All done, print a newline at the end of the string 584 // 585 TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn; 586 TailColumn = (StringLen - StringCurPos + Column) % TotalColumn; 587 ShellPrintEx ((INT32)TailColumn, (INT32)TailRow, L"%N\n"); 588 Done = TRUE; 589 break; 590 591 case CHAR_BACKSPACE: 592 if (StringCurPos != 0) { 593 // 594 // If not move back beyond string beginning, move all characters behind 595 // the current position one character forward 596 // 597 StringCurPos--; 598 Update = StringCurPos; 599 Delete = 1; 600 CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos)); 601 602 // 603 // Adjust the current column and row 604 // 605 MoveCursorBackward (TotalColumn, &Column, &Row); 606 } 607 break; 608 609 case CHAR_TAB: 610 if (!InTabScrolling) { 611 TabCurrent = NULL; 612 // 613 // Initialize a tab complete operation. 614 // 615 Status = CreateTabCompletionList (CurrentString, StringLen, *BufferSize, &TabCompleteList, &TabUpdatePos); 616 if (!EFI_ERROR(Status)) { 617 InTabScrolling = TRUE; 618 } 619 620 // 621 // We do not set up the replacement. 622 // The next section will do that. 623 // 624 } 625 626 if (InTabScrolling) { 627 // 628 // We are in a tab complete operation. 629 // set up the next replacement. 630 // 631 ASSERT(TabCompleteList != NULL); 632 if (TabCurrent == NULL) { 633 TabCurrent = (EFI_SHELL_FILE_INFO*) GetFirstNode (&TabCompleteList->Link); 634 } else { 635 TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode (&TabCompleteList->Link, &TabCurrent->Link); 636 } 637 638 // 639 // Skip over the empty list beginning node 640 // 641 if (IsNull(&TabCompleteList->Link, &TabCurrent->Link)) { 642 TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode (&TabCompleteList->Link, &TabCurrent->Link); 643 } 644 } 645 break; 646 647 default: 648 if (Key.UnicodeChar >= ' ') { 649 // 650 // If we are at the buffer's end, drop the key 651 // 652 if (StringLen == MaxStr - 1 && (ShellInfoObject.ViewingSettings.InsertMode || StringCurPos == StringLen)) { 653 break; 654 } 655 // 656 // If in insert mode, make space by moving each other character 1 657 // space higher in the array 658 // 659 if (ShellInfoObject.ViewingSettings.InsertMode) { 660 CopyMem(CurrentString + StringCurPos + 1, CurrentString + StringCurPos, (StringLen - StringCurPos)*sizeof(CurrentString[0])); 661 } 662 663 CurrentString[StringCurPos] = Key.UnicodeChar; 664 Update = StringCurPos; 665 666 StringCurPos += 1; 667 OutputLength = 1; 668 } 669 break; 670 671 case 0: 672 switch (Key.ScanCode) { 673 case SCAN_DELETE: 674 // 675 // Move characters behind current position one character forward 676 // 677 if (StringLen != 0) { 678 Update = StringCurPos; 679 Delete = 1; 680 CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos)); 681 } 682 break; 683 684 case SCAN_UP: 685 // 686 // Prepare to print the previous command 687 // 688 NewPos = (BUFFER_LIST*)GetPreviousNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link); 689 if (IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link)) { 690 NewPos = (BUFFER_LIST*)GetPreviousNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link); 691 } 692 break; 693 694 case SCAN_DOWN: 695 // 696 // Prepare to print the next command 697 // 698 NewPos = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link); 699 if (NewPos == (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory)) { 700 NewPos = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link); 701 } 702 break; 703 704 case SCAN_LEFT: 705 // 706 // Adjust current cursor position 707 // 708 if (StringCurPos != 0) { 709 --StringCurPos; 710 MoveCursorBackward (TotalColumn, &Column, &Row); 711 } 712 break; 713 714 case SCAN_RIGHT: 715 // 716 // Adjust current cursor position 717 // 718 if (StringCurPos < StringLen) { 719 ++StringCurPos; 720 MoveCursorForward (TotalColumn, TotalRow, &Column, &Row); 721 } 722 break; 723 724 case SCAN_HOME: 725 // 726 // Move current cursor position to the beginning of the command line 727 // 728 Row -= (StringCurPos + StartColumn) / TotalColumn; 729 Column = StartColumn; 730 StringCurPos = 0; 731 break; 732 733 case SCAN_END: 734 // 735 // Move current cursor position to the end of the command line 736 // 737 TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn; 738 TailColumn = (StringLen - StringCurPos + Column) % TotalColumn; 739 Row = TailRow; 740 Column = TailColumn; 741 StringCurPos = StringLen; 742 break; 743 744 case SCAN_ESC: 745 // 746 // Prepare to clear the current command line 747 // 748 CurrentString[0] = 0; 749 Update = 0; 750 Delete = StringLen; 751 Row -= (StringCurPos + StartColumn) / TotalColumn; 752 Column = StartColumn; 753 OutputLength = 0; 754 break; 755 756 case SCAN_INSERT: 757 // 758 // Toggle the SEnvInsertMode flag 759 // 760 ShellInfoObject.ViewingSettings.InsertMode = (BOOLEAN)!ShellInfoObject.ViewingSettings.InsertMode; 761 break; 762 763 case SCAN_F7: 764 // 765 // Print command history 766 // 767 PrintCommandHistory (TotalColumn, TotalRow, 4); 768 *CurrentString = CHAR_NULL; 769 Done = TRUE; 770 break; 771 } 772 } 773 774 if (Done) { 775 break; 776 } 777 778 // 779 // If we are in auto-complete mode, we are preparing to print 780 // the next file or directory name 781 // 782 if (InTabScrolling) { 783 TabOutputStr = AllocateZeroPool (*BufferSize); 784 if (TabOutputStr == NULL) { 785 Status = EFI_OUT_OF_RESOURCES; 786 } 787 } 788 789 if (InTabScrolling && TabOutputStr != NULL) { 790 791 // 792 // Adjust the column and row to the start of TAB-completion string. 793 // 794 Column = (StartColumn + TabUpdatePos) % TotalColumn; 795 Row -= (StartColumn + StringCurPos) / TotalColumn - (StartColumn + TabUpdatePos) / TotalColumn; 796 OutputLength = StrLen (TabCurrent->FileName); 797 // 798 // if the output string contains blank space, quotation marks L'\"' 799 // should be added to the output. 800 // 801 if (StrStr(TabCurrent->FileName, L" ") != NULL){ 802 TabOutputStr[0] = L'\"'; 803 CopyMem (TabOutputStr + 1, TabCurrent->FileName, OutputLength * sizeof (CHAR16)); 804 TabOutputStr[OutputLength + 1] = L'\"'; 805 TabOutputStr[OutputLength + 2] = CHAR_NULL; 806 } else { 807 CopyMem (TabOutputStr, TabCurrent->FileName, OutputLength * sizeof (CHAR16)); 808 TabOutputStr[OutputLength] = CHAR_NULL; 809 } 810 OutputLength = StrLen (TabOutputStr) < MaxStr - 1 ? StrLen (TabOutputStr) : MaxStr - 1; 811 CopyMem (CurrentString + TabUpdatePos, TabOutputStr, OutputLength * sizeof (CHAR16)); 812 CurrentString[TabUpdatePos + OutputLength] = CHAR_NULL; 813 StringCurPos = TabUpdatePos + OutputLength; 814 Update = TabUpdatePos; 815 if (StringLen > TabUpdatePos + OutputLength) { 816 Delete = StringLen - TabUpdatePos - OutputLength; 817 } 818 819 FreePool(TabOutputStr); 820 } 821 822 // 823 // If we have a new position, we are preparing to print a previous or 824 // next command. 825 // 826 if (NewPos != (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory)) { 827 Column = StartColumn; 828 Row -= (StringCurPos + StartColumn) / TotalColumn; 829 830 LinePos = NewPos; 831 NewPos = (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory); 832 833 OutputLength = StrLen (LinePos->Buffer) < MaxStr - 1 ? StrLen (LinePos->Buffer) : MaxStr - 1; 834 CopyMem (CurrentString, LinePos->Buffer, OutputLength * sizeof (CHAR16)); 835 CurrentString[OutputLength] = CHAR_NULL; 836 837 StringCurPos = OutputLength; 838 839 // 840 // Draw new input string 841 // 842 Update = 0; 843 if (StringLen > OutputLength) { 844 // 845 // If old string was longer, blank its tail 846 // 847 Delete = StringLen - OutputLength; 848 } 849 } 850 // 851 // If we need to update the output do so now 852 // 853 if (Update != (UINTN) -1) { 854 ShellPrintEx ((INT32)Column, (INT32)Row, L"%s%.*s", CurrentString + Update, Delete, L""); 855 StringLen = StrLen (CurrentString); 856 857 if (Delete != 0) { 858 SetMem (CurrentString + StringLen, Delete * sizeof (CHAR16), CHAR_NULL); 859 } 860 861 if (StringCurPos > StringLen) { 862 StringCurPos = StringLen; 863 } 864 865 Update = (UINTN) -1; 866 867 // 868 // After using print to reflect newly updates, if we're not using 869 // BACKSPACE and DELETE, we need to move the cursor position forward, 870 // so adjust row and column here. 871 // 872 if (Key.UnicodeChar != CHAR_BACKSPACE && !(Key.UnicodeChar == 0 && Key.ScanCode == SCAN_DELETE)) { 873 // 874 // Calulate row and column of the tail of current string 875 // 876 TailRow = Row + (StringLen - StringCurPos + Column + OutputLength) / TotalColumn; 877 TailColumn = (StringLen - StringCurPos + Column + OutputLength) % TotalColumn; 878 879 // 880 // If the tail of string reaches screen end, screen rolls up, so if 881 // Row does not equal TailRow, Row should be decremented 882 // 883 // (if we are recalling commands using UPPER and DOWN key, and if the 884 // old command is too long to fit the screen, TailColumn must be 79. 885 // 886 if (TailColumn == 0 && TailRow >= TotalRow && Row != TailRow) { 887 Row--; 888 } 889 // 890 // Calculate the cursor position after current operation. If cursor 891 // reaches line end, update both row and column, otherwise, only 892 // column will be changed. 893 // 894 if (Column + OutputLength >= TotalColumn) { 895 SkipLength = OutputLength - (TotalColumn - Column); 896 897 Row += SkipLength / TotalColumn + 1; 898 if (Row > TotalRow - 1) { 899 Row = TotalRow - 1; 900 } 901 902 Column = SkipLength % TotalColumn; 903 } else { 904 Column += OutputLength; 905 } 906 } 907 908 Delete = 0; 909 } 910 // 911 // Set the cursor position for this key 912 // 913 gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row); 914 } while (!Done); 915 916 if (CurrentString != NULL && StrLen(CurrentString) > 0) { 917 // 918 // add the line to the history buffer 919 // 920 AddLineToCommandHistory(CurrentString); 921 } 922 923 // 924 // Return the data to the caller 925 // 926 *BufferSize = StringLen * sizeof (CHAR16); 927 928 // 929 // if this was used it should be deallocated by now... 930 // prevent memory leaks... 931 // 932 if (TabCompleteList != NULL) { 933 ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList); 934 } 935 ASSERT(TabCompleteList == NULL); 936 937 return Status; 938 } 939 940 // 941 // FILE sytle interfaces for StdIn/StdOut/StdErr 942 // 943 EFI_FILE_PROTOCOL FileInterfaceStdIn = { 944 EFI_FILE_REVISION, 945 FileInterfaceOpenNotFound, 946 FileInterfaceNopGeneric, 947 FileInterfaceNopGeneric, 948 FileInterfaceStdInRead, 949 FileInterfaceStdInWrite, 950 FileInterfaceNopGetPosition, 951 FileInterfaceNopSetPosition, 952 FileInterfaceNopGetInfo, 953 FileInterfaceNopSetInfo, 954 FileInterfaceNopGeneric 955 }; 956 957 EFI_FILE_PROTOCOL FileInterfaceStdOut = { 958 EFI_FILE_REVISION, 959 FileInterfaceOpenNotFound, 960 FileInterfaceNopGeneric, 961 FileInterfaceNopGeneric, 962 FileInterfaceStdOutRead, 963 FileInterfaceStdOutWrite, 964 FileInterfaceNopGetPosition, 965 FileInterfaceNopSetPosition, 966 FileInterfaceNopGetInfo, 967 FileInterfaceNopSetInfo, 968 FileInterfaceNopGeneric 969 }; 970 971 EFI_FILE_PROTOCOL FileInterfaceStdErr = { 972 EFI_FILE_REVISION, 973 FileInterfaceOpenNotFound, 974 FileInterfaceNopGeneric, 975 FileInterfaceNopGeneric, 976 FileInterfaceStdErrRead, 977 FileInterfaceStdErrWrite, 978 FileInterfaceNopGetPosition, 979 FileInterfaceNopSetPosition, 980 FileInterfaceNopGetInfo, 981 FileInterfaceNopSetInfo, 982 FileInterfaceNopGeneric 983 }; 984 985 EFI_FILE_PROTOCOL FileInterfaceNulFile = { 986 EFI_FILE_REVISION, 987 FileInterfaceOpenNotFound, 988 FileInterfaceNopGeneric, 989 FileInterfaceNopGeneric, 990 FileInterfaceNulRead, 991 FileInterfaceNulWrite, 992 FileInterfaceNopGetPosition, 993 FileInterfaceNopSetPosition, 994 FileInterfaceNopGetInfo, 995 FileInterfaceNopSetInfo, 996 FileInterfaceNopGeneric 997 }; 998 999 1000 1001 1002 // 1003 // This is identical to EFI_FILE_PROTOCOL except for the additional member 1004 // for the name. 1005 // 1006 1007 typedef struct { 1008 UINT64 Revision; 1009 EFI_FILE_OPEN Open; 1010 EFI_FILE_CLOSE Close; 1011 EFI_FILE_DELETE Delete; 1012 EFI_FILE_READ Read; 1013 EFI_FILE_WRITE Write; 1014 EFI_FILE_GET_POSITION GetPosition; 1015 EFI_FILE_SET_POSITION SetPosition; 1016 EFI_FILE_GET_INFO GetInfo; 1017 EFI_FILE_SET_INFO SetInfo; 1018 EFI_FILE_FLUSH Flush; 1019 CHAR16 Name[1]; 1020 } EFI_FILE_PROTOCOL_ENVIRONMENT; 1021 //ANSI compliance helper to get size of the struct. 1022 #define SIZE_OF_EFI_FILE_PROTOCOL_ENVIRONMENT EFI_FIELD_OFFSET (EFI_FILE_PROTOCOL_ENVIRONMENT, Name) 1023 1024 /** 1025 File style interface for Environment Variable (Close). 1026 1027 Frees the memory for this object. 1028 1029 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 1030 1031 @retval EFI_SUCCESS 1032 **/ 1033 EFI_STATUS 1034 EFIAPI 1035 FileInterfaceEnvClose( 1036 IN EFI_FILE_PROTOCOL *This 1037 ) 1038 { 1039 VOID* NewBuffer; 1040 UINTN NewSize; 1041 EFI_STATUS Status; 1042 BOOLEAN Volatile; 1043 UINTN TotalSize; 1044 1045 // 1046 // Most if not all UEFI commands will have an '\r\n' at the end of any output. 1047 // Since the output was redirected to a variable, it does not make sense to 1048 // keep this. So, before closing, strip the trailing '\r\n' from the variable 1049 // if it exists. 1050 // 1051 NewBuffer = NULL; 1052 NewSize = 0; 1053 TotalSize = 0; 1054 1055 Status = IsVolatileEnv (((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &Volatile); 1056 if (EFI_ERROR (Status)) { 1057 return Status; 1058 } 1059 1060 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); 1061 if (Status == EFI_BUFFER_TOO_SMALL) { 1062 TotalSize = NewSize + sizeof (CHAR16); 1063 NewBuffer = AllocateZeroPool (TotalSize); 1064 if (NewBuffer == NULL) { 1065 return EFI_OUT_OF_RESOURCES; 1066 } 1067 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); 1068 } 1069 1070 if (!EFI_ERROR(Status) && NewBuffer != NULL) { 1071 1072 if (TotalSize / sizeof (CHAR16) >= 3) { 1073 if ( (((CHAR16*)NewBuffer)[TotalSize / sizeof (CHAR16) - 2] == CHAR_LINEFEED) && 1074 (((CHAR16*)NewBuffer)[TotalSize / sizeof (CHAR16) - 3] == CHAR_CARRIAGE_RETURN) 1075 ) { 1076 ((CHAR16*)NewBuffer)[TotalSize / sizeof (CHAR16) - 3] = CHAR_NULL; 1077 } 1078 1079 if (Volatile) { 1080 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V ( 1081 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, 1082 TotalSize - sizeof (CHAR16), 1083 NewBuffer 1084 ); 1085 1086 if (!EFI_ERROR(Status)) { 1087 Status = ShellAddEnvVarToList ( 1088 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, 1089 NewBuffer, 1090 TotalSize, 1091 EFI_VARIABLE_BOOTSERVICE_ACCESS 1092 ); 1093 } 1094 } else { 1095 Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV ( 1096 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, 1097 TotalSize - sizeof (CHAR16), 1098 NewBuffer 1099 ); 1100 1101 if (!EFI_ERROR(Status)) { 1102 Status = ShellAddEnvVarToList ( 1103 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, 1104 NewBuffer, 1105 TotalSize, 1106 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS 1107 ); 1108 } 1109 } 1110 } 1111 } 1112 1113 SHELL_FREE_NON_NULL(NewBuffer); 1114 FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT*)This); 1115 return (Status); 1116 } 1117 1118 /** 1119 File style interface for Environment Variable (Delete). 1120 1121 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 1122 1123 @retval The return value from FileInterfaceEnvClose(). 1124 **/ 1125 EFI_STATUS 1126 EFIAPI 1127 FileInterfaceEnvDelete( 1128 IN EFI_FILE_PROTOCOL *This 1129 ) 1130 { 1131 SHELL_DELETE_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name); 1132 return (FileInterfaceEnvClose(This)); 1133 } 1134 1135 /** 1136 File style interface for Environment Variable (Read). 1137 1138 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 1139 @param[in, out] BufferSize Size in bytes of Buffer. 1140 @param[out] Buffer The pointer to the buffer to fill. 1141 1142 @retval EFI_SUCCESS The data was read. 1143 **/ 1144 EFI_STATUS 1145 EFIAPI 1146 FileInterfaceEnvRead( 1147 IN EFI_FILE_PROTOCOL *This, 1148 IN OUT UINTN *BufferSize, 1149 OUT VOID *Buffer 1150 ) 1151 { 1152 return (SHELL_GET_ENVIRONMENT_VARIABLE( 1153 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, 1154 BufferSize, 1155 Buffer)); 1156 } 1157 1158 /** 1159 File style interface for Volatile Environment Variable (Write). 1160 This function also caches the environment variable into gShellEnvVarList. 1161 1162 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 1163 @param[in, out] BufferSize Size in bytes of Buffer. 1164 @param[in] Buffer The pointer to the buffer to write. 1165 1166 @retval EFI_SUCCESS The data was successfully write to variable. 1167 @retval SHELL_OUT_OF_RESOURCES A memory allocation failed. 1168 **/ 1169 EFI_STATUS 1170 EFIAPI 1171 FileInterfaceEnvVolWrite( 1172 IN EFI_FILE_PROTOCOL *This, 1173 IN OUT UINTN *BufferSize, 1174 IN VOID *Buffer 1175 ) 1176 { 1177 VOID* NewBuffer; 1178 UINTN NewSize; 1179 EFI_STATUS Status; 1180 UINTN TotalSize; 1181 1182 NewBuffer = NULL; 1183 NewSize = 0; 1184 TotalSize = 0; 1185 1186 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); 1187 if (Status == EFI_BUFFER_TOO_SMALL) { 1188 TotalSize = NewSize + *BufferSize + sizeof (CHAR16); 1189 } else if (Status == EFI_NOT_FOUND) { 1190 TotalSize = *BufferSize + sizeof(CHAR16); 1191 } else { 1192 return Status; 1193 } 1194 1195 NewBuffer = AllocateZeroPool (TotalSize); 1196 if (NewBuffer == NULL) { 1197 return EFI_OUT_OF_RESOURCES; 1198 } 1199 1200 if (Status == EFI_BUFFER_TOO_SMALL) { 1201 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); 1202 } 1203 1204 if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) { 1205 FreePool (NewBuffer); 1206 return Status; 1207 } 1208 1209 CopyMem ((UINT8*)NewBuffer + NewSize, Buffer, *BufferSize); 1210 Status = ShellAddEnvVarToList ( 1211 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, 1212 NewBuffer, 1213 TotalSize, 1214 EFI_VARIABLE_BOOTSERVICE_ACCESS 1215 ); 1216 if (EFI_ERROR(Status)) { 1217 FreePool (NewBuffer); 1218 return Status; 1219 } 1220 1221 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V ( 1222 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, 1223 TotalSize - sizeof (CHAR16), 1224 NewBuffer 1225 ); 1226 if (EFI_ERROR(Status)) { 1227 ShellRemvoeEnvVarFromList (((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name); 1228 } 1229 1230 FreePool (NewBuffer); 1231 return Status; 1232 } 1233 1234 1235 /** 1236 File style interface for Non Volatile Environment Variable (Write). 1237 This function also caches the environment variable into gShellEnvVarList. 1238 1239 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 1240 @param[in, out] BufferSize Size in bytes of Buffer. 1241 @param[in] Buffer The pointer to the buffer to write. 1242 1243 @retval EFI_SUCCESS The data was successfully write to variable. 1244 @retval SHELL_OUT_OF_RESOURCES A memory allocation failed. 1245 **/ 1246 EFI_STATUS 1247 EFIAPI 1248 FileInterfaceEnvNonVolWrite( 1249 IN EFI_FILE_PROTOCOL *This, 1250 IN OUT UINTN *BufferSize, 1251 IN VOID *Buffer 1252 ) 1253 { 1254 VOID* NewBuffer; 1255 UINTN NewSize; 1256 EFI_STATUS Status; 1257 UINTN TotalSize; 1258 1259 NewBuffer = NULL; 1260 NewSize = 0; 1261 TotalSize = 0; 1262 1263 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); 1264 if (Status == EFI_BUFFER_TOO_SMALL) { 1265 TotalSize = NewSize + *BufferSize + sizeof (CHAR16); 1266 } else if (Status == EFI_NOT_FOUND) { 1267 TotalSize = *BufferSize + sizeof (CHAR16); 1268 } else { 1269 return Status; 1270 } 1271 1272 NewBuffer = AllocateZeroPool (TotalSize); 1273 if (NewBuffer == NULL) { 1274 return EFI_OUT_OF_RESOURCES; 1275 } 1276 1277 if (Status == EFI_BUFFER_TOO_SMALL) { 1278 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); 1279 } 1280 1281 if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { 1282 FreePool (NewBuffer); 1283 return Status; 1284 } 1285 1286 CopyMem ((UINT8*) NewBuffer + NewSize, Buffer, *BufferSize); 1287 Status = ShellAddEnvVarToList ( 1288 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, 1289 NewBuffer, 1290 TotalSize, 1291 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS 1292 ); 1293 if (EFI_ERROR (Status)) { 1294 FreePool (NewBuffer); 1295 return Status; 1296 } 1297 1298 Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV ( 1299 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, 1300 TotalSize - sizeof (CHAR16), 1301 NewBuffer 1302 ); 1303 if (EFI_ERROR (Status)) { 1304 ShellRemvoeEnvVarFromList (((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name); 1305 } 1306 1307 FreePool (NewBuffer); 1308 return Status; 1309 } 1310 1311 /** 1312 Creates a EFI_FILE_PROTOCOL (almost) object for using to access 1313 environment variables through file operations. 1314 1315 @param EnvName The name of the Environment Variable to be operated on. 1316 1317 @retval NULL Memory could not be allocated. 1318 @return other a pointer to an EFI_FILE_PROTOCOL structure 1319 **/ 1320 EFI_FILE_PROTOCOL* 1321 CreateFileInterfaceEnv( 1322 IN CONST CHAR16 *EnvName 1323 ) 1324 { 1325 EFI_STATUS Status; 1326 EFI_FILE_PROTOCOL_ENVIRONMENT *EnvFileInterface; 1327 UINTN EnvNameSize; 1328 BOOLEAN Volatile; 1329 1330 if (EnvName == NULL) { 1331 return (NULL); 1332 } 1333 1334 Status = IsVolatileEnv (EnvName, &Volatile); 1335 if (EFI_ERROR (Status)) { 1336 return NULL; 1337 } 1338 1339 // 1340 // Get some memory 1341 // 1342 EnvNameSize = StrSize(EnvName); 1343 EnvFileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT)+EnvNameSize); 1344 if (EnvFileInterface == NULL){ 1345 return (NULL); 1346 } 1347 1348 // 1349 // Assign the generic members 1350 // 1351 EnvFileInterface->Revision = EFI_FILE_REVISION; 1352 EnvFileInterface->Open = FileInterfaceOpenNotFound; 1353 EnvFileInterface->Close = FileInterfaceEnvClose; 1354 EnvFileInterface->GetPosition = FileInterfaceNopGetPosition; 1355 EnvFileInterface->SetPosition = FileInterfaceNopSetPosition; 1356 EnvFileInterface->GetInfo = FileInterfaceNopGetInfo; 1357 EnvFileInterface->SetInfo = FileInterfaceNopSetInfo; 1358 EnvFileInterface->Flush = FileInterfaceNopGeneric; 1359 EnvFileInterface->Delete = FileInterfaceEnvDelete; 1360 EnvFileInterface->Read = FileInterfaceEnvRead; 1361 1362 CopyMem(EnvFileInterface->Name, EnvName, EnvNameSize); 1363 1364 // 1365 // Assign the different members for Volatile and Non-Volatile variables 1366 // 1367 if (Volatile) { 1368 EnvFileInterface->Write = FileInterfaceEnvVolWrite; 1369 } else { 1370 EnvFileInterface->Write = FileInterfaceEnvNonVolWrite; 1371 } 1372 return ((EFI_FILE_PROTOCOL *)EnvFileInterface); 1373 } 1374 1375 /** 1376 Move the cursor position one character backward. 1377 1378 @param[in] LineLength Length of a line. Get it by calling QueryMode 1379 @param[in, out] Column Current column of the cursor position 1380 @param[in, out] Row Current row of the cursor position 1381 **/ 1382 VOID 1383 MoveCursorBackward ( 1384 IN UINTN LineLength, 1385 IN OUT UINTN *Column, 1386 IN OUT UINTN *Row 1387 ) 1388 { 1389 // 1390 // If current column is 0, move to the last column of the previous line, 1391 // otherwise, just decrement column. 1392 // 1393 if (*Column == 0) { 1394 *Column = LineLength - 1; 1395 if (*Row > 0) { 1396 (*Row)--; 1397 } 1398 return; 1399 } 1400 (*Column)--; 1401 } 1402 1403 /** 1404 Move the cursor position one character forward. 1405 1406 @param[in] LineLength Length of a line. 1407 @param[in] TotalRow Total row of a screen 1408 @param[in, out] Column Current column of the cursor position 1409 @param[in, out] Row Current row of the cursor position 1410 **/ 1411 VOID 1412 MoveCursorForward ( 1413 IN UINTN LineLength, 1414 IN UINTN TotalRow, 1415 IN OUT UINTN *Column, 1416 IN OUT UINTN *Row 1417 ) 1418 { 1419 // 1420 // Increment Column. 1421 // If this puts column past the end of the line, move to first column 1422 // of the next row. 1423 // 1424 (*Column)++; 1425 if (*Column >= LineLength) { 1426 (*Column) = 0; 1427 if ((*Row) < TotalRow - 1) { 1428 (*Row)++; 1429 } 1430 } 1431 } 1432 1433 /** 1434 Prints out each previously typed command in the command list history log. 1435 1436 When each screen is full it will pause for a key before continuing. 1437 1438 @param[in] TotalCols How many columns are on the screen 1439 @param[in] TotalRows How many rows are on the screen 1440 @param[in] StartColumn which column to start at 1441 **/ 1442 VOID 1443 PrintCommandHistory ( 1444 IN CONST UINTN TotalCols, 1445 IN CONST UINTN TotalRows, 1446 IN CONST UINTN StartColumn 1447 ) 1448 { 1449 BUFFER_LIST *Node; 1450 UINTN Index; 1451 UINTN LineNumber; 1452 UINTN LineCount; 1453 1454 ShellPrintEx (-1, -1, L"\n"); 1455 Index = 0; 1456 LineNumber = 0; 1457 // 1458 // go through history list... 1459 // 1460 for ( Node = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link) 1461 ; !IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link) 1462 ; Node = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link) 1463 ){ 1464 Index++; 1465 LineCount = ((StrLen (Node->Buffer) + StartColumn + 1) / TotalCols) + 1; 1466 1467 if (LineNumber + LineCount >= TotalRows) { 1468 ShellPromptForResponseHii( 1469 ShellPromptResponseTypeEnterContinue, 1470 STRING_TOKEN (STR_SHELL_ENTER_TO_CONT), 1471 ShellInfoObject.HiiHandle, 1472 NULL 1473 ); 1474 LineNumber = 0; 1475 } 1476 ShellPrintEx (-1, -1, L"%2d. %s\n", Index, Node->Buffer); 1477 LineNumber += LineCount; 1478 } 1479 } 1480 1481 1482 1483 1484 1485 1486 // 1487 // This is identical to EFI_FILE_PROTOCOL except for the additional members 1488 // for the buffer, size, and position. 1489 // 1490 1491 typedef struct { 1492 UINT64 Revision; 1493 EFI_FILE_OPEN Open; 1494 EFI_FILE_CLOSE Close; 1495 EFI_FILE_DELETE Delete; 1496 EFI_FILE_READ Read; 1497 EFI_FILE_WRITE Write; 1498 EFI_FILE_GET_POSITION GetPosition; 1499 EFI_FILE_SET_POSITION SetPosition; 1500 EFI_FILE_GET_INFO GetInfo; 1501 EFI_FILE_SET_INFO SetInfo; 1502 EFI_FILE_FLUSH Flush; 1503 VOID *Buffer; 1504 UINT64 Position; 1505 UINT64 BufferSize; 1506 BOOLEAN Unicode; 1507 UINT64 FileSize; 1508 } EFI_FILE_PROTOCOL_MEM; 1509 1510 /** 1511 File style interface for Mem (SetPosition). 1512 1513 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 1514 @param[out] Position The position to set. 1515 1516 @retval EFI_SUCCESS The position was successfully changed. 1517 @retval EFI_INVALID_PARAMETER The Position was invalid. 1518 **/ 1519 EFI_STATUS 1520 EFIAPI 1521 FileInterfaceMemSetPosition( 1522 IN EFI_FILE_PROTOCOL *This, 1523 OUT UINT64 Position 1524 ) 1525 { 1526 if (Position <= ((EFI_FILE_PROTOCOL_MEM*)This)->FileSize) { 1527 ((EFI_FILE_PROTOCOL_MEM*)This)->Position = Position; 1528 return (EFI_SUCCESS); 1529 } else { 1530 return (EFI_INVALID_PARAMETER); 1531 } 1532 } 1533 1534 /** 1535 File style interface for Mem (GetPosition). 1536 1537 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 1538 @param[out] Position The pointer to the position. 1539 1540 @retval EFI_SUCCESS The position was retrieved. 1541 **/ 1542 EFI_STATUS 1543 EFIAPI 1544 FileInterfaceMemGetPosition( 1545 IN EFI_FILE_PROTOCOL *This, 1546 OUT UINT64 *Position 1547 ) 1548 { 1549 *Position = ((EFI_FILE_PROTOCOL_MEM*)This)->Position; 1550 return (EFI_SUCCESS); 1551 } 1552 1553 /** 1554 File style interface for Mem (Write). 1555 1556 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 1557 @param[in, out] BufferSize Size in bytes of Buffer. 1558 @param[in] Buffer The pointer to the buffer to write. 1559 1560 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources. 1561 @retval EFI_SUCCESS The data was written. 1562 **/ 1563 EFI_STATUS 1564 EFIAPI 1565 FileInterfaceMemWrite( 1566 IN EFI_FILE_PROTOCOL *This, 1567 IN OUT UINTN *BufferSize, 1568 IN VOID *Buffer 1569 ) 1570 { 1571 CHAR8 *AsciiBuffer; 1572 EFI_FILE_PROTOCOL_MEM *MemFile; 1573 1574 MemFile = (EFI_FILE_PROTOCOL_MEM *) This; 1575 if (MemFile->Unicode) { 1576 // 1577 // Unicode 1578 // 1579 if ((UINTN)(MemFile->Position + (*BufferSize)) > (UINTN)(MemFile->BufferSize)) { 1580 MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer); 1581 MemFile->BufferSize += (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD; 1582 } 1583 CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, Buffer, *BufferSize); 1584 MemFile->Position += (*BufferSize); 1585 MemFile->FileSize = MemFile->Position; 1586 return (EFI_SUCCESS); 1587 } else { 1588 // 1589 // Ascii 1590 // 1591 AsciiBuffer = AllocateZeroPool(*BufferSize); 1592 if (AsciiBuffer == NULL) { 1593 return (EFI_OUT_OF_RESOURCES); 1594 } 1595 AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer); 1596 if ((UINTN)(MemFile->Position + AsciiStrSize(AsciiBuffer)) > (UINTN)(MemFile->BufferSize)) { 1597 MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + AsciiStrSize(AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer); 1598 MemFile->BufferSize += AsciiStrSize(AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD; 1599 } 1600 CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, AsciiBuffer, AsciiStrSize(AsciiBuffer)); 1601 MemFile->Position += (*BufferSize / sizeof(CHAR16)); 1602 MemFile->FileSize = MemFile->Position; 1603 FreePool(AsciiBuffer); 1604 return (EFI_SUCCESS); 1605 } 1606 } 1607 1608 /** 1609 File style interface for Mem (Read). 1610 1611 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 1612 @param[in, out] BufferSize Size in bytes of Buffer. 1613 @param[in] Buffer The pointer to the buffer to fill. 1614 1615 @retval EFI_SUCCESS The data was read. 1616 **/ 1617 EFI_STATUS 1618 EFIAPI 1619 FileInterfaceMemRead( 1620 IN EFI_FILE_PROTOCOL *This, 1621 IN OUT UINTN *BufferSize, 1622 IN VOID *Buffer 1623 ) 1624 { 1625 EFI_FILE_PROTOCOL_MEM *MemFile; 1626 1627 MemFile = (EFI_FILE_PROTOCOL_MEM *) This; 1628 if (*BufferSize > (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position))) { 1629 (*BufferSize) = (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position)); 1630 } 1631 CopyMem(Buffer, ((UINT8*)MemFile->Buffer) + MemFile->Position, (*BufferSize)); 1632 MemFile->Position = MemFile->Position + (*BufferSize); 1633 return (EFI_SUCCESS); 1634 } 1635 1636 /** 1637 File style interface for Mem (Close). 1638 1639 Frees all memory associated with this object. 1640 1641 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 1642 1643 @retval EFI_SUCCESS The 'file' was closed. 1644 **/ 1645 EFI_STATUS 1646 EFIAPI 1647 FileInterfaceMemClose( 1648 IN EFI_FILE_PROTOCOL *This 1649 ) 1650 { 1651 SHELL_FREE_NON_NULL(((EFI_FILE_PROTOCOL_MEM*)This)->Buffer); 1652 SHELL_FREE_NON_NULL(This); 1653 return (EFI_SUCCESS); 1654 } 1655 1656 /** 1657 Creates a EFI_FILE_PROTOCOL (almost) object for using to access 1658 a file entirely in memory through file operations. 1659 1660 @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii. 1661 1662 @retval NULL Memory could not be allocated. 1663 @return other A pointer to an EFI_FILE_PROTOCOL structure. 1664 **/ 1665 EFI_FILE_PROTOCOL* 1666 CreateFileInterfaceMem( 1667 IN CONST BOOLEAN Unicode 1668 ) 1669 { 1670 EFI_FILE_PROTOCOL_MEM *FileInterface; 1671 1672 // 1673 // Get some memory 1674 // 1675 FileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_MEM)); 1676 if (FileInterface == NULL){ 1677 return (NULL); 1678 } 1679 1680 // 1681 // Assign the generic members 1682 // 1683 FileInterface->Revision = EFI_FILE_REVISION; 1684 FileInterface->Open = FileInterfaceOpenNotFound; 1685 FileInterface->Close = FileInterfaceMemClose; 1686 FileInterface->GetPosition = FileInterfaceMemGetPosition; 1687 FileInterface->SetPosition = FileInterfaceMemSetPosition; 1688 FileInterface->GetInfo = FileInterfaceNopGetInfo; 1689 FileInterface->SetInfo = FileInterfaceNopSetInfo; 1690 FileInterface->Flush = FileInterfaceNopGeneric; 1691 FileInterface->Delete = FileInterfaceNopGeneric; 1692 FileInterface->Read = FileInterfaceMemRead; 1693 FileInterface->Write = FileInterfaceMemWrite; 1694 FileInterface->Unicode = Unicode; 1695 1696 ASSERT(FileInterface->Buffer == NULL); 1697 ASSERT(FileInterface->BufferSize == 0); 1698 ASSERT(FileInterface->Position == 0); 1699 1700 if (Unicode) { 1701 FileInterface->Buffer = AllocateZeroPool(sizeof(gUnicodeFileTag)); 1702 if (FileInterface->Buffer == NULL) { 1703 FreePool (FileInterface); 1704 return NULL; 1705 } 1706 *((CHAR16 *) (FileInterface->Buffer)) = EFI_UNICODE_BYTE_ORDER_MARK; 1707 FileInterface->BufferSize = 2; 1708 FileInterface->Position = 2; 1709 } 1710 1711 return ((EFI_FILE_PROTOCOL *)FileInterface); 1712 } 1713 1714 typedef struct { 1715 UINT64 Revision; 1716 EFI_FILE_OPEN Open; 1717 EFI_FILE_CLOSE Close; 1718 EFI_FILE_DELETE Delete; 1719 EFI_FILE_READ Read; 1720 EFI_FILE_WRITE Write; 1721 EFI_FILE_GET_POSITION GetPosition; 1722 EFI_FILE_SET_POSITION SetPosition; 1723 EFI_FILE_GET_INFO GetInfo; 1724 EFI_FILE_SET_INFO SetInfo; 1725 EFI_FILE_FLUSH Flush; 1726 BOOLEAN Unicode; 1727 EFI_FILE_PROTOCOL *Orig; 1728 } EFI_FILE_PROTOCOL_FILE; 1729 1730 /** 1731 Set a files current position 1732 1733 @param This Protocol instance pointer. 1734 @param Position Byte position from the start of the file. 1735 1736 @retval EFI_SUCCESS Data was written. 1737 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open. 1738 1739 **/ 1740 EFI_STATUS 1741 EFIAPI 1742 FileInterfaceFileSetPosition( 1743 IN EFI_FILE_PROTOCOL *This, 1744 IN UINT64 Position 1745 ) 1746 { 1747 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->SetPosition(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, Position); 1748 } 1749 1750 /** 1751 Get a file's current position 1752 1753 @param This Protocol instance pointer. 1754 @param Position Byte position from the start of the file. 1755 1756 @retval EFI_SUCCESS Data was written. 1757 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.. 1758 1759 **/ 1760 EFI_STATUS 1761 EFIAPI 1762 FileInterfaceFileGetPosition( 1763 IN EFI_FILE_PROTOCOL *This, 1764 OUT UINT64 *Position 1765 ) 1766 { 1767 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetPosition(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, Position); 1768 } 1769 1770 /** 1771 Get information about a file. 1772 1773 @param This Protocol instance pointer. 1774 @param InformationType Type of information to return in Buffer. 1775 @param BufferSize On input size of buffer, on output amount of data in buffer. 1776 @param Buffer The buffer to return data. 1777 1778 @retval EFI_SUCCESS Data was returned. 1779 @retval EFI_UNSUPPORT InformationType is not supported. 1780 @retval EFI_NO_MEDIA The device has no media. 1781 @retval EFI_DEVICE_ERROR The device reported an error. 1782 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. 1783 @retval EFI_WRITE_PROTECTED The device is write protected. 1784 @retval EFI_ACCESS_DENIED The file was open for read only. 1785 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize. 1786 1787 **/ 1788 EFI_STATUS 1789 EFIAPI 1790 FileInterfaceFileGetInfo( 1791 IN EFI_FILE_PROTOCOL *This, 1792 IN EFI_GUID *InformationType, 1793 IN OUT UINTN *BufferSize, 1794 OUT VOID *Buffer 1795 ) 1796 { 1797 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetInfo(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, InformationType, BufferSize, Buffer); 1798 } 1799 1800 /** 1801 Set information about a file 1802 1803 @param This Protocol instance pointer. 1804 @param InformationType Type of information in Buffer. 1805 @param BufferSize Size of buffer. 1806 @param Buffer The data to write. 1807 1808 @retval EFI_SUCCESS Data was returned. 1809 @retval EFI_UNSUPPORT InformationType is not supported. 1810 @retval EFI_NO_MEDIA The device has no media. 1811 @retval EFI_DEVICE_ERROR The device reported an error. 1812 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. 1813 @retval EFI_WRITE_PROTECTED The device is write protected. 1814 @retval EFI_ACCESS_DENIED The file was open for read only. 1815 1816 **/ 1817 EFI_STATUS 1818 EFIAPI 1819 FileInterfaceFileSetInfo( 1820 IN EFI_FILE_PROTOCOL *This, 1821 IN EFI_GUID *InformationType, 1822 IN UINTN BufferSize, 1823 IN VOID *Buffer 1824 ) 1825 { 1826 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->SetInfo(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, InformationType, BufferSize, Buffer); 1827 } 1828 1829 /** 1830 Flush data back for the file handle. 1831 1832 @param This Protocol instance pointer. 1833 1834 @retval EFI_SUCCESS Data was written. 1835 @retval EFI_UNSUPPORT Writes to Open directory are not supported. 1836 @retval EFI_NO_MEDIA The device has no media. 1837 @retval EFI_DEVICE_ERROR The device reported an error. 1838 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. 1839 @retval EFI_WRITE_PROTECTED The device is write protected. 1840 @retval EFI_ACCESS_DENIED The file was open for read only. 1841 @retval EFI_VOLUME_FULL The volume is full. 1842 1843 **/ 1844 EFI_STATUS 1845 EFIAPI 1846 FileInterfaceFileFlush( 1847 IN EFI_FILE_PROTOCOL *This 1848 ) 1849 { 1850 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Flush(((EFI_FILE_PROTOCOL_FILE*)This)->Orig); 1851 } 1852 1853 /** 1854 Read data from the file. 1855 1856 @param This Protocol instance pointer. 1857 @param BufferSize On input size of buffer, on output amount of data in buffer. 1858 @param Buffer The buffer in which data is read. 1859 1860 @retval EFI_SUCCESS Data was read. 1861 @retval EFI_NO_MEDIA The device has no media. 1862 @retval EFI_DEVICE_ERROR The device reported an error. 1863 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. 1864 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size. 1865 1866 **/ 1867 EFI_STATUS 1868 EFIAPI 1869 FileInterfaceFileRead( 1870 IN EFI_FILE_PROTOCOL *This, 1871 IN OUT UINTN *BufferSize, 1872 OUT VOID *Buffer 1873 ) 1874 { 1875 CHAR8 *AsciiStrBuffer; 1876 CHAR16 *UscStrBuffer; 1877 UINTN Size; 1878 UINTN CharNum; 1879 EFI_STATUS Status; 1880 if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) { 1881 // 1882 // Unicode 1883 // 1884 return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer)); 1885 } else { 1886 // 1887 // Ascii 1888 // 1889 Size = (*BufferSize) / sizeof(CHAR16); 1890 AsciiStrBuffer = AllocateZeroPool(Size + sizeof(CHAR8)); 1891 if (AsciiStrBuffer == NULL) { 1892 return EFI_OUT_OF_RESOURCES; 1893 } 1894 UscStrBuffer = AllocateZeroPool(*BufferSize + sizeof(CHAR16)); 1895 if (UscStrBuffer== NULL) { 1896 SHELL_FREE_NON_NULL(AsciiStrBuffer); 1897 return EFI_OUT_OF_RESOURCES; 1898 } 1899 Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiStrBuffer)); 1900 if (!EFI_ERROR(Status)) { 1901 CharNum = UnicodeSPrint(UscStrBuffer, *BufferSize + sizeof(CHAR16), L"%a", AsciiStrBuffer); 1902 if (CharNum == Size) { 1903 CopyMem (Buffer, UscStrBuffer, *BufferSize); 1904 } else { 1905 Status = EFI_UNSUPPORTED; 1906 } 1907 } 1908 SHELL_FREE_NON_NULL(AsciiStrBuffer); 1909 SHELL_FREE_NON_NULL(UscStrBuffer); 1910 return (Status); 1911 } 1912 } 1913 1914 /** 1915 Opens a new file relative to the source file's location. 1916 1917 @param[in] This The protocol instance pointer. 1918 @param[out] NewHandle Returns File Handle for FileName. 1919 @param[in] FileName Null terminated string. "\", ".", and ".." are supported. 1920 @param[in] OpenMode Open mode for file. 1921 @param[in] Attributes Only used for EFI_FILE_MODE_CREATE. 1922 1923 @retval EFI_SUCCESS The device was opened. 1924 @retval EFI_NOT_FOUND The specified file could not be found on the device. 1925 @retval EFI_NO_MEDIA The device has no media. 1926 @retval EFI_MEDIA_CHANGED The media has changed. 1927 @retval EFI_DEVICE_ERROR The device reported an error. 1928 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. 1929 @retval EFI_ACCESS_DENIED The service denied access to the file. 1930 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources. 1931 @retval EFI_VOLUME_FULL The volume is full. 1932 **/ 1933 EFI_STATUS 1934 EFIAPI 1935 FileInterfaceFileOpen ( 1936 IN EFI_FILE_PROTOCOL *This, 1937 OUT EFI_FILE_PROTOCOL **NewHandle, 1938 IN CHAR16 *FileName, 1939 IN UINT64 OpenMode, 1940 IN UINT64 Attributes 1941 ) 1942 { 1943 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Open(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, NewHandle, FileName, OpenMode, Attributes); 1944 } 1945 1946 /** 1947 Close and delete the file handle. 1948 1949 @param This Protocol instance pointer. 1950 1951 @retval EFI_SUCCESS The device was opened. 1952 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted. 1953 1954 **/ 1955 EFI_STATUS 1956 EFIAPI 1957 FileInterfaceFileDelete( 1958 IN EFI_FILE_PROTOCOL *This 1959 ) 1960 { 1961 EFI_STATUS Status; 1962 Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Delete(((EFI_FILE_PROTOCOL_FILE*)This)->Orig); 1963 FreePool(This); 1964 return (Status); 1965 } 1966 1967 /** 1968 File style interface for File (Close). 1969 1970 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 1971 1972 @retval EFI_SUCCESS The file was closed. 1973 **/ 1974 EFI_STATUS 1975 EFIAPI 1976 FileInterfaceFileClose( 1977 IN EFI_FILE_PROTOCOL *This 1978 ) 1979 { 1980 EFI_STATUS Status; 1981 Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Close(((EFI_FILE_PROTOCOL_FILE*)This)->Orig); 1982 FreePool(This); 1983 return (Status); 1984 } 1985 1986 /** 1987 File style interface for File (Write). 1988 1989 If the file was opened with ASCII mode the data will be processed through 1990 AsciiSPrint before writing. 1991 1992 @param[in] This The pointer to the EFI_FILE_PROTOCOL object. 1993 @param[in, out] BufferSize Size in bytes of Buffer. 1994 @param[in] Buffer The pointer to the buffer to write. 1995 1996 @retval EFI_SUCCESS The data was written. 1997 **/ 1998 EFI_STATUS 1999 EFIAPI 2000 FileInterfaceFileWrite( 2001 IN EFI_FILE_PROTOCOL *This, 2002 IN OUT UINTN *BufferSize, 2003 IN VOID *Buffer 2004 ) 2005 { 2006 CHAR8 *AsciiBuffer; 2007 UINTN Size; 2008 EFI_STATUS Status; 2009 if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) { 2010 // 2011 // Unicode 2012 // 2013 return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer)); 2014 } else { 2015 // 2016 // Ascii 2017 // 2018 AsciiBuffer = AllocateZeroPool(*BufferSize); 2019 AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer); 2020 Size = AsciiStrSize(AsciiBuffer) - 1; // (we dont need the null terminator) 2021 Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiBuffer)); 2022 FreePool(AsciiBuffer); 2023 return (Status); 2024 } 2025 } 2026 2027 /** 2028 Create a file interface with unicode information. 2029 2030 This will create a new EFI_FILE_PROTOCOL identical to the Templace 2031 except that the new one has Unicode and Ascii knowledge. 2032 2033 @param[in] Template A pointer to the EFI_FILE_PROTOCOL object. 2034 @param[in] Unicode TRUE for UCS-2, FALSE for ASCII. 2035 2036 @return a new EFI_FILE_PROTOCOL object to be used instead of the template. 2037 **/ 2038 EFI_FILE_PROTOCOL* 2039 CreateFileInterfaceFile( 2040 IN CONST EFI_FILE_PROTOCOL *Template, 2041 IN CONST BOOLEAN Unicode 2042 ) 2043 { 2044 EFI_FILE_PROTOCOL_FILE *NewOne; 2045 2046 NewOne = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_FILE)); 2047 if (NewOne == NULL) { 2048 return (NULL); 2049 } 2050 CopyMem(NewOne, Template, sizeof(EFI_FILE_PROTOCOL_FILE)); 2051 NewOne->Orig = (EFI_FILE_PROTOCOL *)Template; 2052 NewOne->Unicode = Unicode; 2053 NewOne->Open = FileInterfaceFileOpen; 2054 NewOne->Close = FileInterfaceFileClose; 2055 NewOne->Delete = FileInterfaceFileDelete; 2056 NewOne->Read = FileInterfaceFileRead; 2057 NewOne->Write = FileInterfaceFileWrite; 2058 NewOne->GetPosition = FileInterfaceFileGetPosition; 2059 NewOne->SetPosition = FileInterfaceFileSetPosition; 2060 NewOne->GetInfo = FileInterfaceFileGetInfo; 2061 NewOne->SetInfo = FileInterfaceFileSetInfo; 2062 NewOne->Flush = FileInterfaceFileFlush; 2063 2064 return ((EFI_FILE_PROTOCOL *)NewOne); 2065 } 2066