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