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