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