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