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
977 // Most if not all UEFI commands will have an '\r\n' at the end of any output.
978 // Since the output was redirected to a variable, it does not make sense to
979 // keep this. So, before closing, strip the trailing '\r\n' from the variable
985 Status
= IsVolatileEnv (((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &Volatile
);
986 if (EFI_ERROR (Status
)) {
990 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
991 if (Status
== EFI_BUFFER_TOO_SMALL
) {
992 NewBuffer
= AllocateZeroPool(NewSize
+ sizeof(CHAR16
));
993 if (NewBuffer
== NULL
) {
994 return EFI_OUT_OF_RESOURCES
;
996 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
999 if (!EFI_ERROR(Status
) && NewBuffer
!= NULL
) {
1001 if (StrSize(NewBuffer
) > 6)
1003 if ((((CHAR16
*)NewBuffer
)[(StrSize(NewBuffer
)/2) - 2] == CHAR_LINEFEED
)
1004 && (((CHAR16
*)NewBuffer
)[(StrSize(NewBuffer
)/2) - 3] == CHAR_CARRIAGE_RETURN
)) {
1005 ((CHAR16
*)NewBuffer
)[(StrSize(NewBuffer
)/2) - 3] = CHAR_NULL
;
1009 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, StrSize(NewBuffer
), NewBuffer
);
1011 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_NV(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, StrSize(NewBuffer
), NewBuffer
);
1016 SHELL_FREE_NON_NULL(NewBuffer
);
1017 FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
);
1022 File style interface for Environment Variable (Delete).
1024 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1026 @retval The return value from FileInterfaceEnvClose().
1030 FileInterfaceEnvDelete(
1031 IN EFI_FILE_PROTOCOL
*This
1034 SHELL_DELETE_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
);
1035 return (FileInterfaceEnvClose(This
));
1039 File style interface for Environment Variable (Read).
1041 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1042 @param[in, out] BufferSize Size in bytes of Buffer.
1043 @param[out] Buffer The pointer to the buffer to fill.
1045 @retval EFI_SUCCESS The data was read.
1049 FileInterfaceEnvRead(
1050 IN EFI_FILE_PROTOCOL
*This
,
1051 IN OUT UINTN
*BufferSize
,
1055 return (SHELL_GET_ENVIRONMENT_VARIABLE(
1056 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1062 File style interface for Volatile Environment Variable (Write).
1064 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1065 @param[in, out] BufferSize Size in bytes of Buffer.
1066 @param[in] Buffer The pointer to the buffer to write.
1068 @retval EFI_SUCCESS The data was read.
1072 FileInterfaceEnvVolWrite(
1073 IN EFI_FILE_PROTOCOL
*This
,
1074 IN OUT UINTN
*BufferSize
,
1085 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1086 if (Status
== EFI_BUFFER_TOO_SMALL
){
1087 NewBuffer
= AllocateZeroPool(NewSize
+ *BufferSize
+ sizeof(CHAR16
));
1088 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1090 if (!EFI_ERROR(Status
) && NewBuffer
!= NULL
) {
1091 while (((CHAR16
*)NewBuffer
)[NewSize
/2] == CHAR_NULL
) {
1093 // We want to overwrite the CHAR_NULL
1097 CopyMem((UINT8
*)NewBuffer
+ NewSize
+ 2, Buffer
, *BufferSize
);
1098 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, StrSize(NewBuffer
), NewBuffer
);
1099 FreePool(NewBuffer
);
1102 SHELL_FREE_NON_NULL(NewBuffer
);
1103 return (SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, *BufferSize
, Buffer
));
1109 File style interface for Non Volatile Environment Variable (Write).
1111 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1112 @param[in, out] BufferSize Size in bytes of Buffer.
1113 @param[in] Buffer The pointer to the buffer to write.
1115 @retval EFI_SUCCESS The data was read.
1119 FileInterfaceEnvNonVolWrite(
1120 IN EFI_FILE_PROTOCOL
*This
,
1121 IN OUT UINTN
*BufferSize
,
1132 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1133 if (Status
== EFI_BUFFER_TOO_SMALL
){
1134 NewBuffer
= AllocateZeroPool(NewSize
+ *BufferSize
);
1135 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
, &NewSize
, NewBuffer
);
1137 if (!EFI_ERROR(Status
)) {
1138 CopyMem((UINT8
*)NewBuffer
+ NewSize
, Buffer
, *BufferSize
);
1139 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
1140 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1141 NewSize
+ *BufferSize
,
1144 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
1145 ((EFI_FILE_PROTOCOL_ENVIRONMENT
*)This
)->Name
,
1152 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1153 environment variables through file operations.
1155 @param EnvName The name of the Environment Variable to be operated on.
1157 @retval NULL Memory could not be allocated.
1158 @return other a pointer to an EFI_FILE_PROTOCOL structure
1162 CreateFileInterfaceEnv(
1163 IN CONST CHAR16
*EnvName
1167 EFI_FILE_PROTOCOL_ENVIRONMENT
*EnvFileInterface
;
1171 if (EnvName
== NULL
) {
1175 Status
= IsVolatileEnv (EnvName
, &Volatile
);
1176 if (EFI_ERROR (Status
)) {
1183 EnvNameSize
= StrSize(EnvName
);
1184 EnvFileInterface
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT
)+EnvNameSize
);
1185 if (EnvFileInterface
== NULL
){
1190 // Assign the generic members
1192 EnvFileInterface
->Revision
= EFI_FILE_REVISION
;
1193 EnvFileInterface
->Open
= FileInterfaceOpenNotFound
;
1194 EnvFileInterface
->Close
= FileInterfaceEnvClose
;
1195 EnvFileInterface
->GetPosition
= FileInterfaceNopGetPosition
;
1196 EnvFileInterface
->SetPosition
= FileInterfaceNopSetPosition
;
1197 EnvFileInterface
->GetInfo
= FileInterfaceNopGetInfo
;
1198 EnvFileInterface
->SetInfo
= FileInterfaceNopSetInfo
;
1199 EnvFileInterface
->Flush
= FileInterfaceNopGeneric
;
1200 EnvFileInterface
->Delete
= FileInterfaceEnvDelete
;
1201 EnvFileInterface
->Read
= FileInterfaceEnvRead
;
1203 CopyMem(EnvFileInterface
->Name
, EnvName
, EnvNameSize
);
1206 // Assign the different members for Volatile and Non-Volatile variables
1209 EnvFileInterface
->Write
= FileInterfaceEnvVolWrite
;
1211 EnvFileInterface
->Write
= FileInterfaceEnvNonVolWrite
;
1213 return ((EFI_FILE_PROTOCOL
*)EnvFileInterface
);
1217 Move the cursor position one character backward.
1219 @param[in] LineLength Length of a line. Get it by calling QueryMode
1220 @param[in, out] Column Current column of the cursor position
1221 @param[in, out] Row Current row of the cursor position
1225 MoveCursorBackward (
1226 IN UINTN LineLength
,
1227 IN OUT UINTN
*Column
,
1232 // If current column is 0, move to the last column of the previous line,
1233 // otherwise, just decrement column.
1236 *Column
= LineLength
- 1;
1246 Move the cursor position one character forward.
1248 @param[in] LineLength Length of a line.
1249 @param[in] TotalRow Total row of a screen
1250 @param[in, out] Column Current column of the cursor position
1251 @param[in, out] Row Current row of the cursor position
1256 IN UINTN LineLength
,
1258 IN OUT UINTN
*Column
,
1263 // Increment Column.
1264 // If this puts column past the end of the line, move to first column
1268 if (*Column
>= LineLength
) {
1270 if ((*Row
) < TotalRow
- 1) {
1277 Prints out each previously typed command in the command list history log.
1279 When each screen is full it will pause for a key before continuing.
1281 @param[in] TotalCols How many columns are on the screen
1282 @param[in] TotalRows How many rows are on the screen
1283 @param[in] StartColumn which column to start at
1287 PrintCommandHistory (
1288 IN CONST UINTN TotalCols
,
1289 IN CONST UINTN TotalRows
,
1290 IN CONST UINTN StartColumn
1298 ShellPrintEx (-1, -1, L
"\n");
1302 // go through history list...
1304 for ( Node
= (BUFFER_LIST
*)GetFirstNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
)
1305 ; !IsNull(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &Node
->Link
)
1306 ; Node
= (BUFFER_LIST
*)GetNextNode(&ShellInfoObject
.ViewingSettings
.CommandHistory
.Link
, &Node
->Link
)
1309 LineCount
= ((StrLen (Node
->Buffer
) + StartColumn
+ 1) / TotalCols
) + 1;
1311 if (LineNumber
+ LineCount
>= TotalRows
) {
1312 ShellPromptForResponseHii(
1313 ShellPromptResponseTypeEnterContinue
,
1314 STRING_TOKEN (STR_SHELL_ENTER_TO_CONT
),
1315 ShellInfoObject
.HiiHandle
,
1320 ShellPrintEx (-1, -1, L
"%2d. %s\n", Index
, Node
->Buffer
);
1321 LineNumber
+= LineCount
;
1331 // This is identical to EFI_FILE_PROTOCOL except for the additional members
1332 // for the buffer, size, and position.
1338 EFI_FILE_CLOSE Close
;
1339 EFI_FILE_DELETE Delete
;
1341 EFI_FILE_WRITE Write
;
1342 EFI_FILE_GET_POSITION GetPosition
;
1343 EFI_FILE_SET_POSITION SetPosition
;
1344 EFI_FILE_GET_INFO GetInfo
;
1345 EFI_FILE_SET_INFO SetInfo
;
1346 EFI_FILE_FLUSH Flush
;
1352 } EFI_FILE_PROTOCOL_MEM
;
1355 File style interface for Mem (SetPosition).
1357 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1358 @param[out] Position The position to set.
1360 @retval EFI_SUCCESS The position was successfully changed.
1361 @retval EFI_INVALID_PARAMETER The Position was invalid.
1365 FileInterfaceMemSetPosition(
1366 IN EFI_FILE_PROTOCOL
*This
,
1370 if (Position
<= ((EFI_FILE_PROTOCOL_MEM
*)This
)->FileSize
) {
1371 ((EFI_FILE_PROTOCOL_MEM
*)This
)->Position
= Position
;
1372 return (EFI_SUCCESS
);
1374 return (EFI_INVALID_PARAMETER
);
1379 File style interface for Mem (GetPosition).
1381 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1382 @param[out] Position The pointer to the position.
1384 @retval EFI_SUCCESS The position was retrieved.
1388 FileInterfaceMemGetPosition(
1389 IN EFI_FILE_PROTOCOL
*This
,
1390 OUT UINT64
*Position
1393 *Position
= ((EFI_FILE_PROTOCOL_MEM
*)This
)->Position
;
1394 return (EFI_SUCCESS
);
1398 File style interface for Mem (Write).
1400 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1401 @param[in, out] BufferSize Size in bytes of Buffer.
1402 @param[in] Buffer The pointer to the buffer to write.
1404 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.
1405 @retval EFI_SUCCESS The data was written.
1409 FileInterfaceMemWrite(
1410 IN EFI_FILE_PROTOCOL
*This
,
1411 IN OUT UINTN
*BufferSize
,
1416 EFI_FILE_PROTOCOL_MEM
*MemFile
;
1418 MemFile
= (EFI_FILE_PROTOCOL_MEM
*) This
;
1419 if (MemFile
->Unicode
) {
1423 if ((UINTN
)(MemFile
->Position
+ (*BufferSize
)) > (UINTN
)(MemFile
->BufferSize
)) {
1424 MemFile
->Buffer
= ReallocatePool((UINTN
)(MemFile
->BufferSize
), (UINTN
)(MemFile
->BufferSize
) + (*BufferSize
) + MEM_WRITE_REALLOC_OVERHEAD
, MemFile
->Buffer
);
1425 MemFile
->BufferSize
+= (*BufferSize
) + MEM_WRITE_REALLOC_OVERHEAD
;
1427 CopyMem(((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, Buffer
, *BufferSize
);
1428 MemFile
->Position
+= (*BufferSize
);
1429 MemFile
->FileSize
= MemFile
->Position
;
1430 return (EFI_SUCCESS
);
1435 AsciiBuffer
= AllocateZeroPool(*BufferSize
);
1436 if (AsciiBuffer
== NULL
) {
1437 return (EFI_OUT_OF_RESOURCES
);
1439 AsciiSPrint(AsciiBuffer
, *BufferSize
, "%S", Buffer
);
1440 if ((UINTN
)(MemFile
->Position
+ AsciiStrSize(AsciiBuffer
)) > (UINTN
)(MemFile
->BufferSize
)) {
1441 MemFile
->Buffer
= ReallocatePool((UINTN
)(MemFile
->BufferSize
), (UINTN
)(MemFile
->BufferSize
) + AsciiStrSize(AsciiBuffer
) + MEM_WRITE_REALLOC_OVERHEAD
, MemFile
->Buffer
);
1442 MemFile
->BufferSize
+= AsciiStrSize(AsciiBuffer
) + MEM_WRITE_REALLOC_OVERHEAD
;
1444 CopyMem(((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, AsciiBuffer
, AsciiStrSize(AsciiBuffer
));
1445 MemFile
->Position
+= (*BufferSize
/ sizeof(CHAR16
));
1446 MemFile
->FileSize
= MemFile
->Position
;
1447 FreePool(AsciiBuffer
);
1448 return (EFI_SUCCESS
);
1453 File style interface for Mem (Read).
1455 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1456 @param[in, out] BufferSize Size in bytes of Buffer.
1457 @param[in] Buffer The pointer to the buffer to fill.
1459 @retval EFI_SUCCESS The data was read.
1463 FileInterfaceMemRead(
1464 IN EFI_FILE_PROTOCOL
*This
,
1465 IN OUT UINTN
*BufferSize
,
1469 EFI_FILE_PROTOCOL_MEM
*MemFile
;
1471 MemFile
= (EFI_FILE_PROTOCOL_MEM
*) This
;
1472 if (*BufferSize
> (UINTN
)((MemFile
->FileSize
) - (UINTN
)(MemFile
->Position
))) {
1473 (*BufferSize
) = (UINTN
)((MemFile
->FileSize
) - (UINTN
)(MemFile
->Position
));
1475 CopyMem(Buffer
, ((UINT8
*)MemFile
->Buffer
) + MemFile
->Position
, (*BufferSize
));
1476 MemFile
->Position
= MemFile
->Position
+ (*BufferSize
);
1477 return (EFI_SUCCESS
);
1481 File style interface for Mem (Close).
1483 Frees all memory associated with this object.
1485 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1487 @retval EFI_SUCCESS The 'file' was closed.
1491 FileInterfaceMemClose(
1492 IN EFI_FILE_PROTOCOL
*This
1495 SHELL_FREE_NON_NULL(((EFI_FILE_PROTOCOL_MEM
*)This
)->Buffer
);
1496 SHELL_FREE_NON_NULL(This
);
1497 return (EFI_SUCCESS
);
1501 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1502 a file entirely in memory through file operations.
1504 @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii.
1506 @retval NULL Memory could not be allocated.
1507 @return other A pointer to an EFI_FILE_PROTOCOL structure.
1511 CreateFileInterfaceMem(
1512 IN CONST BOOLEAN Unicode
1515 EFI_FILE_PROTOCOL_MEM
*FileInterface
;
1520 FileInterface
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_MEM
));
1521 if (FileInterface
== NULL
){
1526 // Assign the generic members
1528 FileInterface
->Revision
= EFI_FILE_REVISION
;
1529 FileInterface
->Open
= FileInterfaceOpenNotFound
;
1530 FileInterface
->Close
= FileInterfaceMemClose
;
1531 FileInterface
->GetPosition
= FileInterfaceMemGetPosition
;
1532 FileInterface
->SetPosition
= FileInterfaceMemSetPosition
;
1533 FileInterface
->GetInfo
= FileInterfaceNopGetInfo
;
1534 FileInterface
->SetInfo
= FileInterfaceNopSetInfo
;
1535 FileInterface
->Flush
= FileInterfaceNopGeneric
;
1536 FileInterface
->Delete
= FileInterfaceNopGeneric
;
1537 FileInterface
->Read
= FileInterfaceMemRead
;
1538 FileInterface
->Write
= FileInterfaceMemWrite
;
1539 FileInterface
->Unicode
= Unicode
;
1541 ASSERT(FileInterface
->Buffer
== NULL
);
1542 ASSERT(FileInterface
->BufferSize
== 0);
1543 ASSERT(FileInterface
->Position
== 0);
1546 FileInterface
->Buffer
= AllocateZeroPool(sizeof(gUnicodeFileTag
));
1547 if (FileInterface
->Buffer
== NULL
) {
1548 FreePool (FileInterface
);
1551 *((CHAR16
*) (FileInterface
->Buffer
)) = EFI_UNICODE_BYTE_ORDER_MARK
;
1552 FileInterface
->BufferSize
= 2;
1553 FileInterface
->Position
= 2;
1556 return ((EFI_FILE_PROTOCOL
*)FileInterface
);
1562 EFI_FILE_CLOSE Close
;
1563 EFI_FILE_DELETE Delete
;
1565 EFI_FILE_WRITE Write
;
1566 EFI_FILE_GET_POSITION GetPosition
;
1567 EFI_FILE_SET_POSITION SetPosition
;
1568 EFI_FILE_GET_INFO GetInfo
;
1569 EFI_FILE_SET_INFO SetInfo
;
1570 EFI_FILE_FLUSH Flush
;
1572 EFI_FILE_PROTOCOL
*Orig
;
1573 } EFI_FILE_PROTOCOL_FILE
;
1576 Set a files current position
1578 @param This Protocol instance pointer.
1579 @param Position Byte position from the start of the file.
1581 @retval EFI_SUCCESS Data was written.
1582 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
1587 FileInterfaceFileSetPosition(
1588 IN EFI_FILE_PROTOCOL
*This
,
1592 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->SetPosition(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, Position
);
1596 Get a file's current position
1598 @param This Protocol instance pointer.
1599 @param Position Byte position from the start of the file.
1601 @retval EFI_SUCCESS Data was written.
1602 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
1607 FileInterfaceFileGetPosition(
1608 IN EFI_FILE_PROTOCOL
*This
,
1609 OUT UINT64
*Position
1612 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->GetPosition(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, Position
);
1616 Get information about a file.
1618 @param This Protocol instance pointer.
1619 @param InformationType Type of information to return in Buffer.
1620 @param BufferSize On input size of buffer, on output amount of data in buffer.
1621 @param Buffer The buffer to return data.
1623 @retval EFI_SUCCESS Data was returned.
1624 @retval EFI_UNSUPPORT InformationType is not supported.
1625 @retval EFI_NO_MEDIA The device has no media.
1626 @retval EFI_DEVICE_ERROR The device reported an error.
1627 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1628 @retval EFI_WRITE_PROTECTED The device is write protected.
1629 @retval EFI_ACCESS_DENIED The file was open for read only.
1630 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
1635 FileInterfaceFileGetInfo(
1636 IN EFI_FILE_PROTOCOL
*This
,
1637 IN EFI_GUID
*InformationType
,
1638 IN OUT UINTN
*BufferSize
,
1642 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->GetInfo(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, InformationType
, BufferSize
, Buffer
);
1646 Set information about a file
1648 @param This Protocol instance pointer.
1649 @param InformationType Type of information in Buffer.
1650 @param BufferSize Size of buffer.
1651 @param Buffer The data to write.
1653 @retval EFI_SUCCESS Data was returned.
1654 @retval EFI_UNSUPPORT InformationType is not supported.
1655 @retval EFI_NO_MEDIA The device has no media.
1656 @retval EFI_DEVICE_ERROR The device reported an error.
1657 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1658 @retval EFI_WRITE_PROTECTED The device is write protected.
1659 @retval EFI_ACCESS_DENIED The file was open for read only.
1664 FileInterfaceFileSetInfo(
1665 IN EFI_FILE_PROTOCOL
*This
,
1666 IN EFI_GUID
*InformationType
,
1667 IN UINTN BufferSize
,
1671 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->SetInfo(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, InformationType
, BufferSize
, Buffer
);
1675 Flush data back for the file handle.
1677 @param This Protocol instance pointer.
1679 @retval EFI_SUCCESS Data was written.
1680 @retval EFI_UNSUPPORT Writes to Open directory are not supported.
1681 @retval EFI_NO_MEDIA The device has no media.
1682 @retval EFI_DEVICE_ERROR The device reported an error.
1683 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1684 @retval EFI_WRITE_PROTECTED The device is write protected.
1685 @retval EFI_ACCESS_DENIED The file was open for read only.
1686 @retval EFI_VOLUME_FULL The volume is full.
1691 FileInterfaceFileFlush(
1692 IN EFI_FILE_PROTOCOL
*This
1695 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Flush(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1699 Read data from the file.
1701 @param This Protocol instance pointer.
1702 @param BufferSize On input size of buffer, on output amount of data in buffer.
1703 @param Buffer The buffer in which data is read.
1705 @retval EFI_SUCCESS Data was read.
1706 @retval EFI_NO_MEDIA The device has no media.
1707 @retval EFI_DEVICE_ERROR The device reported an error.
1708 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1709 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
1714 FileInterfaceFileRead(
1715 IN EFI_FILE_PROTOCOL
*This
,
1716 IN OUT UINTN
*BufferSize
,
1720 CHAR8
*AsciiStrBuffer
;
1721 CHAR16
*UscStrBuffer
;
1725 if (((EFI_FILE_PROTOCOL_FILE
*)This
)->Unicode
) {
1729 return (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Read(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, BufferSize
, Buffer
));
1734 Size
= (*BufferSize
) / sizeof(CHAR16
);
1735 AsciiStrBuffer
= AllocateZeroPool(Size
+ sizeof(CHAR8
));
1736 if (AsciiStrBuffer
== NULL
) {
1737 return EFI_OUT_OF_RESOURCES
;
1739 UscStrBuffer
= AllocateZeroPool(*BufferSize
+ sizeof(CHAR16
));
1740 if (UscStrBuffer
== NULL
) {
1741 SHELL_FREE_NON_NULL(AsciiStrBuffer
);
1742 return EFI_OUT_OF_RESOURCES
;
1744 Status
= (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Read(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, &Size
, AsciiStrBuffer
));
1745 if (!EFI_ERROR(Status
)) {
1746 CharNum
= UnicodeSPrint(UscStrBuffer
, *BufferSize
+ sizeof(CHAR16
), L
"%a", AsciiStrBuffer
);
1747 if (CharNum
== Size
) {
1748 CopyMem (Buffer
, UscStrBuffer
, *BufferSize
);
1750 Status
= EFI_UNSUPPORTED
;
1753 SHELL_FREE_NON_NULL(AsciiStrBuffer
);
1754 SHELL_FREE_NON_NULL(UscStrBuffer
);
1760 Opens a new file relative to the source file's location.
1762 @param[in] This The protocol instance pointer.
1763 @param[out] NewHandle Returns File Handle for FileName.
1764 @param[in] FileName Null terminated string. "\", ".", and ".." are supported.
1765 @param[in] OpenMode Open mode for file.
1766 @param[in] Attributes Only used for EFI_FILE_MODE_CREATE.
1768 @retval EFI_SUCCESS The device was opened.
1769 @retval EFI_NOT_FOUND The specified file could not be found on the device.
1770 @retval EFI_NO_MEDIA The device has no media.
1771 @retval EFI_MEDIA_CHANGED The media has changed.
1772 @retval EFI_DEVICE_ERROR The device reported an error.
1773 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1774 @retval EFI_ACCESS_DENIED The service denied access to the file.
1775 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
1776 @retval EFI_VOLUME_FULL The volume is full.
1780 FileInterfaceFileOpen (
1781 IN EFI_FILE_PROTOCOL
*This
,
1782 OUT EFI_FILE_PROTOCOL
**NewHandle
,
1783 IN CHAR16
*FileName
,
1785 IN UINT64 Attributes
1788 return ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Open(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, NewHandle
, FileName
, OpenMode
, Attributes
);
1792 Close and delete the file handle.
1794 @param This Protocol instance pointer.
1796 @retval EFI_SUCCESS The device was opened.
1797 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
1802 FileInterfaceFileDelete(
1803 IN EFI_FILE_PROTOCOL
*This
1807 Status
= ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Delete(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1813 File style interface for File (Close).
1815 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1817 @retval EFI_SUCCESS The file was closed.
1821 FileInterfaceFileClose(
1822 IN EFI_FILE_PROTOCOL
*This
1826 Status
= ((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Close(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
);
1832 File style interface for File (Write).
1834 If the file was opened with ASCII mode the data will be processed through
1835 AsciiSPrint before writing.
1837 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1838 @param[in, out] BufferSize Size in bytes of Buffer.
1839 @param[in] Buffer The pointer to the buffer to write.
1841 @retval EFI_SUCCESS The data was written.
1845 FileInterfaceFileWrite(
1846 IN EFI_FILE_PROTOCOL
*This
,
1847 IN OUT UINTN
*BufferSize
,
1854 if (((EFI_FILE_PROTOCOL_FILE
*)This
)->Unicode
) {
1858 return (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Write(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, BufferSize
, Buffer
));
1863 AsciiBuffer
= AllocateZeroPool(*BufferSize
);
1864 AsciiSPrint(AsciiBuffer
, *BufferSize
, "%S", Buffer
);
1865 Size
= AsciiStrSize(AsciiBuffer
) - 1; // (we dont need the null terminator)
1866 Status
= (((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
->Write(((EFI_FILE_PROTOCOL_FILE
*)This
)->Orig
, &Size
, AsciiBuffer
));
1867 FreePool(AsciiBuffer
);
1873 Create a file interface with unicode information.
1875 This will create a new EFI_FILE_PROTOCOL identical to the Templace
1876 except that the new one has Unicode and Ascii knowledge.
1878 @param[in] Template A pointer to the EFI_FILE_PROTOCOL object.
1879 @param[in] Unicode TRUE for UCS-2, FALSE for ASCII.
1881 @return a new EFI_FILE_PROTOCOL object to be used instead of the template.
1884 CreateFileInterfaceFile(
1885 IN CONST EFI_FILE_PROTOCOL
*Template
,
1886 IN CONST BOOLEAN Unicode
1889 EFI_FILE_PROTOCOL_FILE
*NewOne
;
1891 NewOne
= AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_FILE
));
1892 if (NewOne
== NULL
) {
1895 CopyMem(NewOne
, Template
, sizeof(EFI_FILE_PROTOCOL_FILE
));
1896 NewOne
->Orig
= (EFI_FILE_PROTOCOL
*)Template
;
1897 NewOne
->Unicode
= Unicode
;
1898 NewOne
->Open
= FileInterfaceFileOpen
;
1899 NewOne
->Close
= FileInterfaceFileClose
;
1900 NewOne
->Delete
= FileInterfaceFileDelete
;
1901 NewOne
->Read
= FileInterfaceFileRead
;
1902 NewOne
->Write
= FileInterfaceFileWrite
;
1903 NewOne
->GetPosition
= FileInterfaceFileGetPosition
;
1904 NewOne
->SetPosition
= FileInterfaceFileSetPosition
;
1905 NewOne
->GetInfo
= FileInterfaceFileGetInfo
;
1906 NewOne
->SetInfo
= FileInterfaceFileSetInfo
;
1907 NewOne
->Flush
= FileInterfaceFileFlush
;
1909 return ((EFI_FILE_PROTOCOL
*)NewOne
);