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