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