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