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