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