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