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