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