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