TianoCore EDK2 master
Loading...
Searching...
No Matches
SemihostFs.c
Go to the documentation of this file.
1
11#include <Uefi.h>
12
13#include <Guid/FileInfo.h>
14#include <Guid/FileSystemInfo.h>
16
17#include <Library/BaseLib.h>
19#include <Library/DebugLib.h>
21#include <Library/SemihostLib.h>
23#include <Library/UefiLib.h>
24
25#include <Protocol/DevicePath.h>
27
28#include "SemihostFs.h"
29
30#define DEFAULT_SEMIHOST_FS_LABEL L"SemihostFs"
31
32STATIC CHAR16 *mSemihostFsLabel;
33
35 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
36 VolumeOpen
37};
38
39EFI_FILE gSemihostFsFile = {
40 EFI_FILE_PROTOCOL_REVISION,
50 FileFlush
51};
52
53//
54// Device path for semi-hosting. It contains our auto-generated Caller ID GUID.
55//
56typedef struct {
60
61SEMIHOST_DEVICE_PATH gDevicePath = {
62 {
64 },
65 EFI_CALLER_ID_GUID
66 },
67 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
68 }
69};
70
71typedef struct {
72 LIST_ENTRY Link;
73 UINT64 Signature;
74 EFI_FILE File;
75 CHAR8 *FileName;
76 UINT64 OpenMode;
77 UINT32 Position;
78 UINTN SemihostHandle;
79 BOOLEAN IsRoot;
80 EFI_FILE_INFO Info;
82
83#define SEMIHOST_FCB_SIGNATURE SIGNATURE_32( 'S', 'H', 'F', 'C' )
84#define SEMIHOST_FCB_FROM_THIS(a) CR(a, SEMIHOST_FCB, File, SEMIHOST_FCB_SIGNATURE)
85#define SEMIHOST_FCB_FROM_LINK(a) CR(a, SEMIHOST_FCB, Link, SEMIHOST_FCB_SIGNATURE);
86
87EFI_HANDLE gInstallHandle = NULL;
88LIST_ENTRY gFileList = INITIALIZE_LIST_HEAD_VARIABLE (gFileList);
89
91AllocateFCB (
92 VOID
93 )
94{
95 SEMIHOST_FCB *Fcb;
96
97 Fcb = AllocateZeroPool (sizeof (SEMIHOST_FCB));
98 if (Fcb != NULL) {
99 CopyMem (&Fcb->File, &gSemihostFsFile, sizeof (gSemihostFsFile));
100 Fcb->Signature = SEMIHOST_FCB_SIGNATURE;
101 }
102
103 return Fcb;
104}
105
106VOID
107FreeFCB (
108 IN SEMIHOST_FCB *Fcb
109 )
110{
111 // Remove Fcb from gFileList.
112 RemoveEntryList (&Fcb->Link);
113
114 // To help debugging...
115 Fcb->Signature = 0;
116
117 FreePool (Fcb);
118}
119
121VolumeOpen (
123 OUT EFI_FILE **Root
124 )
125{
126 SEMIHOST_FCB *RootFcb;
127
128 if (Root == NULL) {
129 return EFI_INVALID_PARAMETER;
130 }
131
132 RootFcb = AllocateFCB ();
133 if (RootFcb == NULL) {
134 return EFI_OUT_OF_RESOURCES;
135 }
136
137 RootFcb->IsRoot = TRUE;
138 RootFcb->Info.Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
139
140 InsertTailList (&gFileList, &RootFcb->Link);
141
142 *Root = &RootFcb->File;
143
144 return EFI_SUCCESS;
145}
146
175 IN EFI_FILE *This,
176 OUT EFI_FILE **NewHandle,
177 IN CHAR16 *FileName,
178 IN UINT64 OpenMode,
179 IN UINT64 Attributes
180 )
181{
182 SEMIHOST_FCB *FileFcb;
183 RETURN_STATUS Return;
184 EFI_STATUS Status;
185 UINTN SemihostHandle;
186 CHAR8 *AsciiFileName;
187 UINT32 SemihostMode;
188 UINTN Length;
189
190 if ((FileName == NULL) || (NewHandle == NULL)) {
191 return EFI_INVALID_PARAMETER;
192 }
193
194 if ((OpenMode != EFI_FILE_MODE_READ) &&
195 (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE)) &&
196 (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE)))
197 {
198 return EFI_INVALID_PARAMETER;
199 }
200
201 if (((OpenMode & EFI_FILE_MODE_CREATE) != 0) &&
202 ((Attributes & EFI_FILE_DIRECTORY) != 0))
203 {
204 return EFI_WRITE_PROTECTED;
205 }
206
207 Length = StrLen (FileName) + 1;
208 AsciiFileName = AllocatePool (Length);
209 if (AsciiFileName == NULL) {
210 return EFI_OUT_OF_RESOURCES;
211 }
212
213 UnicodeStrToAsciiStrS (FileName, AsciiFileName, Length);
214
215 // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory
216 if ((AsciiStrCmp (AsciiFileName, "\\") == 0) ||
217 (AsciiStrCmp (AsciiFileName, "/") == 0) ||
218 (AsciiStrCmp (AsciiFileName, "") == 0) ||
219 (AsciiStrCmp (AsciiFileName, ".") == 0))
220 {
221 FreePool (AsciiFileName);
222 return (VolumeOpen (&gSemihostFs, NewHandle));
223 }
224
225 //
226 // No control is done here concerning the file path. It is passed
227 // as it is to the host operating system through the semi-hosting
228 // interface. We first try to open the file in the read or update
229 // mode even if the file creation has been asked for. That way, if
230 // the file already exists, it is not truncated to zero length. In
231 // write mode (bit SEMIHOST_FILE_MODE_WRITE up), if the file already
232 // exists, it is reset to an empty file.
233 //
234 if (OpenMode == EFI_FILE_MODE_READ) {
235 SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY;
236 } else {
237 SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY | SEMIHOST_FILE_MODE_UPDATE;
238 }
239
240 Return = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle);
241
242 if (RETURN_ERROR (Return)) {
243 if ((OpenMode & EFI_FILE_MODE_CREATE) != 0) {
244 //
245 // In the create if does not exist case, if the opening in update
246 // mode failed, create it and open it in update mode. The update
247 // mode allows for both read and write from and to the file.
248 //
249 Return = SemihostFileOpen (
250 AsciiFileName,
251 SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY | SEMIHOST_FILE_MODE_UPDATE,
252 &SemihostHandle
253 );
254 if (RETURN_ERROR (Return)) {
255 Status = EFI_DEVICE_ERROR;
256 goto Error;
257 }
258 } else {
259 Status = EFI_NOT_FOUND;
260 goto Error;
261 }
262 }
263
264 // Allocate a control block and fill it
265 FileFcb = AllocateFCB ();
266 if (FileFcb == NULL) {
267 Status = EFI_OUT_OF_RESOURCES;
268 goto Error;
269 }
270
271 FileFcb->FileName = AsciiFileName;
272 FileFcb->SemihostHandle = SemihostHandle;
273 FileFcb->Position = 0;
274 FileFcb->IsRoot = 0;
275 FileFcb->OpenMode = OpenMode;
276
277 Return = SemihostFileLength (SemihostHandle, &Length);
278 if (RETURN_ERROR (Return)) {
279 Status = EFI_DEVICE_ERROR;
280 FreeFCB (FileFcb);
281 goto Error;
282 }
283
284 FileFcb->Info.FileSize = Length;
285 FileFcb->Info.PhysicalSize = Length;
286 FileFcb->Info.Attribute = ((OpenMode & EFI_FILE_MODE_CREATE) != 0) ?
287 Attributes : 0;
288
289 InsertTailList (&gFileList, &FileFcb->Link);
290
291 *NewHandle = &FileFcb->File;
292
293 return EFI_SUCCESS;
294
295Error:
296
297 FreePool (AsciiFileName);
298
299 return Status;
300}
301
312STATIC
315 IN CHAR8 *FileName,
316 IN UINTN Size
317 )
318{
319 EFI_STATUS Status;
320 RETURN_STATUS Return;
321 UINTN FileHandle;
322 UINT8 *Buffer;
323 UINTN Remaining;
324 UINTN Read;
325 UINTN ToRead;
326
327 Status = EFI_DEVICE_ERROR;
328 FileHandle = 0;
329 Buffer = NULL;
330
331 Return = SemihostFileOpen (
332 FileName,
333 SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY,
334 &FileHandle
335 );
336 if (RETURN_ERROR (Return)) {
337 goto Error;
338 }
339
340 Buffer = AllocatePool (Size);
341 if (Buffer == NULL) {
342 Status = EFI_OUT_OF_RESOURCES;
343 goto Error;
344 }
345
346 Read = 0;
347 Remaining = Size;
348 while (Remaining > 0) {
349 ToRead = Remaining;
350 Return = SemihostFileRead (FileHandle, &ToRead, Buffer + Read);
351 if (RETURN_ERROR (Return)) {
352 goto Error;
353 }
354
355 Remaining -= ToRead;
356 Read += ToRead;
357 }
358
359 Return = SemihostFileClose (FileHandle);
360 FileHandle = 0;
361 if (RETURN_ERROR (Return)) {
362 goto Error;
363 }
364
365 Return = SemihostFileOpen (
366 FileName,
367 SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY,
368 &FileHandle
369 );
370 if (RETURN_ERROR (Return)) {
371 goto Error;
372 }
373
374 if (Size > 0) {
375 Return = SemihostFileWrite (FileHandle, &Size, Buffer);
376 if (RETURN_ERROR (Return)) {
377 goto Error;
378 }
379 }
380
381 Status = EFI_SUCCESS;
382
383Error:
384
385 if (FileHandle != 0) {
386 SemihostFileClose (FileHandle);
387 }
388
389 if (Buffer != NULL) {
390 FreePool (Buffer);
391 }
392
393 return (Status);
394}
395
408 IN EFI_FILE *This
409 )
410{
411 SEMIHOST_FCB *Fcb;
412
413 if (This == NULL) {
414 return EFI_INVALID_PARAMETER;
415 }
416
417 Fcb = SEMIHOST_FCB_FROM_THIS (This);
418
419 if (!Fcb->IsRoot) {
420 SemihostFileClose (Fcb->SemihostHandle);
421 //
422 // The file size might have been reduced from its actual
423 // size on the host file system with FileSetInfo(). In
424 // that case, the file has to be truncated.
425 //
426 if (Fcb->Info.FileSize < Fcb->Info.PhysicalSize) {
427 TruncateFile (Fcb->FileName, Fcb->Info.FileSize);
428 }
429
430 FreePool (Fcb->FileName);
431 }
432
433 FreeFCB (Fcb);
434
435 return EFI_SUCCESS;
436}
437
451 IN EFI_FILE *This
452 )
453{
454 SEMIHOST_FCB *Fcb;
455 RETURN_STATUS Return;
456 CHAR8 *FileName;
457 UINTN NameSize;
458
459 if (This == NULL) {
460 return EFI_INVALID_PARAMETER;
461 }
462
463 Fcb = SEMIHOST_FCB_FROM_THIS (This);
464
465 if (!Fcb->IsRoot) {
466 // Get the filename from the Fcb
467 NameSize = AsciiStrLen (Fcb->FileName);
468 FileName = AllocatePool (NameSize + 1);
469
470 AsciiStrCpyS (FileName, NameSize + 1, Fcb->FileName);
471
472 // Close the file if it's open. Disregard return status,
473 // since it might give an error if the file isn't open.
474 This->Close (This);
475
476 // Call the semihost interface to delete the file.
477 Return = SemihostFileRemove (FileName);
478 if (RETURN_ERROR (Return)) {
479 return EFI_WARN_DELETE_FAILURE;
480 }
481
482 return EFI_SUCCESS;
483 } else {
484 return EFI_WARN_DELETE_FAILURE;
485 }
486}
487
508 IN EFI_FILE *This,
509 IN OUT UINTN *BufferSize,
510 OUT VOID *Buffer
511 )
512{
513 SEMIHOST_FCB *Fcb;
514 EFI_STATUS Status;
515 RETURN_STATUS Return;
516
517 if ((This == NULL) || (BufferSize == NULL) || (Buffer == NULL)) {
518 return EFI_INVALID_PARAMETER;
519 }
520
521 Fcb = SEMIHOST_FCB_FROM_THIS (This);
522
523 if (Fcb->IsRoot) {
524 // The semi-hosting interface does not allow to list files on the host machine.
525 Status = EFI_UNSUPPORTED;
526 } else {
527 Status = EFI_SUCCESS;
528 if (Fcb->Position >= Fcb->Info.FileSize) {
529 *BufferSize = 0;
530 if (Fcb->Position > Fcb->Info.FileSize) {
531 Status = EFI_DEVICE_ERROR;
532 }
533 } else {
534 Return = SemihostFileRead (Fcb->SemihostHandle, BufferSize, Buffer);
535 if (RETURN_ERROR (Return)) {
536 Status = EFI_DEVICE_ERROR;
537 } else {
538 Fcb->Position += *BufferSize;
539 }
540 }
541 }
542
543 return Status;
544}
545
558STATIC
561 IN SEMIHOST_FCB *Fcb,
562 IN UINTN Size
563 )
564{
565 RETURN_STATUS Return;
566 UINTN Remaining;
567 CHAR8 WriteBuffer[128];
568 UINTN WriteNb;
569 UINTN WriteSize;
570
571 Return = SemihostFileSeek (Fcb->SemihostHandle, Fcb->Info.FileSize);
572 if (RETURN_ERROR (Return)) {
573 return EFI_DEVICE_ERROR;
574 }
575
576 Remaining = Size;
577 ZeroMem (WriteBuffer, sizeof (WriteBuffer));
578 while (Remaining > 0) {
579 WriteNb = MIN (Remaining, sizeof (WriteBuffer));
580 WriteSize = WriteNb;
581 Return = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, WriteBuffer);
582 if (RETURN_ERROR (Return)) {
583 return EFI_DEVICE_ERROR;
584 }
585
586 Remaining -= WriteNb;
587 }
588
589 return EFI_SUCCESS;
590}
591
611 IN EFI_FILE *This,
612 IN OUT UINTN *BufferSize,
613 IN VOID *Buffer
614 )
615{
616 SEMIHOST_FCB *Fcb;
617 EFI_STATUS Status;
618 UINTN WriteSize;
619 RETURN_STATUS Return;
620 UINTN Length;
621
622 if ((This == NULL) || (BufferSize == NULL) || (Buffer == NULL)) {
623 return EFI_INVALID_PARAMETER;
624 }
625
626 Fcb = SEMIHOST_FCB_FROM_THIS (This);
627
628 // We cannot write a read-only file
629 if ( (Fcb->Info.Attribute & EFI_FILE_READ_ONLY)
630 || !(Fcb->OpenMode & EFI_FILE_MODE_WRITE))
631 {
632 return EFI_ACCESS_DENIED;
633 }
634
635 //
636 // If the position has been set past the end of the file, first grow the
637 // file from its current size "Fcb->Info.FileSize" to "Fcb->Position"
638 // size, filling the gap with zeros.
639 //
640 if (Fcb->Position > Fcb->Info.FileSize) {
641 Status = ExtendFile (Fcb, Fcb->Position - Fcb->Info.FileSize);
642 if (EFI_ERROR (Status)) {
643 return Status;
644 }
645
646 Fcb->Info.FileSize = Fcb->Position;
647 }
648
649 WriteSize = *BufferSize;
650 Return = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);
651 if (RETURN_ERROR (Return)) {
652 return EFI_DEVICE_ERROR;
653 }
654
655 Fcb->Position += *BufferSize;
656 if (Fcb->Position > Fcb->Info.FileSize) {
657 Fcb->Info.FileSize = Fcb->Position;
658 }
659
660 Return = SemihostFileLength (Fcb->SemihostHandle, &Length);
661 if (RETURN_ERROR (Return)) {
662 return EFI_DEVICE_ERROR;
663 }
664
665 Fcb->Info.PhysicalSize = Length;
666
667 return EFI_SUCCESS;
668}
669
683 IN EFI_FILE *This,
684 OUT UINT64 *Position
685 )
686{
687 SEMIHOST_FCB *Fcb;
688
689 if ((This == NULL) || (Position == NULL)) {
690 return EFI_INVALID_PARAMETER;
691 }
692
693 Fcb = SEMIHOST_FCB_FROM_THIS (This);
694
695 *Position = Fcb->Position;
696
697 return EFI_SUCCESS;
698}
699
716 IN EFI_FILE *This,
717 IN UINT64 Position
718 )
719{
720 SEMIHOST_FCB *Fcb;
721 RETURN_STATUS Return;
722
723 if (This == NULL) {
724 return EFI_INVALID_PARAMETER;
725 }
726
727 Fcb = SEMIHOST_FCB_FROM_THIS (This);
728
729 if (Fcb->IsRoot) {
730 if (Position != 0) {
731 return EFI_UNSUPPORTED;
732 }
733 } else {
734 //
735 // UEFI Spec section 12.5:
736 // "Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to
737 // be set to the end of the file."
738 //
739 if (Position == 0xFFFFFFFFFFFFFFFF) {
740 Position = Fcb->Info.FileSize;
741 }
742
743 Return = SemihostFileSeek (Fcb->SemihostHandle, MIN (Position, Fcb->Info.FileSize));
744 if (RETURN_ERROR (Return)) {
745 return EFI_DEVICE_ERROR;
746 }
747 }
748
749 Fcb->Position = Position;
750
751 return EFI_SUCCESS;
752}
753
767STATIC
770 IN SEMIHOST_FCB *Fcb,
771 IN OUT UINTN *BufferSize,
772 OUT VOID *Buffer
773 )
774{
775 EFI_FILE_INFO *Info;
776 UINTN NameSize;
777 UINTN ResultSize;
778 UINTN Index;
779
780 if (Fcb->IsRoot) {
781 NameSize = 0;
782 ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof (CHAR16);
783 } else {
784 NameSize = AsciiStrLen (Fcb->FileName) + 1;
785 ResultSize = SIZE_OF_EFI_FILE_INFO + NameSize * sizeof (CHAR16);
786 }
787
788 if (*BufferSize < ResultSize) {
789 *BufferSize = ResultSize;
790 return EFI_BUFFER_TOO_SMALL;
791 }
792
793 Info = Buffer;
794
795 // Copy the current file info
796 CopyMem (Info, &Fcb->Info, SIZE_OF_EFI_FILE_INFO);
797
798 // Fill in the structure
799 Info->Size = ResultSize;
800
801 if (Fcb->IsRoot) {
802 Info->FileName[0] = L'\0';
803 } else {
804 for (Index = 0; Index < NameSize; Index++) {
805 Info->FileName[Index] = Fcb->FileName[Index];
806 }
807 }
808
809 *BufferSize = ResultSize;
810
811 return EFI_SUCCESS;
812}
813
830STATIC
833 IN SEMIHOST_FCB *Fcb,
834 IN OUT UINTN *BufferSize,
835 OUT VOID *Buffer
836 )
837{
839 EFI_STATUS Status;
840 UINTN ResultSize;
841 UINTN StringSize;
842
843 StringSize = StrSize (mSemihostFsLabel);
844 ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StringSize;
845
846 if (*BufferSize >= ResultSize) {
847 ZeroMem (Buffer, ResultSize);
848 Status = EFI_SUCCESS;
849
850 Info = Buffer;
851
852 Info->Size = ResultSize;
853 Info->ReadOnly = FALSE;
854 Info->VolumeSize = 0;
855 Info->FreeSpace = 0;
856 Info->BlockSize = 0;
857
858 CopyMem (Info->VolumeLabel, mSemihostFsLabel, StringSize);
859 } else {
860 Status = EFI_BUFFER_TOO_SMALL;
861 }
862
863 *BufferSize = ResultSize;
864 return Status;
865}
866
891 IN EFI_FILE *This,
892 IN EFI_GUID *InformationType,
893 IN OUT UINTN *BufferSize,
894 OUT VOID *Buffer
895 )
896{
897 SEMIHOST_FCB *Fcb;
898 EFI_STATUS Status;
899 UINTN ResultSize;
900
901 if ((This == NULL) ||
902 (InformationType == NULL) ||
903 (BufferSize == NULL) ||
904 ((Buffer == NULL) && (*BufferSize > 0)))
905 {
906 return EFI_INVALID_PARAMETER;
907 }
908
909 Fcb = SEMIHOST_FCB_FROM_THIS (This);
910
911 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
912 Status = GetFilesystemInfo (Fcb, BufferSize, Buffer);
913 } else if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
914 Status = GetFileInfo (Fcb, BufferSize, Buffer);
915 } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
916 ResultSize = StrSize (mSemihostFsLabel);
917
918 if (*BufferSize >= ResultSize) {
919 CopyMem (Buffer, mSemihostFsLabel, ResultSize);
920 Status = EFI_SUCCESS;
921 } else {
922 Status = EFI_BUFFER_TOO_SMALL;
923 }
924
925 *BufferSize = ResultSize;
926 } else {
927 Status = EFI_UNSUPPORTED;
928 }
929
930 return Status;
931}
932
954STATIC
957 IN SEMIHOST_FCB *Fcb,
958 IN EFI_FILE_INFO *Info
959 )
960{
961 EFI_STATUS Status;
962 RETURN_STATUS Return;
963 BOOLEAN FileSizeIsDifferent;
964 BOOLEAN FileNameIsDifferent;
965 BOOLEAN ReadOnlyIsDifferent;
966 CHAR8 *AsciiFileName;
967 UINTN FileSize;
968 UINTN Length;
969 UINTN SemihostHandle;
970
971 //
972 // A directory can not be changed to a file and a file can
973 // not be changed to a directory.
974 //
975 if (((Info->Attribute & EFI_FILE_DIRECTORY) != 0) != Fcb->IsRoot) {
976 return EFI_ACCESS_DENIED;
977 }
978
979 Length = StrLen (Info->FileName) + 1;
980 AsciiFileName = AllocatePool (Length);
981 if (AsciiFileName == NULL) {
982 return EFI_OUT_OF_RESOURCES;
983 }
984
985 UnicodeStrToAsciiStrS (Info->FileName, AsciiFileName, Length);
986
987 FileSizeIsDifferent = (Info->FileSize != Fcb->Info.FileSize);
988 FileNameIsDifferent = (AsciiStrCmp (AsciiFileName, Fcb->FileName) != 0);
989 ReadOnlyIsDifferent = CompareMem (
990 &Info->CreateTime,
991 &Fcb->Info.CreateTime,
992 3 * sizeof (EFI_TIME)
993 ) != 0;
994
995 //
996 // For a read-only file or a file opened in read-only mode, only
997 // the Attribute field can be modified. As the root directory is
998 // read-only (i.e. VolumeOpen()), this protects the root directory
999 // description.
1000 //
1001 if ((Fcb->OpenMode == EFI_FILE_MODE_READ) ||
1002 (Fcb->Info.Attribute & EFI_FILE_READ_ONLY))
1003 {
1004 if (FileSizeIsDifferent || FileNameIsDifferent || ReadOnlyIsDifferent) {
1005 Status = EFI_ACCESS_DENIED;
1006 goto Error;
1007 }
1008 }
1009
1010 if (ReadOnlyIsDifferent) {
1011 Status = EFI_WRITE_PROTECTED;
1012 goto Error;
1013 }
1014
1015 Status = EFI_DEVICE_ERROR;
1016
1017 if (FileSizeIsDifferent) {
1018 FileSize = Info->FileSize;
1019 if (Fcb->Info.FileSize < FileSize) {
1020 Status = ExtendFile (Fcb, FileSize - Fcb->Info.FileSize);
1021 if (EFI_ERROR (Status)) {
1022 goto Error;
1023 }
1024
1025 //
1026 // The read/write position from the host file system point of view
1027 // is at the end of the file. If the position from this module
1028 // point of view is smaller than the new file size, then
1029 // ask the host file system to move to that position.
1030 //
1031 if (Fcb->Position < FileSize) {
1032 FileSetPosition (&Fcb->File, Fcb->Position);
1033 }
1034 }
1035
1036 Fcb->Info.FileSize = FileSize;
1037
1038 Return = SemihostFileLength (Fcb->SemihostHandle, &Length);
1039 if (RETURN_ERROR (Return)) {
1040 goto Error;
1041 }
1042
1043 Fcb->Info.PhysicalSize = Length;
1044 }
1045
1046 //
1047 // Note down in RAM the Attribute field but we can not ask
1048 // for its modification to the host file system as the
1049 // semi-host interface does not provide this feature.
1050 //
1051 Fcb->Info.Attribute = Info->Attribute;
1052
1053 if (FileNameIsDifferent) {
1054 Return = SemihostFileOpen (
1055 AsciiFileName,
1056 SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY,
1057 &SemihostHandle
1058 );
1059 if (!RETURN_ERROR (Return)) {
1060 SemihostFileClose (SemihostHandle);
1061 Status = EFI_ACCESS_DENIED;
1062 goto Error;
1063 }
1064
1065 Return = SemihostFileRename (Fcb->FileName, AsciiFileName);
1066 if (RETURN_ERROR (Return)) {
1067 goto Error;
1068 }
1069
1070 FreePool (Fcb->FileName);
1071 Fcb->FileName = AsciiFileName;
1072 AsciiFileName = NULL;
1073 }
1074
1075 Status = EFI_SUCCESS;
1076
1077Error:
1078 if (AsciiFileName != NULL) {
1079 FreePool (AsciiFileName);
1080 }
1081
1082 return Status;
1083}
1084
1119 IN EFI_FILE *This,
1120 IN EFI_GUID *InformationType,
1121 IN UINTN BufferSize,
1122 IN VOID *Buffer
1123 )
1124{
1125 SEMIHOST_FCB *Fcb;
1126 EFI_FILE_INFO *Info;
1127 EFI_FILE_SYSTEM_INFO *SystemInfo;
1128 CHAR16 *VolumeLabel;
1129
1130 if ((This == NULL) || (InformationType == NULL) || (Buffer == NULL)) {
1131 return EFI_INVALID_PARAMETER;
1132 }
1133
1134 Fcb = SEMIHOST_FCB_FROM_THIS (This);
1135
1136 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
1137 Info = Buffer;
1138 if (Info->Size < (SIZE_OF_EFI_FILE_INFO + StrSize (Info->FileName))) {
1139 return EFI_INVALID_PARAMETER;
1140 }
1141
1142 if (BufferSize < Info->Size) {
1143 return EFI_BAD_BUFFER_SIZE;
1144 }
1145
1146 return SetFileInfo (Fcb, Info);
1147 } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
1148 SystemInfo = Buffer;
1149 if (SystemInfo->Size <
1151 {
1152 return EFI_INVALID_PARAMETER;
1153 }
1154
1155 if (BufferSize < SystemInfo->Size) {
1156 return EFI_BAD_BUFFER_SIZE;
1157 }
1158
1159 Buffer = SystemInfo->VolumeLabel;
1160
1161 if (StrSize (Buffer) > 0) {
1162 VolumeLabel = AllocateCopyPool (StrSize (Buffer), Buffer);
1163 if (VolumeLabel != NULL) {
1164 FreePool (mSemihostFsLabel);
1165 mSemihostFsLabel = VolumeLabel;
1166 return EFI_SUCCESS;
1167 } else {
1168 return EFI_OUT_OF_RESOURCES;
1169 }
1170 } else {
1171 return EFI_INVALID_PARAMETER;
1172 }
1173 } else if (!CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
1174 return EFI_UNSUPPORTED;
1175 } else {
1176 return EFI_UNSUPPORTED;
1177 }
1178}
1179
1181FileFlush (
1182 IN EFI_FILE *File
1183 )
1184{
1185 SEMIHOST_FCB *Fcb;
1186
1187 Fcb = SEMIHOST_FCB_FROM_THIS (File);
1188
1189 if (Fcb->IsRoot) {
1190 return EFI_SUCCESS;
1191 } else {
1192 if ( (Fcb->Info.Attribute & EFI_FILE_READ_ONLY)
1193 || !(Fcb->OpenMode & EFI_FILE_MODE_WRITE))
1194 {
1195 return EFI_ACCESS_DENIED;
1196 } else {
1197 return EFI_SUCCESS;
1198 }
1199 }
1200}
1201
1203SemihostFsEntryPoint (
1204 IN EFI_HANDLE ImageHandle,
1205 IN EFI_SYSTEM_TABLE *SystemTable
1206 )
1207{
1208 EFI_STATUS Status;
1209
1210 Status = EFI_NOT_FOUND;
1211
1212 if (SemihostConnectionSupported ()) {
1213 mSemihostFsLabel = AllocateCopyPool (StrSize (DEFAULT_SEMIHOST_FS_LABEL), DEFAULT_SEMIHOST_FS_LABEL);
1214 if (mSemihostFsLabel == NULL) {
1215 return EFI_OUT_OF_RESOURCES;
1216 }
1217
1218 Status = gBS->InstallMultipleProtocolInterfaces (
1219 &gInstallHandle,
1220 &gEfiSimpleFileSystemProtocolGuid,
1221 &gSemihostFs,
1222 &gEfiDevicePathProtocolGuid,
1223 &gDevicePath,
1224 NULL
1225 );
1226
1227 if (EFI_ERROR (Status)) {
1228 FreePool (mSemihostFsLabel);
1229 }
1230 }
1231
1232 return Status;
1233}
UINT64 UINTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
INTN EFIAPI AsciiStrCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
Definition: String.c:716
RETURN_STATUS EFIAPI UnicodeStrToAsciiStrS(IN CONST CHAR16 *Source, OUT CHAR8 *Destination, IN UINTN DestMax)
Definition: SafeString.c:2650
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead)
Definition: BaseLib.h:2904
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
RETURN_STATUS EFIAPI AsciiStrCpyS(OUT CHAR8 *Destination, IN UINTN DestMax, IN CONST CHAR8 *Source)
Definition: SafeString.c:1797
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define HARDWARE_DEVICE_PATH
Definition: DevicePath.h:68
#define HW_VENDOR_DP
Definition: DevicePath.h:133
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define SIZE_OF_EFI_FILE_INFO
Definition: FileInfo.h:62
#define SIZE_OF_EFI_FILE_SYSTEM_INFO
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define MIN(a, b)
Definition: Base.h:1007
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
EFI_STATUS FileOpen(IN EFI_FILE *This, OUT EFI_FILE **NewHandle, IN CHAR16 *FileName, IN UINT64 OpenMode, IN UINT64 Attributes)
Definition: SemihostFs.c:174
STATIC EFI_STATUS GetFileInfo(IN SEMIHOST_FCB *Fcb, IN OUT UINTN *BufferSize, OUT VOID *Buffer)
Definition: SemihostFs.c:769
EFI_STATUS FileClose(IN EFI_FILE *This)
Definition: SemihostFs.c:407
EFI_STATUS FileSetInfo(IN EFI_FILE *This, IN EFI_GUID *InformationType, IN UINTN BufferSize, IN VOID *Buffer)
Definition: SemihostFs.c:1118
EFI_STATUS FileDelete(IN EFI_FILE *This)
Definition: SemihostFs.c:450
STATIC EFI_STATUS ExtendFile(IN SEMIHOST_FCB *Fcb, IN UINTN Size)
Definition: SemihostFs.c:560
EFI_STATUS FileRead(IN EFI_FILE *This, IN OUT UINTN *BufferSize, OUT VOID *Buffer)
Definition: SemihostFs.c:507
EFI_STATUS FileSetPosition(IN EFI_FILE *This, IN UINT64 Position)
Definition: SemihostFs.c:715
STATIC EFI_STATUS GetFilesystemInfo(IN SEMIHOST_FCB *Fcb, IN OUT UINTN *BufferSize, OUT VOID *Buffer)
Definition: SemihostFs.c:832
STATIC EFI_STATUS SetFileInfo(IN SEMIHOST_FCB *Fcb, IN EFI_FILE_INFO *Info)
Definition: SemihostFs.c:956
EFI_STATUS FileGetInfo(IN EFI_FILE *This, IN EFI_GUID *InformationType, IN OUT UINTN *BufferSize, OUT VOID *Buffer)
Definition: SemihostFs.c:890
EFI_STATUS FileWrite(IN EFI_FILE *This, IN OUT UINTN *BufferSize, IN VOID *Buffer)
Definition: SemihostFs.c:610
EFI_STATUS FileGetPosition(IN EFI_FILE *This, OUT UINT64 *Position)
Definition: SemihostFs.c:682
STATIC EFI_STATUS TruncateFile(IN CHAR8 *FileName, IN UINTN Size)
Definition: SemihostFs.c:314
RETURN_STATUS SemihostFileRename(IN CHAR8 *FileName, IN CHAR8 *NewFileName)
Definition: SemihostLib.c:245
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
UINT64 PhysicalSize
Definition: FileInfo.h:31
UINT64 Size
Definition: FileInfo.h:23
UINT64 Attribute
Definition: FileInfo.h:47
CHAR16 FileName[1]
Definition: FileInfo.h:52
UINT64 FileSize
Definition: FileInfo.h:27
Definition: Base.h:213