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