2 EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables,
3 StdIn, StdOut, StdErr, etc...).
5 Copyright 2016 Dell Inc.
6 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
7 (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include "FileHandleInternal.h"
21 #define MEM_WRITE_REALLOC_OVERHEAD 1024
24 File style interface for console (Open).
26 @param[in] This Ignored.
27 @param[out] NewHandle Ignored.
28 @param[in] FileName Ignored.
29 @param[in] OpenMode Ignored.
30 @param[in] Attributes Ignored.
36 FileInterfaceOpenNotFound(
37 IN EFI_FILE_PROTOCOL
*This
,
38 OUT EFI_FILE_PROTOCOL
**NewHandle
,
44 return (EFI_NOT_FOUND
);
48 File style interface for console (Close, Delete, & Flush)
50 @param[in] This Ignored.
56 FileInterfaceNopGeneric(
57 IN EFI_FILE_PROTOCOL
*This
64 File style interface for console (GetPosition).
66 @param[in] This Ignored.
67 @param[out] Position Ignored.
69 @retval EFI_UNSUPPORTED
73 FileInterfaceNopGetPosition(
74 IN EFI_FILE_PROTOCOL
*This
,
78 return (EFI_UNSUPPORTED
);
82 File style interface for console (SetPosition).
84 @param[in] This Ignored.
85 @param[in] Position Ignored.
87 @retval EFI_UNSUPPORTED
91 FileInterfaceNopSetPosition(
92 IN EFI_FILE_PROTOCOL
*This
,
96 return (EFI_UNSUPPORTED
);
100 File style interface for console (GetInfo).
102 @param[in] This Ignored.
103 @param[in] InformationType Ignored.
104 @param[in, out] BufferSize Ignored.
105 @param[out] Buffer Ignored.
107 @retval EFI_UNSUPPORTED
111 FileInterfaceNopGetInfo(
112 IN EFI_FILE_PROTOCOL
*This
,
113 IN EFI_GUID
*InformationType
,
114 IN OUT UINTN
*BufferSize
,
118 return (EFI_UNSUPPORTED
);
122 File style interface for console (SetInfo).
124 @param[in] This Ignored.
125 @param[in] InformationType Ignored.
126 @param[in] BufferSize Ignored.
127 @param[in] Buffer Ignored.
129 @retval EFI_UNSUPPORTED
133 FileInterfaceNopSetInfo(
134 IN EFI_FILE_PROTOCOL
*This
,
135 IN EFI_GUID
*InformationType
,
140 return (EFI_UNSUPPORTED
);
144 File style interface for StdOut (Write).
146 Writes data to the screen.
148 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
149 @param[in, out] BufferSize Size in bytes of Buffer.
150 @param[in] Buffer The pointer to the buffer to write.
152 @retval EFI_UNSUPPORTED No output console is supported.
153 @return A return value from gST->ConOut->OutputString.
157 FileInterfaceStdOutWrite(
158 IN EFI_FILE_PROTOCOL
*This
,
159 IN OUT UINTN
*BufferSize
,
163 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
164 return (EFI_UNSUPPORTED
);
166 if (*((CHAR16
*)Buffer
) == gUnicodeFileTag
) {
167 return (gST
->ConOut
->OutputString(gST
->ConOut
, (CHAR16
*)Buffer
+ 1));
169 return (gST
->ConOut
->OutputString(gST
->ConOut
, Buffer
));
173 File style interface for StdIn (Write).
175 @param[in] This Ignored.
176 @param[in, out] BufferSize Ignored.
177 @param[in] Buffer Ignored.
179 @retval EFI_UNSUPPORTED
183 FileInterfaceStdInWrite(
184 IN EFI_FILE_PROTOCOL
*This
,
185 IN OUT UINTN
*BufferSize
,
189 return (EFI_UNSUPPORTED
);
193 File style interface for console StdErr (Write).
195 Writes error to the error output.
197 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
198 @param[in, out] BufferSize Size in bytes of Buffer.
199 @param[in] Buffer The pointer to the buffer to write.
201 @return A return value from gST->StdErr->OutputString.
205 FileInterfaceStdErrWrite(
206 IN EFI_FILE_PROTOCOL
*This
,
207 IN OUT UINTN
*BufferSize
,
211 return (gST
->StdErr
->OutputString(gST
->StdErr
, Buffer
));
215 File style interface for console StdOut (Read).
217 @param[in] This Ignored.
218 @param[in, out] BufferSize Ignored.
219 @param[out] Buffer Ignored.
221 @retval EFI_UNSUPPORTED
225 FileInterfaceStdOutRead(
226 IN EFI_FILE_PROTOCOL
*This
,
227 IN OUT UINTN
*BufferSize
,
231 return (EFI_UNSUPPORTED
);
235 File style interface for console StdErr (Read).
237 @param[in] This Ignored.
238 @param[in, out] BufferSize Ignored.
239 @param[out] Buffer Ignored.
241 @retval EFI_UNSUPPORTED Always.
245 FileInterfaceStdErrRead(
246 IN EFI_FILE_PROTOCOL
*This
,
247 IN OUT UINTN
*BufferSize
,
251 return (EFI_UNSUPPORTED
);
255 File style interface for NUL file (Read).
257 @param[in] This Ignored.
258 @param[in, out] BufferSize Poiner to 0 upon return.
259 @param[out] Buffer Ignored.
261 @retval EFI_SUCCESS Always.
265 FileInterfaceNulRead(
266 IN EFI_FILE_PROTOCOL
*This
,
267 IN OUT UINTN
*BufferSize
,
272 return (EFI_SUCCESS
);
276 File style interface for NUL file (Write).
278 @param[in] This Ignored.
279 @param[in, out] BufferSize Ignored.
280 @param[in] Buffer Ignored.
286 FileInterfaceNulWrite(
287 IN EFI_FILE_PROTOCOL
*This
,
288 IN OUT UINTN
*BufferSize
,
292 return (EFI_SUCCESS
);
296 Create the TAB completion list.
298 @param[in] InputString The command line to expand.
299 @param[in] StringLen Length of the command line.
300 @param[in] BufferSize Buffer size.
301 @param[out] TabCompletionList Return the TAB completion list.
302 @param[out] TabUpdatePos Return the TAB update position.
306 CreateTabCompletionList (
307 IN CONST CHAR16
*InputString
,
308 IN CONST UINTN StringLen
,
309 IN CONST UINTN BufferSize
,
310 IN OUT EFI_SHELL_FILE_INFO
**TabCompletionList
,
311 IN OUT UINTN
*TabUpdatePos
320 EFI_SHELL_FILE_INFO
*FileList
;
321 EFI_SHELL_FILE_INFO
*FileInfo
;
322 EFI_SHELL_FILE_INFO
*TempFileInfo
;
327 TabStr
= AllocateZeroPool (BufferSize
);
328 if (TabStr
== NULL
) {
329 return EFI_OUT_OF_RESOURCES
;
333 // handle auto complete of file and directory names...
334 // E.g.: cd fs0:\EFI\Bo<TAB>
336 // TabPos TabUpdatePos
342 for (Index
= 0; Index
< StringLen
; Index
++) {
343 switch (InputString
[Index
]) {
345 InQuotation
= (BOOLEAN
) (!InQuotation
);
351 *TabUpdatePos
= TabPos
;
357 // handle the case "fs0:<TAB>"
358 // Update the TabUpdatePos as well.
361 *TabUpdatePos
= Index
+ 1;
369 if (StrStr (InputString
+ TabPos
, L
":") == NULL
) {
371 // If file path doesn't contain ":", ...
373 Cwd
= ShellInfoObject
.NewEfiShellProtocol
->GetCurDir (NULL
);
375 if (InputString
[TabPos
] != L
'\\') {
377 // and it doesn't begin with "\\", it's a path relative to current directory.
378 // TabStr = "<cwd>\\"
380 StrnCpyS (TabStr
, BufferSize
/ sizeof (CHAR16
), Cwd
, (BufferSize
) / sizeof (CHAR16
) - 1);
381 StrCatS (TabStr
, (BufferSize
) / sizeof (CHAR16
), L
"\\");
384 // and it begins with "\\", it's a path pointing to root directory of current map.
387 Index
= StrStr (Cwd
, L
":") - Cwd
+ 1;
388 StrnCpyS (TabStr
, BufferSize
/ sizeof (CHAR16
), Cwd
, Index
);
392 StrnCatS (TabStr
, (BufferSize
) / sizeof (CHAR16
), InputString
+ TabPos
, StringLen
- TabPos
);
393 StrnCatS (TabStr
, (BufferSize
) / sizeof (CHAR16
), L
"*", (BufferSize
) / sizeof (CHAR16
) - 1 - StrLen (TabStr
));
394 Status
= ShellInfoObject
.NewEfiShellProtocol
->FindFiles(TabStr
, &FileList
);
397 // Filter out the non-directory for "CD" command
398 // Filter "." and ".." for all
400 if (!EFI_ERROR (Status
) && FileList
!= NULL
) {
402 // Skip the spaces in the beginning
404 while (*InputString
== L
' ') {
408 for (FileInfo
= (EFI_SHELL_FILE_INFO
*) GetFirstNode (&FileList
->Link
); !IsNull (&FileList
->Link
, &FileInfo
->Link
); ) {
409 if (((StrCmp (FileInfo
->FileName
, L
".") == 0) || (StrCmp (FileInfo
->FileName
, L
"..") == 0)) ||
410 (((InputString
[0] == L
'c' || InputString
[0] == L
'C') && (InputString
[1] == L
'd' || InputString
[1] == L
'D')) &&
411 (ShellIsDirectory (FileInfo
->FullName
) != EFI_SUCCESS
))) {
412 TempFileInfo
= FileInfo
;
413 FileInfo
= (EFI_SHELL_FILE_INFO
*) RemoveEntryList (&FileInfo
->Link
);
414 InternalFreeShellFileInfoNode (TempFileInfo
);
416 FileInfo
= (EFI_SHELL_FILE_INFO
*) GetNextNode (&FileList
->Link
, &FileInfo
->Link
);
421 if (FileList
!= NULL
&& !IsListEmpty (&FileList
->Link
)) {
422 Status
= EFI_SUCCESS
;
424 ShellInfoObject
.NewEfiShellProtocol
->FreeFileList (&FileList
);
425 Status
= EFI_NOT_FOUND
;
430 *TabCompletionList
= FileList
;
435 File style interface for console (Read).
437 This will return a single line of input from the console.
439 @param This A pointer to the EFI_FILE_PROTOCOL instance that is the
440 file handle to read data from. Not used.
441 @param BufferSize On input, the size of the Buffer. On output, the amount
442 of data returned in Buffer. In both cases, the size is
444 @param Buffer The buffer into which the data is read.
447 @retval EFI_SUCCESS The data was read.
448 @retval EFI_NO_MEDIA The device has no medium.
449 @retval EFI_DEVICE_ERROR The device reported an error.
450 @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file.
451 @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file.
452 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
453 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory
454 entry. BufferSize has been updated with the size
455 needed to complete the request.
456 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
460 FileInterfaceStdInRead(
461 IN EFI_FILE_PROTOCOL
*This
,
462 IN OUT UINTN
*BufferSize
,
466 CHAR16
*CurrentString
;
468 UINTN TabUpdatePos
; // Start index of the string updated by TAB stroke
469 UINTN Column
; // Column of current cursor
470 UINTN Row
; // Row of current cursor
471 UINTN StartColumn
; // Column at the beginning of the line
472 UINTN Update
; // Line index for update
473 UINTN Delete
; // Num of chars to delete from console after update
474 UINTN StringLen
; // Total length of the line
475 UINTN StringCurPos
; // Line index corresponding to the cursor
476 UINTN MaxStr
; // Maximum possible line length
477 UINTN TotalColumn
; // Num of columns in the console
478 UINTN TotalRow
; // Num of rows in the console
480 UINTN OutputLength
; // Length of the update string
481 UINTN TailRow
; // Row of end of line
482 UINTN TailColumn
; // Column of end of line
485 BUFFER_LIST
*LinePos
;
489 BOOLEAN InTabScrolling
; // Whether in TAB-completion state
490 EFI_SHELL_FILE_INFO
*TabCompleteList
;
491 EFI_SHELL_FILE_INFO
*TabCurrent
;
493 CHAR16
*TabOutputStr
;
496 // If buffer is not large enough to hold a CHAR16, return minimum buffer size
498 if (*BufferSize
< sizeof (CHAR16
) * 2) {
499 *BufferSize
= sizeof (CHAR16
) * 2;
500 return (EFI_BUFFER_TOO_SMALL
);
504 CurrentString
= Buffer
;
510 LinePos
= NewPos
= (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
);
512 InTabScrolling
= FALSE
;
513 Status
= EFI_SUCCESS
;
516 TabCompleteList
= NULL
;
520 // Get the screen setting and the current cursor location
522 Column
= StartColumn
= gST
->ConOut
->Mode
->CursorColumn
;
523 Row
= gST
->ConOut
->Mode
->CursorRow
;
524 gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &TotalColumn
, &TotalRow
);
527 // Limit the line length to the buffer size or the minimun size of the
528 // screen. (The smaller takes effect)
530 MaxStr
= TotalColumn
* (TotalRow
- 1) - StartColumn
;
531 if (MaxStr
> *BufferSize
/ sizeof (CHAR16
)) {
532 MaxStr
= *BufferSize
/ sizeof (CHAR16
);
534 ZeroMem (CurrentString
, MaxStr
* sizeof (CHAR16
));
539 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &EventIndex
);
540 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
541 if (EFI_ERROR (Status
)) {
543 if (Status
== EFI_NOT_READY
)
546 ZeroMem (CurrentString
, MaxStr
* sizeof(CHAR16
));
552 // Press PageUp or PageDown to scroll the history screen up or down.
553 // Press any other key to quit scrolling.
555 if (Key
.UnicodeChar
== 0 && (Key
.ScanCode
== SCAN_PAGE_UP
|| Key
.ScanCode
== SCAN_PAGE_DOWN
)) {
556 if (Key
.ScanCode
== SCAN_PAGE_UP
) {
557 ConsoleLoggerDisplayHistory(FALSE
, 0, ShellInfoObject
.ConsoleInfo
);
558 } else if (Key
.ScanCode
== SCAN_PAGE_DOWN
) {
559 ConsoleLoggerDisplayHistory(TRUE
, 0, ShellInfoObject
.ConsoleInfo
);
565 ConsoleLoggerStopHistory(ShellInfoObject
.ConsoleInfo
);
571 // If we are quitting TAB scrolling...
573 if (InTabScrolling
&& Key
.UnicodeChar
!= CHAR_TAB
) {
574 if (TabCompleteList
!= NULL
) {
575 ShellInfoObject
.NewEfiShellProtocol
->FreeFileList (&TabCompleteList
);
576 DEBUG_CODE(TabCompleteList
= NULL
;);
578 InTabScrolling
= FALSE
;
581 switch (Key
.UnicodeChar
) {
582 case CHAR_CARRIAGE_RETURN
:
584 // All done, print a newline at the end of the string
586 TailRow
= Row
+ (StringLen
- StringCurPos
+ Column
) / TotalColumn
;
587 TailColumn
= (StringLen
- StringCurPos
+ Column
) % TotalColumn
;
588 ShellPrintEx ((INT32
)TailColumn
, (INT32
)TailRow
, L
"%N\n");
593 if (StringCurPos
!= 0) {
595 // If not move back beyond string beginning, move all characters behind
596 // the current position one character forward
599 Update
= StringCurPos
;
601 CopyMem (CurrentString
+ StringCurPos
, CurrentString
+ StringCurPos
+ 1, sizeof (CHAR16
) * (StringLen
- StringCurPos
));
604 // Adjust the current column and row
606 MoveCursorBackward (TotalColumn
, &Column
, &Row
);
611 if (!InTabScrolling
) {
614 // Initialize a tab complete operation.
616 Status
= CreateTabCompletionList (CurrentString
, StringLen
, *BufferSize
, &TabCompleteList
, &TabUpdatePos
);
617 if (!EFI_ERROR(Status
)) {
618 InTabScrolling
= TRUE
;
622 // We do not set up the replacement.
623 // The next section will do that.
627 if (InTabScrolling
) {
629 // We are in a tab complete operation.
630 // set up the next replacement.
632 ASSERT(TabCompleteList
!= NULL
);
633 if (TabCurrent
== NULL
) {
634 TabCurrent
= (EFI_SHELL_FILE_INFO
*) GetFirstNode (&TabCompleteList
->Link
);
636 TabCurrent
= (EFI_SHELL_FILE_INFO
*) GetNextNode (&TabCompleteList
->Link
, &TabCurrent
->Link
);
640 // Skip over the empty list beginning node
642 if (IsNull(&TabCompleteList
->Link
, &TabCurrent
->Link
)) {
643 TabCurrent
= (EFI_SHELL_FILE_INFO
*) GetNextNode (&TabCompleteList
->Link
, &TabCurrent
->Link
);
649 if (Key
.UnicodeChar
>= ' ') {
651 // If we are at the buffer's end, drop the key
653 if (StringLen
== MaxStr
- 1 && (ShellInfoObject
.ViewingSettings
.InsertMode
|| StringCurPos
== StringLen
)) {
657 // If in insert mode, make space by moving each other character 1
658 // space higher in the array
660 if (ShellInfoObject
.ViewingSettings
.InsertMode
) {
661 CopyMem(CurrentString
+ StringCurPos
+ 1, CurrentString
+ StringCurPos
, (StringLen
- StringCurPos
)*sizeof(CurrentString
[0]));
664 CurrentString
[StringCurPos
] = Key
.UnicodeChar
;
665 Update
= StringCurPos
;
673 switch (Key
.ScanCode
) {
676 // Move characters behind current position one character forward
678 if (StringLen
!= 0) {
679 Update
= StringCurPos
;
681 CopyMem (CurrentString
+ StringCurPos
, CurrentString
+ StringCurPos
+ 1, sizeof (CHAR16
) * (StringLen
- StringCurPos
));
687 // Prepare to print the previous command
689 NewPos
= (BUFFER_LIST
*)GetPreviousNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
690 if (IsNull(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
)) {
691 NewPos
= (BUFFER_LIST
*)GetPreviousNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
697 // Prepare to print the next command
699 NewPos
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
700 if (NewPos
== (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
)) {
701 NewPos
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
707 // Adjust current cursor position
709 if (StringCurPos
!= 0) {
711 MoveCursorBackward (TotalColumn
, &Column
, &Row
);
717 // Adjust current cursor position
719 if (StringCurPos
< StringLen
) {
721 MoveCursorForward (TotalColumn
, TotalRow
, &Column
, &Row
);
727 // Move current cursor position to the beginning of the command line
729 Row
-= (StringCurPos
+ StartColumn
) / TotalColumn
;
730 Column
= StartColumn
;
736 // Move current cursor position to the end of the command line
738 TailRow
= Row
+ (StringLen
- StringCurPos
+ Column
) / TotalColumn
;
739 TailColumn
= (StringLen
- StringCurPos
+ Column
) % TotalColumn
;
742 StringCurPos
= StringLen
;
747 // Prepare to clear the current command line
749 CurrentString
[0] = 0;
752 Row
-= (StringCurPos
+ StartColumn
) / TotalColumn
;
753 Column
= StartColumn
;
759 // Toggle the SEnvInsertMode flag
761 ShellInfoObject
.ViewingSettings
.InsertMode
= (BOOLEAN
)!ShellInfoObject
.ViewingSettings
.InsertMode
;
766 // Print command history
768 PrintCommandHistory (TotalColumn
, TotalRow
, 4);
769 *CurrentString
= CHAR_NULL
;
780 // If we are in auto-complete mode, we are preparing to print
781 // the next file or directory name
783 if (InTabScrolling
) {
784 TabOutputStr
= AllocateZeroPool (*BufferSize
);
785 if (TabOutputStr
== NULL
) {
786 Status
= EFI_OUT_OF_RESOURCES
;
790 if (InTabScrolling
&& TabOutputStr
!= NULL
) {
793 // Adjust the column and row to the start of TAB-completion string.
795 Column
= (StartColumn
+ TabUpdatePos
) % TotalColumn
;
796 Row
-= (StartColumn
+ StringCurPos
) / TotalColumn
- (StartColumn
+ TabUpdatePos
) / TotalColumn
;
797 OutputLength
= StrLen (TabCurrent
->FileName
);
799 // if the output string contains blank space, quotation marks L'\"'
800 // should be added to the output.
802 if (StrStr(TabCurrent
->FileName
, L
" ") != NULL
){
803 TabOutputStr
[0] = L
'\"';
804 CopyMem (TabOutputStr
+ 1, TabCurrent
->FileName
, OutputLength
* sizeof (CHAR16
));
805 TabOutputStr
[OutputLength
+ 1] = L
'\"';
806 TabOutputStr
[OutputLength
+ 2] = CHAR_NULL
;
808 CopyMem (TabOutputStr
, TabCurrent
->FileName
, OutputLength
* sizeof (CHAR16
));
809 TabOutputStr
[OutputLength
] = CHAR_NULL
;
811 OutputLength
= StrLen (TabOutputStr
) < MaxStr
- 1 ? StrLen (TabOutputStr
) : MaxStr
- 1;
812 CopyMem (CurrentString
+ TabUpdatePos
, TabOutputStr
, OutputLength
* sizeof (CHAR16
));
813 CurrentString
[TabUpdatePos
+ OutputLength
] = CHAR_NULL
;
814 StringCurPos
= TabUpdatePos
+ OutputLength
;
815 Update
= TabUpdatePos
;
816 if (StringLen
> TabUpdatePos
+ OutputLength
) {
817 Delete
= StringLen
- TabUpdatePos
- OutputLength
;
820 FreePool(TabOutputStr
);
824 // If we have a new position, we are preparing to print a previous or
827 if (NewPos
!= (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
)) {
828 Column
= StartColumn
;
829 Row
-= (StringCurPos
+ StartColumn
) / TotalColumn
;
832 NewPos
= (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
);
834 OutputLength
= StrLen (LinePos
->Buffer
) < MaxStr
- 1 ? StrLen (LinePos
->Buffer
) : MaxStr
- 1;
835 CopyMem (CurrentString
, LinePos
->Buffer
, OutputLength
* sizeof (CHAR16
));
836 CurrentString
[OutputLength
] = CHAR_NULL
;
838 StringCurPos
= OutputLength
;
841 // Draw new input string
844 if (StringLen
> OutputLength
) {
846 // If old string was longer, blank its tail
848 Delete
= StringLen
- OutputLength
;
852 // If we need to update the output do so now
854 if (Update
!= (UINTN
) -1) {
855 ShellPrintEx ((INT32
)Column
, (INT32
)Row
, L
"%s%.*s", CurrentString
+ Update
, Delete
, L
"");
856 StringLen
= StrLen (CurrentString
);
859 SetMem (CurrentString
+ StringLen
, Delete
* sizeof (CHAR16
), CHAR_NULL
);
862 if (StringCurPos
> StringLen
) {
863 StringCurPos
= StringLen
;
869 // After using print to reflect newly updates, if we're not using
870 // BACKSPACE and DELETE, we need to move the cursor position forward,
871 // so adjust row and column here.
873 if (Key
.UnicodeChar
!= CHAR_BACKSPACE
&& !(Key
.UnicodeChar
== 0 && Key
.ScanCode
== SCAN_DELETE
)) {
875 // Calulate row and column of the tail of current string
877 TailRow
= Row
+ (StringLen
- StringCurPos
+ Column
+ OutputLength
) / TotalColumn
;
878 TailColumn
= (StringLen
- StringCurPos
+ Column
+ OutputLength
) % TotalColumn
;
881 // If the tail of string reaches screen end, screen rolls up, so if
882 // Row does not equal TailRow, Row should be decremented
884 // (if we are recalling commands using UPPER and DOWN key, and if the
885 // old command is too long to fit the screen, TailColumn must be 79.
887 if (TailColumn
== 0 && TailRow
>= TotalRow
&& Row
!= TailRow
) {
891 // Calculate the cursor position after current operation. If cursor
892 // reaches line end, update both row and column, otherwise, only
893 // column will be changed.
895 if (Column
+ OutputLength
>= TotalColumn
) {
896 SkipLength
= OutputLength
- (TotalColumn
- Column
);
898 Row
+= SkipLength
/ TotalColumn
+ 1;
899 if (Row
> TotalRow
- 1) {
903 Column
= SkipLength
% TotalColumn
;
905 Column
+= OutputLength
;
912 // Set the cursor position for this key
914 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, Column
, Row
);
917 if (CurrentString
!= NULL
&& StrLen(CurrentString
) > 0) {
919 // add the line to the history buffer
921 AddLineToCommandHistory(CurrentString
);
925 // Return the data to the caller
927 *BufferSize
= StringLen
* sizeof (CHAR16
);
930 // if this was used it should be deallocated by now...
931 // prevent memory leaks...
933 if (TabCompleteList
!= NULL
) {
934 ShellInfoObject
.NewEfiShellProtocol
->FreeFileList (&TabCompleteList
);
936 ASSERT(TabCompleteList
== NULL
);
942 // FILE sytle interfaces for StdIn/StdOut/StdErr
944 EFI_FILE_PROTOCOL FileInterfaceStdIn
= {
946 FileInterfaceOpenNotFound
,
947 FileInterfaceNopGeneric
,
948 FileInterfaceNopGeneric
,
949 FileInterfaceStdInRead
,
950 FileInterfaceStdInWrite
,
951 FileInterfaceNopGetPosition
,
952 FileInterfaceNopSetPosition
,
953 FileInterfaceNopGetInfo
,
954 FileInterfaceNopSetInfo
,
955 FileInterfaceNopGeneric
958 EFI_FILE_PROTOCOL FileInterfaceStdOut
= {
960 FileInterfaceOpenNotFound
,
961 FileInterfaceNopGeneric
,
962 FileInterfaceNopGeneric
,
963 FileInterfaceStdOutRead
,
964 FileInterfaceStdOutWrite
,
965 FileInterfaceNopGetPosition
,
966 FileInterfaceNopSetPosition
,
967 FileInterfaceNopGetInfo
,
968 FileInterfaceNopSetInfo
,
969 FileInterfaceNopGeneric
972 EFI_FILE_PROTOCOL FileInterfaceStdErr
= {
974 FileInterfaceOpenNotFound
,
975 FileInterfaceNopGeneric
,
976 FileInterfaceNopGeneric
,
977 FileInterfaceStdErrRead
,
978 FileInterfaceStdErrWrite
,
979 FileInterfaceNopGetPosition
,
980 FileInterfaceNopSetPosition
,
981 FileInterfaceNopGetInfo
,
982 FileInterfaceNopSetInfo
,
983 FileInterfaceNopGeneric
986 EFI_FILE_PROTOCOL FileInterfaceNulFile
= {
988 FileInterfaceOpenNotFound
,
989 FileInterfaceNopGeneric
,
990 FileInterfaceNopGeneric
,
991 FileInterfaceNulRead
,
992 FileInterfaceNulWrite
,
993 FileInterfaceNopGetPosition
,
994 FileInterfaceNopSetPosition
,
995 FileInterfaceNopGetInfo
,
996 FileInterfaceNopSetInfo
,
997 FileInterfaceNopGeneric
1004 // This is identical to EFI_FILE_PROTOCOL except for the additional member
1011 EFI_FILE_CLOSE Close
;
1012 EFI_FILE_DELETE Delete
;
1014 EFI_FILE_WRITE Write
;
1015 EFI_FILE_GET_POSITION GetPosition
;
1016 EFI_FILE_SET_POSITION SetPosition
;
1017 EFI_FILE_GET_INFO GetInfo
;
1018 EFI_FILE_SET_INFO SetInfo
;
1019 EFI_FILE_FLUSH Flush
;
1021 } EFI_FILE_PROTOCOL_ENVIRONMENT
;
1022 //ANSI compliance helper to get size of the struct.
1023 #define SIZE_OF_EFI_FILE_PROTOCOL_ENVIRONMENT EFI_FIELD_OFFSET (EFI_FILE_PROTOCOL_ENVIRONMENT, Name)
1026 File style interface for Environment Variable (Close).
1028 Frees the memory for this object.
1030 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1036 FileInterfaceEnvClose(
1037 IN EFI_FILE_PROTOCOL
*This
1046 // Most if not all UEFI commands will have an '\r\n' at the end of any output.
1047 // Since the output was redirected to a variable, it does not make sense to
1048 // keep this. So, before closing, strip the trailing '\r\n' from the variable
1054 Status
= IsVolatileEnv (((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &Volatile
);
1055 if (EFI_ERROR (Status
)) {
1059 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1060 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1061 NewBuffer
= AllocateZeroPool(NewSize
+ sizeof(CHAR16
));
1062 if (NewBuffer
== NULL
) {
1063 return EFI_OUT_OF_RESOURCES
;
1065 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1068 if (!EFI_ERROR(Status
) && NewBuffer
!= NULL
) {
1070 if (StrSize(NewBuffer
) > 6)
1072 if ((((CHAR16
*)NewBuffer
)[(StrSize(NewBuffer
)/2) - 2] == CHAR_LINEFEED
)
1073 && (((CHAR16
*)NewBuffer
)[(StrSize(NewBuffer
)/2) - 3] == CHAR_CARRIAGE_RETURN
)) {
1074 ((CHAR16
*)NewBuffer
)[(StrSize(NewBuffer
)/2) - 3] = CHAR_NULL
;
1078 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, StrSize(NewBuffer
), NewBuffer
);
1080 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_NV(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, StrSize(NewBuffer
), NewBuffer
);
1085 SHELL_FREE_NON_NULL(NewBuffer
);
1086 FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
);
1091 File style interface for Environment Variable (Delete).
1093 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1095 @retval The return value from FileInterfaceEnvClose().
1099 FileInterfaceEnvDelete(
1100 IN EFI_FILE_PROTOCOL
*This
1103 SHELL_DELETE_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
);
1104 return (FileInterfaceEnvClose(This
));
1108 File style interface for Environment Variable (Read).
1110 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1111 @param[in, out] BufferSize Size in bytes of Buffer.
1112 @param[out] Buffer The pointer to the buffer to fill.
1114 @retval EFI_SUCCESS The data was read.
1118 FileInterfaceEnvRead(
1119 IN EFI_FILE_PROTOCOL
*This
,
1120 IN OUT UINTN
*BufferSize
,
1124 return (SHELL_GET_ENVIRONMENT_VARIABLE(
1125 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1131 File style interface for Volatile Environment Variable (Write).
1133 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1134 @param[in, out] BufferSize Size in bytes of Buffer.
1135 @param[in] Buffer The pointer to the buffer to write.
1137 @retval EFI_SUCCESS The data was read.
1141 FileInterfaceEnvVolWrite(
1142 IN EFI_FILE_PROTOCOL
*This
,
1143 IN OUT UINTN
*BufferSize
,
1154 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1155 if (Status
== EFI_BUFFER_TOO_SMALL
){
1156 NewBuffer
= AllocateZeroPool(NewSize
+ *BufferSize
+ sizeof(CHAR16
));
1157 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1159 if (!EFI_ERROR(Status
) && NewBuffer
!= NULL
) {
1160 while (((CHAR16
*)NewBuffer
)[NewSize
/2] == CHAR_NULL
) {
1162 // We want to overwrite the CHAR_NULL
1166 CopyMem((UINT8
*)NewBuffer
+ NewSize
+ 2, Buffer
, *BufferSize
);
1167 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, StrSize(NewBuffer
), NewBuffer
);
1168 FreePool(NewBuffer
);
1171 SHELL_FREE_NON_NULL(NewBuffer
);
1172 return (SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, *BufferSize
, Buffer
));
1178 File style interface for Non Volatile Environment Variable (Write).
1180 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1181 @param[in, out] BufferSize Size in bytes of Buffer.
1182 @param[in] Buffer The pointer to the buffer to write.
1184 @retval EFI_SUCCESS The data was read.
1188 FileInterfaceEnvNonVolWrite(
1189 IN EFI_FILE_PROTOCOL
*This
,
1190 IN OUT UINTN
*BufferSize
,
1201 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1202 if (Status
== EFI_BUFFER_TOO_SMALL
){
1203 NewBuffer
= AllocateZeroPool(NewSize
+ *BufferSize
);
1204 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1206 if (!EFI_ERROR(Status
)) {
1207 CopyMem((UINT8
*)NewBuffer
+ NewSize
, Buffer
, *BufferSize
);
1208 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
1209 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1210 NewSize
+ *BufferSize
,
1213 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
1214 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1221 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1222 environment variables through file operations.
1224 @param EnvName The name of the Environment Variable to be operated on.
1226 @retval NULL Memory could not be allocated.
1227 @return other a pointer to an EFI_FILE_PROTOCOL structure
1231 CreateFileInterfaceEnv(
1232 IN CONST CHAR16
*EnvName
1236 EFI_FILE_PROTOCOL_ENVIRONMENT
*EnvFileInterface
;
1240 if (EnvName
== NULL
) {
1244 Status
= IsVolatileEnv (EnvName
, &Volatile
);
1245 if (EFI_ERROR (Status
)) {
1252 EnvNameSize
= StrSize(EnvName
);
1253 EnvFileInterface
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT
)+EnvNameSize
);
1254 if (EnvFileInterface
== NULL
){
1259 // Assign the generic members
1261 EnvFileInterface
->Revision
= EFI_FILE_REVISION
;
1262 EnvFileInterface
->Open
= FileInterfaceOpenNotFound
;
1263 EnvFileInterface
->Close
= FileInterfaceEnvClose
;
1264 EnvFileInterface
->GetPosition
= FileInterfaceNopGetPosition
;
1265 EnvFileInterface
->SetPosition
= FileInterfaceNopSetPosition
;
1266 EnvFileInterface
->GetInfo
= FileInterfaceNopGetInfo
;
1267 EnvFileInterface
->SetInfo
= FileInterfaceNopSetInfo
;
1268 EnvFileInterface
->Flush
= FileInterfaceNopGeneric
;
1269 EnvFileInterface
->Delete
= FileInterfaceEnvDelete
;
1270 EnvFileInterface
->Read
= FileInterfaceEnvRead
;
1272 CopyMem(EnvFileInterface
->Name
, EnvName
, EnvNameSize
);
1275 // Assign the different members for Volatile and Non-Volatile variables
1278 EnvFileInterface
->Write
= FileInterfaceEnvVolWrite
;
1280 EnvFileInterface
->Write
= FileInterfaceEnvNonVolWrite
;
1282 return ((EFI_FILE_PROTOCOL
*)EnvFileInterface
);
1286 Move the cursor position one character backward.
1288 @param[in] LineLength Length of a line. Get it by calling QueryMode
1289 @param[in, out] Column Current column of the cursor position
1290 @param[in, out] Row Current row of the cursor position
1294 MoveCursorBackward (
1295 IN UINTN LineLength
,
1296 IN OUT UINTN
*Column
,
1301 // If current column is 0, move to the last column of the previous line,
1302 // otherwise, just decrement column.
1305 *Column
= LineLength
- 1;
1315 Move the cursor position one character forward.
1317 @param[in] LineLength Length of a line.
1318 @param[in] TotalRow Total row of a screen
1319 @param[in, out] Column Current column of the cursor position
1320 @param[in, out] Row Current row of the cursor position
1325 IN UINTN LineLength
,
1327 IN OUT UINTN
*Column
,
1332 // Increment Column.
1333 // If this puts column past the end of the line, move to first column
1337 if (*Column
>= LineLength
) {
1339 if ((*Row
) < TotalRow
- 1) {
1346 Prints out each previously typed command in the command list history log.
1348 When each screen is full it will pause for a key before continuing.
1350 @param[in] TotalCols How many columns are on the screen
1351 @param[in] TotalRows How many rows are on the screen
1352 @param[in] StartColumn which column to start at
1356 PrintCommandHistory (
1357 IN CONST UINTN TotalCols
,
1358 IN CONST UINTN TotalRows
,
1359 IN CONST UINTN StartColumn
1367 ShellPrintEx (-1, -1, L
"\n");
1371 // go through history list...
1373 for ( Node
= (BUFFER_LIST
*)GetFirstNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
)
1374 ; !IsNull(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &Node
->Link
)
1375 ; Node
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &Node
->Link
)
1378 LineCount
= ((StrLen (Node
->Buffer
) + StartColumn
+ 1) / TotalCols
) + 1;
1380 if (LineNumber
+ LineCount
>= TotalRows
) {
1381 ShellPromptForResponseHii(
1382 ShellPromptResponseTypeEnterContinue
,
1383 STRING_TOKEN (STR_SHELL_ENTER_TO_CONT
),
1384 ShellInfoObject
.HiiHandle
,
1389 ShellPrintEx (-1, -1, L
"%2d. %s\n", Index
, Node
->Buffer
);
1390 LineNumber
+= LineCount
;
1400 // This is identical to EFI_FILE_PROTOCOL except for the additional members
1401 // for the buffer, size, and position.
1407 EFI_FILE_CLOSE Close
;
1408 EFI_FILE_DELETE Delete
;
1410 EFI_FILE_WRITE Write
;
1411 EFI_FILE_GET_POSITION GetPosition
;
1412 EFI_FILE_SET_POSITION SetPosition
;
1413 EFI_FILE_GET_INFO GetInfo
;
1414 EFI_FILE_SET_INFO SetInfo
;
1415 EFI_FILE_FLUSH Flush
;
1421 } EFI_FILE_PROTOCOL_MEM
;
1424 File style interface for Mem (SetPosition).
1426 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1427 @param[out] Position The position to set.
1429 @retval EFI_SUCCESS The position was successfully changed.
1430 @retval EFI_INVALID_PARAMETER The Position was invalid.
1434 FileInterfaceMemSetPosition(
1435 IN EFI_FILE_PROTOCOL
*This
,
1439 if (Position
<= ((EFI_FILE_PROTOCOL_MEM
*)This
)->FileSize
) {
1440 ((EFI_FILE_PROTOCOL_MEM
*)This
)->Position
= Position
;
1441 return (EFI_SUCCESS
);
1443 return (EFI_INVALID_PARAMETER
);
1448 File style interface for Mem (GetPosition).
1450 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1451 @param[out] Position The pointer to the position.
1453 @retval EFI_SUCCESS The position was retrieved.
1457 FileInterfaceMemGetPosition(
1458 IN EFI_FILE_PROTOCOL
*This
,
1459 OUT UINT64
*Position
1462 *Position
= ((EFI_FILE_PROTOCOL_MEM
*)This
)->Position
;
1463 return (EFI_SUCCESS
);
1467 File style interface for Mem (Write).
1469 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1470 @param[in, out] BufferSize Size in bytes of Buffer.
1471 @param[in] Buffer The pointer to the buffer to write.
1473 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.
1474 @retval EFI_SUCCESS The data was written.
1478 FileInterfaceMemWrite(
1479 IN EFI_FILE_PROTOCOL
*This
,
1480 IN OUT UINTN
*BufferSize
,
1485 EFI_FILE_PROTOCOL_MEM
*MemFile
;
1487 MemFile
= (EFI_FILE_PROTOCOL_MEM
*) This
;
1488 if (MemFile
->Unicode
) {
1492 if ((UINTN
)(MemFile
->Position
+ (*BufferSize
)) > (UINTN
)(MemFile
->BufferSize
)) {
1493 MemFile
->Buffer
= ReallocatePool((UINTN
)(MemFile
->BufferSize
), (UINTN
)(MemFile
->BufferSize
) + (*BufferSize
) + MEM_WRITE_REALLOC_OVERHEAD
, MemFile
->Buffer
);
1494 MemFile
->BufferSize
+= (*BufferSize
) + MEM_WRITE_REALLOC_OVERHEAD
;
1496 CopyMem(((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, Buffer
, *BufferSize
);
1497 MemFile
->Position
+= (*BufferSize
);
1498 MemFile
->FileSize
= MemFile
->Position
;
1499 return (EFI_SUCCESS
);
1504 AsciiBuffer
= AllocateZeroPool(*BufferSize
);
1505 if (AsciiBuffer
== NULL
) {
1506 return (EFI_OUT_OF_RESOURCES
);
1508 AsciiSPrint(AsciiBuffer
, *BufferSize
, "%S", Buffer
);
1509 if ((UINTN
)(MemFile
->Position
+ AsciiStrSize(AsciiBuffer
)) > (UINTN
)(MemFile
->BufferSize
)) {
1510 MemFile
->Buffer
= ReallocatePool((UINTN
)(MemFile
->BufferSize
), (UINTN
)(MemFile
->BufferSize
) + AsciiStrSize(AsciiBuffer
) + MEM_WRITE_REALLOC_OVERHEAD
, MemFile
->Buffer
);
1511 MemFile
->BufferSize
+= AsciiStrSize(AsciiBuffer
) + MEM_WRITE_REALLOC_OVERHEAD
;
1513 CopyMem(((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, AsciiBuffer
, AsciiStrSize(AsciiBuffer
));
1514 MemFile
->Position
+= (*BufferSize
/ sizeof(CHAR16
));
1515 MemFile
->FileSize
= MemFile
->Position
;
1516 FreePool(AsciiBuffer
);
1517 return (EFI_SUCCESS
);
1522 File style interface for Mem (Read).
1524 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1525 @param[in, out] BufferSize Size in bytes of Buffer.
1526 @param[in] Buffer The pointer to the buffer to fill.
1528 @retval EFI_SUCCESS The data was read.
1532 FileInterfaceMemRead(
1533 IN EFI_FILE_PROTOCOL
*This
,
1534 IN OUT UINTN
*BufferSize
,
1538 EFI_FILE_PROTOCOL_MEM
*MemFile
;
1540 MemFile
= (EFI_FILE_PROTOCOL_MEM
*) This
;
1541 if (*BufferSize
> (UINTN
)((MemFile
->FileSize
) - (UINTN
)(MemFile
->Position
))) {
1542 (*BufferSize
) = (UINTN
)((MemFile
->FileSize
) - (UINTN
)(MemFile
->Position
));
1544 CopyMem(Buffer
, ((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, (*BufferSize
));
1545 MemFile
->Position
= MemFile
->Position
+ (*BufferSize
);
1546 return (EFI_SUCCESS
);
1550 File style interface for Mem (Close).
1552 Frees all memory associated with this object.
1554 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1556 @retval EFI_SUCCESS The 'file' was closed.
1560 FileInterfaceMemClose(
1561 IN EFI_FILE_PROTOCOL
*This
1564 SHELL_FREE_NON_NULL(((EFI_FILE_PROTOCOL_MEM
*)This
)->Buffer
);
1565 SHELL_FREE_NON_NULL(This
);
1566 return (EFI_SUCCESS
);
1570 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1571 a file entirely in memory through file operations.
1573 @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii.
1575 @retval NULL Memory could not be allocated.
1576 @return other A pointer to an EFI_FILE_PROTOCOL structure.
1580 CreateFileInterfaceMem(
1581 IN CONST BOOLEAN Unicode
1584 EFI_FILE_PROTOCOL_MEM
*FileInterface
;
1589 FileInterface
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_MEM
));
1590 if (FileInterface
== NULL
){
1595 // Assign the generic members
1597 FileInterface
->Revision
= EFI_FILE_REVISION
;
1598 FileInterface
->Open
= FileInterfaceOpenNotFound
;
1599 FileInterface
->Close
= FileInterfaceMemClose
;
1600 FileInterface
->GetPosition
= FileInterfaceMemGetPosition
;
1601 FileInterface
->SetPosition
= FileInterfaceMemSetPosition
;
1602 FileInterface
->GetInfo
= FileInterfaceNopGetInfo
;
1603 FileInterface
->SetInfo
= FileInterfaceNopSetInfo
;
1604 FileInterface
->Flush
= FileInterfaceNopGeneric
;
1605 FileInterface
->Delete
= FileInterfaceNopGeneric
;
1606 FileInterface
->Read
= FileInterfaceMemRead
;
1607 FileInterface
->Write
= FileInterfaceMemWrite
;
1608 FileInterface
->Unicode
= Unicode
;
1610 ASSERT(FileInterface
->Buffer
== NULL
);
1611 ASSERT(FileInterface
->BufferSize
== 0);
1612 ASSERT(FileInterface
->Position
== 0);
1615 FileInterface
->Buffer
= AllocateZeroPool(sizeof(gUnicodeFileTag
));
1616 if (FileInterface
->Buffer
== NULL
) {
1617 FreePool (FileInterface
);
1620 *((CHAR16
*) (FileInterface
->Buffer
)) = EFI_UNICODE_BYTE_ORDER_MARK
;
1621 FileInterface
->BufferSize
= 2;
1622 FileInterface
->Position
= 2;
1625 return ((EFI_FILE_PROTOCOL
*)FileInterface
);
1631 EFI_FILE_CLOSE Close
;
1632 EFI_FILE_DELETE Delete
;
1634 EFI_FILE_WRITE Write
;
1635 EFI_FILE_GET_POSITION GetPosition
;
1636 EFI_FILE_SET_POSITION SetPosition
;
1637 EFI_FILE_GET_INFO GetInfo
;
1638 EFI_FILE_SET_INFO SetInfo
;
1639 EFI_FILE_FLUSH Flush
;
1641 EFI_FILE_PROTOCOL
*Orig
;
1642 } EFI_FILE_PROTOCOL_FILE
;
1645 Set a files current position
1647 @param This Protocol instance pointer.
1648 @param Position Byte position from the start of the file.
1650 @retval EFI_SUCCESS Data was written.
1651 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
1656 FileInterfaceFileSetPosition(
1657 IN EFI_FILE_PROTOCOL
*This
,
1661 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->SetPosition(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, Position
);
1665 Get a file's current position
1667 @param This Protocol instance pointer.
1668 @param Position Byte position from the start of the file.
1670 @retval EFI_SUCCESS Data was written.
1671 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
1676 FileInterfaceFileGetPosition(
1677 IN EFI_FILE_PROTOCOL
*This
,
1678 OUT UINT64
*Position
1681 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->GetPosition(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, Position
);
1685 Get information about a file.
1687 @param This Protocol instance pointer.
1688 @param InformationType Type of information to return in Buffer.
1689 @param BufferSize On input size of buffer, on output amount of data in buffer.
1690 @param Buffer The buffer to return data.
1692 @retval EFI_SUCCESS Data was returned.
1693 @retval EFI_UNSUPPORT InformationType is not supported.
1694 @retval EFI_NO_MEDIA The device has no media.
1695 @retval EFI_DEVICE_ERROR The device reported an error.
1696 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1697 @retval EFI_WRITE_PROTECTED The device is write protected.
1698 @retval EFI_ACCESS_DENIED The file was open for read only.
1699 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
1704 FileInterfaceFileGetInfo(
1705 IN EFI_FILE_PROTOCOL
*This
,
1706 IN EFI_GUID
*InformationType
,
1707 IN OUT UINTN
*BufferSize
,
1711 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->GetInfo(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, InformationType
, BufferSize
, Buffer
);
1715 Set information about a file
1717 @param This Protocol instance pointer.
1718 @param InformationType Type of information in Buffer.
1719 @param BufferSize Size of buffer.
1720 @param Buffer The data to write.
1722 @retval EFI_SUCCESS Data was returned.
1723 @retval EFI_UNSUPPORT InformationType is not supported.
1724 @retval EFI_NO_MEDIA The device has no media.
1725 @retval EFI_DEVICE_ERROR The device reported an error.
1726 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1727 @retval EFI_WRITE_PROTECTED The device is write protected.
1728 @retval EFI_ACCESS_DENIED The file was open for read only.
1733 FileInterfaceFileSetInfo(
1734 IN EFI_FILE_PROTOCOL
*This
,
1735 IN EFI_GUID
*InformationType
,
1736 IN UINTN BufferSize
,
1740 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->SetInfo(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, InformationType
, BufferSize
, Buffer
);
1744 Flush data back for the file handle.
1746 @param This Protocol instance pointer.
1748 @retval EFI_SUCCESS Data was written.
1749 @retval EFI_UNSUPPORT Writes to Open directory are not supported.
1750 @retval EFI_NO_MEDIA The device has no media.
1751 @retval EFI_DEVICE_ERROR The device reported an error.
1752 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1753 @retval EFI_WRITE_PROTECTED The device is write protected.
1754 @retval EFI_ACCESS_DENIED The file was open for read only.
1755 @retval EFI_VOLUME_FULL The volume is full.
1760 FileInterfaceFileFlush(
1761 IN EFI_FILE_PROTOCOL
*This
1764 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Flush(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1768 Read data from the file.
1770 @param This Protocol instance pointer.
1771 @param BufferSize On input size of buffer, on output amount of data in buffer.
1772 @param Buffer The buffer in which data is read.
1774 @retval EFI_SUCCESS Data was read.
1775 @retval EFI_NO_MEDIA The device has no media.
1776 @retval EFI_DEVICE_ERROR The device reported an error.
1777 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1778 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
1783 FileInterfaceFileRead(
1784 IN EFI_FILE_PROTOCOL
*This
,
1785 IN OUT UINTN
*BufferSize
,
1789 CHAR8
*AsciiStrBuffer
;
1790 CHAR16
*UscStrBuffer
;
1794 if (((EFI_FILE_PROTOCOL_FILE
*)This
)->Unicode
) {
1798 return (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Read(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, BufferSize
, Buffer
));
1803 Size
= (*BufferSize
) / sizeof(CHAR16
);
1804 AsciiStrBuffer
= AllocateZeroPool(Size
+ sizeof(CHAR8
));
1805 if (AsciiStrBuffer
== NULL
) {
1806 return EFI_OUT_OF_RESOURCES
;
1808 UscStrBuffer
= AllocateZeroPool(*BufferSize
+ sizeof(CHAR16
));
1809 if (UscStrBuffer
== NULL
) {
1810 SHELL_FREE_NON_NULL(AsciiStrBuffer
);
1811 return EFI_OUT_OF_RESOURCES
;
1813 Status
= (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Read(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, &Size
, AsciiStrBuffer
));
1814 if (!EFI_ERROR(Status
)) {
1815 CharNum
= UnicodeSPrint(UscStrBuffer
, *BufferSize
+ sizeof(CHAR16
), L
"%a", AsciiStrBuffer
);
1816 if (CharNum
== Size
) {
1817 CopyMem (Buffer
, UscStrBuffer
, *BufferSize
);
1819 Status
= EFI_UNSUPPORTED
;
1822 SHELL_FREE_NON_NULL(AsciiStrBuffer
);
1823 SHELL_FREE_NON_NULL(UscStrBuffer
);
1829 Opens a new file relative to the source file's location.
1831 @param[in] This The protocol instance pointer.
1832 @param[out] NewHandle Returns File Handle for FileName.
1833 @param[in] FileName Null terminated string. "\", ".", and ".." are supported.
1834 @param[in] OpenMode Open mode for file.
1835 @param[in] Attributes Only used for EFI_FILE_MODE_CREATE.
1837 @retval EFI_SUCCESS The device was opened.
1838 @retval EFI_NOT_FOUND The specified file could not be found on the device.
1839 @retval EFI_NO_MEDIA The device has no media.
1840 @retval EFI_MEDIA_CHANGED The media has changed.
1841 @retval EFI_DEVICE_ERROR The device reported an error.
1842 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1843 @retval EFI_ACCESS_DENIED The service denied access to the file.
1844 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
1845 @retval EFI_VOLUME_FULL The volume is full.
1849 FileInterfaceFileOpen (
1850 IN EFI_FILE_PROTOCOL
*This
,
1851 OUT EFI_FILE_PROTOCOL
**NewHandle
,
1852 IN CHAR16
*FileName
,
1854 IN UINT64 Attributes
1857 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Open(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, NewHandle
, FileName
, OpenMode
, Attributes
);
1861 Close and delete the file handle.
1863 @param This Protocol instance pointer.
1865 @retval EFI_SUCCESS The device was opened.
1866 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
1871 FileInterfaceFileDelete(
1872 IN EFI_FILE_PROTOCOL
*This
1876 Status
= ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Delete(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1882 File style interface for File (Close).
1884 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1886 @retval EFI_SUCCESS The file was closed.
1890 FileInterfaceFileClose(
1891 IN EFI_FILE_PROTOCOL
*This
1895 Status
= ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Close(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1901 File style interface for File (Write).
1903 If the file was opened with ASCII mode the data will be processed through
1904 AsciiSPrint before writing.
1906 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1907 @param[in, out] BufferSize Size in bytes of Buffer.
1908 @param[in] Buffer The pointer to the buffer to write.
1910 @retval EFI_SUCCESS The data was written.
1914 FileInterfaceFileWrite(
1915 IN EFI_FILE_PROTOCOL
*This
,
1916 IN OUT UINTN
*BufferSize
,
1923 if (((EFI_FILE_PROTOCOL_FILE
*)This
)->Unicode
) {
1927 return (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Write(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, BufferSize
, Buffer
));
1932 AsciiBuffer
= AllocateZeroPool(*BufferSize
);
1933 AsciiSPrint(AsciiBuffer
, *BufferSize
, "%S", Buffer
);
1934 Size
= AsciiStrSize(AsciiBuffer
) - 1; // (we dont need the null terminator)
1935 Status
= (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Write(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, &Size
, AsciiBuffer
));
1936 FreePool(AsciiBuffer
);
1942 Create a file interface with unicode information.
1944 This will create a new EFI_FILE_PROTOCOL identical to the Templace
1945 except that the new one has Unicode and Ascii knowledge.
1947 @param[in] Template A pointer to the EFI_FILE_PROTOCOL object.
1948 @param[in] Unicode TRUE for UCS-2, FALSE for ASCII.
1950 @return a new EFI_FILE_PROTOCOL object to be used instead of the template.
1953 CreateFileInterfaceFile(
1954 IN CONST EFI_FILE_PROTOCOL
*Template
,
1955 IN CONST BOOLEAN Unicode
1958 EFI_FILE_PROTOCOL_FILE
*NewOne
;
1960 NewOne
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_FILE
));
1961 if (NewOne
== NULL
) {
1964 CopyMem(NewOne
, Template
, sizeof(EFI_FILE_PROTOCOL_FILE
));
1965 NewOne
->Orig
= (EFI_FILE_PROTOCOL
*)Template
;
1966 NewOne
->Unicode
= Unicode
;
1967 NewOne
->Open
= FileInterfaceFileOpen
;
1968 NewOne
->Close
= FileInterfaceFileClose
;
1969 NewOne
->Delete
= FileInterfaceFileDelete
;
1970 NewOne
->Read
= FileInterfaceFileRead
;
1971 NewOne
->Write
= FileInterfaceFileWrite
;
1972 NewOne
->GetPosition
= FileInterfaceFileGetPosition
;
1973 NewOne
->SetPosition
= FileInterfaceFileSetPosition
;
1974 NewOne
->GetInfo
= FileInterfaceFileGetInfo
;
1975 NewOne
->SetInfo
= FileInterfaceFileSetInfo
;
1976 NewOne
->Flush
= FileInterfaceFileFlush
;
1978 return ((EFI_FILE_PROTOCOL
*)NewOne
);