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