]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Application/Shell/FileHandleWrappers.c
StdLib/LibC ARM AARCH64: do not redefine compiler intrinsics
[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
31e5b912 974 BOOLEAN Volatile;\r
416a423f
CP
975\r
976 //\r
977 // Most if not all UEFI commands will have an '\r\n' at the end of any output. \r
978 // Since the output was redirected to a variable, it does not make sense to \r
979 // keep this. So, before closing, strip the trailing '\r\n' from the variable\r
980 // if it exists.\r
981 //\r
982 NewBuffer = NULL;\r
983 NewSize = 0;\r
984\r
31e5b912
RN
985 Status = IsVolatileEnv (((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &Volatile);\r
986 if (EFI_ERROR (Status)) {\r
987 return Status;\r
988 }\r
989\r
416a423f
CP
990 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);\r
991 if (Status == EFI_BUFFER_TOO_SMALL) {\r
992 NewBuffer = AllocateZeroPool(NewSize + sizeof(CHAR16));\r
993 if (NewBuffer == NULL) {\r
994 return EFI_OUT_OF_RESOURCES;\r
995 } \r
996 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);\r
997 }\r
998 \r
03bc7c2b 999 if (!EFI_ERROR(Status) && NewBuffer != NULL) {\r
416a423f
CP
1000 \r
1001 if (StrSize(NewBuffer) > 6)\r
1002 {\r
1003 if ((((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 2] == CHAR_LINEFEED) \r
1004 && (((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] == CHAR_CARRIAGE_RETURN)) {\r
1005 ((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] = CHAR_NULL; \r
1006 }\r
31e5b912
RN
1007\r
1008 if (Volatile) {\r
416a423f
CP
1009 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);\r
1010 } else {\r
1011 Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);\r
1012 }\r
1013 }\r
1014 } \r
1015 \r
1016 SHELL_FREE_NON_NULL(NewBuffer);\r
a405b86d 1017 FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT*)This);\r
416a423f 1018 return (Status);\r
a405b86d 1019}\r
1020\r
1021/**\r
1022 File style interface for Environment Variable (Delete).\r
1023 \r
1024 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
1025 \r
1026 @retval The return value from FileInterfaceEnvClose().\r
1027**/\r
1028EFI_STATUS\r
1029EFIAPI\r
1030FileInterfaceEnvDelete(\r
1031 IN EFI_FILE_PROTOCOL *This\r
1032 )\r
1033{\r
1034 SHELL_DELETE_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name);\r
1035 return (FileInterfaceEnvClose(This));\r
1036}\r
1037\r
1038/**\r
1039 File style interface for Environment Variable (Read).\r
1040 \r
4ff7e37b
ED
1041 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
1042 @param[in, out] BufferSize Size in bytes of Buffer.\r
1043 @param[out] Buffer The pointer to the buffer to fill.\r
a405b86d 1044 \r
1045 @retval EFI_SUCCESS The data was read.\r
1046**/\r
1047EFI_STATUS\r
1048EFIAPI\r
1049FileInterfaceEnvRead(\r
1050 IN EFI_FILE_PROTOCOL *This,\r
1051 IN OUT UINTN *BufferSize,\r
1052 OUT VOID *Buffer\r
1053 )\r
1054{\r
1055 return (SHELL_GET_ENVIRONMENT_VARIABLE(\r
1056 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,\r
1057 BufferSize,\r
1058 Buffer));\r
1059}\r
1060\r
1061/**\r
1062 File style interface for Volatile Environment Variable (Write).\r
1063 \r
4ff7e37b
ED
1064 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
1065 @param[in, out] BufferSize Size in bytes of Buffer.\r
1066 @param[in] Buffer The pointer to the buffer to write.\r
a405b86d 1067 \r
1068 @retval EFI_SUCCESS The data was read.\r
1069**/\r
1070EFI_STATUS\r
1071EFIAPI\r
1072FileInterfaceEnvVolWrite(\r
1073 IN EFI_FILE_PROTOCOL *This,\r
1074 IN OUT UINTN *BufferSize,\r
1075 IN VOID *Buffer\r
1076 )\r
1077{\r
1078 VOID* NewBuffer;\r
1079 UINTN NewSize;\r
1080 EFI_STATUS Status;\r
1081\r
1082 NewBuffer = NULL;\r
1083 NewSize = 0;\r
1084\r
1085 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);\r
1086 if (Status == EFI_BUFFER_TOO_SMALL){\r
1087 NewBuffer = AllocateZeroPool(NewSize + *BufferSize + sizeof(CHAR16));\r
1088 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);\r
1089 }\r
1090 if (!EFI_ERROR(Status) && NewBuffer != NULL) {\r
1091 while (((CHAR16*)NewBuffer)[NewSize/2] == CHAR_NULL) {\r
1092 //\r
1093 // We want to overwrite the CHAR_NULL\r
1094 //\r
1095 NewSize -= 2;\r
1096 }\r
1097 CopyMem((UINT8*)NewBuffer + NewSize + 2, Buffer, *BufferSize);\r
1098 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);\r
1099 FreePool(NewBuffer);\r
1100 return (Status);\r
1101 } else {\r
1102 SHELL_FREE_NON_NULL(NewBuffer);\r
1103 return (SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, *BufferSize, Buffer));\r
1104 }\r
1105}\r
1106\r
1107\r
1108/**\r
1109 File style interface for Non Volatile Environment Variable (Write).\r
1110 \r
4ff7e37b
ED
1111 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
1112 @param[in, out] BufferSize Size in bytes of Buffer.\r
1113 @param[in] Buffer The pointer to the buffer to write.\r
a405b86d 1114 \r
1115 @retval EFI_SUCCESS The data was read.\r
1116**/\r
1117EFI_STATUS\r
1118EFIAPI\r
1119FileInterfaceEnvNonVolWrite(\r
1120 IN EFI_FILE_PROTOCOL *This,\r
1121 IN OUT UINTN *BufferSize,\r
1122 IN VOID *Buffer\r
1123 )\r
1124{\r
1125 VOID* NewBuffer;\r
1126 UINTN NewSize;\r
1127 EFI_STATUS Status;\r
1128\r
1129 NewBuffer = NULL;\r
1130 NewSize = 0;\r
1131\r
1132 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);\r
1133 if (Status == EFI_BUFFER_TOO_SMALL){\r
1134 NewBuffer = AllocateZeroPool(NewSize + *BufferSize);\r
1135 Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);\r
1136 }\r
1137 if (!EFI_ERROR(Status)) {\r
1138 CopyMem((UINT8*)NewBuffer + NewSize, Buffer, *BufferSize);\r
1139 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(\r
1140 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,\r
1141 NewSize + *BufferSize,\r
1142 NewBuffer));\r
1143 } else {\r
1144 return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(\r
1145 ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,\r
1146 *BufferSize,\r
1147 Buffer));\r
1148 }\r
1149}\r
1150\r
1151/**\r
1152 Creates a EFI_FILE_PROTOCOL (almost) object for using to access\r
1153 environment variables through file operations.\r
1154\r
1155 @param EnvName The name of the Environment Variable to be operated on.\r
1156\r
1157 @retval NULL Memory could not be allocated.\r
1158 @return other a pointer to an EFI_FILE_PROTOCOL structure\r
1159**/\r
1160EFI_FILE_PROTOCOL*\r
1161EFIAPI\r
1162CreateFileInterfaceEnv(\r
1163 IN CONST CHAR16 *EnvName\r
1164 )\r
1165{\r
31e5b912 1166 EFI_STATUS Status;\r
a405b86d 1167 EFI_FILE_PROTOCOL_ENVIRONMENT *EnvFileInterface;\r
323d3d11 1168 UINTN EnvNameSize;\r
31e5b912 1169 BOOLEAN Volatile;\r
a405b86d 1170\r
1171 if (EnvName == NULL) {\r
1172 return (NULL);\r
1173 }\r
1174\r
31e5b912
RN
1175 Status = IsVolatileEnv (EnvName, &Volatile);\r
1176 if (EFI_ERROR (Status)) {\r
1177 return NULL;\r
1178 }\r
1179\r
a405b86d 1180 //\r
1181 // Get some memory\r
1182 //\r
323d3d11
QS
1183 EnvNameSize = StrSize(EnvName);\r
1184 EnvFileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT)+EnvNameSize);\r
a405b86d 1185 if (EnvFileInterface == NULL){\r
1186 return (NULL);\r
1187 }\r
1188\r
1189 //\r
1190 // Assign the generic members\r
1191 //\r
1192 EnvFileInterface->Revision = EFI_FILE_REVISION;\r
1193 EnvFileInterface->Open = FileInterfaceOpenNotFound;\r
1194 EnvFileInterface->Close = FileInterfaceEnvClose;\r
1195 EnvFileInterface->GetPosition = FileInterfaceNopGetPosition;\r
1196 EnvFileInterface->SetPosition = FileInterfaceNopSetPosition;\r
1197 EnvFileInterface->GetInfo = FileInterfaceNopGetInfo;\r
1198 EnvFileInterface->SetInfo = FileInterfaceNopSetInfo;\r
1199 EnvFileInterface->Flush = FileInterfaceNopGeneric;\r
1200 EnvFileInterface->Delete = FileInterfaceEnvDelete;\r
1201 EnvFileInterface->Read = FileInterfaceEnvRead;\r
323d3d11
QS
1202 \r
1203 CopyMem(EnvFileInterface->Name, EnvName, EnvNameSize);\r
a405b86d 1204\r
1205 //\r
1206 // Assign the different members for Volatile and Non-Volatile variables\r
1207 //\r
31e5b912 1208 if (Volatile) {\r
a405b86d 1209 EnvFileInterface->Write = FileInterfaceEnvVolWrite;\r
1210 } else {\r
1211 EnvFileInterface->Write = FileInterfaceEnvNonVolWrite;\r
1212 }\r
1213 return ((EFI_FILE_PROTOCOL *)EnvFileInterface);\r
1214}\r
1215\r
1216/**\r
1217 Move the cursor position one character backward.\r
1218\r
1219 @param[in] LineLength Length of a line. Get it by calling QueryMode\r
4ff7e37b
ED
1220 @param[in, out] Column Current column of the cursor position\r
1221 @param[in, out] Row Current row of the cursor position\r
a405b86d 1222**/\r
1223VOID\r
1224EFIAPI\r
1225MoveCursorBackward (\r
1226 IN UINTN LineLength,\r
1227 IN OUT UINTN *Column,\r
1228 IN OUT UINTN *Row\r
1229 )\r
1230{\r
1231 //\r
1232 // If current column is 0, move to the last column of the previous line,\r
1233 // otherwise, just decrement column.\r
1234 //\r
1235 if (*Column == 0) {\r
1236 *Column = LineLength - 1;\r
1237 if (*Row > 0) {\r
1238 (*Row)--;\r
1239 }\r
1240 return;\r
1241 }\r
1242 (*Column)--;\r
1243}\r
1244\r
1245/**\r
1246 Move the cursor position one character forward.\r
1247\r
1248 @param[in] LineLength Length of a line.\r
1249 @param[in] TotalRow Total row of a screen\r
4ff7e37b
ED
1250 @param[in, out] Column Current column of the cursor position\r
1251 @param[in, out] Row Current row of the cursor position\r
a405b86d 1252**/\r
1253VOID\r
1254EFIAPI\r
1255MoveCursorForward (\r
1256 IN UINTN LineLength,\r
1257 IN UINTN TotalRow,\r
1258 IN OUT UINTN *Column,\r
1259 IN OUT UINTN *Row\r
1260 )\r
1261{\r
1262 //\r
1263 // Increment Column.\r
1264 // If this puts column past the end of the line, move to first column\r
1265 // of the next row.\r
1266 //\r
1267 (*Column)++;\r
1268 if (*Column >= LineLength) {\r
1269 (*Column) = 0;\r
1270 if ((*Row) < TotalRow - 1) {\r
1271 (*Row)++;\r
1272 }\r
1273 }\r
1274}\r
1275\r
1276/**\r
1277 Prints out each previously typed command in the command list history log.\r
1278\r
1279 When each screen is full it will pause for a key before continuing.\r
1280\r
1281 @param[in] TotalCols How many columns are on the screen\r
1282 @param[in] TotalRows How many rows are on the screen\r
1283 @param[in] StartColumn which column to start at\r
1284**/\r
1285VOID\r
1286EFIAPI\r
1287PrintCommandHistory (\r
1288 IN CONST UINTN TotalCols,\r
1289 IN CONST UINTN TotalRows,\r
1290 IN CONST UINTN StartColumn\r
1291 )\r
1292{\r
1293 BUFFER_LIST *Node;\r
1294 UINTN Index;\r
1295 UINTN LineNumber;\r
1296 UINTN LineCount;\r
1297\r
1298 ShellPrintEx (-1, -1, L"\n");\r
1299 Index = 0;\r
1300 LineNumber = 0;\r
1301 //\r
1302 // go through history list...\r
1303 //\r
1304 for ( Node = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link)\r
1305 ; !IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link)\r
1306 ; Node = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link)\r
1307 ){\r
1308 Index++;\r
1309 LineCount = ((StrLen (Node->Buffer) + StartColumn + 1) / TotalCols) + 1;\r
1310\r
1311 if (LineNumber + LineCount >= TotalRows) {\r
1312 ShellPromptForResponseHii(\r
1313 ShellPromptResponseTypeEnterContinue,\r
1314 STRING_TOKEN (STR_SHELL_ENTER_TO_CONT),\r
1315 ShellInfoObject.HiiHandle,\r
1316 NULL\r
1317 );\r
1318 LineNumber = 0;\r
1319 }\r
1320 ShellPrintEx (-1, -1, L"%2d. %s\n", Index, Node->Buffer);\r
1321 LineNumber += LineCount;\r
1322 }\r
1323}\r
1324\r
1325\r
1326\r
1327\r
1328\r
1329\r
1330//\r
1331// This is identical to EFI_FILE_PROTOCOL except for the additional members\r
1332// for the buffer, size, and position.\r
1333//\r
1334\r
1335typedef struct {\r
1336 UINT64 Revision;\r
1337 EFI_FILE_OPEN Open;\r
1338 EFI_FILE_CLOSE Close;\r
1339 EFI_FILE_DELETE Delete;\r
1340 EFI_FILE_READ Read;\r
1341 EFI_FILE_WRITE Write;\r
1342 EFI_FILE_GET_POSITION GetPosition;\r
1343 EFI_FILE_SET_POSITION SetPosition;\r
1344 EFI_FILE_GET_INFO GetInfo;\r
1345 EFI_FILE_SET_INFO SetInfo;\r
1346 EFI_FILE_FLUSH Flush;\r
1347 VOID *Buffer;\r
1348 UINT64 Position;\r
1349 UINT64 BufferSize;\r
1350 BOOLEAN Unicode;\r
7bcd3ff6 1351 UINT64 FileSize;\r
a405b86d 1352} EFI_FILE_PROTOCOL_MEM;\r
1353\r
1354/**\r
1355 File style interface for Mem (SetPosition).\r
1356 \r
1357 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
1358 @param[out] Position The position to set.\r
1359 \r
1360 @retval EFI_SUCCESS The position was successfully changed.\r
1361 @retval EFI_INVALID_PARAMETER The Position was invalid.\r
1362**/\r
1363EFI_STATUS\r
1364EFIAPI\r
1365FileInterfaceMemSetPosition(\r
1366 IN EFI_FILE_PROTOCOL *This,\r
1367 OUT UINT64 Position\r
1368 )\r
1369{\r
7bcd3ff6 1370 if (Position <= ((EFI_FILE_PROTOCOL_MEM*)This)->FileSize) {\r
a405b86d 1371 ((EFI_FILE_PROTOCOL_MEM*)This)->Position = Position;\r
1372 return (EFI_SUCCESS);\r
1373 } else {\r
1374 return (EFI_INVALID_PARAMETER);\r
1375 }\r
1376}\r
1377\r
1378/**\r
1379 File style interface for Mem (GetPosition).\r
1380 \r
1381 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
1382 @param[out] Position The pointer to the position.\r
1383 \r
1384 @retval EFI_SUCCESS The position was retrieved.\r
1385**/ \r
1386EFI_STATUS\r
1387EFIAPI\r
1388FileInterfaceMemGetPosition(\r
1389 IN EFI_FILE_PROTOCOL *This,\r
1390 OUT UINT64 *Position\r
1391 )\r
1392{\r
1393 *Position = ((EFI_FILE_PROTOCOL_MEM*)This)->Position;\r
1394 return (EFI_SUCCESS);\r
1395}\r
1396\r
1397/**\r
1398 File style interface for Mem (Write).\r
1399 \r
4ff7e37b
ED
1400 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
1401 @param[in, out] BufferSize Size in bytes of Buffer.\r
1402 @param[in] Buffer The pointer to the buffer to write.\r
a405b86d 1403 \r
ecae5117 1404 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.\r
1405 @retval EFI_SUCCESS The data was written.\r
a405b86d 1406**/\r
1407EFI_STATUS\r
1408EFIAPI\r
1409FileInterfaceMemWrite(\r
1410 IN EFI_FILE_PROTOCOL *This,\r
1411 IN OUT UINTN *BufferSize,\r
1412 IN VOID *Buffer\r
1413 )\r
1414{\r
9ed21946 1415 CHAR8 *AsciiBuffer;\r
1416 EFI_FILE_PROTOCOL_MEM *MemFile;\r
1417\r
1418 MemFile = (EFI_FILE_PROTOCOL_MEM *) This;\r
1419 if (MemFile->Unicode) {\r
a405b86d 1420 //\r
1421 // Unicode\r
1422 //\r
9ed21946 1423 if ((UINTN)(MemFile->Position + (*BufferSize)) > (UINTN)(MemFile->BufferSize)) {\r
c8d9d0e2
JD
1424 MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer);\r
1425 MemFile->BufferSize += (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD;\r
a405b86d 1426 }\r
9ed21946 1427 CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, Buffer, *BufferSize);\r
1428 MemFile->Position += (*BufferSize);\r
7bcd3ff6 1429 MemFile->FileSize = MemFile->Position;\r
a405b86d 1430 return (EFI_SUCCESS);\r
1431 } else {\r
1432 //\r
1433 // Ascii\r
1434 //\r
733f138d 1435 AsciiBuffer = AllocateZeroPool(*BufferSize);\r
ecae5117 1436 if (AsciiBuffer == NULL) {\r
1437 return (EFI_OUT_OF_RESOURCES);\r
1438 }\r
a405b86d 1439 AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer);\r
9ed21946 1440 if ((UINTN)(MemFile->Position + AsciiStrSize(AsciiBuffer)) > (UINTN)(MemFile->BufferSize)) {\r
c8d9d0e2
JD
1441 MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + AsciiStrSize(AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer);\r
1442 MemFile->BufferSize += AsciiStrSize(AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD;\r
a405b86d 1443 }\r
9ed21946 1444 CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, AsciiBuffer, AsciiStrSize(AsciiBuffer));\r
1445 MemFile->Position += (*BufferSize / sizeof(CHAR16));\r
7bcd3ff6 1446 MemFile->FileSize = MemFile->Position;\r
a405b86d 1447 FreePool(AsciiBuffer);\r
1448 return (EFI_SUCCESS);\r
1449 }\r
1450}\r
1451\r
1452/**\r
1453 File style interface for Mem (Read).\r
1454 \r
4ff7e37b
ED
1455 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
1456 @param[in, out] BufferSize Size in bytes of Buffer.\r
1457 @param[in] Buffer The pointer to the buffer to fill.\r
a405b86d 1458 \r
1459 @retval EFI_SUCCESS The data was read.\r
1460**/\r
1461EFI_STATUS\r
1462EFIAPI\r
1463FileInterfaceMemRead(\r
1464 IN EFI_FILE_PROTOCOL *This,\r
1465 IN OUT UINTN *BufferSize,\r
1466 IN VOID *Buffer\r
1467 )\r
1468{\r
9ed21946 1469 EFI_FILE_PROTOCOL_MEM *MemFile;\r
1470\r
1471 MemFile = (EFI_FILE_PROTOCOL_MEM *) This;\r
7bcd3ff6
JD
1472 if (*BufferSize > (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position))) {\r
1473 (*BufferSize) = (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position));\r
a405b86d 1474 }\r
9ed21946 1475 CopyMem(Buffer, ((UINT8*)MemFile->Buffer) + MemFile->Position, (*BufferSize));\r
1476 MemFile->Position = MemFile->Position + (*BufferSize);\r
a405b86d 1477 return (EFI_SUCCESS);\r
1478}\r
1479\r
1480/**\r
1481 File style interface for Mem (Close).\r
1482\r
1483 Frees all memory associated with this object.\r
1484 \r
1485 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
1486 \r
1487 @retval EFI_SUCCESS The 'file' was closed.\r
1488**/ \r
1489EFI_STATUS\r
1490EFIAPI\r
1491FileInterfaceMemClose(\r
1492 IN EFI_FILE_PROTOCOL *This\r
1493 )\r
1494{\r
1495 SHELL_FREE_NON_NULL(((EFI_FILE_PROTOCOL_MEM*)This)->Buffer);\r
3c865f20 1496 SHELL_FREE_NON_NULL(This);\r
a405b86d 1497 return (EFI_SUCCESS);\r
1498}\r
1499\r
1500/**\r
1501 Creates a EFI_FILE_PROTOCOL (almost) object for using to access\r
1502 a file entirely in memory through file operations.\r
1503\r
1504 @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii.\r
1505\r
1506 @retval NULL Memory could not be allocated.\r
1507 @return other A pointer to an EFI_FILE_PROTOCOL structure.\r
1508**/\r
1509EFI_FILE_PROTOCOL*\r
1510EFIAPI\r
1511CreateFileInterfaceMem(\r
1512 IN CONST BOOLEAN Unicode\r
1513 )\r
1514{\r
1515 EFI_FILE_PROTOCOL_MEM *FileInterface;\r
1516\r
1517 //\r
1518 // Get some memory\r
1519 //\r
1520 FileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_MEM));\r
1521 if (FileInterface == NULL){\r
1522 return (NULL);\r
1523 }\r
1524\r
1525 //\r
1526 // Assign the generic members\r
1527 //\r
1528 FileInterface->Revision = EFI_FILE_REVISION;\r
1529 FileInterface->Open = FileInterfaceOpenNotFound;\r
1530 FileInterface->Close = FileInterfaceMemClose;\r
1531 FileInterface->GetPosition = FileInterfaceMemGetPosition;\r
1532 FileInterface->SetPosition = FileInterfaceMemSetPosition;\r
1533 FileInterface->GetInfo = FileInterfaceNopGetInfo;\r
1534 FileInterface->SetInfo = FileInterfaceNopSetInfo;\r
1535 FileInterface->Flush = FileInterfaceNopGeneric;\r
1536 FileInterface->Delete = FileInterfaceNopGeneric;\r
1537 FileInterface->Read = FileInterfaceMemRead;\r
1538 FileInterface->Write = FileInterfaceMemWrite;\r
1539 FileInterface->Unicode = Unicode;\r
1540\r
1541 ASSERT(FileInterface->Buffer == NULL);\r
1542 ASSERT(FileInterface->BufferSize == 0);\r
1543 ASSERT(FileInterface->Position == 0);\r
1544\r
9ed21946 1545 if (Unicode) {\r
1546 FileInterface->Buffer = AllocateZeroPool(sizeof(gUnicodeFileTag));\r
9eec4d38
QS
1547 if (FileInterface->Buffer == NULL) {\r
1548 FreePool (FileInterface);\r
1549 return NULL;\r
1550 }\r
9ed21946 1551 *((CHAR16 *) (FileInterface->Buffer)) = EFI_UNICODE_BYTE_ORDER_MARK;\r
1552 FileInterface->BufferSize = 2;\r
1553 FileInterface->Position = 2;\r
1554 }\r
1555\r
a405b86d 1556 return ((EFI_FILE_PROTOCOL *)FileInterface);\r
1557}\r
1558\r
1559typedef struct {\r
1560 UINT64 Revision;\r
1561 EFI_FILE_OPEN Open;\r
1562 EFI_FILE_CLOSE Close;\r
1563 EFI_FILE_DELETE Delete;\r
1564 EFI_FILE_READ Read;\r
1565 EFI_FILE_WRITE Write;\r
1566 EFI_FILE_GET_POSITION GetPosition;\r
1567 EFI_FILE_SET_POSITION SetPosition;\r
1568 EFI_FILE_GET_INFO GetInfo;\r
1569 EFI_FILE_SET_INFO SetInfo;\r
1570 EFI_FILE_FLUSH Flush;\r
1571 BOOLEAN Unicode;\r
1572 EFI_FILE_PROTOCOL *Orig;\r
1573} EFI_FILE_PROTOCOL_FILE;\r
1574\r
733f138d 1575/**\r
1576 Set a files current position\r
1577\r
1578 @param This Protocol instance pointer.\r
1579 @param Position Byte position from the start of the file.\r
1580 \r
1581 @retval EFI_SUCCESS Data was written.\r
1582 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.\r
1583\r
1584**/\r
1585EFI_STATUS\r
1586EFIAPI\r
1587FileInterfaceFileSetPosition(\r
1588 IN EFI_FILE_PROTOCOL *This,\r
1589 IN UINT64 Position\r
1590 )\r
1591{\r
1592 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->SetPosition(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, Position);\r
1593}\r
1594\r
1595/**\r
1596 Get a file's current position\r
1597\r
1598 @param This Protocol instance pointer.\r
1599 @param Position Byte position from the start of the file.\r
1600 \r
1601 @retval EFI_SUCCESS Data was written.\r
1602 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..\r
1603\r
1604**/\r
1605EFI_STATUS\r
1606EFIAPI\r
1607FileInterfaceFileGetPosition(\r
1608 IN EFI_FILE_PROTOCOL *This,\r
1609 OUT UINT64 *Position\r
1610 )\r
1611{\r
1612 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetPosition(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, Position);\r
1613}\r
1614\r
1615/**\r
1616 Get information about a file.\r
1617\r
1618 @param This Protocol instance pointer.\r
1619 @param InformationType Type of information to return in Buffer.\r
1620 @param BufferSize On input size of buffer, on output amount of data in buffer.\r
1621 @param Buffer The buffer to return data.\r
1622\r
1623 @retval EFI_SUCCESS Data was returned.\r
1624 @retval EFI_UNSUPPORT InformationType is not supported.\r
1625 @retval EFI_NO_MEDIA The device has no media.\r
1626 @retval EFI_DEVICE_ERROR The device reported an error.\r
1627 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
1628 @retval EFI_WRITE_PROTECTED The device is write protected.\r
1629 @retval EFI_ACCESS_DENIED The file was open for read only.\r
1630 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.\r
1631\r
1632**/\r
1633EFI_STATUS\r
1634EFIAPI\r
1635FileInterfaceFileGetInfo(\r
1636 IN EFI_FILE_PROTOCOL *This,\r
1637 IN EFI_GUID *InformationType,\r
1638 IN OUT UINTN *BufferSize,\r
1639 OUT VOID *Buffer\r
1640 )\r
1641{\r
1642 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetInfo(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, InformationType, BufferSize, Buffer);\r
1643}\r
1644\r
1645/**\r
1646 Set information about a file\r
1647\r
ae724571 1648 @param This Protocol instance pointer.\r
733f138d 1649 @param InformationType Type of information in Buffer.\r
1650 @param BufferSize Size of buffer.\r
1651 @param Buffer The data to write.\r
1652\r
1653 @retval EFI_SUCCESS Data was returned.\r
1654 @retval EFI_UNSUPPORT InformationType is not supported.\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_WRITE_PROTECTED The device is write protected.\r
1659 @retval EFI_ACCESS_DENIED The file was open for read only.\r
1660\r
1661**/\r
1662EFI_STATUS\r
1663EFIAPI\r
1664FileInterfaceFileSetInfo(\r
1665 IN EFI_FILE_PROTOCOL *This,\r
1666 IN EFI_GUID *InformationType,\r
1667 IN UINTN BufferSize,\r
1668 IN VOID *Buffer\r
1669 )\r
1670{\r
1671 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->SetInfo(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, InformationType, BufferSize, Buffer);\r
1672}\r
1673\r
1674/**\r
1675 Flush data back for the file handle.\r
1676\r
1677 @param This Protocol instance pointer.\r
1678\r
1679 @retval EFI_SUCCESS Data was written.\r
1680 @retval EFI_UNSUPPORT Writes to Open directory are not supported.\r
1681 @retval EFI_NO_MEDIA The device has no media.\r
1682 @retval EFI_DEVICE_ERROR The device reported an error.\r
1683 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
1684 @retval EFI_WRITE_PROTECTED The device is write protected.\r
1685 @retval EFI_ACCESS_DENIED The file was open for read only.\r
1686 @retval EFI_VOLUME_FULL The volume is full.\r
1687\r
1688**/\r
1689EFI_STATUS\r
1690EFIAPI\r
1691FileInterfaceFileFlush(\r
1692 IN EFI_FILE_PROTOCOL *This\r
1693 )\r
1694{\r
1695 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Flush(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);\r
1696}\r
1697\r
1698/**\r
1699 Read data from the file.\r
1700\r
1701 @param This Protocol instance pointer.\r
1702 @param BufferSize On input size of buffer, on output amount of data in buffer.\r
1703 @param Buffer The buffer in which data is read.\r
1704\r
1705 @retval EFI_SUCCESS Data was read.\r
1706 @retval EFI_NO_MEDIA The device has no media.\r
1707 @retval EFI_DEVICE_ERROR The device reported an error.\r
1708 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
1709 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.\r
1710\r
1711**/\r
1712EFI_STATUS\r
1713EFIAPI\r
1714FileInterfaceFileRead(\r
1715 IN EFI_FILE_PROTOCOL *This,\r
1716 IN OUT UINTN *BufferSize,\r
1717 OUT VOID *Buffer\r
1718 )\r
1719{\r
48cb33ec
QS
1720 CHAR8 *AsciiStrBuffer;\r
1721 CHAR16 *UscStrBuffer;\r
733f138d 1722 UINTN Size;\r
48cb33ec 1723 UINTN CharNum;\r
733f138d 1724 EFI_STATUS Status;\r
1725 if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) {\r
1726 //\r
1727 // Unicode\r
1728 //\r
1729 return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer));\r
1730 } else {\r
1731 //\r
1732 // Ascii\r
1733 //\r
48cb33ec
QS
1734 Size = (*BufferSize) / sizeof(CHAR16);\r
1735 AsciiStrBuffer = AllocateZeroPool(Size + sizeof(CHAR8));\r
1736 if (AsciiStrBuffer == NULL) {\r
1737 return EFI_OUT_OF_RESOURCES;\r
1738 }\r
1739 UscStrBuffer = AllocateZeroPool(*BufferSize + sizeof(CHAR16));\r
1740 if (UscStrBuffer== NULL) {\r
1741 SHELL_FREE_NON_NULL(AsciiStrBuffer);\r
1742 return EFI_OUT_OF_RESOURCES;\r
1743 }\r
1744 Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiStrBuffer));\r
1745 if (!EFI_ERROR(Status)) {\r
1746 CharNum = UnicodeSPrint(UscStrBuffer, *BufferSize + sizeof(CHAR16), L"%a", AsciiStrBuffer);\r
1747 if (CharNum == Size) {\r
1748 CopyMem (Buffer, UscStrBuffer, *BufferSize);\r
1749 } else {\r
1750 Status = EFI_UNSUPPORTED;\r
1751 }\r
1752 }\r
1753 SHELL_FREE_NON_NULL(AsciiStrBuffer);\r
1754 SHELL_FREE_NON_NULL(UscStrBuffer);\r
733f138d 1755 return (Status);\r
1756 }\r
1757}\r
1758\r
1759/**\r
1760 Opens a new file relative to the source file's location.\r
1761\r
1762 @param[in] This The protocol instance pointer.\r
1763 @param[out] NewHandle Returns File Handle for FileName.\r
1764 @param[in] FileName Null terminated string. "\", ".", and ".." are supported.\r
1765 @param[in] OpenMode Open mode for file.\r
1766 @param[in] Attributes Only used for EFI_FILE_MODE_CREATE.\r
1767\r
1768 @retval EFI_SUCCESS The device was opened.\r
1769 @retval EFI_NOT_FOUND The specified file could not be found on the device.\r
1770 @retval EFI_NO_MEDIA The device has no media.\r
1771 @retval EFI_MEDIA_CHANGED The media has changed.\r
1772 @retval EFI_DEVICE_ERROR The device reported an error.\r
1773 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
1774 @retval EFI_ACCESS_DENIED The service denied access to the file.\r
1775 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.\r
1776 @retval EFI_VOLUME_FULL The volume is full.\r
1777**/\r
1778EFI_STATUS\r
1779EFIAPI\r
1780FileInterfaceFileOpen (\r
1781 IN EFI_FILE_PROTOCOL *This,\r
1782 OUT EFI_FILE_PROTOCOL **NewHandle,\r
1783 IN CHAR16 *FileName,\r
1784 IN UINT64 OpenMode,\r
1785 IN UINT64 Attributes\r
1786 )\r
1787{\r
1788 return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Open(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, NewHandle, FileName, OpenMode, Attributes);\r
1789}\r
1790\r
1791/**\r
1792 Close and delete the file handle.\r
1793\r
1794 @param This Protocol instance pointer.\r
1795 \r
1796 @retval EFI_SUCCESS The device was opened.\r
1797 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.\r
1798\r
1799**/\r
1800EFI_STATUS\r
1801EFIAPI\r
1802FileInterfaceFileDelete(\r
1803 IN EFI_FILE_PROTOCOL *This\r
1804 )\r
1805{\r
1806 EFI_STATUS Status;\r
1807 Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Delete(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);\r
1808 FreePool(This);\r
1809 return (Status);\r
1810}\r
1811\r
a405b86d 1812/**\r
1813 File style interface for File (Close).\r
1814 \r
1815 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
1816 \r
1817 @retval EFI_SUCCESS The file was closed.\r
1818**/\r
1819EFI_STATUS\r
1820EFIAPI\r
1821FileInterfaceFileClose(\r
1822 IN EFI_FILE_PROTOCOL *This\r
1823 )\r
1824{\r
733f138d 1825 EFI_STATUS Status;\r
1826 Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Close(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);\r
a405b86d 1827 FreePool(This);\r
733f138d 1828 return (Status);\r
a405b86d 1829}\r
1830\r
1831/**\r
1832 File style interface for File (Write).\r
1833\r
1834 If the file was opened with ASCII mode the data will be processed through \r
1835 AsciiSPrint before writing.\r
1836 \r
4ff7e37b
ED
1837 @param[in] This The pointer to the EFI_FILE_PROTOCOL object.\r
1838 @param[in, out] BufferSize Size in bytes of Buffer.\r
1839 @param[in] Buffer The pointer to the buffer to write.\r
a405b86d 1840 \r
1841 @retval EFI_SUCCESS The data was written.\r
1842**/\r
1843EFI_STATUS\r
1844EFIAPI\r
1845FileInterfaceFileWrite(\r
733f138d 1846 IN EFI_FILE_PROTOCOL *This,\r
1847 IN OUT UINTN *BufferSize,\r
1848 IN VOID *Buffer\r
a405b86d 1849 )\r
1850{\r
1851 CHAR8 *AsciiBuffer;\r
1852 UINTN Size;\r
1853 EFI_STATUS Status;\r
1854 if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) {\r
1855 //\r
1856 // Unicode\r
1857 //\r
1858 return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer));\r
1859 } else {\r
1860 //\r
1861 // Ascii\r
1862 //\r
733f138d 1863 AsciiBuffer = AllocateZeroPool(*BufferSize);\r
a405b86d 1864 AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer);\r
1865 Size = AsciiStrSize(AsciiBuffer) - 1; // (we dont need the null terminator)\r
1866 Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiBuffer));\r
1867 FreePool(AsciiBuffer);\r
1868 return (Status);\r
1869 }\r
1870}\r
1871\r
1872/**\r
1873 Create a file interface with unicode information.\r
1874\r
1875 This will create a new EFI_FILE_PROTOCOL identical to the Templace\r
1876 except that the new one has Unicode and Ascii knowledge.\r
1877 \r
1878 @param[in] Template A pointer to the EFI_FILE_PROTOCOL object.\r
1879 @param[in] Unicode TRUE for UCS-2, FALSE for ASCII.\r
1880 \r
1881 @return a new EFI_FILE_PROTOCOL object to be used instead of the template.\r
1882**/\r
1883EFI_FILE_PROTOCOL*\r
1884CreateFileInterfaceFile(\r
1885 IN CONST EFI_FILE_PROTOCOL *Template,\r
1886 IN CONST BOOLEAN Unicode\r
1887 )\r
1888{\r
1889 EFI_FILE_PROTOCOL_FILE *NewOne;\r
1890\r
733f138d 1891 NewOne = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_FILE));\r
3c865f20 1892 if (NewOne == NULL) {\r
1893 return (NULL);\r
1894 }\r
a405b86d 1895 CopyMem(NewOne, Template, sizeof(EFI_FILE_PROTOCOL_FILE));\r
733f138d 1896 NewOne->Orig = (EFI_FILE_PROTOCOL *)Template;\r
1897 NewOne->Unicode = Unicode;\r
1898 NewOne->Open = FileInterfaceFileOpen;\r
1899 NewOne->Close = FileInterfaceFileClose;\r
1900 NewOne->Delete = FileInterfaceFileDelete;\r
1901 NewOne->Read = FileInterfaceFileRead;\r
1902 NewOne->Write = FileInterfaceFileWrite;\r
1903 NewOne->GetPosition = FileInterfaceFileGetPosition;\r
1904 NewOne->SetPosition = FileInterfaceFileSetPosition;\r
1905 NewOne->GetInfo = FileInterfaceFileGetInfo;\r
1906 NewOne->SetInfo = FileInterfaceFileSetInfo;\r
1907 NewOne->Flush = FileInterfaceFileFlush;\r
a405b86d 1908\r
1909 return ((EFI_FILE_PROTOCOL *)NewOne);\r
1910}\r