]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Application/Shell/FileHandleWrappers.c
ShellPkg: Do not write the UNICODE BOM on ConOut.
[mirror_edk2.git] / ShellPkg / Application / Shell / FileHandleWrappers.c
1 /** @file
2 EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables,
3 StdIn, StdOut, StdErr, etc...).
4
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
12
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.
15
16 **/
17
18 #include "Shell.h"
19 #include "FileHandleInternal.h"
20
21 /**
22 File style interface for console (Open).
23
24 @param[in] This Ignored.
25 @param[out] NewHandle Ignored.
26 @param[in] FileName Ignored.
27 @param[in] OpenMode Ignored.
28 @param[in] Attributes Ignored.
29
30 @retval EFI_NOT_FOUND
31 **/
32 EFI_STATUS
33 EFIAPI
34 FileInterfaceOpenNotFound(
35 IN EFI_FILE_PROTOCOL *This,
36 OUT EFI_FILE_PROTOCOL **NewHandle,
37 IN CHAR16 *FileName,
38 IN UINT64 OpenMode,
39 IN UINT64 Attributes
40 )
41 {
42 return (EFI_NOT_FOUND);
43 }
44
45 /**
46 File style interface for console (Close, Delete, & Flush)
47
48 @param[in] This Ignored.
49
50 @retval EFI_SUCCESS
51 **/
52 EFI_STATUS
53 EFIAPI
54 FileInterfaceNopGeneric(
55 IN EFI_FILE_PROTOCOL *This
56 )
57 {
58 return (EFI_SUCCESS);
59 }
60
61 /**
62 File style interface for console (GetPosition).
63
64 @param[in] This Ignored.
65 @param[out] Position Ignored.
66
67 @retval EFI_UNSUPPORTED
68 **/
69 EFI_STATUS
70 EFIAPI
71 FileInterfaceNopGetPosition(
72 IN EFI_FILE_PROTOCOL *This,
73 OUT UINT64 *Position
74 )
75 {
76 return (EFI_UNSUPPORTED);
77 }
78
79 /**
80 File style interface for console (SetPosition).
81
82 @param[in] This Ignored.
83 @param[in] Position Ignored.
84
85 @retval EFI_UNSUPPORTED
86 **/
87 EFI_STATUS
88 EFIAPI
89 FileInterfaceNopSetPosition(
90 IN EFI_FILE_PROTOCOL *This,
91 IN UINT64 Position
92 )
93 {
94 return (EFI_UNSUPPORTED);
95 }
96
97 /**
98 File style interface for console (GetInfo).
99
100 @param[in] This Ignored.
101 @param[in] InformationType Ignored.
102 @param[in, out] BufferSize Ignored.
103 @param[out] Buffer Ignored.
104
105 @retval EFI_UNSUPPORTED
106 **/
107 EFI_STATUS
108 EFIAPI
109 FileInterfaceNopGetInfo(
110 IN EFI_FILE_PROTOCOL *This,
111 IN EFI_GUID *InformationType,
112 IN OUT UINTN *BufferSize,
113 OUT VOID *Buffer
114 )
115 {
116 return (EFI_UNSUPPORTED);
117 }
118
119 /**
120 File style interface for console (SetInfo).
121
122 @param[in] This Ignored.
123 @param[in] InformationType Ignored.
124 @param[in] BufferSize Ignored.
125 @param[in] Buffer Ignored.
126
127 @retval EFI_UNSUPPORTED
128 **/
129 EFI_STATUS
130 EFIAPI
131 FileInterfaceNopSetInfo(
132 IN EFI_FILE_PROTOCOL *This,
133 IN EFI_GUID *InformationType,
134 IN UINTN BufferSize,
135 IN VOID *Buffer
136 )
137 {
138 return (EFI_UNSUPPORTED);
139 }
140
141 /**
142 File style interface for StdOut (Write).
143
144 Writes data to the screen.
145
146 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
147 @param[in, out] BufferSize Size in bytes of Buffer.
148 @param[in] Buffer The pointer to the buffer to write.
149
150 @retval EFI_UNSUPPORTED No output console is supported.
151 @return A return value from gST->ConOut->OutputString.
152 **/
153 EFI_STATUS
154 EFIAPI
155 FileInterfaceStdOutWrite(
156 IN EFI_FILE_PROTOCOL *This,
157 IN OUT UINTN *BufferSize,
158 IN VOID *Buffer
159 )
160 {
161 if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
162 return (EFI_UNSUPPORTED);
163 }
164 if (*((CHAR16 *)Buffer) == gUnicodeFileTag) {
165 return (gST->ConOut->OutputString(gST->ConOut, (CHAR16 *)Buffer + 1));
166 }
167 return (gST->ConOut->OutputString(gST->ConOut, Buffer));
168 }
169
170 /**
171 File style interface for StdIn (Write).
172
173 @param[in] This Ignored.
174 @param[in, out] BufferSize Ignored.
175 @param[in] Buffer Ignored.
176
177 @retval EFI_UNSUPPORTED
178 **/
179 EFI_STATUS
180 EFIAPI
181 FileInterfaceStdInWrite(
182 IN EFI_FILE_PROTOCOL *This,
183 IN OUT UINTN *BufferSize,
184 IN VOID *Buffer
185 )
186 {
187 return (EFI_UNSUPPORTED);
188 }
189
190 /**
191 File style interface for console StdErr (Write).
192
193 Writes error to the error output.
194
195 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
196 @param[in, out] BufferSize Size in bytes of Buffer.
197 @param[in] Buffer The pointer to the buffer to write.
198
199 @return A return value from gST->StdErr->OutputString.
200 **/
201 EFI_STATUS
202 EFIAPI
203 FileInterfaceStdErrWrite(
204 IN EFI_FILE_PROTOCOL *This,
205 IN OUT UINTN *BufferSize,
206 IN VOID *Buffer
207 )
208 {
209 return (gST->StdErr->OutputString(gST->StdErr, Buffer));
210 }
211
212 /**
213 File style interface for console StdOut (Read).
214
215 @param[in] This Ignored.
216 @param[in, out] BufferSize Ignored.
217 @param[out] Buffer Ignored.
218
219 @retval EFI_UNSUPPORTED
220 **/
221 EFI_STATUS
222 EFIAPI
223 FileInterfaceStdOutRead(
224 IN EFI_FILE_PROTOCOL *This,
225 IN OUT UINTN *BufferSize,
226 OUT VOID *Buffer
227 )
228 {
229 return (EFI_UNSUPPORTED);
230 }
231
232 /**
233 File style interface for console StdErr (Read).
234
235 @param[in] This Ignored.
236 @param[in, out] BufferSize Ignored.
237 @param[out] Buffer Ignored.
238
239 @retval EFI_UNSUPPORTED Always.
240 **/
241 EFI_STATUS
242 EFIAPI
243 FileInterfaceStdErrRead(
244 IN EFI_FILE_PROTOCOL *This,
245 IN OUT UINTN *BufferSize,
246 OUT VOID *Buffer
247 )
248 {
249 return (EFI_UNSUPPORTED);
250 }
251
252 /**
253 File style interface for NUL file (Read).
254
255 @param[in] This Ignored.
256 @param[in, out] BufferSize Poiner to 0 upon return.
257 @param[out] Buffer Ignored.
258
259 @retval EFI_SUCCESS Always.
260 **/
261 EFI_STATUS
262 EFIAPI
263 FileInterfaceNulRead(
264 IN EFI_FILE_PROTOCOL *This,
265 IN OUT UINTN *BufferSize,
266 OUT VOID *Buffer
267 )
268 {
269 *BufferSize = 0;
270 return (EFI_SUCCESS);
271 }
272
273 /**
274 File style interface for NUL file (Write).
275
276 @param[in] This Ignored.
277 @param[in, out] BufferSize Ignored.
278 @param[in] Buffer Ignored.
279
280 @retval EFI_SUCCESS
281 **/
282 EFI_STATUS
283 EFIAPI
284 FileInterfaceNulWrite(
285 IN EFI_FILE_PROTOCOL *This,
286 IN OUT UINTN *BufferSize,
287 IN VOID *Buffer
288 )
289 {
290 return (EFI_SUCCESS);
291 }
292
293 /**
294 File style interface for console (Read).
295
296 This will return a single line of input from the console.
297
298 @param This A pointer to the EFI_FILE_PROTOCOL instance that is the
299 file handle to read data from. Not used.
300 @param BufferSize On input, the size of the Buffer. On output, the amount
301 of data returned in Buffer. In both cases, the size is
302 measured in bytes.
303 @param Buffer The buffer into which the data is read.
304
305
306 @retval EFI_SUCCESS The data was read.
307 @retval EFI_NO_MEDIA The device has no medium.
308 @retval EFI_DEVICE_ERROR The device reported an error.
309 @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file.
310 @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file.
311 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
312 @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory
313 entry. BufferSize has been updated with the size
314 needed to complete the request.
315 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
316 **/
317 EFI_STATUS
318 EFIAPI
319 FileInterfaceStdInRead(
320 IN EFI_FILE_PROTOCOL *This,
321 IN OUT UINTN *BufferSize,
322 OUT VOID *Buffer
323 )
324 {
325 CHAR16 *CurrentString;
326 BOOLEAN Done;
327 UINTN Column; // Column of current cursor
328 UINTN Row; // Row of current cursor
329 UINTN StartColumn; // Column at the beginning of the line
330 UINTN Update; // Line index for update
331 UINTN Delete; // Num of chars to delete from console after update
332 UINTN StringLen; // Total length of the line
333 UINTN StringCurPos; // Line index corresponding to the cursor
334 UINTN MaxStr; // Maximum possible line length
335 UINTN Index;
336 UINTN TotalColumn; // Num of columns in the console
337 UINTN TotalRow; // Num of rows in the console
338 UINTN SkipLength;
339 UINTN OutputLength; // Length of the update string
340 UINTN TailRow; // Row of end of line
341 UINTN TailColumn; // Column of end of line
342 EFI_INPUT_KEY Key;
343
344 BUFFER_LIST *LinePos;
345 BUFFER_LIST *NewPos;
346 BOOLEAN InScrolling;
347 EFI_STATUS Status;
348 BOOLEAN InTabScrolling; // Whether in TAB-completion state
349 EFI_SHELL_FILE_INFO *FoundFileList;
350 EFI_SHELL_FILE_INFO *TabLinePos;
351 EFI_SHELL_FILE_INFO *TempPos;
352 CHAR16 *TabStr;
353 CHAR16 *TabOutputStr;
354 BOOLEAN InQuotationMode;
355 CHAR16 *TempStr;
356 UINTN TabPos; // Start index of the string to search for TAB completion.
357 UINTN TabUpdatePos; // Start index of the string updated by TAB stroke
358 // UINTN Count;
359 UINTN EventIndex;
360 CONST CHAR16 *Cwd;
361
362 //
363 // If buffer is not large enough to hold a CHAR16, return minimum buffer size
364 //
365 if (*BufferSize < sizeof (CHAR16) * 2) {
366 *BufferSize = sizeof (CHAR16) * 2;
367 return (EFI_BUFFER_TOO_SMALL);
368 }
369
370 Done = FALSE;
371 CurrentString = Buffer;
372 StringLen = 0;
373 StringCurPos = 0;
374 OutputLength = 0;
375 Update = 0;
376 Delete = 0;
377 LinePos = NewPos = (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory);
378 InScrolling = FALSE;
379 InTabScrolling = FALSE;
380 Status = EFI_SUCCESS;
381 TabLinePos = NULL;
382 FoundFileList = NULL;
383 TempPos = NULL;
384 TabPos = 0;
385 TabUpdatePos = 0;
386
387 //
388 // Allocate buffers
389 //
390 TabStr = AllocateZeroPool (*BufferSize);
391 if (TabStr == NULL) {
392 return EFI_OUT_OF_RESOURCES;
393 }
394 TabOutputStr = AllocateZeroPool (*BufferSize);
395 if (TabOutputStr == NULL) {
396 FreePool(TabStr);
397 return EFI_OUT_OF_RESOURCES;
398 }
399
400 //
401 // Get the screen setting and the current cursor location
402 //
403 Column = StartColumn = gST->ConOut->Mode->CursorColumn;
404 Row = gST->ConOut->Mode->CursorRow;
405 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &TotalColumn, &TotalRow);
406
407 //
408 // Limit the line length to the buffer size or the minimun size of the
409 // screen. (The smaller takes effect)
410 //
411 MaxStr = TotalColumn * (TotalRow - 1) - StartColumn;
412 if (MaxStr > *BufferSize / sizeof (CHAR16)) {
413 MaxStr = *BufferSize / sizeof (CHAR16);
414 }
415 ZeroMem (CurrentString, MaxStr * sizeof (CHAR16));
416 do {
417 //
418 // Read a key
419 //
420 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
421 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
422 if (EFI_ERROR (Status)) {
423 break;
424 }
425
426 //
427 // Press PageUp or PageDown to scroll the history screen up or down.
428 // Press any other key to quit scrolling.
429 //
430 if (Key.UnicodeChar == 0 && (Key.ScanCode == SCAN_PAGE_UP || Key.ScanCode == SCAN_PAGE_DOWN)) {
431 if (Key.ScanCode == SCAN_PAGE_UP) {
432 ConsoleLoggerDisplayHistory(FALSE, 0, ShellInfoObject.ConsoleInfo);
433 } else if (Key.ScanCode == SCAN_PAGE_DOWN) {
434 ConsoleLoggerDisplayHistory(TRUE, 0, ShellInfoObject.ConsoleInfo);
435 }
436
437 InScrolling = TRUE;
438 } else {
439 if (InScrolling) {
440 ConsoleLoggerStopHistory(ShellInfoObject.ConsoleInfo);
441 InScrolling = FALSE;
442 }
443 }
444
445 //
446 // If we are quitting TAB scrolling...
447 //
448 if (InTabScrolling && Key.UnicodeChar != CHAR_TAB) {
449 if (FoundFileList != NULL) {
450 ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
451 DEBUG_CODE(FoundFileList = NULL;);
452 }
453 InTabScrolling = FALSE;
454 }
455
456 switch (Key.UnicodeChar) {
457 case CHAR_CARRIAGE_RETURN:
458 //
459 // All done, print a newline at the end of the string
460 //
461 TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn;
462 TailColumn = (StringLen - StringCurPos + Column) % TotalColumn;
463 ShellPrintEx ((INT32)TailColumn, (INT32)TailRow, L"%N\n");
464 Done = TRUE;
465 break;
466
467 case CHAR_BACKSPACE:
468 if (StringCurPos != 0) {
469 //
470 // If not move back beyond string beginning, move all characters behind
471 // the current position one character forward
472 //
473 StringCurPos--;
474 Update = StringCurPos;
475 Delete = 1;
476 CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos));
477
478 //
479 // Adjust the current column and row
480 //
481 MoveCursorBackward (TotalColumn, &Column, &Row);
482 }
483 break;
484
485 case CHAR_TAB:
486 //
487 // handle auto complete of file and directory names...
488 //
489 if (InTabScrolling) {
490 ASSERT(FoundFileList != NULL);
491 ASSERT(TabLinePos != NULL);
492 TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);
493 if (IsNull(&(FoundFileList->Link), &TabLinePos->Link)) {
494 TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);
495 }
496 } else {
497 TabPos = 0;
498 TabUpdatePos = 0;
499 InQuotationMode = FALSE;
500 for (Index = 0; Index < StringLen; Index++) {
501 if (CurrentString[Index] == L'\"') {
502 InQuotationMode = (BOOLEAN)(!InQuotationMode);
503 }
504 if (CurrentString[Index] == L' ' && !InQuotationMode) {
505 TabPos = Index + 1;
506 TabUpdatePos = Index + 1;
507 }
508 if (CurrentString[Index] == L'\\') {
509 TabUpdatePos = Index + 1;
510 }
511 }
512 if (StrStr(CurrentString + TabPos, L":") == NULL) {
513 Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir(NULL);
514 if (Cwd != NULL) {
515 StrnCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), Cwd, (*BufferSize)/sizeof(CHAR16) - 1);
516 StrCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"\\");
517 if (TabStr[StrLen(TabStr)-1] == L'\\' && *(CurrentString + TabPos) == L'\\' ) {
518 TabStr[StrLen(TabStr)-1] = CHAR_NULL;
519 }
520 StrnCatS( TabStr,
521 (*BufferSize)/sizeof(CHAR16),
522 CurrentString + TabPos,
523 StringLen - TabPos
524 );
525 } else {
526 *TabStr = CHAR_NULL;
527 StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos, StringLen - TabPos);
528 }
529 } else {
530 StrnCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos, (*BufferSize)/sizeof(CHAR16) - 1);
531 }
532 StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"*", (*BufferSize)/sizeof(CHAR16) - 1 - StrLen(TabStr));
533 FoundFileList = NULL;
534 Status = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FoundFileList);
535 for ( TempStr = CurrentString
536 ; *TempStr == L' '
537 ; TempStr++); // note the ';'... empty for loop
538 //
539 // make sure we have a list before we do anything more...
540 //
541 if (EFI_ERROR (Status) || FoundFileList == NULL) {
542 InTabScrolling = FALSE;
543 TabLinePos = NULL;
544 continue;
545 } else {
546 //
547 // enumerate through the list of files
548 //
549 for ( TempPos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(FoundFileList->Link))
550 ; !IsNull(&FoundFileList->Link, &TempPos->Link)
551 ; TempPos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &(TempPos->Link))
552 ){
553 //
554 // If "cd" is typed, only directory name will be auto-complete filled
555 // in either case . and .. will be removed.
556 //
557 if ((((TempStr[0] == L'c' || TempStr[0] == L'C') &&
558 (TempStr[1] == L'd' || TempStr[1] == L'D')
559 ) && ((ShellIsDirectory(TempPos->FullName) != EFI_SUCCESS)
560 ||(StrCmp(TempPos->FileName, L".") == 0)
561 ||(StrCmp(TempPos->FileName, L"..") == 0)
562 )) || ((StrCmp(TempPos->FileName, L".") == 0)
563 ||(StrCmp(TempPos->FileName, L"..") == 0))){
564 TabLinePos = TempPos;
565 TempPos = (EFI_SHELL_FILE_INFO*)(RemoveEntryList(&(TempPos->Link))->BackLink);
566 InternalFreeShellFileInfoNode(TabLinePos);
567 }
568 }
569 if (FoundFileList != NULL && !IsListEmpty(&FoundFileList->Link)) {
570 TabLinePos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FoundFileList->Link);
571 InTabScrolling = TRUE;
572 } else {
573 FreePool(FoundFileList);
574 FoundFileList = NULL;
575 }
576 }
577 }
578 break;
579
580 default:
581 if (Key.UnicodeChar >= ' ') {
582 //
583 // If we are at the buffer's end, drop the key
584 //
585 if (StringLen == MaxStr - 1 && (ShellInfoObject.ViewingSettings.InsertMode || StringCurPos == StringLen)) {
586 break;
587 }
588 //
589 // If in insert mode, make space by moving each other character 1
590 // space higher in the array
591 //
592 if (ShellInfoObject.ViewingSettings.InsertMode) {
593 CopyMem(CurrentString + StringCurPos + 1, CurrentString + StringCurPos, (StringLen - StringCurPos)*sizeof(CurrentString[0]));
594 }
595
596 CurrentString[StringCurPos] = Key.UnicodeChar;
597 Update = StringCurPos;
598
599 StringCurPos += 1;
600 OutputLength = 1;
601 }
602 break;
603
604 case 0:
605 switch (Key.ScanCode) {
606 case SCAN_DELETE:
607 //
608 // Move characters behind current position one character forward
609 //
610 if (StringLen != 0) {
611 Update = StringCurPos;
612 Delete = 1;
613 CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos));
614 }
615 break;
616
617 case SCAN_UP:
618 //
619 // Prepare to print the previous command
620 //
621 NewPos = (BUFFER_LIST*)GetPreviousNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
622 if (IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link)) {
623 NewPos = (BUFFER_LIST*)GetPreviousNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
624 }
625 break;
626
627 case SCAN_DOWN:
628 //
629 // Prepare to print the next command
630 //
631 NewPos = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
632 if (NewPos == (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory)) {
633 NewPos = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
634 }
635 break;
636
637 case SCAN_LEFT:
638 //
639 // Adjust current cursor position
640 //
641 if (StringCurPos != 0) {
642 --StringCurPos;
643 MoveCursorBackward (TotalColumn, &Column, &Row);
644 }
645 break;
646
647 case SCAN_RIGHT:
648 //
649 // Adjust current cursor position
650 //
651 if (StringCurPos < StringLen) {
652 ++StringCurPos;
653 MoveCursorForward (TotalColumn, TotalRow, &Column, &Row);
654 }
655 break;
656
657 case SCAN_HOME:
658 //
659 // Move current cursor position to the beginning of the command line
660 //
661 Row -= (StringCurPos + StartColumn) / TotalColumn;
662 Column = StartColumn;
663 StringCurPos = 0;
664 break;
665
666 case SCAN_END:
667 //
668 // Move current cursor position to the end of the command line
669 //
670 TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn;
671 TailColumn = (StringLen - StringCurPos + Column) % TotalColumn;
672 Row = TailRow;
673 Column = TailColumn;
674 StringCurPos = StringLen;
675 break;
676
677 case SCAN_ESC:
678 //
679 // Prepare to clear the current command line
680 //
681 CurrentString[0] = 0;
682 Update = 0;
683 Delete = StringLen;
684 Row -= (StringCurPos + StartColumn) / TotalColumn;
685 Column = StartColumn;
686 OutputLength = 0;
687 break;
688
689 case SCAN_INSERT:
690 //
691 // Toggle the SEnvInsertMode flag
692 //
693 ShellInfoObject.ViewingSettings.InsertMode = (BOOLEAN)!ShellInfoObject.ViewingSettings.InsertMode;
694 break;
695
696 case SCAN_F7:
697 //
698 // Print command history
699 //
700 PrintCommandHistory (TotalColumn, TotalRow, 4);
701 *CurrentString = CHAR_NULL;
702 Done = TRUE;
703 break;
704 }
705 }
706
707 if (Done) {
708 break;
709 }
710
711 //
712 // If we are in auto-complete mode, we are preparing to print
713 // the next file or directory name
714 //
715 if (InTabScrolling) {
716 //
717 // Adjust the column and row to the start of TAB-completion string.
718 //
719 Column = (StartColumn + TabUpdatePos) % TotalColumn;
720 Row -= (StartColumn + StringCurPos) / TotalColumn - (StartColumn + TabUpdatePos) / TotalColumn;
721 OutputLength = StrLen (TabLinePos->FileName);
722 //
723 // if the output string contains blank space, quotation marks L'\"'
724 // should be added to the output.
725 //
726 if (StrStr(TabLinePos->FileName, L" ") != NULL){
727 TabOutputStr[0] = L'\"';
728 CopyMem (TabOutputStr + 1, TabLinePos->FileName, OutputLength * sizeof (CHAR16));
729 TabOutputStr[OutputLength + 1] = L'\"';
730 TabOutputStr[OutputLength + 2] = CHAR_NULL;
731 } else {
732 CopyMem (TabOutputStr, TabLinePos->FileName, OutputLength * sizeof (CHAR16));
733 TabOutputStr[OutputLength] = CHAR_NULL;
734 }
735 OutputLength = StrLen (TabOutputStr) < MaxStr - 1 ? StrLen (TabOutputStr) : MaxStr - 1;
736 CopyMem (CurrentString + TabUpdatePos, TabOutputStr, OutputLength * sizeof (CHAR16));
737 CurrentString[TabUpdatePos + OutputLength] = CHAR_NULL;
738 StringCurPos = TabUpdatePos + OutputLength;
739 Update = TabUpdatePos;
740 if (StringLen > TabUpdatePos + OutputLength) {
741 Delete = StringLen - TabUpdatePos - OutputLength;
742 }
743 }
744
745 //
746 // If we have a new position, we are preparing to print a previous or
747 // next command.
748 //
749 if (NewPos != (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory)) {
750 Column = StartColumn;
751 Row -= (StringCurPos + StartColumn) / TotalColumn;
752
753 LinePos = NewPos;
754 NewPos = (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory);
755
756 OutputLength = StrLen (LinePos->Buffer) < MaxStr - 1 ? StrLen (LinePos->Buffer) : MaxStr - 1;
757 CopyMem (CurrentString, LinePos->Buffer, OutputLength * sizeof (CHAR16));
758 CurrentString[OutputLength] = CHAR_NULL;
759
760 StringCurPos = OutputLength;
761
762 //
763 // Draw new input string
764 //
765 Update = 0;
766 if (StringLen > OutputLength) {
767 //
768 // If old string was longer, blank its tail
769 //
770 Delete = StringLen - OutputLength;
771 }
772 }
773 //
774 // If we need to update the output do so now
775 //
776 if (Update != (UINTN) -1) {
777 ShellPrintEx ((INT32)Column, (INT32)Row, L"%s%.*s", CurrentString + Update, Delete, L"");
778 StringLen = StrLen (CurrentString);
779
780 if (Delete != 0) {
781 SetMem (CurrentString + StringLen, Delete * sizeof (CHAR16), CHAR_NULL);
782 }
783
784 if (StringCurPos > StringLen) {
785 StringCurPos = StringLen;
786 }
787
788 Update = (UINTN) -1;
789
790 //
791 // After using print to reflect newly updates, if we're not using
792 // BACKSPACE and DELETE, we need to move the cursor position forward,
793 // so adjust row and column here.
794 //
795 if (Key.UnicodeChar != CHAR_BACKSPACE && !(Key.UnicodeChar == 0 && Key.ScanCode == SCAN_DELETE)) {
796 //
797 // Calulate row and column of the tail of current string
798 //
799 TailRow = Row + (StringLen - StringCurPos + Column + OutputLength) / TotalColumn;
800 TailColumn = (StringLen - StringCurPos + Column + OutputLength) % TotalColumn;
801
802 //
803 // If the tail of string reaches screen end, screen rolls up, so if
804 // Row does not equal TailRow, Row should be decremented
805 //
806 // (if we are recalling commands using UPPER and DOWN key, and if the
807 // old command is too long to fit the screen, TailColumn must be 79.
808 //
809 if (TailColumn == 0 && TailRow >= TotalRow && Row != TailRow) {
810 Row--;
811 }
812 //
813 // Calculate the cursor position after current operation. If cursor
814 // reaches line end, update both row and column, otherwise, only
815 // column will be changed.
816 //
817 if (Column + OutputLength >= TotalColumn) {
818 SkipLength = OutputLength - (TotalColumn - Column);
819
820 Row += SkipLength / TotalColumn + 1;
821 if (Row > TotalRow - 1) {
822 Row = TotalRow - 1;
823 }
824
825 Column = SkipLength % TotalColumn;
826 } else {
827 Column += OutputLength;
828 }
829 }
830
831 Delete = 0;
832 }
833 //
834 // Set the cursor position for this key
835 //
836 gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
837 } while (!Done);
838
839 if (CurrentString != NULL && StrLen(CurrentString) > 0) {
840 //
841 // add the line to the history buffer
842 //
843 AddLineToCommandHistory(CurrentString);
844 }
845
846 FreePool (TabStr);
847 FreePool (TabOutputStr);
848 //
849 // Return the data to the caller
850 //
851 *BufferSize = StringLen * sizeof (CHAR16);
852
853 //
854 // if this was used it should be deallocated by now...
855 // prevent memory leaks...
856 //
857 ASSERT(FoundFileList == NULL);
858
859 return Status;
860 }
861
862 //
863 // FILE sytle interfaces for StdIn/StdOut/StdErr
864 //
865 EFI_FILE_PROTOCOL FileInterfaceStdIn = {
866 EFI_FILE_REVISION,
867 FileInterfaceOpenNotFound,
868 FileInterfaceNopGeneric,
869 FileInterfaceNopGeneric,
870 FileInterfaceStdInRead,
871 FileInterfaceStdInWrite,
872 FileInterfaceNopGetPosition,
873 FileInterfaceNopSetPosition,
874 FileInterfaceNopGetInfo,
875 FileInterfaceNopSetInfo,
876 FileInterfaceNopGeneric
877 };
878
879 EFI_FILE_PROTOCOL FileInterfaceStdOut = {
880 EFI_FILE_REVISION,
881 FileInterfaceOpenNotFound,
882 FileInterfaceNopGeneric,
883 FileInterfaceNopGeneric,
884 FileInterfaceStdOutRead,
885 FileInterfaceStdOutWrite,
886 FileInterfaceNopGetPosition,
887 FileInterfaceNopSetPosition,
888 FileInterfaceNopGetInfo,
889 FileInterfaceNopSetInfo,
890 FileInterfaceNopGeneric
891 };
892
893 EFI_FILE_PROTOCOL FileInterfaceStdErr = {
894 EFI_FILE_REVISION,
895 FileInterfaceOpenNotFound,
896 FileInterfaceNopGeneric,
897 FileInterfaceNopGeneric,
898 FileInterfaceStdErrRead,
899 FileInterfaceStdErrWrite,
900 FileInterfaceNopGetPosition,
901 FileInterfaceNopSetPosition,
902 FileInterfaceNopGetInfo,
903 FileInterfaceNopSetInfo,
904 FileInterfaceNopGeneric
905 };
906
907 EFI_FILE_PROTOCOL FileInterfaceNulFile = {
908 EFI_FILE_REVISION,
909 FileInterfaceOpenNotFound,
910 FileInterfaceNopGeneric,
911 FileInterfaceNopGeneric,
912 FileInterfaceNulRead,
913 FileInterfaceNulWrite,
914 FileInterfaceNopGetPosition,
915 FileInterfaceNopSetPosition,
916 FileInterfaceNopGetInfo,
917 FileInterfaceNopSetInfo,
918 FileInterfaceNopGeneric
919 };
920
921
922
923
924 //
925 // This is identical to EFI_FILE_PROTOCOL except for the additional member
926 // for the name.
927 //
928
929 typedef struct {
930 UINT64 Revision;
931 EFI_FILE_OPEN Open;
932 EFI_FILE_CLOSE Close;
933 EFI_FILE_DELETE Delete;
934 EFI_FILE_READ Read;
935 EFI_FILE_WRITE Write;
936 EFI_FILE_GET_POSITION GetPosition;
937 EFI_FILE_SET_POSITION SetPosition;
938 EFI_FILE_GET_INFO GetInfo;
939 EFI_FILE_SET_INFO SetInfo;
940 EFI_FILE_FLUSH Flush;
941 CHAR16 Name[1];
942 } EFI_FILE_PROTOCOL_ENVIRONMENT;
943 //ANSI compliance helper to get size of the struct.
944 #define SIZE_OF_EFI_FILE_PROTOCOL_ENVIRONMENT EFI_FIELD_OFFSET (EFI_FILE_PROTOCOL_ENVIRONMENT, Name)
945
946 /**
947 File style interface for Environment Variable (Close).
948
949 Frees the memory for this object.
950
951 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
952
953 @retval EFI_SUCCESS
954 **/
955 EFI_STATUS
956 EFIAPI
957 FileInterfaceEnvClose(
958 IN EFI_FILE_PROTOCOL *This
959 )
960 {
961 VOID* NewBuffer;
962 UINTN NewSize;
963 EFI_STATUS Status;
964
965 //
966 // Most if not all UEFI commands will have an '\r\n' at the end of any output.
967 // Since the output was redirected to a variable, it does not make sense to
968 // keep this. So, before closing, strip the trailing '\r\n' from the variable
969 // if it exists.
970 //
971 NewBuffer = NULL;
972 NewSize = 0;
973
974 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
975 if (Status == EFI_BUFFER_TOO_SMALL) {
976 NewBuffer = AllocateZeroPool(NewSize + sizeof(CHAR16));
977 if (NewBuffer == NULL) {
978 return EFI_OUT_OF_RESOURCES;
979 }
980 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
981 }
982
983 if (!EFI_ERROR(Status) && NewBuffer != NULL) {
984
985 if (StrSize(NewBuffer) > 6)
986 {
987 if ((((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 2] == CHAR_LINEFEED)
988 && (((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] == CHAR_CARRIAGE_RETURN)) {
989 ((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] = CHAR_NULL;
990 }
991
992 if (IsVolatileEnv(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name)) {
993 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);
994 } else {
995 Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);
996 }
997 }
998 }
999
1000 SHELL_FREE_NON_NULL(NewBuffer);
1001 FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT*)This);
1002 return (Status);
1003 }
1004
1005 /**
1006 File style interface for Environment Variable (Delete).
1007
1008 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1009
1010 @retval The return value from FileInterfaceEnvClose().
1011 **/
1012 EFI_STATUS
1013 EFIAPI
1014 FileInterfaceEnvDelete(
1015 IN EFI_FILE_PROTOCOL *This
1016 )
1017 {
1018 SHELL_DELETE_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name);
1019 return (FileInterfaceEnvClose(This));
1020 }
1021
1022 /**
1023 File style interface for Environment Variable (Read).
1024
1025 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1026 @param[in, out] BufferSize Size in bytes of Buffer.
1027 @param[out] Buffer The pointer to the buffer to fill.
1028
1029 @retval EFI_SUCCESS The data was read.
1030 **/
1031 EFI_STATUS
1032 EFIAPI
1033 FileInterfaceEnvRead(
1034 IN EFI_FILE_PROTOCOL *This,
1035 IN OUT UINTN *BufferSize,
1036 OUT VOID *Buffer
1037 )
1038 {
1039 return (SHELL_GET_ENVIRONMENT_VARIABLE(
1040 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,
1041 BufferSize,
1042 Buffer));
1043 }
1044
1045 /**
1046 File style interface for Volatile Environment Variable (Write).
1047
1048 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1049 @param[in, out] BufferSize Size in bytes of Buffer.
1050 @param[in] Buffer The pointer to the buffer to write.
1051
1052 @retval EFI_SUCCESS The data was read.
1053 **/
1054 EFI_STATUS
1055 EFIAPI
1056 FileInterfaceEnvVolWrite(
1057 IN EFI_FILE_PROTOCOL *This,
1058 IN OUT UINTN *BufferSize,
1059 IN VOID *Buffer
1060 )
1061 {
1062 VOID* NewBuffer;
1063 UINTN NewSize;
1064 EFI_STATUS Status;
1065
1066 NewBuffer = NULL;
1067 NewSize = 0;
1068
1069 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
1070 if (Status == EFI_BUFFER_TOO_SMALL){
1071 NewBuffer = AllocateZeroPool(NewSize + *BufferSize + sizeof(CHAR16));
1072 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
1073 }
1074 if (!EFI_ERROR(Status) && NewBuffer != NULL) {
1075 while (((CHAR16*)NewBuffer)[NewSize/2] == CHAR_NULL) {
1076 //
1077 // We want to overwrite the CHAR_NULL
1078 //
1079 NewSize -= 2;
1080 }
1081 CopyMem((UINT8*)NewBuffer + NewSize + 2, Buffer, *BufferSize);
1082 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);
1083 FreePool(NewBuffer);
1084 return (Status);
1085 } else {
1086 SHELL_FREE_NON_NULL(NewBuffer);
1087 return (SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, *BufferSize, Buffer));
1088 }
1089 }
1090
1091
1092 /**
1093 File style interface for Non Volatile Environment Variable (Write).
1094
1095 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1096 @param[in, out] BufferSize Size in bytes of Buffer.
1097 @param[in] Buffer The pointer to the buffer to write.
1098
1099 @retval EFI_SUCCESS The data was read.
1100 **/
1101 EFI_STATUS
1102 EFIAPI
1103 FileInterfaceEnvNonVolWrite(
1104 IN EFI_FILE_PROTOCOL *This,
1105 IN OUT UINTN *BufferSize,
1106 IN VOID *Buffer
1107 )
1108 {
1109 VOID* NewBuffer;
1110 UINTN NewSize;
1111 EFI_STATUS Status;
1112
1113 NewBuffer = NULL;
1114 NewSize = 0;
1115
1116 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
1117 if (Status == EFI_BUFFER_TOO_SMALL){
1118 NewBuffer = AllocateZeroPool(NewSize + *BufferSize);
1119 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
1120 }
1121 if (!EFI_ERROR(Status)) {
1122 CopyMem((UINT8*)NewBuffer + NewSize, Buffer, *BufferSize);
1123 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
1124 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,
1125 NewSize + *BufferSize,
1126 NewBuffer));
1127 } else {
1128 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
1129 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,
1130 *BufferSize,
1131 Buffer));
1132 }
1133 }
1134
1135 /**
1136 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1137 environment variables through file operations.
1138
1139 @param EnvName The name of the Environment Variable to be operated on.
1140
1141 @retval NULL Memory could not be allocated.
1142 @return other a pointer to an EFI_FILE_PROTOCOL structure
1143 **/
1144 EFI_FILE_PROTOCOL*
1145 EFIAPI
1146 CreateFileInterfaceEnv(
1147 IN CONST CHAR16 *EnvName
1148 )
1149 {
1150 EFI_FILE_PROTOCOL_ENVIRONMENT *EnvFileInterface;
1151 UINTN EnvNameSize;
1152
1153 if (EnvName == NULL) {
1154 return (NULL);
1155 }
1156
1157 //
1158 // Get some memory
1159 //
1160 EnvNameSize = StrSize(EnvName);
1161 EnvFileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT)+EnvNameSize);
1162 if (EnvFileInterface == NULL){
1163 return (NULL);
1164 }
1165
1166 //
1167 // Assign the generic members
1168 //
1169 EnvFileInterface->Revision = EFI_FILE_REVISION;
1170 EnvFileInterface->Open = FileInterfaceOpenNotFound;
1171 EnvFileInterface->Close = FileInterfaceEnvClose;
1172 EnvFileInterface->GetPosition = FileInterfaceNopGetPosition;
1173 EnvFileInterface->SetPosition = FileInterfaceNopSetPosition;
1174 EnvFileInterface->GetInfo = FileInterfaceNopGetInfo;
1175 EnvFileInterface->SetInfo = FileInterfaceNopSetInfo;
1176 EnvFileInterface->Flush = FileInterfaceNopGeneric;
1177 EnvFileInterface->Delete = FileInterfaceEnvDelete;
1178 EnvFileInterface->Read = FileInterfaceEnvRead;
1179
1180 CopyMem(EnvFileInterface->Name, EnvName, EnvNameSize);
1181
1182 //
1183 // Assign the different members for Volatile and Non-Volatile variables
1184 //
1185 if (IsVolatileEnv(EnvName)) {
1186 EnvFileInterface->Write = FileInterfaceEnvVolWrite;
1187 } else {
1188 EnvFileInterface->Write = FileInterfaceEnvNonVolWrite;
1189 }
1190 return ((EFI_FILE_PROTOCOL *)EnvFileInterface);
1191 }
1192
1193 /**
1194 Move the cursor position one character backward.
1195
1196 @param[in] LineLength Length of a line. Get it by calling QueryMode
1197 @param[in, out] Column Current column of the cursor position
1198 @param[in, out] Row Current row of the cursor position
1199 **/
1200 VOID
1201 EFIAPI
1202 MoveCursorBackward (
1203 IN UINTN LineLength,
1204 IN OUT UINTN *Column,
1205 IN OUT UINTN *Row
1206 )
1207 {
1208 //
1209 // If current column is 0, move to the last column of the previous line,
1210 // otherwise, just decrement column.
1211 //
1212 if (*Column == 0) {
1213 *Column = LineLength - 1;
1214 if (*Row > 0) {
1215 (*Row)--;
1216 }
1217 return;
1218 }
1219 (*Column)--;
1220 }
1221
1222 /**
1223 Move the cursor position one character forward.
1224
1225 @param[in] LineLength Length of a line.
1226 @param[in] TotalRow Total row of a screen
1227 @param[in, out] Column Current column of the cursor position
1228 @param[in, out] Row Current row of the cursor position
1229 **/
1230 VOID
1231 EFIAPI
1232 MoveCursorForward (
1233 IN UINTN LineLength,
1234 IN UINTN TotalRow,
1235 IN OUT UINTN *Column,
1236 IN OUT UINTN *Row
1237 )
1238 {
1239 //
1240 // Increment Column.
1241 // If this puts column past the end of the line, move to first column
1242 // of the next row.
1243 //
1244 (*Column)++;
1245 if (*Column >= LineLength) {
1246 (*Column) = 0;
1247 if ((*Row) < TotalRow - 1) {
1248 (*Row)++;
1249 }
1250 }
1251 }
1252
1253 /**
1254 Prints out each previously typed command in the command list history log.
1255
1256 When each screen is full it will pause for a key before continuing.
1257
1258 @param[in] TotalCols How many columns are on the screen
1259 @param[in] TotalRows How many rows are on the screen
1260 @param[in] StartColumn which column to start at
1261 **/
1262 VOID
1263 EFIAPI
1264 PrintCommandHistory (
1265 IN CONST UINTN TotalCols,
1266 IN CONST UINTN TotalRows,
1267 IN CONST UINTN StartColumn
1268 )
1269 {
1270 BUFFER_LIST *Node;
1271 UINTN Index;
1272 UINTN LineNumber;
1273 UINTN LineCount;
1274
1275 ShellPrintEx (-1, -1, L"\n");
1276 Index = 0;
1277 LineNumber = 0;
1278 //
1279 // go through history list...
1280 //
1281 for ( Node = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link)
1282 ; !IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link)
1283 ; Node = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link)
1284 ){
1285 Index++;
1286 LineCount = ((StrLen (Node->Buffer) + StartColumn + 1) / TotalCols) + 1;
1287
1288 if (LineNumber + LineCount >= TotalRows) {
1289 ShellPromptForResponseHii(
1290 ShellPromptResponseTypeEnterContinue,
1291 STRING_TOKEN (STR_SHELL_ENTER_TO_CONT),
1292 ShellInfoObject.HiiHandle,
1293 NULL
1294 );
1295 LineNumber = 0;
1296 }
1297 ShellPrintEx (-1, -1, L"%2d. %s\n", Index, Node->Buffer);
1298 LineNumber += LineCount;
1299 }
1300 }
1301
1302
1303
1304
1305
1306
1307 //
1308 // This is identical to EFI_FILE_PROTOCOL except for the additional members
1309 // for the buffer, size, and position.
1310 //
1311
1312 typedef struct {
1313 UINT64 Revision;
1314 EFI_FILE_OPEN Open;
1315 EFI_FILE_CLOSE Close;
1316 EFI_FILE_DELETE Delete;
1317 EFI_FILE_READ Read;
1318 EFI_FILE_WRITE Write;
1319 EFI_FILE_GET_POSITION GetPosition;
1320 EFI_FILE_SET_POSITION SetPosition;
1321 EFI_FILE_GET_INFO GetInfo;
1322 EFI_FILE_SET_INFO SetInfo;
1323 EFI_FILE_FLUSH Flush;
1324 VOID *Buffer;
1325 UINT64 Position;
1326 UINT64 BufferSize;
1327 BOOLEAN Unicode;
1328 UINT64 FileSize;
1329 } EFI_FILE_PROTOCOL_MEM;
1330
1331 /**
1332 File style interface for Mem (SetPosition).
1333
1334 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1335 @param[out] Position The position to set.
1336
1337 @retval EFI_SUCCESS The position was successfully changed.
1338 @retval EFI_INVALID_PARAMETER The Position was invalid.
1339 **/
1340 EFI_STATUS
1341 EFIAPI
1342 FileInterfaceMemSetPosition(
1343 IN EFI_FILE_PROTOCOL *This,
1344 OUT UINT64 Position
1345 )
1346 {
1347 if (Position <= ((EFI_FILE_PROTOCOL_MEM*)This)->FileSize) {
1348 ((EFI_FILE_PROTOCOL_MEM*)This)->Position = Position;
1349 return (EFI_SUCCESS);
1350 } else {
1351 return (EFI_INVALID_PARAMETER);
1352 }
1353 }
1354
1355 /**
1356 File style interface for Mem (GetPosition).
1357
1358 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1359 @param[out] Position The pointer to the position.
1360
1361 @retval EFI_SUCCESS The position was retrieved.
1362 **/
1363 EFI_STATUS
1364 EFIAPI
1365 FileInterfaceMemGetPosition(
1366 IN EFI_FILE_PROTOCOL *This,
1367 OUT UINT64 *Position
1368 )
1369 {
1370 *Position = ((EFI_FILE_PROTOCOL_MEM*)This)->Position;
1371 return (EFI_SUCCESS);
1372 }
1373
1374 /**
1375 File style interface for Mem (Write).
1376
1377 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1378 @param[in, out] BufferSize Size in bytes of Buffer.
1379 @param[in] Buffer The pointer to the buffer to write.
1380
1381 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.
1382 @retval EFI_SUCCESS The data was written.
1383 **/
1384 EFI_STATUS
1385 EFIAPI
1386 FileInterfaceMemWrite(
1387 IN EFI_FILE_PROTOCOL *This,
1388 IN OUT UINTN *BufferSize,
1389 IN VOID *Buffer
1390 )
1391 {
1392 CHAR8 *AsciiBuffer;
1393 EFI_FILE_PROTOCOL_MEM *MemFile;
1394
1395 MemFile = (EFI_FILE_PROTOCOL_MEM *) This;
1396 if (MemFile->Unicode) {
1397 //
1398 // Unicode
1399 //
1400 if ((UINTN)(MemFile->Position + (*BufferSize)) > (UINTN)(MemFile->BufferSize)) {
1401 MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + (*BufferSize) + 10, MemFile->Buffer);
1402 MemFile->BufferSize += (*BufferSize) + 10;
1403 }
1404 CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, Buffer, *BufferSize);
1405 MemFile->Position += (*BufferSize);
1406 MemFile->FileSize = MemFile->Position;
1407 return (EFI_SUCCESS);
1408 } else {
1409 //
1410 // Ascii
1411 //
1412 AsciiBuffer = AllocateZeroPool(*BufferSize);
1413 if (AsciiBuffer == NULL) {
1414 return (EFI_OUT_OF_RESOURCES);
1415 }
1416 AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer);
1417 if ((UINTN)(MemFile->Position + AsciiStrSize(AsciiBuffer)) > (UINTN)(MemFile->BufferSize)) {
1418 MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + AsciiStrSize(AsciiBuffer) + 10, MemFile->Buffer);
1419 MemFile->BufferSize += AsciiStrSize(AsciiBuffer) + 10;
1420 }
1421 CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, AsciiBuffer, AsciiStrSize(AsciiBuffer));
1422 MemFile->Position += (*BufferSize / sizeof(CHAR16));
1423 MemFile->FileSize = MemFile->Position;
1424 FreePool(AsciiBuffer);
1425 return (EFI_SUCCESS);
1426 }
1427 }
1428
1429 /**
1430 File style interface for Mem (Read).
1431
1432 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1433 @param[in, out] BufferSize Size in bytes of Buffer.
1434 @param[in] Buffer The pointer to the buffer to fill.
1435
1436 @retval EFI_SUCCESS The data was read.
1437 **/
1438 EFI_STATUS
1439 EFIAPI
1440 FileInterfaceMemRead(
1441 IN EFI_FILE_PROTOCOL *This,
1442 IN OUT UINTN *BufferSize,
1443 IN VOID *Buffer
1444 )
1445 {
1446 EFI_FILE_PROTOCOL_MEM *MemFile;
1447
1448 MemFile = (EFI_FILE_PROTOCOL_MEM *) This;
1449 if (*BufferSize > (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position))) {
1450 (*BufferSize) = (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position));
1451 }
1452 CopyMem(Buffer, ((UINT8*)MemFile->Buffer) + MemFile->Position, (*BufferSize));
1453 MemFile->Position = MemFile->Position + (*BufferSize);
1454 return (EFI_SUCCESS);
1455 }
1456
1457 /**
1458 File style interface for Mem (Close).
1459
1460 Frees all memory associated with this object.
1461
1462 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1463
1464 @retval EFI_SUCCESS The 'file' was closed.
1465 **/
1466 EFI_STATUS
1467 EFIAPI
1468 FileInterfaceMemClose(
1469 IN EFI_FILE_PROTOCOL *This
1470 )
1471 {
1472 SHELL_FREE_NON_NULL(((EFI_FILE_PROTOCOL_MEM*)This)->Buffer);
1473 SHELL_FREE_NON_NULL(This);
1474 return (EFI_SUCCESS);
1475 }
1476
1477 /**
1478 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1479 a file entirely in memory through file operations.
1480
1481 @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii.
1482
1483 @retval NULL Memory could not be allocated.
1484 @return other A pointer to an EFI_FILE_PROTOCOL structure.
1485 **/
1486 EFI_FILE_PROTOCOL*
1487 EFIAPI
1488 CreateFileInterfaceMem(
1489 IN CONST BOOLEAN Unicode
1490 )
1491 {
1492 EFI_FILE_PROTOCOL_MEM *FileInterface;
1493
1494 //
1495 // Get some memory
1496 //
1497 FileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_MEM));
1498 if (FileInterface == NULL){
1499 return (NULL);
1500 }
1501
1502 //
1503 // Assign the generic members
1504 //
1505 FileInterface->Revision = EFI_FILE_REVISION;
1506 FileInterface->Open = FileInterfaceOpenNotFound;
1507 FileInterface->Close = FileInterfaceMemClose;
1508 FileInterface->GetPosition = FileInterfaceMemGetPosition;
1509 FileInterface->SetPosition = FileInterfaceMemSetPosition;
1510 FileInterface->GetInfo = FileInterfaceNopGetInfo;
1511 FileInterface->SetInfo = FileInterfaceNopSetInfo;
1512 FileInterface->Flush = FileInterfaceNopGeneric;
1513 FileInterface->Delete = FileInterfaceNopGeneric;
1514 FileInterface->Read = FileInterfaceMemRead;
1515 FileInterface->Write = FileInterfaceMemWrite;
1516 FileInterface->Unicode = Unicode;
1517
1518 ASSERT(FileInterface->Buffer == NULL);
1519 ASSERT(FileInterface->BufferSize == 0);
1520 ASSERT(FileInterface->Position == 0);
1521
1522 if (Unicode) {
1523 FileInterface->Buffer = AllocateZeroPool(sizeof(gUnicodeFileTag));
1524 if (FileInterface->Buffer == NULL) {
1525 FreePool (FileInterface);
1526 return NULL;
1527 }
1528 *((CHAR16 *) (FileInterface->Buffer)) = EFI_UNICODE_BYTE_ORDER_MARK;
1529 FileInterface->BufferSize = 2;
1530 FileInterface->Position = 2;
1531 }
1532
1533 return ((EFI_FILE_PROTOCOL *)FileInterface);
1534 }
1535
1536 typedef struct {
1537 UINT64 Revision;
1538 EFI_FILE_OPEN Open;
1539 EFI_FILE_CLOSE Close;
1540 EFI_FILE_DELETE Delete;
1541 EFI_FILE_READ Read;
1542 EFI_FILE_WRITE Write;
1543 EFI_FILE_GET_POSITION GetPosition;
1544 EFI_FILE_SET_POSITION SetPosition;
1545 EFI_FILE_GET_INFO GetInfo;
1546 EFI_FILE_SET_INFO SetInfo;
1547 EFI_FILE_FLUSH Flush;
1548 BOOLEAN Unicode;
1549 EFI_FILE_PROTOCOL *Orig;
1550 } EFI_FILE_PROTOCOL_FILE;
1551
1552 /**
1553 Set a files current position
1554
1555 @param This Protocol instance pointer.
1556 @param Position Byte position from the start of the file.
1557
1558 @retval EFI_SUCCESS Data was written.
1559 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
1560
1561 **/
1562 EFI_STATUS
1563 EFIAPI
1564 FileInterfaceFileSetPosition(
1565 IN EFI_FILE_PROTOCOL *This,
1566 IN UINT64 Position
1567 )
1568 {
1569 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->SetPosition(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, Position);
1570 }
1571
1572 /**
1573 Get a file's current position
1574
1575 @param This Protocol instance pointer.
1576 @param Position Byte position from the start of the file.
1577
1578 @retval EFI_SUCCESS Data was written.
1579 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
1580
1581 **/
1582 EFI_STATUS
1583 EFIAPI
1584 FileInterfaceFileGetPosition(
1585 IN EFI_FILE_PROTOCOL *This,
1586 OUT UINT64 *Position
1587 )
1588 {
1589 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetPosition(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, Position);
1590 }
1591
1592 /**
1593 Get information about a file.
1594
1595 @param This Protocol instance pointer.
1596 @param InformationType Type of information to return in Buffer.
1597 @param BufferSize On input size of buffer, on output amount of data in buffer.
1598 @param Buffer The buffer to return data.
1599
1600 @retval EFI_SUCCESS Data was returned.
1601 @retval EFI_UNSUPPORT InformationType is not supported.
1602 @retval EFI_NO_MEDIA The device has no media.
1603 @retval EFI_DEVICE_ERROR The device reported an error.
1604 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1605 @retval EFI_WRITE_PROTECTED The device is write protected.
1606 @retval EFI_ACCESS_DENIED The file was open for read only.
1607 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
1608
1609 **/
1610 EFI_STATUS
1611 EFIAPI
1612 FileInterfaceFileGetInfo(
1613 IN EFI_FILE_PROTOCOL *This,
1614 IN EFI_GUID *InformationType,
1615 IN OUT UINTN *BufferSize,
1616 OUT VOID *Buffer
1617 )
1618 {
1619 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetInfo(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, InformationType, BufferSize, Buffer);
1620 }
1621
1622 /**
1623 Set information about a file
1624
1625 @param This Protocol instance pointer.
1626 @param InformationType Type of information in Buffer.
1627 @param BufferSize Size of buffer.
1628 @param Buffer The data to write.
1629
1630 @retval EFI_SUCCESS Data was returned.
1631 @retval EFI_UNSUPPORT InformationType is not supported.
1632 @retval EFI_NO_MEDIA The device has no media.
1633 @retval EFI_DEVICE_ERROR The device reported an error.
1634 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1635 @retval EFI_WRITE_PROTECTED The device is write protected.
1636 @retval EFI_ACCESS_DENIED The file was open for read only.
1637
1638 **/
1639 EFI_STATUS
1640 EFIAPI
1641 FileInterfaceFileSetInfo(
1642 IN EFI_FILE_PROTOCOL *This,
1643 IN EFI_GUID *InformationType,
1644 IN UINTN BufferSize,
1645 IN VOID *Buffer
1646 )
1647 {
1648 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->SetInfo(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, InformationType, BufferSize, Buffer);
1649 }
1650
1651 /**
1652 Flush data back for the file handle.
1653
1654 @param This Protocol instance pointer.
1655
1656 @retval EFI_SUCCESS Data was written.
1657 @retval EFI_UNSUPPORT Writes to Open directory are not supported.
1658 @retval EFI_NO_MEDIA The device has no media.
1659 @retval EFI_DEVICE_ERROR The device reported an error.
1660 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1661 @retval EFI_WRITE_PROTECTED The device is write protected.
1662 @retval EFI_ACCESS_DENIED The file was open for read only.
1663 @retval EFI_VOLUME_FULL The volume is full.
1664
1665 **/
1666 EFI_STATUS
1667 EFIAPI
1668 FileInterfaceFileFlush(
1669 IN EFI_FILE_PROTOCOL *This
1670 )
1671 {
1672 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Flush(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);
1673 }
1674
1675 /**
1676 Read data from the file.
1677
1678 @param This Protocol instance pointer.
1679 @param BufferSize On input size of buffer, on output amount of data in buffer.
1680 @param Buffer The buffer in which data is read.
1681
1682 @retval EFI_SUCCESS Data was read.
1683 @retval EFI_NO_MEDIA The device has no media.
1684 @retval EFI_DEVICE_ERROR The device reported an error.
1685 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1686 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
1687
1688 **/
1689 EFI_STATUS
1690 EFIAPI
1691 FileInterfaceFileRead(
1692 IN EFI_FILE_PROTOCOL *This,
1693 IN OUT UINTN *BufferSize,
1694 OUT VOID *Buffer
1695 )
1696 {
1697 CHAR8 *AsciiStrBuffer;
1698 CHAR16 *UscStrBuffer;
1699 UINTN Size;
1700 UINTN CharNum;
1701 EFI_STATUS Status;
1702 if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) {
1703 //
1704 // Unicode
1705 //
1706 return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer));
1707 } else {
1708 //
1709 // Ascii
1710 //
1711 Size = (*BufferSize) / sizeof(CHAR16);
1712 AsciiStrBuffer = AllocateZeroPool(Size + sizeof(CHAR8));
1713 if (AsciiStrBuffer == NULL) {
1714 return EFI_OUT_OF_RESOURCES;
1715 }
1716 UscStrBuffer = AllocateZeroPool(*BufferSize + sizeof(CHAR16));
1717 if (UscStrBuffer== NULL) {
1718 SHELL_FREE_NON_NULL(AsciiStrBuffer);
1719 return EFI_OUT_OF_RESOURCES;
1720 }
1721 Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiStrBuffer));
1722 if (!EFI_ERROR(Status)) {
1723 CharNum = UnicodeSPrint(UscStrBuffer, *BufferSize + sizeof(CHAR16), L"%a", AsciiStrBuffer);
1724 if (CharNum == Size) {
1725 CopyMem (Buffer, UscStrBuffer, *BufferSize);
1726 } else {
1727 Status = EFI_UNSUPPORTED;
1728 }
1729 }
1730 SHELL_FREE_NON_NULL(AsciiStrBuffer);
1731 SHELL_FREE_NON_NULL(UscStrBuffer);
1732 return (Status);
1733 }
1734 }
1735
1736 /**
1737 Opens a new file relative to the source file's location.
1738
1739 @param[in] This The protocol instance pointer.
1740 @param[out] NewHandle Returns File Handle for FileName.
1741 @param[in] FileName Null terminated string. "\", ".", and ".." are supported.
1742 @param[in] OpenMode Open mode for file.
1743 @param[in] Attributes Only used for EFI_FILE_MODE_CREATE.
1744
1745 @retval EFI_SUCCESS The device was opened.
1746 @retval EFI_NOT_FOUND The specified file could not be found on the device.
1747 @retval EFI_NO_MEDIA The device has no media.
1748 @retval EFI_MEDIA_CHANGED The media has changed.
1749 @retval EFI_DEVICE_ERROR The device reported an error.
1750 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1751 @retval EFI_ACCESS_DENIED The service denied access to the file.
1752 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
1753 @retval EFI_VOLUME_FULL The volume is full.
1754 **/
1755 EFI_STATUS
1756 EFIAPI
1757 FileInterfaceFileOpen (
1758 IN EFI_FILE_PROTOCOL *This,
1759 OUT EFI_FILE_PROTOCOL **NewHandle,
1760 IN CHAR16 *FileName,
1761 IN UINT64 OpenMode,
1762 IN UINT64 Attributes
1763 )
1764 {
1765 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Open(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, NewHandle, FileName, OpenMode, Attributes);
1766 }
1767
1768 /**
1769 Close and delete the file handle.
1770
1771 @param This Protocol instance pointer.
1772
1773 @retval EFI_SUCCESS The device was opened.
1774 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
1775
1776 **/
1777 EFI_STATUS
1778 EFIAPI
1779 FileInterfaceFileDelete(
1780 IN EFI_FILE_PROTOCOL *This
1781 )
1782 {
1783 EFI_STATUS Status;
1784 Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Delete(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);
1785 FreePool(This);
1786 return (Status);
1787 }
1788
1789 /**
1790 File style interface for File (Close).
1791
1792 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1793
1794 @retval EFI_SUCCESS The file was closed.
1795 **/
1796 EFI_STATUS
1797 EFIAPI
1798 FileInterfaceFileClose(
1799 IN EFI_FILE_PROTOCOL *This
1800 )
1801 {
1802 EFI_STATUS Status;
1803 Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Close(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);
1804 FreePool(This);
1805 return (Status);
1806 }
1807
1808 /**
1809 File style interface for File (Write).
1810
1811 If the file was opened with ASCII mode the data will be processed through
1812 AsciiSPrint before writing.
1813
1814 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1815 @param[in, out] BufferSize Size in bytes of Buffer.
1816 @param[in] Buffer The pointer to the buffer to write.
1817
1818 @retval EFI_SUCCESS The data was written.
1819 **/
1820 EFI_STATUS
1821 EFIAPI
1822 FileInterfaceFileWrite(
1823 IN EFI_FILE_PROTOCOL *This,
1824 IN OUT UINTN *BufferSize,
1825 IN VOID *Buffer
1826 )
1827 {
1828 CHAR8 *AsciiBuffer;
1829 UINTN Size;
1830 EFI_STATUS Status;
1831 if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) {
1832 //
1833 // Unicode
1834 //
1835 return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer));
1836 } else {
1837 //
1838 // Ascii
1839 //
1840 AsciiBuffer = AllocateZeroPool(*BufferSize);
1841 AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer);
1842 Size = AsciiStrSize(AsciiBuffer) - 1; // (we dont need the null terminator)
1843 Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiBuffer));
1844 FreePool(AsciiBuffer);
1845 return (Status);
1846 }
1847 }
1848
1849 /**
1850 Create a file interface with unicode information.
1851
1852 This will create a new EFI_FILE_PROTOCOL identical to the Templace
1853 except that the new one has Unicode and Ascii knowledge.
1854
1855 @param[in] Template A pointer to the EFI_FILE_PROTOCOL object.
1856 @param[in] Unicode TRUE for UCS-2, FALSE for ASCII.
1857
1858 @return a new EFI_FILE_PROTOCOL object to be used instead of the template.
1859 **/
1860 EFI_FILE_PROTOCOL*
1861 CreateFileInterfaceFile(
1862 IN CONST EFI_FILE_PROTOCOL *Template,
1863 IN CONST BOOLEAN Unicode
1864 )
1865 {
1866 EFI_FILE_PROTOCOL_FILE *NewOne;
1867
1868 NewOne = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_FILE));
1869 if (NewOne == NULL) {
1870 return (NULL);
1871 }
1872 CopyMem(NewOne, Template, sizeof(EFI_FILE_PROTOCOL_FILE));
1873 NewOne->Orig = (EFI_FILE_PROTOCOL *)Template;
1874 NewOne->Unicode = Unicode;
1875 NewOne->Open = FileInterfaceFileOpen;
1876 NewOne->Close = FileInterfaceFileClose;
1877 NewOne->Delete = FileInterfaceFileDelete;
1878 NewOne->Read = FileInterfaceFileRead;
1879 NewOne->Write = FileInterfaceFileWrite;
1880 NewOne->GetPosition = FileInterfaceFileGetPosition;
1881 NewOne->SetPosition = FileInterfaceFileSetPosition;
1882 NewOne->GetInfo = FileInterfaceFileGetInfo;
1883 NewOne->SetInfo = FileInterfaceFileSetInfo;
1884 NewOne->Flush = FileInterfaceFileFlush;
1885
1886 return ((EFI_FILE_PROTOCOL *)NewOne);
1887 }