]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Application/Shell/FileHandleWrappers.c
ShellPkg AARCH64: remove DEBUG BuildOptions override
[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 ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
576 }
577 }
578 }
579 break;
580
581 default:
582 if (Key.UnicodeChar >= ' ') {
583 //
584 // If we are at the buffer's end, drop the key
585 //
586 if (StringLen == MaxStr - 1 && (ShellInfoObject.ViewingSettings.InsertMode || StringCurPos == StringLen)) {
587 break;
588 }
589 //
590 // If in insert mode, make space by moving each other character 1
591 // space higher in the array
592 //
593 if (ShellInfoObject.ViewingSettings.InsertMode) {
594 CopyMem(CurrentString + StringCurPos + 1, CurrentString + StringCurPos, (StringLen - StringCurPos)*sizeof(CurrentString[0]));
595 }
596
597 CurrentString[StringCurPos] = Key.UnicodeChar;
598 Update = StringCurPos;
599
600 StringCurPos += 1;
601 OutputLength = 1;
602 }
603 break;
604
605 case 0:
606 switch (Key.ScanCode) {
607 case SCAN_DELETE:
608 //
609 // Move characters behind current position one character forward
610 //
611 if (StringLen != 0) {
612 Update = StringCurPos;
613 Delete = 1;
614 CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos));
615 }
616 break;
617
618 case SCAN_UP:
619 //
620 // Prepare to print the previous command
621 //
622 NewPos = (BUFFER_LIST*)GetPreviousNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
623 if (IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link)) {
624 NewPos = (BUFFER_LIST*)GetPreviousNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
625 }
626 break;
627
628 case SCAN_DOWN:
629 //
630 // Prepare to print the next command
631 //
632 NewPos = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
633 if (NewPos == (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory)) {
634 NewPos = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
635 }
636 break;
637
638 case SCAN_LEFT:
639 //
640 // Adjust current cursor position
641 //
642 if (StringCurPos != 0) {
643 --StringCurPos;
644 MoveCursorBackward (TotalColumn, &Column, &Row);
645 }
646 break;
647
648 case SCAN_RIGHT:
649 //
650 // Adjust current cursor position
651 //
652 if (StringCurPos < StringLen) {
653 ++StringCurPos;
654 MoveCursorForward (TotalColumn, TotalRow, &Column, &Row);
655 }
656 break;
657
658 case SCAN_HOME:
659 //
660 // Move current cursor position to the beginning of the command line
661 //
662 Row -= (StringCurPos + StartColumn) / TotalColumn;
663 Column = StartColumn;
664 StringCurPos = 0;
665 break;
666
667 case SCAN_END:
668 //
669 // Move current cursor position to the end of the command line
670 //
671 TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn;
672 TailColumn = (StringLen - StringCurPos + Column) % TotalColumn;
673 Row = TailRow;
674 Column = TailColumn;
675 StringCurPos = StringLen;
676 break;
677
678 case SCAN_ESC:
679 //
680 // Prepare to clear the current command line
681 //
682 CurrentString[0] = 0;
683 Update = 0;
684 Delete = StringLen;
685 Row -= (StringCurPos + StartColumn) / TotalColumn;
686 Column = StartColumn;
687 OutputLength = 0;
688 break;
689
690 case SCAN_INSERT:
691 //
692 // Toggle the SEnvInsertMode flag
693 //
694 ShellInfoObject.ViewingSettings.InsertMode = (BOOLEAN)!ShellInfoObject.ViewingSettings.InsertMode;
695 break;
696
697 case SCAN_F7:
698 //
699 // Print command history
700 //
701 PrintCommandHistory (TotalColumn, TotalRow, 4);
702 *CurrentString = CHAR_NULL;
703 Done = TRUE;
704 break;
705 }
706 }
707
708 if (Done) {
709 break;
710 }
711
712 //
713 // If we are in auto-complete mode, we are preparing to print
714 // the next file or directory name
715 //
716 if (InTabScrolling) {
717 //
718 // Adjust the column and row to the start of TAB-completion string.
719 //
720 Column = (StartColumn + TabUpdatePos) % TotalColumn;
721 Row -= (StartColumn + StringCurPos) / TotalColumn - (StartColumn + TabUpdatePos) / TotalColumn;
722 OutputLength = StrLen (TabLinePos->FileName);
723 //
724 // if the output string contains blank space, quotation marks L'\"'
725 // should be added to the output.
726 //
727 if (StrStr(TabLinePos->FileName, L" ") != NULL){
728 TabOutputStr[0] = L'\"';
729 CopyMem (TabOutputStr + 1, TabLinePos->FileName, OutputLength * sizeof (CHAR16));
730 TabOutputStr[OutputLength + 1] = L'\"';
731 TabOutputStr[OutputLength + 2] = CHAR_NULL;
732 } else {
733 CopyMem (TabOutputStr, TabLinePos->FileName, OutputLength * sizeof (CHAR16));
734 TabOutputStr[OutputLength] = CHAR_NULL;
735 }
736 OutputLength = StrLen (TabOutputStr) < MaxStr - 1 ? StrLen (TabOutputStr) : MaxStr - 1;
737 CopyMem (CurrentString + TabUpdatePos, TabOutputStr, OutputLength * sizeof (CHAR16));
738 CurrentString[TabUpdatePos + OutputLength] = CHAR_NULL;
739 StringCurPos = TabUpdatePos + OutputLength;
740 Update = TabUpdatePos;
741 if (StringLen > TabUpdatePos + OutputLength) {
742 Delete = StringLen - TabUpdatePos - OutputLength;
743 }
744 }
745
746 //
747 // If we have a new position, we are preparing to print a previous or
748 // next command.
749 //
750 if (NewPos != (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory)) {
751 Column = StartColumn;
752 Row -= (StringCurPos + StartColumn) / TotalColumn;
753
754 LinePos = NewPos;
755 NewPos = (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory);
756
757 OutputLength = StrLen (LinePos->Buffer) < MaxStr - 1 ? StrLen (LinePos->Buffer) : MaxStr - 1;
758 CopyMem (CurrentString, LinePos->Buffer, OutputLength * sizeof (CHAR16));
759 CurrentString[OutputLength] = CHAR_NULL;
760
761 StringCurPos = OutputLength;
762
763 //
764 // Draw new input string
765 //
766 Update = 0;
767 if (StringLen > OutputLength) {
768 //
769 // If old string was longer, blank its tail
770 //
771 Delete = StringLen - OutputLength;
772 }
773 }
774 //
775 // If we need to update the output do so now
776 //
777 if (Update != (UINTN) -1) {
778 ShellPrintEx ((INT32)Column, (INT32)Row, L"%s%.*s", CurrentString + Update, Delete, L"");
779 StringLen = StrLen (CurrentString);
780
781 if (Delete != 0) {
782 SetMem (CurrentString + StringLen, Delete * sizeof (CHAR16), CHAR_NULL);
783 }
784
785 if (StringCurPos > StringLen) {
786 StringCurPos = StringLen;
787 }
788
789 Update = (UINTN) -1;
790
791 //
792 // After using print to reflect newly updates, if we're not using
793 // BACKSPACE and DELETE, we need to move the cursor position forward,
794 // so adjust row and column here.
795 //
796 if (Key.UnicodeChar != CHAR_BACKSPACE && !(Key.UnicodeChar == 0 && Key.ScanCode == SCAN_DELETE)) {
797 //
798 // Calulate row and column of the tail of current string
799 //
800 TailRow = Row + (StringLen - StringCurPos + Column + OutputLength) / TotalColumn;
801 TailColumn = (StringLen - StringCurPos + Column + OutputLength) % TotalColumn;
802
803 //
804 // If the tail of string reaches screen end, screen rolls up, so if
805 // Row does not equal TailRow, Row should be decremented
806 //
807 // (if we are recalling commands using UPPER and DOWN key, and if the
808 // old command is too long to fit the screen, TailColumn must be 79.
809 //
810 if (TailColumn == 0 && TailRow >= TotalRow && Row != TailRow) {
811 Row--;
812 }
813 //
814 // Calculate the cursor position after current operation. If cursor
815 // reaches line end, update both row and column, otherwise, only
816 // column will be changed.
817 //
818 if (Column + OutputLength >= TotalColumn) {
819 SkipLength = OutputLength - (TotalColumn - Column);
820
821 Row += SkipLength / TotalColumn + 1;
822 if (Row > TotalRow - 1) {
823 Row = TotalRow - 1;
824 }
825
826 Column = SkipLength % TotalColumn;
827 } else {
828 Column += OutputLength;
829 }
830 }
831
832 Delete = 0;
833 }
834 //
835 // Set the cursor position for this key
836 //
837 gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
838 } while (!Done);
839
840 if (CurrentString != NULL && StrLen(CurrentString) > 0) {
841 //
842 // add the line to the history buffer
843 //
844 AddLineToCommandHistory(CurrentString);
845 }
846
847 FreePool (TabStr);
848 FreePool (TabOutputStr);
849 //
850 // Return the data to the caller
851 //
852 *BufferSize = StringLen * sizeof (CHAR16);
853
854 //
855 // if this was used it should be deallocated by now...
856 // prevent memory leaks...
857 //
858 if (FoundFileList != NULL) {
859 ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
860 }
861 ASSERT(FoundFileList == NULL);
862
863 return Status;
864 }
865
866 //
867 // FILE sytle interfaces for StdIn/StdOut/StdErr
868 //
869 EFI_FILE_PROTOCOL FileInterfaceStdIn = {
870 EFI_FILE_REVISION,
871 FileInterfaceOpenNotFound,
872 FileInterfaceNopGeneric,
873 FileInterfaceNopGeneric,
874 FileInterfaceStdInRead,
875 FileInterfaceStdInWrite,
876 FileInterfaceNopGetPosition,
877 FileInterfaceNopSetPosition,
878 FileInterfaceNopGetInfo,
879 FileInterfaceNopSetInfo,
880 FileInterfaceNopGeneric
881 };
882
883 EFI_FILE_PROTOCOL FileInterfaceStdOut = {
884 EFI_FILE_REVISION,
885 FileInterfaceOpenNotFound,
886 FileInterfaceNopGeneric,
887 FileInterfaceNopGeneric,
888 FileInterfaceStdOutRead,
889 FileInterfaceStdOutWrite,
890 FileInterfaceNopGetPosition,
891 FileInterfaceNopSetPosition,
892 FileInterfaceNopGetInfo,
893 FileInterfaceNopSetInfo,
894 FileInterfaceNopGeneric
895 };
896
897 EFI_FILE_PROTOCOL FileInterfaceStdErr = {
898 EFI_FILE_REVISION,
899 FileInterfaceOpenNotFound,
900 FileInterfaceNopGeneric,
901 FileInterfaceNopGeneric,
902 FileInterfaceStdErrRead,
903 FileInterfaceStdErrWrite,
904 FileInterfaceNopGetPosition,
905 FileInterfaceNopSetPosition,
906 FileInterfaceNopGetInfo,
907 FileInterfaceNopSetInfo,
908 FileInterfaceNopGeneric
909 };
910
911 EFI_FILE_PROTOCOL FileInterfaceNulFile = {
912 EFI_FILE_REVISION,
913 FileInterfaceOpenNotFound,
914 FileInterfaceNopGeneric,
915 FileInterfaceNopGeneric,
916 FileInterfaceNulRead,
917 FileInterfaceNulWrite,
918 FileInterfaceNopGetPosition,
919 FileInterfaceNopSetPosition,
920 FileInterfaceNopGetInfo,
921 FileInterfaceNopSetInfo,
922 FileInterfaceNopGeneric
923 };
924
925
926
927
928 //
929 // This is identical to EFI_FILE_PROTOCOL except for the additional member
930 // for the name.
931 //
932
933 typedef struct {
934 UINT64 Revision;
935 EFI_FILE_OPEN Open;
936 EFI_FILE_CLOSE Close;
937 EFI_FILE_DELETE Delete;
938 EFI_FILE_READ Read;
939 EFI_FILE_WRITE Write;
940 EFI_FILE_GET_POSITION GetPosition;
941 EFI_FILE_SET_POSITION SetPosition;
942 EFI_FILE_GET_INFO GetInfo;
943 EFI_FILE_SET_INFO SetInfo;
944 EFI_FILE_FLUSH Flush;
945 CHAR16 Name[1];
946 } EFI_FILE_PROTOCOL_ENVIRONMENT;
947 //ANSI compliance helper to get size of the struct.
948 #define SIZE_OF_EFI_FILE_PROTOCOL_ENVIRONMENT EFI_FIELD_OFFSET (EFI_FILE_PROTOCOL_ENVIRONMENT, Name)
949
950 /**
951 File style interface for Environment Variable (Close).
952
953 Frees the memory for this object.
954
955 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
956
957 @retval EFI_SUCCESS
958 **/
959 EFI_STATUS
960 EFIAPI
961 FileInterfaceEnvClose(
962 IN EFI_FILE_PROTOCOL *This
963 )
964 {
965 VOID* NewBuffer;
966 UINTN NewSize;
967 EFI_STATUS Status;
968
969 //
970 // Most if not all UEFI commands will have an '\r\n' at the end of any output.
971 // Since the output was redirected to a variable, it does not make sense to
972 // keep this. So, before closing, strip the trailing '\r\n' from the variable
973 // if it exists.
974 //
975 NewBuffer = NULL;
976 NewSize = 0;
977
978 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
979 if (Status == EFI_BUFFER_TOO_SMALL) {
980 NewBuffer = AllocateZeroPool(NewSize + sizeof(CHAR16));
981 if (NewBuffer == NULL) {
982 return EFI_OUT_OF_RESOURCES;
983 }
984 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
985 }
986
987 if (!EFI_ERROR(Status) && NewBuffer != NULL) {
988
989 if (StrSize(NewBuffer) > 6)
990 {
991 if ((((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 2] == CHAR_LINEFEED)
992 && (((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] == CHAR_CARRIAGE_RETURN)) {
993 ((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] = CHAR_NULL;
994 }
995
996 if (IsVolatileEnv(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name)) {
997 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);
998 } else {
999 Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);
1000 }
1001 }
1002 }
1003
1004 SHELL_FREE_NON_NULL(NewBuffer);
1005 FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT*)This);
1006 return (Status);
1007 }
1008
1009 /**
1010 File style interface for Environment Variable (Delete).
1011
1012 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1013
1014 @retval The return value from FileInterfaceEnvClose().
1015 **/
1016 EFI_STATUS
1017 EFIAPI
1018 FileInterfaceEnvDelete(
1019 IN EFI_FILE_PROTOCOL *This
1020 )
1021 {
1022 SHELL_DELETE_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name);
1023 return (FileInterfaceEnvClose(This));
1024 }
1025
1026 /**
1027 File style interface for Environment Variable (Read).
1028
1029 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1030 @param[in, out] BufferSize Size in bytes of Buffer.
1031 @param[out] Buffer The pointer to the buffer to fill.
1032
1033 @retval EFI_SUCCESS The data was read.
1034 **/
1035 EFI_STATUS
1036 EFIAPI
1037 FileInterfaceEnvRead(
1038 IN EFI_FILE_PROTOCOL *This,
1039 IN OUT UINTN *BufferSize,
1040 OUT VOID *Buffer
1041 )
1042 {
1043 return (SHELL_GET_ENVIRONMENT_VARIABLE(
1044 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,
1045 BufferSize,
1046 Buffer));
1047 }
1048
1049 /**
1050 File style interface for Volatile Environment Variable (Write).
1051
1052 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1053 @param[in, out] BufferSize Size in bytes of Buffer.
1054 @param[in] Buffer The pointer to the buffer to write.
1055
1056 @retval EFI_SUCCESS The data was read.
1057 **/
1058 EFI_STATUS
1059 EFIAPI
1060 FileInterfaceEnvVolWrite(
1061 IN EFI_FILE_PROTOCOL *This,
1062 IN OUT UINTN *BufferSize,
1063 IN VOID *Buffer
1064 )
1065 {
1066 VOID* NewBuffer;
1067 UINTN NewSize;
1068 EFI_STATUS Status;
1069
1070 NewBuffer = NULL;
1071 NewSize = 0;
1072
1073 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
1074 if (Status == EFI_BUFFER_TOO_SMALL){
1075 NewBuffer = AllocateZeroPool(NewSize + *BufferSize + sizeof(CHAR16));
1076 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
1077 }
1078 if (!EFI_ERROR(Status) && NewBuffer != NULL) {
1079 while (((CHAR16*)NewBuffer)[NewSize/2] == CHAR_NULL) {
1080 //
1081 // We want to overwrite the CHAR_NULL
1082 //
1083 NewSize -= 2;
1084 }
1085 CopyMem((UINT8*)NewBuffer + NewSize + 2, Buffer, *BufferSize);
1086 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);
1087 FreePool(NewBuffer);
1088 return (Status);
1089 } else {
1090 SHELL_FREE_NON_NULL(NewBuffer);
1091 return (SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, *BufferSize, Buffer));
1092 }
1093 }
1094
1095
1096 /**
1097 File style interface for Non Volatile Environment Variable (Write).
1098
1099 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1100 @param[in, out] BufferSize Size in bytes of Buffer.
1101 @param[in] Buffer The pointer to the buffer to write.
1102
1103 @retval EFI_SUCCESS The data was read.
1104 **/
1105 EFI_STATUS
1106 EFIAPI
1107 FileInterfaceEnvNonVolWrite(
1108 IN EFI_FILE_PROTOCOL *This,
1109 IN OUT UINTN *BufferSize,
1110 IN VOID *Buffer
1111 )
1112 {
1113 VOID* NewBuffer;
1114 UINTN NewSize;
1115 EFI_STATUS Status;
1116
1117 NewBuffer = NULL;
1118 NewSize = 0;
1119
1120 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
1121 if (Status == EFI_BUFFER_TOO_SMALL){
1122 NewBuffer = AllocateZeroPool(NewSize + *BufferSize);
1123 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
1124 }
1125 if (!EFI_ERROR(Status)) {
1126 CopyMem((UINT8*)NewBuffer + NewSize, Buffer, *BufferSize);
1127 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
1128 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,
1129 NewSize + *BufferSize,
1130 NewBuffer));
1131 } else {
1132 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
1133 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,
1134 *BufferSize,
1135 Buffer));
1136 }
1137 }
1138
1139 /**
1140 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1141 environment variables through file operations.
1142
1143 @param EnvName The name of the Environment Variable to be operated on.
1144
1145 @retval NULL Memory could not be allocated.
1146 @return other a pointer to an EFI_FILE_PROTOCOL structure
1147 **/
1148 EFI_FILE_PROTOCOL*
1149 EFIAPI
1150 CreateFileInterfaceEnv(
1151 IN CONST CHAR16 *EnvName
1152 )
1153 {
1154 EFI_FILE_PROTOCOL_ENVIRONMENT *EnvFileInterface;
1155 UINTN EnvNameSize;
1156
1157 if (EnvName == NULL) {
1158 return (NULL);
1159 }
1160
1161 //
1162 // Get some memory
1163 //
1164 EnvNameSize = StrSize(EnvName);
1165 EnvFileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT)+EnvNameSize);
1166 if (EnvFileInterface == NULL){
1167 return (NULL);
1168 }
1169
1170 //
1171 // Assign the generic members
1172 //
1173 EnvFileInterface->Revision = EFI_FILE_REVISION;
1174 EnvFileInterface->Open = FileInterfaceOpenNotFound;
1175 EnvFileInterface->Close = FileInterfaceEnvClose;
1176 EnvFileInterface->GetPosition = FileInterfaceNopGetPosition;
1177 EnvFileInterface->SetPosition = FileInterfaceNopSetPosition;
1178 EnvFileInterface->GetInfo = FileInterfaceNopGetInfo;
1179 EnvFileInterface->SetInfo = FileInterfaceNopSetInfo;
1180 EnvFileInterface->Flush = FileInterfaceNopGeneric;
1181 EnvFileInterface->Delete = FileInterfaceEnvDelete;
1182 EnvFileInterface->Read = FileInterfaceEnvRead;
1183
1184 CopyMem(EnvFileInterface->Name, EnvName, EnvNameSize);
1185
1186 //
1187 // Assign the different members for Volatile and Non-Volatile variables
1188 //
1189 if (IsVolatileEnv(EnvName)) {
1190 EnvFileInterface->Write = FileInterfaceEnvVolWrite;
1191 } else {
1192 EnvFileInterface->Write = FileInterfaceEnvNonVolWrite;
1193 }
1194 return ((EFI_FILE_PROTOCOL *)EnvFileInterface);
1195 }
1196
1197 /**
1198 Move the cursor position one character backward.
1199
1200 @param[in] LineLength Length of a line. Get it by calling QueryMode
1201 @param[in, out] Column Current column of the cursor position
1202 @param[in, out] Row Current row of the cursor position
1203 **/
1204 VOID
1205 EFIAPI
1206 MoveCursorBackward (
1207 IN UINTN LineLength,
1208 IN OUT UINTN *Column,
1209 IN OUT UINTN *Row
1210 )
1211 {
1212 //
1213 // If current column is 0, move to the last column of the previous line,
1214 // otherwise, just decrement column.
1215 //
1216 if (*Column == 0) {
1217 *Column = LineLength - 1;
1218 if (*Row > 0) {
1219 (*Row)--;
1220 }
1221 return;
1222 }
1223 (*Column)--;
1224 }
1225
1226 /**
1227 Move the cursor position one character forward.
1228
1229 @param[in] LineLength Length of a line.
1230 @param[in] TotalRow Total row of a screen
1231 @param[in, out] Column Current column of the cursor position
1232 @param[in, out] Row Current row of the cursor position
1233 **/
1234 VOID
1235 EFIAPI
1236 MoveCursorForward (
1237 IN UINTN LineLength,
1238 IN UINTN TotalRow,
1239 IN OUT UINTN *Column,
1240 IN OUT UINTN *Row
1241 )
1242 {
1243 //
1244 // Increment Column.
1245 // If this puts column past the end of the line, move to first column
1246 // of the next row.
1247 //
1248 (*Column)++;
1249 if (*Column >= LineLength) {
1250 (*Column) = 0;
1251 if ((*Row) < TotalRow - 1) {
1252 (*Row)++;
1253 }
1254 }
1255 }
1256
1257 /**
1258 Prints out each previously typed command in the command list history log.
1259
1260 When each screen is full it will pause for a key before continuing.
1261
1262 @param[in] TotalCols How many columns are on the screen
1263 @param[in] TotalRows How many rows are on the screen
1264 @param[in] StartColumn which column to start at
1265 **/
1266 VOID
1267 EFIAPI
1268 PrintCommandHistory (
1269 IN CONST UINTN TotalCols,
1270 IN CONST UINTN TotalRows,
1271 IN CONST UINTN StartColumn
1272 )
1273 {
1274 BUFFER_LIST *Node;
1275 UINTN Index;
1276 UINTN LineNumber;
1277 UINTN LineCount;
1278
1279 ShellPrintEx (-1, -1, L"\n");
1280 Index = 0;
1281 LineNumber = 0;
1282 //
1283 // go through history list...
1284 //
1285 for ( Node = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link)
1286 ; !IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link)
1287 ; Node = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link)
1288 ){
1289 Index++;
1290 LineCount = ((StrLen (Node->Buffer) + StartColumn + 1) / TotalCols) + 1;
1291
1292 if (LineNumber + LineCount >= TotalRows) {
1293 ShellPromptForResponseHii(
1294 ShellPromptResponseTypeEnterContinue,
1295 STRING_TOKEN (STR_SHELL_ENTER_TO_CONT),
1296 ShellInfoObject.HiiHandle,
1297 NULL
1298 );
1299 LineNumber = 0;
1300 }
1301 ShellPrintEx (-1, -1, L"%2d. %s\n", Index, Node->Buffer);
1302 LineNumber += LineCount;
1303 }
1304 }
1305
1306
1307
1308
1309
1310
1311 //
1312 // This is identical to EFI_FILE_PROTOCOL except for the additional members
1313 // for the buffer, size, and position.
1314 //
1315
1316 typedef struct {
1317 UINT64 Revision;
1318 EFI_FILE_OPEN Open;
1319 EFI_FILE_CLOSE Close;
1320 EFI_FILE_DELETE Delete;
1321 EFI_FILE_READ Read;
1322 EFI_FILE_WRITE Write;
1323 EFI_FILE_GET_POSITION GetPosition;
1324 EFI_FILE_SET_POSITION SetPosition;
1325 EFI_FILE_GET_INFO GetInfo;
1326 EFI_FILE_SET_INFO SetInfo;
1327 EFI_FILE_FLUSH Flush;
1328 VOID *Buffer;
1329 UINT64 Position;
1330 UINT64 BufferSize;
1331 BOOLEAN Unicode;
1332 UINT64 FileSize;
1333 } EFI_FILE_PROTOCOL_MEM;
1334
1335 /**
1336 File style interface for Mem (SetPosition).
1337
1338 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1339 @param[out] Position The position to set.
1340
1341 @retval EFI_SUCCESS The position was successfully changed.
1342 @retval EFI_INVALID_PARAMETER The Position was invalid.
1343 **/
1344 EFI_STATUS
1345 EFIAPI
1346 FileInterfaceMemSetPosition(
1347 IN EFI_FILE_PROTOCOL *This,
1348 OUT UINT64 Position
1349 )
1350 {
1351 if (Position <= ((EFI_FILE_PROTOCOL_MEM*)This)->FileSize) {
1352 ((EFI_FILE_PROTOCOL_MEM*)This)->Position = Position;
1353 return (EFI_SUCCESS);
1354 } else {
1355 return (EFI_INVALID_PARAMETER);
1356 }
1357 }
1358
1359 /**
1360 File style interface for Mem (GetPosition).
1361
1362 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1363 @param[out] Position The pointer to the position.
1364
1365 @retval EFI_SUCCESS The position was retrieved.
1366 **/
1367 EFI_STATUS
1368 EFIAPI
1369 FileInterfaceMemGetPosition(
1370 IN EFI_FILE_PROTOCOL *This,
1371 OUT UINT64 *Position
1372 )
1373 {
1374 *Position = ((EFI_FILE_PROTOCOL_MEM*)This)->Position;
1375 return (EFI_SUCCESS);
1376 }
1377
1378 /**
1379 File style interface for Mem (Write).
1380
1381 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1382 @param[in, out] BufferSize Size in bytes of Buffer.
1383 @param[in] Buffer The pointer to the buffer to write.
1384
1385 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.
1386 @retval EFI_SUCCESS The data was written.
1387 **/
1388 EFI_STATUS
1389 EFIAPI
1390 FileInterfaceMemWrite(
1391 IN EFI_FILE_PROTOCOL *This,
1392 IN OUT UINTN *BufferSize,
1393 IN VOID *Buffer
1394 )
1395 {
1396 CHAR8 *AsciiBuffer;
1397 EFI_FILE_PROTOCOL_MEM *MemFile;
1398
1399 MemFile = (EFI_FILE_PROTOCOL_MEM *) This;
1400 if (MemFile->Unicode) {
1401 //
1402 // Unicode
1403 //
1404 if ((UINTN)(MemFile->Position + (*BufferSize)) > (UINTN)(MemFile->BufferSize)) {
1405 MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer);
1406 MemFile->BufferSize += (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD;
1407 }
1408 CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, Buffer, *BufferSize);
1409 MemFile->Position += (*BufferSize);
1410 MemFile->FileSize = MemFile->Position;
1411 return (EFI_SUCCESS);
1412 } else {
1413 //
1414 // Ascii
1415 //
1416 AsciiBuffer = AllocateZeroPool(*BufferSize);
1417 if (AsciiBuffer == NULL) {
1418 return (EFI_OUT_OF_RESOURCES);
1419 }
1420 AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer);
1421 if ((UINTN)(MemFile->Position + AsciiStrSize(AsciiBuffer)) > (UINTN)(MemFile->BufferSize)) {
1422 MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + AsciiStrSize(AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer);
1423 MemFile->BufferSize += AsciiStrSize(AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD;
1424 }
1425 CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, AsciiBuffer, AsciiStrSize(AsciiBuffer));
1426 MemFile->Position += (*BufferSize / sizeof(CHAR16));
1427 MemFile->FileSize = MemFile->Position;
1428 FreePool(AsciiBuffer);
1429 return (EFI_SUCCESS);
1430 }
1431 }
1432
1433 /**
1434 File style interface for Mem (Read).
1435
1436 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1437 @param[in, out] BufferSize Size in bytes of Buffer.
1438 @param[in] Buffer The pointer to the buffer to fill.
1439
1440 @retval EFI_SUCCESS The data was read.
1441 **/
1442 EFI_STATUS
1443 EFIAPI
1444 FileInterfaceMemRead(
1445 IN EFI_FILE_PROTOCOL *This,
1446 IN OUT UINTN *BufferSize,
1447 IN VOID *Buffer
1448 )
1449 {
1450 EFI_FILE_PROTOCOL_MEM *MemFile;
1451
1452 MemFile = (EFI_FILE_PROTOCOL_MEM *) This;
1453 if (*BufferSize > (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position))) {
1454 (*BufferSize) = (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position));
1455 }
1456 CopyMem(Buffer, ((UINT8*)MemFile->Buffer) + MemFile->Position, (*BufferSize));
1457 MemFile->Position = MemFile->Position + (*BufferSize);
1458 return (EFI_SUCCESS);
1459 }
1460
1461 /**
1462 File style interface for Mem (Close).
1463
1464 Frees all memory associated with this object.
1465
1466 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1467
1468 @retval EFI_SUCCESS The 'file' was closed.
1469 **/
1470 EFI_STATUS
1471 EFIAPI
1472 FileInterfaceMemClose(
1473 IN EFI_FILE_PROTOCOL *This
1474 )
1475 {
1476 SHELL_FREE_NON_NULL(((EFI_FILE_PROTOCOL_MEM*)This)->Buffer);
1477 SHELL_FREE_NON_NULL(This);
1478 return (EFI_SUCCESS);
1479 }
1480
1481 /**
1482 Creates a EFI_FILE_PROTOCOL (almost) object for using to access
1483 a file entirely in memory through file operations.
1484
1485 @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii.
1486
1487 @retval NULL Memory could not be allocated.
1488 @return other A pointer to an EFI_FILE_PROTOCOL structure.
1489 **/
1490 EFI_FILE_PROTOCOL*
1491 EFIAPI
1492 CreateFileInterfaceMem(
1493 IN CONST BOOLEAN Unicode
1494 )
1495 {
1496 EFI_FILE_PROTOCOL_MEM *FileInterface;
1497
1498 //
1499 // Get some memory
1500 //
1501 FileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_MEM));
1502 if (FileInterface == NULL){
1503 return (NULL);
1504 }
1505
1506 //
1507 // Assign the generic members
1508 //
1509 FileInterface->Revision = EFI_FILE_REVISION;
1510 FileInterface->Open = FileInterfaceOpenNotFound;
1511 FileInterface->Close = FileInterfaceMemClose;
1512 FileInterface->GetPosition = FileInterfaceMemGetPosition;
1513 FileInterface->SetPosition = FileInterfaceMemSetPosition;
1514 FileInterface->GetInfo = FileInterfaceNopGetInfo;
1515 FileInterface->SetInfo = FileInterfaceNopSetInfo;
1516 FileInterface->Flush = FileInterfaceNopGeneric;
1517 FileInterface->Delete = FileInterfaceNopGeneric;
1518 FileInterface->Read = FileInterfaceMemRead;
1519 FileInterface->Write = FileInterfaceMemWrite;
1520 FileInterface->Unicode = Unicode;
1521
1522 ASSERT(FileInterface->Buffer == NULL);
1523 ASSERT(FileInterface->BufferSize == 0);
1524 ASSERT(FileInterface->Position == 0);
1525
1526 if (Unicode) {
1527 FileInterface->Buffer = AllocateZeroPool(sizeof(gUnicodeFileTag));
1528 if (FileInterface->Buffer == NULL) {
1529 FreePool (FileInterface);
1530 return NULL;
1531 }
1532 *((CHAR16 *) (FileInterface->Buffer)) = EFI_UNICODE_BYTE_ORDER_MARK;
1533 FileInterface->BufferSize = 2;
1534 FileInterface->Position = 2;
1535 }
1536
1537 return ((EFI_FILE_PROTOCOL *)FileInterface);
1538 }
1539
1540 typedef struct {
1541 UINT64 Revision;
1542 EFI_FILE_OPEN Open;
1543 EFI_FILE_CLOSE Close;
1544 EFI_FILE_DELETE Delete;
1545 EFI_FILE_READ Read;
1546 EFI_FILE_WRITE Write;
1547 EFI_FILE_GET_POSITION GetPosition;
1548 EFI_FILE_SET_POSITION SetPosition;
1549 EFI_FILE_GET_INFO GetInfo;
1550 EFI_FILE_SET_INFO SetInfo;
1551 EFI_FILE_FLUSH Flush;
1552 BOOLEAN Unicode;
1553 EFI_FILE_PROTOCOL *Orig;
1554 } EFI_FILE_PROTOCOL_FILE;
1555
1556 /**
1557 Set a files current position
1558
1559 @param This Protocol instance pointer.
1560 @param Position Byte position from the start of the file.
1561
1562 @retval EFI_SUCCESS Data was written.
1563 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
1564
1565 **/
1566 EFI_STATUS
1567 EFIAPI
1568 FileInterfaceFileSetPosition(
1569 IN EFI_FILE_PROTOCOL *This,
1570 IN UINT64 Position
1571 )
1572 {
1573 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->SetPosition(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, Position);
1574 }
1575
1576 /**
1577 Get a file's current position
1578
1579 @param This Protocol instance pointer.
1580 @param Position Byte position from the start of the file.
1581
1582 @retval EFI_SUCCESS Data was written.
1583 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
1584
1585 **/
1586 EFI_STATUS
1587 EFIAPI
1588 FileInterfaceFileGetPosition(
1589 IN EFI_FILE_PROTOCOL *This,
1590 OUT UINT64 *Position
1591 )
1592 {
1593 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetPosition(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, Position);
1594 }
1595
1596 /**
1597 Get information about a file.
1598
1599 @param This Protocol instance pointer.
1600 @param InformationType Type of information to return in Buffer.
1601 @param BufferSize On input size of buffer, on output amount of data in buffer.
1602 @param Buffer The buffer to return data.
1603
1604 @retval EFI_SUCCESS Data was returned.
1605 @retval EFI_UNSUPPORT InformationType is not supported.
1606 @retval EFI_NO_MEDIA The device has no media.
1607 @retval EFI_DEVICE_ERROR The device reported an error.
1608 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1609 @retval EFI_WRITE_PROTECTED The device is write protected.
1610 @retval EFI_ACCESS_DENIED The file was open for read only.
1611 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
1612
1613 **/
1614 EFI_STATUS
1615 EFIAPI
1616 FileInterfaceFileGetInfo(
1617 IN EFI_FILE_PROTOCOL *This,
1618 IN EFI_GUID *InformationType,
1619 IN OUT UINTN *BufferSize,
1620 OUT VOID *Buffer
1621 )
1622 {
1623 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetInfo(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, InformationType, BufferSize, Buffer);
1624 }
1625
1626 /**
1627 Set information about a file
1628
1629 @param This Protocol instance pointer.
1630 @param InformationType Type of information in Buffer.
1631 @param BufferSize Size of buffer.
1632 @param Buffer The data to write.
1633
1634 @retval EFI_SUCCESS Data was returned.
1635 @retval EFI_UNSUPPORT InformationType is not supported.
1636 @retval EFI_NO_MEDIA The device has no media.
1637 @retval EFI_DEVICE_ERROR The device reported an error.
1638 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1639 @retval EFI_WRITE_PROTECTED The device is write protected.
1640 @retval EFI_ACCESS_DENIED The file was open for read only.
1641
1642 **/
1643 EFI_STATUS
1644 EFIAPI
1645 FileInterfaceFileSetInfo(
1646 IN EFI_FILE_PROTOCOL *This,
1647 IN EFI_GUID *InformationType,
1648 IN UINTN BufferSize,
1649 IN VOID *Buffer
1650 )
1651 {
1652 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->SetInfo(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, InformationType, BufferSize, Buffer);
1653 }
1654
1655 /**
1656 Flush data back for the file handle.
1657
1658 @param This Protocol instance pointer.
1659
1660 @retval EFI_SUCCESS Data was written.
1661 @retval EFI_UNSUPPORT Writes to Open directory are not supported.
1662 @retval EFI_NO_MEDIA The device has no media.
1663 @retval EFI_DEVICE_ERROR The device reported an error.
1664 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1665 @retval EFI_WRITE_PROTECTED The device is write protected.
1666 @retval EFI_ACCESS_DENIED The file was open for read only.
1667 @retval EFI_VOLUME_FULL The volume is full.
1668
1669 **/
1670 EFI_STATUS
1671 EFIAPI
1672 FileInterfaceFileFlush(
1673 IN EFI_FILE_PROTOCOL *This
1674 )
1675 {
1676 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Flush(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);
1677 }
1678
1679 /**
1680 Read data from the file.
1681
1682 @param This Protocol instance pointer.
1683 @param BufferSize On input size of buffer, on output amount of data in buffer.
1684 @param Buffer The buffer in which data is read.
1685
1686 @retval EFI_SUCCESS Data was read.
1687 @retval EFI_NO_MEDIA The device has no media.
1688 @retval EFI_DEVICE_ERROR The device reported an error.
1689 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1690 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
1691
1692 **/
1693 EFI_STATUS
1694 EFIAPI
1695 FileInterfaceFileRead(
1696 IN EFI_FILE_PROTOCOL *This,
1697 IN OUT UINTN *BufferSize,
1698 OUT VOID *Buffer
1699 )
1700 {
1701 CHAR8 *AsciiStrBuffer;
1702 CHAR16 *UscStrBuffer;
1703 UINTN Size;
1704 UINTN CharNum;
1705 EFI_STATUS Status;
1706 if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) {
1707 //
1708 // Unicode
1709 //
1710 return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer));
1711 } else {
1712 //
1713 // Ascii
1714 //
1715 Size = (*BufferSize) / sizeof(CHAR16);
1716 AsciiStrBuffer = AllocateZeroPool(Size + sizeof(CHAR8));
1717 if (AsciiStrBuffer == NULL) {
1718 return EFI_OUT_OF_RESOURCES;
1719 }
1720 UscStrBuffer = AllocateZeroPool(*BufferSize + sizeof(CHAR16));
1721 if (UscStrBuffer== NULL) {
1722 SHELL_FREE_NON_NULL(AsciiStrBuffer);
1723 return EFI_OUT_OF_RESOURCES;
1724 }
1725 Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiStrBuffer));
1726 if (!EFI_ERROR(Status)) {
1727 CharNum = UnicodeSPrint(UscStrBuffer, *BufferSize + sizeof(CHAR16), L"%a", AsciiStrBuffer);
1728 if (CharNum == Size) {
1729 CopyMem (Buffer, UscStrBuffer, *BufferSize);
1730 } else {
1731 Status = EFI_UNSUPPORTED;
1732 }
1733 }
1734 SHELL_FREE_NON_NULL(AsciiStrBuffer);
1735 SHELL_FREE_NON_NULL(UscStrBuffer);
1736 return (Status);
1737 }
1738 }
1739
1740 /**
1741 Opens a new file relative to the source file's location.
1742
1743 @param[in] This The protocol instance pointer.
1744 @param[out] NewHandle Returns File Handle for FileName.
1745 @param[in] FileName Null terminated string. "\", ".", and ".." are supported.
1746 @param[in] OpenMode Open mode for file.
1747 @param[in] Attributes Only used for EFI_FILE_MODE_CREATE.
1748
1749 @retval EFI_SUCCESS The device was opened.
1750 @retval EFI_NOT_FOUND The specified file could not be found on the device.
1751 @retval EFI_NO_MEDIA The device has no media.
1752 @retval EFI_MEDIA_CHANGED The media has changed.
1753 @retval EFI_DEVICE_ERROR The device reported an error.
1754 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1755 @retval EFI_ACCESS_DENIED The service denied access to the file.
1756 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
1757 @retval EFI_VOLUME_FULL The volume is full.
1758 **/
1759 EFI_STATUS
1760 EFIAPI
1761 FileInterfaceFileOpen (
1762 IN EFI_FILE_PROTOCOL *This,
1763 OUT EFI_FILE_PROTOCOL **NewHandle,
1764 IN CHAR16 *FileName,
1765 IN UINT64 OpenMode,
1766 IN UINT64 Attributes
1767 )
1768 {
1769 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Open(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, NewHandle, FileName, OpenMode, Attributes);
1770 }
1771
1772 /**
1773 Close and delete the file handle.
1774
1775 @param This Protocol instance pointer.
1776
1777 @retval EFI_SUCCESS The device was opened.
1778 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
1779
1780 **/
1781 EFI_STATUS
1782 EFIAPI
1783 FileInterfaceFileDelete(
1784 IN EFI_FILE_PROTOCOL *This
1785 )
1786 {
1787 EFI_STATUS Status;
1788 Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Delete(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);
1789 FreePool(This);
1790 return (Status);
1791 }
1792
1793 /**
1794 File style interface for File (Close).
1795
1796 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1797
1798 @retval EFI_SUCCESS The file was closed.
1799 **/
1800 EFI_STATUS
1801 EFIAPI
1802 FileInterfaceFileClose(
1803 IN EFI_FILE_PROTOCOL *This
1804 )
1805 {
1806 EFI_STATUS Status;
1807 Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Close(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);
1808 FreePool(This);
1809 return (Status);
1810 }
1811
1812 /**
1813 File style interface for File (Write).
1814
1815 If the file was opened with ASCII mode the data will be processed through
1816 AsciiSPrint before writing.
1817
1818 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
1819 @param[in, out] BufferSize Size in bytes of Buffer.
1820 @param[in] Buffer The pointer to the buffer to write.
1821
1822 @retval EFI_SUCCESS The data was written.
1823 **/
1824 EFI_STATUS
1825 EFIAPI
1826 FileInterfaceFileWrite(
1827 IN EFI_FILE_PROTOCOL *This,
1828 IN OUT UINTN *BufferSize,
1829 IN VOID *Buffer
1830 )
1831 {
1832 CHAR8 *AsciiBuffer;
1833 UINTN Size;
1834 EFI_STATUS Status;
1835 if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) {
1836 //
1837 // Unicode
1838 //
1839 return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer));
1840 } else {
1841 //
1842 // Ascii
1843 //
1844 AsciiBuffer = AllocateZeroPool(*BufferSize);
1845 AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer);
1846 Size = AsciiStrSize(AsciiBuffer) - 1; // (we dont need the null terminator)
1847 Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiBuffer));
1848 FreePool(AsciiBuffer);
1849 return (Status);
1850 }
1851 }
1852
1853 /**
1854 Create a file interface with unicode information.
1855
1856 This will create a new EFI_FILE_PROTOCOL identical to the Templace
1857 except that the new one has Unicode and Ascii knowledge.
1858
1859 @param[in] Template A pointer to the EFI_FILE_PROTOCOL object.
1860 @param[in] Unicode TRUE for UCS-2, FALSE for ASCII.
1861
1862 @return a new EFI_FILE_PROTOCOL object to be used instead of the template.
1863 **/
1864 EFI_FILE_PROTOCOL*
1865 CreateFileInterfaceFile(
1866 IN CONST EFI_FILE_PROTOCOL *Template,
1867 IN CONST BOOLEAN Unicode
1868 )
1869 {
1870 EFI_FILE_PROTOCOL_FILE *NewOne;
1871
1872 NewOne = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_FILE));
1873 if (NewOne == NULL) {
1874 return (NULL);
1875 }
1876 CopyMem(NewOne, Template, sizeof(EFI_FILE_PROTOCOL_FILE));
1877 NewOne->Orig = (EFI_FILE_PROTOCOL *)Template;
1878 NewOne->Unicode = Unicode;
1879 NewOne->Open = FileInterfaceFileOpen;
1880 NewOne->Close = FileInterfaceFileClose;
1881 NewOne->Delete = FileInterfaceFileDelete;
1882 NewOne->Read = FileInterfaceFileRead;
1883 NewOne->Write = FileInterfaceFileWrite;
1884 NewOne->GetPosition = FileInterfaceFileGetPosition;
1885 NewOne->SetPosition = FileInterfaceFileSetPosition;
1886 NewOne->GetInfo = FileInterfaceFileGetInfo;
1887 NewOne->SetInfo = FileInterfaceFileSetInfo;
1888 NewOne->Flush = FileInterfaceFileFlush;
1889
1890 return ((EFI_FILE_PROTOCOL *)NewOne);
1891 }