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