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