FileHandleWrappers.c revision fbd2dfadfe6fb16ab7b49fca3764e05e65d97b8a
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**/
31EFI_STATUS
32EFIAPI
33FileInterfaceOpenNotFound(
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**/
51EFI_STATUS
52EFIAPI
53FileInterfaceNopGeneric(
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**/
68EFI_STATUS
69EFIAPI
70FileInterfaceNopGetPosition(
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**/
86EFI_STATUS
87EFIAPI
88FileInterfaceNopSetPosition(
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**/
106EFI_STATUS
107EFIAPI
108FileInterfaceNopGetInfo(
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**/
128EFI_STATUS
129EFIAPI
130FileInterfaceNopSetInfo(
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**/
152EFI_STATUS
153EFIAPI
154FileInterfaceStdOutWrite(
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**/
176EFI_STATUS
177EFIAPI
178FileInterfaceStdInWrite(
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**/
198EFI_STATUS
199EFIAPI
200FileInterfaceStdErrWrite(
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**/
218EFI_STATUS
219EFIAPI
220FileInterfaceStdOutRead(
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**/
238EFI_STATUS
239EFIAPI
240FileInterfaceStdErrRead(
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**/
258EFI_STATUS
259EFIAPI
260FileInterfaceNulRead(
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**/
279EFI_STATUS
280EFIAPI
281FileInterfaceNulWrite(
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**/
314EFI_STATUS
315EFIAPI
316FileInterfaceStdInRead(
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//
862EFI_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
876EFI_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
890EFI_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
904EFI_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
926typedef 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**/
952EFI_STATUS
953EFIAPI
954FileInterfaceEnvClose(
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**/
1009EFI_STATUS
1010EFIAPI
1011FileInterfaceEnvDelete(
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**/
1028EFI_STATUS
1029EFIAPI
1030FileInterfaceEnvRead(
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**/
1051EFI_STATUS
1052EFIAPI
1053FileInterfaceEnvVolWrite(
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**/
1098EFI_STATUS
1099EFIAPI
1100FileInterfaceEnvNonVolWrite(
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**/
1141EFI_FILE_PROTOCOL*
1142EFIAPI
1143CreateFileInterfaceEnv(
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**/
1197VOID
1198EFIAPI
1199MoveCursorBackward (
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**/
1227VOID
1228EFIAPI
1229MoveCursorForward (
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**/
1259VOID
1260EFIAPI
1261PrintCommandHistory (
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
1309typedef 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**/
1336EFI_STATUS
1337EFIAPI
1338FileInterfaceMemSetPosition(
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**/
1359EFI_STATUS
1360EFIAPI
1361FileInterfaceMemGetPosition(
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**/
1380EFI_STATUS
1381EFIAPI
1382FileInterfaceMemWrite(
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**/
1429EFI_STATUS
1430EFIAPI
1431FileInterfaceMemRead(
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**/
1454EFI_STATUS
1455EFIAPI
1456FileInterfaceMemClose(
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**/
1474EFI_FILE_PROTOCOL*
1475EFIAPI
1476CreateFileInterfaceMem(
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
1513typedef 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**/
1539EFI_STATUS
1540EFIAPI
1541FileInterfaceFileSetPosition(
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**/
1559EFI_STATUS
1560EFIAPI
1561FileInterfaceFileGetPosition(
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**/
1587EFI_STATUS
1588EFIAPI
1589FileInterfaceFileGetInfo(
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**/
1616EFI_STATUS
1617EFIAPI
1618FileInterfaceFileSetInfo(
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**/
1643EFI_STATUS
1644EFIAPI
1645FileInterfaceFileFlush(
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**/
1666EFI_STATUS
1667EFIAPI
1668FileInterfaceFileRead(
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**/
1732EFI_STATUS
1733EFIAPI
1734FileInterfaceFileOpen (
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**/
1754EFI_STATUS
1755EFIAPI
1756FileInterfaceFileDelete(
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**/
1773EFI_STATUS
1774EFIAPI
1775FileInterfaceFileClose(
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**/
1797EFI_STATUS
1798EFIAPI
1799FileInterfaceFileWrite(
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**/
1837EFI_FILE_PROTOCOL*
1838CreateFileInterfaceFile(
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