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