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