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
)) {
426 if (Status
== EFI_NOT_READY
)
429 ZeroMem (CurrentString
, MaxStr
* sizeof(CHAR16
));
435 // Press PageUp or PageDown to scroll the history screen up or down.
436 // Press any other key to quit scrolling.
438 if (Key
.UnicodeChar
== 0 && (Key
.ScanCode
== SCAN_PAGE_UP
|| Key
.ScanCode
== SCAN_PAGE_DOWN
)) {
439 if (Key
.ScanCode
== SCAN_PAGE_UP
) {
440 ConsoleLoggerDisplayHistory(FALSE
, 0, ShellInfoObject
.ConsoleInfo
);
441 } else if (Key
.ScanCode
== SCAN_PAGE_DOWN
) {
442 ConsoleLoggerDisplayHistory(TRUE
, 0, ShellInfoObject
.ConsoleInfo
);
448 ConsoleLoggerStopHistory(ShellInfoObject
.ConsoleInfo
);
454 // If we are quitting TAB scrolling...
456 if (InTabScrolling
&& Key
.UnicodeChar
!= CHAR_TAB
) {
457 if (FoundFileList
!= NULL
) {
458 ShellInfoObject
.NewEfiShellProtocol
->FreeFileList (&FoundFileList
);
459 DEBUG_CODE(FoundFileList
= NULL
;);
461 InTabScrolling
= FALSE
;
464 switch (Key
.UnicodeChar
) {
465 case CHAR_CARRIAGE_RETURN
:
467 // All done, print a newline at the end of the string
469 TailRow
= Row
+ (StringLen
- StringCurPos
+ Column
) / TotalColumn
;
470 TailColumn
= (StringLen
- StringCurPos
+ Column
) % TotalColumn
;
471 ShellPrintEx ((INT32
)TailColumn
, (INT32
)TailRow
, L
"%N\n");
476 if (StringCurPos
!= 0) {
478 // If not move back beyond string beginning, move all characters behind
479 // the current position one character forward
482 Update
= StringCurPos
;
484 CopyMem (CurrentString
+ StringCurPos
, CurrentString
+ StringCurPos
+ 1, sizeof (CHAR16
) * (StringLen
- StringCurPos
));
487 // Adjust the current column and row
489 MoveCursorBackward (TotalColumn
, &Column
, &Row
);
495 // handle auto complete of file and directory names...
497 if (InTabScrolling
) {
498 ASSERT(FoundFileList
!= NULL
);
499 ASSERT(TabLinePos
!= NULL
);
500 TabLinePos
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&(FoundFileList
->Link
), &TabLinePos
->Link
);
501 if (IsNull(&(FoundFileList
->Link
), &TabLinePos
->Link
)) {
502 TabLinePos
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&(FoundFileList
->Link
), &TabLinePos
->Link
);
507 InQuotationMode
= FALSE
;
508 for (Index
= 0; Index
< StringLen
; Index
++) {
509 if (CurrentString
[Index
] == L
'\"') {
510 InQuotationMode
= (BOOLEAN
)(!InQuotationMode
);
512 if (CurrentString
[Index
] == L
' ' && !InQuotationMode
) {
514 TabUpdatePos
= Index
+ 1;
516 if (CurrentString
[Index
] == L
'\\') {
517 TabUpdatePos
= Index
+ 1;
520 if (StrStr(CurrentString
+ TabPos
, L
":") == NULL
) {
521 Cwd
= ShellInfoObject
.NewEfiShellProtocol
->GetCurDir(NULL
);
523 StrnCpyS(TabStr
, (*BufferSize
)/sizeof(CHAR16
), Cwd
, (*BufferSize
)/sizeof(CHAR16
) - 1);
524 StrCatS(TabStr
, (*BufferSize
)/sizeof(CHAR16
), L
"\\");
525 if (TabStr
[StrLen(TabStr
)-1] == L
'\\' && *(CurrentString
+ TabPos
) == L
'\\' ) {
526 TabStr
[StrLen(TabStr
)-1] = CHAR_NULL
;
529 (*BufferSize
)/sizeof(CHAR16
),
530 CurrentString
+ TabPos
,
535 StrnCatS(TabStr
, (*BufferSize
)/sizeof(CHAR16
), CurrentString
+ TabPos
, StringLen
- TabPos
);
538 StrnCpyS(TabStr
, (*BufferSize
)/sizeof(CHAR16
), CurrentString
+ TabPos
, (*BufferSize
)/sizeof(CHAR16
) - 1);
540 StrnCatS(TabStr
, (*BufferSize
)/sizeof(CHAR16
), L
"*", (*BufferSize
)/sizeof(CHAR16
) - 1 - StrLen(TabStr
));
541 FoundFileList
= NULL
;
542 Status
= ShellInfoObject
.NewEfiShellProtocol
->FindFiles(TabStr
, &FoundFileList
);
543 for ( TempStr
= CurrentString
545 ; TempStr
++); // note the ';'... empty for loop
547 // make sure we have a list before we do anything more...
549 if (EFI_ERROR (Status
) || FoundFileList
== NULL
) {
550 InTabScrolling
= FALSE
;
555 // enumerate through the list of files
557 for ( TempPos
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&(FoundFileList
->Link
))
558 ; !IsNull(&FoundFileList
->Link
, &TempPos
->Link
)
559 ; TempPos
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&(FoundFileList
->Link
), &(TempPos
->Link
))
562 // If "cd" is typed, only directory name will be auto-complete filled
563 // in either case . and .. will be removed.
565 if ((((TempStr
[0] == L
'c' || TempStr
[0] == L
'C') &&
566 (TempStr
[1] == L
'd' || TempStr
[1] == L
'D')
567 ) && ((ShellIsDirectory(TempPos
->FullName
) != EFI_SUCCESS
)
568 ||(StrCmp(TempPos
->FileName
, L
".") == 0)
569 ||(StrCmp(TempPos
->FileName
, L
"..") == 0)
570 )) || ((StrCmp(TempPos
->FileName
, L
".") == 0)
571 ||(StrCmp(TempPos
->FileName
, L
"..") == 0))){
572 TabLinePos
= TempPos
;
573 TempPos
= (EFI_SHELL_FILE_INFO
*)(RemoveEntryList(&(TempPos
->Link
))->BackLink
);
574 InternalFreeShellFileInfoNode(TabLinePos
);
577 if (FoundFileList
!= NULL
&& !IsListEmpty(&FoundFileList
->Link
)) {
578 TabLinePos
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&FoundFileList
->Link
);
579 InTabScrolling
= TRUE
;
581 ShellInfoObject
.NewEfiShellProtocol
->FreeFileList (&FoundFileList
);
588 if (Key
.UnicodeChar
>= ' ') {
590 // If we are at the buffer's end, drop the key
592 if (StringLen
== MaxStr
- 1 && (ShellInfoObject
.ViewingSettings
.InsertMode
|| StringCurPos
== StringLen
)) {
596 // If in insert mode, make space by moving each other character 1
597 // space higher in the array
599 if (ShellInfoObject
.ViewingSettings
.InsertMode
) {
600 CopyMem(CurrentString
+ StringCurPos
+ 1, CurrentString
+ StringCurPos
, (StringLen
- StringCurPos
)*sizeof(CurrentString
[0]));
603 CurrentString
[StringCurPos
] = Key
.UnicodeChar
;
604 Update
= StringCurPos
;
612 switch (Key
.ScanCode
) {
615 // Move characters behind current position one character forward
617 if (StringLen
!= 0) {
618 Update
= StringCurPos
;
620 CopyMem (CurrentString
+ StringCurPos
, CurrentString
+ StringCurPos
+ 1, sizeof (CHAR16
) * (StringLen
- StringCurPos
));
626 // Prepare to print the previous command
628 NewPos
= (BUFFER_LIST
*)GetPreviousNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
629 if (IsNull(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
)) {
630 NewPos
= (BUFFER_LIST
*)GetPreviousNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
636 // Prepare to print the next command
638 NewPos
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
639 if (NewPos
== (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
)) {
640 NewPos
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &LinePos
->Link
);
646 // Adjust current cursor position
648 if (StringCurPos
!= 0) {
650 MoveCursorBackward (TotalColumn
, &Column
, &Row
);
656 // Adjust current cursor position
658 if (StringCurPos
< StringLen
) {
660 MoveCursorForward (TotalColumn
, TotalRow
, &Column
, &Row
);
666 // Move current cursor position to the beginning of the command line
668 Row
-= (StringCurPos
+ StartColumn
) / TotalColumn
;
669 Column
= StartColumn
;
675 // Move current cursor position to the end of the command line
677 TailRow
= Row
+ (StringLen
- StringCurPos
+ Column
) / TotalColumn
;
678 TailColumn
= (StringLen
- StringCurPos
+ Column
) % TotalColumn
;
681 StringCurPos
= StringLen
;
686 // Prepare to clear the current command line
688 CurrentString
[0] = 0;
691 Row
-= (StringCurPos
+ StartColumn
) / TotalColumn
;
692 Column
= StartColumn
;
698 // Toggle the SEnvInsertMode flag
700 ShellInfoObject
.ViewingSettings
.InsertMode
= (BOOLEAN
)!ShellInfoObject
.ViewingSettings
.InsertMode
;
705 // Print command history
707 PrintCommandHistory (TotalColumn
, TotalRow
, 4);
708 *CurrentString
= CHAR_NULL
;
719 // If we are in auto-complete mode, we are preparing to print
720 // the next file or directory name
722 if (InTabScrolling
) {
724 // Adjust the column and row to the start of TAB-completion string.
726 Column
= (StartColumn
+ TabUpdatePos
) % TotalColumn
;
727 Row
-= (StartColumn
+ StringCurPos
) / TotalColumn
- (StartColumn
+ TabUpdatePos
) / TotalColumn
;
728 OutputLength
= StrLen (TabLinePos
->FileName
);
730 // if the output string contains blank space, quotation marks L'\"'
731 // should be added to the output.
733 if (StrStr(TabLinePos
->FileName
, L
" ") != NULL
){
734 TabOutputStr
[0] = L
'\"';
735 CopyMem (TabOutputStr
+ 1, TabLinePos
->FileName
, OutputLength
* sizeof (CHAR16
));
736 TabOutputStr
[OutputLength
+ 1] = L
'\"';
737 TabOutputStr
[OutputLength
+ 2] = CHAR_NULL
;
739 CopyMem (TabOutputStr
, TabLinePos
->FileName
, OutputLength
* sizeof (CHAR16
));
740 TabOutputStr
[OutputLength
] = CHAR_NULL
;
742 OutputLength
= StrLen (TabOutputStr
) < MaxStr
- 1 ? StrLen (TabOutputStr
) : MaxStr
- 1;
743 CopyMem (CurrentString
+ TabUpdatePos
, TabOutputStr
, OutputLength
* sizeof (CHAR16
));
744 CurrentString
[TabUpdatePos
+ OutputLength
] = CHAR_NULL
;
745 StringCurPos
= TabUpdatePos
+ OutputLength
;
746 Update
= TabUpdatePos
;
747 if (StringLen
> TabUpdatePos
+ OutputLength
) {
748 Delete
= StringLen
- TabUpdatePos
- OutputLength
;
753 // If we have a new position, we are preparing to print a previous or
756 if (NewPos
!= (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
)) {
757 Column
= StartColumn
;
758 Row
-= (StringCurPos
+ StartColumn
) / TotalColumn
;
761 NewPos
= (BUFFER_LIST
*)(&ShellInfoObject
.ViewingSettings
.CommandHistory
);
763 OutputLength
= StrLen (LinePos
->Buffer
) < MaxStr
- 1 ? StrLen (LinePos
->Buffer
) : MaxStr
- 1;
764 CopyMem (CurrentString
, LinePos
->Buffer
, OutputLength
* sizeof (CHAR16
));
765 CurrentString
[OutputLength
] = CHAR_NULL
;
767 StringCurPos
= OutputLength
;
770 // Draw new input string
773 if (StringLen
> OutputLength
) {
775 // If old string was longer, blank its tail
777 Delete
= StringLen
- OutputLength
;
781 // If we need to update the output do so now
783 if (Update
!= (UINTN
) -1) {
784 ShellPrintEx ((INT32
)Column
, (INT32
)Row
, L
"%s%.*s", CurrentString
+ Update
, Delete
, L
"");
785 StringLen
= StrLen (CurrentString
);
788 SetMem (CurrentString
+ StringLen
, Delete
* sizeof (CHAR16
), CHAR_NULL
);
791 if (StringCurPos
> StringLen
) {
792 StringCurPos
= StringLen
;
798 // After using print to reflect newly updates, if we're not using
799 // BACKSPACE and DELETE, we need to move the cursor position forward,
800 // so adjust row and column here.
802 if (Key
.UnicodeChar
!= CHAR_BACKSPACE
&& !(Key
.UnicodeChar
== 0 && Key
.ScanCode
== SCAN_DELETE
)) {
804 // Calulate row and column of the tail of current string
806 TailRow
= Row
+ (StringLen
- StringCurPos
+ Column
+ OutputLength
) / TotalColumn
;
807 TailColumn
= (StringLen
- StringCurPos
+ Column
+ OutputLength
) % TotalColumn
;
810 // If the tail of string reaches screen end, screen rolls up, so if
811 // Row does not equal TailRow, Row should be decremented
813 // (if we are recalling commands using UPPER and DOWN key, and if the
814 // old command is too long to fit the screen, TailColumn must be 79.
816 if (TailColumn
== 0 && TailRow
>= TotalRow
&& Row
!= TailRow
) {
820 // Calculate the cursor position after current operation. If cursor
821 // reaches line end, update both row and column, otherwise, only
822 // column will be changed.
824 if (Column
+ OutputLength
>= TotalColumn
) {
825 SkipLength
= OutputLength
- (TotalColumn
- Column
);
827 Row
+= SkipLength
/ TotalColumn
+ 1;
828 if (Row
> TotalRow
- 1) {
832 Column
= SkipLength
% TotalColumn
;
834 Column
+= OutputLength
;
841 // Set the cursor position for this key
843 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, Column
, Row
);
846 if (CurrentString
!= NULL
&& StrLen(CurrentString
) > 0) {
848 // add the line to the history buffer
850 AddLineToCommandHistory(CurrentString
);
854 FreePool (TabOutputStr
);
856 // Return the data to the caller
858 *BufferSize
= StringLen
* sizeof (CHAR16
);
861 // if this was used it should be deallocated by now...
862 // prevent memory leaks...
864 if (FoundFileList
!= NULL
) {
865 ShellInfoObject
.NewEfiShellProtocol
->FreeFileList (&FoundFileList
);
867 ASSERT(FoundFileList
== NULL
);
873 // FILE sytle interfaces for StdIn/StdOut/StdErr
875 EFI_FILE_PROTOCOL FileInterfaceStdIn
= {
877 FileInterfaceOpenNotFound
,
878 FileInterfaceNopGeneric
,
879 FileInterfaceNopGeneric
,
880 FileInterfaceStdInRead
,
881 FileInterfaceStdInWrite
,
882 FileInterfaceNopGetPosition
,
883 FileInterfaceNopSetPosition
,
884 FileInterfaceNopGetInfo
,
885 FileInterfaceNopSetInfo
,
886 FileInterfaceNopGeneric
889 EFI_FILE_PROTOCOL FileInterfaceStdOut
= {
891 FileInterfaceOpenNotFound
,
892 FileInterfaceNopGeneric
,
893 FileInterfaceNopGeneric
,
894 FileInterfaceStdOutRead
,
895 FileInterfaceStdOutWrite
,
896 FileInterfaceNopGetPosition
,
897 FileInterfaceNopSetPosition
,
898 FileInterfaceNopGetInfo
,
899 FileInterfaceNopSetInfo
,
900 FileInterfaceNopGeneric
903 EFI_FILE_PROTOCOL FileInterfaceStdErr
= {
905 FileInterfaceOpenNotFound
,
906 FileInterfaceNopGeneric
,
907 FileInterfaceNopGeneric
,
908 FileInterfaceStdErrRead
,
909 FileInterfaceStdErrWrite
,
910 FileInterfaceNopGetPosition
,
911 FileInterfaceNopSetPosition
,
912 FileInterfaceNopGetInfo
,
913 FileInterfaceNopSetInfo
,
914 FileInterfaceNopGeneric
917 EFI_FILE_PROTOCOL FileInterfaceNulFile
= {
919 FileInterfaceOpenNotFound
,
920 FileInterfaceNopGeneric
,
921 FileInterfaceNopGeneric
,
922 FileInterfaceNulRead
,
923 FileInterfaceNulWrite
,
924 FileInterfaceNopGetPosition
,
925 FileInterfaceNopSetPosition
,
926 FileInterfaceNopGetInfo
,
927 FileInterfaceNopSetInfo
,
928 FileInterfaceNopGeneric
935 // This is identical to EFI_FILE_PROTOCOL except for the additional member
942 EFI_FILE_CLOSE Close
;
943 EFI_FILE_DELETE Delete
;
945 EFI_FILE_WRITE Write
;
946 EFI_FILE_GET_POSITION GetPosition
;
947 EFI_FILE_SET_POSITION SetPosition
;
948 EFI_FILE_GET_INFO GetInfo
;
949 EFI_FILE_SET_INFO SetInfo
;
950 EFI_FILE_FLUSH Flush
;
952 } EFI_FILE_PROTOCOL_ENVIRONMENT
;
953 //ANSI compliance helper to get size of the struct.
954 #define SIZE_OF_EFI_FILE_PROTOCOL_ENVIRONMENT EFI_FIELD_OFFSET (EFI_FILE_PROTOCOL_ENVIRONMENT, Name)
957 File style interface for Environment Variable (Close).
959 Frees the memory for this object.
961 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
967 FileInterfaceEnvClose(
968 IN EFI_FILE_PROTOCOL
*This
976 // Most if not all UEFI commands will have an '\r\n' at the end of any output.
977 // Since the output was redirected to a variable, it does not make sense to
978 // keep this. So, before closing, strip the trailing '\r\n' from the variable
984 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
985 if (Status
== EFI_BUFFER_TOO_SMALL
) {
986 NewBuffer
= AllocateZeroPool(NewSize
+ sizeof(CHAR16
));
987 if (NewBuffer
== NULL
) {
988 return EFI_OUT_OF_RESOURCES
;
990 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
993 if (!EFI_ERROR(Status
) && NewBuffer
!= NULL
) {
995 if (StrSize(NewBuffer
) > 6)
997 if ((((CHAR16
*)NewBuffer
)[(StrSize(NewBuffer
)/2) - 2] == CHAR_LINEFEED
)
998 && (((CHAR16
*)NewBuffer
)[(StrSize(NewBuffer
)/2) - 3] == CHAR_CARRIAGE_RETURN
)) {
999 ((CHAR16
*)NewBuffer
)[(StrSize(NewBuffer
)/2) - 3] = CHAR_NULL
;
1002 if (IsVolatileEnv(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
)) {
1003 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, StrSize(NewBuffer
), NewBuffer
);
1005 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_NV(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, StrSize(NewBuffer
), NewBuffer
);
1010 SHELL_FREE_NON_NULL(NewBuffer
);
1011 FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
);
1016 File style interface for Environment Variable (Delete).
1018 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1020 @retval The return value from FileInterfaceEnvClose().
1024 FileInterfaceEnvDelete(
1025 IN EFI_FILE_PROTOCOL
*This
1028 SHELL_DELETE_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
);
1029 return (FileInterfaceEnvClose(This
));
1033 File style interface for Environment Variable (Read).
1035 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1036 @param[in, out] BufferSize Size in bytes of Buffer.
1037 @param[out] Buffer The pointer to the buffer to fill.
1039 @retval EFI_SUCCESS The data was read.
1043 FileInterfaceEnvRead(
1044 IN EFI_FILE_PROTOCOL
*This
,
1045 IN OUT UINTN
*BufferSize
,
1049 return (SHELL_GET_ENVIRONMENT_VARIABLE(
1050 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1056 File style interface for Volatile Environment Variable (Write).
1058 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1059 @param[in, out] BufferSize Size in bytes of Buffer.
1060 @param[in] Buffer The pointer to the buffer to write.
1062 @retval EFI_SUCCESS The data was read.
1066 FileInterfaceEnvVolWrite(
1067 IN EFI_FILE_PROTOCOL
*This
,
1068 IN OUT UINTN
*BufferSize
,
1079 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1080 if (Status
== EFI_BUFFER_TOO_SMALL
){
1081 NewBuffer
= AllocateZeroPool(NewSize
+ *BufferSize
+ sizeof(CHAR16
));
1082 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1084 if (!EFI_ERROR(Status
) && NewBuffer
!= NULL
) {
1085 while (((CHAR16
*)NewBuffer
)[NewSize
/2] == CHAR_NULL
) {
1087 // We want to overwrite the CHAR_NULL
1091 CopyMem((UINT8
*)NewBuffer
+ NewSize
+ 2, Buffer
, *BufferSize
);
1092 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, StrSize(NewBuffer
), NewBuffer
);
1093 FreePool(NewBuffer
);
1096 SHELL_FREE_NON_NULL(NewBuffer
);
1097 return (SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, *BufferSize
, Buffer
));
1103 File style interface for Non Volatile Environment Variable (Write).
1105 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1106 @param[in, out] BufferSize Size in bytes of Buffer.
1107 @param[in] Buffer The pointer to the buffer to write.
1109 @retval EFI_SUCCESS The data was read.
1113 FileInterfaceEnvNonVolWrite(
1114 IN EFI_FILE_PROTOCOL
*This
,
1115 IN OUT UINTN
*BufferSize
,
1126 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1127 if (Status
== EFI_BUFFER_TOO_SMALL
){
1128 NewBuffer
= AllocateZeroPool(NewSize
+ *BufferSize
);
1129 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1131 if (!EFI_ERROR(Status
)) {
1132 CopyMem((UINT8
*)NewBuffer
+ NewSize
, Buffer
, *BufferSize
);
1133 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
1134 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1135 NewSize
+ *BufferSize
,
1138 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
1139 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1146 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1147 environment variables through file operations.
1149 @param EnvName The name of the Environment Variable to be operated on.
1151 @retval NULL Memory could not be allocated.
1152 @return other a pointer to an EFI_FILE_PROTOCOL structure
1156 CreateFileInterfaceEnv(
1157 IN CONST CHAR16
*EnvName
1160 EFI_FILE_PROTOCOL_ENVIRONMENT
*EnvFileInterface
;
1163 if (EnvName
== NULL
) {
1170 EnvNameSize
= StrSize(EnvName
);
1171 EnvFileInterface
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT
)+EnvNameSize
);
1172 if (EnvFileInterface
== NULL
){
1177 // Assign the generic members
1179 EnvFileInterface
->Revision
= EFI_FILE_REVISION
;
1180 EnvFileInterface
->Open
= FileInterfaceOpenNotFound
;
1181 EnvFileInterface
->Close
= FileInterfaceEnvClose
;
1182 EnvFileInterface
->GetPosition
= FileInterfaceNopGetPosition
;
1183 EnvFileInterface
->SetPosition
= FileInterfaceNopSetPosition
;
1184 EnvFileInterface
->GetInfo
= FileInterfaceNopGetInfo
;
1185 EnvFileInterface
->SetInfo
= FileInterfaceNopSetInfo
;
1186 EnvFileInterface
->Flush
= FileInterfaceNopGeneric
;
1187 EnvFileInterface
->Delete
= FileInterfaceEnvDelete
;
1188 EnvFileInterface
->Read
= FileInterfaceEnvRead
;
1190 CopyMem(EnvFileInterface
->Name
, EnvName
, EnvNameSize
);
1193 // Assign the different members for Volatile and Non-Volatile variables
1195 if (IsVolatileEnv(EnvName
)) {
1196 EnvFileInterface
->Write
= FileInterfaceEnvVolWrite
;
1198 EnvFileInterface
->Write
= FileInterfaceEnvNonVolWrite
;
1200 return ((EFI_FILE_PROTOCOL
*)EnvFileInterface
);
1204 Move the cursor position one character backward.
1206 @param[in] LineLength Length of a line. Get it by calling QueryMode
1207 @param[in, out] Column Current column of the cursor position
1208 @param[in, out] Row Current row of the cursor position
1212 MoveCursorBackward (
1213 IN UINTN LineLength
,
1214 IN OUT UINTN
*Column
,
1219 // If current column is 0, move to the last column of the previous line,
1220 // otherwise, just decrement column.
1223 *Column
= LineLength
- 1;
1233 Move the cursor position one character forward.
1235 @param[in] LineLength Length of a line.
1236 @param[in] TotalRow Total row of a screen
1237 @param[in, out] Column Current column of the cursor position
1238 @param[in, out] Row Current row of the cursor position
1243 IN UINTN LineLength
,
1245 IN OUT UINTN
*Column
,
1250 // Increment Column.
1251 // If this puts column past the end of the line, move to first column
1255 if (*Column
>= LineLength
) {
1257 if ((*Row
) < TotalRow
- 1) {
1264 Prints out each previously typed command in the command list history log.
1266 When each screen is full it will pause for a key before continuing.
1268 @param[in] TotalCols How many columns are on the screen
1269 @param[in] TotalRows How many rows are on the screen
1270 @param[in] StartColumn which column to start at
1274 PrintCommandHistory (
1275 IN CONST UINTN TotalCols
,
1276 IN CONST UINTN TotalRows
,
1277 IN CONST UINTN StartColumn
1285 ShellPrintEx (-1, -1, L
"\n");
1289 // go through history list...
1291 for ( Node
= (BUFFER_LIST
*)GetFirstNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
)
1292 ; !IsNull(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &Node
->Link
)
1293 ; Node
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &Node
->Link
)
1296 LineCount
= ((StrLen (Node
->Buffer
) + StartColumn
+ 1) / TotalCols
) + 1;
1298 if (LineNumber
+ LineCount
>= TotalRows
) {
1299 ShellPromptForResponseHii(
1300 ShellPromptResponseTypeEnterContinue
,
1301 STRING_TOKEN (STR_SHELL_ENTER_TO_CONT
),
1302 ShellInfoObject
.HiiHandle
,
1307 ShellPrintEx (-1, -1, L
"%2d. %s\n", Index
, Node
->Buffer
);
1308 LineNumber
+= LineCount
;
1318 // This is identical to EFI_FILE_PROTOCOL except for the additional members
1319 // for the buffer, size, and position.
1325 EFI_FILE_CLOSE Close
;
1326 EFI_FILE_DELETE Delete
;
1328 EFI_FILE_WRITE Write
;
1329 EFI_FILE_GET_POSITION GetPosition
;
1330 EFI_FILE_SET_POSITION SetPosition
;
1331 EFI_FILE_GET_INFO GetInfo
;
1332 EFI_FILE_SET_INFO SetInfo
;
1333 EFI_FILE_FLUSH Flush
;
1339 } EFI_FILE_PROTOCOL_MEM
;
1342 File style interface for Mem (SetPosition).
1344 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1345 @param[out] Position The position to set.
1347 @retval EFI_SUCCESS The position was successfully changed.
1348 @retval EFI_INVALID_PARAMETER The Position was invalid.
1352 FileInterfaceMemSetPosition(
1353 IN EFI_FILE_PROTOCOL
*This
,
1357 if (Position
<= ((EFI_FILE_PROTOCOL_MEM
*)This
)->FileSize
) {
1358 ((EFI_FILE_PROTOCOL_MEM
*)This
)->Position
= Position
;
1359 return (EFI_SUCCESS
);
1361 return (EFI_INVALID_PARAMETER
);
1366 File style interface for Mem (GetPosition).
1368 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1369 @param[out] Position The pointer to the position.
1371 @retval EFI_SUCCESS The position was retrieved.
1375 FileInterfaceMemGetPosition(
1376 IN EFI_FILE_PROTOCOL
*This
,
1377 OUT UINT64
*Position
1380 *Position
= ((EFI_FILE_PROTOCOL_MEM
*)This
)->Position
;
1381 return (EFI_SUCCESS
);
1385 File style interface for Mem (Write).
1387 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1388 @param[in, out] BufferSize Size in bytes of Buffer.
1389 @param[in] Buffer The pointer to the buffer to write.
1391 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.
1392 @retval EFI_SUCCESS The data was written.
1396 FileInterfaceMemWrite(
1397 IN EFI_FILE_PROTOCOL
*This
,
1398 IN OUT UINTN
*BufferSize
,
1403 EFI_FILE_PROTOCOL_MEM
*MemFile
;
1405 MemFile
= (EFI_FILE_PROTOCOL_MEM
*) This
;
1406 if (MemFile
->Unicode
) {
1410 if ((UINTN
)(MemFile
->Position
+ (*BufferSize
)) > (UINTN
)(MemFile
->BufferSize
)) {
1411 MemFile
->Buffer
= ReallocatePool((UINTN
)(MemFile
->BufferSize
), (UINTN
)(MemFile
->BufferSize
) + (*BufferSize
) + MEM_WRITE_REALLOC_OVERHEAD
, MemFile
->Buffer
);
1412 MemFile
->BufferSize
+= (*BufferSize
) + MEM_WRITE_REALLOC_OVERHEAD
;
1414 CopyMem(((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, Buffer
, *BufferSize
);
1415 MemFile
->Position
+= (*BufferSize
);
1416 MemFile
->FileSize
= MemFile
->Position
;
1417 return (EFI_SUCCESS
);
1422 AsciiBuffer
= AllocateZeroPool(*BufferSize
);
1423 if (AsciiBuffer
== NULL
) {
1424 return (EFI_OUT_OF_RESOURCES
);
1426 AsciiSPrint(AsciiBuffer
, *BufferSize
, "%S", Buffer
);
1427 if ((UINTN
)(MemFile
->Position
+ AsciiStrSize(AsciiBuffer
)) > (UINTN
)(MemFile
->BufferSize
)) {
1428 MemFile
->Buffer
= ReallocatePool((UINTN
)(MemFile
->BufferSize
), (UINTN
)(MemFile
->BufferSize
) + AsciiStrSize(AsciiBuffer
) + MEM_WRITE_REALLOC_OVERHEAD
, MemFile
->Buffer
);
1429 MemFile
->BufferSize
+= AsciiStrSize(AsciiBuffer
) + MEM_WRITE_REALLOC_OVERHEAD
;
1431 CopyMem(((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, AsciiBuffer
, AsciiStrSize(AsciiBuffer
));
1432 MemFile
->Position
+= (*BufferSize
/ sizeof(CHAR16
));
1433 MemFile
->FileSize
= MemFile
->Position
;
1434 FreePool(AsciiBuffer
);
1435 return (EFI_SUCCESS
);
1440 File style interface for Mem (Read).
1442 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1443 @param[in, out] BufferSize Size in bytes of Buffer.
1444 @param[in] Buffer The pointer to the buffer to fill.
1446 @retval EFI_SUCCESS The data was read.
1450 FileInterfaceMemRead(
1451 IN EFI_FILE_PROTOCOL
*This
,
1452 IN OUT UINTN
*BufferSize
,
1456 EFI_FILE_PROTOCOL_MEM
*MemFile
;
1458 MemFile
= (EFI_FILE_PROTOCOL_MEM
*) This
;
1459 if (*BufferSize
> (UINTN
)((MemFile
->FileSize
) - (UINTN
)(MemFile
->Position
))) {
1460 (*BufferSize
) = (UINTN
)((MemFile
->FileSize
) - (UINTN
)(MemFile
->Position
));
1462 CopyMem(Buffer
, ((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, (*BufferSize
));
1463 MemFile
->Position
= MemFile
->Position
+ (*BufferSize
);
1464 return (EFI_SUCCESS
);
1468 File style interface for Mem (Close).
1470 Frees all memory associated with this object.
1472 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1474 @retval EFI_SUCCESS The 'file' was closed.
1478 FileInterfaceMemClose(
1479 IN EFI_FILE_PROTOCOL
*This
1482 SHELL_FREE_NON_NULL(((EFI_FILE_PROTOCOL_MEM
*)This
)->Buffer
);
1483 SHELL_FREE_NON_NULL(This
);
1484 return (EFI_SUCCESS
);
1488 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1489 a file entirely in memory through file operations.
1491 @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii.
1493 @retval NULL Memory could not be allocated.
1494 @return other A pointer to an EFI_FILE_PROTOCOL structure.
1498 CreateFileInterfaceMem(
1499 IN CONST BOOLEAN Unicode
1502 EFI_FILE_PROTOCOL_MEM
*FileInterface
;
1507 FileInterface
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_MEM
));
1508 if (FileInterface
== NULL
){
1513 // Assign the generic members
1515 FileInterface
->Revision
= EFI_FILE_REVISION
;
1516 FileInterface
->Open
= FileInterfaceOpenNotFound
;
1517 FileInterface
->Close
= FileInterfaceMemClose
;
1518 FileInterface
->GetPosition
= FileInterfaceMemGetPosition
;
1519 FileInterface
->SetPosition
= FileInterfaceMemSetPosition
;
1520 FileInterface
->GetInfo
= FileInterfaceNopGetInfo
;
1521 FileInterface
->SetInfo
= FileInterfaceNopSetInfo
;
1522 FileInterface
->Flush
= FileInterfaceNopGeneric
;
1523 FileInterface
->Delete
= FileInterfaceNopGeneric
;
1524 FileInterface
->Read
= FileInterfaceMemRead
;
1525 FileInterface
->Write
= FileInterfaceMemWrite
;
1526 FileInterface
->Unicode
= Unicode
;
1528 ASSERT(FileInterface
->Buffer
== NULL
);
1529 ASSERT(FileInterface
->BufferSize
== 0);
1530 ASSERT(FileInterface
->Position
== 0);
1533 FileInterface
->Buffer
= AllocateZeroPool(sizeof(gUnicodeFileTag
));
1534 if (FileInterface
->Buffer
== NULL
) {
1535 FreePool (FileInterface
);
1538 *((CHAR16
*) (FileInterface
->Buffer
)) = EFI_UNICODE_BYTE_ORDER_MARK
;
1539 FileInterface
->BufferSize
= 2;
1540 FileInterface
->Position
= 2;
1543 return ((EFI_FILE_PROTOCOL
*)FileInterface
);
1549 EFI_FILE_CLOSE Close
;
1550 EFI_FILE_DELETE Delete
;
1552 EFI_FILE_WRITE Write
;
1553 EFI_FILE_GET_POSITION GetPosition
;
1554 EFI_FILE_SET_POSITION SetPosition
;
1555 EFI_FILE_GET_INFO GetInfo
;
1556 EFI_FILE_SET_INFO SetInfo
;
1557 EFI_FILE_FLUSH Flush
;
1559 EFI_FILE_PROTOCOL
*Orig
;
1560 } EFI_FILE_PROTOCOL_FILE
;
1563 Set a files current position
1565 @param This Protocol instance pointer.
1566 @param Position Byte position from the start of the file.
1568 @retval EFI_SUCCESS Data was written.
1569 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
1574 FileInterfaceFileSetPosition(
1575 IN EFI_FILE_PROTOCOL
*This
,
1579 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->SetPosition(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, Position
);
1583 Get a file's current position
1585 @param This Protocol instance pointer.
1586 @param Position Byte position from the start of the file.
1588 @retval EFI_SUCCESS Data was written.
1589 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
1594 FileInterfaceFileGetPosition(
1595 IN EFI_FILE_PROTOCOL
*This
,
1596 OUT UINT64
*Position
1599 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->GetPosition(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, Position
);
1603 Get information about a file.
1605 @param This Protocol instance pointer.
1606 @param InformationType Type of information to return in Buffer.
1607 @param BufferSize On input size of buffer, on output amount of data in buffer.
1608 @param Buffer The buffer to return data.
1610 @retval EFI_SUCCESS Data was returned.
1611 @retval EFI_UNSUPPORT InformationType is not supported.
1612 @retval EFI_NO_MEDIA The device has no media.
1613 @retval EFI_DEVICE_ERROR The device reported an error.
1614 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1615 @retval EFI_WRITE_PROTECTED The device is write protected.
1616 @retval EFI_ACCESS_DENIED The file was open for read only.
1617 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
1622 FileInterfaceFileGetInfo(
1623 IN EFI_FILE_PROTOCOL
*This
,
1624 IN EFI_GUID
*InformationType
,
1625 IN OUT UINTN
*BufferSize
,
1629 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->GetInfo(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, InformationType
, BufferSize
, Buffer
);
1633 Set information about a file
1635 @param This Protocol instance pointer.
1636 @param InformationType Type of information in Buffer.
1637 @param BufferSize Size of buffer.
1638 @param Buffer The data to write.
1640 @retval EFI_SUCCESS Data was returned.
1641 @retval EFI_UNSUPPORT InformationType is not supported.
1642 @retval EFI_NO_MEDIA The device has no media.
1643 @retval EFI_DEVICE_ERROR The device reported an error.
1644 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1645 @retval EFI_WRITE_PROTECTED The device is write protected.
1646 @retval EFI_ACCESS_DENIED The file was open for read only.
1651 FileInterfaceFileSetInfo(
1652 IN EFI_FILE_PROTOCOL
*This
,
1653 IN EFI_GUID
*InformationType
,
1654 IN UINTN BufferSize
,
1658 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->SetInfo(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, InformationType
, BufferSize
, Buffer
);
1662 Flush data back for the file handle.
1664 @param This Protocol instance pointer.
1666 @retval EFI_SUCCESS Data was written.
1667 @retval EFI_UNSUPPORT Writes to Open directory are not supported.
1668 @retval EFI_NO_MEDIA The device has no media.
1669 @retval EFI_DEVICE_ERROR The device reported an error.
1670 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1671 @retval EFI_WRITE_PROTECTED The device is write protected.
1672 @retval EFI_ACCESS_DENIED The file was open for read only.
1673 @retval EFI_VOLUME_FULL The volume is full.
1678 FileInterfaceFileFlush(
1679 IN EFI_FILE_PROTOCOL
*This
1682 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Flush(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1686 Read data from the file.
1688 @param This Protocol instance pointer.
1689 @param BufferSize On input size of buffer, on output amount of data in buffer.
1690 @param Buffer The buffer in which data is read.
1692 @retval EFI_SUCCESS Data was read.
1693 @retval EFI_NO_MEDIA The device has no media.
1694 @retval EFI_DEVICE_ERROR The device reported an error.
1695 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1696 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
1701 FileInterfaceFileRead(
1702 IN EFI_FILE_PROTOCOL
*This
,
1703 IN OUT UINTN
*BufferSize
,
1707 CHAR8
*AsciiStrBuffer
;
1708 CHAR16
*UscStrBuffer
;
1712 if (((EFI_FILE_PROTOCOL_FILE
*)This
)->Unicode
) {
1716 return (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Read(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, BufferSize
, Buffer
));
1721 Size
= (*BufferSize
) / sizeof(CHAR16
);
1722 AsciiStrBuffer
= AllocateZeroPool(Size
+ sizeof(CHAR8
));
1723 if (AsciiStrBuffer
== NULL
) {
1724 return EFI_OUT_OF_RESOURCES
;
1726 UscStrBuffer
= AllocateZeroPool(*BufferSize
+ sizeof(CHAR16
));
1727 if (UscStrBuffer
== NULL
) {
1728 SHELL_FREE_NON_NULL(AsciiStrBuffer
);
1729 return EFI_OUT_OF_RESOURCES
;
1731 Status
= (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Read(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, &Size
, AsciiStrBuffer
));
1732 if (!EFI_ERROR(Status
)) {
1733 CharNum
= UnicodeSPrint(UscStrBuffer
, *BufferSize
+ sizeof(CHAR16
), L
"%a", AsciiStrBuffer
);
1734 if (CharNum
== Size
) {
1735 CopyMem (Buffer
, UscStrBuffer
, *BufferSize
);
1737 Status
= EFI_UNSUPPORTED
;
1740 SHELL_FREE_NON_NULL(AsciiStrBuffer
);
1741 SHELL_FREE_NON_NULL(UscStrBuffer
);
1747 Opens a new file relative to the source file's location.
1749 @param[in] This The protocol instance pointer.
1750 @param[out] NewHandle Returns File Handle for FileName.
1751 @param[in] FileName Null terminated string. "\", ".", and ".." are supported.
1752 @param[in] OpenMode Open mode for file.
1753 @param[in] Attributes Only used for EFI_FILE_MODE_CREATE.
1755 @retval EFI_SUCCESS The device was opened.
1756 @retval EFI_NOT_FOUND The specified file could not be found on the device.
1757 @retval EFI_NO_MEDIA The device has no media.
1758 @retval EFI_MEDIA_CHANGED The media has changed.
1759 @retval EFI_DEVICE_ERROR The device reported an error.
1760 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1761 @retval EFI_ACCESS_DENIED The service denied access to the file.
1762 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
1763 @retval EFI_VOLUME_FULL The volume is full.
1767 FileInterfaceFileOpen (
1768 IN EFI_FILE_PROTOCOL
*This
,
1769 OUT EFI_FILE_PROTOCOL
**NewHandle
,
1770 IN CHAR16
*FileName
,
1772 IN UINT64 Attributes
1775 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Open(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, NewHandle
, FileName
, OpenMode
, Attributes
);
1779 Close and delete the file handle.
1781 @param This Protocol instance pointer.
1783 @retval EFI_SUCCESS The device was opened.
1784 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
1789 FileInterfaceFileDelete(
1790 IN EFI_FILE_PROTOCOL
*This
1794 Status
= ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Delete(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1800 File style interface for File (Close).
1802 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1804 @retval EFI_SUCCESS The file was closed.
1808 FileInterfaceFileClose(
1809 IN EFI_FILE_PROTOCOL
*This
1813 Status
= ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Close(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1819 File style interface for File (Write).
1821 If the file was opened with ASCII mode the data will be processed through
1822 AsciiSPrint before writing.
1824 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1825 @param[in, out] BufferSize Size in bytes of Buffer.
1826 @param[in] Buffer The pointer to the buffer to write.
1828 @retval EFI_SUCCESS The data was written.
1832 FileInterfaceFileWrite(
1833 IN EFI_FILE_PROTOCOL
*This
,
1834 IN OUT UINTN
*BufferSize
,
1841 if (((EFI_FILE_PROTOCOL_FILE
*)This
)->Unicode
) {
1845 return (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Write(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, BufferSize
, Buffer
));
1850 AsciiBuffer
= AllocateZeroPool(*BufferSize
);
1851 AsciiSPrint(AsciiBuffer
, *BufferSize
, "%S", Buffer
);
1852 Size
= AsciiStrSize(AsciiBuffer
) - 1; // (we dont need the null terminator)
1853 Status
= (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Write(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, &Size
, AsciiBuffer
));
1854 FreePool(AsciiBuffer
);
1860 Create a file interface with unicode information.
1862 This will create a new EFI_FILE_PROTOCOL identical to the Templace
1863 except that the new one has Unicode and Ascii knowledge.
1865 @param[in] Template A pointer to the EFI_FILE_PROTOCOL object.
1866 @param[in] Unicode TRUE for UCS-2, FALSE for ASCII.
1868 @return a new EFI_FILE_PROTOCOL object to be used instead of the template.
1871 CreateFileInterfaceFile(
1872 IN CONST EFI_FILE_PROTOCOL
*Template
,
1873 IN CONST BOOLEAN Unicode
1876 EFI_FILE_PROTOCOL_FILE
*NewOne
;
1878 NewOne
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_FILE
));
1879 if (NewOne
== NULL
) {
1882 CopyMem(NewOne
, Template
, sizeof(EFI_FILE_PROTOCOL_FILE
));
1883 NewOne
->Orig
= (EFI_FILE_PROTOCOL
*)Template
;
1884 NewOne
->Unicode
= Unicode
;
1885 NewOne
->Open
= FileInterfaceFileOpen
;
1886 NewOne
->Close
= FileInterfaceFileClose
;
1887 NewOne
->Delete
= FileInterfaceFileDelete
;
1888 NewOne
->Read
= FileInterfaceFileRead
;
1889 NewOne
->Write
= FileInterfaceFileWrite
;
1890 NewOne
->GetPosition
= FileInterfaceFileGetPosition
;
1891 NewOne
->SetPosition
= FileInterfaceFileSetPosition
;
1892 NewOne
->GetInfo
= FileInterfaceFileGetInfo
;
1893 NewOne
->SetInfo
= FileInterfaceFileSetInfo
;
1894 NewOne
->Flush
= FileInterfaceFileFlush
;
1896 return ((EFI_FILE_PROTOCOL
*)NewOne
);