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 File style interface for console (Read).
298 This will return a single line of input from the console.
300 @param This A pointer to the EFI_FILE_PROTOCOL instance that is the
301 file handle to read data from. Not used.
302 @param BufferSize On input, the size of the Buffer. On output, the amount
303 of data returned in Buffer. In both cases, the size is
305 @param Buffer The buffer into which the data is read.
308 @retval EFI_SUCCESS The data was read.
309 @retval EFI_NO_MEDIA The device has no medium.
310 @retval EFI_DEVICE_ERROR The device reported an error.
311 @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file.
312 @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file.
313 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
314 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory
315 entry. BufferSize has been updated with the size
316 needed to complete the request.
317 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
321 FileInterfaceStdInRead(
322 IN EFI_FILE_PROTOCOL
*This
,
323 IN OUT UINTN
*BufferSize
,
327 CHAR16
*CurrentString
;
329 UINTN Column
; // Column of current cursor
330 UINTN Row
; // Row of current cursor
331 UINTN StartColumn
; // Column at the beginning of the line
332 UINTN Update
; // Line index for update
333 UINTN Delete
; // Num of chars to delete from console after update
334 UINTN StringLen
; // Total length of the line
335 UINTN StringCurPos
; // Line index corresponding to the cursor
336 UINTN MaxStr
; // Maximum possible line length
338 UINTN TotalColumn
; // Num of columns in the console
339 UINTN TotalRow
; // Num of rows in the console
341 UINTN OutputLength
; // Length of the update string
342 UINTN TailRow
; // Row of end of line
343 UINTN TailColumn
; // Column of end of line
346 BUFFER_LIST
*LinePos
;
350 BOOLEAN InTabScrolling
; // Whether in TAB-completion state
351 EFI_SHELL_FILE_INFO
*FoundFileList
;
352 EFI_SHELL_FILE_INFO
*TabLinePos
;
353 EFI_SHELL_FILE_INFO
*TempPos
;
355 CHAR16
*TabOutputStr
;
356 BOOLEAN InQuotationMode
;
358 UINTN TabPos
; // Start index of the string to search for TAB completion.
359 UINTN TabUpdatePos
; // Start index of the string updated by TAB stroke
365 // If buffer is not large enough to hold a CHAR16, return minimum buffer size
367 if (*BufferSize
< sizeof (CHAR16
) * 2) {
368 *BufferSize
= sizeof (CHAR16
) * 2;
369 return (EFI_BUFFER_TOO_SMALL
);
373 CurrentString
= Buffer
;
379 LinePos
= NewPos
= (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
);
381 InTabScrolling
= FALSE
;
382 Status
= EFI_SUCCESS
;
384 FoundFileList
= NULL
;
392 TabStr
= AllocateZeroPool (*BufferSize
);
393 if (TabStr
== NULL
) {
394 return EFI_OUT_OF_RESOURCES
;
396 TabOutputStr
= AllocateZeroPool (*BufferSize
);
397 if (TabOutputStr
== NULL
) {
399 return EFI_OUT_OF_RESOURCES
;
403 // Get the screen setting and the current cursor location
405 Column
= StartColumn
= gST
->ConOut
->Mode
->CursorColumn
;
406 Row
= gST
->ConOut
->Mode
->CursorRow
;
407 gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &TotalColumn
, &TotalRow
);
410 // Limit the line length to the buffer size or the minimun size of the
411 // screen. (The smaller takes effect)
413 MaxStr
= TotalColumn
* (TotalRow
- 1) - StartColumn
;
414 if (MaxStr
> *BufferSize
/ sizeof (CHAR16
)) {
415 MaxStr
= *BufferSize
/ sizeof (CHAR16
);
417 ZeroMem (CurrentString
, MaxStr
* sizeof (CHAR16
));
422 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &EventIndex
);
423 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
424 if (EFI_ERROR (Status
)) {
429 // Press PageUp or PageDown to scroll the history screen up or down.
430 // Press any other key to quit scrolling.
432 if (Key
.UnicodeChar
== 0 && (Key
.ScanCode
== SCAN_PAGE_UP
|| Key
.ScanCode
== SCAN_PAGE_DOWN
)) {
433 if (Key
.ScanCode
== SCAN_PAGE_UP
) {
434 ConsoleLoggerDisplayHistory(FALSE
, 0, ShellInfoObject
.ConsoleInfo
);
435 } else if (Key
.ScanCode
== SCAN_PAGE_DOWN
) {
436 ConsoleLoggerDisplayHistory(TRUE
, 0, ShellInfoObject
.ConsoleInfo
);
442 ConsoleLoggerStopHistory(ShellInfoObject
.ConsoleInfo
);
448 // If we are quitting TAB scrolling...
450 if (InTabScrolling
&& Key
.UnicodeChar
!= CHAR_TAB
) {
451 if (FoundFileList
!= NULL
) {
452 ShellInfoObject
.NewEfiShellProtocol
->FreeFileList (&FoundFileList
);
453 DEBUG_CODE(FoundFileList
= NULL
;);
455 InTabScrolling
= FALSE
;
458 switch (Key
.UnicodeChar
) {
459 case CHAR_CARRIAGE_RETURN
:
461 // All done, print a newline at the end of the string
463 TailRow
= Row
+ (StringLen
- StringCurPos
+ Column
) / TotalColumn
;
464 TailColumn
= (StringLen
- StringCurPos
+ Column
) % TotalColumn
;
465 ShellPrintEx ((INT32
)TailColumn
, (INT32
)TailRow
, L
"%N\n");
470 if (StringCurPos
!= 0) {
472 // If not move back beyond string beginning, move all characters behind
473 // the current position one character forward
476 Update
= StringCurPos
;
478 CopyMem (CurrentString
+ StringCurPos
, CurrentString
+ StringCurPos
+ 1, sizeof (CHAR16
) * (StringLen
- StringCurPos
));
481 // Adjust the current column and row
483 MoveCursorBackward (TotalColumn
, &Column
, &Row
);
489 // handle auto complete of file and directory names...
491 if (InTabScrolling
) {
492 ASSERT(FoundFileList
!= NULL
);
493 ASSERT(TabLinePos
!= NULL
);
494 TabLinePos
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&(FoundFileList
->Link
), &TabLinePos
->Link
);
495 if (IsNull(&(FoundFileList
->Link
), &TabLinePos
->Link
)) {
496 TabLinePos
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&(FoundFileList
->Link
), &TabLinePos
->Link
);
501 InQuotationMode
= FALSE
;
502 for (Index
= 0; Index
< StringLen
; Index
++) {
503 if (CurrentString
[Index
] == L
'\"') {
504 InQuotationMode
= (BOOLEAN
)(!InQuotationMode
);
506 if (CurrentString
[Index
] == L
' ' && !InQuotationMode
) {
508 TabUpdatePos
= Index
+ 1;
510 if (CurrentString
[Index
] == L
'\\') {
511 TabUpdatePos
= Index
+ 1;
514 if (StrStr(CurrentString
+ TabPos
, L
":") == NULL
) {
515 Cwd
= ShellInfoObject
.NewEfiShellProtocol
->GetCurDir(NULL
);
517 StrnCpyS(TabStr
, (*BufferSize
)/sizeof(CHAR16
), Cwd
, (*BufferSize
)/sizeof(CHAR16
) - 1);
518 StrCatS(TabStr
, (*BufferSize
)/sizeof(CHAR16
), L
"\\");
519 if (TabStr
[StrLen(TabStr
)-1] == L
'\\' && *(CurrentString
+ TabPos
) == L
'\\' ) {
520 TabStr
[StrLen(TabStr
)-1] = CHAR_NULL
;
523 (*BufferSize
)/sizeof(CHAR16
),
524 CurrentString
+ TabPos
,
529 StrnCatS(TabStr
, (*BufferSize
)/sizeof(CHAR16
), CurrentString
+ TabPos
, StringLen
- TabPos
);
532 StrnCpyS(TabStr
, (*BufferSize
)/sizeof(CHAR16
), CurrentString
+ TabPos
, (*BufferSize
)/sizeof(CHAR16
) - 1);
534 StrnCatS(TabStr
, (*BufferSize
)/sizeof(CHAR16
), L
"*", (*BufferSize
)/sizeof(CHAR16
) - 1 - StrLen(TabStr
));
535 FoundFileList
= NULL
;
536 Status
= ShellInfoObject
.NewEfiShellProtocol
->FindFiles(TabStr
, &FoundFileList
);
537 for ( TempStr
= CurrentString
539 ; TempStr
++); // note the ';'... empty for loop
541 // make sure we have a list before we do anything more...
543 if (EFI_ERROR (Status
) || FoundFileList
== NULL
) {
544 InTabScrolling
= FALSE
;
549 // enumerate through the list of files
551 for ( TempPos
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&(FoundFileList
->Link
))
552 ; !IsNull(&FoundFileList
->Link
, &TempPos
->Link
)
553 ; TempPos
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&(FoundFileList
->Link
), &(TempPos
->Link
))
556 // If "cd" is typed, only directory name will be auto-complete filled
557 // in either case . and .. will be removed.
559 if ((((TempStr
[0] == L
'c' || TempStr
[0] == L
'C') &&
560 (TempStr
[1] == L
'd' || TempStr
[1] == L
'D')
561 ) && ((ShellIsDirectory(TempPos
->FullName
) != EFI_SUCCESS
)
562 ||(StrCmp(TempPos
->FileName
, L
".") == 0)
563 ||(StrCmp(TempPos
->FileName
, L
"..") == 0)
564 )) || ((StrCmp(TempPos
->FileName
, L
".") == 0)
565 ||(StrCmp(TempPos
->FileName
, L
"..") == 0))){
566 TabLinePos
= TempPos
;
567 TempPos
= (EFI_SHELL_FILE_INFO
*)(RemoveEntryList(&(TempPos
->Link
))->BackLink
);
568 InternalFreeShellFileInfoNode(TabLinePos
);
571 if (FoundFileList
!= NULL
&& !IsListEmpty(&FoundFileList
->Link
)) {
572 TabLinePos
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&FoundFileList
->Link
);
573 InTabScrolling
= TRUE
;
575 FreePool(FoundFileList
);
576 FoundFileList
= NULL
;
583 if (Key
.UnicodeChar
>= ' ') {
585 // If we are at the buffer's end, drop the key
587 if (StringLen
== MaxStr
- 1 && (ShellInfoObject
.ViewingSettings
.InsertMode
|| StringCurPos
== StringLen
)) {
591 // If in insert mode, make space by moving each other character 1
592 // space higher in the array
594 if (ShellInfoObject
.ViewingSettings
.InsertMode
) {
595 CopyMem(CurrentString
+ StringCurPos
+ 1, CurrentString
+ StringCurPos
, (StringLen
- StringCurPos
)*sizeof(CurrentString
[0]));
598 CurrentString
[StringCurPos
] = Key
.UnicodeChar
;
599 Update
= StringCurPos
;
607 switch (Key
.ScanCode
) {
610 // Move characters behind current position one character forward
612 if (StringLen
!= 0) {
613 Update
= StringCurPos
;
615 CopyMem (CurrentString
+ StringCurPos
, CurrentString
+ StringCurPos
+ 1, sizeof (CHAR16
) * (StringLen
- StringCurPos
));
621 // Prepare to print the previous command
623 NewPos
= (BUFFER_LIST
*)GetPreviousNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
624 if (IsNull(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
)) {
625 NewPos
= (BUFFER_LIST
*)GetPreviousNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
631 // Prepare to print the next command
633 NewPos
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
634 if (NewPos
== (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
)) {
635 NewPos
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
641 // Adjust current cursor position
643 if (StringCurPos
!= 0) {
645 MoveCursorBackward (TotalColumn
, &Column
, &Row
);
651 // Adjust current cursor position
653 if (StringCurPos
< StringLen
) {
655 MoveCursorForward (TotalColumn
, TotalRow
, &Column
, &Row
);
661 // Move current cursor position to the beginning of the command line
663 Row
-= (StringCurPos
+ StartColumn
) / TotalColumn
;
664 Column
= StartColumn
;
670 // Move current cursor position to the end of the command line
672 TailRow
= Row
+ (StringLen
- StringCurPos
+ Column
) / TotalColumn
;
673 TailColumn
= (StringLen
- StringCurPos
+ Column
) % TotalColumn
;
676 StringCurPos
= StringLen
;
681 // Prepare to clear the current command line
683 CurrentString
[0] = 0;
686 Row
-= (StringCurPos
+ StartColumn
) / TotalColumn
;
687 Column
= StartColumn
;
693 // Toggle the SEnvInsertMode flag
695 ShellInfoObject
.ViewingSettings
.InsertMode
= (BOOLEAN
)!ShellInfoObject
.ViewingSettings
.InsertMode
;
700 // Print command history
702 PrintCommandHistory (TotalColumn
, TotalRow
, 4);
703 *CurrentString
= CHAR_NULL
;
714 // If we are in auto-complete mode, we are preparing to print
715 // the next file or directory name
717 if (InTabScrolling
) {
719 // Adjust the column and row to the start of TAB-completion string.
721 Column
= (StartColumn
+ TabUpdatePos
) % TotalColumn
;
722 Row
-= (StartColumn
+ StringCurPos
) / TotalColumn
- (StartColumn
+ TabUpdatePos
) / TotalColumn
;
723 OutputLength
= StrLen (TabLinePos
->FileName
);
725 // if the output string contains blank space, quotation marks L'\"'
726 // should be added to the output.
728 if (StrStr(TabLinePos
->FileName
, L
" ") != NULL
){
729 TabOutputStr
[0] = L
'\"';
730 CopyMem (TabOutputStr
+ 1, TabLinePos
->FileName
, OutputLength
* sizeof (CHAR16
));
731 TabOutputStr
[OutputLength
+ 1] = L
'\"';
732 TabOutputStr
[OutputLength
+ 2] = CHAR_NULL
;
734 CopyMem (TabOutputStr
, TabLinePos
->FileName
, OutputLength
* sizeof (CHAR16
));
735 TabOutputStr
[OutputLength
] = CHAR_NULL
;
737 OutputLength
= StrLen (TabOutputStr
) < MaxStr
- 1 ? StrLen (TabOutputStr
) : MaxStr
- 1;
738 CopyMem (CurrentString
+ TabUpdatePos
, TabOutputStr
, OutputLength
* sizeof (CHAR16
));
739 CurrentString
[TabUpdatePos
+ OutputLength
] = CHAR_NULL
;
740 StringCurPos
= TabUpdatePos
+ OutputLength
;
741 Update
= TabUpdatePos
;
742 if (StringLen
> TabUpdatePos
+ OutputLength
) {
743 Delete
= StringLen
- TabUpdatePos
- OutputLength
;
748 // If we have a new position, we are preparing to print a previous or
751 if (NewPos
!= (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
)) {
752 Column
= StartColumn
;
753 Row
-= (StringCurPos
+ StartColumn
) / TotalColumn
;
756 NewPos
= (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
);
758 OutputLength
= StrLen (LinePos
->Buffer
) < MaxStr
- 1 ? StrLen (LinePos
->Buffer
) : MaxStr
- 1;
759 CopyMem (CurrentString
, LinePos
->Buffer
, OutputLength
* sizeof (CHAR16
));
760 CurrentString
[OutputLength
] = CHAR_NULL
;
762 StringCurPos
= OutputLength
;
765 // Draw new input string
768 if (StringLen
> OutputLength
) {
770 // If old string was longer, blank its tail
772 Delete
= StringLen
- OutputLength
;
776 // If we need to update the output do so now
778 if (Update
!= (UINTN
) -1) {
779 ShellPrintEx ((INT32
)Column
, (INT32
)Row
, L
"%s%.*s", CurrentString
+ Update
, Delete
, L
"");
780 StringLen
= StrLen (CurrentString
);
783 SetMem (CurrentString
+ StringLen
, Delete
* sizeof (CHAR16
), CHAR_NULL
);
786 if (StringCurPos
> StringLen
) {
787 StringCurPos
= StringLen
;
793 // After using print to reflect newly updates, if we're not using
794 // BACKSPACE and DELETE, we need to move the cursor position forward,
795 // so adjust row and column here.
797 if (Key
.UnicodeChar
!= CHAR_BACKSPACE
&& !(Key
.UnicodeChar
== 0 && Key
.ScanCode
== SCAN_DELETE
)) {
799 // Calulate row and column of the tail of current string
801 TailRow
= Row
+ (StringLen
- StringCurPos
+ Column
+ OutputLength
) / TotalColumn
;
802 TailColumn
= (StringLen
- StringCurPos
+ Column
+ OutputLength
) % TotalColumn
;
805 // If the tail of string reaches screen end, screen rolls up, so if
806 // Row does not equal TailRow, Row should be decremented
808 // (if we are recalling commands using UPPER and DOWN key, and if the
809 // old command is too long to fit the screen, TailColumn must be 79.
811 if (TailColumn
== 0 && TailRow
>= TotalRow
&& Row
!= TailRow
) {
815 // Calculate the cursor position after current operation. If cursor
816 // reaches line end, update both row and column, otherwise, only
817 // column will be changed.
819 if (Column
+ OutputLength
>= TotalColumn
) {
820 SkipLength
= OutputLength
- (TotalColumn
- Column
);
822 Row
+= SkipLength
/ TotalColumn
+ 1;
823 if (Row
> TotalRow
- 1) {
827 Column
= SkipLength
% TotalColumn
;
829 Column
+= OutputLength
;
836 // Set the cursor position for this key
838 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, Column
, Row
);
841 if (CurrentString
!= NULL
&& StrLen(CurrentString
) > 0) {
843 // add the line to the history buffer
845 AddLineToCommandHistory(CurrentString
);
849 FreePool (TabOutputStr
);
851 // Return the data to the caller
853 *BufferSize
= StringLen
* sizeof (CHAR16
);
856 // if this was used it should be deallocated by now...
857 // prevent memory leaks...
859 ASSERT(FoundFileList
== NULL
);
865 // FILE sytle interfaces for StdIn/StdOut/StdErr
867 EFI_FILE_PROTOCOL FileInterfaceStdIn
= {
869 FileInterfaceOpenNotFound
,
870 FileInterfaceNopGeneric
,
871 FileInterfaceNopGeneric
,
872 FileInterfaceStdInRead
,
873 FileInterfaceStdInWrite
,
874 FileInterfaceNopGetPosition
,
875 FileInterfaceNopSetPosition
,
876 FileInterfaceNopGetInfo
,
877 FileInterfaceNopSetInfo
,
878 FileInterfaceNopGeneric
881 EFI_FILE_PROTOCOL FileInterfaceStdOut
= {
883 FileInterfaceOpenNotFound
,
884 FileInterfaceNopGeneric
,
885 FileInterfaceNopGeneric
,
886 FileInterfaceStdOutRead
,
887 FileInterfaceStdOutWrite
,
888 FileInterfaceNopGetPosition
,
889 FileInterfaceNopSetPosition
,
890 FileInterfaceNopGetInfo
,
891 FileInterfaceNopSetInfo
,
892 FileInterfaceNopGeneric
895 EFI_FILE_PROTOCOL FileInterfaceStdErr
= {
897 FileInterfaceOpenNotFound
,
898 FileInterfaceNopGeneric
,
899 FileInterfaceNopGeneric
,
900 FileInterfaceStdErrRead
,
901 FileInterfaceStdErrWrite
,
902 FileInterfaceNopGetPosition
,
903 FileInterfaceNopSetPosition
,
904 FileInterfaceNopGetInfo
,
905 FileInterfaceNopSetInfo
,
906 FileInterfaceNopGeneric
909 EFI_FILE_PROTOCOL FileInterfaceNulFile
= {
911 FileInterfaceOpenNotFound
,
912 FileInterfaceNopGeneric
,
913 FileInterfaceNopGeneric
,
914 FileInterfaceNulRead
,
915 FileInterfaceNulWrite
,
916 FileInterfaceNopGetPosition
,
917 FileInterfaceNopSetPosition
,
918 FileInterfaceNopGetInfo
,
919 FileInterfaceNopSetInfo
,
920 FileInterfaceNopGeneric
927 // This is identical to EFI_FILE_PROTOCOL except for the additional member
934 EFI_FILE_CLOSE Close
;
935 EFI_FILE_DELETE Delete
;
937 EFI_FILE_WRITE Write
;
938 EFI_FILE_GET_POSITION GetPosition
;
939 EFI_FILE_SET_POSITION SetPosition
;
940 EFI_FILE_GET_INFO GetInfo
;
941 EFI_FILE_SET_INFO SetInfo
;
942 EFI_FILE_FLUSH Flush
;
944 } EFI_FILE_PROTOCOL_ENVIRONMENT
;
945 //ANSI compliance helper to get size of the struct.
946 #define SIZE_OF_EFI_FILE_PROTOCOL_ENVIRONMENT EFI_FIELD_OFFSET (EFI_FILE_PROTOCOL_ENVIRONMENT, Name)
949 File style interface for Environment Variable (Close).
951 Frees the memory for this object.
953 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
959 FileInterfaceEnvClose(
960 IN EFI_FILE_PROTOCOL
*This
968 // Most if not all UEFI commands will have an '\r\n' at the end of any output.
969 // Since the output was redirected to a variable, it does not make sense to
970 // keep this. So, before closing, strip the trailing '\r\n' from the variable
976 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
977 if (Status
== EFI_BUFFER_TOO_SMALL
) {
978 NewBuffer
= AllocateZeroPool(NewSize
+ sizeof(CHAR16
));
979 if (NewBuffer
== NULL
) {
980 return EFI_OUT_OF_RESOURCES
;
982 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
985 if (!EFI_ERROR(Status
) && NewBuffer
!= NULL
) {
987 if (StrSize(NewBuffer
) > 6)
989 if ((((CHAR16
*)NewBuffer
)[(StrSize(NewBuffer
)/2) - 2] == CHAR_LINEFEED
)
990 && (((CHAR16
*)NewBuffer
)[(StrSize(NewBuffer
)/2) - 3] == CHAR_CARRIAGE_RETURN
)) {
991 ((CHAR16
*)NewBuffer
)[(StrSize(NewBuffer
)/2) - 3] = CHAR_NULL
;
994 if (IsVolatileEnv(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
)) {
995 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, StrSize(NewBuffer
), NewBuffer
);
997 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_NV(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, StrSize(NewBuffer
), NewBuffer
);
1002 SHELL_FREE_NON_NULL(NewBuffer
);
1003 FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
);
1008 File style interface for Environment Variable (Delete).
1010 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1012 @retval The return value from FileInterfaceEnvClose().
1016 FileInterfaceEnvDelete(
1017 IN EFI_FILE_PROTOCOL
*This
1020 SHELL_DELETE_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
);
1021 return (FileInterfaceEnvClose(This
));
1025 File style interface for Environment Variable (Read).
1027 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1028 @param[in, out] BufferSize Size in bytes of Buffer.
1029 @param[out] Buffer The pointer to the buffer to fill.
1031 @retval EFI_SUCCESS The data was read.
1035 FileInterfaceEnvRead(
1036 IN EFI_FILE_PROTOCOL
*This
,
1037 IN OUT UINTN
*BufferSize
,
1041 return (SHELL_GET_ENVIRONMENT_VARIABLE(
1042 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1048 File style interface for Volatile Environment Variable (Write).
1050 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1051 @param[in, out] BufferSize Size in bytes of Buffer.
1052 @param[in] Buffer The pointer to the buffer to write.
1054 @retval EFI_SUCCESS The data was read.
1058 FileInterfaceEnvVolWrite(
1059 IN EFI_FILE_PROTOCOL
*This
,
1060 IN OUT UINTN
*BufferSize
,
1071 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1072 if (Status
== EFI_BUFFER_TOO_SMALL
){
1073 NewBuffer
= AllocateZeroPool(NewSize
+ *BufferSize
+ sizeof(CHAR16
));
1074 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1076 if (!EFI_ERROR(Status
) && NewBuffer
!= NULL
) {
1077 while (((CHAR16
*)NewBuffer
)[NewSize
/2] == CHAR_NULL
) {
1079 // We want to overwrite the CHAR_NULL
1083 CopyMem((UINT8
*)NewBuffer
+ NewSize
+ 2, Buffer
, *BufferSize
);
1084 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, StrSize(NewBuffer
), NewBuffer
);
1085 FreePool(NewBuffer
);
1088 SHELL_FREE_NON_NULL(NewBuffer
);
1089 return (SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, *BufferSize
, Buffer
));
1095 File style interface for Non Volatile Environment Variable (Write).
1097 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1098 @param[in, out] BufferSize Size in bytes of Buffer.
1099 @param[in] Buffer The pointer to the buffer to write.
1101 @retval EFI_SUCCESS The data was read.
1105 FileInterfaceEnvNonVolWrite(
1106 IN EFI_FILE_PROTOCOL
*This
,
1107 IN OUT UINTN
*BufferSize
,
1118 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1119 if (Status
== EFI_BUFFER_TOO_SMALL
){
1120 NewBuffer
= AllocateZeroPool(NewSize
+ *BufferSize
);
1121 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1123 if (!EFI_ERROR(Status
)) {
1124 CopyMem((UINT8
*)NewBuffer
+ NewSize
, Buffer
, *BufferSize
);
1125 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
1126 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1127 NewSize
+ *BufferSize
,
1130 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
1131 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1138 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1139 environment variables through file operations.
1141 @param EnvName The name of the Environment Variable to be operated on.
1143 @retval NULL Memory could not be allocated.
1144 @return other a pointer to an EFI_FILE_PROTOCOL structure
1148 CreateFileInterfaceEnv(
1149 IN CONST CHAR16
*EnvName
1152 EFI_FILE_PROTOCOL_ENVIRONMENT
*EnvFileInterface
;
1155 if (EnvName
== NULL
) {
1162 EnvNameSize
= StrSize(EnvName
);
1163 EnvFileInterface
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT
)+EnvNameSize
);
1164 if (EnvFileInterface
== NULL
){
1169 // Assign the generic members
1171 EnvFileInterface
->Revision
= EFI_FILE_REVISION
;
1172 EnvFileInterface
->Open
= FileInterfaceOpenNotFound
;
1173 EnvFileInterface
->Close
= FileInterfaceEnvClose
;
1174 EnvFileInterface
->GetPosition
= FileInterfaceNopGetPosition
;
1175 EnvFileInterface
->SetPosition
= FileInterfaceNopSetPosition
;
1176 EnvFileInterface
->GetInfo
= FileInterfaceNopGetInfo
;
1177 EnvFileInterface
->SetInfo
= FileInterfaceNopSetInfo
;
1178 EnvFileInterface
->Flush
= FileInterfaceNopGeneric
;
1179 EnvFileInterface
->Delete
= FileInterfaceEnvDelete
;
1180 EnvFileInterface
->Read
= FileInterfaceEnvRead
;
1182 CopyMem(EnvFileInterface
->Name
, EnvName
, EnvNameSize
);
1185 // Assign the different members for Volatile and Non-Volatile variables
1187 if (IsVolatileEnv(EnvName
)) {
1188 EnvFileInterface
->Write
= FileInterfaceEnvVolWrite
;
1190 EnvFileInterface
->Write
= FileInterfaceEnvNonVolWrite
;
1192 return ((EFI_FILE_PROTOCOL
*)EnvFileInterface
);
1196 Move the cursor position one character backward.
1198 @param[in] LineLength Length of a line. Get it by calling QueryMode
1199 @param[in, out] Column Current column of the cursor position
1200 @param[in, out] Row Current row of the cursor position
1204 MoveCursorBackward (
1205 IN UINTN LineLength
,
1206 IN OUT UINTN
*Column
,
1211 // If current column is 0, move to the last column of the previous line,
1212 // otherwise, just decrement column.
1215 *Column
= LineLength
- 1;
1225 Move the cursor position one character forward.
1227 @param[in] LineLength Length of a line.
1228 @param[in] TotalRow Total row of a screen
1229 @param[in, out] Column Current column of the cursor position
1230 @param[in, out] Row Current row of the cursor position
1235 IN UINTN LineLength
,
1237 IN OUT UINTN
*Column
,
1242 // Increment Column.
1243 // If this puts column past the end of the line, move to first column
1247 if (*Column
>= LineLength
) {
1249 if ((*Row
) < TotalRow
- 1) {
1256 Prints out each previously typed command in the command list history log.
1258 When each screen is full it will pause for a key before continuing.
1260 @param[in] TotalCols How many columns are on the screen
1261 @param[in] TotalRows How many rows are on the screen
1262 @param[in] StartColumn which column to start at
1266 PrintCommandHistory (
1267 IN CONST UINTN TotalCols
,
1268 IN CONST UINTN TotalRows
,
1269 IN CONST UINTN StartColumn
1277 ShellPrintEx (-1, -1, L
"\n");
1281 // go through history list...
1283 for ( Node
= (BUFFER_LIST
*)GetFirstNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
)
1284 ; !IsNull(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &Node
->Link
)
1285 ; Node
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &Node
->Link
)
1288 LineCount
= ((StrLen (Node
->Buffer
) + StartColumn
+ 1) / TotalCols
) + 1;
1290 if (LineNumber
+ LineCount
>= TotalRows
) {
1291 ShellPromptForResponseHii(
1292 ShellPromptResponseTypeEnterContinue
,
1293 STRING_TOKEN (STR_SHELL_ENTER_TO_CONT
),
1294 ShellInfoObject
.HiiHandle
,
1299 ShellPrintEx (-1, -1, L
"%2d. %s\n", Index
, Node
->Buffer
);
1300 LineNumber
+= LineCount
;
1310 // This is identical to EFI_FILE_PROTOCOL except for the additional members
1311 // for the buffer, size, and position.
1317 EFI_FILE_CLOSE Close
;
1318 EFI_FILE_DELETE Delete
;
1320 EFI_FILE_WRITE Write
;
1321 EFI_FILE_GET_POSITION GetPosition
;
1322 EFI_FILE_SET_POSITION SetPosition
;
1323 EFI_FILE_GET_INFO GetInfo
;
1324 EFI_FILE_SET_INFO SetInfo
;
1325 EFI_FILE_FLUSH Flush
;
1331 } EFI_FILE_PROTOCOL_MEM
;
1334 File style interface for Mem (SetPosition).
1336 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1337 @param[out] Position The position to set.
1339 @retval EFI_SUCCESS The position was successfully changed.
1340 @retval EFI_INVALID_PARAMETER The Position was invalid.
1344 FileInterfaceMemSetPosition(
1345 IN EFI_FILE_PROTOCOL
*This
,
1349 if (Position
<= ((EFI_FILE_PROTOCOL_MEM
*)This
)->FileSize
) {
1350 ((EFI_FILE_PROTOCOL_MEM
*)This
)->Position
= Position
;
1351 return (EFI_SUCCESS
);
1353 return (EFI_INVALID_PARAMETER
);
1358 File style interface for Mem (GetPosition).
1360 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1361 @param[out] Position The pointer to the position.
1363 @retval EFI_SUCCESS The position was retrieved.
1367 FileInterfaceMemGetPosition(
1368 IN EFI_FILE_PROTOCOL
*This
,
1369 OUT UINT64
*Position
1372 *Position
= ((EFI_FILE_PROTOCOL_MEM
*)This
)->Position
;
1373 return (EFI_SUCCESS
);
1377 File style interface for Mem (Write).
1379 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1380 @param[in, out] BufferSize Size in bytes of Buffer.
1381 @param[in] Buffer The pointer to the buffer to write.
1383 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.
1384 @retval EFI_SUCCESS The data was written.
1388 FileInterfaceMemWrite(
1389 IN EFI_FILE_PROTOCOL
*This
,
1390 IN OUT UINTN
*BufferSize
,
1395 EFI_FILE_PROTOCOL_MEM
*MemFile
;
1397 MemFile
= (EFI_FILE_PROTOCOL_MEM
*) This
;
1398 if (MemFile
->Unicode
) {
1402 if ((UINTN
)(MemFile
->Position
+ (*BufferSize
)) > (UINTN
)(MemFile
->BufferSize
)) {
1403 MemFile
->Buffer
= ReallocatePool((UINTN
)(MemFile
->BufferSize
), (UINTN
)(MemFile
->BufferSize
) + (*BufferSize
) + MEM_WRITE_REALLOC_OVERHEAD
, MemFile
->Buffer
);
1404 MemFile
->BufferSize
+= (*BufferSize
) + MEM_WRITE_REALLOC_OVERHEAD
;
1406 CopyMem(((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, Buffer
, *BufferSize
);
1407 MemFile
->Position
+= (*BufferSize
);
1408 MemFile
->FileSize
= MemFile
->Position
;
1409 return (EFI_SUCCESS
);
1414 AsciiBuffer
= AllocateZeroPool(*BufferSize
);
1415 if (AsciiBuffer
== NULL
) {
1416 return (EFI_OUT_OF_RESOURCES
);
1418 AsciiSPrint(AsciiBuffer
, *BufferSize
, "%S", Buffer
);
1419 if ((UINTN
)(MemFile
->Position
+ AsciiStrSize(AsciiBuffer
)) > (UINTN
)(MemFile
->BufferSize
)) {
1420 MemFile
->Buffer
= ReallocatePool((UINTN
)(MemFile
->BufferSize
), (UINTN
)(MemFile
->BufferSize
) + AsciiStrSize(AsciiBuffer
) + MEM_WRITE_REALLOC_OVERHEAD
, MemFile
->Buffer
);
1421 MemFile
->BufferSize
+= AsciiStrSize(AsciiBuffer
) + MEM_WRITE_REALLOC_OVERHEAD
;
1423 CopyMem(((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, AsciiBuffer
, AsciiStrSize(AsciiBuffer
));
1424 MemFile
->Position
+= (*BufferSize
/ sizeof(CHAR16
));
1425 MemFile
->FileSize
= MemFile
->Position
;
1426 FreePool(AsciiBuffer
);
1427 return (EFI_SUCCESS
);
1432 File style interface for Mem (Read).
1434 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1435 @param[in, out] BufferSize Size in bytes of Buffer.
1436 @param[in] Buffer The pointer to the buffer to fill.
1438 @retval EFI_SUCCESS The data was read.
1442 FileInterfaceMemRead(
1443 IN EFI_FILE_PROTOCOL
*This
,
1444 IN OUT UINTN
*BufferSize
,
1448 EFI_FILE_PROTOCOL_MEM
*MemFile
;
1450 MemFile
= (EFI_FILE_PROTOCOL_MEM
*) This
;
1451 if (*BufferSize
> (UINTN
)((MemFile
->FileSize
) - (UINTN
)(MemFile
->Position
))) {
1452 (*BufferSize
) = (UINTN
)((MemFile
->FileSize
) - (UINTN
)(MemFile
->Position
));
1454 CopyMem(Buffer
, ((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, (*BufferSize
));
1455 MemFile
->Position
= MemFile
->Position
+ (*BufferSize
);
1456 return (EFI_SUCCESS
);
1460 File style interface for Mem (Close).
1462 Frees all memory associated with this object.
1464 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1466 @retval EFI_SUCCESS The 'file' was closed.
1470 FileInterfaceMemClose(
1471 IN EFI_FILE_PROTOCOL
*This
1474 SHELL_FREE_NON_NULL(((EFI_FILE_PROTOCOL_MEM
*)This
)->Buffer
);
1475 SHELL_FREE_NON_NULL(This
);
1476 return (EFI_SUCCESS
);
1480 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1481 a file entirely in memory through file operations.
1483 @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii.
1485 @retval NULL Memory could not be allocated.
1486 @return other A pointer to an EFI_FILE_PROTOCOL structure.
1490 CreateFileInterfaceMem(
1491 IN CONST BOOLEAN Unicode
1494 EFI_FILE_PROTOCOL_MEM
*FileInterface
;
1499 FileInterface
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_MEM
));
1500 if (FileInterface
== NULL
){
1505 // Assign the generic members
1507 FileInterface
->Revision
= EFI_FILE_REVISION
;
1508 FileInterface
->Open
= FileInterfaceOpenNotFound
;
1509 FileInterface
->Close
= FileInterfaceMemClose
;
1510 FileInterface
->GetPosition
= FileInterfaceMemGetPosition
;
1511 FileInterface
->SetPosition
= FileInterfaceMemSetPosition
;
1512 FileInterface
->GetInfo
= FileInterfaceNopGetInfo
;
1513 FileInterface
->SetInfo
= FileInterfaceNopSetInfo
;
1514 FileInterface
->Flush
= FileInterfaceNopGeneric
;
1515 FileInterface
->Delete
= FileInterfaceNopGeneric
;
1516 FileInterface
->Read
= FileInterfaceMemRead
;
1517 FileInterface
->Write
= FileInterfaceMemWrite
;
1518 FileInterface
->Unicode
= Unicode
;
1520 ASSERT(FileInterface
->Buffer
== NULL
);
1521 ASSERT(FileInterface
->BufferSize
== 0);
1522 ASSERT(FileInterface
->Position
== 0);
1525 FileInterface
->Buffer
= AllocateZeroPool(sizeof(gUnicodeFileTag
));
1526 if (FileInterface
->Buffer
== NULL
) {
1527 FreePool (FileInterface
);
1530 *((CHAR16
*) (FileInterface
->Buffer
)) = EFI_UNICODE_BYTE_ORDER_MARK
;
1531 FileInterface
->BufferSize
= 2;
1532 FileInterface
->Position
= 2;
1535 return ((EFI_FILE_PROTOCOL
*)FileInterface
);
1541 EFI_FILE_CLOSE Close
;
1542 EFI_FILE_DELETE Delete
;
1544 EFI_FILE_WRITE Write
;
1545 EFI_FILE_GET_POSITION GetPosition
;
1546 EFI_FILE_SET_POSITION SetPosition
;
1547 EFI_FILE_GET_INFO GetInfo
;
1548 EFI_FILE_SET_INFO SetInfo
;
1549 EFI_FILE_FLUSH Flush
;
1551 EFI_FILE_PROTOCOL
*Orig
;
1552 } EFI_FILE_PROTOCOL_FILE
;
1555 Set a files current position
1557 @param This Protocol instance pointer.
1558 @param Position Byte position from the start of the file.
1560 @retval EFI_SUCCESS Data was written.
1561 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
1566 FileInterfaceFileSetPosition(
1567 IN EFI_FILE_PROTOCOL
*This
,
1571 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->SetPosition(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, Position
);
1575 Get a file's current position
1577 @param This Protocol instance pointer.
1578 @param Position Byte position from the start of the file.
1580 @retval EFI_SUCCESS Data was written.
1581 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
1586 FileInterfaceFileGetPosition(
1587 IN EFI_FILE_PROTOCOL
*This
,
1588 OUT UINT64
*Position
1591 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->GetPosition(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, Position
);
1595 Get information about a file.
1597 @param This Protocol instance pointer.
1598 @param InformationType Type of information to return in Buffer.
1599 @param BufferSize On input size of buffer, on output amount of data in buffer.
1600 @param Buffer The buffer to return data.
1602 @retval EFI_SUCCESS Data was returned.
1603 @retval EFI_UNSUPPORT InformationType is not supported.
1604 @retval EFI_NO_MEDIA The device has no media.
1605 @retval EFI_DEVICE_ERROR The device reported an error.
1606 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1607 @retval EFI_WRITE_PROTECTED The device is write protected.
1608 @retval EFI_ACCESS_DENIED The file was open for read only.
1609 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
1614 FileInterfaceFileGetInfo(
1615 IN EFI_FILE_PROTOCOL
*This
,
1616 IN EFI_GUID
*InformationType
,
1617 IN OUT UINTN
*BufferSize
,
1621 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->GetInfo(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, InformationType
, BufferSize
, Buffer
);
1625 Set information about a file
1627 @param This Protocol instance pointer.
1628 @param InformationType Type of information in Buffer.
1629 @param BufferSize Size of buffer.
1630 @param Buffer The data to write.
1632 @retval EFI_SUCCESS Data was returned.
1633 @retval EFI_UNSUPPORT InformationType is not supported.
1634 @retval EFI_NO_MEDIA The device has no media.
1635 @retval EFI_DEVICE_ERROR The device reported an error.
1636 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1637 @retval EFI_WRITE_PROTECTED The device is write protected.
1638 @retval EFI_ACCESS_DENIED The file was open for read only.
1643 FileInterfaceFileSetInfo(
1644 IN EFI_FILE_PROTOCOL
*This
,
1645 IN EFI_GUID
*InformationType
,
1646 IN UINTN BufferSize
,
1650 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->SetInfo(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, InformationType
, BufferSize
, Buffer
);
1654 Flush data back for the file handle.
1656 @param This Protocol instance pointer.
1658 @retval EFI_SUCCESS Data was written.
1659 @retval EFI_UNSUPPORT Writes to Open directory are not supported.
1660 @retval EFI_NO_MEDIA The device has no media.
1661 @retval EFI_DEVICE_ERROR The device reported an error.
1662 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1663 @retval EFI_WRITE_PROTECTED The device is write protected.
1664 @retval EFI_ACCESS_DENIED The file was open for read only.
1665 @retval EFI_VOLUME_FULL The volume is full.
1670 FileInterfaceFileFlush(
1671 IN EFI_FILE_PROTOCOL
*This
1674 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Flush(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1678 Read data from the file.
1680 @param This Protocol instance pointer.
1681 @param BufferSize On input size of buffer, on output amount of data in buffer.
1682 @param Buffer The buffer in which data is read.
1684 @retval EFI_SUCCESS Data was read.
1685 @retval EFI_NO_MEDIA The device has no media.
1686 @retval EFI_DEVICE_ERROR The device reported an error.
1687 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1688 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
1693 FileInterfaceFileRead(
1694 IN EFI_FILE_PROTOCOL
*This
,
1695 IN OUT UINTN
*BufferSize
,
1699 CHAR8
*AsciiStrBuffer
;
1700 CHAR16
*UscStrBuffer
;
1704 if (((EFI_FILE_PROTOCOL_FILE
*)This
)->Unicode
) {
1708 return (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Read(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, BufferSize
, Buffer
));
1713 Size
= (*BufferSize
) / sizeof(CHAR16
);
1714 AsciiStrBuffer
= AllocateZeroPool(Size
+ sizeof(CHAR8
));
1715 if (AsciiStrBuffer
== NULL
) {
1716 return EFI_OUT_OF_RESOURCES
;
1718 UscStrBuffer
= AllocateZeroPool(*BufferSize
+ sizeof(CHAR16
));
1719 if (UscStrBuffer
== NULL
) {
1720 SHELL_FREE_NON_NULL(AsciiStrBuffer
);
1721 return EFI_OUT_OF_RESOURCES
;
1723 Status
= (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Read(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, &Size
, AsciiStrBuffer
));
1724 if (!EFI_ERROR(Status
)) {
1725 CharNum
= UnicodeSPrint(UscStrBuffer
, *BufferSize
+ sizeof(CHAR16
), L
"%a", AsciiStrBuffer
);
1726 if (CharNum
== Size
) {
1727 CopyMem (Buffer
, UscStrBuffer
, *BufferSize
);
1729 Status
= EFI_UNSUPPORTED
;
1732 SHELL_FREE_NON_NULL(AsciiStrBuffer
);
1733 SHELL_FREE_NON_NULL(UscStrBuffer
);
1739 Opens a new file relative to the source file's location.
1741 @param[in] This The protocol instance pointer.
1742 @param[out] NewHandle Returns File Handle for FileName.
1743 @param[in] FileName Null terminated string. "\", ".", and ".." are supported.
1744 @param[in] OpenMode Open mode for file.
1745 @param[in] Attributes Only used for EFI_FILE_MODE_CREATE.
1747 @retval EFI_SUCCESS The device was opened.
1748 @retval EFI_NOT_FOUND The specified file could not be found on the device.
1749 @retval EFI_NO_MEDIA The device has no media.
1750 @retval EFI_MEDIA_CHANGED The media has changed.
1751 @retval EFI_DEVICE_ERROR The device reported an error.
1752 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1753 @retval EFI_ACCESS_DENIED The service denied access to the file.
1754 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
1755 @retval EFI_VOLUME_FULL The volume is full.
1759 FileInterfaceFileOpen (
1760 IN EFI_FILE_PROTOCOL
*This
,
1761 OUT EFI_FILE_PROTOCOL
**NewHandle
,
1762 IN CHAR16
*FileName
,
1764 IN UINT64 Attributes
1767 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Open(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, NewHandle
, FileName
, OpenMode
, Attributes
);
1771 Close and delete the file handle.
1773 @param This Protocol instance pointer.
1775 @retval EFI_SUCCESS The device was opened.
1776 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
1781 FileInterfaceFileDelete(
1782 IN EFI_FILE_PROTOCOL
*This
1786 Status
= ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Delete(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1792 File style interface for File (Close).
1794 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1796 @retval EFI_SUCCESS The file was closed.
1800 FileInterfaceFileClose(
1801 IN EFI_FILE_PROTOCOL
*This
1805 Status
= ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Close(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1811 File style interface for File (Write).
1813 If the file was opened with ASCII mode the data will be processed through
1814 AsciiSPrint before writing.
1816 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1817 @param[in, out] BufferSize Size in bytes of Buffer.
1818 @param[in] Buffer The pointer to the buffer to write.
1820 @retval EFI_SUCCESS The data was written.
1824 FileInterfaceFileWrite(
1825 IN EFI_FILE_PROTOCOL
*This
,
1826 IN OUT UINTN
*BufferSize
,
1833 if (((EFI_FILE_PROTOCOL_FILE
*)This
)->Unicode
) {
1837 return (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Write(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, BufferSize
, Buffer
));
1842 AsciiBuffer
= AllocateZeroPool(*BufferSize
);
1843 AsciiSPrint(AsciiBuffer
, *BufferSize
, "%S", Buffer
);
1844 Size
= AsciiStrSize(AsciiBuffer
) - 1; // (we dont need the null terminator)
1845 Status
= (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Write(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, &Size
, AsciiBuffer
));
1846 FreePool(AsciiBuffer
);
1852 Create a file interface with unicode information.
1854 This will create a new EFI_FILE_PROTOCOL identical to the Templace
1855 except that the new one has Unicode and Ascii knowledge.
1857 @param[in] Template A pointer to the EFI_FILE_PROTOCOL object.
1858 @param[in] Unicode TRUE for UCS-2, FALSE for ASCII.
1860 @return a new EFI_FILE_PROTOCOL object to be used instead of the template.
1863 CreateFileInterfaceFile(
1864 IN CONST EFI_FILE_PROTOCOL
*Template
,
1865 IN CONST BOOLEAN Unicode
1868 EFI_FILE_PROTOCOL_FILE
*NewOne
;
1870 NewOne
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_FILE
));
1871 if (NewOne
== NULL
) {
1874 CopyMem(NewOne
, Template
, sizeof(EFI_FILE_PROTOCOL_FILE
));
1875 NewOne
->Orig
= (EFI_FILE_PROTOCOL
*)Template
;
1876 NewOne
->Unicode
= Unicode
;
1877 NewOne
->Open
= FileInterfaceFileOpen
;
1878 NewOne
->Close
= FileInterfaceFileClose
;
1879 NewOne
->Delete
= FileInterfaceFileDelete
;
1880 NewOne
->Read
= FileInterfaceFileRead
;
1881 NewOne
->Write
= FileInterfaceFileWrite
;
1882 NewOne
->GetPosition
= FileInterfaceFileGetPosition
;
1883 NewOne
->SetPosition
= FileInterfaceFileSetPosition
;
1884 NewOne
->GetInfo
= FileInterfaceFileGetInfo
;
1885 NewOne
->SetInfo
= FileInterfaceFileSetInfo
;
1886 NewOne
->Flush
= FileInterfaceFileFlush
;
1888 return ((EFI_FILE_PROTOCOL
*)NewOne
);