This patch implements UdfRead(), UdfGetPosition() and UdfSetPosition()
functions.
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
---
MdeModulePkg/Universal/Disk/UdfDxe/File.c | 264 ++++++++++++++++++++-
.../Universal/Disk/UdfDxe/FileSystemOperations.c | 102 ++++++--
MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 33 +++
3 files changed, 371 insertions(+), 28 deletions(-)
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/File.c b/MdeModulePkg/Universal/Disk/UdfDxe/File.c
index dcb9ff2cf5..3b93beb3f8 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/File.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/File.c
@@ -198,7 +198,7 @@ UdfOpen (
//
// Build full path
//
- if (FileName[0] == L'\\') {
+ if (*FileName == L'\\') {
StrCpyS (FilePath, UDF_PATH_LENGTH, FileName);
} else {
StrCpyS (FilePath, UDF_PATH_LENGTH, PrivFileData->AbsoluteFileName);
@@ -247,6 +247,7 @@ UdfOpen (
}
StrCpyS (NewPrivFileData->FileName, UDF_PATH_LENGTH, FileName);
+
Status = GetFileSize (
PrivFsData->BlockIo,
PrivFsData->DiskIo,
@@ -308,7 +309,197 @@ UdfRead (
OUT VOID *Buffer
)
{
- return EFI_VOLUME_CORRUPTED;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ PRIVATE_UDF_FILE_DATA *PrivFileData;
+ PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;
+ UDF_VOLUME_INFO *Volume;
+ UDF_FILE_INFO *Parent;
+ UDF_READ_DIRECTORY_INFO *ReadDirInfo;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+ UDF_FILE_INFO FoundFile;
+ UDF_FILE_IDENTIFIER_DESCRIPTOR *NewFileIdentifierDesc;
+ VOID *NewFileEntryData;
+ CHAR16 FileName[UDF_FILENAME_LENGTH] = { 0 };
+ UINT64 FileSize;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ if (This == NULL || BufferSize == NULL || (*BufferSize != 0 &&
+ Buffer == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Error_Invalid_Params;
+ }
+
+ PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
+
+ PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);
+
+ BlockIo = PrivFsData->BlockIo;
+ DiskIo = PrivFsData->DiskIo;
+ Volume = &PrivFsData->Volume;
+ ReadDirInfo = &PrivFileData->ReadDirInfo;
+ NewFileIdentifierDesc = NULL;
+ NewFileEntryData = NULL;
+
+ Parent = _PARENT_FILE (PrivFileData);
+
+ Status = EFI_VOLUME_CORRUPTED;
+
+ if (IS_FID_NORMAL_FILE (Parent->FileIdentifierDesc)) {
+ if (PrivFileData->FilePosition > PrivFileData->FileSize) {
+ //
+ // File's position is beyond the EOF
+ //
+ Status = EFI_DEVICE_ERROR;
+ goto Error_File_Beyond_The_Eof;
+ }
+
+ if (PrivFileData->FilePosition == PrivFileData->FileSize) {
+ *BufferSize = 0;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ Status = ReadFileData (
+ BlockIo,
+ DiskIo,
+ Volume,
+ Parent,
+ PrivFileData->FileSize,
+ &PrivFileData->FilePosition,
+ Buffer,
+ BufferSize
+ );
+ } else if (IS_FID_DIRECTORY_FILE (Parent->FileIdentifierDesc)) {
+ if (ReadDirInfo->FidOffset == 0 && PrivFileData->FilePosition > 0) {
+ Status = EFI_DEVICE_ERROR;
+ *BufferSize = 0;
+ goto Done;
+ }
+
+ for (;;) {
+ Status = ReadDirectoryEntry (
+ BlockIo,
+ DiskIo,
+ Volume,
+ &Parent->FileIdentifierDesc->Icb,
+ Parent->FileEntry,
+ ReadDirInfo,
+ &NewFileIdentifierDesc
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_DEVICE_ERROR) {
+ FreePool (ReadDirInfo->DirectoryData);
+ ZeroMem ((VOID *)ReadDirInfo, sizeof (UDF_READ_DIRECTORY_INFO));
+
+ *BufferSize = 0;
+ Status = EFI_SUCCESS;
+ }
+
+ goto Done;
+ }
+
+ if (!IS_FID_PARENT_FILE (NewFileIdentifierDesc)) {
+ break;
+ }
+
+ FreePool ((VOID *)NewFileIdentifierDesc);
+ }
+
+ Status = FindFileEntry (
+ BlockIo,
+ DiskIo,
+ Volume,
+ &NewFileIdentifierDesc->Icb,
+ &NewFileEntryData
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Find_Fe;
+ }
+
+ if (IS_FE_SYMLINK (NewFileEntryData)) {
+ Status = ResolveSymlink (
+ BlockIo,
+ DiskIo,
+ Volume,
+ Parent,
+ NewFileEntryData,
+ &FoundFile
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Resolve_Symlink;
+ }
+
+ FreePool ((VOID *)NewFileEntryData);
+ NewFileEntryData = FoundFile.FileEntry;
+
+ Status = GetFileNameFromFid (NewFileIdentifierDesc, FileName);
+ if (EFI_ERROR (Status)) {
+ FreePool ((VOID *)FoundFile.FileIdentifierDesc);
+ goto Error_Get_FileName;
+ }
+
+ FreePool ((VOID *)NewFileIdentifierDesc);
+ NewFileIdentifierDesc = FoundFile.FileIdentifierDesc;
+ } else {
+ FoundFile.FileIdentifierDesc = NewFileIdentifierDesc;
+ FoundFile.FileEntry = NewFileEntryData;
+
+ Status = GetFileNameFromFid (FoundFile.FileIdentifierDesc, FileName);
+ if (EFI_ERROR (Status)) {
+ goto Error_Get_FileName;
+ }
+ }
+
+ Status = GetFileSize (
+ BlockIo,
+ DiskIo,
+ Volume,
+ &FoundFile,
+ &FileSize
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Get_File_Size;
+ }
+
+ Status = SetFileInfo (
+ &FoundFile,
+ FileSize,
+ FileName,
+ BufferSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Set_File_Info;
+ }
+
+ PrivFileData->FilePosition++;
+ Status = EFI_SUCCESS;
+ } else if (IS_FID_DELETED_FILE (Parent->FileIdentifierDesc)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+Error_Set_File_Info:
+Error_Get_File_Size:
+Error_Get_FileName:
+Error_Resolve_Symlink:
+ if (NewFileEntryData != NULL) {
+ FreePool (NewFileEntryData);
+ }
+
+Error_Find_Fe:
+ if (NewFileIdentifierDesc != NULL) {
+ FreePool ((VOID *)NewFileIdentifierDesc);
+ }
+
+Done:
+Error_File_Beyond_The_Eof:
+Error_Invalid_Params:
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
}
/**
@@ -346,7 +537,7 @@ UdfClose (
if (!PrivFileData->IsRootDirectory) {
CleanupFileInformation (&PrivFileData->File);
- if (PrivFileData->ReadDirInfo.DirectoryData) {
+ if (PrivFileData->ReadDirInfo.DirectoryData != NULL) {
FreePool (PrivFileData->ReadDirInfo.DirectoryData);
}
}
@@ -439,7 +630,28 @@ UdfGetPosition (
OUT UINT64 *Position
)
{
- return EFI_UNSUPPORTED;
+ PRIVATE_UDF_FILE_DATA *PrivFileData;
+
+ if (This == NULL || Position == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
+
+ //
+ // As per UEFI spec, if the file handle is a directory, then the current file
+ // position has no meaning and the operation is not supported.
+ //
+ if (IS_FID_DIRECTORY_FILE (&PrivFileData->File.FileIdentifierDesc)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // The file is not a directory. So, return its position.
+ //
+ *Position = PrivFileData->FilePosition;
+
+ return EFI_SUCCESS;
}
/**
@@ -459,7 +671,45 @@ UdfSetPosition (
IN UINT64 Position
)
{
- return EFI_UNSUPPORTED;
+ EFI_STATUS Status;
+ PRIVATE_UDF_FILE_DATA *PrivFileData;
+ UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_UNSUPPORTED;
+
+ PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
+
+ FileIdentifierDesc = PrivFileData->File.FileIdentifierDesc;
+ if (IS_FID_DIRECTORY_FILE (FileIdentifierDesc)) {
+ //
+ // If the file handle is a directory, the _only_ position that may be set is
+ // zero. This has no effect of starting the read proccess of the directory
+ // entries over.
+ //
+ if (Position == 0) {
+ PrivFileData->FilePosition = Position;
+ PrivFileData->ReadDirInfo.FidOffset = 0;
+ Status = EFI_SUCCESS;
+ }
+ } else if (IS_FID_NORMAL_FILE (FileIdentifierDesc)) {
+ //
+ // Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to be
+ // set to the EOF.
+ //
+ if (Position == 0xFFFFFFFFFFFFFFFF) {
+ PrivFileData->FilePosition = PrivFileData->FileSize - 1;
+ } else {
+ PrivFileData->FilePosition = Position;
+ }
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
}
/**
@@ -505,7 +755,7 @@ UdfGetInfo (
UINT64 FreeSpaceSize;
CHAR16 VolumeLabel[64];
- if (This == NULL || InformationType == NULL || BufferSize == 0 ||
+ if (This == NULL || InformationType == NULL || BufferSize == NULL ||
(*BufferSize != 0 && Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
@@ -553,7 +803,7 @@ UdfGetInfo (
// NULL-terminated OSTA compressed format, so we must check for the NULL
// character.
//
- if (!*String) {
+ if (*String == L'\0') {
break;
}
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
index 2f7f945479..65cf8dc057 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
@@ -384,7 +384,7 @@ GetFileSetDescriptors (
for (Index = 0; Index < Volume->LogicalVolDescsNo; Index++) {
FileSetDesc = AllocateZeroPool (sizeof (UDF_FILE_SET_DESCRIPTOR));
- if (!FileSetDesc) {
+ if (FileSetDesc == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error_Alloc_Fsd;
}
@@ -533,13 +533,13 @@ GetFileEntryData (
ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData;
*Length = ExtendedFileEntry->InformationLength;
- *Data = (VOID *)((UINT8 *)&ExtendedFileEntry->Data[0] +
+ *Data = (VOID *)((UINT8 *)ExtendedFileEntry->Data +
ExtendedFileEntry->LengthOfExtendedAttributes);
} else if (IS_FE (FileEntryData)) {
FileEntry = (UDF_FILE_ENTRY *)FileEntryData;
*Length = FileEntry->InformationLength;
- *Data = (VOID *)((UINT8 *)&FileEntry->Data[0] +
+ *Data = (VOID *)((UINT8 *)FileEntry->Data +
FileEntry->LengthOfExtendedAttributes);
}
}
@@ -561,13 +561,13 @@ GetAdsInformation (
ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData;
*Length = ExtendedFileEntry->LengthOfAllocationDescriptors;
- *AdsData = (VOID *)((UINT8 *)&ExtendedFileEntry->Data[0] +
+ *AdsData = (VOID *)((UINT8 *)ExtendedFileEntry->Data +
ExtendedFileEntry->LengthOfExtendedAttributes);
} else if (IS_FE (FileEntryData)) {
FileEntry = (UDF_FILE_ENTRY *)FileEntryData;
*Length = FileEntry->LengthOfAllocationDescriptors;
- *AdsData = (VOID *)((UINT8 *)&FileEntry->Data[0] +
+ *AdsData = (VOID *)((UINT8 *)FileEntry->Data +
FileEntry->LengthOfExtendedAttributes);
}
}
@@ -955,7 +955,7 @@ ReadFile (
// Allocate buffer for starting read data.
//
ReadFileInfo->FileData = AllocatePool (Length);
- if (!ReadFileInfo->FileData) {
+ if (ReadFileInfo->FileData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
@@ -1135,7 +1135,7 @@ ReadFile (
ReadFileInfo->FilePosition += DataLength;
BytesLeft -= DataLength;
- if (!BytesLeft) {
+ if (BytesLeft == 0) {
//
// There is no more file data to read.
//
@@ -1155,7 +1155,8 @@ ReadFile (
break;
case EXTENDED_ADS_SEQUENCE:
- // Not supported. Haven't got a volume with that yet.
+ // FIXME: Not supported. Got no volume with it, yet.
+ ASSERT (FALSE);
Status = EFI_UNSUPPORTED;
break;
}
@@ -1214,7 +1215,7 @@ InternalFindFile (
// If FileName is current file or working directory, just duplicate Parent's
// FE/EFE and FID descriptors.
//
- if (!StrCmp (FileName, L".")) {
+ if (StrCmp (FileName, L".") == 0) {
DuplicateFe (BlockIo, Volume, Parent->FileEntry, &File->FileEntry);
DuplicateFid (Parent->FileIdentifierDesc, &File->FileIdentifierDesc);
@@ -1254,7 +1255,7 @@ InternalFindFile (
// directory (Parent), and if FileName is either ".." or "\\", then it's
// the expected FID.
//
- if (!StrCmp (FileName, L"..") || !StrCmp (FileName, L"\\")) {
+ if (StrCmp (FileName, L"..") == 0 || StrCmp (FileName, L"\\") == 0) {
Found = TRUE;
break;
}
@@ -1268,14 +1269,14 @@ InternalFindFile (
}
//
- // OK - their filename lengths match. Now, compare if their filenames.
+ // OK - their filename lengths match. Now, compare their characters.
//
Status = GetFileNameFromFid (FileIdentifierDesc, FoundFileName);
if (EFI_ERROR (Status)) {
break;
}
- if (!StrCmp (FileName, FoundFileName)) {
+ if (StrCmp (FileName, FoundFileName) == 0) {
//
// FID has been found. Prepare to find its respective FE/EFE.
//
@@ -1288,7 +1289,7 @@ InternalFindFile (
FreePool ((VOID *)FileIdentifierDesc);
}
- if (ReadDirInfo.DirectoryData) {
+ if (ReadDirInfo.DirectoryData != NULL) {
//
// Free all allocated resources for the directory listing.
//
@@ -1306,7 +1307,7 @@ InternalFindFile (
//
// Otherwise, find FE/EFE from the respective FID.
//
- if (StrCmp (FileName, L"\\")) {
+ if (StrCmp (FileName, L"\\") != 0) {
Status = FindFileEntry (
BlockIo,
DiskIo,
@@ -1685,7 +1686,7 @@ FindFile (
//
// Open root directory.
//
- if (!Root) {
+ if (Root == NULL) {
//
// There is no file found for the root directory yet. So, find only its
// FID by now.
@@ -1798,7 +1799,7 @@ ReadDirectoryEntry (
UDF_READ_FILE_INFO ReadFileInfo;
UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc;
- if (!ReadDirInfo->DirectoryData) {
+ if (ReadDirInfo->DirectoryData == NULL) {
//
// The directory's recorded data has not been read yet. So let's cache it
// into memory and the next calls won't need to read it again.
@@ -1873,7 +1874,7 @@ GetFileNameFromFid (
OstaCompressed =
(UINT8 *)(
- (UINT8 *)&FileIdentifierDesc->Data[0] +
+ (UINT8 *)FileIdentifierDesc->Data +
FileIdentifierDesc->LengthOfImplementationUse
);
@@ -2235,8 +2236,7 @@ SetFileInfo (
//
FileInfoLength = sizeof (EFI_FILE_INFO) + (FileName ?
StrSize (FileName) :
- sizeof (CHAR16)
- );
+ sizeof (CHAR16));
if (*BufferSize < FileInfoLength) {
//
// The given Buffer has no size enough for EFI_FILE_INFO structure.
@@ -2434,7 +2434,7 @@ GetVolumeSize (
Length = LogicalVolInt->NumberOfPartitions;
for (Index = 0; Index < Length; Index += sizeof (UINT32)) {
- LsnsNo = *(UINT32 *)((UINT8 *)&LogicalVolInt->Data[0] + Index);
+ LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);
if (LsnsNo == 0xFFFFFFFFUL) {
//
// Size not specified.
@@ -2447,7 +2447,7 @@ GetVolumeSize (
Length = (LogicalVolInt->NumberOfPartitions * sizeof (UINT32)) << 1;
for (; Index < Length; Index += sizeof (UINT32)) {
- LsnsNo = *(UINT32 *)((UINT8 *)&LogicalVolInt->Data[0] + Index);
+ LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);
if (LsnsNo == 0xFFFFFFFFUL) {
//
// Size not specified.
@@ -2470,3 +2470,63 @@ GetVolumeSize (
return EFI_SUCCESS;
}
+
+/**
+ Seek a file and read its data into memory on an UDF volume.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[in] File File information structure.
+ @param[in] FileSize Size of the file.
+ @param[in out] FilePosition File position.
+ @param[in out] Buffer File data.
+ @param[in out] BufferSize Read size.
+
+ @retval EFI_SUCCESS File seeked and read.
+ @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_OUT_OF_RESOURCES The file's recorded data was not read due to lack
+ of resources.
+
+**/
+EFI_STATUS
+ReadFileData (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_FILE_INFO *File,
+ IN UINT64 FileSize,
+ IN OUT UINT64 *FilePosition,
+ IN OUT VOID *Buffer,
+ IN OUT UINT64 *BufferSize
+ )
+{
+ EFI_STATUS Status;
+ UDF_READ_FILE_INFO ReadFileInfo;
+
+ ReadFileInfo.Flags = READ_FILE_SEEK_AND_READ;
+ ReadFileInfo.FilePosition = *FilePosition;
+ ReadFileInfo.FileData = Buffer;
+ ReadFileInfo.FileDataSize = *BufferSize;
+ ReadFileInfo.FileSize = FileSize;
+
+ Status = ReadFile (
+ BlockIo,
+ DiskIo,
+ Volume,
+ &File->FileIdentifierDesc->Icb,
+ File->FileEntry,
+ &ReadFileInfo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *BufferSize = ReadFileInfo.FileDataSize;
+ *FilePosition = ReadFileInfo.FilePosition;
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h
index 37d7c613e1..ccea385e22 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h
@@ -1032,6 +1032,39 @@ GetVolumeSize (
);
/**
+ Seek a file and read its data into memory on an UDF volume.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[in] File File information structure.
+ @param[in] FileSize Size of the file.
+ @param[in out] FilePosition File position.
+ @param[in out] Buffer File data.
+ @param[in out] BufferSize Read size.
+
+ @retval EFI_SUCCESS File seeked and read.
+ @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_OUT_OF_RESOURCES The file's recorded data was not read due to lack
+ of resources.
+
+**/
+EFI_STATUS
+ReadFileData (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_FILE_INFO *File,
+ IN UINT64 FileSize,
+ IN OUT UINT64 *FilePosition,
+ IN OUT VOID *Buffer,
+ IN OUT UINT64 *BufferSize
+ );
+
+/**
Mangle a filename by cutting off trailing whitespaces, "\\", "." and "..".
@param[in] FileName Filename.
--
2.11.0
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.