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