This patch implements UdfRead(), UdfGetPosition() and UdfSetPosition()
functions.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Paulo Alcantara <pca...@zytor.com>
---
 MdeModulePkg/Universal/Disk/UdfDxe/File.c          | 254 ++++++++++++++++++++-
 .../Universal/Disk/UdfDxe/FileSystemOperations.c   |  60 +++++
 MdeModulePkg/Universal/Disk/UdfDxe/Udf.h           |  33 +++
 3 files changed, 344 insertions(+), 3 deletions(-)

diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/File.c 
b/MdeModulePkg/Universal/Disk/UdfDxe/File.c
index f32dcf0..04b6530 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/File.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/File.c
@@ -321,7 +321,196 @@ 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 || !BufferSize || (*BufferSize && !Buffer)) {
+    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 && PrivFileData->FilePosition) {
+      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) {
+    FreePool (NewFileEntryData);
+  }
+
+Error_Find_Fe:
+  if (NewFileIdentifierDesc) {
+    FreePool ((VOID *)NewFileIdentifierDesc);
+  }
+
+Done:
+Error_File_Beyond_The_Eof:
+Error_Invalid_Params:
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
 }
 
 /**
@@ -450,7 +639,28 @@ UdfGetPosition (
   OUT  UINT64             *Position
   )
 {
-  return EFI_UNSUPPORTED;
+  PRIVATE_UDF_FILE_DATA *PrivFileData;
+
+  if (!This || !Position) {
+    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;
 }
 
 /**
@@ -470,7 +680,45 @@ UdfSetPosition (
   IN UINT64             Position
   )
 {
-  return EFI_UNSUPPORTED;
+  EFI_STATUS                      Status;
+  PRIVATE_UDF_FILE_DATA           *PrivFileData;
+  UDF_FILE_IDENTIFIER_DESCRIPTOR  *FileIdentifierDesc;
+
+  if (!This) {
+    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) {
+      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;
 }
 
 /**
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c 
b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
index 65a7af1..829463f 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
@@ -2533,3 +2533,63 @@ Read_Next_Sequence:
 
   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 14913b7..e3f7c87 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.
-- 
1.9.3


------------------------------------------------------------------------------
Dive into the World of Parallel Programming! The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to