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