2 Handle operations in files and directories from UDF/ECMA-167 file systems.
4 Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
5 Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials are licensed and made available
8 under the terms and conditions of the BSD License which accompanies this
9 distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
13 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 EFI_FILE_PROTOCOL gUdfFileIoOps
= {
19 EFI_FILE_PROTOCOL_REVISION
,
36 #define _ROOT_FILE(_PrivData) (_PrivData)->Root
37 #define _PARENT_FILE(_PrivData) \
38 ((_PrivData)->IsRootDirectory ? (_PrivData)->Root : &(_PrivData)->File)
39 #define _FILE(_PrivData) _PARENT_FILE(_PrivData)
42 Open the root directory on a volume.
44 @param This Protocol instance pointer.
45 @param Root Returns an Open file handle for the root directory
47 @retval EFI_SUCCESS The device was opened.
48 @retval EFI_UNSUPPORTED This volume does not support the file system.
49 @retval EFI_NO_MEDIA The device has no media.
50 @retval EFI_DEVICE_ERROR The device reported an error.
51 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
52 @retval EFI_ACCESS_DENIED The service denied access to the file.
53 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of
60 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*This
,
61 OUT EFI_FILE_PROTOCOL
**Root
66 PRIVATE_UDF_SIMPLE_FS_DATA
*PrivFsData
;
67 PRIVATE_UDF_FILE_DATA
*PrivFileData
;
69 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
71 if (This
== NULL
|| Root
== NULL
) {
72 Status
= EFI_INVALID_PARAMETER
;
73 goto Error_Invalid_Params
;
76 PrivFsData
= PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (This
);
78 if (PrivFsData
->OpenFiles
== 0) {
80 // There is no more open files. Read volume information again since it was
81 // cleaned up on the last UdfClose() call.
83 Status
= ReadUdfVolumeInformation (
88 if (EFI_ERROR (Status
)) {
89 goto Error_Read_Udf_Volume
;
93 CleanupFileInformation (&PrivFsData
->Root
);
96 // Find root directory file.
98 Status
= FindRootDirectory (
104 if (EFI_ERROR (Status
)) {
105 goto Error_Find_Root_Dir
;
109 (PRIVATE_UDF_FILE_DATA
*) AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA
));
110 if (PrivFileData
== NULL
) {
111 Status
= EFI_OUT_OF_RESOURCES
;
112 goto Error_Alloc_Priv_File_Data
;
115 PrivFileData
->Signature
= PRIVATE_UDF_FILE_DATA_SIGNATURE
;
116 PrivFileData
->SimpleFs
= This
;
117 PrivFileData
->Root
= &PrivFsData
->Root
;
118 PrivFileData
->IsRootDirectory
= TRUE
;
120 CopyMem ((VOID
*)&PrivFileData
->FileIo
, (VOID
*)&gUdfFileIoOps
,
121 sizeof (EFI_FILE_PROTOCOL
));
123 *Root
= &PrivFileData
->FileIo
;
125 PrivFsData
->OpenFiles
++;
127 gBS
->RestoreTPL (OldTpl
);
131 Error_Alloc_Priv_File_Data
:
132 CleanupFileInformation (&PrivFsData
->Root
);
136 Error_Read_Udf_Volume
:
137 Error_Invalid_Params
:
138 gBS
->RestoreTPL (OldTpl
);
144 Opens a new file relative to the source file's location.
146 @param This The protocol instance pointer.
147 @param NewHandle Returns File Handle for FileName.
148 @param FileName Null terminated string. "\", ".", and ".." are supported.
149 @param OpenMode Open mode for file.
150 @param Attributes Only used for EFI_FILE_MODE_CREATE.
152 @retval EFI_SUCCESS The device was opened.
153 @retval EFI_NOT_FOUND The specified file could not be found on the
155 @retval EFI_NO_MEDIA The device has no media.
156 @retval EFI_MEDIA_CHANGED The media has changed.
157 @retval EFI_DEVICE_ERROR The device reported an error.
158 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
159 @retval EFI_ACCESS_DENIED The service denied access to the file.
160 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of
162 @retval EFI_VOLUME_FULL The volume is full.
168 IN EFI_FILE_PROTOCOL
*This
,
169 OUT EFI_FILE_PROTOCOL
**NewHandle
,
177 PRIVATE_UDF_FILE_DATA
*PrivFileData
;
178 PRIVATE_UDF_SIMPLE_FS_DATA
*PrivFsData
;
179 CHAR16 FilePath
[UDF_PATH_LENGTH
];
181 PRIVATE_UDF_FILE_DATA
*NewPrivFileData
;
182 CHAR16
*TempFileName
;
184 ZeroMem (FilePath
, sizeof FilePath
);
185 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
187 if (This
== NULL
|| NewHandle
== NULL
|| FileName
== NULL
) {
188 Status
= EFI_INVALID_PARAMETER
;
189 goto Error_Invalid_Params
;
192 if (OpenMode
!= EFI_FILE_MODE_READ
) {
193 Status
= EFI_WRITE_PROTECTED
;
194 goto Error_Invalid_Params
;
197 PrivFileData
= PRIVATE_UDF_FILE_DATA_FROM_THIS (This
);
199 PrivFsData
= PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData
->SimpleFs
);
204 if (*FileName
== L
'\\') {
205 StrCpyS (FilePath
, UDF_PATH_LENGTH
, FileName
);
207 StrCpyS (FilePath
, UDF_PATH_LENGTH
, PrivFileData
->AbsoluteFileName
);
208 StrCatS (FilePath
, UDF_PATH_LENGTH
, L
"\\");
209 StrCatS (FilePath
, UDF_PATH_LENGTH
, FileName
);
212 MangleFileName (FilePath
);
213 if (FilePath
[0] == L
'\0') {
214 Status
= EFI_NOT_FOUND
;
215 goto Error_Bad_FileName
;
223 _ROOT_FILE (PrivFileData
),
224 _PARENT_FILE (PrivFileData
),
225 &_PARENT_FILE(PrivFileData
)->FileIdentifierDesc
->Icb
,
228 if (EFI_ERROR (Status
)) {
229 goto Error_Find_File
;
233 (PRIVATE_UDF_FILE_DATA
*)AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA
));
234 if (NewPrivFileData
== NULL
) {
235 Status
= EFI_OUT_OF_RESOURCES
;
236 goto Error_Alloc_New_Priv_File_Data
;
239 CopyMem ((VOID
*)NewPrivFileData
, (VOID
*)PrivFileData
,
240 sizeof (PRIVATE_UDF_FILE_DATA
));
241 CopyMem ((VOID
*)&NewPrivFileData
->File
, &File
, sizeof (UDF_FILE_INFO
));
243 NewPrivFileData
->IsRootDirectory
= FALSE
;
245 StrCpyS (NewPrivFileData
->AbsoluteFileName
, UDF_PATH_LENGTH
, FilePath
);
246 FileName
= NewPrivFileData
->AbsoluteFileName
;
248 while ((TempFileName
= StrStr (FileName
, L
"\\")) != NULL
) {
249 FileName
= TempFileName
+ 1;
252 StrCpyS (NewPrivFileData
->FileName
, UDF_FILENAME_LENGTH
, FileName
);
254 Status
= GetFileSize (
258 &NewPrivFileData
->File
,
259 &NewPrivFileData
->FileSize
261 if (EFI_ERROR (Status
)) {
264 "%a: GetFileSize() fails with status - %r.\n",
267 goto Error_Get_File_Size
;
270 NewPrivFileData
->FilePosition
= 0;
271 ZeroMem ((VOID
*)&NewPrivFileData
->ReadDirInfo
,
272 sizeof (UDF_READ_DIRECTORY_INFO
));
274 *NewHandle
= &NewPrivFileData
->FileIo
;
276 PrivFsData
->OpenFiles
++;
278 gBS
->RestoreTPL (OldTpl
);
283 FreePool ((VOID
*)NewPrivFileData
);
285 Error_Alloc_New_Priv_File_Data
:
286 CleanupFileInformation (&File
);
290 Error_Invalid_Params
:
291 gBS
->RestoreTPL (OldTpl
);
297 Read data from the file.
299 @param This Protocol instance pointer.
300 @param BufferSize On input size of buffer, on output amount of data in
302 @param Buffer The buffer in which data is read.
304 @retval EFI_SUCCESS Data was read.
305 @retval EFI_NO_MEDIA The device has no media.
306 @retval EFI_DEVICE_ERROR The device reported an error.
307 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
308 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains
315 IN EFI_FILE_PROTOCOL
*This
,
316 IN OUT UINTN
*BufferSize
,
322 PRIVATE_UDF_FILE_DATA
*PrivFileData
;
323 PRIVATE_UDF_SIMPLE_FS_DATA
*PrivFsData
;
324 UDF_VOLUME_INFO
*Volume
;
325 UDF_FILE_INFO
*Parent
;
326 UDF_READ_DIRECTORY_INFO
*ReadDirInfo
;
327 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
328 EFI_DISK_IO_PROTOCOL
*DiskIo
;
329 UDF_FILE_INFO FoundFile
;
330 UDF_FILE_IDENTIFIER_DESCRIPTOR
*NewFileIdentifierDesc
;
331 VOID
*NewFileEntryData
;
332 CHAR16 FileName
[UDF_FILENAME_LENGTH
];
334 UINT64 BufferSizeUint64
;
336 ZeroMem (FileName
, sizeof FileName
);
337 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
339 if (This
== NULL
|| BufferSize
== NULL
|| (*BufferSize
!= 0 &&
341 Status
= EFI_INVALID_PARAMETER
;
342 goto Error_Invalid_Params
;
345 PrivFileData
= PRIVATE_UDF_FILE_DATA_FROM_THIS (This
);
346 PrivFsData
= PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData
->SimpleFs
);
348 BlockIo
= PrivFsData
->BlockIo
;
349 DiskIo
= PrivFsData
->DiskIo
;
350 Volume
= &PrivFsData
->Volume
;
351 ReadDirInfo
= &PrivFileData
->ReadDirInfo
;
352 NewFileIdentifierDesc
= NULL
;
353 NewFileEntryData
= NULL
;
355 Parent
= _PARENT_FILE (PrivFileData
);
357 Status
= EFI_VOLUME_CORRUPTED
;
359 if (IS_FID_NORMAL_FILE (Parent
->FileIdentifierDesc
)) {
360 if (PrivFileData
->FilePosition
> PrivFileData
->FileSize
) {
362 // File's position is beyond the EOF
364 Status
= EFI_DEVICE_ERROR
;
365 goto Error_File_Beyond_The_Eof
;
368 if (PrivFileData
->FilePosition
== PrivFileData
->FileSize
) {
370 Status
= EFI_SUCCESS
;
374 BufferSizeUint64
= *BufferSize
;
376 Status
= ReadFileData (
381 PrivFileData
->FileSize
,
382 &PrivFileData
->FilePosition
,
386 ASSERT (BufferSizeUint64
<= MAX_UINTN
);
387 *BufferSize
= (UINTN
)BufferSizeUint64
;
388 } else if (IS_FID_DIRECTORY_FILE (Parent
->FileIdentifierDesc
)) {
389 if (ReadDirInfo
->FidOffset
== 0 && PrivFileData
->FilePosition
> 0) {
390 Status
= EFI_DEVICE_ERROR
;
396 Status
= ReadDirectoryEntry (
400 &Parent
->FileIdentifierDesc
->Icb
,
403 &NewFileIdentifierDesc
405 if (EFI_ERROR (Status
)) {
406 if (Status
== EFI_DEVICE_ERROR
) {
407 FreePool (ReadDirInfo
->DirectoryData
);
408 ZeroMem ((VOID
*)ReadDirInfo
, sizeof (UDF_READ_DIRECTORY_INFO
));
411 Status
= EFI_SUCCESS
;
417 // After calling function ReadDirectoryEntry(), if 'NewFileIdentifierDesc'
418 // is NULL, then the 'Status' must be EFI_OUT_OF_RESOURCES. Hence, if the
419 // code reaches here, 'NewFileIdentifierDesc' must be not NULL.
421 // The ASSERT here is for addressing a false positive NULL pointer
422 // dereference issue raised from static analysis.
424 ASSERT (NewFileIdentifierDesc
!= NULL
);
426 if (!IS_FID_PARENT_FILE (NewFileIdentifierDesc
)) {
430 FreePool ((VOID
*)NewFileIdentifierDesc
);
433 Status
= FindFileEntry (
437 &NewFileIdentifierDesc
->Icb
,
440 if (EFI_ERROR (Status
)) {
443 ASSERT (NewFileEntryData
!= NULL
);
445 if (FE_ICB_FILE_TYPE (NewFileEntryData
) == UdfFileEntrySymlink
) {
446 Status
= ResolveSymlink (
454 if (EFI_ERROR (Status
)) {
455 goto Error_Resolve_Symlink
;
458 FreePool ((VOID
*)NewFileEntryData
);
459 NewFileEntryData
= FoundFile
.FileEntry
;
461 Status
= GetFileNameFromFid (NewFileIdentifierDesc
, ARRAY_SIZE (FileName
), FileName
);
462 if (EFI_ERROR (Status
)) {
463 FreePool ((VOID
*)FoundFile
.FileIdentifierDesc
);
464 goto Error_Get_FileName
;
467 FreePool ((VOID
*)NewFileIdentifierDesc
);
468 NewFileIdentifierDesc
= FoundFile
.FileIdentifierDesc
;
470 FoundFile
.FileIdentifierDesc
= NewFileIdentifierDesc
;
471 FoundFile
.FileEntry
= NewFileEntryData
;
473 Status
= GetFileNameFromFid (FoundFile
.FileIdentifierDesc
, ARRAY_SIZE (FileName
), FileName
);
474 if (EFI_ERROR (Status
)) {
475 goto Error_Get_FileName
;
479 Status
= GetFileSize (
486 if (EFI_ERROR (Status
)) {
487 goto Error_Get_File_Size
;
490 Status
= SetFileInfo (
497 if (EFI_ERROR (Status
)) {
498 goto Error_Set_File_Info
;
501 PrivFileData
->FilePosition
++;
502 Status
= EFI_SUCCESS
;
503 } else if (IS_FID_DELETED_FILE (Parent
->FileIdentifierDesc
)) {
505 // Code should never reach here.
508 Status
= EFI_DEVICE_ERROR
;
514 Error_Resolve_Symlink
:
515 if (NewFileEntryData
!= NULL
) {
516 FreePool (NewFileEntryData
);
520 if (NewFileIdentifierDesc
!= NULL
) {
521 FreePool ((VOID
*)NewFileIdentifierDesc
);
525 Error_File_Beyond_The_Eof
:
526 Error_Invalid_Params
:
527 gBS
->RestoreTPL (OldTpl
);
533 Close the file handle.
535 @param This Protocol instance pointer.
537 @retval EFI_SUCCESS The file was closed.
543 IN EFI_FILE_PROTOCOL
*This
548 PRIVATE_UDF_FILE_DATA
*PrivFileData
;
550 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
552 Status
= EFI_SUCCESS
;
555 Status
= EFI_INVALID_PARAMETER
;
559 PrivFileData
= PRIVATE_UDF_FILE_DATA_FROM_THIS (This
);
561 if (!PrivFileData
->IsRootDirectory
) {
562 CleanupFileInformation (&PrivFileData
->File
);
564 if (PrivFileData
->ReadDirInfo
.DirectoryData
!= NULL
) {
565 FreePool (PrivFileData
->ReadDirInfo
.DirectoryData
);
569 FreePool ((VOID
*)PrivFileData
);
572 gBS
->RestoreTPL (OldTpl
);
578 Close and delete the file handle.
580 @param This Protocol instance pointer.
582 @retval EFI_SUCCESS The file was closed and deleted.
583 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not
590 IN EFI_FILE_PROTOCOL
*This
593 PRIVATE_UDF_FILE_DATA
*PrivFileData
;
596 return EFI_INVALID_PARAMETER
;
599 PrivFileData
= PRIVATE_UDF_FILE_DATA_FROM_THIS (This
);
601 (VOID
)PrivFileData
->FileIo
.Close(This
);
603 return EFI_WARN_DELETE_FAILURE
;
607 Write data to a file.
609 @param This Protocol instance pointer.
610 @param BufferSize On input size of buffer, on output amount of data in
612 @param Buffer The buffer in which data to write.
614 @retval EFI_SUCCESS Data was written.
615 @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
616 @retval EFI_NO_MEDIA The device has no media.
617 @retval EFI_DEVICE_ERROR The device reported an error.
618 @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
619 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
620 @retval EFI_WRITE_PROTECTED The device is write protected.
621 @retval EFI_ACCESS_DENIED The file was open for read only.
622 @retval EFI_VOLUME_FULL The volume is full.
628 IN EFI_FILE_PROTOCOL
*This
,
629 IN OUT UINTN
*BufferSize
,
633 return EFI_UNSUPPORTED
;
637 Get file's current position.
639 @param This Protocol instance pointer.
640 @param Position Byte position from the start of the file.
642 @retval EFI_SUCCESS Position was updated.
643 @retval EFI_UNSUPPORTED Seek request for directories is not valid.
649 IN EFI_FILE_PROTOCOL
*This
,
653 PRIVATE_UDF_FILE_DATA
*PrivFileData
;
655 if (This
== NULL
|| Position
== NULL
) {
656 return EFI_INVALID_PARAMETER
;
659 PrivFileData
= PRIVATE_UDF_FILE_DATA_FROM_THIS (This
);
662 // As per UEFI spec, if the file handle is a directory, then the current file
663 // position has no meaning and the operation is not supported.
665 if (IS_FID_DIRECTORY_FILE (PrivFileData
->File
.FileIdentifierDesc
)) {
666 return EFI_UNSUPPORTED
;
670 // The file is not a directory. So, return its position.
672 *Position
= PrivFileData
->FilePosition
;
678 Set file's current position.
680 @param This Protocol instance pointer.
681 @param Position Byte position from the start of the file.
683 @retval EFI_SUCCESS Position was updated.
684 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
690 IN EFI_FILE_PROTOCOL
*This
,
695 PRIVATE_UDF_FILE_DATA
*PrivFileData
;
696 UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
;
699 return EFI_INVALID_PARAMETER
;
702 Status
= EFI_UNSUPPORTED
;
704 PrivFileData
= PRIVATE_UDF_FILE_DATA_FROM_THIS (This
);
706 FileIdentifierDesc
= _FILE (PrivFileData
)->FileIdentifierDesc
;
707 ASSERT (FileIdentifierDesc
!= NULL
);
708 if (IS_FID_DIRECTORY_FILE (FileIdentifierDesc
)) {
710 // If the file handle is a directory, the _only_ position that may be set is
711 // zero. This has no effect of starting the read proccess of the directory
715 PrivFileData
->FilePosition
= Position
;
716 PrivFileData
->ReadDirInfo
.FidOffset
= 0;
717 Status
= EFI_SUCCESS
;
719 } else if (IS_FID_NORMAL_FILE (FileIdentifierDesc
)) {
721 // Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to be
724 if (Position
== 0xFFFFFFFFFFFFFFFF) {
725 PrivFileData
->FilePosition
= PrivFileData
->FileSize
;
727 PrivFileData
->FilePosition
= Position
;
730 Status
= EFI_SUCCESS
;
737 Get information about a file.
739 @attention This is boundary function that may receive untrusted input.
740 @attention The input is from FileSystem.
742 The File Set Descriptor is external input, so this routine will do basic
743 validation for File Set Descriptor and report status.
745 @param This Protocol instance pointer.
746 @param InformationType Type of information to return in Buffer.
747 @param BufferSize On input size of buffer, on output amount of data in
749 @param Buffer The buffer to return data.
751 @retval EFI_SUCCESS Data was returned.
752 @retval EFI_UNSUPPORTED InformationType is not supported.
753 @retval EFI_NO_MEDIA The device has no media.
754 @retval EFI_DEVICE_ERROR The device reported an error.
755 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
756 @retval EFI_WRITE_PROTECTED The device is write protected.
757 @retval EFI_ACCESS_DENIED The file was open for read only.
758 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in
765 IN EFI_FILE_PROTOCOL
*This
,
766 IN EFI_GUID
*InformationType
,
767 IN OUT UINTN
*BufferSize
,
772 PRIVATE_UDF_FILE_DATA
*PrivFileData
;
773 PRIVATE_UDF_SIMPLE_FS_DATA
*PrivFsData
;
774 EFI_FILE_SYSTEM_INFO
*FileSystemInfo
;
775 UINTN FileSystemInfoLength
;
777 UDF_FILE_SET_DESCRIPTOR
*FileSetDesc
;
779 UINT8
*OstaCompressed
;
782 UINT64 FreeSpaceSize
;
783 CHAR16 VolumeLabel
[64];
785 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
||
786 (*BufferSize
!= 0 && Buffer
== NULL
)) {
787 return EFI_INVALID_PARAMETER
;
790 PrivFileData
= PRIVATE_UDF_FILE_DATA_FROM_THIS (This
);
792 PrivFsData
= PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData
->SimpleFs
);
794 Status
= EFI_UNSUPPORTED
;
796 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
797 Status
= SetFileInfo (
798 _FILE (PrivFileData
),
799 PrivFileData
->FileSize
,
800 PrivFileData
->FileName
,
804 } else if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
805 String
= VolumeLabel
;
807 FileSetDesc
= &PrivFsData
->Volume
.FileSetDesc
;
809 OstaCompressed
= &FileSetDesc
->LogicalVolumeIdentifier
[0];
811 CompressionId
= OstaCompressed
[0];
812 if (!IS_VALID_COMPRESSION_ID (CompressionId
)) {
813 return EFI_VOLUME_CORRUPTED
;
816 for (Index
= 1; Index
< 128; Index
++) {
817 if (CompressionId
== 16) {
818 *String
= *(UINT8
*)(OstaCompressed
+ Index
) << 8;
821 if (Index
> ARRAY_SIZE (VolumeLabel
)) {
822 return EFI_VOLUME_CORRUPTED
;
829 *String
|= (CHAR16
)(*(UINT8
*)(OstaCompressed
+ Index
));
833 // Unlike FID Identifiers, Logical Volume Identifier is stored in a
834 // NULL-terminated OSTA compressed format, so we must check for the NULL
837 if (*String
== L
'\0') {
844 Index
= ((UINTN
)String
- (UINTN
)VolumeLabel
) / sizeof (CHAR16
);
845 if (Index
> ARRAY_SIZE (VolumeLabel
) - 1) {
846 Index
= ARRAY_SIZE (VolumeLabel
) - 1;
848 VolumeLabel
[Index
] = L
'\0';
850 FileSystemInfoLength
= StrSize (VolumeLabel
) +
851 sizeof (EFI_FILE_SYSTEM_INFO
);
852 if (*BufferSize
< FileSystemInfoLength
) {
853 *BufferSize
= FileSystemInfoLength
;
854 return EFI_BUFFER_TOO_SMALL
;
857 FileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*)Buffer
;
859 FileSystemInfo
->VolumeLabel
,
860 (*BufferSize
- OFFSET_OF (EFI_FILE_SYSTEM_INFO
, VolumeLabel
)) / sizeof (CHAR16
),
863 Status
= GetVolumeSize (
870 if (EFI_ERROR (Status
)) {
874 FileSystemInfo
->Size
= FileSystemInfoLength
;
875 FileSystemInfo
->ReadOnly
= TRUE
;
876 FileSystemInfo
->BlockSize
=
877 PrivFsData
->Volume
.LogicalVolDesc
.LogicalBlockSize
;
878 FileSystemInfo
->VolumeSize
= VolumeSize
;
879 FileSystemInfo
->FreeSpace
= FreeSpaceSize
;
881 *BufferSize
= FileSystemInfoLength
;
882 Status
= EFI_SUCCESS
;
889 Set information about a file.
891 @param This Protocol instance pointer.
892 @param InformationType Type of information in Buffer.
893 @param BufferSize Size of buffer.
894 @param Buffer The data to write.
896 @retval EFI_SUCCESS Data was set.
897 @retval EFI_UNSUPPORTED InformationType is not supported.
898 @retval EFI_NO_MEDIA The device has no media.
899 @retval EFI_DEVICE_ERROR The device reported an error.
900 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
901 @retval EFI_WRITE_PROTECTED The device is write protected.
902 @retval EFI_ACCESS_DENIED The file was open for read only.
908 IN EFI_FILE_PROTOCOL
*This
,
909 IN EFI_GUID
*InformationType
,
914 return EFI_WRITE_PROTECTED
;
918 Flush data back for the file handle.
920 @param This Protocol instance pointer.
922 @retval EFI_SUCCESS Data was flushed.
923 @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
924 @retval EFI_NO_MEDIA The device has no media.
925 @retval EFI_DEVICE_ERROR The device reported an error.
926 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
927 @retval EFI_WRITE_PROTECTED The device is write protected.
928 @retval EFI_ACCESS_DENIED The file was open for read only.
929 @retval EFI_VOLUME_FULL The volume is full.
935 IN EFI_FILE_PROTOCOL
*This
938 return EFI_WRITE_PROTECTED
;