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 - 2018, 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[in, out] TabCompletionList Return the TAB completion list.
302 @param[in, out] TabUpdatePos Return the TAB update position.
305 CreateTabCompletionList (
306 IN CONST CHAR16
*InputString
,
307 IN CONST UINTN StringLen
,
308 IN CONST UINTN BufferSize
,
309 IN OUT EFI_SHELL_FILE_INFO
**TabCompletionList
,
310 IN OUT UINTN
*TabUpdatePos
319 EFI_SHELL_FILE_INFO
*FileList
;
320 EFI_SHELL_FILE_INFO
*FileInfo
;
321 EFI_SHELL_FILE_INFO
*TempFileInfo
;
326 TabStr
= AllocateZeroPool (BufferSize
);
327 if (TabStr
== NULL
) {
328 return EFI_OUT_OF_RESOURCES
;
332 // handle auto complete of file and directory names...
333 // E.g.: cd fs0:\EFI\Bo<TAB>
335 // TabPos TabUpdatePos
341 for (Index
= 0; Index
< StringLen
; Index
++) {
342 switch (InputString
[Index
]) {
344 InQuotation
= (BOOLEAN
) (!InQuotation
);
350 *TabUpdatePos
= TabPos
;
356 // handle the case "fs0:<TAB>"
357 // Update the TabUpdatePos as well.
360 *TabUpdatePos
= Index
+ 1;
368 if (StrStr (InputString
+ TabPos
, L
":") == NULL
) {
370 // If file path doesn't contain ":", ...
372 Cwd
= ShellInfoObject
.NewEfiShellProtocol
->GetCurDir (NULL
);
374 if (InputString
[TabPos
] != L
'\\') {
376 // and it doesn't begin with "\\", it's a path relative to current directory.
377 // TabStr = "<cwd>\\"
379 StrnCpyS (TabStr
, BufferSize
/ sizeof (CHAR16
), Cwd
, (BufferSize
) / sizeof (CHAR16
) - 1);
380 StrCatS (TabStr
, (BufferSize
) / sizeof (CHAR16
), L
"\\");
383 // and it begins with "\\", it's a path pointing to root directory of current map.
386 Index
= StrStr (Cwd
, L
":") - Cwd
+ 1;
387 StrnCpyS (TabStr
, BufferSize
/ sizeof (CHAR16
), Cwd
, Index
);
391 StrnCatS (TabStr
, (BufferSize
) / sizeof (CHAR16
), InputString
+ TabPos
, StringLen
- TabPos
);
392 StrnCatS (TabStr
, (BufferSize
) / sizeof (CHAR16
), L
"*", (BufferSize
) / sizeof (CHAR16
) - 1 - StrLen (TabStr
));
393 Status
= ShellInfoObject
.NewEfiShellProtocol
->FindFiles(TabStr
, &FileList
);
396 // Filter out the non-directory for "CD" command
397 // Filter "." and ".." for all
399 if (!EFI_ERROR (Status
) && FileList
!= NULL
) {
401 // Skip the spaces in the beginning
403 while (*InputString
== L
' ') {
407 for (FileInfo
= (EFI_SHELL_FILE_INFO
*) GetFirstNode (&FileList
->Link
); !IsNull (&FileList
->Link
, &FileInfo
->Link
); ) {
408 if (((StrCmp (FileInfo
->FileName
, L
".") == 0) || (StrCmp (FileInfo
->FileName
, L
"..") == 0)) ||
409 (((InputString
[0] == L
'c' || InputString
[0] == L
'C') && (InputString
[1] == L
'd' || InputString
[1] == L
'D')) &&
410 (ShellIsDirectory (FileInfo
->FullName
) != EFI_SUCCESS
))) {
411 TempFileInfo
= FileInfo
;
412 FileInfo
= (EFI_SHELL_FILE_INFO
*) RemoveEntryList (&FileInfo
->Link
);
413 InternalFreeShellFileInfoNode (TempFileInfo
);
415 FileInfo
= (EFI_SHELL_FILE_INFO
*) GetNextNode (&FileList
->Link
, &FileInfo
->Link
);
420 if (FileList
!= NULL
&& !IsListEmpty (&FileList
->Link
)) {
421 Status
= EFI_SUCCESS
;
423 ShellInfoObject
.NewEfiShellProtocol
->FreeFileList (&FileList
);
424 Status
= EFI_NOT_FOUND
;
429 *TabCompletionList
= FileList
;
434 File style interface for console (Read).
436 This will return a single line of input from the console.
438 @param This A pointer to the EFI_FILE_PROTOCOL instance that is the
439 file handle to read data from. Not used.
440 @param BufferSize On input, the size of the Buffer. On output, the amount
441 of data returned in Buffer. In both cases, the size is
443 @param Buffer The buffer into which the data is read.
446 @retval EFI_SUCCESS The data was read.
447 @retval EFI_NO_MEDIA The device has no medium.
448 @retval EFI_DEVICE_ERROR The device reported an error.
449 @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file.
450 @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file.
451 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
452 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory
453 entry. BufferSize has been updated with the size
454 needed to complete the request.
455 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
459 FileInterfaceStdInRead(
460 IN EFI_FILE_PROTOCOL
*This
,
461 IN OUT UINTN
*BufferSize
,
465 CHAR16
*CurrentString
;
467 UINTN TabUpdatePos
; // Start index of the string updated by TAB stroke
468 UINTN Column
; // Column of current cursor
469 UINTN Row
; // Row of current cursor
470 UINTN StartColumn
; // Column at the beginning of the line
471 UINTN Update
; // Line index for update
472 UINTN Delete
; // Num of chars to delete from console after update
473 UINTN StringLen
; // Total length of the line
474 UINTN StringCurPos
; // Line index corresponding to the cursor
475 UINTN MaxStr
; // Maximum possible line length
476 UINTN TotalColumn
; // Num of columns in the console
477 UINTN TotalRow
; // Num of rows in the console
479 UINTN OutputLength
; // Length of the update string
480 UINTN TailRow
; // Row of end of line
481 UINTN TailColumn
; // Column of end of line
484 BUFFER_LIST
*LinePos
;
488 BOOLEAN InTabScrolling
; // Whether in TAB-completion state
489 EFI_SHELL_FILE_INFO
*TabCompleteList
;
490 EFI_SHELL_FILE_INFO
*TabCurrent
;
492 CHAR16
*TabOutputStr
;
495 // If buffer is not large enough to hold a CHAR16, return minimum buffer size
497 if (*BufferSize
< sizeof (CHAR16
) * 2) {
498 *BufferSize
= sizeof (CHAR16
) * 2;
499 return (EFI_BUFFER_TOO_SMALL
);
503 CurrentString
= Buffer
;
509 LinePos
= NewPos
= (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
);
511 InTabScrolling
= FALSE
;
512 Status
= EFI_SUCCESS
;
515 TabCompleteList
= NULL
;
519 // Get the screen setting and the current cursor location
521 Column
= StartColumn
= gST
->ConOut
->Mode
->CursorColumn
;
522 Row
= gST
->ConOut
->Mode
->CursorRow
;
523 gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &TotalColumn
, &TotalRow
);
526 // Limit the line length to the buffer size or the minimun size of the
527 // screen. (The smaller takes effect)
529 MaxStr
= TotalColumn
* (TotalRow
- 1) - StartColumn
;
530 if (MaxStr
> *BufferSize
/ sizeof (CHAR16
)) {
531 MaxStr
= *BufferSize
/ sizeof (CHAR16
);
533 ZeroMem (CurrentString
, MaxStr
* sizeof (CHAR16
));
538 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &EventIndex
);
539 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
540 if (EFI_ERROR (Status
)) {
542 if (Status
== EFI_NOT_READY
)
545 ZeroMem (CurrentString
, MaxStr
* sizeof(CHAR16
));
551 // Press PageUp or PageDown to scroll the history screen up or down.
552 // Press any other key to quit scrolling.
554 if (Key
.UnicodeChar
== 0 && (Key
.ScanCode
== SCAN_PAGE_UP
|| Key
.ScanCode
== SCAN_PAGE_DOWN
)) {
555 if (Key
.ScanCode
== SCAN_PAGE_UP
) {
556 ConsoleLoggerDisplayHistory(FALSE
, 0, ShellInfoObject
.ConsoleInfo
);
557 } else if (Key
.ScanCode
== SCAN_PAGE_DOWN
) {
558 ConsoleLoggerDisplayHistory(TRUE
, 0, ShellInfoObject
.ConsoleInfo
);
564 ConsoleLoggerStopHistory(ShellInfoObject
.ConsoleInfo
);
570 // If we are quitting TAB scrolling...
572 if (InTabScrolling
&& Key
.UnicodeChar
!= CHAR_TAB
) {
573 if (TabCompleteList
!= NULL
) {
574 ShellInfoObject
.NewEfiShellProtocol
->FreeFileList (&TabCompleteList
);
575 DEBUG_CODE(TabCompleteList
= NULL
;);
577 InTabScrolling
= FALSE
;
580 switch (Key
.UnicodeChar
) {
581 case CHAR_CARRIAGE_RETURN
:
583 // All done, print a newline at the end of the string
585 TailRow
= Row
+ (StringLen
- StringCurPos
+ Column
) / TotalColumn
;
586 TailColumn
= (StringLen
- StringCurPos
+ Column
) % TotalColumn
;
587 ShellPrintEx ((INT32
)TailColumn
, (INT32
)TailRow
, L
"%N\n");
592 if (StringCurPos
!= 0) {
594 // If not move back beyond string beginning, move all characters behind
595 // the current position one character forward
598 Update
= StringCurPos
;
600 CopyMem (CurrentString
+ StringCurPos
, CurrentString
+ StringCurPos
+ 1, sizeof (CHAR16
) * (StringLen
- StringCurPos
));
603 // Adjust the current column and row
605 MoveCursorBackward (TotalColumn
, &Column
, &Row
);
610 if (!InTabScrolling
) {
613 // Initialize a tab complete operation.
615 Status
= CreateTabCompletionList (CurrentString
, StringLen
, *BufferSize
, &TabCompleteList
, &TabUpdatePos
);
616 if (!EFI_ERROR(Status
)) {
617 InTabScrolling
= TRUE
;
621 // We do not set up the replacement.
622 // The next section will do that.
626 if (InTabScrolling
) {
628 // We are in a tab complete operation.
629 // set up the next replacement.
631 ASSERT(TabCompleteList
!= NULL
);
632 if (TabCurrent
== NULL
) {
633 TabCurrent
= (EFI_SHELL_FILE_INFO
*) GetFirstNode (&TabCompleteList
->Link
);
635 TabCurrent
= (EFI_SHELL_FILE_INFO
*) GetNextNode (&TabCompleteList
->Link
, &TabCurrent
->Link
);
639 // Skip over the empty list beginning node
641 if (IsNull(&TabCompleteList
->Link
, &TabCurrent
->Link
)) {
642 TabCurrent
= (EFI_SHELL_FILE_INFO
*) GetNextNode (&TabCompleteList
->Link
, &TabCurrent
->Link
);
648 if (Key
.UnicodeChar
>= ' ') {
650 // If we are at the buffer's end, drop the key
652 if (StringLen
== MaxStr
- 1 && (ShellInfoObject
.ViewingSettings
.InsertMode
|| StringCurPos
== StringLen
)) {
656 // If in insert mode, make space by moving each other character 1
657 // space higher in the array
659 if (ShellInfoObject
.ViewingSettings
.InsertMode
) {
660 CopyMem(CurrentString
+ StringCurPos
+ 1, CurrentString
+ StringCurPos
, (StringLen
- StringCurPos
)*sizeof(CurrentString
[0]));
663 CurrentString
[StringCurPos
] = Key
.UnicodeChar
;
664 Update
= StringCurPos
;
672 switch (Key
.ScanCode
) {
675 // Move characters behind current position one character forward
677 if (StringLen
!= 0) {
678 Update
= StringCurPos
;
680 CopyMem (CurrentString
+ StringCurPos
, CurrentString
+ StringCurPos
+ 1, sizeof (CHAR16
) * (StringLen
- StringCurPos
));
686 // Prepare to print the previous command
688 NewPos
= (BUFFER_LIST
*)GetPreviousNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
689 if (IsNull(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
)) {
690 NewPos
= (BUFFER_LIST
*)GetPreviousNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
696 // Prepare to print the next command
698 NewPos
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
699 if (NewPos
== (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
)) {
700 NewPos
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
706 // Adjust current cursor position
708 if (StringCurPos
!= 0) {
710 MoveCursorBackward (TotalColumn
, &Column
, &Row
);
716 // Adjust current cursor position
718 if (StringCurPos
< StringLen
) {
720 MoveCursorForward (TotalColumn
, TotalRow
, &Column
, &Row
);
726 // Move current cursor position to the beginning of the command line
728 Row
-= (StringCurPos
+ StartColumn
) / TotalColumn
;
729 Column
= StartColumn
;
735 // Move current cursor position to the end of the command line
737 TailRow
= Row
+ (StringLen
- StringCurPos
+ Column
) / TotalColumn
;
738 TailColumn
= (StringLen
- StringCurPos
+ Column
) % TotalColumn
;
741 StringCurPos
= StringLen
;
746 // Prepare to clear the current command line
748 CurrentString
[0] = 0;
751 Row
-= (StringCurPos
+ StartColumn
) / TotalColumn
;
752 Column
= StartColumn
;
758 // Toggle the SEnvInsertMode flag
760 ShellInfoObject
.ViewingSettings
.InsertMode
= (BOOLEAN
)!ShellInfoObject
.ViewingSettings
.InsertMode
;
765 // Print command history
767 PrintCommandHistory (TotalColumn
, TotalRow
, 4);
768 *CurrentString
= CHAR_NULL
;
779 // If we are in auto-complete mode, we are preparing to print
780 // the next file or directory name
782 if (InTabScrolling
) {
783 TabOutputStr
= AllocateZeroPool (*BufferSize
);
784 if (TabOutputStr
== NULL
) {
785 Status
= EFI_OUT_OF_RESOURCES
;
789 if (InTabScrolling
&& TabOutputStr
!= NULL
) {
792 // Adjust the column and row to the start of TAB-completion string.
794 Column
= (StartColumn
+ TabUpdatePos
) % TotalColumn
;
795 Row
-= (StartColumn
+ StringCurPos
) / TotalColumn
- (StartColumn
+ TabUpdatePos
) / TotalColumn
;
796 OutputLength
= StrLen (TabCurrent
->FileName
);
798 // if the output string contains blank space, quotation marks L'\"'
799 // should be added to the output.
801 if (StrStr(TabCurrent
->FileName
, L
" ") != NULL
){
802 TabOutputStr
[0] = L
'\"';
803 CopyMem (TabOutputStr
+ 1, TabCurrent
->FileName
, OutputLength
* sizeof (CHAR16
));
804 TabOutputStr
[OutputLength
+ 1] = L
'\"';
805 TabOutputStr
[OutputLength
+ 2] = CHAR_NULL
;
807 CopyMem (TabOutputStr
, TabCurrent
->FileName
, OutputLength
* sizeof (CHAR16
));
808 TabOutputStr
[OutputLength
] = CHAR_NULL
;
810 OutputLength
= StrLen (TabOutputStr
) < MaxStr
- 1 ? StrLen (TabOutputStr
) : MaxStr
- 1;
811 CopyMem (CurrentString
+ TabUpdatePos
, TabOutputStr
, OutputLength
* sizeof (CHAR16
));
812 CurrentString
[TabUpdatePos
+ OutputLength
] = CHAR_NULL
;
813 StringCurPos
= TabUpdatePos
+ OutputLength
;
814 Update
= TabUpdatePos
;
815 if (StringLen
> TabUpdatePos
+ OutputLength
) {
816 Delete
= StringLen
- TabUpdatePos
- OutputLength
;
819 FreePool(TabOutputStr
);
823 // If we have a new position, we are preparing to print a previous or
826 if (NewPos
!= (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
)) {
827 Column
= StartColumn
;
828 Row
-= (StringCurPos
+ StartColumn
) / TotalColumn
;
831 NewPos
= (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
);
833 OutputLength
= StrLen (LinePos
->Buffer
) < MaxStr
- 1 ? StrLen (LinePos
->Buffer
) : MaxStr
- 1;
834 CopyMem (CurrentString
, LinePos
->Buffer
, OutputLength
* sizeof (CHAR16
));
835 CurrentString
[OutputLength
] = CHAR_NULL
;
837 StringCurPos
= OutputLength
;
840 // Draw new input string
843 if (StringLen
> OutputLength
) {
845 // If old string was longer, blank its tail
847 Delete
= StringLen
- OutputLength
;
851 // If we need to update the output do so now
853 if (Update
!= (UINTN
) -1) {
854 ShellPrintEx ((INT32
)Column
, (INT32
)Row
, L
"%s%.*s", CurrentString
+ Update
, Delete
, L
"");
855 StringLen
= StrLen (CurrentString
);
858 SetMem (CurrentString
+ StringLen
, Delete
* sizeof (CHAR16
), CHAR_NULL
);
861 if (StringCurPos
> StringLen
) {
862 StringCurPos
= StringLen
;
868 // After using print to reflect newly updates, if we're not using
869 // BACKSPACE and DELETE, we need to move the cursor position forward,
870 // so adjust row and column here.
872 if (Key
.UnicodeChar
!= CHAR_BACKSPACE
&& !(Key
.UnicodeChar
== 0 && Key
.ScanCode
== SCAN_DELETE
)) {
874 // Calulate row and column of the tail of current string
876 TailRow
= Row
+ (StringLen
- StringCurPos
+ Column
+ OutputLength
) / TotalColumn
;
877 TailColumn
= (StringLen
- StringCurPos
+ Column
+ OutputLength
) % TotalColumn
;
880 // If the tail of string reaches screen end, screen rolls up, so if
881 // Row does not equal TailRow, Row should be decremented
883 // (if we are recalling commands using UPPER and DOWN key, and if the
884 // old command is too long to fit the screen, TailColumn must be 79.
886 if (TailColumn
== 0 && TailRow
>= TotalRow
&& Row
!= TailRow
) {
890 // Calculate the cursor position after current operation. If cursor
891 // reaches line end, update both row and column, otherwise, only
892 // column will be changed.
894 if (Column
+ OutputLength
>= TotalColumn
) {
895 SkipLength
= OutputLength
- (TotalColumn
- Column
);
897 Row
+= SkipLength
/ TotalColumn
+ 1;
898 if (Row
> TotalRow
- 1) {
902 Column
= SkipLength
% TotalColumn
;
904 Column
+= OutputLength
;
911 // Set the cursor position for this key
913 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, Column
, Row
);
916 if (CurrentString
!= NULL
&& StrLen(CurrentString
) > 0) {
918 // add the line to the history buffer
920 AddLineToCommandHistory(CurrentString
);
924 // Return the data to the caller
926 *BufferSize
= StringLen
* sizeof (CHAR16
);
929 // if this was used it should be deallocated by now...
930 // prevent memory leaks...
932 if (TabCompleteList
!= NULL
) {
933 ShellInfoObject
.NewEfiShellProtocol
->FreeFileList (&TabCompleteList
);
935 ASSERT(TabCompleteList
== NULL
);
941 // FILE sytle interfaces for StdIn/StdOut/StdErr
943 EFI_FILE_PROTOCOL FileInterfaceStdIn
= {
945 FileInterfaceOpenNotFound
,
946 FileInterfaceNopGeneric
,
947 FileInterfaceNopGeneric
,
948 FileInterfaceStdInRead
,
949 FileInterfaceStdInWrite
,
950 FileInterfaceNopGetPosition
,
951 FileInterfaceNopSetPosition
,
952 FileInterfaceNopGetInfo
,
953 FileInterfaceNopSetInfo
,
954 FileInterfaceNopGeneric
957 EFI_FILE_PROTOCOL FileInterfaceStdOut
= {
959 FileInterfaceOpenNotFound
,
960 FileInterfaceNopGeneric
,
961 FileInterfaceNopGeneric
,
962 FileInterfaceStdOutRead
,
963 FileInterfaceStdOutWrite
,
964 FileInterfaceNopGetPosition
,
965 FileInterfaceNopSetPosition
,
966 FileInterfaceNopGetInfo
,
967 FileInterfaceNopSetInfo
,
968 FileInterfaceNopGeneric
971 EFI_FILE_PROTOCOL FileInterfaceStdErr
= {
973 FileInterfaceOpenNotFound
,
974 FileInterfaceNopGeneric
,
975 FileInterfaceNopGeneric
,
976 FileInterfaceStdErrRead
,
977 FileInterfaceStdErrWrite
,
978 FileInterfaceNopGetPosition
,
979 FileInterfaceNopSetPosition
,
980 FileInterfaceNopGetInfo
,
981 FileInterfaceNopSetInfo
,
982 FileInterfaceNopGeneric
985 EFI_FILE_PROTOCOL FileInterfaceNulFile
= {
987 FileInterfaceOpenNotFound
,
988 FileInterfaceNopGeneric
,
989 FileInterfaceNopGeneric
,
990 FileInterfaceNulRead
,
991 FileInterfaceNulWrite
,
992 FileInterfaceNopGetPosition
,
993 FileInterfaceNopSetPosition
,
994 FileInterfaceNopGetInfo
,
995 FileInterfaceNopSetInfo
,
996 FileInterfaceNopGeneric
1003 // This is identical to EFI_FILE_PROTOCOL except for the additional member
1010 EFI_FILE_CLOSE Close
;
1011 EFI_FILE_DELETE Delete
;
1013 EFI_FILE_WRITE Write
;
1014 EFI_FILE_GET_POSITION GetPosition
;
1015 EFI_FILE_SET_POSITION SetPosition
;
1016 EFI_FILE_GET_INFO GetInfo
;
1017 EFI_FILE_SET_INFO SetInfo
;
1018 EFI_FILE_FLUSH Flush
;
1020 } EFI_FILE_PROTOCOL_ENVIRONMENT
;
1021 //ANSI compliance helper to get size of the struct.
1022 #define SIZE_OF_EFI_FILE_PROTOCOL_ENVIRONMENT EFI_FIELD_OFFSET (EFI_FILE_PROTOCOL_ENVIRONMENT, Name)
1025 File style interface for Environment Variable (Close).
1027 Frees the memory for this object.
1029 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1035 FileInterfaceEnvClose(
1036 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
1055 Status
= IsVolatileEnv (((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &Volatile
);
1056 if (EFI_ERROR (Status
)) {
1060 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1061 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1062 TotalSize
= NewSize
+ sizeof (CHAR16
);
1063 NewBuffer
= AllocateZeroPool (TotalSize
);
1064 if (NewBuffer
== NULL
) {
1065 return EFI_OUT_OF_RESOURCES
;
1067 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1070 if (!EFI_ERROR(Status
) && NewBuffer
!= NULL
) {
1072 if (TotalSize
/ sizeof (CHAR16
) >= 3) {
1073 if ( (((CHAR16
*)NewBuffer
)[TotalSize
/ sizeof (CHAR16
) - 2] == CHAR_LINEFEED
) &&
1074 (((CHAR16
*)NewBuffer
)[TotalSize
/ sizeof (CHAR16
) - 3] == CHAR_CARRIAGE_RETURN
)
1076 ((CHAR16
*)NewBuffer
)[TotalSize
/ sizeof (CHAR16
) - 3] = CHAR_NULL
;
1078 // If the NewBuffer end with \r\n\0, We will repace '\r' by '\0' and then update TotalSize.
1080 TotalSize
-= sizeof(CHAR16
) * 2;
1084 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_V (
1085 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1086 TotalSize
- sizeof (CHAR16
),
1090 if (!EFI_ERROR(Status
)) {
1091 Status
= ShellAddEnvVarToList (
1092 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1095 EFI_VARIABLE_BOOTSERVICE_ACCESS
1099 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_NV (
1100 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1101 TotalSize
- sizeof (CHAR16
),
1105 if (!EFI_ERROR(Status
)) {
1106 Status
= ShellAddEnvVarToList (
1107 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1110 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
1117 SHELL_FREE_NON_NULL(NewBuffer
);
1118 FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
);
1123 File style interface for Environment Variable (Delete).
1125 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1127 @retval The return value from FileInterfaceEnvClose().
1131 FileInterfaceEnvDelete(
1132 IN EFI_FILE_PROTOCOL
*This
1135 SHELL_DELETE_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
);
1136 return (FileInterfaceEnvClose(This
));
1140 File style interface for Environment Variable (Read).
1142 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1143 @param[in, out] BufferSize Size in bytes of Buffer.
1144 @param[out] Buffer The pointer to the buffer to fill.
1146 @retval EFI_SUCCESS The data was read.
1150 FileInterfaceEnvRead(
1151 IN EFI_FILE_PROTOCOL
*This
,
1152 IN OUT UINTN
*BufferSize
,
1156 return (SHELL_GET_ENVIRONMENT_VARIABLE(
1157 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1163 File style interface for Volatile Environment Variable (Write).
1164 This function also caches the environment variable into gShellEnvVarList.
1166 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1167 @param[in, out] BufferSize Size in bytes of Buffer.
1168 @param[in] Buffer The pointer to the buffer to write.
1170 @retval EFI_SUCCESS The data was successfully write to variable.
1171 @retval SHELL_OUT_OF_RESOURCES A memory allocation failed.
1175 FileInterfaceEnvVolWrite(
1176 IN EFI_FILE_PROTOCOL
*This
,
1177 IN OUT UINTN
*BufferSize
,
1190 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1191 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1192 TotalSize
= NewSize
+ *BufferSize
+ sizeof (CHAR16
);
1193 } else if (Status
== EFI_NOT_FOUND
) {
1194 TotalSize
= *BufferSize
+ sizeof(CHAR16
);
1199 NewBuffer
= AllocateZeroPool (TotalSize
);
1200 if (NewBuffer
== NULL
) {
1201 return EFI_OUT_OF_RESOURCES
;
1204 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1205 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1208 if (EFI_ERROR (Status
) && Status
!= EFI_NOT_FOUND
) {
1209 FreePool (NewBuffer
);
1213 CopyMem ((UINT8
*)NewBuffer
+ NewSize
, Buffer
, *BufferSize
);
1214 Status
= ShellAddEnvVarToList (
1215 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1218 EFI_VARIABLE_BOOTSERVICE_ACCESS
1220 if (EFI_ERROR(Status
)) {
1221 FreePool (NewBuffer
);
1225 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_V (
1226 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1227 TotalSize
- sizeof (CHAR16
),
1230 if (EFI_ERROR(Status
)) {
1231 ShellRemvoeEnvVarFromList (((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
);
1234 FreePool (NewBuffer
);
1240 File style interface for Non Volatile Environment Variable (Write).
1241 This function also caches the environment variable into gShellEnvVarList.
1243 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1244 @param[in, out] BufferSize Size in bytes of Buffer.
1245 @param[in] Buffer The pointer to the buffer to write.
1247 @retval EFI_SUCCESS The data was successfully write to variable.
1248 @retval SHELL_OUT_OF_RESOURCES A memory allocation failed.
1252 FileInterfaceEnvNonVolWrite(
1253 IN EFI_FILE_PROTOCOL
*This
,
1254 IN OUT UINTN
*BufferSize
,
1267 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1268 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1269 TotalSize
= NewSize
+ *BufferSize
+ sizeof (CHAR16
);
1270 } else if (Status
== EFI_NOT_FOUND
) {
1271 TotalSize
= *BufferSize
+ sizeof (CHAR16
);
1276 NewBuffer
= AllocateZeroPool (TotalSize
);
1277 if (NewBuffer
== NULL
) {
1278 return EFI_OUT_OF_RESOURCES
;
1281 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1282 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1285 if (EFI_ERROR(Status
) && Status
!= EFI_NOT_FOUND
) {
1286 FreePool (NewBuffer
);
1290 CopyMem ((UINT8
*) NewBuffer
+ NewSize
, Buffer
, *BufferSize
);
1291 Status
= ShellAddEnvVarToList (
1292 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1295 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
1297 if (EFI_ERROR (Status
)) {
1298 FreePool (NewBuffer
);
1302 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_NV (
1303 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1304 TotalSize
- sizeof (CHAR16
),
1307 if (EFI_ERROR (Status
)) {
1308 ShellRemvoeEnvVarFromList (((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
);
1311 FreePool (NewBuffer
);
1316 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1317 environment variables through file operations.
1319 @param EnvName The name of the Environment Variable to be operated on.
1321 @retval NULL Memory could not be allocated.
1322 @return other a pointer to an EFI_FILE_PROTOCOL structure
1325 CreateFileInterfaceEnv(
1326 IN CONST CHAR16
*EnvName
1330 EFI_FILE_PROTOCOL_ENVIRONMENT
*EnvFileInterface
;
1334 if (EnvName
== NULL
) {
1338 Status
= IsVolatileEnv (EnvName
, &Volatile
);
1339 if (EFI_ERROR (Status
)) {
1346 EnvNameSize
= StrSize(EnvName
);
1347 EnvFileInterface
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT
)+EnvNameSize
);
1348 if (EnvFileInterface
== NULL
){
1353 // Assign the generic members
1355 EnvFileInterface
->Revision
= EFI_FILE_REVISION
;
1356 EnvFileInterface
->Open
= FileInterfaceOpenNotFound
;
1357 EnvFileInterface
->Close
= FileInterfaceEnvClose
;
1358 EnvFileInterface
->GetPosition
= FileInterfaceNopGetPosition
;
1359 EnvFileInterface
->SetPosition
= FileInterfaceNopSetPosition
;
1360 EnvFileInterface
->GetInfo
= FileInterfaceNopGetInfo
;
1361 EnvFileInterface
->SetInfo
= FileInterfaceNopSetInfo
;
1362 EnvFileInterface
->Flush
= FileInterfaceNopGeneric
;
1363 EnvFileInterface
->Delete
= FileInterfaceEnvDelete
;
1364 EnvFileInterface
->Read
= FileInterfaceEnvRead
;
1366 CopyMem(EnvFileInterface
->Name
, EnvName
, EnvNameSize
);
1369 // Assign the different members for Volatile and Non-Volatile variables
1372 EnvFileInterface
->Write
= FileInterfaceEnvVolWrite
;
1374 EnvFileInterface
->Write
= FileInterfaceEnvNonVolWrite
;
1376 return ((EFI_FILE_PROTOCOL
*)EnvFileInterface
);
1380 Move the cursor position one character backward.
1382 @param[in] LineLength Length of a line. Get it by calling QueryMode
1383 @param[in, out] Column Current column of the cursor position
1384 @param[in, out] Row Current row of the cursor position
1387 MoveCursorBackward (
1388 IN UINTN LineLength
,
1389 IN OUT UINTN
*Column
,
1394 // If current column is 0, move to the last column of the previous line,
1395 // otherwise, just decrement column.
1398 *Column
= LineLength
- 1;
1408 Move the cursor position one character forward.
1410 @param[in] LineLength Length of a line.
1411 @param[in] TotalRow Total row of a screen
1412 @param[in, out] Column Current column of the cursor position
1413 @param[in, out] Row Current row of the cursor position
1417 IN UINTN LineLength
,
1419 IN OUT UINTN
*Column
,
1424 // Increment Column.
1425 // If this puts column past the end of the line, move to first column
1429 if (*Column
>= LineLength
) {
1431 if ((*Row
) < TotalRow
- 1) {
1438 Prints out each previously typed command in the command list history log.
1440 When each screen is full it will pause for a key before continuing.
1442 @param[in] TotalCols How many columns are on the screen
1443 @param[in] TotalRows How many rows are on the screen
1444 @param[in] StartColumn which column to start at
1447 PrintCommandHistory (
1448 IN CONST UINTN TotalCols
,
1449 IN CONST UINTN TotalRows
,
1450 IN CONST UINTN StartColumn
1458 ShellPrintEx (-1, -1, L
"\n");
1462 // go through history list...
1464 for ( Node
= (BUFFER_LIST
*)GetFirstNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
)
1465 ; !IsNull(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &Node
->Link
)
1466 ; Node
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &Node
->Link
)
1469 LineCount
= ((StrLen (Node
->Buffer
) + StartColumn
+ 1) / TotalCols
) + 1;
1471 if (LineNumber
+ LineCount
>= TotalRows
) {
1472 ShellPromptForResponseHii(
1473 ShellPromptResponseTypeEnterContinue
,
1474 STRING_TOKEN (STR_SHELL_ENTER_TO_CONT
),
1475 ShellInfoObject
.HiiHandle
,
1480 ShellPrintEx (-1, -1, L
"%2d. %s\n", Index
, Node
->Buffer
);
1481 LineNumber
+= LineCount
;
1491 // This is identical to EFI_FILE_PROTOCOL except for the additional members
1492 // for the buffer, size, and position.
1498 EFI_FILE_CLOSE Close
;
1499 EFI_FILE_DELETE Delete
;
1501 EFI_FILE_WRITE Write
;
1502 EFI_FILE_GET_POSITION GetPosition
;
1503 EFI_FILE_SET_POSITION SetPosition
;
1504 EFI_FILE_GET_INFO GetInfo
;
1505 EFI_FILE_SET_INFO SetInfo
;
1506 EFI_FILE_FLUSH Flush
;
1512 } EFI_FILE_PROTOCOL_MEM
;
1515 File style interface for Mem (SetPosition).
1517 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1518 @param[out] Position The position to set.
1520 @retval EFI_SUCCESS The position was successfully changed.
1521 @retval EFI_INVALID_PARAMETER The Position was invalid.
1525 FileInterfaceMemSetPosition(
1526 IN EFI_FILE_PROTOCOL
*This
,
1530 if (Position
<= ((EFI_FILE_PROTOCOL_MEM
*)This
)->FileSize
) {
1531 ((EFI_FILE_PROTOCOL_MEM
*)This
)->Position
= Position
;
1532 return (EFI_SUCCESS
);
1534 return (EFI_INVALID_PARAMETER
);
1539 File style interface for Mem (GetPosition).
1541 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1542 @param[out] Position The pointer to the position.
1544 @retval EFI_SUCCESS The position was retrieved.
1548 FileInterfaceMemGetPosition(
1549 IN EFI_FILE_PROTOCOL
*This
,
1550 OUT UINT64
*Position
1553 *Position
= ((EFI_FILE_PROTOCOL_MEM
*)This
)->Position
;
1554 return (EFI_SUCCESS
);
1558 File style interface for Mem (GetInfo).
1560 @param This Protocol instance pointer.
1561 @param InformationType Type of information to return in Buffer.
1562 @param BufferSize On input size of buffer, on output amount of data in buffer.
1563 @param Buffer The buffer to return data.
1565 @retval EFI_SUCCESS Data was returned.
1566 @retval EFI_UNSUPPORT InformationType is not supported.
1567 @retval EFI_NO_MEDIA The device has no media.
1568 @retval EFI_DEVICE_ERROR The device reported an error.
1569 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1570 @retval EFI_WRITE_PROTECTED The device is write protected.
1571 @retval EFI_ACCESS_DENIED The file was open for read only.
1572 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
1577 FileInterfaceMemGetInfo(
1578 IN EFI_FILE_PROTOCOL
*This
,
1579 IN EFI_GUID
*InformationType
,
1580 IN OUT UINTN
*BufferSize
,
1584 EFI_FILE_INFO
*FileInfo
;
1586 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1587 if (*BufferSize
< sizeof (EFI_FILE_INFO
)) {
1588 *BufferSize
= sizeof (EFI_FILE_INFO
);
1589 return EFI_BUFFER_TOO_SMALL
;
1591 if (Buffer
== NULL
) {
1592 return EFI_INVALID_PARAMETER
;
1594 FileInfo
= (EFI_FILE_INFO
*)Buffer
;
1595 FileInfo
->Size
= sizeof (*FileInfo
);
1596 ZeroMem (FileInfo
, sizeof (*FileInfo
));
1597 FileInfo
->FileSize
= ((EFI_FILE_PROTOCOL_MEM
*)This
)->FileSize
;
1598 FileInfo
->PhysicalSize
= FileInfo
->FileSize
;
1602 return EFI_UNSUPPORTED
;
1606 File style interface for Mem (Write).
1608 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1609 @param[in, out] BufferSize Size in bytes of Buffer.
1610 @param[in] Buffer The pointer to the buffer to write.
1612 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.
1613 @retval EFI_SUCCESS The data was written.
1617 FileInterfaceMemWrite(
1618 IN EFI_FILE_PROTOCOL
*This
,
1619 IN OUT UINTN
*BufferSize
,
1624 EFI_FILE_PROTOCOL_MEM
*MemFile
;
1626 MemFile
= (EFI_FILE_PROTOCOL_MEM
*) This
;
1627 if (MemFile
->Unicode
) {
1631 if ((UINTN
)(MemFile
->Position
+ (*BufferSize
)) > (UINTN
)(MemFile
->BufferSize
)) {
1632 MemFile
->Buffer
= ReallocatePool((UINTN
)(MemFile
->BufferSize
), (UINTN
)(MemFile
->BufferSize
) + (*BufferSize
) + MEM_WRITE_REALLOC_OVERHEAD
, MemFile
->Buffer
);
1633 MemFile
->BufferSize
+= (*BufferSize
) + MEM_WRITE_REALLOC_OVERHEAD
;
1635 CopyMem(((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, Buffer
, *BufferSize
);
1636 MemFile
->Position
+= (*BufferSize
);
1637 MemFile
->FileSize
= MemFile
->Position
;
1638 return (EFI_SUCCESS
);
1643 AsciiBuffer
= AllocateZeroPool(*BufferSize
);
1644 if (AsciiBuffer
== NULL
) {
1645 return (EFI_OUT_OF_RESOURCES
);
1647 AsciiSPrint(AsciiBuffer
, *BufferSize
, "%S", Buffer
);
1648 if ((UINTN
)(MemFile
->Position
+ AsciiStrSize(AsciiBuffer
)) > (UINTN
)(MemFile
->BufferSize
)) {
1649 MemFile
->Buffer
= ReallocatePool((UINTN
)(MemFile
->BufferSize
), (UINTN
)(MemFile
->BufferSize
) + AsciiStrSize(AsciiBuffer
) + MEM_WRITE_REALLOC_OVERHEAD
, MemFile
->Buffer
);
1650 MemFile
->BufferSize
+= AsciiStrSize(AsciiBuffer
) + MEM_WRITE_REALLOC_OVERHEAD
;
1652 CopyMem(((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, AsciiBuffer
, AsciiStrSize(AsciiBuffer
));
1653 MemFile
->Position
+= (*BufferSize
/ sizeof(CHAR16
));
1654 MemFile
->FileSize
= MemFile
->Position
;
1655 FreePool(AsciiBuffer
);
1656 return (EFI_SUCCESS
);
1661 File style interface for Mem (Read).
1663 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1664 @param[in, out] BufferSize Size in bytes of Buffer.
1665 @param[in] Buffer The pointer to the buffer to fill.
1667 @retval EFI_SUCCESS The data was read.
1671 FileInterfaceMemRead(
1672 IN EFI_FILE_PROTOCOL
*This
,
1673 IN OUT UINTN
*BufferSize
,
1677 EFI_FILE_PROTOCOL_MEM
*MemFile
;
1679 MemFile
= (EFI_FILE_PROTOCOL_MEM
*) This
;
1680 if (*BufferSize
> (UINTN
)((MemFile
->FileSize
) - (UINTN
)(MemFile
->Position
))) {
1681 (*BufferSize
) = (UINTN
)((MemFile
->FileSize
) - (UINTN
)(MemFile
->Position
));
1683 CopyMem(Buffer
, ((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, (*BufferSize
));
1684 MemFile
->Position
= MemFile
->Position
+ (*BufferSize
);
1685 return (EFI_SUCCESS
);
1689 File style interface for Mem (Close).
1691 Frees all memory associated with this object.
1693 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1695 @retval EFI_SUCCESS The 'file' was closed.
1699 FileInterfaceMemClose(
1700 IN EFI_FILE_PROTOCOL
*This
1703 SHELL_FREE_NON_NULL(((EFI_FILE_PROTOCOL_MEM
*)This
)->Buffer
);
1704 SHELL_FREE_NON_NULL(This
);
1705 return (EFI_SUCCESS
);
1709 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1710 a file entirely in memory through file operations.
1712 @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii.
1714 @retval NULL Memory could not be allocated.
1715 @return other A pointer to an EFI_FILE_PROTOCOL structure.
1718 CreateFileInterfaceMem(
1719 IN CONST BOOLEAN Unicode
1722 EFI_FILE_PROTOCOL_MEM
*FileInterface
;
1727 FileInterface
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_MEM
));
1728 if (FileInterface
== NULL
){
1733 // Assign the generic members
1735 FileInterface
->Revision
= EFI_FILE_REVISION
;
1736 FileInterface
->Open
= FileInterfaceOpenNotFound
;
1737 FileInterface
->Close
= FileInterfaceMemClose
;
1738 FileInterface
->GetPosition
= FileInterfaceMemGetPosition
;
1739 FileInterface
->SetPosition
= FileInterfaceMemSetPosition
;
1740 FileInterface
->GetInfo
= FileInterfaceMemGetInfo
;
1741 FileInterface
->SetInfo
= FileInterfaceNopSetInfo
;
1742 FileInterface
->Flush
= FileInterfaceNopGeneric
;
1743 FileInterface
->Delete
= FileInterfaceNopGeneric
;
1744 FileInterface
->Read
= FileInterfaceMemRead
;
1745 FileInterface
->Write
= FileInterfaceMemWrite
;
1746 FileInterface
->Unicode
= Unicode
;
1748 ASSERT(FileInterface
->Buffer
== NULL
);
1749 ASSERT(FileInterface
->BufferSize
== 0);
1750 ASSERT(FileInterface
->Position
== 0);
1753 FileInterface
->Buffer
= AllocateZeroPool(sizeof(gUnicodeFileTag
));
1754 if (FileInterface
->Buffer
== NULL
) {
1755 FreePool (FileInterface
);
1758 *((CHAR16
*) (FileInterface
->Buffer
)) = EFI_UNICODE_BYTE_ORDER_MARK
;
1759 FileInterface
->BufferSize
= 2;
1760 FileInterface
->Position
= 2;
1763 return ((EFI_FILE_PROTOCOL
*)FileInterface
);
1769 EFI_FILE_CLOSE Close
;
1770 EFI_FILE_DELETE Delete
;
1772 EFI_FILE_WRITE Write
;
1773 EFI_FILE_GET_POSITION GetPosition
;
1774 EFI_FILE_SET_POSITION SetPosition
;
1775 EFI_FILE_GET_INFO GetInfo
;
1776 EFI_FILE_SET_INFO SetInfo
;
1777 EFI_FILE_FLUSH Flush
;
1779 EFI_FILE_PROTOCOL
*Orig
;
1780 } EFI_FILE_PROTOCOL_FILE
;
1783 Set a files current position
1785 @param This Protocol instance pointer.
1786 @param Position Byte position from the start of the file.
1788 @retval EFI_SUCCESS Data was written.
1789 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
1794 FileInterfaceFileSetPosition(
1795 IN EFI_FILE_PROTOCOL
*This
,
1799 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->SetPosition(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, Position
);
1803 Get a file's current position
1805 @param This Protocol instance pointer.
1806 @param Position Byte position from the start of the file.
1808 @retval EFI_SUCCESS Data was written.
1809 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
1814 FileInterfaceFileGetPosition(
1815 IN EFI_FILE_PROTOCOL
*This
,
1816 OUT UINT64
*Position
1819 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->GetPosition(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, Position
);
1823 Get information about a file.
1825 @param This Protocol instance pointer.
1826 @param InformationType Type of information to return in Buffer.
1827 @param BufferSize On input size of buffer, on output amount of data in buffer.
1828 @param Buffer The buffer to return data.
1830 @retval EFI_SUCCESS Data was returned.
1831 @retval EFI_UNSUPPORT InformationType is not supported.
1832 @retval EFI_NO_MEDIA The device has no media.
1833 @retval EFI_DEVICE_ERROR The device reported an error.
1834 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1835 @retval EFI_WRITE_PROTECTED The device is write protected.
1836 @retval EFI_ACCESS_DENIED The file was open for read only.
1837 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
1842 FileInterfaceFileGetInfo(
1843 IN EFI_FILE_PROTOCOL
*This
,
1844 IN EFI_GUID
*InformationType
,
1845 IN OUT UINTN
*BufferSize
,
1849 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->GetInfo(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, InformationType
, BufferSize
, Buffer
);
1853 Set information about a file
1855 @param This Protocol instance pointer.
1856 @param InformationType Type of information in Buffer.
1857 @param BufferSize Size of buffer.
1858 @param Buffer The data to write.
1860 @retval EFI_SUCCESS Data was returned.
1861 @retval EFI_UNSUPPORT InformationType is not supported.
1862 @retval EFI_NO_MEDIA The device has no media.
1863 @retval EFI_DEVICE_ERROR The device reported an error.
1864 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1865 @retval EFI_WRITE_PROTECTED The device is write protected.
1866 @retval EFI_ACCESS_DENIED The file was open for read only.
1871 FileInterfaceFileSetInfo(
1872 IN EFI_FILE_PROTOCOL
*This
,
1873 IN EFI_GUID
*InformationType
,
1874 IN UINTN BufferSize
,
1878 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->SetInfo(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, InformationType
, BufferSize
, Buffer
);
1882 Flush data back for the file handle.
1884 @param This Protocol instance pointer.
1886 @retval EFI_SUCCESS Data was written.
1887 @retval EFI_UNSUPPORT Writes to Open directory are not supported.
1888 @retval EFI_NO_MEDIA The device has no media.
1889 @retval EFI_DEVICE_ERROR The device reported an error.
1890 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1891 @retval EFI_WRITE_PROTECTED The device is write protected.
1892 @retval EFI_ACCESS_DENIED The file was open for read only.
1893 @retval EFI_VOLUME_FULL The volume is full.
1898 FileInterfaceFileFlush(
1899 IN EFI_FILE_PROTOCOL
*This
1902 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Flush(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1906 Read data from the file.
1908 @param This Protocol instance pointer.
1909 @param BufferSize On input size of buffer, on output amount of data in buffer.
1910 @param Buffer The buffer in which data is read.
1912 @retval EFI_SUCCESS Data was read.
1913 @retval EFI_NO_MEDIA The device has no media.
1914 @retval EFI_DEVICE_ERROR The device reported an error.
1915 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1916 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
1921 FileInterfaceFileRead(
1922 IN EFI_FILE_PROTOCOL
*This
,
1923 IN OUT UINTN
*BufferSize
,
1927 CHAR8
*AsciiStrBuffer
;
1928 CHAR16
*UscStrBuffer
;
1932 if (((EFI_FILE_PROTOCOL_FILE
*)This
)->Unicode
) {
1936 return (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Read(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, BufferSize
, Buffer
));
1941 Size
= (*BufferSize
) / sizeof(CHAR16
);
1942 AsciiStrBuffer
= AllocateZeroPool(Size
+ sizeof(CHAR8
));
1943 if (AsciiStrBuffer
== NULL
) {
1944 return EFI_OUT_OF_RESOURCES
;
1946 UscStrBuffer
= AllocateZeroPool(*BufferSize
+ sizeof(CHAR16
));
1947 if (UscStrBuffer
== NULL
) {
1948 SHELL_FREE_NON_NULL(AsciiStrBuffer
);
1949 return EFI_OUT_OF_RESOURCES
;
1951 Status
= (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Read(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, &Size
, AsciiStrBuffer
));
1952 if (!EFI_ERROR(Status
)) {
1953 CharNum
= UnicodeSPrint(UscStrBuffer
, *BufferSize
+ sizeof(CHAR16
), L
"%a", AsciiStrBuffer
);
1954 if (CharNum
== Size
) {
1955 CopyMem (Buffer
, UscStrBuffer
, *BufferSize
);
1957 Status
= EFI_UNSUPPORTED
;
1960 SHELL_FREE_NON_NULL(AsciiStrBuffer
);
1961 SHELL_FREE_NON_NULL(UscStrBuffer
);
1967 Opens a new file relative to the source file's location.
1969 @param[in] This The protocol instance pointer.
1970 @param[out] NewHandle Returns File Handle for FileName.
1971 @param[in] FileName Null terminated string. "\", ".", and ".." are supported.
1972 @param[in] OpenMode Open mode for file.
1973 @param[in] Attributes Only used for EFI_FILE_MODE_CREATE.
1975 @retval EFI_SUCCESS The device was opened.
1976 @retval EFI_NOT_FOUND The specified file could not be found on the device.
1977 @retval EFI_NO_MEDIA The device has no media.
1978 @retval EFI_MEDIA_CHANGED The media has changed.
1979 @retval EFI_DEVICE_ERROR The device reported an error.
1980 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1981 @retval EFI_ACCESS_DENIED The service denied access to the file.
1982 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
1983 @retval EFI_VOLUME_FULL The volume is full.
1987 FileInterfaceFileOpen (
1988 IN EFI_FILE_PROTOCOL
*This
,
1989 OUT EFI_FILE_PROTOCOL
**NewHandle
,
1990 IN CHAR16
*FileName
,
1992 IN UINT64 Attributes
1995 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Open(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, NewHandle
, FileName
, OpenMode
, Attributes
);
1999 Close and delete the file handle.
2001 @param This Protocol instance pointer.
2003 @retval EFI_SUCCESS The device was opened.
2004 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
2009 FileInterfaceFileDelete(
2010 IN EFI_FILE_PROTOCOL
*This
2014 Status
= ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Delete(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
2020 File style interface for File (Close).
2022 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
2024 @retval EFI_SUCCESS The file was closed.
2028 FileInterfaceFileClose(
2029 IN EFI_FILE_PROTOCOL
*This
2033 Status
= ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Close(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
2039 File style interface for File (Write).
2041 If the file was opened with ASCII mode the data will be processed through
2042 AsciiSPrint before writing.
2044 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
2045 @param[in, out] BufferSize Size in bytes of Buffer.
2046 @param[in] Buffer The pointer to the buffer to write.
2048 @retval EFI_SUCCESS The data was written.
2052 FileInterfaceFileWrite(
2053 IN EFI_FILE_PROTOCOL
*This
,
2054 IN OUT UINTN
*BufferSize
,
2061 if (((EFI_FILE_PROTOCOL_FILE
*)This
)->Unicode
) {
2065 return (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Write(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, BufferSize
, Buffer
));
2070 AsciiBuffer
= AllocateZeroPool(*BufferSize
);
2071 AsciiSPrint(AsciiBuffer
, *BufferSize
, "%S", Buffer
);
2072 Size
= AsciiStrSize(AsciiBuffer
) - 1; // (we dont need the null terminator)
2073 Status
= (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Write(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, &Size
, AsciiBuffer
));
2074 FreePool(AsciiBuffer
);
2080 Create a file interface with unicode information.
2082 This will create a new EFI_FILE_PROTOCOL identical to the Templace
2083 except that the new one has Unicode and Ascii knowledge.
2085 @param[in] Template A pointer to the EFI_FILE_PROTOCOL object.
2086 @param[in] Unicode TRUE for UCS-2, FALSE for ASCII.
2088 @return a new EFI_FILE_PROTOCOL object to be used instead of the template.
2091 CreateFileInterfaceFile(
2092 IN CONST EFI_FILE_PROTOCOL
*Template
,
2093 IN CONST BOOLEAN Unicode
2096 EFI_FILE_PROTOCOL_FILE
*NewOne
;
2098 NewOne
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_FILE
));
2099 if (NewOne
== NULL
) {
2102 CopyMem(NewOne
, Template
, sizeof(EFI_FILE_PROTOCOL_FILE
));
2103 NewOne
->Orig
= (EFI_FILE_PROTOCOL
*)Template
;
2104 NewOne
->Unicode
= Unicode
;
2105 NewOne
->Open
= FileInterfaceFileOpen
;
2106 NewOne
->Close
= FileInterfaceFileClose
;
2107 NewOne
->Delete
= FileInterfaceFileDelete
;
2108 NewOne
->Read
= FileInterfaceFileRead
;
2109 NewOne
->Write
= FileInterfaceFileWrite
;
2110 NewOne
->GetPosition
= FileInterfaceFileGetPosition
;
2111 NewOne
->SetPosition
= FileInterfaceFileSetPosition
;
2112 NewOne
->GetInfo
= FileInterfaceFileGetInfo
;
2113 NewOne
->SetInfo
= FileInterfaceFileSetInfo
;
2114 NewOne
->Flush
= FileInterfaceFileFlush
;
2116 return ((EFI_FILE_PROTOCOL
*)NewOne
);