summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/Disk/UdfDxe
diff options
context:
space:
mode:
authorkx <kx@radix.pro>2024-06-04 06:43:08 +0300
committerkx <kx@radix.pro>2024-06-04 06:43:08 +0300
commit7e2ccccace24636f29ddc210b94606abd4c7e42b (patch)
tree545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Universal/Disk/UdfDxe
parent27b044605cd5f6b33a3d231576003850b3fe305b (diff)
downloadedk2-trunk.tar.xz
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Universal/Disk/UdfDxe')
-rw-r--r--MdeModulePkg/Universal/Disk/UdfDxe/ComponentName.c358
-rw-r--r--MdeModulePkg/Universal/Disk/UdfDxe/File.c1834
-rw-r--r--MdeModulePkg/Universal/Disk/UdfDxe/FileName.c428
-rw-r--r--MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c5972
-rw-r--r--MdeModulePkg/Universal/Disk/UdfDxe/Udf.c668
-rw-r--r--MdeModulePkg/Universal/Disk/UdfDxe/Udf.h2432
-rw-r--r--MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf124
7 files changed, 5908 insertions, 5908 deletions
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/ComponentName.c b/MdeModulePkg/Universal/Disk/UdfDxe/ComponentName.c
index 89d3eaf341..025cf1fc31 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/ComponentName.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/ComponentName.c
@@ -1,179 +1,179 @@
-/** @file
- UEFI Component Name protocol for UDF/ECMA-167 file system driver.
-
- Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-**/
-
-#include "Udf.h"
-
-//
-// EFI Component Name Protocol
-//
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUdfComponentName = {
- UdfComponentNameGetDriverName,
- UdfComponentNameGetControllerName,
- "eng"
-};
-
-//
-// EFI Component Name 2 Protocol
-//
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUdfComponentName2 = {
- (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UdfComponentNameGetDriverName,
- (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UdfComponentNameGetControllerName,
- "en"
-};
-
-//
-// Driver name table for Udf module.
-// It is shared by the implementation of ComponentName & ComponentName2 Protocol.
-//
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUdfDriverNameTable[] = {
- {
- "eng;en",
- L"UDF File System Driver"
- },
- {
- NULL,
- NULL
- }
-};
-
-/**
- Retrieves a Unicode string that is the user readable name of the driver.
-
- This function retrieves the user readable name of a driver in the form of a
- Unicode string. If the driver specified by This has a user readable name in
- the language specified by Language, then a pointer to the driver name is
- returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
- by This does not support the language specified by Language,
- then EFI_UNSUPPORTED is returned.
-
- @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
- EFI_COMPONENT_NAME_PROTOCOL instance.
-
- @param Language[in] A pointer to a Null-terminated ASCII string
- array indicating the language. This is the
- language of the driver name that the caller is
- requesting, and it must match one of the
- languages specified in SupportedLanguages. The
- number of languages supported by a driver is up
- to the driver writer. Language is specified
- in RFC 4646 or ISO 639-2 language code format.
-
- @param DriverName[out] A pointer to the Unicode string to return.
- This Unicode string is the name of the
- driver specified by This in the language
- specified by Language.
-
- @retval EFI_SUCCESS The Unicode string for the Driver specified by
- This and the language specified by Language was
- returned in DriverName.
-
- @retval EFI_INVALID_PARAMETER Language is NULL.
-
- @retval EFI_INVALID_PARAMETER DriverName is NULL.
-
- @retval EFI_UNSUPPORTED The driver specified by This does not support
- the language specified by Language.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfComponentNameGetDriverName (
- IN EFI_COMPONENT_NAME_PROTOCOL *This,
- IN CHAR8 *Language,
- OUT CHAR16 **DriverName
- )
-{
- return LookupUnicodeString2 (
- Language,
- This->SupportedLanguages,
- mUdfDriverNameTable,
- DriverName,
- (BOOLEAN)(This == &gUdfComponentName)
- );
-}
-
-/**
- Retrieves a Unicode string that is the user readable name of the controller
- that is being managed by a driver.
-
- This function retrieves the user readable name of the controller specified by
- ControllerHandle and ChildHandle in the form of a Unicode string. If the
- driver specified by This has a user readable name in the language specified by
- Language, then a pointer to the controller name is returned in ControllerName,
- and EFI_SUCCESS is returned. If the driver specified by This is not currently
- managing the controller specified by ControllerHandle and ChildHandle,
- then EFI_UNSUPPORTED is returned. If the driver specified by This does not
- support the language specified by Language, then EFI_UNSUPPORTED is returned.
-
- @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
- EFI_COMPONENT_NAME_PROTOCOL instance.
-
- @param ControllerHandle[in] The handle of a controller that the driver
- specified by This is managing. This handle
- specifies the controller whose name is to be
- returned.
-
- @param ChildHandle[in] The handle of the child controller to retrieve
- the name of. This is an optional parameter that
- may be NULL. It will be NULL for device
- drivers. It will also be NULL for a bus drivers
- that wish to retrieve the name of the bus
- controller. It will not be NULL for a bus
- driver that wishes to retrieve the name of a
- child controller.
-
- @param Language[in] A pointer to a Null-terminated ASCII string
- array indicating the language. This is the
- language of the driver name that the caller is
- requesting, and it must match one of the
- languages specified in SupportedLanguages. The
- number of languages supported by a driver is up
- to the driver writer. Language is specified in
- RFC 4646 or ISO 639-2 language code format.
-
- @param ControllerName[out] A pointer to the Unicode string to return.
- This Unicode string is the name of the
- controller specified by ControllerHandle and
- ChildHandle in the language specified by
- Language from the point of view of the driver
- specified by This.
-
- @retval EFI_SUCCESS The Unicode string for the user readable name in
- the language specified by Language for the
- driver specified by This was returned in
- DriverName.
-
- @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
-
- @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
- EFI_HANDLE.
-
- @retval EFI_INVALID_PARAMETER Language is NULL.
-
- @retval EFI_INVALID_PARAMETER ControllerName is NULL.
-
- @retval EFI_UNSUPPORTED The driver specified by This is not currently
- managing the controller specified by
- ControllerHandle and ChildHandle.
-
- @retval EFI_UNSUPPORTED The driver specified by This does not support
- the language specified by Language.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfComponentNameGetControllerName (
- IN EFI_COMPONENT_NAME_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_HANDLE ChildHandle OPTIONAL,
- IN CHAR8 *Language,
- OUT CHAR16 **ControllerName
- )
-{
- return EFI_UNSUPPORTED;
-}
+/** @file
+ UEFI Component Name protocol for UDF/ECMA-167 file system driver.
+
+ Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Udf.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUdfComponentName = {
+ UdfComponentNameGetDriverName,
+ UdfComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUdfComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UdfComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UdfComponentNameGetControllerName,
+ "en"
+};
+
+//
+// Driver name table for Udf module.
+// It is shared by the implementation of ComponentName & ComponentName2 Protocol.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUdfDriverNameTable[] = {
+ {
+ "eng;en",
+ L"UDF File System Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mUdfDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gUdfComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/File.c b/MdeModulePkg/Universal/Disk/UdfDxe/File.c
index ca2f3e0766..d6c5028a3a 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/File.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/File.c
@@ -1,917 +1,917 @@
-/** @file
- Handle operations in files and directories from UDF/ECMA-167 file systems.
-
- Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-**/
-
-#include "Udf.h"
-
-EFI_FILE_PROTOCOL gUdfFileIoOps = {
- EFI_FILE_PROTOCOL_REVISION,
- UdfOpen,
- UdfClose,
- UdfDelete,
- UdfRead,
- UdfWrite,
- UdfGetPosition,
- UdfSetPosition,
- UdfGetInfo,
- UdfSetInfo,
- UdfFlush,
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-#define _ROOT_FILE(_PrivData) (_PrivData)->Root
-#define _PARENT_FILE(_PrivData) \
- ((_PrivData)->IsRootDirectory ? (_PrivData)->Root : &(_PrivData)->File)
-#define _FILE(_PrivData) _PARENT_FILE(_PrivData)
-
-/**
- Open the root directory on a volume.
-
- @param This Protocol instance pointer.
- @param Root Returns an Open file handle for the root directory
-
- @retval EFI_SUCCESS The device was opened.
- @retval EFI_UNSUPPORTED This volume does not support the file system.
- @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_ACCESS_DENIED The service denied access to the file.
- @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of
- resources.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfOpenVolume (
- IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
- OUT EFI_FILE_PROTOCOL **Root
- )
-{
- EFI_TPL OldTpl;
- EFI_STATUS Status;
- PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;
- PRIVATE_UDF_FILE_DATA *PrivFileData;
-
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
-
- if ((This == NULL) || (Root == NULL)) {
- Status = EFI_INVALID_PARAMETER;
- goto Error_Invalid_Params;
- }
-
- PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (This);
-
- if (PrivFsData->OpenFiles == 0) {
- //
- // There is no more open files. Read volume information again since it was
- // cleaned up on the last UdfClose() call.
- //
- Status = ReadUdfVolumeInformation (
- PrivFsData->BlockIo,
- PrivFsData->DiskIo,
- &PrivFsData->Volume
- );
- if (EFI_ERROR (Status)) {
- goto Error_Read_Udf_Volume;
- }
- }
-
- CleanupFileInformation (&PrivFsData->Root);
-
- //
- // Find root directory file.
- //
- Status = FindRootDirectory (
- PrivFsData->BlockIo,
- PrivFsData->DiskIo,
- &PrivFsData->Volume,
- &PrivFsData->Root
- );
- if (EFI_ERROR (Status)) {
- goto Error_Find_Root_Dir;
- }
-
- PrivFileData =
- (PRIVATE_UDF_FILE_DATA *)AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA));
- if (PrivFileData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error_Alloc_Priv_File_Data;
- }
-
- PrivFileData->Signature = PRIVATE_UDF_FILE_DATA_SIGNATURE;
- PrivFileData->SimpleFs = This;
- PrivFileData->Root = &PrivFsData->Root;
- PrivFileData->IsRootDirectory = TRUE;
-
- CopyMem (
- (VOID *)&PrivFileData->FileIo,
- (VOID *)&gUdfFileIoOps,
- sizeof (EFI_FILE_PROTOCOL)
- );
-
- *Root = &PrivFileData->FileIo;
-
- PrivFsData->OpenFiles++;
-
- gBS->RestoreTPL (OldTpl);
-
- return EFI_SUCCESS;
-
-Error_Alloc_Priv_File_Data:
- CleanupFileInformation (&PrivFsData->Root);
-
-Error_Find_Root_Dir:
-
-Error_Read_Udf_Volume:
-Error_Invalid_Params:
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-/**
- Opens a new file relative to the source file's location.
-
- @param This The protocol instance pointer.
- @param NewHandle Returns File Handle for FileName.
- @param FileName Null terminated string. "\", ".", and ".." are supported.
- @param OpenMode Open mode for file.
- @param Attributes Only used for EFI_FILE_MODE_CREATE.
-
- @retval EFI_SUCCESS The device was opened.
- @retval EFI_NOT_FOUND The specified file could not be found on the
- device.
- @retval EFI_NO_MEDIA The device has no media.
- @retval EFI_MEDIA_CHANGED The media has changed.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_ACCESS_DENIED The service denied access to the file.
- @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of
- resources.
- @retval EFI_VOLUME_FULL The volume is full.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfOpen (
- IN EFI_FILE_PROTOCOL *This,
- OUT EFI_FILE_PROTOCOL **NewHandle,
- IN CHAR16 *FileName,
- IN UINT64 OpenMode,
- IN UINT64 Attributes
- )
-{
- EFI_TPL OldTpl;
- EFI_STATUS Status;
- PRIVATE_UDF_FILE_DATA *PrivFileData;
- PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;
- CHAR16 FilePath[UDF_PATH_LENGTH];
- UDF_FILE_INFO File;
- PRIVATE_UDF_FILE_DATA *NewPrivFileData;
- CHAR16 *TempFileName;
-
- ZeroMem (FilePath, sizeof FilePath);
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
-
- if ((This == NULL) || (NewHandle == NULL) || (FileName == NULL)) {
- Status = EFI_INVALID_PARAMETER;
- goto Error_Invalid_Params;
- }
-
- if (OpenMode != EFI_FILE_MODE_READ) {
- Status = EFI_WRITE_PROTECTED;
- goto Error_Invalid_Params;
- }
-
- PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
-
- PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);
-
- //
- // Build full path
- //
- if (*FileName == L'\\') {
- StrCpyS (FilePath, UDF_PATH_LENGTH, FileName);
- } else {
- StrCpyS (FilePath, UDF_PATH_LENGTH, PrivFileData->AbsoluteFileName);
- StrCatS (FilePath, UDF_PATH_LENGTH, L"\\");
- StrCatS (FilePath, UDF_PATH_LENGTH, FileName);
- }
-
- MangleFileName (FilePath);
- if (FilePath[0] == L'\0') {
- Status = EFI_NOT_FOUND;
- goto Error_Bad_FileName;
- }
-
- Status = FindFile (
- PrivFsData->BlockIo,
- PrivFsData->DiskIo,
- &PrivFsData->Volume,
- FilePath,
- _ROOT_FILE (PrivFileData),
- _PARENT_FILE (PrivFileData),
- &_PARENT_FILE (PrivFileData)->FileIdentifierDesc->Icb,
- &File
- );
- if (EFI_ERROR (Status)) {
- goto Error_Find_File;
- }
-
- NewPrivFileData =
- (PRIVATE_UDF_FILE_DATA *)AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA));
- if (NewPrivFileData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error_Alloc_New_Priv_File_Data;
- }
-
- CopyMem (
- (VOID *)NewPrivFileData,
- (VOID *)PrivFileData,
- sizeof (PRIVATE_UDF_FILE_DATA)
- );
- CopyMem ((VOID *)&NewPrivFileData->File, &File, sizeof (UDF_FILE_INFO));
-
- NewPrivFileData->IsRootDirectory = FALSE;
-
- StrCpyS (NewPrivFileData->AbsoluteFileName, UDF_PATH_LENGTH, FilePath);
- FileName = NewPrivFileData->AbsoluteFileName;
-
- while ((TempFileName = StrStr (FileName, L"\\")) != NULL) {
- FileName = TempFileName + 1;
- }
-
- StrCpyS (NewPrivFileData->FileName, UDF_FILENAME_LENGTH, FileName);
-
- Status = GetFileSize (
- PrivFsData->BlockIo,
- PrivFsData->DiskIo,
- &PrivFsData->Volume,
- &NewPrivFileData->File,
- &NewPrivFileData->FileSize
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: GetFileSize() fails with status - %r.\n",
- __func__,
- Status
- ));
- goto Error_Get_File_Size;
- }
-
- NewPrivFileData->FilePosition = 0;
- ZeroMem (
- (VOID *)&NewPrivFileData->ReadDirInfo,
- sizeof (UDF_READ_DIRECTORY_INFO)
- );
-
- *NewHandle = &NewPrivFileData->FileIo;
-
- PrivFsData->OpenFiles++;
-
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-
-Error_Get_File_Size:
- FreePool ((VOID *)NewPrivFileData);
-
-Error_Alloc_New_Priv_File_Data:
- CleanupFileInformation (&File);
-
-Error_Find_File:
-Error_Bad_FileName:
-Error_Invalid_Params:
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-/**
- Read data from the file.
-
- @param This Protocol instance pointer.
- @param BufferSize On input size of buffer, on output amount of data in
- buffer.
- @param Buffer The buffer in which data is read.
-
- @retval EFI_SUCCESS Data was read.
- @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_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains
- required size.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfRead (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- 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];
- UINT64 FileSize;
- UINT64 BufferSizeUint64;
-
- ZeroMem (FileName, sizeof FileName);
- 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;
- }
-
- BufferSizeUint64 = *BufferSize;
-
- Status = ReadFileData (
- BlockIo,
- DiskIo,
- Volume,
- Parent,
- PrivFileData->FileSize,
- &PrivFileData->FilePosition,
- Buffer,
- &BufferSizeUint64
- );
- ASSERT (BufferSizeUint64 <= MAX_UINTN);
- *BufferSize = (UINTN)BufferSizeUint64;
- } 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;
- }
-
- //
- // After calling function ReadDirectoryEntry(), if 'NewFileIdentifierDesc'
- // is NULL, then the 'Status' must be EFI_OUT_OF_RESOURCES. Hence, if the
- // code reaches here, 'NewFileIdentifierDesc' must be not NULL.
- //
- // The ASSERT here is for addressing a false positive NULL pointer
- // dereference issue raised from static analysis.
- //
- ASSERT (NewFileIdentifierDesc != NULL);
-
- 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;
- }
-
- ASSERT (NewFileEntryData != NULL);
-
- if (FE_ICB_FILE_TYPE (NewFileEntryData) == UdfFileEntrySymlink) {
- 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, ARRAY_SIZE (FileName), 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, ARRAY_SIZE (FileName), 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)) {
- //
- // Code should never reach here.
- //
- ASSERT (FALSE);
- 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;
-}
-
-/**
- Close the file handle.
-
- @param This Protocol instance pointer.
-
- @retval EFI_SUCCESS The file was closed.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfClose (
- IN EFI_FILE_PROTOCOL *This
- )
-{
- EFI_TPL OldTpl;
- EFI_STATUS Status;
- PRIVATE_UDF_FILE_DATA *PrivFileData;
-
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
-
- Status = EFI_SUCCESS;
-
- if (This == NULL) {
- Status = EFI_INVALID_PARAMETER;
- goto Exit;
- }
-
- PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
-
- if (!PrivFileData->IsRootDirectory) {
- CleanupFileInformation (&PrivFileData->File);
-
- if (PrivFileData->ReadDirInfo.DirectoryData != NULL) {
- FreePool (PrivFileData->ReadDirInfo.DirectoryData);
- }
- }
-
- FreePool ((VOID *)PrivFileData);
-
-Exit:
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-/**
- Close and delete the file handle.
-
- @param This Protocol instance pointer.
-
- @retval EFI_SUCCESS The file was closed and deleted.
- @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not
- deleted.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfDelete (
- IN EFI_FILE_PROTOCOL *This
- )
-{
- PRIVATE_UDF_FILE_DATA *PrivFileData;
-
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
-
- (VOID)PrivFileData->FileIo.Close (This);
-
- return EFI_WARN_DELETE_FAILURE;
-}
-
-/**
- Write data to a file.
-
- @param This Protocol instance pointer.
- @param BufferSize On input size of buffer, on output amount of data in
- buffer.
- @param Buffer The buffer in which data to write.
-
- @retval EFI_SUCCESS Data was written.
- @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
- @retval EFI_NO_MEDIA The device has no media.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_WRITE_PROTECTED The device is write protected.
- @retval EFI_ACCESS_DENIED The file was open for read only.
- @retval EFI_VOLUME_FULL The volume is full.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfWrite (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-/**
- Get file's current position.
-
- @param This Protocol instance pointer.
- @param Position Byte position from the start of the file.
-
- @retval EFI_SUCCESS Position was updated.
- @retval EFI_UNSUPPORTED Seek request for directories is not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfGetPosition (
- IN EFI_FILE_PROTOCOL *This,
- OUT UINT64 *Position
- )
-{
- 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;
-}
-
-/**
- Set file's current position.
-
- @param This Protocol instance pointer.
- @param Position Byte position from the start of the file.
-
- @retval EFI_SUCCESS Position was updated.
- @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfSetPosition (
- IN EFI_FILE_PROTOCOL *This,
- IN UINT64 Position
- )
-{
- 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 = _FILE (PrivFileData)->FileIdentifierDesc;
- ASSERT (FileIdentifierDesc != NULL);
- 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;
- } else {
- PrivFileData->FilePosition = Position;
- }
-
- Status = EFI_SUCCESS;
- }
-
- return Status;
-}
-
-/**
- Get information about a file.
-
- @param This Protocol instance pointer.
- @param InformationType Type of information to return in Buffer.
- @param BufferSize On input size of buffer, on output amount of data in
- buffer.
- @param Buffer The buffer to return data.
-
- @retval EFI_SUCCESS Data was returned.
- @retval EFI_UNSUPPORTED InformationType is 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_WRITE_PROTECTED The device is write protected.
- @retval EFI_ACCESS_DENIED The file was open for read only.
- @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in
- BufferSize.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfGetInfo (
- IN EFI_FILE_PROTOCOL *This,
- IN EFI_GUID *InformationType,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- EFI_STATUS Status;
- PRIVATE_UDF_FILE_DATA *PrivFileData;
- PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;
- EFI_FILE_SYSTEM_INFO *FileSystemInfo;
- UINTN FileSystemInfoLength;
- UINT64 VolumeSize;
- UINT64 FreeSpaceSize;
- EFI_FILE_SYSTEM_VOLUME_LABEL *FileSystemVolumeLabel;
- UINTN FileSystemVolumeLabelLength;
- CHAR16 VolumeLabel[64];
-
- if ((This == NULL) || (InformationType == NULL) || (BufferSize == NULL) ||
- ((*BufferSize != 0) && (Buffer == NULL)))
- {
- return EFI_INVALID_PARAMETER;
- }
-
- PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
-
- PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);
-
- Status = EFI_UNSUPPORTED;
-
- if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
- Status = SetFileInfo (
- _FILE (PrivFileData),
- PrivFileData->FileSize,
- PrivFileData->FileName,
- BufferSize,
- Buffer
- );
- } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
- Status = GetVolumeLabel (&PrivFsData->Volume, ARRAY_SIZE (VolumeLabel), VolumeLabel);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- FileSystemInfoLength = StrSize (VolumeLabel) +
- sizeof (EFI_FILE_SYSTEM_INFO);
- if (*BufferSize < FileSystemInfoLength) {
- *BufferSize = FileSystemInfoLength;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- FileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;
- StrCpyS (
- FileSystemInfo->VolumeLabel,
- (*BufferSize - SIZE_OF_EFI_FILE_SYSTEM_INFO) / sizeof (CHAR16),
- VolumeLabel
- );
- Status = GetVolumeSize (
- PrivFsData->BlockIo,
- PrivFsData->DiskIo,
- &PrivFsData->Volume,
- &VolumeSize,
- &FreeSpaceSize
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- FileSystemInfo->Size = FileSystemInfoLength;
- FileSystemInfo->ReadOnly = TRUE;
- FileSystemInfo->BlockSize =
- PrivFsData->Volume.LogicalVolDesc.LogicalBlockSize;
- FileSystemInfo->VolumeSize = VolumeSize;
- FileSystemInfo->FreeSpace = FreeSpaceSize;
-
- *BufferSize = FileSystemInfoLength;
- Status = EFI_SUCCESS;
- } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
- Status = GetVolumeLabel (&PrivFsData->Volume, ARRAY_SIZE (VolumeLabel), VolumeLabel);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- FileSystemVolumeLabelLength = StrSize (VolumeLabel) +
- sizeof (EFI_FILE_SYSTEM_VOLUME_LABEL);
- if (*BufferSize < FileSystemVolumeLabelLength) {
- *BufferSize = FileSystemVolumeLabelLength;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- FileSystemVolumeLabel = (EFI_FILE_SYSTEM_VOLUME_LABEL *)Buffer;
- StrCpyS (
- FileSystemVolumeLabel->VolumeLabel,
- (*BufferSize - SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL) / sizeof (CHAR16),
- VolumeLabel
- );
- Status = EFI_SUCCESS;
- }
-
- return Status;
-}
-
-/**
- Set information about a file.
-
- @param This Protocol instance pointer.
- @param InformationType Type of information in Buffer.
- @param BufferSize Size of buffer.
- @param Buffer The data to write.
-
- @retval EFI_SUCCESS Data was set.
- @retval EFI_UNSUPPORTED InformationType is 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_WRITE_PROTECTED The device is write protected.
- @retval EFI_ACCESS_DENIED The file was open for read only.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfSetInfo (
- IN EFI_FILE_PROTOCOL *This,
- IN EFI_GUID *InformationType,
- IN UINTN BufferSize,
- IN VOID *Buffer
- )
-{
- return EFI_WRITE_PROTECTED;
-}
-
-/**
- Flush data back for the file handle.
-
- @param This Protocol instance pointer.
-
- @retval EFI_SUCCESS Data was flushed.
- @retval EFI_UNSUPPORTED Writes to Open directory are 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_WRITE_PROTECTED The device is write protected.
- @retval EFI_ACCESS_DENIED The file was open for read only.
- @retval EFI_VOLUME_FULL The volume is full.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfFlush (
- IN EFI_FILE_PROTOCOL *This
- )
-{
- return EFI_WRITE_PROTECTED;
-}
+/** @file
+ Handle operations in files and directories from UDF/ECMA-167 file systems.
+
+ Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
+ Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Udf.h"
+
+EFI_FILE_PROTOCOL gUdfFileIoOps = {
+ EFI_FILE_PROTOCOL_REVISION,
+ UdfOpen,
+ UdfClose,
+ UdfDelete,
+ UdfRead,
+ UdfWrite,
+ UdfGetPosition,
+ UdfSetPosition,
+ UdfGetInfo,
+ UdfSetInfo,
+ UdfFlush,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+#define _ROOT_FILE(_PrivData) (_PrivData)->Root
+#define _PARENT_FILE(_PrivData) \
+ ((_PrivData)->IsRootDirectory ? (_PrivData)->Root : &(_PrivData)->File)
+#define _FILE(_PrivData) _PARENT_FILE(_PrivData)
+
+/**
+ Open the root directory on a volume.
+
+ @param This Protocol instance pointer.
+ @param Root Returns an Open file handle for the root directory
+
+ @retval EFI_SUCCESS The device was opened.
+ @retval EFI_UNSUPPORTED This volume does not support the file system.
+ @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_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of
+ resources.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfOpenVolume (
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **Root
+ )
+{
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;
+ PRIVATE_UDF_FILE_DATA *PrivFileData;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ if ((This == NULL) || (Root == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Error_Invalid_Params;
+ }
+
+ PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (This);
+
+ if (PrivFsData->OpenFiles == 0) {
+ //
+ // There is no more open files. Read volume information again since it was
+ // cleaned up on the last UdfClose() call.
+ //
+ Status = ReadUdfVolumeInformation (
+ PrivFsData->BlockIo,
+ PrivFsData->DiskIo,
+ &PrivFsData->Volume
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Read_Udf_Volume;
+ }
+ }
+
+ CleanupFileInformation (&PrivFsData->Root);
+
+ //
+ // Find root directory file.
+ //
+ Status = FindRootDirectory (
+ PrivFsData->BlockIo,
+ PrivFsData->DiskIo,
+ &PrivFsData->Volume,
+ &PrivFsData->Root
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Find_Root_Dir;
+ }
+
+ PrivFileData =
+ (PRIVATE_UDF_FILE_DATA *)AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA));
+ if (PrivFileData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error_Alloc_Priv_File_Data;
+ }
+
+ PrivFileData->Signature = PRIVATE_UDF_FILE_DATA_SIGNATURE;
+ PrivFileData->SimpleFs = This;
+ PrivFileData->Root = &PrivFsData->Root;
+ PrivFileData->IsRootDirectory = TRUE;
+
+ CopyMem (
+ (VOID *)&PrivFileData->FileIo,
+ (VOID *)&gUdfFileIoOps,
+ sizeof (EFI_FILE_PROTOCOL)
+ );
+
+ *Root = &PrivFileData->FileIo;
+
+ PrivFsData->OpenFiles++;
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+
+Error_Alloc_Priv_File_Data:
+ CleanupFileInformation (&PrivFsData->Root);
+
+Error_Find_Root_Dir:
+
+Error_Read_Udf_Volume:
+Error_Invalid_Params:
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+/**
+ Opens a new file relative to the source file's location.
+
+ @param This The protocol instance pointer.
+ @param NewHandle Returns File Handle for FileName.
+ @param FileName Null terminated string. "\", ".", and ".." are supported.
+ @param OpenMode Open mode for file.
+ @param Attributes Only used for EFI_FILE_MODE_CREATE.
+
+ @retval EFI_SUCCESS The device was opened.
+ @retval EFI_NOT_FOUND The specified file could not be found on the
+ device.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_MEDIA_CHANGED The media has changed.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of
+ resources.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfOpen (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ )
+{
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ PRIVATE_UDF_FILE_DATA *PrivFileData;
+ PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;
+ CHAR16 FilePath[UDF_PATH_LENGTH];
+ UDF_FILE_INFO File;
+ PRIVATE_UDF_FILE_DATA *NewPrivFileData;
+ CHAR16 *TempFileName;
+
+ ZeroMem (FilePath, sizeof FilePath);
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ if ((This == NULL) || (NewHandle == NULL) || (FileName == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Error_Invalid_Params;
+ }
+
+ if (OpenMode != EFI_FILE_MODE_READ) {
+ Status = EFI_WRITE_PROTECTED;
+ goto Error_Invalid_Params;
+ }
+
+ PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
+
+ PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);
+
+ //
+ // Build full path
+ //
+ if (*FileName == L'\\') {
+ StrCpyS (FilePath, UDF_PATH_LENGTH, FileName);
+ } else {
+ StrCpyS (FilePath, UDF_PATH_LENGTH, PrivFileData->AbsoluteFileName);
+ StrCatS (FilePath, UDF_PATH_LENGTH, L"\\");
+ StrCatS (FilePath, UDF_PATH_LENGTH, FileName);
+ }
+
+ MangleFileName (FilePath);
+ if (FilePath[0] == L'\0') {
+ Status = EFI_NOT_FOUND;
+ goto Error_Bad_FileName;
+ }
+
+ Status = FindFile (
+ PrivFsData->BlockIo,
+ PrivFsData->DiskIo,
+ &PrivFsData->Volume,
+ FilePath,
+ _ROOT_FILE (PrivFileData),
+ _PARENT_FILE (PrivFileData),
+ &_PARENT_FILE (PrivFileData)->FileIdentifierDesc->Icb,
+ &File
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Find_File;
+ }
+
+ NewPrivFileData =
+ (PRIVATE_UDF_FILE_DATA *)AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA));
+ if (NewPrivFileData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error_Alloc_New_Priv_File_Data;
+ }
+
+ CopyMem (
+ (VOID *)NewPrivFileData,
+ (VOID *)PrivFileData,
+ sizeof (PRIVATE_UDF_FILE_DATA)
+ );
+ CopyMem ((VOID *)&NewPrivFileData->File, &File, sizeof (UDF_FILE_INFO));
+
+ NewPrivFileData->IsRootDirectory = FALSE;
+
+ StrCpyS (NewPrivFileData->AbsoluteFileName, UDF_PATH_LENGTH, FilePath);
+ FileName = NewPrivFileData->AbsoluteFileName;
+
+ while ((TempFileName = StrStr (FileName, L"\\")) != NULL) {
+ FileName = TempFileName + 1;
+ }
+
+ StrCpyS (NewPrivFileData->FileName, UDF_FILENAME_LENGTH, FileName);
+
+ Status = GetFileSize (
+ PrivFsData->BlockIo,
+ PrivFsData->DiskIo,
+ &PrivFsData->Volume,
+ &NewPrivFileData->File,
+ &NewPrivFileData->FileSize
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: GetFileSize() fails with status - %r.\n",
+ __func__,
+ Status
+ ));
+ goto Error_Get_File_Size;
+ }
+
+ NewPrivFileData->FilePosition = 0;
+ ZeroMem (
+ (VOID *)&NewPrivFileData->ReadDirInfo,
+ sizeof (UDF_READ_DIRECTORY_INFO)
+ );
+
+ *NewHandle = &NewPrivFileData->FileIo;
+
+ PrivFsData->OpenFiles++;
+
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+
+Error_Get_File_Size:
+ FreePool ((VOID *)NewPrivFileData);
+
+Error_Alloc_New_Priv_File_Data:
+ CleanupFileInformation (&File);
+
+Error_Find_File:
+Error_Bad_FileName:
+Error_Invalid_Params:
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+/**
+ Read data from the file.
+
+ @param This Protocol instance pointer.
+ @param BufferSize On input size of buffer, on output amount of data in
+ buffer.
+ @param Buffer The buffer in which data is read.
+
+ @retval EFI_SUCCESS Data was read.
+ @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_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains
+ required size.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfRead (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ 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];
+ UINT64 FileSize;
+ UINT64 BufferSizeUint64;
+
+ ZeroMem (FileName, sizeof FileName);
+ 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;
+ }
+
+ BufferSizeUint64 = *BufferSize;
+
+ Status = ReadFileData (
+ BlockIo,
+ DiskIo,
+ Volume,
+ Parent,
+ PrivFileData->FileSize,
+ &PrivFileData->FilePosition,
+ Buffer,
+ &BufferSizeUint64
+ );
+ ASSERT (BufferSizeUint64 <= MAX_UINTN);
+ *BufferSize = (UINTN)BufferSizeUint64;
+ } 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;
+ }
+
+ //
+ // After calling function ReadDirectoryEntry(), if 'NewFileIdentifierDesc'
+ // is NULL, then the 'Status' must be EFI_OUT_OF_RESOURCES. Hence, if the
+ // code reaches here, 'NewFileIdentifierDesc' must be not NULL.
+ //
+ // The ASSERT here is for addressing a false positive NULL pointer
+ // dereference issue raised from static analysis.
+ //
+ ASSERT (NewFileIdentifierDesc != NULL);
+
+ 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;
+ }
+
+ ASSERT (NewFileEntryData != NULL);
+
+ if (FE_ICB_FILE_TYPE (NewFileEntryData) == UdfFileEntrySymlink) {
+ 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, ARRAY_SIZE (FileName), 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, ARRAY_SIZE (FileName), 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)) {
+ //
+ // Code should never reach here.
+ //
+ ASSERT (FALSE);
+ 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;
+}
+
+/**
+ Close the file handle.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The file was closed.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfClose (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ PRIVATE_UDF_FILE_DATA *PrivFileData;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Status = EFI_SUCCESS;
+
+ if (This == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
+
+ if (!PrivFileData->IsRootDirectory) {
+ CleanupFileInformation (&PrivFileData->File);
+
+ if (PrivFileData->ReadDirInfo.DirectoryData != NULL) {
+ FreePool (PrivFileData->ReadDirInfo.DirectoryData);
+ }
+ }
+
+ FreePool ((VOID *)PrivFileData);
+
+Exit:
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+/**
+ Close and delete the file handle.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The file was closed and deleted.
+ @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not
+ deleted.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfDelete (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ PRIVATE_UDF_FILE_DATA *PrivFileData;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
+
+ (VOID)PrivFileData->FileIo.Close (This);
+
+ return EFI_WARN_DELETE_FAILURE;
+}
+
+/**
+ Write data to a file.
+
+ @param This Protocol instance pointer.
+ @param BufferSize On input size of buffer, on output amount of data in
+ buffer.
+ @param Buffer The buffer in which data to write.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfWrite (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Get file's current position.
+
+ @param This Protocol instance pointer.
+ @param Position Byte position from the start of the file.
+
+ @retval EFI_SUCCESS Position was updated.
+ @retval EFI_UNSUPPORTED Seek request for directories is not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfGetPosition (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT UINT64 *Position
+ )
+{
+ 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;
+}
+
+/**
+ Set file's current position.
+
+ @param This Protocol instance pointer.
+ @param Position Byte position from the start of the file.
+
+ @retval EFI_SUCCESS Position was updated.
+ @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfSetPosition (
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINT64 Position
+ )
+{
+ 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 = _FILE (PrivFileData)->FileIdentifierDesc;
+ ASSERT (FileIdentifierDesc != NULL);
+ 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;
+ } else {
+ PrivFileData->FilePosition = Position;
+ }
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Get information about a file.
+
+ @param This Protocol instance pointer.
+ @param InformationType Type of information to return in Buffer.
+ @param BufferSize On input size of buffer, on output amount of data in
+ buffer.
+ @param Buffer The buffer to return data.
+
+ @retval EFI_SUCCESS Data was returned.
+ @retval EFI_UNSUPPORTED InformationType is 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_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in
+ BufferSize.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfGetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ PRIVATE_UDF_FILE_DATA *PrivFileData;
+ PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;
+ EFI_FILE_SYSTEM_INFO *FileSystemInfo;
+ UINTN FileSystemInfoLength;
+ UINT64 VolumeSize;
+ UINT64 FreeSpaceSize;
+ EFI_FILE_SYSTEM_VOLUME_LABEL *FileSystemVolumeLabel;
+ UINTN FileSystemVolumeLabelLength;
+ CHAR16 VolumeLabel[64];
+
+ if ((This == NULL) || (InformationType == NULL) || (BufferSize == NULL) ||
+ ((*BufferSize != 0) && (Buffer == NULL)))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
+
+ PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);
+
+ Status = EFI_UNSUPPORTED;
+
+ if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
+ Status = SetFileInfo (
+ _FILE (PrivFileData),
+ PrivFileData->FileSize,
+ PrivFileData->FileName,
+ BufferSize,
+ Buffer
+ );
+ } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
+ Status = GetVolumeLabel (&PrivFsData->Volume, ARRAY_SIZE (VolumeLabel), VolumeLabel);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FileSystemInfoLength = StrSize (VolumeLabel) +
+ sizeof (EFI_FILE_SYSTEM_INFO);
+ if (*BufferSize < FileSystemInfoLength) {
+ *BufferSize = FileSystemInfoLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ FileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;
+ StrCpyS (
+ FileSystemInfo->VolumeLabel,
+ (*BufferSize - SIZE_OF_EFI_FILE_SYSTEM_INFO) / sizeof (CHAR16),
+ VolumeLabel
+ );
+ Status = GetVolumeSize (
+ PrivFsData->BlockIo,
+ PrivFsData->DiskIo,
+ &PrivFsData->Volume,
+ &VolumeSize,
+ &FreeSpaceSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FileSystemInfo->Size = FileSystemInfoLength;
+ FileSystemInfo->ReadOnly = TRUE;
+ FileSystemInfo->BlockSize =
+ PrivFsData->Volume.LogicalVolDesc.LogicalBlockSize;
+ FileSystemInfo->VolumeSize = VolumeSize;
+ FileSystemInfo->FreeSpace = FreeSpaceSize;
+
+ *BufferSize = FileSystemInfoLength;
+ Status = EFI_SUCCESS;
+ } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
+ Status = GetVolumeLabel (&PrivFsData->Volume, ARRAY_SIZE (VolumeLabel), VolumeLabel);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FileSystemVolumeLabelLength = StrSize (VolumeLabel) +
+ sizeof (EFI_FILE_SYSTEM_VOLUME_LABEL);
+ if (*BufferSize < FileSystemVolumeLabelLength) {
+ *BufferSize = FileSystemVolumeLabelLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ FileSystemVolumeLabel = (EFI_FILE_SYSTEM_VOLUME_LABEL *)Buffer;
+ StrCpyS (
+ FileSystemVolumeLabel->VolumeLabel,
+ (*BufferSize - SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL) / sizeof (CHAR16),
+ VolumeLabel
+ );
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Set information about a file.
+
+ @param This Protocol instance pointer.
+ @param InformationType Type of information in Buffer.
+ @param BufferSize Size of buffer.
+ @param Buffer The data to write.
+
+ @retval EFI_SUCCESS Data was set.
+ @retval EFI_UNSUPPORTED InformationType is 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_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfSetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return EFI_WRITE_PROTECTED;
+}
+
+/**
+ Flush data back for the file handle.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS Data was flushed.
+ @retval EFI_UNSUPPORTED Writes to Open directory are 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_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfFlush (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ return EFI_WRITE_PROTECTED;
+}
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileName.c b/MdeModulePkg/Universal/Disk/UdfDxe/FileName.c
index 6db34a9c8c..4480d1e47c 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/FileName.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileName.c
@@ -1,214 +1,214 @@
-/** @file
- Helper functions for mangling file names in UDF/ECMA-167 file systems.
-
- Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-**/
-
-#include "Udf.h"
-
-/**
- Trim the leading and trailing spaces for a give Unicode string.
-
- @param[in] String The Unicode string to trim.
-
- @return A pointer to the trimmed string.
-
-**/
-CHAR16 *
-TrimString (
- IN CHAR16 *String
- )
-{
- CHAR16 *TempString;
-
- for ( ; *String != L'\0' && *String == L' '; String++) {
- }
-
- TempString = String + StrLen (String) - 1;
- while ((TempString >= String) && (*TempString == L' ')) {
- TempString--;
- }
-
- *(TempString + 1) = L'\0';
-
- return String;
-}
-
-/**
- Replace the content of a Unicode string with the content of another Unicode
- string.
-
- @param[in] Destination A pointer to a Unicode string.
- @param[in] Source A pointer to a Unicode string.
-
-**/
-VOID
-ReplaceLeft (
- IN CHAR16 *Destination,
- IN CONST CHAR16 *Source
- )
-{
- CONST CHAR16 *EndString;
-
- EndString = Source + StrLen (Source);
- while (Source <= EndString) {
- *Destination++ = *Source++;
- }
-}
-
-/**
- Remove one or more consecutive backslashes starting from the second character
- of a given Unicode string.
-
- @param[in] String A pointer to a Unicode string.
-
- @return A pointer to the modified string.
-
-**/
-CHAR16 *
-ExcludeTrailingBackslashes (
- IN CHAR16 *String
- )
-{
- CHAR16 *TempString;
-
- switch (*(String + 1)) {
- case L'\\':
- break;
- case L'\0':
- default:
- String++;
- goto Exit;
- }
-
- TempString = String;
- while (*TempString != L'\0' && *TempString == L'\\') {
- TempString++;
- }
-
- if (TempString - 1 > String) {
- ReplaceLeft (String + 1, TempString);
- }
-
- String++;
-
-Exit:
- return String;
-}
-
-/**
- Mangle a filename by cutting off trailing whitespaces, "\\", "." and "..".
-
- @param[in] FileName Filename.
-
- @retval The mangled Filename.
-
-**/
-CHAR16 *
-MangleFileName (
- IN CHAR16 *FileName
- )
-{
- CHAR16 *FileNameSavedPointer;
- CHAR16 *TempFileName;
- UINTN BackslashesNo;
-
- if ((FileName == NULL) || (*FileName == L'\0')) {
- FileName = NULL;
- goto Exit;
- }
-
- FileName = TrimString (FileName);
- if (*FileName == L'\0') {
- goto Exit;
- }
-
- if ((StrLen (FileName) > 1) && (FileName[StrLen (FileName) - 1] == L'\\')) {
- FileName[StrLen (FileName) - 1] = L'\0';
- }
-
- FileNameSavedPointer = FileName;
-
- if (FileName[0] == L'.') {
- if (FileName[1] == L'.') {
- if (FileName[2] == L'\0') {
- goto Exit;
- } else {
- FileName += 2;
- }
- } else if (FileName[1] == L'\0') {
- goto Exit;
- }
- }
-
- while (*FileName != L'\0') {
- if (*FileName == L'\\') {
- FileName = ExcludeTrailingBackslashes (FileName);
- } else if (*FileName == L'.') {
- switch (*(FileName + 1)) {
- case L'\0':
- *FileName = L'\0';
- break;
- case L'\\':
- TempFileName = FileName + 1;
- TempFileName = ExcludeTrailingBackslashes (TempFileName);
- ReplaceLeft (FileName, TempFileName);
- break;
- case '.':
- if ((*(FileName - 1) != L'\\') && ((*(FileName + 2) != L'\\') ||
- (*(FileName + 2) != L'\0')))
- {
- FileName++;
- continue;
- }
-
- BackslashesNo = 0;
- TempFileName = FileName - 1;
- while (TempFileName >= FileNameSavedPointer) {
- if (*TempFileName == L'\\') {
- if (++BackslashesNo == 2) {
- break;
- }
- }
-
- TempFileName--;
- }
-
- TempFileName++;
-
- if ((*TempFileName == L'.') && (*(TempFileName + 1) == L'.')) {
- FileName += 2;
- } else {
- if (*(FileName + 2) != L'\0') {
- ReplaceLeft (TempFileName, FileName + 3);
- if (*(TempFileName - 1) == L'\\') {
- FileName = TempFileName;
- ExcludeTrailingBackslashes (TempFileName - 1);
- TempFileName = FileName;
- }
- } else {
- *TempFileName = L'\0';
- }
-
- FileName = TempFileName;
- }
-
- break;
- default:
- FileName++;
- }
- } else {
- FileName++;
- }
- }
-
- FileName = FileNameSavedPointer;
- if ((StrLen (FileName) > 1) && (FileName[StrLen (FileName) - 1] == L'\\')) {
- FileName[StrLen (FileName) - 1] = L'\0';
- }
-
-Exit:
- return FileName;
-}
+/** @file
+ Helper functions for mangling file names in UDF/ECMA-167 file systems.
+
+ Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Udf.h"
+
+/**
+ Trim the leading and trailing spaces for a give Unicode string.
+
+ @param[in] String The Unicode string to trim.
+
+ @return A pointer to the trimmed string.
+
+**/
+CHAR16 *
+TrimString (
+ IN CHAR16 *String
+ )
+{
+ CHAR16 *TempString;
+
+ for ( ; *String != L'\0' && *String == L' '; String++) {
+ }
+
+ TempString = String + StrLen (String) - 1;
+ while ((TempString >= String) && (*TempString == L' ')) {
+ TempString--;
+ }
+
+ *(TempString + 1) = L'\0';
+
+ return String;
+}
+
+/**
+ Replace the content of a Unicode string with the content of another Unicode
+ string.
+
+ @param[in] Destination A pointer to a Unicode string.
+ @param[in] Source A pointer to a Unicode string.
+
+**/
+VOID
+ReplaceLeft (
+ IN CHAR16 *Destination,
+ IN CONST CHAR16 *Source
+ )
+{
+ CONST CHAR16 *EndString;
+
+ EndString = Source + StrLen (Source);
+ while (Source <= EndString) {
+ *Destination++ = *Source++;
+ }
+}
+
+/**
+ Remove one or more consecutive backslashes starting from the second character
+ of a given Unicode string.
+
+ @param[in] String A pointer to a Unicode string.
+
+ @return A pointer to the modified string.
+
+**/
+CHAR16 *
+ExcludeTrailingBackslashes (
+ IN CHAR16 *String
+ )
+{
+ CHAR16 *TempString;
+
+ switch (*(String + 1)) {
+ case L'\\':
+ break;
+ case L'\0':
+ default:
+ String++;
+ goto Exit;
+ }
+
+ TempString = String;
+ while (*TempString != L'\0' && *TempString == L'\\') {
+ TempString++;
+ }
+
+ if (TempString - 1 > String) {
+ ReplaceLeft (String + 1, TempString);
+ }
+
+ String++;
+
+Exit:
+ return String;
+}
+
+/**
+ Mangle a filename by cutting off trailing whitespaces, "\\", "." and "..".
+
+ @param[in] FileName Filename.
+
+ @retval The mangled Filename.
+
+**/
+CHAR16 *
+MangleFileName (
+ IN CHAR16 *FileName
+ )
+{
+ CHAR16 *FileNameSavedPointer;
+ CHAR16 *TempFileName;
+ UINTN BackslashesNo;
+
+ if ((FileName == NULL) || (*FileName == L'\0')) {
+ FileName = NULL;
+ goto Exit;
+ }
+
+ FileName = TrimString (FileName);
+ if (*FileName == L'\0') {
+ goto Exit;
+ }
+
+ if ((StrLen (FileName) > 1) && (FileName[StrLen (FileName) - 1] == L'\\')) {
+ FileName[StrLen (FileName) - 1] = L'\0';
+ }
+
+ FileNameSavedPointer = FileName;
+
+ if (FileName[0] == L'.') {
+ if (FileName[1] == L'.') {
+ if (FileName[2] == L'\0') {
+ goto Exit;
+ } else {
+ FileName += 2;
+ }
+ } else if (FileName[1] == L'\0') {
+ goto Exit;
+ }
+ }
+
+ while (*FileName != L'\0') {
+ if (*FileName == L'\\') {
+ FileName = ExcludeTrailingBackslashes (FileName);
+ } else if (*FileName == L'.') {
+ switch (*(FileName + 1)) {
+ case L'\0':
+ *FileName = L'\0';
+ break;
+ case L'\\':
+ TempFileName = FileName + 1;
+ TempFileName = ExcludeTrailingBackslashes (TempFileName);
+ ReplaceLeft (FileName, TempFileName);
+ break;
+ case '.':
+ if ((*(FileName - 1) != L'\\') && ((*(FileName + 2) != L'\\') ||
+ (*(FileName + 2) != L'\0')))
+ {
+ FileName++;
+ continue;
+ }
+
+ BackslashesNo = 0;
+ TempFileName = FileName - 1;
+ while (TempFileName >= FileNameSavedPointer) {
+ if (*TempFileName == L'\\') {
+ if (++BackslashesNo == 2) {
+ break;
+ }
+ }
+
+ TempFileName--;
+ }
+
+ TempFileName++;
+
+ if ((*TempFileName == L'.') && (*(TempFileName + 1) == L'.')) {
+ FileName += 2;
+ } else {
+ if (*(FileName + 2) != L'\0') {
+ ReplaceLeft (TempFileName, FileName + 3);
+ if (*(TempFileName - 1) == L'\\') {
+ FileName = TempFileName;
+ ExcludeTrailingBackslashes (TempFileName - 1);
+ TempFileName = FileName;
+ }
+ } else {
+ *TempFileName = L'\0';
+ }
+
+ FileName = TempFileName;
+ }
+
+ break;
+ default:
+ FileName++;
+ }
+ } else {
+ FileName++;
+ }
+ }
+
+ FileName = FileNameSavedPointer;
+ if ((StrLen (FileName) > 1) && (FileName[StrLen (FileName) - 1] == L'\\')) {
+ FileName[StrLen (FileName) - 1] = L'\0';
+ }
+
+Exit:
+ return FileName;
+}
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
index 86020de6e0..52eb472a58 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
@@ -1,2986 +1,2986 @@
-/** @file
- Handle on-disk format and volume structures in UDF/ECMA-167 file systems.
-
- Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-**/
-
-#include "Udf.h"
-
-//
-// Vendor-Defined Device Path GUID for UDF file system
-//
-EFI_GUID gUdfDevPathGuid = EFI_UDF_DEVICE_PATH_GUID;
-
-/**
- Find the anchor volume descriptor pointer.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[out] AnchorPoint Anchor volume descriptor pointer.
-
- @retval EFI_SUCCESS Anchor volume descriptor pointer found.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval other Anchor volume descriptor pointer not found.
-
-**/
-EFI_STATUS
-FindAnchorVolumeDescriptorPointer (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint
- )
-{
- EFI_STATUS Status;
- UINT32 BlockSize;
- EFI_LBA EndLBA;
- EFI_LBA DescriptorLBAs[4];
- UINTN Index;
- UDF_DESCRIPTOR_TAG *DescriptorTag;
-
- BlockSize = BlockIo->Media->BlockSize;
- EndLBA = BlockIo->Media->LastBlock;
- DescriptorLBAs[0] = 256;
- DescriptorLBAs[1] = EndLBA - 256;
- DescriptorLBAs[2] = EndLBA;
- DescriptorLBAs[3] = 512;
-
- for (Index = 0; Index < ARRAY_SIZE (DescriptorLBAs); Index++) {
- Status = DiskIo->ReadDisk (
- DiskIo,
- BlockIo->Media->MediaId,
- MultU64x32 (DescriptorLBAs[Index], BlockSize),
- sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER),
- (VOID *)AnchorPoint
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- DescriptorTag = &AnchorPoint->DescriptorTag;
-
- //
- // Check if read LBA has a valid AVDP descriptor.
- //
- if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
- return EFI_SUCCESS;
- }
- }
-
- //
- // No AVDP found.
- //
- return EFI_VOLUME_CORRUPTED;
-}
-
-/**
- Save the content of Logical Volume Descriptors and Partitions Descriptors in
- memory.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] AnchorPoint Anchor volume descriptor pointer.
- @param[out] Volume UDF volume information structure.
-
- @retval EFI_SUCCESS The descriptors were saved.
- @retval EFI_OUT_OF_RESOURCES The descriptors were not saved due to lack of
- resources.
- @retval other The descriptors were not saved due to
- ReadDisk error.
-
-**/
-EFI_STATUS
-StartMainVolumeDescriptorSequence (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint,
- OUT UDF_VOLUME_INFO *Volume
- )
-{
- EFI_STATUS Status;
- UINT32 BlockSize;
- UDF_EXTENT_AD *ExtentAd;
- EFI_LBA SeqStartBlock;
- EFI_LBA SeqEndBlock;
- BOOLEAN StopSequence;
- VOID *Buffer;
- UDF_DESCRIPTOR_TAG *DescriptorTag;
- UINT32 LogicalBlockSize;
-
- BlockSize = BlockIo->Media->BlockSize;
- ExtentAd = &AnchorPoint->MainVolumeDescriptorSequenceExtent;
-
- //
- // Allocate buffer for reading disk blocks
- //
- Buffer = AllocateZeroPool ((UINTN)BlockSize);
- if (Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // The logical partition created by Partition driver is relative to the main
- // VDS extent location, so we start the Main Volume Descriptor Sequence at
- // LBA 0.
- //
- // We don't need to check again if we have valid Volume Descriptors here since
- // Partition driver already did.
- //
- SeqStartBlock = 0;
- SeqEndBlock = SeqStartBlock + DivU64x32 (
- (UINT64)ExtentAd->ExtentLength,
- BlockSize
- );
- StopSequence = FALSE;
- for ( ; SeqStartBlock < SeqEndBlock && !StopSequence; SeqStartBlock++) {
- //
- // Read disk block
- //
- Status = BlockIo->ReadBlocks (
- BlockIo,
- BlockIo->Media->MediaId,
- SeqStartBlock,
- BlockSize,
- Buffer
- );
- if (EFI_ERROR (Status)) {
- goto Out_Free;
- }
-
- DescriptorTag = Buffer;
-
- switch (DescriptorTag->TagIdentifier) {
- case UdfPartitionDescriptor:
- //
- // Save Partition Descriptor
- //
- CopyMem (&Volume->PartitionDesc, Buffer, sizeof (Volume->PartitionDesc));
- break;
-
- case UdfLogicalVolumeDescriptor:
- //
- // Save Logical Volume Descriptor
- //
- CopyMem (&Volume->LogicalVolDesc, Buffer, sizeof (Volume->LogicalVolDesc));
- break;
-
- case UdfTerminatingDescriptor:
- StopSequence = TRUE;
- break;
-
- default:
- ;
- }
- }
-
- //
- // Determine FE (File Entry) size
- //
- LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
- if (LogicalBlockSize >= UDF_LOGICAL_SECTOR_SIZE) {
- Volume->FileEntrySize = (UINTN)LogicalBlockSize;
- } else {
- Volume->FileEntrySize = UDF_LOGICAL_SECTOR_SIZE;
- }
-
- Status = EFI_SUCCESS;
-
-Out_Free:
- //
- // Free block read buffer
- //
- FreePool (Buffer);
-
- return Status;
-}
-
-/**
- Return a Partition Descriptor given a Long Allocation Descriptor. This is
- necessary to calculate the right extent (LongAd) offset which is added up
- with partition's starting location.
-
- @param[in] Volume Volume information pointer.
- @param[in] LongAd Long Allocation Descriptor pointer.
-
- @return A pointer to a Partition Descriptor.
-
-**/
-UDF_PARTITION_DESCRIPTOR *
-GetPdFromLongAd (
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd
- )
-{
- UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;
- UINT16 PartitionNum;
-
- LogicalVolDesc = &Volume->LogicalVolDesc;
-
- switch (LogicalVolDesc->DomainIdentifier.Suffix.Domain.UdfRevision) {
- case 0x0102:
- case 0x0150:
- case 0x0200:
- case 0x0201:
- case 0x0250:
- case 0x0260:
- //
- // UDF 1.02 specification:
- //
- // There shall be exactly one prevailing Logical Volume Descriptor recorded
- // per Volume Set. The Partition Maps field shall contain only Type 1
- // Partition Maps.
- //
- // UDF 1.50 through 2.60 specs say:
- //
- // For the purpose of interchange partition maps shall be limited to
- // Partition Map type 1, except type 2 maps as described in the document.
- //
- // NOTE: Only one Type 1 (Physical) Partition is supported. It has been
- // checked already in Partition driver for existence of a single Type 1
- // Partition map. Hence, the 'PartitionReferenceNumber' field (the index
- // used to access Partition Maps data within the Logical Volume Descriptor)
- // in the Long Allocation Descriptor should be 0 to indicate there is only
- // one partition.
- //
- if (LongAd->ExtentLocation.PartitionReferenceNumber != 0) {
- return NULL;
- }
-
- //
- // Since only one partition, get the first one directly.
- //
- PartitionNum = *(UINT16 *)((UINTN)&LogicalVolDesc->PartitionMaps[4]);
- break;
-
- default:
- //
- // Unsupported UDF revision
- //
- return NULL;
- }
-
- //
- // Check if partition number matches Partition Descriptor found in Main Volume
- // Descriptor Sequence.
- //
- if (Volume->PartitionDesc.PartitionNumber == PartitionNum) {
- return &Volume->PartitionDesc;
- }
-
- return NULL;
-}
-
-/**
- Return logical sector number of a given Long Allocation Descriptor.
-
- @param[in] Volume Volume information pointer.
- @param[in] LongAd Long Allocation Descriptor pointer.
- @param[out] Lsn Logical sector number pointer.
-
- @retval EFI_SUCCESS Logical sector number successfully returned.
- @retval EFI_UNSUPPORTED Logical sector number is not returned due to
- unrecognized format.
-
-**/
-EFI_STATUS
-GetLongAdLsn (
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd,
- OUT UINT64 *Lsn
- )
-{
- UDF_PARTITION_DESCRIPTOR *PartitionDesc;
-
- PartitionDesc = GetPdFromLongAd (Volume, LongAd);
- if (PartitionDesc == NULL) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: Fail to get the Partition Descriptor from the given Long Allocation Descriptor.\n",
- __func__
- ));
- return EFI_UNSUPPORTED;
- }
-
- *Lsn = (UINT64)PartitionDesc->PartitionStartingLocation -
- Volume->MainVdsStartLocation +
- LongAd->ExtentLocation.LogicalBlockNumber;
-
- return EFI_SUCCESS;
-}
-
-/**
- Return logical sector number of a given Short Allocation Descriptor.
-
- @param[in] Volume Volume pointer.
- @param[in] PartitionDesc Partition Descriptor pointer.
- @param[in] ShortAd Short Allocation Descriptor pointer.
-
- @return The logical sector number of a given Short Allocation Descriptor.
-
-**/
-UINT64
-GetShortAdLsn (
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_PARTITION_DESCRIPTOR *PartitionDesc,
- IN UDF_SHORT_ALLOCATION_DESCRIPTOR *ShortAd
- )
-{
- return (UINT64)PartitionDesc->PartitionStartingLocation -
- Volume->MainVdsStartLocation + ShortAd->ExtentPosition;
-}
-
-/**
- Find File Set Descriptor of a given Logical Volume Descriptor.
-
- The found FSD will contain the extent (LogicalVolumeContentsUse) where our
- root directory is.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume Volume information pointer.
-
- @retval EFI_SUCCESS File Set Descriptor pointer found.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval other File Set Descriptor pointer not found.
-
-**/
-EFI_STATUS
-FindFileSetDescriptor (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume
- )
-{
- EFI_STATUS Status;
- UINT64 Lsn;
- UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;
- UDF_DESCRIPTOR_TAG *DescriptorTag;
-
- LogicalVolDesc = &Volume->LogicalVolDesc;
- Status = GetLongAdLsn (Volume, &LogicalVolDesc->LogicalVolumeContentsUse, &Lsn);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // As per UDF 2.60 specification:
- //
- // There shall be exactly one File Set Descriptor recorded per Logical
- // Volume.
- //
- // Read disk block
- //
- Status = DiskIo->ReadDisk (
- DiskIo,
- BlockIo->Media->MediaId,
- MultU64x32 (Lsn, LogicalVolDesc->LogicalBlockSize),
- sizeof (Volume->FileSetDesc),
- &Volume->FileSetDesc
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- DescriptorTag = &Volume->FileSetDesc.DescriptorTag;
-
- //
- // Check if read block is a File Set Descriptor
- //
- if (DescriptorTag->TagIdentifier != UdfFileSetDescriptor) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Read Volume and File Structure on an UDF file system.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[out] Volume Volume information pointer.
-
- @retval EFI_SUCCESS Volume and File Structure were read.
- @retval other Volume and File Structure were not read.
-
-**/
-EFI_STATUS
-ReadVolumeFileStructure (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- OUT UDF_VOLUME_INFO *Volume
- )
-{
- EFI_STATUS Status;
- UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint;
- UDF_EXTENT_AD *ExtentAd;
-
- //
- // Find Anchor Volume Descriptor Pointer
- //
- Status = FindAnchorVolumeDescriptorPointer (
- BlockIo,
- DiskIo,
- &AnchorPoint
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Save Main VDS start block number
- //
- ExtentAd = &AnchorPoint.MainVolumeDescriptorSequenceExtent;
-
- Volume->MainVdsStartLocation = (UINT64)ExtentAd->ExtentLocation;
-
- //
- // Start Main Volume Descriptor Sequence.
- //
- Status = StartMainVolumeDescriptorSequence (
- BlockIo,
- DiskIo,
- &AnchorPoint,
- Volume
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- return Status;
-}
-
-/**
- Calculate length of a given File Identifier Descriptor.
-
- @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
-
- @return The length of a given File Identifier Descriptor.
-
-**/
-UINT64
-GetFidDescriptorLength (
- IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc
- )
-{
- return (UINT64)(
- (INTN)((OFFSET_OF (UDF_FILE_IDENTIFIER_DESCRIPTOR, Data[0]) + 3 +
- FileIdentifierDesc->LengthOfFileIdentifier +
- FileIdentifierDesc->LengthOfImplementationUse) >> 2) << 2
- );
-}
-
-/**
- Duplicate a given File Identifier Descriptor.
-
- @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
- @param[out] NewFileIdentifierDesc The duplicated File Identifier Descriptor.
-
-**/
-VOID
-DuplicateFid (
- IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc,
- OUT UDF_FILE_IDENTIFIER_DESCRIPTOR **NewFileIdentifierDesc
- )
-{
- *NewFileIdentifierDesc =
- (UDF_FILE_IDENTIFIER_DESCRIPTOR *)AllocateCopyPool (
- (UINTN)GetFidDescriptorLength (FileIdentifierDesc),
- FileIdentifierDesc
- );
-}
-
-/**
- Duplicate either a given File Entry or a given Extended File Entry.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] Volume Volume information pointer.
- @param[in] FileEntry (Extended) File Entry pointer.
- @param[out] NewFileEntry The duplicated (Extended) File Entry.
-
-**/
-VOID
-DuplicateFe (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN UDF_VOLUME_INFO *Volume,
- IN VOID *FileEntry,
- OUT VOID **NewFileEntry
- )
-{
- *NewFileEntry = AllocateCopyPool (Volume->FileEntrySize, FileEntry);
-}
-
-/**
- Get raw data + length of a given File Entry or Extended File Entry.
-
- The file's recorded data can contain either real file content (inline) or
- a sequence of extents (or Allocation Descriptors) which tells where file's
- content is stored in.
-
- NOTE: The FE/EFE can be thought it was an inode.
-
- @attention This is boundary function that may receive untrusted input.
- @attention The input is from FileSystem.
-
- The (Extended) File Entry is external input, so this routine will do basic
- validation for (Extended) File Entry and report status.
-
- @param[in] FileEntryData (Extended) File Entry pointer.
- @param[in] FileEntrySize Size of the (Extended) File Entry specified
- by FileEntryData.
- @param[out] Data Buffer contains the raw data of a given
- (Extended) File Entry.
- @param[out] Length Length of the data in Buffer.
-
- @retval EFI_SUCCESS Raw data and size of the FE/EFE was read.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
-
-**/
-EFI_STATUS
-GetFileEntryData (
- IN VOID *FileEntryData,
- IN UINTN FileEntrySize,
- OUT VOID **Data,
- OUT UINT64 *Length
- )
-{
- UDF_DESCRIPTOR_TAG *DescriptorTag;
- UDF_EXTENDED_FILE_ENTRY *ExtendedFileEntry;
- UDF_FILE_ENTRY *FileEntry;
-
- DescriptorTag = FileEntryData;
-
- if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {
- ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData;
-
- *Length = ExtendedFileEntry->InformationLength;
- *Data = (VOID *)((UINT8 *)ExtendedFileEntry->Data +
- ExtendedFileEntry->LengthOfExtendedAttributes);
- } else if (DescriptorTag->TagIdentifier == UdfFileEntry) {
- FileEntry = (UDF_FILE_ENTRY *)FileEntryData;
-
- *Length = FileEntry->InformationLength;
- *Data = (VOID *)((UINT8 *)FileEntry->Data +
- FileEntry->LengthOfExtendedAttributes);
- }
-
- if ((*Length > FileEntrySize) ||
- ((UINTN)FileEntryData > (UINTN)(*Data)) ||
- ((UINTN)(*Data) - (UINTN)FileEntryData > FileEntrySize - *Length))
- {
- return EFI_VOLUME_CORRUPTED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Get Allocation Descriptors' data information from a given FE/EFE.
-
- @attention This is boundary function that may receive untrusted input.
- @attention The input is from FileSystem.
-
- The (Extended) File Entry is external input, so this routine will do basic
- validation for (Extended) File Entry and report status.
-
- @param[in] FileEntryData (Extended) File Entry pointer.
- @param[in] FileEntrySize Size of the (Extended) File Entry specified
- by FileEntryData.
- @param[out] AdsData Buffer contains the Allocation Descriptors'
- data from a given FE/EFE.
- @param[out] Length Length of the data in AdsData.
-
- @retval EFI_SUCCESS The data and size of Allocation Descriptors
- were read from the FE/EFE.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
-
-**/
-EFI_STATUS
-GetAdsInformation (
- IN VOID *FileEntryData,
- IN UINTN FileEntrySize,
- OUT VOID **AdsData,
- OUT UINT64 *Length
- )
-{
- UDF_DESCRIPTOR_TAG *DescriptorTag;
- UDF_EXTENDED_FILE_ENTRY *ExtendedFileEntry;
- UDF_FILE_ENTRY *FileEntry;
-
- DescriptorTag = FileEntryData;
-
- if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {
- ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData;
-
- *Length = ExtendedFileEntry->LengthOfAllocationDescriptors;
- *AdsData = (VOID *)((UINT8 *)ExtendedFileEntry->Data +
- ExtendedFileEntry->LengthOfExtendedAttributes);
- } else if (DescriptorTag->TagIdentifier == UdfFileEntry) {
- FileEntry = (UDF_FILE_ENTRY *)FileEntryData;
-
- *Length = FileEntry->LengthOfAllocationDescriptors;
- *AdsData = (VOID *)((UINT8 *)FileEntry->Data +
- FileEntry->LengthOfExtendedAttributes);
- }
-
- if ((*Length > FileEntrySize) ||
- ((UINTN)FileEntryData > (UINTN)(*AdsData)) ||
- ((UINTN)(*AdsData) - (UINTN)FileEntryData > FileEntrySize - *Length))
- {
- return EFI_VOLUME_CORRUPTED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Read next Long Allocation Descriptor from a given file's data.
-
- @param[in] Data File's data pointer.
- @param[in,out] Offset Starting offset of the File's data to read.
- @param[in] Length Length of the data to read.
- @param[out] FoundLongAd Long Allocation Descriptor pointer.
-
- @retval EFI_SUCCESS A Long Allocation Descriptor was found.
- @retval EFI_DEVICE_ERROR No more Long Allocation Descriptors.
-
-**/
-EFI_STATUS
-GetLongAdFromAds (
- IN VOID *Data,
- IN OUT UINT64 *Offset,
- IN UINT64 Length,
- OUT UDF_LONG_ALLOCATION_DESCRIPTOR **FoundLongAd
- )
-{
- UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd;
- UDF_EXTENT_FLAGS ExtentFlags;
-
- for ( ; ;) {
- if (*Offset >= Length) {
- //
- // No more Long Allocation Descriptors.
- //
- return EFI_DEVICE_ERROR;
- }
-
- LongAd =
- (UDF_LONG_ALLOCATION_DESCRIPTOR *)((UINT8 *)Data + *Offset);
-
- //
- // If it's either an indirect AD (Extended Alllocation Descriptor) or an
- // allocated AD, then return it.
- //
- ExtentFlags = GET_EXTENT_FLAGS (LongAdsSequence, LongAd);
- if ((ExtentFlags == ExtentIsNextExtent) ||
- (ExtentFlags == ExtentRecordedAndAllocated))
- {
- break;
- }
-
- //
- // This AD is either not recorded but allocated, or not recorded and not
- // allocated. Skip it.
- //
- *Offset += AD_LENGTH (LongAdsSequence);
- }
-
- *FoundLongAd = LongAd;
-
- return EFI_SUCCESS;
-}
-
-/**
- Read next Short Allocation Descriptor from a given file's data.
-
- @param[in] Data File's data pointer.
- @param[in,out] Offset Starting offset of the File's data to read.
- @param[in] Length Length of the data to read.
- @param[out] FoundShortAd Short Allocation Descriptor pointer.
-
- @retval EFI_SUCCESS A Short Allocation Descriptor was found.
- @retval EFI_DEVICE_ERROR No more Short Allocation Descriptors.
-
-**/
-EFI_STATUS
-GetShortAdFromAds (
- IN VOID *Data,
- IN OUT UINT64 *Offset,
- IN UINT64 Length,
- OUT UDF_SHORT_ALLOCATION_DESCRIPTOR **FoundShortAd
- )
-{
- UDF_SHORT_ALLOCATION_DESCRIPTOR *ShortAd;
- UDF_EXTENT_FLAGS ExtentFlags;
-
- for ( ; ;) {
- if (*Offset >= Length) {
- //
- // No more Short Allocation Descriptors.
- //
- return EFI_DEVICE_ERROR;
- }
-
- ShortAd =
- (UDF_SHORT_ALLOCATION_DESCRIPTOR *)((UINT8 *)Data + *Offset);
-
- //
- // If it's either an indirect AD (Extended Alllocation Descriptor) or an
- // allocated AD, then return it.
- //
- ExtentFlags = GET_EXTENT_FLAGS (ShortAdsSequence, ShortAd);
- if ((ExtentFlags == ExtentIsNextExtent) ||
- (ExtentFlags == ExtentRecordedAndAllocated))
- {
- break;
- }
-
- //
- // This AD is either not recorded but allocated, or not recorded and not
- // allocated. Skip it.
- //
- *Offset += AD_LENGTH (ShortAdsSequence);
- }
-
- *FoundShortAd = ShortAd;
-
- return EFI_SUCCESS;
-}
-
-/**
- Get either a Short Allocation Descriptor or a Long Allocation Descriptor from
- file's data.
-
- @param[in] RecordingFlags Flag to indicate the type of descriptor.
- @param[in] Data File's data pointer.
- @param[in,out] Offset Starting offset of the File's data to read.
- @param[in] Length Length of the data to read.
- @param[out] FoundAd Allocation Descriptor pointer.
-
- @retval EFI_SUCCESS A Short Allocation Descriptor was found.
- @retval EFI_DEVICE_ERROR No more Allocation Descriptors.
- Invalid type of descriptor was given.
-
-**/
-EFI_STATUS
-GetAllocationDescriptor (
- IN UDF_FE_RECORDING_FLAGS RecordingFlags,
- IN VOID *Data,
- IN OUT UINT64 *Offset,
- IN UINT64 Length,
- OUT VOID **FoundAd
- )
-{
- if (RecordingFlags == LongAdsSequence) {
- return GetLongAdFromAds (
- Data,
- Offset,
- Length,
- (UDF_LONG_ALLOCATION_DESCRIPTOR **)FoundAd
- );
- } else if (RecordingFlags == ShortAdsSequence) {
- return GetShortAdFromAds (
- Data,
- Offset,
- Length,
- (UDF_SHORT_ALLOCATION_DESCRIPTOR **)FoundAd
- );
- }
-
- //
- // Code should never reach here.
- //
- ASSERT (FALSE);
- return EFI_DEVICE_ERROR;
-}
-
-/**
- Return logical sector number of either Short or Long Allocation Descriptor.
-
- @param[in] RecordingFlags Flag to indicate the type of descriptor.
- @param[in] Volume Volume information pointer.
- @param[in] ParentIcb Long Allocation Descriptor pointer.
- @param[in] Ad Allocation Descriptor pointer.
- @param[out] Lsn Logical sector number pointer.
-
- @retval EFI_SUCCESS Logical sector number of the given Allocation
- Descriptor successfully returned.
- @retval EFI_UNSUPPORTED Logical sector number of the given Allocation
- Descriptor is not returned due to unrecognized
- format.
-
-**/
-EFI_STATUS
-GetAllocationDescriptorLsn (
- IN UDF_FE_RECORDING_FLAGS RecordingFlags,
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,
- IN VOID *Ad,
- OUT UINT64 *Lsn
- )
-{
- UDF_PARTITION_DESCRIPTOR *PartitionDesc;
-
- if (RecordingFlags == LongAdsSequence) {
- return GetLongAdLsn (Volume, (UDF_LONG_ALLOCATION_DESCRIPTOR *)Ad, Lsn);
- } else if (RecordingFlags == ShortAdsSequence) {
- PartitionDesc = GetPdFromLongAd (Volume, ParentIcb);
- if (PartitionDesc == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- *Lsn = GetShortAdLsn (
- Volume,
- PartitionDesc,
- (UDF_SHORT_ALLOCATION_DESCRIPTOR *)Ad
- );
- return EFI_SUCCESS;
- }
-
- //
- // Code should never reach here.
- //
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
-}
-
-/**
- Return offset + length of a given indirect Allocation Descriptor (AED).
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume Volume information pointer.
- @param[in] ParentIcb Long Allocation Descriptor pointer.
- @param[in] RecordingFlags Flag to indicate the type of descriptor.
- @param[in] Ad Allocation Descriptor pointer.
- @param[out] Offset Offset of a given indirect Allocation
- Descriptor.
- @param[out] Length Length of a given indirect Allocation
- Descriptor.
-
- @retval EFI_SUCCESS The offset and length were returned.
- @retval EFI_OUT_OF_RESOURCES The offset and length were not returned due
- to lack of resources.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval other The offset and length were not returned.
-
-**/
-EFI_STATUS
-GetAedAdsOffset (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,
- IN UDF_FE_RECORDING_FLAGS RecordingFlags,
- IN VOID *Ad,
- OUT UINT64 *Offset,
- OUT UINT64 *Length
- )
-{
- EFI_STATUS Status;
- UINT32 ExtentLength;
- UINT64 Lsn;
- VOID *Data;
- UINT32 LogicalBlockSize;
- UDF_ALLOCATION_EXTENT_DESCRIPTOR *AllocExtDesc;
- UDF_DESCRIPTOR_TAG *DescriptorTag;
-
- ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);
- Status = GetAllocationDescriptorLsn (
- RecordingFlags,
- Volume,
- ParentIcb,
- Ad,
- &Lsn
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Data = AllocatePool (ExtentLength);
- if (Data == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
-
- //
- // Read extent.
- //
- Status = DiskIo->ReadDisk (
- DiskIo,
- BlockIo->Media->MediaId,
- MultU64x32 (Lsn, LogicalBlockSize),
- ExtentLength,
- Data
- );
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
-
- AllocExtDesc = (UDF_ALLOCATION_EXTENT_DESCRIPTOR *)Data;
-
- DescriptorTag = &AllocExtDesc->DescriptorTag;
-
- //
- // Check if read extent contains a valid tag identifier for AED.
- //
- if (DescriptorTag->TagIdentifier != UdfAllocationExtentDescriptor) {
- Status = EFI_VOLUME_CORRUPTED;
- goto Exit;
- }
-
- //
- // Get AED's block offset and its length.
- //
- *Offset = MultU64x32 (Lsn, LogicalBlockSize) +
- sizeof (UDF_ALLOCATION_EXTENT_DESCRIPTOR);
- *Length = AllocExtDesc->LengthOfAllocationDescriptors;
-
-Exit:
- FreePool (Data);
-
- return Status;
-}
-
-/**
- Read Allocation Extent Descriptor into memory.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume Volume information pointer.
- @param[in] ParentIcb Long Allocation Descriptor pointer.
- @param[in] RecordingFlags Flag to indicate the type of descriptor.
- @param[in] Ad Allocation Descriptor pointer.
- @param[out] Data Buffer that contains the Allocation Extent
- Descriptor.
- @param[out] Length Length of Data.
-
- @retval EFI_SUCCESS The Allocation Extent Descriptor was read.
- @retval EFI_OUT_OF_RESOURCES The Allocation Extent Descriptor was not read
- due to lack of resources.
- @retval other Fail to read the disk.
-
-**/
-EFI_STATUS
-GetAedAdsData (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,
- IN UDF_FE_RECORDING_FLAGS RecordingFlags,
- IN VOID *Ad,
- OUT VOID **Data,
- OUT UINT64 *Length
- )
-{
- EFI_STATUS Status;
- UINT64 Offset;
-
- //
- // Get AED's offset + length.
- //
- Status = GetAedAdsOffset (
- BlockIo,
- DiskIo,
- Volume,
- ParentIcb,
- RecordingFlags,
- Ad,
- &Offset,
- Length
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Allocate buffer to read in AED's data.
- //
- *Data = AllocatePool ((UINTN)(*Length));
- if (*Data == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- return DiskIo->ReadDisk (
- DiskIo,
- BlockIo->Media->MediaId,
- Offset,
- (UINTN)(*Length),
- *Data
- );
-}
-
-/**
- Function used to serialise reads of Allocation Descriptors.
-
- @param[in] RecordingFlags Flag to indicate the type of descriptor.
- @param[in] Ad Allocation Descriptor pointer.
- @param[in, out] Buffer Buffer to hold the next Allocation Descriptor.
- @param[in] Length Length of Buffer.
-
- @retval EFI_SUCCESS Buffer was grown to hold the next Allocation
- Descriptor.
- @retval EFI_OUT_OF_RESOURCES Buffer was not grown due to lack of resources.
-
-**/
-EFI_STATUS
-GrowUpBufferToNextAd (
- IN UDF_FE_RECORDING_FLAGS RecordingFlags,
- IN VOID *Ad,
- IN OUT VOID **Buffer,
- IN UINT64 Length
- )
-{
- UINT32 ExtentLength;
-
- ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);
-
- if (*Buffer == NULL) {
- *Buffer = AllocatePool (ExtentLength);
- if (*Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- } else {
- *Buffer = ReallocatePool ((UINTN)Length, (UINTN)(Length + ExtentLength), *Buffer);
- if (*Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Read data or size of either a File Entry or an Extended File Entry.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume Volume information pointer.
- @param[in] ParentIcb Long Allocation Descriptor pointer.
- @param[in] FileEntryData FE/EFE structure pointer.
- @param[in, out] ReadFileInfo Read file information pointer.
-
- @retval EFI_SUCCESS Data or size of a FE/EFE was read.
- @retval EFI_OUT_OF_RESOURCES Data or size of a FE/EFE was not read due to
- lack of resources.
- @retval EFI_INVALID_PARAMETER The read file flag given in ReadFileInfo is
- invalid.
- @retval EFI_UNSUPPORTED The FE recording flag given in FileEntryData
- is not supported.
- @retval other Data or size of a FE/EFE was not read.
-
-**/
-EFI_STATUS
-ReadFile (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,
- IN VOID *FileEntryData,
- IN OUT UDF_READ_FILE_INFO *ReadFileInfo
- )
-{
- EFI_STATUS Status;
- UINT32 LogicalBlockSize;
- VOID *Data;
- VOID *DataBak;
- UINT64 Length;
- VOID *Ad;
- UINT64 AdOffset;
- UINT64 Lsn;
- BOOLEAN DoFreeAed;
- UINT64 FilePosition;
- UINT64 Offset;
- UINT64 DataOffset;
- UINT64 BytesLeft;
- UINT64 DataLength;
- BOOLEAN FinishedSeeking;
- UINT32 ExtentLength;
- UDF_FE_RECORDING_FLAGS RecordingFlags;
-
- LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
- DoFreeAed = FALSE;
-
- //
- // set BytesLeft to suppress incorrect compiler/analyzer warnings
- //
- BytesLeft = 0;
- DataOffset = 0;
- FilePosition = 0;
- FinishedSeeking = FALSE;
- Data = NULL;
-
- switch (ReadFileInfo->Flags) {
- case ReadFileGetFileSize:
- case ReadFileAllocateAndRead:
- //
- // Initialise ReadFileInfo structure for either getting file size, or
- // reading file's recorded data.
- //
- ReadFileInfo->ReadLength = 0;
- ReadFileInfo->FileData = NULL;
- break;
- case ReadFileSeekAndRead:
- //
- // About to seek a file and/or read its data.
- //
- Length = ReadFileInfo->FileSize - ReadFileInfo->FilePosition;
- if (ReadFileInfo->FileDataSize > Length) {
- //
- // About to read beyond the EOF -- truncate it.
- //
- ReadFileInfo->FileDataSize = Length;
- }
-
- //
- // Initialise data to start seeking and/or reading a file.
- //
- BytesLeft = ReadFileInfo->FileDataSize;
- DataOffset = 0;
- FilePosition = 0;
- FinishedSeeking = FALSE;
-
- break;
- }
-
- RecordingFlags = GET_FE_RECORDING_FLAGS (FileEntryData);
- switch (RecordingFlags) {
- case InlineData:
- //
- // There are no extents for this FE/EFE. All data is inline.
- //
- Status = GetFileEntryData (FileEntryData, Volume->FileEntrySize, &Data, &Length);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (ReadFileInfo->Flags == ReadFileGetFileSize) {
- ReadFileInfo->ReadLength = Length;
- } else if (ReadFileInfo->Flags == ReadFileAllocateAndRead) {
- //
- // Allocate buffer for starting read data.
- //
- ReadFileInfo->FileData = AllocatePool ((UINTN)Length);
- if (ReadFileInfo->FileData == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Read all inline data into ReadFileInfo->FileData
- //
- CopyMem (ReadFileInfo->FileData, Data, (UINTN)Length);
- ReadFileInfo->ReadLength = Length;
- } else if (ReadFileInfo->Flags == ReadFileSeekAndRead) {
- //
- // If FilePosition is non-zero, seek file to FilePosition, read
- // FileDataSize bytes and then updates FilePosition.
- //
- CopyMem (
- ReadFileInfo->FileData,
- (VOID *)((UINT8 *)Data + ReadFileInfo->FilePosition),
- (UINTN)ReadFileInfo->FileDataSize
- );
-
- ReadFileInfo->FilePosition += ReadFileInfo->FileDataSize;
- } else {
- ASSERT (FALSE);
- return EFI_INVALID_PARAMETER;
- }
-
- Status = EFI_SUCCESS;
- break;
-
- case LongAdsSequence:
- case ShortAdsSequence:
- //
- // This FE/EFE contains a run of Allocation Descriptors. Get data + size
- // for start reading them out.
- //
- Status = GetAdsInformation (FileEntryData, Volume->FileEntrySize, &Data, &Length);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- AdOffset = 0;
-
- for ( ; ;) {
- //
- // Read AD.
- //
- Status = GetAllocationDescriptor (
- RecordingFlags,
- Data,
- &AdOffset,
- Length,
- &Ad
- );
- if (Status == EFI_DEVICE_ERROR) {
- Status = EFI_SUCCESS;
- goto Done;
- }
-
- //
- // Check if AD is an indirect AD. If so, read Allocation Extent
- // Descriptor and its extents (ADs).
- //
- if (GET_EXTENT_FLAGS (RecordingFlags, Ad) == ExtentIsNextExtent) {
- DataBak = Data;
- Status = GetAedAdsData (
- BlockIo,
- DiskIo,
- Volume,
- ParentIcb,
- RecordingFlags,
- Ad,
- &Data,
- &Length
- );
-
- if (!DoFreeAed) {
- DoFreeAed = TRUE;
- } else {
- FreePool (DataBak);
- }
-
- if (EFI_ERROR (Status)) {
- goto Error_Get_Aed;
- }
-
- ASSERT (Data != NULL);
-
- AdOffset = 0;
- continue;
- }
-
- ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);
-
- Status = GetAllocationDescriptorLsn (
- RecordingFlags,
- Volume,
- ParentIcb,
- Ad,
- &Lsn
- );
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- switch (ReadFileInfo->Flags) {
- case ReadFileGetFileSize:
- ReadFileInfo->ReadLength += ExtentLength;
- break;
- case ReadFileAllocateAndRead:
- //
- // Increase FileData (if necessary) to read next extent.
- //
- Status = GrowUpBufferToNextAd (
- RecordingFlags,
- Ad,
- &ReadFileInfo->FileData,
- ReadFileInfo->ReadLength
- );
- if (EFI_ERROR (Status)) {
- goto Error_Alloc_Buffer_To_Next_Ad;
- }
-
- //
- // Read extent's data into FileData.
- //
- Status = DiskIo->ReadDisk (
- DiskIo,
- BlockIo->Media->MediaId,
- MultU64x32 (Lsn, LogicalBlockSize),
- ExtentLength,
- (VOID *)((UINT8 *)ReadFileInfo->FileData +
- ReadFileInfo->ReadLength)
- );
- if (EFI_ERROR (Status)) {
- goto Error_Read_Disk_Blk;
- }
-
- ReadFileInfo->ReadLength += ExtentLength;
- break;
- case ReadFileSeekAndRead:
- //
- // Seek file first before reading in its data.
- //
- if (FinishedSeeking) {
- Offset = 0;
- goto Skip_File_Seek;
- }
-
- if (FilePosition + ExtentLength < ReadFileInfo->FilePosition) {
- FilePosition += ExtentLength;
- goto Skip_Ad;
- }
-
- if (FilePosition + ExtentLength > ReadFileInfo->FilePosition) {
- Offset = ReadFileInfo->FilePosition - FilePosition;
- } else {
- Offset = 0;
- }
-
- //
- // Done with seeking file. Start reading its data.
- //
- FinishedSeeking = TRUE;
-
-Skip_File_Seek:
- //
- // Make sure we don't read more data than really wanted.
- //
- if (ExtentLength - Offset > BytesLeft) {
- DataLength = BytesLeft;
- } else {
- DataLength = ExtentLength - Offset;
- }
-
- //
- // Read extent's data into FileData.
- //
- Status = DiskIo->ReadDisk (
- DiskIo,
- BlockIo->Media->MediaId,
- Offset + MultU64x32 (Lsn, LogicalBlockSize),
- (UINTN)DataLength,
- (VOID *)((UINT8 *)ReadFileInfo->FileData +
- DataOffset)
- );
- if (EFI_ERROR (Status)) {
- goto Error_Read_Disk_Blk;
- }
-
- //
- // Update current file's position.
- //
- DataOffset += DataLength;
- ReadFileInfo->FilePosition += DataLength;
-
- BytesLeft -= DataLength;
- if (BytesLeft == 0) {
- //
- // There is no more file data to read.
- //
- Status = EFI_SUCCESS;
- goto Done;
- }
-
- break;
- }
-
-Skip_Ad:
- //
- // Point to the next AD (extent).
- //
- AdOffset += AD_LENGTH (RecordingFlags);
- }
-
- break;
- case ExtendedAdsSequence:
- // FIXME: Not supported. Got no volume with it, yet.
- ASSERT (FALSE);
- Status = EFI_UNSUPPORTED;
- break;
-
- default:
- //
- // A flag value reserved by the ECMA-167 standard (3rd Edition - June
- // 1997); 14.6 ICB Tag; 14.6.8 Flags (RBP 18); was found.
- //
- Status = EFI_UNSUPPORTED;
- break;
- }
-
-Done:
- if (DoFreeAed) {
- FreePool (Data);
- }
-
- return Status;
-
-Error_Read_Disk_Blk:
-Error_Alloc_Buffer_To_Next_Ad:
- if (ReadFileInfo->Flags != ReadFileSeekAndRead) {
- FreePool (ReadFileInfo->FileData);
- }
-
- if (DoFreeAed) {
- FreePool (Data);
- }
-
-Error_Get_Aed:
- return Status;
-}
-
-/**
- Find a file by its filename from a given Parent file.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume Volume information pointer.
- @param[in] FileName File name string.
- @param[in] Parent Parent directory file.
- @param[in] Icb Long Allocation Descriptor pointer.
- @param[out] File Found file.
-
- @retval EFI_SUCCESS The file was found.
- @retval EFI_INVALID_PARAMETER One or more input parameters are invalid.
- @retval EFI_NOT_FOUND The file was not found.
-
-**/
-EFI_STATUS
-InternalFindFile (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN CHAR16 *FileName,
- IN UDF_FILE_INFO *Parent,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb,
- OUT UDF_FILE_INFO *File
- )
-{
- EFI_STATUS Status;
- UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc;
- UDF_READ_DIRECTORY_INFO ReadDirInfo;
- BOOLEAN Found;
- CHAR16 FoundFileName[UDF_FILENAME_LENGTH];
- VOID *CompareFileEntry;
-
- //
- // Check if both Parent->FileIdentifierDesc and Icb are NULL.
- //
- if ((Parent->FileIdentifierDesc == NULL) && (Icb == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Check if parent file is really directory.
- //
- if (FE_ICB_FILE_TYPE (Parent->FileEntry) != UdfFileEntryDirectory) {
- return EFI_NOT_FOUND;
- }
-
- //
- // If FileName is current file or working directory, just duplicate Parent's
- // FE/EFE and FID descriptors.
- //
- if (StrCmp (FileName, L".") == 0) {
- if (Parent->FileIdentifierDesc == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- DuplicateFe (BlockIo, Volume, Parent->FileEntry, &File->FileEntry);
- if (File->FileEntry == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- DuplicateFid (Parent->FileIdentifierDesc, &File->FileIdentifierDesc);
- if (File->FileIdentifierDesc == NULL) {
- FreePool (File->FileEntry);
- return EFI_OUT_OF_RESOURCES;
- }
-
- return EFI_SUCCESS;
- }
-
- //
- // Start directory listing.
- //
- ZeroMem ((VOID *)&ReadDirInfo, sizeof (UDF_READ_DIRECTORY_INFO));
- Found = FALSE;
-
- for ( ; ;) {
- Status = ReadDirectoryEntry (
- BlockIo,
- DiskIo,
- Volume,
- (Parent->FileIdentifierDesc != NULL) ?
- &Parent->FileIdentifierDesc->Icb :
- Icb,
- Parent->FileEntry,
- &ReadDirInfo,
- &FileIdentifierDesc
- );
- if (EFI_ERROR (Status)) {
- if (Status == EFI_DEVICE_ERROR) {
- Status = EFI_NOT_FOUND;
- }
-
- break;
- }
-
- //
- // After calling function ReadDirectoryEntry(), if 'FileIdentifierDesc' is
- // NULL, then the 'Status' must be EFI_OUT_OF_RESOURCES. Hence, if the code
- // reaches here, 'FileIdentifierDesc' must be not NULL.
- //
- // The ASSERT here is for addressing a false positive NULL pointer
- // dereference issue raised from static analysis.
- //
- ASSERT (FileIdentifierDesc != NULL);
-
- if (FileIdentifierDesc->FileCharacteristics & PARENT_FILE) {
- //
- // This FID contains the location (FE/EFE) of the parent directory of this
- // directory (Parent), and if FileName is either ".." or "\\", then it's
- // the expected FID.
- //
- if ((StrCmp (FileName, L"..") == 0) || (StrCmp (FileName, L"\\") == 0)) {
- Found = TRUE;
- break;
- }
- } else {
- Status = GetFileNameFromFid (FileIdentifierDesc, ARRAY_SIZE (FoundFileName), FoundFileName);
- if (EFI_ERROR (Status)) {
- break;
- }
-
- if (StrCmp (FileName, FoundFileName) == 0) {
- //
- // FID has been found. Prepare to find its respective FE/EFE.
- //
- Found = TRUE;
- break;
- }
- }
-
- FreePool ((VOID *)FileIdentifierDesc);
- }
-
- if (ReadDirInfo.DirectoryData != NULL) {
- //
- // Free all allocated resources for the directory listing.
- //
- FreePool (ReadDirInfo.DirectoryData);
- }
-
- if (Found) {
- Status = EFI_SUCCESS;
-
- File->FileIdentifierDesc = FileIdentifierDesc;
-
- //
- // If the requested file is root directory, then the FE/EFE was already
- // retrieved in UdfOpenVolume() function, thus no need to find it again.
- //
- // Otherwise, find FE/EFE from the respective FID.
- //
- if (StrCmp (FileName, L"\\") != 0) {
- Status = FindFileEntry (
- BlockIo,
- DiskIo,
- Volume,
- &FileIdentifierDesc->Icb,
- &CompareFileEntry
- );
- if (EFI_ERROR (Status)) {
- goto Error_Find_Fe;
- }
-
- //
- // Make sure that both Parent's FE/EFE and found FE/EFE are not equal.
- //
- if (CompareMem (
- (VOID *)Parent->FileEntry,
- (VOID *)CompareFileEntry,
- Volume->FileEntrySize
- ) != 0)
- {
- File->FileEntry = CompareFileEntry;
- } else {
- FreePool ((VOID *)FileIdentifierDesc);
- FreePool ((VOID *)CompareFileEntry);
- Status = EFI_NOT_FOUND;
- }
- }
- }
-
- return Status;
-
-Error_Find_Fe:
- FreePool ((VOID *)FileIdentifierDesc);
-
- return Status;
-}
-
-/**
- Read volume information on a medium which contains a valid UDF file system.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[out] Volume UDF volume information structure.
-
- @retval EFI_SUCCESS Volume information read.
- @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 volume was not read due to lack of resources.
-
-**/
-EFI_STATUS
-ReadUdfVolumeInformation (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- OUT UDF_VOLUME_INFO *Volume
- )
-{
- EFI_STATUS Status;
-
- //
- // Read all necessary UDF volume information and keep it private to the driver
- //
- Status = ReadVolumeFileStructure (
- BlockIo,
- DiskIo,
- Volume
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Find File Set Descriptor
- //
- Status = FindFileSetDescriptor (BlockIo, DiskIo, Volume);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- return Status;
-}
-
-/**
- Find the root directory on an UDF volume.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume UDF volume information structure.
- @param[out] File Root directory file.
-
- @retval EFI_SUCCESS Root directory found.
- @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 root directory was not found due to lack of
- resources.
-
-**/
-EFI_STATUS
-FindRootDirectory (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- OUT UDF_FILE_INFO *File
- )
-{
- EFI_STATUS Status;
- UDF_FILE_INFO Parent;
-
- Status = FindFileEntry (
- BlockIo,
- DiskIo,
- Volume,
- &Volume->FileSetDesc.RootDirectoryIcb,
- &File->FileEntry
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Parent.FileEntry = File->FileEntry;
- Parent.FileIdentifierDesc = NULL;
-
- Status = FindFile (
- BlockIo,
- DiskIo,
- Volume,
- L"\\",
- NULL,
- &Parent,
- &Volume->FileSetDesc.RootDirectoryIcb,
- File
- );
- if (EFI_ERROR (Status)) {
- FreePool (File->FileEntry);
- }
-
- return Status;
-}
-
-/**
- Find either a File Entry or a Extended File Entry from a given ICB.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume UDF volume information structure.
- @param[in] Icb ICB of the FID.
- @param[out] FileEntry File Entry or Extended File Entry.
-
- @retval EFI_SUCCESS File Entry or Extended File Entry found.
- @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 FE/EFE entry was not found due to lack of
- resources.
-
-**/
-EFI_STATUS
-FindFileEntry (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb,
- OUT VOID **FileEntry
- )
-{
- EFI_STATUS Status;
- UINT64 Lsn;
- UINT32 LogicalBlockSize;
- UDF_DESCRIPTOR_TAG *DescriptorTag;
- VOID *ReadBuffer;
-
- Status = GetLongAdLsn (Volume, Icb, &Lsn);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
-
- ReadBuffer = AllocateZeroPool (Volume->FileEntrySize);
- if (ReadBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Read extent.
- //
- Status = DiskIo->ReadDisk (
- DiskIo,
- BlockIo->Media->MediaId,
- MultU64x32 (Lsn, LogicalBlockSize),
- Volume->FileEntrySize,
- ReadBuffer
- );
- if (EFI_ERROR (Status)) {
- goto Error_Read_Disk_Blk;
- }
-
- DescriptorTag = ReadBuffer;
-
- //
- // Check if the read extent contains a valid Tag Identifier for the expected
- // FE/EFE.
- //
- if ((DescriptorTag->TagIdentifier != UdfFileEntry) &&
- (DescriptorTag->TagIdentifier != UdfExtendedFileEntry))
- {
- Status = EFI_VOLUME_CORRUPTED;
- goto Error_Invalid_Fe;
- }
-
- *FileEntry = ReadBuffer;
- return EFI_SUCCESS;
-
-Error_Invalid_Fe:
-Error_Read_Disk_Blk:
- FreePool (ReadBuffer);
-
- return Status;
-}
-
-/**
- Find a file given its absolute path on an UDF volume.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume UDF volume information structure.
- @param[in] FilePath File's absolute path.
- @param[in] Root Root directory file.
- @param[in] Parent Parent directory file.
- @param[in] Icb ICB of Parent.
- @param[out] File Found file.
-
- @retval EFI_SUCCESS FilePath was found.
- @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 FilePath file was not found due to lack of
- resources.
-
-**/
-EFI_STATUS
-FindFile (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN CHAR16 *FilePath,
- IN UDF_FILE_INFO *Root,
- IN UDF_FILE_INFO *Parent,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb,
- OUT UDF_FILE_INFO *File
- )
-{
- EFI_STATUS Status;
- CHAR16 FileName[UDF_FILENAME_LENGTH];
- CHAR16 *FileNamePointer;
- UDF_FILE_INFO PreviousFile;
- VOID *FileEntry;
-
- Status = EFI_NOT_FOUND;
-
- CopyMem ((VOID *)&PreviousFile, (VOID *)Parent, sizeof (UDF_FILE_INFO));
- while (*FilePath != L'\0') {
- FileNamePointer = FileName;
- while (*FilePath != L'\0' && *FilePath != L'\\') {
- if ((((UINTN)FileNamePointer - (UINTN)FileName) / sizeof (CHAR16)) >=
- (ARRAY_SIZE (FileName) - 1))
- {
- return EFI_NOT_FOUND;
- }
-
- *FileNamePointer++ = *FilePath++;
- }
-
- *FileNamePointer = L'\0';
- if (FileName[0] == L'\0') {
- //
- // Open root directory.
- //
- if (Root == NULL) {
- //
- // There is no file found for the root directory yet. So, find only its
- // FID by now.
- //
- // See UdfOpenVolume() function.
- //
- Status = InternalFindFile (
- BlockIo,
- DiskIo,
- Volume,
- L"\\",
- &PreviousFile,
- Icb,
- File
- );
- } else {
- //
- // We've already a file pointer (Root) for the root directory. Duplicate
- // its FE/EFE and FID descriptors.
- //
- Status = EFI_SUCCESS;
- DuplicateFe (BlockIo, Volume, Root->FileEntry, &File->FileEntry);
- if (File->FileEntry == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- } else {
- //
- // File->FileEntry is not NULL.
- //
- DuplicateFid (Root->FileIdentifierDesc, &File->FileIdentifierDesc);
- if (File->FileIdentifierDesc == NULL) {
- FreePool (File->FileEntry);
- Status = EFI_OUT_OF_RESOURCES;
- }
- }
- }
- } else {
- //
- // No root directory. Find filename from the current directory.
- //
- Status = InternalFindFile (
- BlockIo,
- DiskIo,
- Volume,
- FileName,
- &PreviousFile,
- Icb,
- File
- );
- }
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // If the found file is a symlink, then find its respective FE/EFE and
- // FID descriptors.
- //
- if (FE_ICB_FILE_TYPE (File->FileEntry) == UdfFileEntrySymlink) {
- FreePool ((VOID *)File->FileIdentifierDesc);
-
- FileEntry = File->FileEntry;
-
- Status = ResolveSymlink (
- BlockIo,
- DiskIo,
- Volume,
- &PreviousFile,
- FileEntry,
- File
- );
-
- FreePool (FileEntry);
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- if (CompareMem (
- (VOID *)&PreviousFile,
- (VOID *)Parent,
- sizeof (UDF_FILE_INFO)
- ) != 0)
- {
- CleanupFileInformation (&PreviousFile);
- }
-
- CopyMem ((VOID *)&PreviousFile, (VOID *)File, sizeof (UDF_FILE_INFO));
- if ((*FilePath != L'\0') && (*FilePath == L'\\')) {
- FilePath++;
- }
- }
-
- return Status;
-}
-
-/**
- Read a directory entry at a time on an UDF volume.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume UDF volume information structure.
- @param[in] ParentIcb ICB of the parent file.
- @param[in] FileEntryData FE/EFE of the parent file.
- @param[in, out] ReadDirInfo Next read directory listing structure
- information.
- @param[out] FoundFid File Identifier Descriptor pointer.
-
- @retval EFI_SUCCESS Directory entry 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 directory entry was not read due to lack of
- resources.
-
-**/
-EFI_STATUS
-ReadDirectoryEntry (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,
- IN VOID *FileEntryData,
- IN OUT UDF_READ_DIRECTORY_INFO *ReadDirInfo,
- OUT UDF_FILE_IDENTIFIER_DESCRIPTOR **FoundFid
- )
-{
- EFI_STATUS Status;
- UDF_READ_FILE_INFO ReadFileInfo;
- UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc;
-
- 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.
- //
- ReadFileInfo.Flags = ReadFileAllocateAndRead;
-
- Status = ReadFile (
- BlockIo,
- DiskIo,
- Volume,
- ParentIcb,
- FileEntryData,
- &ReadFileInfo
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Fill in ReadDirInfo structure with the read directory's data information.
- //
- ReadDirInfo->DirectoryData = ReadFileInfo.FileData;
- ReadDirInfo->DirectoryLength = ReadFileInfo.ReadLength;
- }
-
- do {
- if (ReadDirInfo->FidOffset >= ReadDirInfo->DirectoryLength) {
- //
- // There are no longer FIDs for this directory. By returning
- // EFI_DEVICE_ERROR to the callee will indicate end of directory
- // listening.
- //
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Get FID for this entry.
- //
- FileIdentifierDesc = GET_FID_FROM_ADS (
- ReadDirInfo->DirectoryData,
- ReadDirInfo->FidOffset
- );
- //
- // Update FidOffset to point to next FID.
- //
- ReadDirInfo->FidOffset += GetFidDescriptorLength (FileIdentifierDesc);
- } while (FileIdentifierDesc->FileCharacteristics & DELETED_FILE);
-
- DuplicateFid (FileIdentifierDesc, FoundFid);
- if (*FoundFid == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Get a filename (encoded in OSTA-compressed format) from a File Identifier
- Descriptor on an UDF volume.
-
- @attention This is boundary function that may receive untrusted input.
- @attention The input is from FileSystem.
-
- The File Identifier Descriptor is external input, so this routine will do
- basic validation for File Identifier Descriptor and report status.
-
- @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
- @param[in] CharMax The maximum number of FileName Unicode char,
- including terminating null char.
- @param[out] FileName Decoded filename.
-
- @retval EFI_SUCCESS Filename decoded and read.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_BUFFER_TOO_SMALL The string buffer FileName cannot hold the
- decoded filename.
-**/
-EFI_STATUS
-GetFileNameFromFid (
- IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc,
- IN UINTN CharMax,
- OUT CHAR16 *FileName
- )
-{
- UINT8 *OstaCompressed;
- UINT8 CompressionId;
- UINT8 Length;
- UINTN Index;
- CHAR16 *FileNameBak;
-
- if (CharMax == 0) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- OstaCompressed =
- (UINT8 *)(
- (UINT8 *)FileIdentifierDesc->Data +
- FileIdentifierDesc->LengthOfImplementationUse
- );
-
- CompressionId = OstaCompressed[0];
- if (!IS_VALID_COMPRESSION_ID (CompressionId)) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- FileNameBak = FileName;
-
- //
- // Decode filename.
- //
- Length = FileIdentifierDesc->LengthOfFileIdentifier;
- if (CompressionId == 16) {
- if (((UINTN)Length >> 1) > CharMax) {
- return EFI_BUFFER_TOO_SMALL;
- }
- } else {
- if ((Length != 0) && ((UINTN)Length - 1 > CharMax)) {
- return EFI_BUFFER_TOO_SMALL;
- }
- }
-
- for (Index = 1; Index < Length; Index++) {
- if (CompressionId == 16) {
- *FileName = OstaCompressed[Index++] << 8;
- } else {
- *FileName = 0;
- }
-
- if (Index < Length) {
- *FileName |= (CHAR16)(OstaCompressed[Index]);
- }
-
- FileName++;
- }
-
- Index = ((UINTN)FileName - (UINTN)FileNameBak) / sizeof (CHAR16);
- if (Index > CharMax - 1) {
- Index = CharMax - 1;
- }
-
- FileNameBak[Index] = L'\0';
-
- return EFI_SUCCESS;
-}
-
-/**
- Resolve a symlink file on an UDF volume.
-
- @attention This is boundary function that may receive untrusted input.
- @attention The input is from FileSystem.
-
- The Path Component is external input, so this routine will do basic
- validation for Path Component and report status.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume UDF volume information structure.
- @param[in] Parent Parent file.
- @param[in] FileEntryData FE/EFE structure pointer.
- @param[out] File Resolved file.
-
- @retval EFI_SUCCESS Symlink file resolved.
- @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 symlink file was not resolved due to lack of
- resources.
-
-**/
-EFI_STATUS
-ResolveSymlink (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_FILE_INFO *Parent,
- IN VOID *FileEntryData,
- OUT UDF_FILE_INFO *File
- )
-{
- EFI_STATUS Status;
- UDF_READ_FILE_INFO ReadFileInfo;
- UINT8 *Data;
- UINT64 Length;
- UINT8 *EndData;
- UDF_PATH_COMPONENT *PathComp;
- UINT8 PathCompLength;
- CHAR16 FileName[UDF_FILENAME_LENGTH];
- CHAR16 *Char;
- UINTN Index;
- UINT8 CompressionId;
- UDF_FILE_INFO PreviousFile;
- BOOLEAN NotParent;
- BOOLEAN NotFile;
-
- ZeroMem ((VOID *)File, sizeof (UDF_FILE_INFO));
-
- //
- // Symlink files on UDF volumes do not contain so much data other than
- // Path Components which resolves to real filenames, so it's OK to read in
- // all its data here -- usually the data will be inline with the FE/EFE for
- // lower filenames.
- //
- ReadFileInfo.Flags = ReadFileAllocateAndRead;
-
- Status = ReadFile (
- BlockIo,
- DiskIo,
- Volume,
- &Parent->FileIdentifierDesc->Icb,
- FileEntryData,
- &ReadFileInfo
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Length = ReadFileInfo.ReadLength;
-
- Data = (UINT8 *)ReadFileInfo.FileData;
- EndData = Data + Length;
-
- CopyMem ((VOID *)&PreviousFile, (VOID *)Parent, sizeof (UDF_FILE_INFO));
-
- for ( ; ;) {
- PathComp = (UDF_PATH_COMPONENT *)Data;
-
- PathCompLength = PathComp->LengthOfComponentIdentifier;
-
- switch (PathComp->ComponentType) {
- case 1:
- //
- // This Path Component specifies the root directory hierarchy subject to
- // agreement between the originator and recipient of the medium. Skip it.
- //
- // Fall through.
- //
- case 2:
- //
- // "\\." of the current directory. Read next Path Component.
- //
- goto Next_Path_Component;
- case 3:
- //
- // ".." (parent directory). Go to it.
- //
- CopyMem ((VOID *)FileName, L"..", 6);
- break;
- case 4:
- //
- // "." (current file). Duplicate both FE/EFE and FID of this file.
- //
- DuplicateFe (BlockIo, Volume, PreviousFile.FileEntry, &File->FileEntry);
- if (File->FileEntry == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error_Find_File;
- }
-
- DuplicateFid (
- PreviousFile.FileIdentifierDesc,
- &File->FileIdentifierDesc
- );
- if (File->FileIdentifierDesc == NULL) {
- FreePool (File->FileEntry);
- Status = EFI_OUT_OF_RESOURCES;
- goto Error_Find_File;
- }
-
- goto Next_Path_Component;
- case 5:
- //
- // This Path Component identifies an object, either a file or a
- // directory or an alias.
- //
- // Decode it from the compressed data in ComponentIdentifier and find
- // respective path.
- //
- CompressionId = PathComp->ComponentIdentifier[0];
- if (!IS_VALID_COMPRESSION_ID (CompressionId)) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- if ((UINTN)PathComp->ComponentIdentifier + PathCompLength > (UINTN)EndData) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- Char = FileName;
- for (Index = 1; Index < PathCompLength; Index++) {
- if (CompressionId == 16) {
- *Char = *(UINT8 *)((UINT8 *)PathComp->ComponentIdentifier +
- Index) << 8;
- Index++;
- } else {
- if (Index > ARRAY_SIZE (FileName)) {
- return EFI_UNSUPPORTED;
- }
-
- *Char = 0;
- }
-
- if (Index < Length) {
- *Char |= (CHAR16)(*(UINT8 *)((UINT8 *)PathComp->ComponentIdentifier + Index));
- }
-
- Char++;
- }
-
- Index = ((UINTN)Char - (UINTN)FileName) / sizeof (CHAR16);
- if (Index > ARRAY_SIZE (FileName) - 1) {
- Index = ARRAY_SIZE (FileName) - 1;
- }
-
- FileName[Index] = L'\0';
- break;
- default:
- //
- // According to the ECMA-167 standard (3rd Edition - June 1997), Section
- // 14.16.1.1, all other values are reserved.
- //
- Status = EFI_VOLUME_CORRUPTED;
- goto Error_Find_File;
- }
-
- //
- // Find file from the read filename in symlink's file data.
- //
- Status = InternalFindFile (
- BlockIo,
- DiskIo,
- Volume,
- FileName,
- &PreviousFile,
- NULL,
- File
- );
- if (EFI_ERROR (Status)) {
- goto Error_Find_File;
- }
-
-Next_Path_Component:
- Data += sizeof (UDF_PATH_COMPONENT) + PathCompLength;
- if (Data >= EndData) {
- break;
- }
-
- //
- // Check the content in the file info pointed by File.
- //
- if ((File->FileEntry == NULL) || (File->FileIdentifierDesc == NULL)) {
- Status = EFI_VOLUME_CORRUPTED;
- goto Error_Find_File;
- }
-
- NotParent = (CompareMem (
- (VOID *)&PreviousFile,
- (VOID *)Parent,
- sizeof (UDF_FILE_INFO)
- ) != 0);
- NotFile = (CompareMem (
- (VOID *)&PreviousFile,
- (VOID *)File,
- sizeof (UDF_FILE_INFO)
- ) != 0);
-
- if (NotParent && NotFile) {
- CleanupFileInformation (&PreviousFile);
- }
-
- if (NotFile) {
- CopyMem ((VOID *)&PreviousFile, (VOID *)File, sizeof (UDF_FILE_INFO));
- }
- }
-
- //
- // Unmap the symlink file.
- //
- FreePool (ReadFileInfo.FileData);
-
- //
- // Check the content in the resolved file info.
- //
- if ((File->FileEntry == NULL) || (File->FileIdentifierDesc == NULL)) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- return EFI_SUCCESS;
-
-Error_Find_File:
- if (CompareMem (
- (VOID *)&PreviousFile,
- (VOID *)Parent,
- sizeof (UDF_FILE_INFO)
- ) != 0)
- {
- CleanupFileInformation (&PreviousFile);
- }
-
- FreePool (ReadFileInfo.FileData);
-
- return Status;
-}
-
-/**
- Clean up in-memory UDF file information.
-
- @param[in] File File information pointer.
-
-**/
-VOID
-CleanupFileInformation (
- IN UDF_FILE_INFO *File
- )
-{
- if (File->FileEntry != NULL) {
- FreePool (File->FileEntry);
- }
-
- if (File->FileIdentifierDesc != NULL) {
- FreePool ((VOID *)File->FileIdentifierDesc);
- }
-
- ZeroMem ((VOID *)File, sizeof (UDF_FILE_INFO));
-}
-
-/**
- Find a file from its absolute path 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[out] Size Size of the file.
-
- @retval EFI_SUCCESS File size calculated and set in Size.
- @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 size was not calculated due to lack of
- resources.
-
-**/
-EFI_STATUS
-GetFileSize (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_FILE_INFO *File,
- OUT UINT64 *Size
- )
-{
- EFI_STATUS Status;
- UDF_READ_FILE_INFO ReadFileInfo;
-
- ReadFileInfo.Flags = ReadFileGetFileSize;
-
- Status = ReadFile (
- BlockIo,
- DiskIo,
- Volume,
- &File->FileIdentifierDesc->Icb,
- File->FileEntry,
- &ReadFileInfo
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- *Size = ReadFileInfo.ReadLength;
-
- return EFI_SUCCESS;
-}
-
-/**
- Set information about a file on an UDF volume.
-
- @param[in] File File pointer.
- @param[in] FileSize Size of the file.
- @param[in] FileName Filename of the file.
- @param[in, out] BufferSize Size of the returned file infomation.
- @param[out] Buffer Data of the returned file information.
-
- @retval EFI_SUCCESS File information set.
- @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 information was not set due to lack of
- resources.
-
-**/
-EFI_STATUS
-SetFileInfo (
- IN UDF_FILE_INFO *File,
- IN UINT64 FileSize,
- IN CHAR16 *FileName,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- UINTN FileInfoLength;
- EFI_FILE_INFO *FileInfo;
- UDF_FILE_ENTRY *FileEntry;
- UDF_EXTENDED_FILE_ENTRY *ExtendedFileEntry;
- UDF_DESCRIPTOR_TAG *DescriptorTag;
-
- //
- // Calculate the needed size for the EFI_FILE_INFO structure.
- //
- FileInfoLength = sizeof (EFI_FILE_INFO) + ((FileName != NULL) ?
- StrSize (FileName) :
- sizeof (CHAR16));
- if (*BufferSize < FileInfoLength) {
- //
- // The given Buffer has no size enough for EFI_FILE_INFO structure.
- //
- *BufferSize = FileInfoLength;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- //
- // Buffer now contains room enough to store EFI_FILE_INFO structure.
- // Now, fill it in with all necessary information about the file.
- //
- FileInfo = (EFI_FILE_INFO *)Buffer;
- FileInfo->Size = FileInfoLength;
- FileInfo->Attribute &= ~EFI_FILE_VALID_ATTR;
- FileInfo->Attribute |= EFI_FILE_READ_ONLY;
-
- if (IS_FID_DIRECTORY_FILE (File->FileIdentifierDesc)) {
- FileInfo->Attribute |= EFI_FILE_DIRECTORY;
- } else if (IS_FID_NORMAL_FILE (File->FileIdentifierDesc)) {
- FileInfo->Attribute |= EFI_FILE_ARCHIVE;
- }
-
- if (IS_FID_HIDDEN_FILE (File->FileIdentifierDesc)) {
- FileInfo->Attribute |= EFI_FILE_HIDDEN;
- }
-
- DescriptorTag = File->FileEntry;
-
- if (DescriptorTag->TagIdentifier == UdfFileEntry) {
- FileEntry = (UDF_FILE_ENTRY *)File->FileEntry;
-
- //
- // Check if FE has the system attribute set.
- //
- if (FileEntry->IcbTag.Flags & (1 << 10)) {
- FileInfo->Attribute |= EFI_FILE_SYSTEM;
- }
-
- FileInfo->FileSize = FileSize;
- FileInfo->PhysicalSize = FileSize;
-
- FileInfo->CreateTime.Year = FileEntry->AccessTime.Year;
- FileInfo->CreateTime.Month = FileEntry->AccessTime.Month;
- FileInfo->CreateTime.Day = FileEntry->AccessTime.Day;
- FileInfo->CreateTime.Hour = FileEntry->AccessTime.Hour;
- FileInfo->CreateTime.Minute = FileEntry->AccessTime.Minute;
- FileInfo->CreateTime.Second = FileEntry->AccessTime.Second;
- FileInfo->CreateTime.Nanosecond =
- FileEntry->AccessTime.HundredsOfMicroseconds;
-
- FileInfo->LastAccessTime.Year =
- FileEntry->AccessTime.Year;
- FileInfo->LastAccessTime.Month =
- FileEntry->AccessTime.Month;
- FileInfo->LastAccessTime.Day =
- FileEntry->AccessTime.Day;
- FileInfo->LastAccessTime.Hour =
- FileEntry->AccessTime.Hour;
- FileInfo->LastAccessTime.Minute =
- FileEntry->AccessTime.Minute;
- FileInfo->LastAccessTime.Second =
- FileEntry->AccessTime.Second;
- FileInfo->LastAccessTime.Nanosecond =
- FileEntry->AccessTime.HundredsOfMicroseconds;
- } else if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {
- ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)File->FileEntry;
-
- //
- // Check if EFE has the system attribute set.
- //
- if (ExtendedFileEntry->IcbTag.Flags & (1 << 10)) {
- FileInfo->Attribute |= EFI_FILE_SYSTEM;
- }
-
- FileInfo->FileSize = FileSize;
- FileInfo->PhysicalSize = FileSize;
-
- FileInfo->CreateTime.Year = ExtendedFileEntry->CreationTime.Year;
- FileInfo->CreateTime.Month = ExtendedFileEntry->CreationTime.Month;
- FileInfo->CreateTime.Day = ExtendedFileEntry->CreationTime.Day;
- FileInfo->CreateTime.Hour = ExtendedFileEntry->CreationTime.Hour;
- FileInfo->CreateTime.Minute = ExtendedFileEntry->CreationTime.Second;
- FileInfo->CreateTime.Second = ExtendedFileEntry->CreationTime.Second;
- FileInfo->CreateTime.Nanosecond =
- ExtendedFileEntry->AccessTime.HundredsOfMicroseconds;
-
- FileInfo->LastAccessTime.Year =
- ExtendedFileEntry->AccessTime.Year;
- FileInfo->LastAccessTime.Month =
- ExtendedFileEntry->AccessTime.Month;
- FileInfo->LastAccessTime.Day =
- ExtendedFileEntry->AccessTime.Day;
- FileInfo->LastAccessTime.Hour =
- ExtendedFileEntry->AccessTime.Hour;
- FileInfo->LastAccessTime.Minute =
- ExtendedFileEntry->AccessTime.Minute;
- FileInfo->LastAccessTime.Second =
- ExtendedFileEntry->AccessTime.Second;
- FileInfo->LastAccessTime.Nanosecond =
- ExtendedFileEntry->AccessTime.HundredsOfMicroseconds;
- }
-
- FileInfo->CreateTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
- FileInfo->CreateTime.Daylight = EFI_TIME_ADJUST_DAYLIGHT;
- FileInfo->LastAccessTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
- FileInfo->LastAccessTime.Daylight = EFI_TIME_ADJUST_DAYLIGHT;
-
- CopyMem (
- (VOID *)&FileInfo->ModificationTime,
- (VOID *)&FileInfo->LastAccessTime,
- sizeof (EFI_TIME)
- );
-
- if (FileName != NULL) {
- StrCpyS (FileInfo->FileName, StrLen (FileName) + 1, FileName);
- } else {
- FileInfo->FileName[0] = '\0';
- }
-
- *BufferSize = FileInfoLength;
-
- return EFI_SUCCESS;
-}
-
-/**
- Get volume label of an UDF volume.
-
- @attention This is boundary function that may receive untrusted input.
- @attention The input is from FileSystem.
-
- The File Set Descriptor is external input, so this routine will do basic
- validation for File Set Descriptor and report status.
-
- @param[in] Volume Volume information pointer.
- @param[in] CharMax The maximum number of Unicode char in String,
- including terminating null char.
- @param[out] String String buffer pointer to store the volume label.
-
- @retval EFI_SUCCESS Volume label is returned.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_BUFFER_TOO_SMALL The string buffer String cannot hold the
- volume label.
-
-**/
-EFI_STATUS
-GetVolumeLabel (
- IN UDF_VOLUME_INFO *Volume,
- IN UINTN CharMax,
- OUT CHAR16 *String
- )
-{
- UDF_FILE_SET_DESCRIPTOR *FileSetDesc;
- UINTN Index;
- UINT8 *OstaCompressed;
- UINT8 CompressionId;
- CHAR16 *StringBak;
-
- FileSetDesc = &Volume->FileSetDesc;
-
- OstaCompressed = &FileSetDesc->LogicalVolumeIdentifier[0];
-
- CompressionId = OstaCompressed[0];
- if (!IS_VALID_COMPRESSION_ID (CompressionId)) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- StringBak = String;
- for (Index = 1; Index < 128; Index++) {
- if (CompressionId == 16) {
- if ((Index >> 1) > CharMax) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- *String = *(UINT8 *)(OstaCompressed + Index) << 8;
- Index++;
- } else {
- if (Index > CharMax) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- *String = 0;
- }
-
- if (Index < 128) {
- *String |= (CHAR16)(*(UINT8 *)(OstaCompressed + Index));
- }
-
- //
- // Unlike FID Identifiers, Logical Volume Identifier is stored in a
- // NULL-terminated OSTA compressed format, so we must check for the NULL
- // character.
- //
- if (*String == L'\0') {
- break;
- }
-
- String++;
- }
-
- Index = ((UINTN)String - (UINTN)StringBak) / sizeof (CHAR16);
- if (Index > CharMax - 1) {
- Index = CharMax - 1;
- }
-
- StringBak[Index] = L'\0';
-
- return EFI_SUCCESS;
-}
-
-/**
- Get volume and free space size information of an UDF volume.
-
- @attention This is boundary function that may receive untrusted input.
- @attention The input is from FileSystem.
-
- The Logical Volume Descriptor and the Logical Volume Integrity Descriptor are
- external inputs, so this routine will do basic validation for both descriptors
- and report status.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume UDF volume information structure.
- @param[out] VolumeSize Volume size.
- @param[out] FreeSpaceSize Free space size.
-
- @retval EFI_SUCCESS Volume and free space size calculated.
- @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 volume and free space size were not
- calculated due to lack of resources.
-
-**/
-EFI_STATUS
-GetVolumeSize (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- OUT UINT64 *VolumeSize,
- OUT UINT64 *FreeSpaceSize
- )
-{
- EFI_STATUS Status;
- UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;
- UDF_EXTENT_AD *ExtentAd;
- UINT64 Lsn;
- UINT32 LogicalBlockSize;
- UDF_LOGICAL_VOLUME_INTEGRITY *LogicalVolInt;
- UDF_DESCRIPTOR_TAG *DescriptorTag;
- UINTN Index;
- UINTN Length;
- UINT32 LsnsNo;
-
- LogicalVolDesc = &Volume->LogicalVolDesc;
-
- ExtentAd = &LogicalVolDesc->IntegritySequenceExtent;
-
- if ((ExtentAd->ExtentLength == 0) ||
- (ExtentAd->ExtentLength < sizeof (UDF_LOGICAL_VOLUME_INTEGRITY)))
- {
- return EFI_VOLUME_CORRUPTED;
- }
-
- LogicalVolInt = AllocatePool (ExtentAd->ExtentLength);
- if (LogicalVolInt == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Get location of Logical Volume Integrity Descriptor
- //
- Lsn = (UINT64)ExtentAd->ExtentLocation - Volume->MainVdsStartLocation;
-
- LogicalBlockSize = LogicalVolDesc->LogicalBlockSize;
-
- //
- // Read disk block
- //
- Status = DiskIo->ReadDisk (
- DiskIo,
- BlockIo->Media->MediaId,
- MultU64x32 (Lsn, LogicalBlockSize),
- ExtentAd->ExtentLength,
- LogicalVolInt
- );
- if (EFI_ERROR (Status)) {
- goto Out_Free;
- }
-
- DescriptorTag = &LogicalVolInt->DescriptorTag;
-
- //
- // Check if read block is a Logical Volume Integrity Descriptor
- //
- if (DescriptorTag->TagIdentifier != UdfLogicalVolumeIntegrityDescriptor) {
- Status = EFI_VOLUME_CORRUPTED;
- goto Out_Free;
- }
-
- if ((LogicalVolInt->NumberOfPartitions > MAX_UINT32 / sizeof (UINT32) / 2) ||
- (LogicalVolInt->NumberOfPartitions * sizeof (UINT32) * 2 >
- ExtentAd->ExtentLength - sizeof (UDF_LOGICAL_VOLUME_INTEGRITY)))
- {
- Status = EFI_VOLUME_CORRUPTED;
- goto Out_Free;
- }
-
- *VolumeSize = 0;
- *FreeSpaceSize = 0;
-
- Length = LogicalVolInt->NumberOfPartitions;
- for (Index = 0; Index < Length; Index += sizeof (UINT32)) {
- LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);
- //
- // Check if size is not specified
- //
- if (LsnsNo == 0xFFFFFFFFUL) {
- continue;
- }
-
- //
- // Accumulate free space size
- //
- *FreeSpaceSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);
- }
-
- Length = LogicalVolInt->NumberOfPartitions * sizeof (UINT32) * 2;
- for ( ; Index < Length; Index += sizeof (UINT32)) {
- LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);
- //
- // Check if size is not specified
- //
- if (LsnsNo == 0xFFFFFFFFUL) {
- continue;
- }
-
- //
- // Accumulate used volume space
- //
- *VolumeSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);
- }
-
- Status = EFI_SUCCESS;
-
-Out_Free:
- //
- // Free Logical Volume Integrity Descriptor
- //
- FreePool (LogicalVolInt);
-
- return Status;
-}
-
-/**
- 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 = ReadFileSeekAndRead;
- 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;
-}
-
-/**
- Check if ControllerHandle supports an UDF file system.
-
- @param[in] This Protocol instance pointer.
- @param[in] ControllerHandle Handle of device to test.
-
- @retval EFI_SUCCESS UDF file system found.
- @retval EFI_UNSUPPORTED UDF file system not found.
-
-**/
-EFI_STATUS
-SupportUdfFileSystem (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
- EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode;
- EFI_GUID *VendorDefinedGuid;
-
- //
- // Open Device Path protocol on ControllerHandle
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID **)&DevicePath,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
- }
-
- Status = EFI_UNSUPPORTED;
-
- //
- // Get last Device Path node
- //
- LastDevicePathNode = NULL;
- DevicePathNode = DevicePath;
- while (!IsDevicePathEnd (DevicePathNode)) {
- LastDevicePathNode = DevicePathNode;
- DevicePathNode = NextDevicePathNode (DevicePathNode);
- }
-
- //
- // Check if last Device Path node contains a Vendor-Defined Media Device Path
- // of an UDF file system.
- //
- if ((LastDevicePathNode != NULL) &&
- (DevicePathType (LastDevicePathNode) == MEDIA_DEVICE_PATH) &&
- (DevicePathSubType (LastDevicePathNode) == MEDIA_VENDOR_DP))
- {
- VendorDefinedGuid = (EFI_GUID *)((UINTN)LastDevicePathNode +
- OFFSET_OF (VENDOR_DEVICE_PATH, Guid));
- if (CompareGuid (VendorDefinedGuid, &gUdfDevPathGuid)) {
- Status = EFI_SUCCESS;
- }
- }
-
- //
- // Close Device Path protocol on ControllerHandle
- //
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
-
- return Status;
-}
+/** @file
+ Handle on-disk format and volume structures in UDF/ECMA-167 file systems.
+
+ Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
+ Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Udf.h"
+
+//
+// Vendor-Defined Device Path GUID for UDF file system
+//
+EFI_GUID gUdfDevPathGuid = EFI_UDF_DEVICE_PATH_GUID;
+
+/**
+ Find the anchor volume descriptor pointer.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[out] AnchorPoint Anchor volume descriptor pointer.
+
+ @retval EFI_SUCCESS Anchor volume descriptor pointer found.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval other Anchor volume descriptor pointer not found.
+
+**/
+EFI_STATUS
+FindAnchorVolumeDescriptorPointer (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint
+ )
+{
+ EFI_STATUS Status;
+ UINT32 BlockSize;
+ EFI_LBA EndLBA;
+ EFI_LBA DescriptorLBAs[4];
+ UINTN Index;
+ UDF_DESCRIPTOR_TAG *DescriptorTag;
+
+ BlockSize = BlockIo->Media->BlockSize;
+ EndLBA = BlockIo->Media->LastBlock;
+ DescriptorLBAs[0] = 256;
+ DescriptorLBAs[1] = EndLBA - 256;
+ DescriptorLBAs[2] = EndLBA;
+ DescriptorLBAs[3] = 512;
+
+ for (Index = 0; Index < ARRAY_SIZE (DescriptorLBAs); Index++) {
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32 (DescriptorLBAs[Index], BlockSize),
+ sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER),
+ (VOID *)AnchorPoint
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DescriptorTag = &AnchorPoint->DescriptorTag;
+
+ //
+ // Check if read LBA has a valid AVDP descriptor.
+ //
+ if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // No AVDP found.
+ //
+ return EFI_VOLUME_CORRUPTED;
+}
+
+/**
+ Save the content of Logical Volume Descriptors and Partitions Descriptors in
+ memory.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] AnchorPoint Anchor volume descriptor pointer.
+ @param[out] Volume UDF volume information structure.
+
+ @retval EFI_SUCCESS The descriptors were saved.
+ @retval EFI_OUT_OF_RESOURCES The descriptors were not saved due to lack of
+ resources.
+ @retval other The descriptors were not saved due to
+ ReadDisk error.
+
+**/
+EFI_STATUS
+StartMainVolumeDescriptorSequence (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint,
+ OUT UDF_VOLUME_INFO *Volume
+ )
+{
+ EFI_STATUS Status;
+ UINT32 BlockSize;
+ UDF_EXTENT_AD *ExtentAd;
+ EFI_LBA SeqStartBlock;
+ EFI_LBA SeqEndBlock;
+ BOOLEAN StopSequence;
+ VOID *Buffer;
+ UDF_DESCRIPTOR_TAG *DescriptorTag;
+ UINT32 LogicalBlockSize;
+
+ BlockSize = BlockIo->Media->BlockSize;
+ ExtentAd = &AnchorPoint->MainVolumeDescriptorSequenceExtent;
+
+ //
+ // Allocate buffer for reading disk blocks
+ //
+ Buffer = AllocateZeroPool ((UINTN)BlockSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // The logical partition created by Partition driver is relative to the main
+ // VDS extent location, so we start the Main Volume Descriptor Sequence at
+ // LBA 0.
+ //
+ // We don't need to check again if we have valid Volume Descriptors here since
+ // Partition driver already did.
+ //
+ SeqStartBlock = 0;
+ SeqEndBlock = SeqStartBlock + DivU64x32 (
+ (UINT64)ExtentAd->ExtentLength,
+ BlockSize
+ );
+ StopSequence = FALSE;
+ for ( ; SeqStartBlock < SeqEndBlock && !StopSequence; SeqStartBlock++) {
+ //
+ // Read disk block
+ //
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ SeqStartBlock,
+ BlockSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ goto Out_Free;
+ }
+
+ DescriptorTag = Buffer;
+
+ switch (DescriptorTag->TagIdentifier) {
+ case UdfPartitionDescriptor:
+ //
+ // Save Partition Descriptor
+ //
+ CopyMem (&Volume->PartitionDesc, Buffer, sizeof (Volume->PartitionDesc));
+ break;
+
+ case UdfLogicalVolumeDescriptor:
+ //
+ // Save Logical Volume Descriptor
+ //
+ CopyMem (&Volume->LogicalVolDesc, Buffer, sizeof (Volume->LogicalVolDesc));
+ break;
+
+ case UdfTerminatingDescriptor:
+ StopSequence = TRUE;
+ break;
+
+ default:
+ ;
+ }
+ }
+
+ //
+ // Determine FE (File Entry) size
+ //
+ LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
+ if (LogicalBlockSize >= UDF_LOGICAL_SECTOR_SIZE) {
+ Volume->FileEntrySize = (UINTN)LogicalBlockSize;
+ } else {
+ Volume->FileEntrySize = UDF_LOGICAL_SECTOR_SIZE;
+ }
+
+ Status = EFI_SUCCESS;
+
+Out_Free:
+ //
+ // Free block read buffer
+ //
+ FreePool (Buffer);
+
+ return Status;
+}
+
+/**
+ Return a Partition Descriptor given a Long Allocation Descriptor. This is
+ necessary to calculate the right extent (LongAd) offset which is added up
+ with partition's starting location.
+
+ @param[in] Volume Volume information pointer.
+ @param[in] LongAd Long Allocation Descriptor pointer.
+
+ @return A pointer to a Partition Descriptor.
+
+**/
+UDF_PARTITION_DESCRIPTOR *
+GetPdFromLongAd (
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd
+ )
+{
+ UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;
+ UINT16 PartitionNum;
+
+ LogicalVolDesc = &Volume->LogicalVolDesc;
+
+ switch (LogicalVolDesc->DomainIdentifier.Suffix.Domain.UdfRevision) {
+ case 0x0102:
+ case 0x0150:
+ case 0x0200:
+ case 0x0201:
+ case 0x0250:
+ case 0x0260:
+ //
+ // UDF 1.02 specification:
+ //
+ // There shall be exactly one prevailing Logical Volume Descriptor recorded
+ // per Volume Set. The Partition Maps field shall contain only Type 1
+ // Partition Maps.
+ //
+ // UDF 1.50 through 2.60 specs say:
+ //
+ // For the purpose of interchange partition maps shall be limited to
+ // Partition Map type 1, except type 2 maps as described in the document.
+ //
+ // NOTE: Only one Type 1 (Physical) Partition is supported. It has been
+ // checked already in Partition driver for existence of a single Type 1
+ // Partition map. Hence, the 'PartitionReferenceNumber' field (the index
+ // used to access Partition Maps data within the Logical Volume Descriptor)
+ // in the Long Allocation Descriptor should be 0 to indicate there is only
+ // one partition.
+ //
+ if (LongAd->ExtentLocation.PartitionReferenceNumber != 0) {
+ return NULL;
+ }
+
+ //
+ // Since only one partition, get the first one directly.
+ //
+ PartitionNum = *(UINT16 *)((UINTN)&LogicalVolDesc->PartitionMaps[4]);
+ break;
+
+ default:
+ //
+ // Unsupported UDF revision
+ //
+ return NULL;
+ }
+
+ //
+ // Check if partition number matches Partition Descriptor found in Main Volume
+ // Descriptor Sequence.
+ //
+ if (Volume->PartitionDesc.PartitionNumber == PartitionNum) {
+ return &Volume->PartitionDesc;
+ }
+
+ return NULL;
+}
+
+/**
+ Return logical sector number of a given Long Allocation Descriptor.
+
+ @param[in] Volume Volume information pointer.
+ @param[in] LongAd Long Allocation Descriptor pointer.
+ @param[out] Lsn Logical sector number pointer.
+
+ @retval EFI_SUCCESS Logical sector number successfully returned.
+ @retval EFI_UNSUPPORTED Logical sector number is not returned due to
+ unrecognized format.
+
+**/
+EFI_STATUS
+GetLongAdLsn (
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd,
+ OUT UINT64 *Lsn
+ )
+{
+ UDF_PARTITION_DESCRIPTOR *PartitionDesc;
+
+ PartitionDesc = GetPdFromLongAd (Volume, LongAd);
+ if (PartitionDesc == NULL) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Fail to get the Partition Descriptor from the given Long Allocation Descriptor.\n",
+ __func__
+ ));
+ return EFI_UNSUPPORTED;
+ }
+
+ *Lsn = (UINT64)PartitionDesc->PartitionStartingLocation -
+ Volume->MainVdsStartLocation +
+ LongAd->ExtentLocation.LogicalBlockNumber;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return logical sector number of a given Short Allocation Descriptor.
+
+ @param[in] Volume Volume pointer.
+ @param[in] PartitionDesc Partition Descriptor pointer.
+ @param[in] ShortAd Short Allocation Descriptor pointer.
+
+ @return The logical sector number of a given Short Allocation Descriptor.
+
+**/
+UINT64
+GetShortAdLsn (
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_PARTITION_DESCRIPTOR *PartitionDesc,
+ IN UDF_SHORT_ALLOCATION_DESCRIPTOR *ShortAd
+ )
+{
+ return (UINT64)PartitionDesc->PartitionStartingLocation -
+ Volume->MainVdsStartLocation + ShortAd->ExtentPosition;
+}
+
+/**
+ Find File Set Descriptor of a given Logical Volume Descriptor.
+
+ The found FSD will contain the extent (LogicalVolumeContentsUse) where our
+ root directory is.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume Volume information pointer.
+
+ @retval EFI_SUCCESS File Set Descriptor pointer found.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval other File Set Descriptor pointer not found.
+
+**/
+EFI_STATUS
+FindFileSetDescriptor (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Lsn;
+ UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;
+ UDF_DESCRIPTOR_TAG *DescriptorTag;
+
+ LogicalVolDesc = &Volume->LogicalVolDesc;
+ Status = GetLongAdLsn (Volume, &LogicalVolDesc->LogicalVolumeContentsUse, &Lsn);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // As per UDF 2.60 specification:
+ //
+ // There shall be exactly one File Set Descriptor recorded per Logical
+ // Volume.
+ //
+ // Read disk block
+ //
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32 (Lsn, LogicalVolDesc->LogicalBlockSize),
+ sizeof (Volume->FileSetDesc),
+ &Volume->FileSetDesc
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DescriptorTag = &Volume->FileSetDesc.DescriptorTag;
+
+ //
+ // Check if read block is a File Set Descriptor
+ //
+ if (DescriptorTag->TagIdentifier != UdfFileSetDescriptor) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read Volume and File Structure on an UDF file system.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[out] Volume Volume information pointer.
+
+ @retval EFI_SUCCESS Volume and File Structure were read.
+ @retval other Volume and File Structure were not read.
+
+**/
+EFI_STATUS
+ReadVolumeFileStructure (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ OUT UDF_VOLUME_INFO *Volume
+ )
+{
+ EFI_STATUS Status;
+ UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint;
+ UDF_EXTENT_AD *ExtentAd;
+
+ //
+ // Find Anchor Volume Descriptor Pointer
+ //
+ Status = FindAnchorVolumeDescriptorPointer (
+ BlockIo,
+ DiskIo,
+ &AnchorPoint
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Save Main VDS start block number
+ //
+ ExtentAd = &AnchorPoint.MainVolumeDescriptorSequenceExtent;
+
+ Volume->MainVdsStartLocation = (UINT64)ExtentAd->ExtentLocation;
+
+ //
+ // Start Main Volume Descriptor Sequence.
+ //
+ Status = StartMainVolumeDescriptorSequence (
+ BlockIo,
+ DiskIo,
+ &AnchorPoint,
+ Volume
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return Status;
+}
+
+/**
+ Calculate length of a given File Identifier Descriptor.
+
+ @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
+
+ @return The length of a given File Identifier Descriptor.
+
+**/
+UINT64
+GetFidDescriptorLength (
+ IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc
+ )
+{
+ return (UINT64)(
+ (INTN)((OFFSET_OF (UDF_FILE_IDENTIFIER_DESCRIPTOR, Data[0]) + 3 +
+ FileIdentifierDesc->LengthOfFileIdentifier +
+ FileIdentifierDesc->LengthOfImplementationUse) >> 2) << 2
+ );
+}
+
+/**
+ Duplicate a given File Identifier Descriptor.
+
+ @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
+ @param[out] NewFileIdentifierDesc The duplicated File Identifier Descriptor.
+
+**/
+VOID
+DuplicateFid (
+ IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc,
+ OUT UDF_FILE_IDENTIFIER_DESCRIPTOR **NewFileIdentifierDesc
+ )
+{
+ *NewFileIdentifierDesc =
+ (UDF_FILE_IDENTIFIER_DESCRIPTOR *)AllocateCopyPool (
+ (UINTN)GetFidDescriptorLength (FileIdentifierDesc),
+ FileIdentifierDesc
+ );
+}
+
+/**
+ Duplicate either a given File Entry or a given Extended File Entry.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] Volume Volume information pointer.
+ @param[in] FileEntry (Extended) File Entry pointer.
+ @param[out] NewFileEntry The duplicated (Extended) File Entry.
+
+**/
+VOID
+DuplicateFe (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN VOID *FileEntry,
+ OUT VOID **NewFileEntry
+ )
+{
+ *NewFileEntry = AllocateCopyPool (Volume->FileEntrySize, FileEntry);
+}
+
+/**
+ Get raw data + length of a given File Entry or Extended File Entry.
+
+ The file's recorded data can contain either real file content (inline) or
+ a sequence of extents (or Allocation Descriptors) which tells where file's
+ content is stored in.
+
+ NOTE: The FE/EFE can be thought it was an inode.
+
+ @attention This is boundary function that may receive untrusted input.
+ @attention The input is from FileSystem.
+
+ The (Extended) File Entry is external input, so this routine will do basic
+ validation for (Extended) File Entry and report status.
+
+ @param[in] FileEntryData (Extended) File Entry pointer.
+ @param[in] FileEntrySize Size of the (Extended) File Entry specified
+ by FileEntryData.
+ @param[out] Data Buffer contains the raw data of a given
+ (Extended) File Entry.
+ @param[out] Length Length of the data in Buffer.
+
+ @retval EFI_SUCCESS Raw data and size of the FE/EFE was read.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+
+**/
+EFI_STATUS
+GetFileEntryData (
+ IN VOID *FileEntryData,
+ IN UINTN FileEntrySize,
+ OUT VOID **Data,
+ OUT UINT64 *Length
+ )
+{
+ UDF_DESCRIPTOR_TAG *DescriptorTag;
+ UDF_EXTENDED_FILE_ENTRY *ExtendedFileEntry;
+ UDF_FILE_ENTRY *FileEntry;
+
+ DescriptorTag = FileEntryData;
+
+ if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {
+ ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData;
+
+ *Length = ExtendedFileEntry->InformationLength;
+ *Data = (VOID *)((UINT8 *)ExtendedFileEntry->Data +
+ ExtendedFileEntry->LengthOfExtendedAttributes);
+ } else if (DescriptorTag->TagIdentifier == UdfFileEntry) {
+ FileEntry = (UDF_FILE_ENTRY *)FileEntryData;
+
+ *Length = FileEntry->InformationLength;
+ *Data = (VOID *)((UINT8 *)FileEntry->Data +
+ FileEntry->LengthOfExtendedAttributes);
+ }
+
+ if ((*Length > FileEntrySize) ||
+ ((UINTN)FileEntryData > (UINTN)(*Data)) ||
+ ((UINTN)(*Data) - (UINTN)FileEntryData > FileEntrySize - *Length))
+ {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Allocation Descriptors' data information from a given FE/EFE.
+
+ @attention This is boundary function that may receive untrusted input.
+ @attention The input is from FileSystem.
+
+ The (Extended) File Entry is external input, so this routine will do basic
+ validation for (Extended) File Entry and report status.
+
+ @param[in] FileEntryData (Extended) File Entry pointer.
+ @param[in] FileEntrySize Size of the (Extended) File Entry specified
+ by FileEntryData.
+ @param[out] AdsData Buffer contains the Allocation Descriptors'
+ data from a given FE/EFE.
+ @param[out] Length Length of the data in AdsData.
+
+ @retval EFI_SUCCESS The data and size of Allocation Descriptors
+ were read from the FE/EFE.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+
+**/
+EFI_STATUS
+GetAdsInformation (
+ IN VOID *FileEntryData,
+ IN UINTN FileEntrySize,
+ OUT VOID **AdsData,
+ OUT UINT64 *Length
+ )
+{
+ UDF_DESCRIPTOR_TAG *DescriptorTag;
+ UDF_EXTENDED_FILE_ENTRY *ExtendedFileEntry;
+ UDF_FILE_ENTRY *FileEntry;
+
+ DescriptorTag = FileEntryData;
+
+ if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {
+ ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData;
+
+ *Length = ExtendedFileEntry->LengthOfAllocationDescriptors;
+ *AdsData = (VOID *)((UINT8 *)ExtendedFileEntry->Data +
+ ExtendedFileEntry->LengthOfExtendedAttributes);
+ } else if (DescriptorTag->TagIdentifier == UdfFileEntry) {
+ FileEntry = (UDF_FILE_ENTRY *)FileEntryData;
+
+ *Length = FileEntry->LengthOfAllocationDescriptors;
+ *AdsData = (VOID *)((UINT8 *)FileEntry->Data +
+ FileEntry->LengthOfExtendedAttributes);
+ }
+
+ if ((*Length > FileEntrySize) ||
+ ((UINTN)FileEntryData > (UINTN)(*AdsData)) ||
+ ((UINTN)(*AdsData) - (UINTN)FileEntryData > FileEntrySize - *Length))
+ {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read next Long Allocation Descriptor from a given file's data.
+
+ @param[in] Data File's data pointer.
+ @param[in,out] Offset Starting offset of the File's data to read.
+ @param[in] Length Length of the data to read.
+ @param[out] FoundLongAd Long Allocation Descriptor pointer.
+
+ @retval EFI_SUCCESS A Long Allocation Descriptor was found.
+ @retval EFI_DEVICE_ERROR No more Long Allocation Descriptors.
+
+**/
+EFI_STATUS
+GetLongAdFromAds (
+ IN VOID *Data,
+ IN OUT UINT64 *Offset,
+ IN UINT64 Length,
+ OUT UDF_LONG_ALLOCATION_DESCRIPTOR **FoundLongAd
+ )
+{
+ UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd;
+ UDF_EXTENT_FLAGS ExtentFlags;
+
+ for ( ; ;) {
+ if (*Offset >= Length) {
+ //
+ // No more Long Allocation Descriptors.
+ //
+ return EFI_DEVICE_ERROR;
+ }
+
+ LongAd =
+ (UDF_LONG_ALLOCATION_DESCRIPTOR *)((UINT8 *)Data + *Offset);
+
+ //
+ // If it's either an indirect AD (Extended Alllocation Descriptor) or an
+ // allocated AD, then return it.
+ //
+ ExtentFlags = GET_EXTENT_FLAGS (LongAdsSequence, LongAd);
+ if ((ExtentFlags == ExtentIsNextExtent) ||
+ (ExtentFlags == ExtentRecordedAndAllocated))
+ {
+ break;
+ }
+
+ //
+ // This AD is either not recorded but allocated, or not recorded and not
+ // allocated. Skip it.
+ //
+ *Offset += AD_LENGTH (LongAdsSequence);
+ }
+
+ *FoundLongAd = LongAd;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read next Short Allocation Descriptor from a given file's data.
+
+ @param[in] Data File's data pointer.
+ @param[in,out] Offset Starting offset of the File's data to read.
+ @param[in] Length Length of the data to read.
+ @param[out] FoundShortAd Short Allocation Descriptor pointer.
+
+ @retval EFI_SUCCESS A Short Allocation Descriptor was found.
+ @retval EFI_DEVICE_ERROR No more Short Allocation Descriptors.
+
+**/
+EFI_STATUS
+GetShortAdFromAds (
+ IN VOID *Data,
+ IN OUT UINT64 *Offset,
+ IN UINT64 Length,
+ OUT UDF_SHORT_ALLOCATION_DESCRIPTOR **FoundShortAd
+ )
+{
+ UDF_SHORT_ALLOCATION_DESCRIPTOR *ShortAd;
+ UDF_EXTENT_FLAGS ExtentFlags;
+
+ for ( ; ;) {
+ if (*Offset >= Length) {
+ //
+ // No more Short Allocation Descriptors.
+ //
+ return EFI_DEVICE_ERROR;
+ }
+
+ ShortAd =
+ (UDF_SHORT_ALLOCATION_DESCRIPTOR *)((UINT8 *)Data + *Offset);
+
+ //
+ // If it's either an indirect AD (Extended Alllocation Descriptor) or an
+ // allocated AD, then return it.
+ //
+ ExtentFlags = GET_EXTENT_FLAGS (ShortAdsSequence, ShortAd);
+ if ((ExtentFlags == ExtentIsNextExtent) ||
+ (ExtentFlags == ExtentRecordedAndAllocated))
+ {
+ break;
+ }
+
+ //
+ // This AD is either not recorded but allocated, or not recorded and not
+ // allocated. Skip it.
+ //
+ *Offset += AD_LENGTH (ShortAdsSequence);
+ }
+
+ *FoundShortAd = ShortAd;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get either a Short Allocation Descriptor or a Long Allocation Descriptor from
+ file's data.
+
+ @param[in] RecordingFlags Flag to indicate the type of descriptor.
+ @param[in] Data File's data pointer.
+ @param[in,out] Offset Starting offset of the File's data to read.
+ @param[in] Length Length of the data to read.
+ @param[out] FoundAd Allocation Descriptor pointer.
+
+ @retval EFI_SUCCESS A Short Allocation Descriptor was found.
+ @retval EFI_DEVICE_ERROR No more Allocation Descriptors.
+ Invalid type of descriptor was given.
+
+**/
+EFI_STATUS
+GetAllocationDescriptor (
+ IN UDF_FE_RECORDING_FLAGS RecordingFlags,
+ IN VOID *Data,
+ IN OUT UINT64 *Offset,
+ IN UINT64 Length,
+ OUT VOID **FoundAd
+ )
+{
+ if (RecordingFlags == LongAdsSequence) {
+ return GetLongAdFromAds (
+ Data,
+ Offset,
+ Length,
+ (UDF_LONG_ALLOCATION_DESCRIPTOR **)FoundAd
+ );
+ } else if (RecordingFlags == ShortAdsSequence) {
+ return GetShortAdFromAds (
+ Data,
+ Offset,
+ Length,
+ (UDF_SHORT_ALLOCATION_DESCRIPTOR **)FoundAd
+ );
+ }
+
+ //
+ // Code should never reach here.
+ //
+ ASSERT (FALSE);
+ return EFI_DEVICE_ERROR;
+}
+
+/**
+ Return logical sector number of either Short or Long Allocation Descriptor.
+
+ @param[in] RecordingFlags Flag to indicate the type of descriptor.
+ @param[in] Volume Volume information pointer.
+ @param[in] ParentIcb Long Allocation Descriptor pointer.
+ @param[in] Ad Allocation Descriptor pointer.
+ @param[out] Lsn Logical sector number pointer.
+
+ @retval EFI_SUCCESS Logical sector number of the given Allocation
+ Descriptor successfully returned.
+ @retval EFI_UNSUPPORTED Logical sector number of the given Allocation
+ Descriptor is not returned due to unrecognized
+ format.
+
+**/
+EFI_STATUS
+GetAllocationDescriptorLsn (
+ IN UDF_FE_RECORDING_FLAGS RecordingFlags,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,
+ IN VOID *Ad,
+ OUT UINT64 *Lsn
+ )
+{
+ UDF_PARTITION_DESCRIPTOR *PartitionDesc;
+
+ if (RecordingFlags == LongAdsSequence) {
+ return GetLongAdLsn (Volume, (UDF_LONG_ALLOCATION_DESCRIPTOR *)Ad, Lsn);
+ } else if (RecordingFlags == ShortAdsSequence) {
+ PartitionDesc = GetPdFromLongAd (Volume, ParentIcb);
+ if (PartitionDesc == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *Lsn = GetShortAdLsn (
+ Volume,
+ PartitionDesc,
+ (UDF_SHORT_ALLOCATION_DESCRIPTOR *)Ad
+ );
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Code should never reach here.
+ //
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Return offset + length of a given indirect Allocation Descriptor (AED).
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume Volume information pointer.
+ @param[in] ParentIcb Long Allocation Descriptor pointer.
+ @param[in] RecordingFlags Flag to indicate the type of descriptor.
+ @param[in] Ad Allocation Descriptor pointer.
+ @param[out] Offset Offset of a given indirect Allocation
+ Descriptor.
+ @param[out] Length Length of a given indirect Allocation
+ Descriptor.
+
+ @retval EFI_SUCCESS The offset and length were returned.
+ @retval EFI_OUT_OF_RESOURCES The offset and length were not returned due
+ to lack of resources.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval other The offset and length were not returned.
+
+**/
+EFI_STATUS
+GetAedAdsOffset (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,
+ IN UDF_FE_RECORDING_FLAGS RecordingFlags,
+ IN VOID *Ad,
+ OUT UINT64 *Offset,
+ OUT UINT64 *Length
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ExtentLength;
+ UINT64 Lsn;
+ VOID *Data;
+ UINT32 LogicalBlockSize;
+ UDF_ALLOCATION_EXTENT_DESCRIPTOR *AllocExtDesc;
+ UDF_DESCRIPTOR_TAG *DescriptorTag;
+
+ ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);
+ Status = GetAllocationDescriptorLsn (
+ RecordingFlags,
+ Volume,
+ ParentIcb,
+ Ad,
+ &Lsn
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Data = AllocatePool (ExtentLength);
+ if (Data == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
+
+ //
+ // Read extent.
+ //
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32 (Lsn, LogicalBlockSize),
+ ExtentLength,
+ Data
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ AllocExtDesc = (UDF_ALLOCATION_EXTENT_DESCRIPTOR *)Data;
+
+ DescriptorTag = &AllocExtDesc->DescriptorTag;
+
+ //
+ // Check if read extent contains a valid tag identifier for AED.
+ //
+ if (DescriptorTag->TagIdentifier != UdfAllocationExtentDescriptor) {
+ Status = EFI_VOLUME_CORRUPTED;
+ goto Exit;
+ }
+
+ //
+ // Get AED's block offset and its length.
+ //
+ *Offset = MultU64x32 (Lsn, LogicalBlockSize) +
+ sizeof (UDF_ALLOCATION_EXTENT_DESCRIPTOR);
+ *Length = AllocExtDesc->LengthOfAllocationDescriptors;
+
+Exit:
+ FreePool (Data);
+
+ return Status;
+}
+
+/**
+ Read Allocation Extent Descriptor into memory.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume Volume information pointer.
+ @param[in] ParentIcb Long Allocation Descriptor pointer.
+ @param[in] RecordingFlags Flag to indicate the type of descriptor.
+ @param[in] Ad Allocation Descriptor pointer.
+ @param[out] Data Buffer that contains the Allocation Extent
+ Descriptor.
+ @param[out] Length Length of Data.
+
+ @retval EFI_SUCCESS The Allocation Extent Descriptor was read.
+ @retval EFI_OUT_OF_RESOURCES The Allocation Extent Descriptor was not read
+ due to lack of resources.
+ @retval other Fail to read the disk.
+
+**/
+EFI_STATUS
+GetAedAdsData (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,
+ IN UDF_FE_RECORDING_FLAGS RecordingFlags,
+ IN VOID *Ad,
+ OUT VOID **Data,
+ OUT UINT64 *Length
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Offset;
+
+ //
+ // Get AED's offset + length.
+ //
+ Status = GetAedAdsOffset (
+ BlockIo,
+ DiskIo,
+ Volume,
+ ParentIcb,
+ RecordingFlags,
+ Ad,
+ &Offset,
+ Length
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Allocate buffer to read in AED's data.
+ //
+ *Data = AllocatePool ((UINTN)(*Length));
+ if (*Data == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ Offset,
+ (UINTN)(*Length),
+ *Data
+ );
+}
+
+/**
+ Function used to serialise reads of Allocation Descriptors.
+
+ @param[in] RecordingFlags Flag to indicate the type of descriptor.
+ @param[in] Ad Allocation Descriptor pointer.
+ @param[in, out] Buffer Buffer to hold the next Allocation Descriptor.
+ @param[in] Length Length of Buffer.
+
+ @retval EFI_SUCCESS Buffer was grown to hold the next Allocation
+ Descriptor.
+ @retval EFI_OUT_OF_RESOURCES Buffer was not grown due to lack of resources.
+
+**/
+EFI_STATUS
+GrowUpBufferToNextAd (
+ IN UDF_FE_RECORDING_FLAGS RecordingFlags,
+ IN VOID *Ad,
+ IN OUT VOID **Buffer,
+ IN UINT64 Length
+ )
+{
+ UINT32 ExtentLength;
+
+ ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);
+
+ if (*Buffer == NULL) {
+ *Buffer = AllocatePool (ExtentLength);
+ if (*Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ *Buffer = ReallocatePool ((UINTN)Length, (UINTN)(Length + ExtentLength), *Buffer);
+ if (*Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read data or size of either a File Entry or an Extended File Entry.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume Volume information pointer.
+ @param[in] ParentIcb Long Allocation Descriptor pointer.
+ @param[in] FileEntryData FE/EFE structure pointer.
+ @param[in, out] ReadFileInfo Read file information pointer.
+
+ @retval EFI_SUCCESS Data or size of a FE/EFE was read.
+ @retval EFI_OUT_OF_RESOURCES Data or size of a FE/EFE was not read due to
+ lack of resources.
+ @retval EFI_INVALID_PARAMETER The read file flag given in ReadFileInfo is
+ invalid.
+ @retval EFI_UNSUPPORTED The FE recording flag given in FileEntryData
+ is not supported.
+ @retval other Data or size of a FE/EFE was not read.
+
+**/
+EFI_STATUS
+ReadFile (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,
+ IN VOID *FileEntryData,
+ IN OUT UDF_READ_FILE_INFO *ReadFileInfo
+ )
+{
+ EFI_STATUS Status;
+ UINT32 LogicalBlockSize;
+ VOID *Data;
+ VOID *DataBak;
+ UINT64 Length;
+ VOID *Ad;
+ UINT64 AdOffset;
+ UINT64 Lsn;
+ BOOLEAN DoFreeAed;
+ UINT64 FilePosition;
+ UINT64 Offset;
+ UINT64 DataOffset;
+ UINT64 BytesLeft;
+ UINT64 DataLength;
+ BOOLEAN FinishedSeeking;
+ UINT32 ExtentLength;
+ UDF_FE_RECORDING_FLAGS RecordingFlags;
+
+ LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
+ DoFreeAed = FALSE;
+
+ //
+ // set BytesLeft to suppress incorrect compiler/analyzer warnings
+ //
+ BytesLeft = 0;
+ DataOffset = 0;
+ FilePosition = 0;
+ FinishedSeeking = FALSE;
+ Data = NULL;
+
+ switch (ReadFileInfo->Flags) {
+ case ReadFileGetFileSize:
+ case ReadFileAllocateAndRead:
+ //
+ // Initialise ReadFileInfo structure for either getting file size, or
+ // reading file's recorded data.
+ //
+ ReadFileInfo->ReadLength = 0;
+ ReadFileInfo->FileData = NULL;
+ break;
+ case ReadFileSeekAndRead:
+ //
+ // About to seek a file and/or read its data.
+ //
+ Length = ReadFileInfo->FileSize - ReadFileInfo->FilePosition;
+ if (ReadFileInfo->FileDataSize > Length) {
+ //
+ // About to read beyond the EOF -- truncate it.
+ //
+ ReadFileInfo->FileDataSize = Length;
+ }
+
+ //
+ // Initialise data to start seeking and/or reading a file.
+ //
+ BytesLeft = ReadFileInfo->FileDataSize;
+ DataOffset = 0;
+ FilePosition = 0;
+ FinishedSeeking = FALSE;
+
+ break;
+ }
+
+ RecordingFlags = GET_FE_RECORDING_FLAGS (FileEntryData);
+ switch (RecordingFlags) {
+ case InlineData:
+ //
+ // There are no extents for this FE/EFE. All data is inline.
+ //
+ Status = GetFileEntryData (FileEntryData, Volume->FileEntrySize, &Data, &Length);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (ReadFileInfo->Flags == ReadFileGetFileSize) {
+ ReadFileInfo->ReadLength = Length;
+ } else if (ReadFileInfo->Flags == ReadFileAllocateAndRead) {
+ //
+ // Allocate buffer for starting read data.
+ //
+ ReadFileInfo->FileData = AllocatePool ((UINTN)Length);
+ if (ReadFileInfo->FileData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Read all inline data into ReadFileInfo->FileData
+ //
+ CopyMem (ReadFileInfo->FileData, Data, (UINTN)Length);
+ ReadFileInfo->ReadLength = Length;
+ } else if (ReadFileInfo->Flags == ReadFileSeekAndRead) {
+ //
+ // If FilePosition is non-zero, seek file to FilePosition, read
+ // FileDataSize bytes and then updates FilePosition.
+ //
+ CopyMem (
+ ReadFileInfo->FileData,
+ (VOID *)((UINT8 *)Data + ReadFileInfo->FilePosition),
+ (UINTN)ReadFileInfo->FileDataSize
+ );
+
+ ReadFileInfo->FilePosition += ReadFileInfo->FileDataSize;
+ } else {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ break;
+
+ case LongAdsSequence:
+ case ShortAdsSequence:
+ //
+ // This FE/EFE contains a run of Allocation Descriptors. Get data + size
+ // for start reading them out.
+ //
+ Status = GetAdsInformation (FileEntryData, Volume->FileEntrySize, &Data, &Length);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ AdOffset = 0;
+
+ for ( ; ;) {
+ //
+ // Read AD.
+ //
+ Status = GetAllocationDescriptor (
+ RecordingFlags,
+ Data,
+ &AdOffset,
+ Length,
+ &Ad
+ );
+ if (Status == EFI_DEVICE_ERROR) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ //
+ // Check if AD is an indirect AD. If so, read Allocation Extent
+ // Descriptor and its extents (ADs).
+ //
+ if (GET_EXTENT_FLAGS (RecordingFlags, Ad) == ExtentIsNextExtent) {
+ DataBak = Data;
+ Status = GetAedAdsData (
+ BlockIo,
+ DiskIo,
+ Volume,
+ ParentIcb,
+ RecordingFlags,
+ Ad,
+ &Data,
+ &Length
+ );
+
+ if (!DoFreeAed) {
+ DoFreeAed = TRUE;
+ } else {
+ FreePool (DataBak);
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto Error_Get_Aed;
+ }
+
+ ASSERT (Data != NULL);
+
+ AdOffset = 0;
+ continue;
+ }
+
+ ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);
+
+ Status = GetAllocationDescriptorLsn (
+ RecordingFlags,
+ Volume,
+ ParentIcb,
+ Ad,
+ &Lsn
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ switch (ReadFileInfo->Flags) {
+ case ReadFileGetFileSize:
+ ReadFileInfo->ReadLength += ExtentLength;
+ break;
+ case ReadFileAllocateAndRead:
+ //
+ // Increase FileData (if necessary) to read next extent.
+ //
+ Status = GrowUpBufferToNextAd (
+ RecordingFlags,
+ Ad,
+ &ReadFileInfo->FileData,
+ ReadFileInfo->ReadLength
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Alloc_Buffer_To_Next_Ad;
+ }
+
+ //
+ // Read extent's data into FileData.
+ //
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32 (Lsn, LogicalBlockSize),
+ ExtentLength,
+ (VOID *)((UINT8 *)ReadFileInfo->FileData +
+ ReadFileInfo->ReadLength)
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Read_Disk_Blk;
+ }
+
+ ReadFileInfo->ReadLength += ExtentLength;
+ break;
+ case ReadFileSeekAndRead:
+ //
+ // Seek file first before reading in its data.
+ //
+ if (FinishedSeeking) {
+ Offset = 0;
+ goto Skip_File_Seek;
+ }
+
+ if (FilePosition + ExtentLength < ReadFileInfo->FilePosition) {
+ FilePosition += ExtentLength;
+ goto Skip_Ad;
+ }
+
+ if (FilePosition + ExtentLength > ReadFileInfo->FilePosition) {
+ Offset = ReadFileInfo->FilePosition - FilePosition;
+ } else {
+ Offset = 0;
+ }
+
+ //
+ // Done with seeking file. Start reading its data.
+ //
+ FinishedSeeking = TRUE;
+
+Skip_File_Seek:
+ //
+ // Make sure we don't read more data than really wanted.
+ //
+ if (ExtentLength - Offset > BytesLeft) {
+ DataLength = BytesLeft;
+ } else {
+ DataLength = ExtentLength - Offset;
+ }
+
+ //
+ // Read extent's data into FileData.
+ //
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ Offset + MultU64x32 (Lsn, LogicalBlockSize),
+ (UINTN)DataLength,
+ (VOID *)((UINT8 *)ReadFileInfo->FileData +
+ DataOffset)
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Read_Disk_Blk;
+ }
+
+ //
+ // Update current file's position.
+ //
+ DataOffset += DataLength;
+ ReadFileInfo->FilePosition += DataLength;
+
+ BytesLeft -= DataLength;
+ if (BytesLeft == 0) {
+ //
+ // There is no more file data to read.
+ //
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ break;
+ }
+
+Skip_Ad:
+ //
+ // Point to the next AD (extent).
+ //
+ AdOffset += AD_LENGTH (RecordingFlags);
+ }
+
+ break;
+ case ExtendedAdsSequence:
+ // FIXME: Not supported. Got no volume with it, yet.
+ ASSERT (FALSE);
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ default:
+ //
+ // A flag value reserved by the ECMA-167 standard (3rd Edition - June
+ // 1997); 14.6 ICB Tag; 14.6.8 Flags (RBP 18); was found.
+ //
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+Done:
+ if (DoFreeAed) {
+ FreePool (Data);
+ }
+
+ return Status;
+
+Error_Read_Disk_Blk:
+Error_Alloc_Buffer_To_Next_Ad:
+ if (ReadFileInfo->Flags != ReadFileSeekAndRead) {
+ FreePool (ReadFileInfo->FileData);
+ }
+
+ if (DoFreeAed) {
+ FreePool (Data);
+ }
+
+Error_Get_Aed:
+ return Status;
+}
+
+/**
+ Find a file by its filename from a given Parent file.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume Volume information pointer.
+ @param[in] FileName File name string.
+ @param[in] Parent Parent directory file.
+ @param[in] Icb Long Allocation Descriptor pointer.
+ @param[out] File Found file.
+
+ @retval EFI_SUCCESS The file was found.
+ @retval EFI_INVALID_PARAMETER One or more input parameters are invalid.
+ @retval EFI_NOT_FOUND The file was not found.
+
+**/
+EFI_STATUS
+InternalFindFile (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN CHAR16 *FileName,
+ IN UDF_FILE_INFO *Parent,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb,
+ OUT UDF_FILE_INFO *File
+ )
+{
+ EFI_STATUS Status;
+ UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc;
+ UDF_READ_DIRECTORY_INFO ReadDirInfo;
+ BOOLEAN Found;
+ CHAR16 FoundFileName[UDF_FILENAME_LENGTH];
+ VOID *CompareFileEntry;
+
+ //
+ // Check if both Parent->FileIdentifierDesc and Icb are NULL.
+ //
+ if ((Parent->FileIdentifierDesc == NULL) && (Icb == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if parent file is really directory.
+ //
+ if (FE_ICB_FILE_TYPE (Parent->FileEntry) != UdfFileEntryDirectory) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // If FileName is current file or working directory, just duplicate Parent's
+ // FE/EFE and FID descriptors.
+ //
+ if (StrCmp (FileName, L".") == 0) {
+ if (Parent->FileIdentifierDesc == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DuplicateFe (BlockIo, Volume, Parent->FileEntry, &File->FileEntry);
+ if (File->FileEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DuplicateFid (Parent->FileIdentifierDesc, &File->FileIdentifierDesc);
+ if (File->FileIdentifierDesc == NULL) {
+ FreePool (File->FileEntry);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Start directory listing.
+ //
+ ZeroMem ((VOID *)&ReadDirInfo, sizeof (UDF_READ_DIRECTORY_INFO));
+ Found = FALSE;
+
+ for ( ; ;) {
+ Status = ReadDirectoryEntry (
+ BlockIo,
+ DiskIo,
+ Volume,
+ (Parent->FileIdentifierDesc != NULL) ?
+ &Parent->FileIdentifierDesc->Icb :
+ Icb,
+ Parent->FileEntry,
+ &ReadDirInfo,
+ &FileIdentifierDesc
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_DEVICE_ERROR) {
+ Status = EFI_NOT_FOUND;
+ }
+
+ break;
+ }
+
+ //
+ // After calling function ReadDirectoryEntry(), if 'FileIdentifierDesc' is
+ // NULL, then the 'Status' must be EFI_OUT_OF_RESOURCES. Hence, if the code
+ // reaches here, 'FileIdentifierDesc' must be not NULL.
+ //
+ // The ASSERT here is for addressing a false positive NULL pointer
+ // dereference issue raised from static analysis.
+ //
+ ASSERT (FileIdentifierDesc != NULL);
+
+ if (FileIdentifierDesc->FileCharacteristics & PARENT_FILE) {
+ //
+ // This FID contains the location (FE/EFE) of the parent directory of this
+ // directory (Parent), and if FileName is either ".." or "\\", then it's
+ // the expected FID.
+ //
+ if ((StrCmp (FileName, L"..") == 0) || (StrCmp (FileName, L"\\") == 0)) {
+ Found = TRUE;
+ break;
+ }
+ } else {
+ Status = GetFileNameFromFid (FileIdentifierDesc, ARRAY_SIZE (FoundFileName), FoundFileName);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (StrCmp (FileName, FoundFileName) == 0) {
+ //
+ // FID has been found. Prepare to find its respective FE/EFE.
+ //
+ Found = TRUE;
+ break;
+ }
+ }
+
+ FreePool ((VOID *)FileIdentifierDesc);
+ }
+
+ if (ReadDirInfo.DirectoryData != NULL) {
+ //
+ // Free all allocated resources for the directory listing.
+ //
+ FreePool (ReadDirInfo.DirectoryData);
+ }
+
+ if (Found) {
+ Status = EFI_SUCCESS;
+
+ File->FileIdentifierDesc = FileIdentifierDesc;
+
+ //
+ // If the requested file is root directory, then the FE/EFE was already
+ // retrieved in UdfOpenVolume() function, thus no need to find it again.
+ //
+ // Otherwise, find FE/EFE from the respective FID.
+ //
+ if (StrCmp (FileName, L"\\") != 0) {
+ Status = FindFileEntry (
+ BlockIo,
+ DiskIo,
+ Volume,
+ &FileIdentifierDesc->Icb,
+ &CompareFileEntry
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Find_Fe;
+ }
+
+ //
+ // Make sure that both Parent's FE/EFE and found FE/EFE are not equal.
+ //
+ if (CompareMem (
+ (VOID *)Parent->FileEntry,
+ (VOID *)CompareFileEntry,
+ Volume->FileEntrySize
+ ) != 0)
+ {
+ File->FileEntry = CompareFileEntry;
+ } else {
+ FreePool ((VOID *)FileIdentifierDesc);
+ FreePool ((VOID *)CompareFileEntry);
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ }
+
+ return Status;
+
+Error_Find_Fe:
+ FreePool ((VOID *)FileIdentifierDesc);
+
+ return Status;
+}
+
+/**
+ Read volume information on a medium which contains a valid UDF file system.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[out] Volume UDF volume information structure.
+
+ @retval EFI_SUCCESS Volume information read.
+ @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 volume was not read due to lack of resources.
+
+**/
+EFI_STATUS
+ReadUdfVolumeInformation (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ OUT UDF_VOLUME_INFO *Volume
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Read all necessary UDF volume information and keep it private to the driver
+ //
+ Status = ReadVolumeFileStructure (
+ BlockIo,
+ DiskIo,
+ Volume
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Find File Set Descriptor
+ //
+ Status = FindFileSetDescriptor (BlockIo, DiskIo, Volume);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return Status;
+}
+
+/**
+ Find the root directory on an UDF volume.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[out] File Root directory file.
+
+ @retval EFI_SUCCESS Root directory found.
+ @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 root directory was not found due to lack of
+ resources.
+
+**/
+EFI_STATUS
+FindRootDirectory (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ OUT UDF_FILE_INFO *File
+ )
+{
+ EFI_STATUS Status;
+ UDF_FILE_INFO Parent;
+
+ Status = FindFileEntry (
+ BlockIo,
+ DiskIo,
+ Volume,
+ &Volume->FileSetDesc.RootDirectoryIcb,
+ &File->FileEntry
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Parent.FileEntry = File->FileEntry;
+ Parent.FileIdentifierDesc = NULL;
+
+ Status = FindFile (
+ BlockIo,
+ DiskIo,
+ Volume,
+ L"\\",
+ NULL,
+ &Parent,
+ &Volume->FileSetDesc.RootDirectoryIcb,
+ File
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (File->FileEntry);
+ }
+
+ return Status;
+}
+
+/**
+ Find either a File Entry or a Extended File Entry from a given ICB.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[in] Icb ICB of the FID.
+ @param[out] FileEntry File Entry or Extended File Entry.
+
+ @retval EFI_SUCCESS File Entry or Extended File Entry found.
+ @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 FE/EFE entry was not found due to lack of
+ resources.
+
+**/
+EFI_STATUS
+FindFileEntry (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb,
+ OUT VOID **FileEntry
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Lsn;
+ UINT32 LogicalBlockSize;
+ UDF_DESCRIPTOR_TAG *DescriptorTag;
+ VOID *ReadBuffer;
+
+ Status = GetLongAdLsn (Volume, Icb, &Lsn);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
+
+ ReadBuffer = AllocateZeroPool (Volume->FileEntrySize);
+ if (ReadBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Read extent.
+ //
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32 (Lsn, LogicalBlockSize),
+ Volume->FileEntrySize,
+ ReadBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Read_Disk_Blk;
+ }
+
+ DescriptorTag = ReadBuffer;
+
+ //
+ // Check if the read extent contains a valid Tag Identifier for the expected
+ // FE/EFE.
+ //
+ if ((DescriptorTag->TagIdentifier != UdfFileEntry) &&
+ (DescriptorTag->TagIdentifier != UdfExtendedFileEntry))
+ {
+ Status = EFI_VOLUME_CORRUPTED;
+ goto Error_Invalid_Fe;
+ }
+
+ *FileEntry = ReadBuffer;
+ return EFI_SUCCESS;
+
+Error_Invalid_Fe:
+Error_Read_Disk_Blk:
+ FreePool (ReadBuffer);
+
+ return Status;
+}
+
+/**
+ Find a file given its absolute path on an UDF volume.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[in] FilePath File's absolute path.
+ @param[in] Root Root directory file.
+ @param[in] Parent Parent directory file.
+ @param[in] Icb ICB of Parent.
+ @param[out] File Found file.
+
+ @retval EFI_SUCCESS FilePath was found.
+ @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 FilePath file was not found due to lack of
+ resources.
+
+**/
+EFI_STATUS
+FindFile (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN CHAR16 *FilePath,
+ IN UDF_FILE_INFO *Root,
+ IN UDF_FILE_INFO *Parent,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb,
+ OUT UDF_FILE_INFO *File
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 FileName[UDF_FILENAME_LENGTH];
+ CHAR16 *FileNamePointer;
+ UDF_FILE_INFO PreviousFile;
+ VOID *FileEntry;
+
+ Status = EFI_NOT_FOUND;
+
+ CopyMem ((VOID *)&PreviousFile, (VOID *)Parent, sizeof (UDF_FILE_INFO));
+ while (*FilePath != L'\0') {
+ FileNamePointer = FileName;
+ while (*FilePath != L'\0' && *FilePath != L'\\') {
+ if ((((UINTN)FileNamePointer - (UINTN)FileName) / sizeof (CHAR16)) >=
+ (ARRAY_SIZE (FileName) - 1))
+ {
+ return EFI_NOT_FOUND;
+ }
+
+ *FileNamePointer++ = *FilePath++;
+ }
+
+ *FileNamePointer = L'\0';
+ if (FileName[0] == L'\0') {
+ //
+ // Open root directory.
+ //
+ if (Root == NULL) {
+ //
+ // There is no file found for the root directory yet. So, find only its
+ // FID by now.
+ //
+ // See UdfOpenVolume() function.
+ //
+ Status = InternalFindFile (
+ BlockIo,
+ DiskIo,
+ Volume,
+ L"\\",
+ &PreviousFile,
+ Icb,
+ File
+ );
+ } else {
+ //
+ // We've already a file pointer (Root) for the root directory. Duplicate
+ // its FE/EFE and FID descriptors.
+ //
+ Status = EFI_SUCCESS;
+ DuplicateFe (BlockIo, Volume, Root->FileEntry, &File->FileEntry);
+ if (File->FileEntry == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ //
+ // File->FileEntry is not NULL.
+ //
+ DuplicateFid (Root->FileIdentifierDesc, &File->FileIdentifierDesc);
+ if (File->FileIdentifierDesc == NULL) {
+ FreePool (File->FileEntry);
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+ }
+ } else {
+ //
+ // No root directory. Find filename from the current directory.
+ //
+ Status = InternalFindFile (
+ BlockIo,
+ DiskIo,
+ Volume,
+ FileName,
+ &PreviousFile,
+ Icb,
+ File
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // If the found file is a symlink, then find its respective FE/EFE and
+ // FID descriptors.
+ //
+ if (FE_ICB_FILE_TYPE (File->FileEntry) == UdfFileEntrySymlink) {
+ FreePool ((VOID *)File->FileIdentifierDesc);
+
+ FileEntry = File->FileEntry;
+
+ Status = ResolveSymlink (
+ BlockIo,
+ DiskIo,
+ Volume,
+ &PreviousFile,
+ FileEntry,
+ File
+ );
+
+ FreePool (FileEntry);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ if (CompareMem (
+ (VOID *)&PreviousFile,
+ (VOID *)Parent,
+ sizeof (UDF_FILE_INFO)
+ ) != 0)
+ {
+ CleanupFileInformation (&PreviousFile);
+ }
+
+ CopyMem ((VOID *)&PreviousFile, (VOID *)File, sizeof (UDF_FILE_INFO));
+ if ((*FilePath != L'\0') && (*FilePath == L'\\')) {
+ FilePath++;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Read a directory entry at a time on an UDF volume.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[in] ParentIcb ICB of the parent file.
+ @param[in] FileEntryData FE/EFE of the parent file.
+ @param[in, out] ReadDirInfo Next read directory listing structure
+ information.
+ @param[out] FoundFid File Identifier Descriptor pointer.
+
+ @retval EFI_SUCCESS Directory entry 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 directory entry was not read due to lack of
+ resources.
+
+**/
+EFI_STATUS
+ReadDirectoryEntry (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,
+ IN VOID *FileEntryData,
+ IN OUT UDF_READ_DIRECTORY_INFO *ReadDirInfo,
+ OUT UDF_FILE_IDENTIFIER_DESCRIPTOR **FoundFid
+ )
+{
+ EFI_STATUS Status;
+ UDF_READ_FILE_INFO ReadFileInfo;
+ UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc;
+
+ 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.
+ //
+ ReadFileInfo.Flags = ReadFileAllocateAndRead;
+
+ Status = ReadFile (
+ BlockIo,
+ DiskIo,
+ Volume,
+ ParentIcb,
+ FileEntryData,
+ &ReadFileInfo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Fill in ReadDirInfo structure with the read directory's data information.
+ //
+ ReadDirInfo->DirectoryData = ReadFileInfo.FileData;
+ ReadDirInfo->DirectoryLength = ReadFileInfo.ReadLength;
+ }
+
+ do {
+ if (ReadDirInfo->FidOffset >= ReadDirInfo->DirectoryLength) {
+ //
+ // There are no longer FIDs for this directory. By returning
+ // EFI_DEVICE_ERROR to the callee will indicate end of directory
+ // listening.
+ //
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get FID for this entry.
+ //
+ FileIdentifierDesc = GET_FID_FROM_ADS (
+ ReadDirInfo->DirectoryData,
+ ReadDirInfo->FidOffset
+ );
+ //
+ // Update FidOffset to point to next FID.
+ //
+ ReadDirInfo->FidOffset += GetFidDescriptorLength (FileIdentifierDesc);
+ } while (FileIdentifierDesc->FileCharacteristics & DELETED_FILE);
+
+ DuplicateFid (FileIdentifierDesc, FoundFid);
+ if (*FoundFid == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get a filename (encoded in OSTA-compressed format) from a File Identifier
+ Descriptor on an UDF volume.
+
+ @attention This is boundary function that may receive untrusted input.
+ @attention The input is from FileSystem.
+
+ The File Identifier Descriptor is external input, so this routine will do
+ basic validation for File Identifier Descriptor and report status.
+
+ @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
+ @param[in] CharMax The maximum number of FileName Unicode char,
+ including terminating null char.
+ @param[out] FileName Decoded filename.
+
+ @retval EFI_SUCCESS Filename decoded and read.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TOO_SMALL The string buffer FileName cannot hold the
+ decoded filename.
+**/
+EFI_STATUS
+GetFileNameFromFid (
+ IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc,
+ IN UINTN CharMax,
+ OUT CHAR16 *FileName
+ )
+{
+ UINT8 *OstaCompressed;
+ UINT8 CompressionId;
+ UINT8 Length;
+ UINTN Index;
+ CHAR16 *FileNameBak;
+
+ if (CharMax == 0) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ OstaCompressed =
+ (UINT8 *)(
+ (UINT8 *)FileIdentifierDesc->Data +
+ FileIdentifierDesc->LengthOfImplementationUse
+ );
+
+ CompressionId = OstaCompressed[0];
+ if (!IS_VALID_COMPRESSION_ID (CompressionId)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ FileNameBak = FileName;
+
+ //
+ // Decode filename.
+ //
+ Length = FileIdentifierDesc->LengthOfFileIdentifier;
+ if (CompressionId == 16) {
+ if (((UINTN)Length >> 1) > CharMax) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ } else {
+ if ((Length != 0) && ((UINTN)Length - 1 > CharMax)) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ }
+
+ for (Index = 1; Index < Length; Index++) {
+ if (CompressionId == 16) {
+ *FileName = OstaCompressed[Index++] << 8;
+ } else {
+ *FileName = 0;
+ }
+
+ if (Index < Length) {
+ *FileName |= (CHAR16)(OstaCompressed[Index]);
+ }
+
+ FileName++;
+ }
+
+ Index = ((UINTN)FileName - (UINTN)FileNameBak) / sizeof (CHAR16);
+ if (Index > CharMax - 1) {
+ Index = CharMax - 1;
+ }
+
+ FileNameBak[Index] = L'\0';
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Resolve a symlink file on an UDF volume.
+
+ @attention This is boundary function that may receive untrusted input.
+ @attention The input is from FileSystem.
+
+ The Path Component is external input, so this routine will do basic
+ validation for Path Component and report status.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[in] Parent Parent file.
+ @param[in] FileEntryData FE/EFE structure pointer.
+ @param[out] File Resolved file.
+
+ @retval EFI_SUCCESS Symlink file resolved.
+ @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 symlink file was not resolved due to lack of
+ resources.
+
+**/
+EFI_STATUS
+ResolveSymlink (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_FILE_INFO *Parent,
+ IN VOID *FileEntryData,
+ OUT UDF_FILE_INFO *File
+ )
+{
+ EFI_STATUS Status;
+ UDF_READ_FILE_INFO ReadFileInfo;
+ UINT8 *Data;
+ UINT64 Length;
+ UINT8 *EndData;
+ UDF_PATH_COMPONENT *PathComp;
+ UINT8 PathCompLength;
+ CHAR16 FileName[UDF_FILENAME_LENGTH];
+ CHAR16 *Char;
+ UINTN Index;
+ UINT8 CompressionId;
+ UDF_FILE_INFO PreviousFile;
+ BOOLEAN NotParent;
+ BOOLEAN NotFile;
+
+ ZeroMem ((VOID *)File, sizeof (UDF_FILE_INFO));
+
+ //
+ // Symlink files on UDF volumes do not contain so much data other than
+ // Path Components which resolves to real filenames, so it's OK to read in
+ // all its data here -- usually the data will be inline with the FE/EFE for
+ // lower filenames.
+ //
+ ReadFileInfo.Flags = ReadFileAllocateAndRead;
+
+ Status = ReadFile (
+ BlockIo,
+ DiskIo,
+ Volume,
+ &Parent->FileIdentifierDesc->Icb,
+ FileEntryData,
+ &ReadFileInfo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Length = ReadFileInfo.ReadLength;
+
+ Data = (UINT8 *)ReadFileInfo.FileData;
+ EndData = Data + Length;
+
+ CopyMem ((VOID *)&PreviousFile, (VOID *)Parent, sizeof (UDF_FILE_INFO));
+
+ for ( ; ;) {
+ PathComp = (UDF_PATH_COMPONENT *)Data;
+
+ PathCompLength = PathComp->LengthOfComponentIdentifier;
+
+ switch (PathComp->ComponentType) {
+ case 1:
+ //
+ // This Path Component specifies the root directory hierarchy subject to
+ // agreement between the originator and recipient of the medium. Skip it.
+ //
+ // Fall through.
+ //
+ case 2:
+ //
+ // "\\." of the current directory. Read next Path Component.
+ //
+ goto Next_Path_Component;
+ case 3:
+ //
+ // ".." (parent directory). Go to it.
+ //
+ CopyMem ((VOID *)FileName, L"..", 6);
+ break;
+ case 4:
+ //
+ // "." (current file). Duplicate both FE/EFE and FID of this file.
+ //
+ DuplicateFe (BlockIo, Volume, PreviousFile.FileEntry, &File->FileEntry);
+ if (File->FileEntry == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error_Find_File;
+ }
+
+ DuplicateFid (
+ PreviousFile.FileIdentifierDesc,
+ &File->FileIdentifierDesc
+ );
+ if (File->FileIdentifierDesc == NULL) {
+ FreePool (File->FileEntry);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error_Find_File;
+ }
+
+ goto Next_Path_Component;
+ case 5:
+ //
+ // This Path Component identifies an object, either a file or a
+ // directory or an alias.
+ //
+ // Decode it from the compressed data in ComponentIdentifier and find
+ // respective path.
+ //
+ CompressionId = PathComp->ComponentIdentifier[0];
+ if (!IS_VALID_COMPRESSION_ID (CompressionId)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ if ((UINTN)PathComp->ComponentIdentifier + PathCompLength > (UINTN)EndData) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ Char = FileName;
+ for (Index = 1; Index < PathCompLength; Index++) {
+ if (CompressionId == 16) {
+ *Char = *(UINT8 *)((UINT8 *)PathComp->ComponentIdentifier +
+ Index) << 8;
+ Index++;
+ } else {
+ if (Index > ARRAY_SIZE (FileName)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *Char = 0;
+ }
+
+ if (Index < Length) {
+ *Char |= (CHAR16)(*(UINT8 *)((UINT8 *)PathComp->ComponentIdentifier + Index));
+ }
+
+ Char++;
+ }
+
+ Index = ((UINTN)Char - (UINTN)FileName) / sizeof (CHAR16);
+ if (Index > ARRAY_SIZE (FileName) - 1) {
+ Index = ARRAY_SIZE (FileName) - 1;
+ }
+
+ FileName[Index] = L'\0';
+ break;
+ default:
+ //
+ // According to the ECMA-167 standard (3rd Edition - June 1997), Section
+ // 14.16.1.1, all other values are reserved.
+ //
+ Status = EFI_VOLUME_CORRUPTED;
+ goto Error_Find_File;
+ }
+
+ //
+ // Find file from the read filename in symlink's file data.
+ //
+ Status = InternalFindFile (
+ BlockIo,
+ DiskIo,
+ Volume,
+ FileName,
+ &PreviousFile,
+ NULL,
+ File
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error_Find_File;
+ }
+
+Next_Path_Component:
+ Data += sizeof (UDF_PATH_COMPONENT) + PathCompLength;
+ if (Data >= EndData) {
+ break;
+ }
+
+ //
+ // Check the content in the file info pointed by File.
+ //
+ if ((File->FileEntry == NULL) || (File->FileIdentifierDesc == NULL)) {
+ Status = EFI_VOLUME_CORRUPTED;
+ goto Error_Find_File;
+ }
+
+ NotParent = (CompareMem (
+ (VOID *)&PreviousFile,
+ (VOID *)Parent,
+ sizeof (UDF_FILE_INFO)
+ ) != 0);
+ NotFile = (CompareMem (
+ (VOID *)&PreviousFile,
+ (VOID *)File,
+ sizeof (UDF_FILE_INFO)
+ ) != 0);
+
+ if (NotParent && NotFile) {
+ CleanupFileInformation (&PreviousFile);
+ }
+
+ if (NotFile) {
+ CopyMem ((VOID *)&PreviousFile, (VOID *)File, sizeof (UDF_FILE_INFO));
+ }
+ }
+
+ //
+ // Unmap the symlink file.
+ //
+ FreePool (ReadFileInfo.FileData);
+
+ //
+ // Check the content in the resolved file info.
+ //
+ if ((File->FileEntry == NULL) || (File->FileIdentifierDesc == NULL)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ return EFI_SUCCESS;
+
+Error_Find_File:
+ if (CompareMem (
+ (VOID *)&PreviousFile,
+ (VOID *)Parent,
+ sizeof (UDF_FILE_INFO)
+ ) != 0)
+ {
+ CleanupFileInformation (&PreviousFile);
+ }
+
+ FreePool (ReadFileInfo.FileData);
+
+ return Status;
+}
+
+/**
+ Clean up in-memory UDF file information.
+
+ @param[in] File File information pointer.
+
+**/
+VOID
+CleanupFileInformation (
+ IN UDF_FILE_INFO *File
+ )
+{
+ if (File->FileEntry != NULL) {
+ FreePool (File->FileEntry);
+ }
+
+ if (File->FileIdentifierDesc != NULL) {
+ FreePool ((VOID *)File->FileIdentifierDesc);
+ }
+
+ ZeroMem ((VOID *)File, sizeof (UDF_FILE_INFO));
+}
+
+/**
+ Find a file from its absolute path 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[out] Size Size of the file.
+
+ @retval EFI_SUCCESS File size calculated and set in Size.
+ @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 size was not calculated due to lack of
+ resources.
+
+**/
+EFI_STATUS
+GetFileSize (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_FILE_INFO *File,
+ OUT UINT64 *Size
+ )
+{
+ EFI_STATUS Status;
+ UDF_READ_FILE_INFO ReadFileInfo;
+
+ ReadFileInfo.Flags = ReadFileGetFileSize;
+
+ Status = ReadFile (
+ BlockIo,
+ DiskIo,
+ Volume,
+ &File->FileIdentifierDesc->Icb,
+ File->FileEntry,
+ &ReadFileInfo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *Size = ReadFileInfo.ReadLength;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set information about a file on an UDF volume.
+
+ @param[in] File File pointer.
+ @param[in] FileSize Size of the file.
+ @param[in] FileName Filename of the file.
+ @param[in, out] BufferSize Size of the returned file infomation.
+ @param[out] Buffer Data of the returned file information.
+
+ @retval EFI_SUCCESS File information set.
+ @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 information was not set due to lack of
+ resources.
+
+**/
+EFI_STATUS
+SetFileInfo (
+ IN UDF_FILE_INFO *File,
+ IN UINT64 FileSize,
+ IN CHAR16 *FileName,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ UINTN FileInfoLength;
+ EFI_FILE_INFO *FileInfo;
+ UDF_FILE_ENTRY *FileEntry;
+ UDF_EXTENDED_FILE_ENTRY *ExtendedFileEntry;
+ UDF_DESCRIPTOR_TAG *DescriptorTag;
+
+ //
+ // Calculate the needed size for the EFI_FILE_INFO structure.
+ //
+ FileInfoLength = sizeof (EFI_FILE_INFO) + ((FileName != NULL) ?
+ StrSize (FileName) :
+ sizeof (CHAR16));
+ if (*BufferSize < FileInfoLength) {
+ //
+ // The given Buffer has no size enough for EFI_FILE_INFO structure.
+ //
+ *BufferSize = FileInfoLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Buffer now contains room enough to store EFI_FILE_INFO structure.
+ // Now, fill it in with all necessary information about the file.
+ //
+ FileInfo = (EFI_FILE_INFO *)Buffer;
+ FileInfo->Size = FileInfoLength;
+ FileInfo->Attribute &= ~EFI_FILE_VALID_ATTR;
+ FileInfo->Attribute |= EFI_FILE_READ_ONLY;
+
+ if (IS_FID_DIRECTORY_FILE (File->FileIdentifierDesc)) {
+ FileInfo->Attribute |= EFI_FILE_DIRECTORY;
+ } else if (IS_FID_NORMAL_FILE (File->FileIdentifierDesc)) {
+ FileInfo->Attribute |= EFI_FILE_ARCHIVE;
+ }
+
+ if (IS_FID_HIDDEN_FILE (File->FileIdentifierDesc)) {
+ FileInfo->Attribute |= EFI_FILE_HIDDEN;
+ }
+
+ DescriptorTag = File->FileEntry;
+
+ if (DescriptorTag->TagIdentifier == UdfFileEntry) {
+ FileEntry = (UDF_FILE_ENTRY *)File->FileEntry;
+
+ //
+ // Check if FE has the system attribute set.
+ //
+ if (FileEntry->IcbTag.Flags & (1 << 10)) {
+ FileInfo->Attribute |= EFI_FILE_SYSTEM;
+ }
+
+ FileInfo->FileSize = FileSize;
+ FileInfo->PhysicalSize = FileSize;
+
+ FileInfo->CreateTime.Year = FileEntry->AccessTime.Year;
+ FileInfo->CreateTime.Month = FileEntry->AccessTime.Month;
+ FileInfo->CreateTime.Day = FileEntry->AccessTime.Day;
+ FileInfo->CreateTime.Hour = FileEntry->AccessTime.Hour;
+ FileInfo->CreateTime.Minute = FileEntry->AccessTime.Minute;
+ FileInfo->CreateTime.Second = FileEntry->AccessTime.Second;
+ FileInfo->CreateTime.Nanosecond =
+ FileEntry->AccessTime.HundredsOfMicroseconds;
+
+ FileInfo->LastAccessTime.Year =
+ FileEntry->AccessTime.Year;
+ FileInfo->LastAccessTime.Month =
+ FileEntry->AccessTime.Month;
+ FileInfo->LastAccessTime.Day =
+ FileEntry->AccessTime.Day;
+ FileInfo->LastAccessTime.Hour =
+ FileEntry->AccessTime.Hour;
+ FileInfo->LastAccessTime.Minute =
+ FileEntry->AccessTime.Minute;
+ FileInfo->LastAccessTime.Second =
+ FileEntry->AccessTime.Second;
+ FileInfo->LastAccessTime.Nanosecond =
+ FileEntry->AccessTime.HundredsOfMicroseconds;
+ } else if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {
+ ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)File->FileEntry;
+
+ //
+ // Check if EFE has the system attribute set.
+ //
+ if (ExtendedFileEntry->IcbTag.Flags & (1 << 10)) {
+ FileInfo->Attribute |= EFI_FILE_SYSTEM;
+ }
+
+ FileInfo->FileSize = FileSize;
+ FileInfo->PhysicalSize = FileSize;
+
+ FileInfo->CreateTime.Year = ExtendedFileEntry->CreationTime.Year;
+ FileInfo->CreateTime.Month = ExtendedFileEntry->CreationTime.Month;
+ FileInfo->CreateTime.Day = ExtendedFileEntry->CreationTime.Day;
+ FileInfo->CreateTime.Hour = ExtendedFileEntry->CreationTime.Hour;
+ FileInfo->CreateTime.Minute = ExtendedFileEntry->CreationTime.Second;
+ FileInfo->CreateTime.Second = ExtendedFileEntry->CreationTime.Second;
+ FileInfo->CreateTime.Nanosecond =
+ ExtendedFileEntry->AccessTime.HundredsOfMicroseconds;
+
+ FileInfo->LastAccessTime.Year =
+ ExtendedFileEntry->AccessTime.Year;
+ FileInfo->LastAccessTime.Month =
+ ExtendedFileEntry->AccessTime.Month;
+ FileInfo->LastAccessTime.Day =
+ ExtendedFileEntry->AccessTime.Day;
+ FileInfo->LastAccessTime.Hour =
+ ExtendedFileEntry->AccessTime.Hour;
+ FileInfo->LastAccessTime.Minute =
+ ExtendedFileEntry->AccessTime.Minute;
+ FileInfo->LastAccessTime.Second =
+ ExtendedFileEntry->AccessTime.Second;
+ FileInfo->LastAccessTime.Nanosecond =
+ ExtendedFileEntry->AccessTime.HundredsOfMicroseconds;
+ }
+
+ FileInfo->CreateTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ FileInfo->CreateTime.Daylight = EFI_TIME_ADJUST_DAYLIGHT;
+ FileInfo->LastAccessTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ FileInfo->LastAccessTime.Daylight = EFI_TIME_ADJUST_DAYLIGHT;
+
+ CopyMem (
+ (VOID *)&FileInfo->ModificationTime,
+ (VOID *)&FileInfo->LastAccessTime,
+ sizeof (EFI_TIME)
+ );
+
+ if (FileName != NULL) {
+ StrCpyS (FileInfo->FileName, StrLen (FileName) + 1, FileName);
+ } else {
+ FileInfo->FileName[0] = '\0';
+ }
+
+ *BufferSize = FileInfoLength;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get volume label of an UDF volume.
+
+ @attention This is boundary function that may receive untrusted input.
+ @attention The input is from FileSystem.
+
+ The File Set Descriptor is external input, so this routine will do basic
+ validation for File Set Descriptor and report status.
+
+ @param[in] Volume Volume information pointer.
+ @param[in] CharMax The maximum number of Unicode char in String,
+ including terminating null char.
+ @param[out] String String buffer pointer to store the volume label.
+
+ @retval EFI_SUCCESS Volume label is returned.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TOO_SMALL The string buffer String cannot hold the
+ volume label.
+
+**/
+EFI_STATUS
+GetVolumeLabel (
+ IN UDF_VOLUME_INFO *Volume,
+ IN UINTN CharMax,
+ OUT CHAR16 *String
+ )
+{
+ UDF_FILE_SET_DESCRIPTOR *FileSetDesc;
+ UINTN Index;
+ UINT8 *OstaCompressed;
+ UINT8 CompressionId;
+ CHAR16 *StringBak;
+
+ FileSetDesc = &Volume->FileSetDesc;
+
+ OstaCompressed = &FileSetDesc->LogicalVolumeIdentifier[0];
+
+ CompressionId = OstaCompressed[0];
+ if (!IS_VALID_COMPRESSION_ID (CompressionId)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ StringBak = String;
+ for (Index = 1; Index < 128; Index++) {
+ if (CompressionId == 16) {
+ if ((Index >> 1) > CharMax) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *String = *(UINT8 *)(OstaCompressed + Index) << 8;
+ Index++;
+ } else {
+ if (Index > CharMax) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *String = 0;
+ }
+
+ if (Index < 128) {
+ *String |= (CHAR16)(*(UINT8 *)(OstaCompressed + Index));
+ }
+
+ //
+ // Unlike FID Identifiers, Logical Volume Identifier is stored in a
+ // NULL-terminated OSTA compressed format, so we must check for the NULL
+ // character.
+ //
+ if (*String == L'\0') {
+ break;
+ }
+
+ String++;
+ }
+
+ Index = ((UINTN)String - (UINTN)StringBak) / sizeof (CHAR16);
+ if (Index > CharMax - 1) {
+ Index = CharMax - 1;
+ }
+
+ StringBak[Index] = L'\0';
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get volume and free space size information of an UDF volume.
+
+ @attention This is boundary function that may receive untrusted input.
+ @attention The input is from FileSystem.
+
+ The Logical Volume Descriptor and the Logical Volume Integrity Descriptor are
+ external inputs, so this routine will do basic validation for both descriptors
+ and report status.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[out] VolumeSize Volume size.
+ @param[out] FreeSpaceSize Free space size.
+
+ @retval EFI_SUCCESS Volume and free space size calculated.
+ @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 volume and free space size were not
+ calculated due to lack of resources.
+
+**/
+EFI_STATUS
+GetVolumeSize (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ OUT UINT64 *VolumeSize,
+ OUT UINT64 *FreeSpaceSize
+ )
+{
+ EFI_STATUS Status;
+ UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;
+ UDF_EXTENT_AD *ExtentAd;
+ UINT64 Lsn;
+ UINT32 LogicalBlockSize;
+ UDF_LOGICAL_VOLUME_INTEGRITY *LogicalVolInt;
+ UDF_DESCRIPTOR_TAG *DescriptorTag;
+ UINTN Index;
+ UINTN Length;
+ UINT32 LsnsNo;
+
+ LogicalVolDesc = &Volume->LogicalVolDesc;
+
+ ExtentAd = &LogicalVolDesc->IntegritySequenceExtent;
+
+ if ((ExtentAd->ExtentLength == 0) ||
+ (ExtentAd->ExtentLength < sizeof (UDF_LOGICAL_VOLUME_INTEGRITY)))
+ {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ LogicalVolInt = AllocatePool (ExtentAd->ExtentLength);
+ if (LogicalVolInt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get location of Logical Volume Integrity Descriptor
+ //
+ Lsn = (UINT64)ExtentAd->ExtentLocation - Volume->MainVdsStartLocation;
+
+ LogicalBlockSize = LogicalVolDesc->LogicalBlockSize;
+
+ //
+ // Read disk block
+ //
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32 (Lsn, LogicalBlockSize),
+ ExtentAd->ExtentLength,
+ LogicalVolInt
+ );
+ if (EFI_ERROR (Status)) {
+ goto Out_Free;
+ }
+
+ DescriptorTag = &LogicalVolInt->DescriptorTag;
+
+ //
+ // Check if read block is a Logical Volume Integrity Descriptor
+ //
+ if (DescriptorTag->TagIdentifier != UdfLogicalVolumeIntegrityDescriptor) {
+ Status = EFI_VOLUME_CORRUPTED;
+ goto Out_Free;
+ }
+
+ if ((LogicalVolInt->NumberOfPartitions > MAX_UINT32 / sizeof (UINT32) / 2) ||
+ (LogicalVolInt->NumberOfPartitions * sizeof (UINT32) * 2 >
+ ExtentAd->ExtentLength - sizeof (UDF_LOGICAL_VOLUME_INTEGRITY)))
+ {
+ Status = EFI_VOLUME_CORRUPTED;
+ goto Out_Free;
+ }
+
+ *VolumeSize = 0;
+ *FreeSpaceSize = 0;
+
+ Length = LogicalVolInt->NumberOfPartitions;
+ for (Index = 0; Index < Length; Index += sizeof (UINT32)) {
+ LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);
+ //
+ // Check if size is not specified
+ //
+ if (LsnsNo == 0xFFFFFFFFUL) {
+ continue;
+ }
+
+ //
+ // Accumulate free space size
+ //
+ *FreeSpaceSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);
+ }
+
+ Length = LogicalVolInt->NumberOfPartitions * sizeof (UINT32) * 2;
+ for ( ; Index < Length; Index += sizeof (UINT32)) {
+ LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);
+ //
+ // Check if size is not specified
+ //
+ if (LsnsNo == 0xFFFFFFFFUL) {
+ continue;
+ }
+
+ //
+ // Accumulate used volume space
+ //
+ *VolumeSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);
+ }
+
+ Status = EFI_SUCCESS;
+
+Out_Free:
+ //
+ // Free Logical Volume Integrity Descriptor
+ //
+ FreePool (LogicalVolInt);
+
+ return Status;
+}
+
+/**
+ 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 = ReadFileSeekAndRead;
+ 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;
+}
+
+/**
+ Check if ControllerHandle supports an UDF file system.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] ControllerHandle Handle of device to test.
+
+ @retval EFI_SUCCESS UDF file system found.
+ @retval EFI_UNSUPPORTED UDF file system not found.
+
+**/
+EFI_STATUS
+SupportUdfFileSystem (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
+ EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode;
+ EFI_GUID *VendorDefinedGuid;
+
+ //
+ // Open Device Path protocol on ControllerHandle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **)&DevicePath,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = EFI_UNSUPPORTED;
+
+ //
+ // Get last Device Path node
+ //
+ LastDevicePathNode = NULL;
+ DevicePathNode = DevicePath;
+ while (!IsDevicePathEnd (DevicePathNode)) {
+ LastDevicePathNode = DevicePathNode;
+ DevicePathNode = NextDevicePathNode (DevicePathNode);
+ }
+
+ //
+ // Check if last Device Path node contains a Vendor-Defined Media Device Path
+ // of an UDF file system.
+ //
+ if ((LastDevicePathNode != NULL) &&
+ (DevicePathType (LastDevicePathNode) == MEDIA_DEVICE_PATH) &&
+ (DevicePathSubType (LastDevicePathNode) == MEDIA_VENDOR_DP))
+ {
+ VendorDefinedGuid = (EFI_GUID *)((UINTN)LastDevicePathNode +
+ OFFSET_OF (VENDOR_DEVICE_PATH, Guid));
+ if (CompareGuid (VendorDefinedGuid, &gUdfDevPathGuid)) {
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Close Device Path protocol on ControllerHandle
+ //
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.c b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.c
index 0be6ac0260..62432bd53a 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.c
@@ -1,334 +1,334 @@
-/** @file
- UDF/ECMA-167 file system driver.
-
- Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-**/
-
-#include "Udf.h"
-
-//
-// UDF filesystem driver's Global Variables.
-//
-EFI_DRIVER_BINDING_PROTOCOL gUdfDriverBinding = {
- UdfDriverBindingSupported,
- UdfDriverBindingStart,
- UdfDriverBindingStop,
- 0x10,
- NULL,
- NULL
-};
-
-EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gUdfSimpleFsTemplate = {
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
- UdfOpenVolume
-};
-
-/**
- Test to see if this driver supports ControllerHandle. Any ControllerHandle
- than contains a BlockIo and DiskIo protocol or a BlockIo2 protocol can be
- supported.
-
- @param[in] This Protocol instance pointer.
- @param[in] ControllerHandle Handle of device to test.
- @param[in] RemainingDevicePath Optional parameter use to pick a specific
- child device to start.
-
- @retval EFI_SUCCESS This driver supports this device.
- @retval EFI_ALREADY_STARTED This driver is already running on this device.
- @retval other This driver does not support this device.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfDriverBindingSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
-{
- EFI_STATUS Status;
- EFI_DISK_IO_PROTOCOL *DiskIo;
-
- //
- // Open DiskIo protocol on ControllerHandle
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiDiskIoProtocolGuid,
- (VOID **)&DiskIo,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Close DiskIo protocol on ControllerHandle
- //
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiDiskIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
-
- //
- // Test whether ControllerHandle supports BlockIo protocol
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiBlockIoProtocolGuid,
- NULL,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
-
- return Status;
-}
-
-/**
- Start this driver on ControllerHandle by opening a Block IO or a Block IO2
- or both, and Disk IO protocol, reading Device Path, and creating a child
- handle with a Disk IO and device path protocol.
-
- @param[in] This Protocol instance pointer.
- @param[in] ControllerHandle Handle of device to bind driver to
- @param[in] RemainingDevicePath Optional parameter use to pick a specific
- child device to start.
-
- @retval EFI_SUCCESS This driver is added to ControllerHandle.
- @retval EFI_ALREADY_STARTED This driver is already running on
- ControllerHandle.
- @retval other This driver does not support this device.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfDriverBindingStart (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
-{
- EFI_TPL OldTpl;
- EFI_STATUS Status;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
- EFI_DISK_IO_PROTOCOL *DiskIo;
- PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;
-
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
-
- //
- // Open BlockIo protocol on ControllerHandle
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiBlockIoProtocolGuid,
- (VOID **)&BlockIo,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Open DiskIo protocol on ControllerHandle
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiDiskIoProtocolGuid,
- (VOID **)&DiskIo,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Check if ControllerHandle supports an UDF file system
- //
- Status = SupportUdfFileSystem (This, ControllerHandle);
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
-
- //
- // Initialize private file system structure
- //
- PrivFsData =
- (PRIVATE_UDF_SIMPLE_FS_DATA *)
- AllocateZeroPool (sizeof (PRIVATE_UDF_SIMPLE_FS_DATA));
- if (PrivFsData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
-
- //
- // Create new child handle
- //
- PrivFsData->Signature = PRIVATE_UDF_SIMPLE_FS_DATA_SIGNATURE;
- PrivFsData->BlockIo = BlockIo;
- PrivFsData->DiskIo = DiskIo;
- PrivFsData->Handle = ControllerHandle;
-
- //
- // Set up SimpleFs protocol
- //
- CopyMem (
- (VOID *)&PrivFsData->SimpleFs,
- (VOID *)&gUdfSimpleFsTemplate,
- sizeof (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL)
- );
-
- //
- // Install child handle
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &PrivFsData->Handle,
- &gEfiSimpleFileSystemProtocolGuid,
- &PrivFsData->SimpleFs,
- NULL
- );
-
-Exit:
- if (EFI_ERROR (Status)) {
- //
- // Close DiskIo protocol on ControllerHandle
- //
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiDiskIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- //
- // Close BlockIo protocol on ControllerHandle
- //
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiBlockIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- }
-
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-/**
- Stop this driver on ControllerHandle. Support stopping any child handles
- created by this driver.
-
- @param This Protocol instance pointer.
- @param ControllerHandle Handle of device to stop driver on
- @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
- children is zero stop the entire bus driver.
- @param ChildHandleBuffer List of Child Handles to Stop.
-
- @retval EFI_SUCCESS This driver is removed ControllerHandle
- @retval other This driver was not removed from this device
-
-**/
-EFI_STATUS
-EFIAPI
-UdfDriverBindingStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer
- )
-{
- PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;
- EFI_STATUS Status;
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;
-
- //
- // Open SimpleFs protocol on ControllerHandle
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiSimpleFileSystemProtocolGuid,
- (VOID **)&SimpleFs,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (SimpleFs);
-
- //
- // Uninstall child handle
- //
- Status = gBS->UninstallMultipleProtocolInterfaces (
- PrivFsData->Handle,
- &gEfiSimpleFileSystemProtocolGuid,
- &PrivFsData->SimpleFs,
- NULL
- );
-
- FreePool ((VOID *)PrivFsData);
- }
-
- if (!EFI_ERROR (Status)) {
- //
- // Close DiskIo protocol on ControllerHandle
- //
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiDiskIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- //
- // Close BlockIo protocol on ControllerHandle
- //
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiBlockIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- }
-
- return Status;
-}
-
-/**
- The user Entry Point for UDF file system driver. The user code starts with
- this function.
-
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The entry point is executed successfully.
- @retval other Some error occurs when executing this entry point.
-
-**/
-EFI_STATUS
-EFIAPI
-InitializeUdf (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
-
- Status = EfiLibInstallDriverBindingComponentName2 (
- ImageHandle,
- SystemTable,
- &gUdfDriverBinding,
- ImageHandle,
- &gUdfComponentName,
- &gUdfComponentName2
- );
- ASSERT_EFI_ERROR (Status);
-
- return Status;
-}
+/** @file
+ UDF/ECMA-167 file system driver.
+
+ Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Udf.h"
+
+//
+// UDF filesystem driver's Global Variables.
+//
+EFI_DRIVER_BINDING_PROTOCOL gUdfDriverBinding = {
+ UdfDriverBindingSupported,
+ UdfDriverBindingStart,
+ UdfDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gUdfSimpleFsTemplate = {
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
+ UdfOpenVolume
+};
+
+/**
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ than contains a BlockIo and DiskIo protocol or a BlockIo2 protocol can be
+ supported.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] ControllerHandle Handle of device to test.
+ @param[in] RemainingDevicePath Optional parameter use to pick a specific
+ child device to start.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_ALREADY_STARTED This driver is already running on this device.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+
+ //
+ // Open DiskIo protocol on ControllerHandle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ (VOID **)&DiskIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Close DiskIo protocol on ControllerHandle
+ //
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ //
+ // Test whether ControllerHandle supports BlockIo protocol
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+
+ return Status;
+}
+
+/**
+ Start this driver on ControllerHandle by opening a Block IO or a Block IO2
+ or both, and Disk IO protocol, reading Device Path, and creating a child
+ handle with a Disk IO and device path protocol.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] ControllerHandle Handle of device to bind driver to
+ @param[in] RemainingDevicePath Optional parameter use to pick a specific
+ child device to start.
+
+ @retval EFI_SUCCESS This driver is added to ControllerHandle.
+ @retval EFI_ALREADY_STARTED This driver is already running on
+ ControllerHandle.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+ PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ //
+ // Open BlockIo protocol on ControllerHandle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **)&BlockIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Open DiskIo protocol on ControllerHandle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ (VOID **)&DiskIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Check if ControllerHandle supports an UDF file system
+ //
+ Status = SupportUdfFileSystem (This, ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Initialize private file system structure
+ //
+ PrivFsData =
+ (PRIVATE_UDF_SIMPLE_FS_DATA *)
+ AllocateZeroPool (sizeof (PRIVATE_UDF_SIMPLE_FS_DATA));
+ if (PrivFsData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ //
+ // Create new child handle
+ //
+ PrivFsData->Signature = PRIVATE_UDF_SIMPLE_FS_DATA_SIGNATURE;
+ PrivFsData->BlockIo = BlockIo;
+ PrivFsData->DiskIo = DiskIo;
+ PrivFsData->Handle = ControllerHandle;
+
+ //
+ // Set up SimpleFs protocol
+ //
+ CopyMem (
+ (VOID *)&PrivFsData->SimpleFs,
+ (VOID *)&gUdfSimpleFsTemplate,
+ sizeof (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL)
+ );
+
+ //
+ // Install child handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &PrivFsData->Handle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ &PrivFsData->SimpleFs,
+ NULL
+ );
+
+Exit:
+ if (EFI_ERROR (Status)) {
+ //
+ // Close DiskIo protocol on ControllerHandle
+ //
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ //
+ // Close BlockIo protocol on ControllerHandle
+ //
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ }
+
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+/**
+ Stop this driver on ControllerHandle. Support stopping any child handles
+ created by this driver.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to stop driver on
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
+ children is zero stop the entire bus driver.
+ @param ChildHandleBuffer List of Child Handles to Stop.
+
+ @retval EFI_SUCCESS This driver is removed ControllerHandle
+ @retval other This driver was not removed from this device
+
+**/
+EFI_STATUS
+EFIAPI
+UdfDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;
+ EFI_STATUS Status;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;
+
+ //
+ // Open SimpleFs protocol on ControllerHandle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID **)&SimpleFs,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (SimpleFs);
+
+ //
+ // Uninstall child handle
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ PrivFsData->Handle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ &PrivFsData->SimpleFs,
+ NULL
+ );
+
+ FreePool ((VOID *)PrivFsData);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Close DiskIo protocol on ControllerHandle
+ //
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ //
+ // Close BlockIo protocol on ControllerHandle
+ //
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ }
+
+ return Status;
+}
+
+/**
+ The user Entry Point for UDF file system driver. The user code starts with
+ this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeUdf (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gUdfDriverBinding,
+ ImageHandle,
+ &gUdfComponentName,
+ &gUdfComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h
index 8c0d551093..1ba81eb044 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h
@@ -1,1216 +1,1216 @@
-/** @file
- UDF/ECMA-167 file system driver.
-
- Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-**/
-
-#ifndef _UDF_H_
-#define _UDF_H_
-
-#include <Uefi.h>
-#include <Base.h>
-
-#include <Protocol/BlockIo.h>
-#include <Protocol/ComponentName.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/DriverBinding.h>
-#include <Protocol/DiskIo.h>
-#include <Protocol/SimpleFileSystem.h>
-
-#include <Guid/FileInfo.h>
-#include <Guid/FileSystemInfo.h>
-#include <Guid/FileSystemVolumeLabelInfo.h>
-
-#include <Library/DebugLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/BaseLib.h>
-#include <Library/UefiLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/DevicePathLib.h>
-
-#include <IndustryStandard/ElTorito.h>
-#include <IndustryStandard/Udf.h>
-
-//
-// C5BD4D42-1A76-4996-8956-73CDA326CD0A
-//
-#define EFI_UDF_DEVICE_PATH_GUID \
- { 0xC5BD4D42, 0x1A76, 0x4996, \
- { 0x89, 0x56, 0x73, 0xCD, 0xA3, 0x26, 0xCD, 0x0A } \
- }
-
-#define FE_ICB_FILE_TYPE(_Ptr) \
- (UDF_FILE_ENTRY_TYPE)( \
- ((UDF_DESCRIPTOR_TAG *)(_Ptr))->TagIdentifier == UdfFileEntry ? \
- ((UDF_FILE_ENTRY *)(_Ptr))->IcbTag.FileType : \
- ((UDF_EXTENDED_FILE_ENTRY *)(_Ptr))->IcbTag.FileType)
-
-typedef enum {
- UdfFileEntryDirectory = 4,
- UdfFileEntryStandardFile = 5,
- UdfFileEntrySymlink = 12,
-} UDF_FILE_ENTRY_TYPE;
-
-#define HIDDEN_FILE (1 << 0)
-#define DIRECTORY_FILE (1 << 1)
-#define DELETED_FILE (1 << 2)
-#define PARENT_FILE (1 << 3)
-
-#define IS_FID_HIDDEN_FILE(_Fid) \
- (BOOLEAN)((_Fid)->FileCharacteristics & HIDDEN_FILE)
-#define IS_FID_DIRECTORY_FILE(_Fid) \
- (BOOLEAN)((_Fid)->FileCharacteristics & DIRECTORY_FILE)
-#define IS_FID_DELETED_FILE(_Fid) \
- (BOOLEAN)((_Fid)->FileCharacteristics & DELETED_FILE)
-#define IS_FID_PARENT_FILE(_Fid) \
- (BOOLEAN)((_Fid)->FileCharacteristics & PARENT_FILE)
-#define IS_FID_NORMAL_FILE(_Fid) \
- (BOOLEAN)(!IS_FID_DIRECTORY_FILE (_Fid) && \
- !IS_FID_PARENT_FILE (_Fid))
-
-typedef enum {
- ShortAdsSequence,
- LongAdsSequence,
- ExtendedAdsSequence,
- InlineData
-} UDF_FE_RECORDING_FLAGS;
-
-#define GET_FE_RECORDING_FLAGS(_Fe) \
- ((UDF_FE_RECORDING_FLAGS)((UDF_ICB_TAG *)( \
- (UINT8 *)(_Fe) + \
- sizeof (UDF_DESCRIPTOR_TAG)))->Flags & 0x07)
-
-typedef enum {
- ExtentRecordedAndAllocated,
- ExtentNotRecordedButAllocated,
- ExtentNotRecordedNotAllocated,
- ExtentIsNextExtent,
-} UDF_EXTENT_FLAGS;
-
-#define AD_LENGTH(_RecFlags) \
- ((_RecFlags) == ShortAdsSequence ? \
- ((UINT64)(sizeof (UDF_SHORT_ALLOCATION_DESCRIPTOR))) : \
- ((UINT64)(sizeof (UDF_LONG_ALLOCATION_DESCRIPTOR))))
-
-#define GET_EXTENT_FLAGS(_RecFlags, _Ad) \
- ((_RecFlags) == ShortAdsSequence ? \
- ((UDF_EXTENT_FLAGS)((((UDF_SHORT_ALLOCATION_DESCRIPTOR *)(_Ad))->ExtentLength >> \
- 30) & 0x3)) : \
- ((UDF_EXTENT_FLAGS)((((UDF_LONG_ALLOCATION_DESCRIPTOR *)(_Ad))->ExtentLength >> \
- 30) & 0x3)))
-
-#define GET_EXTENT_LENGTH(_RecFlags, _Ad) \
- ((_RecFlags) == ShortAdsSequence ? \
- ((UINT32)((((UDF_SHORT_ALLOCATION_DESCRIPTOR *)(_Ad))->ExtentLength & \
- ~0xC0000000UL))) : \
- ((UINT32)((((UDF_LONG_ALLOCATION_DESCRIPTOR *)(_Ad))->ExtentLength & \
- ~0xC0000000UL))))
-
-#define UDF_FILENAME_LENGTH 128
-#define UDF_PATH_LENGTH 512
-
-#define GET_FID_FROM_ADS(_Data, _Offs) \
- ((UDF_FILE_IDENTIFIER_DESCRIPTOR *)((UINT8 *)(_Data) + (_Offs)))
-
-#define IS_VALID_COMPRESSION_ID(_CompId) \
- ((BOOLEAN)((_CompId) == 8 || (_CompId) == 16))
-
-#define UDF_STANDARD_IDENTIFIER_LENGTH 5
-
-#pragma pack(1)
-
-typedef struct {
- UINT8 StandardIdentifier[UDF_STANDARD_IDENTIFIER_LENGTH];
-} UDF_STANDARD_IDENTIFIER;
-
-#pragma pack()
-
-typedef enum {
- ReadFileGetFileSize,
- ReadFileAllocateAndRead,
- ReadFileSeekAndRead,
-} UDF_READ_FILE_FLAGS;
-
-typedef struct {
- VOID *FileData;
- UDF_READ_FILE_FLAGS Flags;
- UINT64 FileDataSize;
- UINT64 FilePosition;
- UINT64 FileSize;
- UINT64 ReadLength;
-} UDF_READ_FILE_INFO;
-
-#pragma pack(1)
-
-typedef struct {
- UINT16 TypeAndTimezone;
- INT16 Year;
- UINT8 Month;
- UINT8 Day;
- UINT8 Hour;
- UINT8 Minute;
- UINT8 Second;
- UINT8 Centiseconds;
- UINT8 HundredsOfMicroseconds;
- UINT8 Microseconds;
-} UDF_TIMESTAMP;
-
-typedef struct {
- UDF_DESCRIPTOR_TAG DescriptorTag;
- UINT32 PrevAllocationExtentDescriptor;
- UINT32 LengthOfAllocationDescriptors;
-} UDF_ALLOCATION_EXTENT_DESCRIPTOR;
-
-typedef struct {
- UINT8 StructureType;
- UINT8 StandardIdentifier[UDF_STANDARD_IDENTIFIER_LENGTH];
- UINT8 StructureVersion;
- UINT8 Reserved;
- UINT8 StructureData[2040];
-} UDF_VOLUME_DESCRIPTOR;
-
-typedef struct {
- UDF_DESCRIPTOR_TAG DescriptorTag;
- UDF_TIMESTAMP RecordingDateTime;
- UINT32 IntegrityType;
- UDF_EXTENT_AD NextIntegrityExtent;
- UINT8 LogicalVolumeContentsUse[32];
- UINT32 NumberOfPartitions;
- UINT32 LengthOfImplementationUse;
- UINT8 Data[0];
-} UDF_LOGICAL_VOLUME_INTEGRITY;
-
-typedef struct {
- UDF_DESCRIPTOR_TAG DescriptorTag;
- UINT32 VolumeDescriptorSequenceNumber;
- UINT16 PartitionFlags;
- UINT16 PartitionNumber;
- UDF_ENTITY_ID PartitionContents;
- UINT8 PartitionContentsUse[128];
- UINT32 AccessType;
- UINT32 PartitionStartingLocation;
- UINT32 PartitionLength;
- UDF_ENTITY_ID ImplementationIdentifier;
- UINT8 ImplementationUse[128];
- UINT8 Reserved[156];
-} UDF_PARTITION_DESCRIPTOR;
-
-typedef struct {
- UDF_DESCRIPTOR_TAG DescriptorTag;
- UDF_TIMESTAMP RecordingDateAndTime;
- UINT16 InterchangeLevel;
- UINT16 MaximumInterchangeLevel;
- UINT32 CharacterSetList;
- UINT32 MaximumCharacterSetList;
- UINT32 FileSetNumber;
- UINT32 FileSetDescriptorNumber;
- UDF_CHAR_SPEC LogicalVolumeIdentifierCharacterSet;
- UINT8 LogicalVolumeIdentifier[128];
- UDF_CHAR_SPEC FileSetCharacterSet;
- UINT8 FileSetIdentifier[32];
- UINT8 CopyrightFileIdentifier[32];
- UINT8 AbstractFileIdentifier[32];
- UDF_LONG_ALLOCATION_DESCRIPTOR RootDirectoryIcb;
- UDF_ENTITY_ID DomainIdentifier;
- UDF_LONG_ALLOCATION_DESCRIPTOR NextExtent;
- UDF_LONG_ALLOCATION_DESCRIPTOR SystemStreamDirectoryIcb;
- UINT8 Reserved[32];
-} UDF_FILE_SET_DESCRIPTOR;
-
-typedef struct {
- UINT32 ExtentLength;
- UINT32 ExtentPosition;
-} UDF_SHORT_ALLOCATION_DESCRIPTOR;
-
-typedef struct {
- UDF_DESCRIPTOR_TAG DescriptorTag;
- UINT16 FileVersionNumber;
- UINT8 FileCharacteristics;
- UINT8 LengthOfFileIdentifier;
- UDF_LONG_ALLOCATION_DESCRIPTOR Icb;
- UINT16 LengthOfImplementationUse;
- UINT8 Data[0];
-} UDF_FILE_IDENTIFIER_DESCRIPTOR;
-
-typedef struct {
- UINT32 PriorRecordNumberOfDirectEntries;
- UINT16 StrategyType;
- UINT16 StrategyParameter;
- UINT16 MaximumNumberOfEntries;
- UINT8 Reserved;
- UINT8 FileType;
- UDF_LB_ADDR ParentIcbLocation;
- UINT16 Flags;
-} UDF_ICB_TAG;
-
-typedef struct {
- UDF_DESCRIPTOR_TAG DescriptorTag;
- UDF_ICB_TAG IcbTag;
- UINT32 Uid;
- UINT32 Gid;
- UINT32 Permissions;
- UINT16 FileLinkCount;
- UINT8 RecordFormat;
- UINT8 RecordDisplayAttributes;
- UINT32 RecordLength;
- UINT64 InformationLength;
- UINT64 LogicalBlocksRecorded;
- UDF_TIMESTAMP AccessTime;
- UDF_TIMESTAMP ModificationTime;
- UDF_TIMESTAMP AttributeTime;
- UINT32 CheckPoint;
- UDF_LONG_ALLOCATION_DESCRIPTOR ExtendedAttributeIcb;
- UDF_ENTITY_ID ImplementationIdentifier;
- UINT64 UniqueId;
- UINT32 LengthOfExtendedAttributes;
- UINT32 LengthOfAllocationDescriptors;
- UINT8 Data[0]; // L_EA + L_AD
-} UDF_FILE_ENTRY;
-
-typedef struct {
- UDF_DESCRIPTOR_TAG DescriptorTag;
- UDF_ICB_TAG IcbTag;
- UINT32 Uid;
- UINT32 Gid;
- UINT32 Permissions;
- UINT16 FileLinkCount;
- UINT8 RecordFormat;
- UINT8 RecordDisplayAttributes;
- UINT32 RecordLength;
- UINT64 InformationLength;
- UINT64 ObjectSize;
- UINT64 LogicalBlocksRecorded;
- UDF_TIMESTAMP AccessTime;
- UDF_TIMESTAMP ModificationTime;
- UDF_TIMESTAMP CreationTime;
- UDF_TIMESTAMP AttributeTime;
- UINT32 CheckPoint;
- UINT32 Reserved;
- UDF_LONG_ALLOCATION_DESCRIPTOR ExtendedAttributeIcb;
- UDF_LONG_ALLOCATION_DESCRIPTOR StreamDirectoryIcb;
- UDF_ENTITY_ID ImplementationIdentifier;
- UINT64 UniqueId;
- UINT32 LengthOfExtendedAttributes;
- UINT32 LengthOfAllocationDescriptors;
- UINT8 Data[0]; // L_EA + L_AD
-} UDF_EXTENDED_FILE_ENTRY;
-
-typedef struct {
- UINT8 ComponentType;
- UINT8 LengthOfComponentIdentifier;
- UINT16 ComponentFileVersionNumber;
- UINT8 ComponentIdentifier[0];
-} UDF_PATH_COMPONENT;
-
-#pragma pack()
-
-//
-// UDF filesystem driver's private data
-//
-typedef struct {
- UINT64 MainVdsStartLocation;
- UDF_LOGICAL_VOLUME_DESCRIPTOR LogicalVolDesc;
- UDF_PARTITION_DESCRIPTOR PartitionDesc;
- UDF_FILE_SET_DESCRIPTOR FileSetDesc;
- UINTN FileEntrySize;
-} UDF_VOLUME_INFO;
-
-typedef struct {
- VOID *FileEntry;
- UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc;
-} UDF_FILE_INFO;
-
-typedef struct {
- VOID *DirectoryData;
- UINT64 DirectoryLength;
- UINT64 FidOffset;
-} UDF_READ_DIRECTORY_INFO;
-
-#define PRIVATE_UDF_FILE_DATA_SIGNATURE SIGNATURE_32 ('U', 'd', 'f', 'f')
-
-#define PRIVATE_UDF_FILE_DATA_FROM_THIS(a) \
- CR ( \
- a, \
- PRIVATE_UDF_FILE_DATA, \
- FileIo, \
- PRIVATE_UDF_FILE_DATA_SIGNATURE \
- )
-
-typedef struct {
- UINTN Signature;
- BOOLEAN IsRootDirectory;
- UDF_FILE_INFO *Root;
- UDF_FILE_INFO File;
- UDF_READ_DIRECTORY_INFO ReadDirInfo;
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;
- EFI_FILE_PROTOCOL FileIo;
- CHAR16 AbsoluteFileName[UDF_PATH_LENGTH];
- CHAR16 FileName[UDF_FILENAME_LENGTH];
- UINT64 FileSize;
- UINT64 FilePosition;
-} PRIVATE_UDF_FILE_DATA;
-
-#define PRIVATE_UDF_SIMPLE_FS_DATA_SIGNATURE SIGNATURE_32 ('U', 'd', 'f', 's')
-
-#define PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS(a) \
- CR ( \
- a, \
- PRIVATE_UDF_SIMPLE_FS_DATA, \
- SimpleFs, \
- PRIVATE_UDF_SIMPLE_FS_DATA_SIGNATURE \
- )
-
-typedef struct {
- UINTN Signature;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
- EFI_DISK_IO_PROTOCOL *DiskIo;
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFs;
- UDF_VOLUME_INFO Volume;
- UDF_FILE_INFO Root;
- UINTN OpenFiles;
- EFI_HANDLE Handle;
-} PRIVATE_UDF_SIMPLE_FS_DATA;
-
-//
-// Global Variables
-//
-extern EFI_DRIVER_BINDING_PROTOCOL gUdfDriverBinding;
-extern EFI_COMPONENT_NAME_PROTOCOL gUdfComponentName;
-extern EFI_COMPONENT_NAME2_PROTOCOL gUdfComponentName2;
-
-//
-// Function Prototypes
-//
-
-/**
- Open the root directory on a volume.
-
- @param This Protocol instance pointer.
- @param Root Returns an Open file handle for the root directory
-
- @retval EFI_SUCCESS The device was opened.
- @retval EFI_UNSUPPORTED This volume does not support the file system.
- @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_ACCESS_DENIED The service denied access to the file.
- @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfOpenVolume (
- IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
- OUT EFI_FILE_PROTOCOL **Root
- );
-
-/**
- Opens a new file relative to the source file's location.
-
- @param This The protocol instance pointer.
- @param NewHandle Returns File Handle for FileName.
- @param FileName Null terminated string. "\", ".", and ".." are supported.
- @param OpenMode Open mode for file.
- @param Attributes Only used for EFI_FILE_MODE_CREATE.
-
- @retval EFI_SUCCESS The device was opened.
- @retval EFI_NOT_FOUND The specified file could not be found on the device.
- @retval EFI_NO_MEDIA The device has no media.
- @retval EFI_MEDIA_CHANGED The media has changed.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_ACCESS_DENIED The service denied access to the file.
- @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
- @retval EFI_VOLUME_FULL The volume is full.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfOpen (
- IN EFI_FILE_PROTOCOL *This,
- OUT EFI_FILE_PROTOCOL **NewHandle,
- IN CHAR16 *FileName,
- IN UINT64 OpenMode,
- IN UINT64 Attributes
- );
-
-/**
- Read data from the file.
-
- @param This Protocol instance pointer.
- @param BufferSize On input size of buffer, on output amount of data in buffer.
- @param Buffer The buffer in which data is read.
-
- @retval EFI_SUCCESS Data was read.
- @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_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfRead (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- );
-
-/**
- Close the file handle.
-
- @param This Protocol instance pointer.
-
- @retval EFI_SUCCESS The file was closed.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfClose (
- IN EFI_FILE_PROTOCOL *This
- );
-
-/**
- Close and delete the file handle.
-
- @param This Protocol instance pointer.
-
- @retval EFI_SUCCESS The file was closed and deleted.
- @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not
- deleted.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfDelete (
- IN EFI_FILE_PROTOCOL *This
- );
-
-/**
- Write data to a file.
-
- @param This Protocol instance pointer.
- @param BufferSize On input size of buffer, on output amount of data in buffer.
- @param Buffer The buffer in which data to write.
-
- @retval EFI_SUCCESS Data was written.
- @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
- @retval EFI_NO_MEDIA The device has no media.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_WRITE_PROTECTED The device is write protected.
- @retval EFI_ACCESS_DENIED The file was open for read only.
- @retval EFI_VOLUME_FULL The volume is full.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfWrite (
- IN EFI_FILE_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- );
-
-/**
- Get file's current position.
-
- @param This Protocol instance pointer.
- @param Position Byte position from the start of the file.
-
- @retval EFI_SUCCESS Position was updated.
- @retval EFI_UNSUPPORTED Seek request for directories is not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfGetPosition (
- IN EFI_FILE_PROTOCOL *This,
- OUT UINT64 *Position
- );
-
-/**
- Set file's current position.
-
- @param This Protocol instance pointer.
- @param Position Byte position from the start of the file.
-
- @retval EFI_SUCCESS Position was updated.
- @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfSetPosition (
- IN EFI_FILE_PROTOCOL *This,
- IN UINT64 Position
- );
-
-/**
- Get information about a file.
-
- @attention This is boundary function that may receive untrusted input.
- @attention The input is from FileSystem.
-
- The File Set Descriptor is external input, so this routine will do basic
- validation for File Set Descriptor and report status.
-
- @param This Protocol instance pointer.
- @param InformationType Type of information to return in Buffer.
- @param BufferSize On input size of buffer, on output amount of data in
- buffer.
- @param Buffer The buffer to return data.
-
- @retval EFI_SUCCESS Data was returned.
- @retval EFI_UNSUPPORTED InformationType is 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_WRITE_PROTECTED The device is write protected.
- @retval EFI_ACCESS_DENIED The file was open for read only.
- @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in
- BufferSize.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfGetInfo (
- IN EFI_FILE_PROTOCOL *This,
- IN EFI_GUID *InformationType,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- );
-
-/**
- Set information about a file.
-
- @param This Protocol instance pointer.
- @param InformationType Type of information in Buffer.
- @param BufferSize Size of buffer.
- @param Buffer The data to write.
-
- @retval EFI_SUCCESS Data was set.
- @retval EFI_UNSUPPORTED InformationType is 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_WRITE_PROTECTED The device is write protected.
- @retval EFI_ACCESS_DENIED The file was open for read only.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfSetInfo (
- IN EFI_FILE_PROTOCOL *This,
- IN EFI_GUID *InformationType,
- IN UINTN BufferSize,
- IN VOID *Buffer
- );
-
-/**
- Flush data back for the file handle.
-
- @param This Protocol instance pointer.
-
- @retval EFI_SUCCESS Data was flushed.
- @retval EFI_UNSUPPORTED Writes to Open directory are 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_WRITE_PROTECTED The device is write protected.
- @retval EFI_ACCESS_DENIED The file was open for read only.
- @retval EFI_VOLUME_FULL The volume is full.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfFlush (
- IN EFI_FILE_PROTOCOL *This
- );
-
-/**
- Read volume information on a medium which contains a valid UDF file system.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[out] Volume UDF volume information structure.
-
- @retval EFI_SUCCESS Volume information read.
- @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 volume was not read due to lack of resources.
-
-**/
-EFI_STATUS
-ReadUdfVolumeInformation (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- OUT UDF_VOLUME_INFO *Volume
- );
-
-/**
- Find the root directory on an UDF volume.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume UDF volume information structure.
- @param[out] File Root directory file.
-
- @retval EFI_SUCCESS Root directory found.
- @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 root directory was not found due to lack of
- resources.
-
-**/
-EFI_STATUS
-FindRootDirectory (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- OUT UDF_FILE_INFO *File
- );
-
-/**
- Find either a File Entry or a Extended File Entry from a given ICB.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume UDF volume information structure.
- @param[in] Icb ICB of the FID.
- @param[out] FileEntry File Entry or Extended File Entry.
-
- @retval EFI_SUCCESS File Entry or Extended File Entry found.
- @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 FE/EFE entry was not found due to lack of
- resources.
-
-**/
-EFI_STATUS
-FindFileEntry (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb,
- OUT VOID **FileEntry
- );
-
-/**
- Find a file given its absolute path on an UDF volume.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume UDF volume information structure.
- @param[in] FilePath File's absolute path.
- @param[in] Root Root directory file.
- @param[in] Parent Parent directory file.
- @param[in] Icb ICB of Parent.
- @param[out] File Found file.
-
- @retval EFI_SUCCESS FilePath was found.
- @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 FilePath file was not found due to lack of
- resources.
-
-**/
-EFI_STATUS
-FindFile (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN CHAR16 *FilePath,
- IN UDF_FILE_INFO *Root,
- IN UDF_FILE_INFO *Parent,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb,
- OUT UDF_FILE_INFO *File
- );
-
-/**
- Read a directory entry at a time on an UDF volume.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume UDF volume information structure.
- @param[in] ParentIcb ICB of the parent file.
- @param[in] FileEntryData FE/EFE of the parent file.
- @param[in, out] ReadDirInfo Next read directory listing structure
- information.
- @param[out] FoundFid File Identifier Descriptor pointer.
-
- @retval EFI_SUCCESS Directory entry 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 directory entry was not read due to lack of
- resources.
-
-**/
-EFI_STATUS
-ReadDirectoryEntry (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,
- IN VOID *FileEntryData,
- IN OUT UDF_READ_DIRECTORY_INFO *ReadDirInfo,
- OUT UDF_FILE_IDENTIFIER_DESCRIPTOR **FoundFid
- );
-
-/**
- Get a filename (encoded in OSTA-compressed format) from a File Identifier
- Descriptor on an UDF volume.
-
- @attention This is boundary function that may receive untrusted input.
- @attention The input is from FileSystem.
-
- The File Identifier Descriptor is external input, so this routine will do
- basic validation for File Identifier Descriptor and report status.
-
- @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
- @param[in] CharMax The maximum number of FileName Unicode char,
- including terminating null char.
- @param[out] FileName Decoded filename.
-
- @retval EFI_SUCCESS Filename decoded and read.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_BUFFER_TOO_SMALL The string buffer FileName cannot hold the
- decoded filename.
-**/
-EFI_STATUS
-GetFileNameFromFid (
- IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc,
- IN UINTN CharMax,
- OUT CHAR16 *FileName
- );
-
-/**
- Resolve a symlink file on an UDF volume.
-
- @attention This is boundary function that may receive untrusted input.
- @attention The input is from FileSystem.
-
- The Path Component is external input, so this routine will do basic
- validation for Path Component and report status.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume UDF volume information structure.
- @param[in] Parent Parent file.
- @param[in] FileEntryData FE/EFE structure pointer.
- @param[out] File Resolved file.
-
- @retval EFI_SUCCESS Symlink file resolved.
- @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 symlink file was not resolved due to lack of
- resources.
-
-**/
-EFI_STATUS
-ResolveSymlink (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_FILE_INFO *Parent,
- IN VOID *FileEntryData,
- OUT UDF_FILE_INFO *File
- );
-
-/**
- Clean up in-memory UDF file information.
-
- @param[in] File File information pointer.
-
-**/
-VOID
-CleanupFileInformation (
- IN UDF_FILE_INFO *File
- );
-
-/**
- Find a file from its absolute path 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[out] Size Size of the file.
-
- @retval EFI_SUCCESS File size calculated and set in Size.
- @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 size was not calculated due to lack of
- resources.
-
-**/
-EFI_STATUS
-GetFileSize (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- IN UDF_FILE_INFO *File,
- OUT UINT64 *Size
- );
-
-/**
- Set information about a file on an UDF volume.
-
- @param[in] File File pointer.
- @param[in] FileSize Size of the file.
- @param[in] FileName Filename of the file.
- @param[in, out] BufferSize Size of the returned file infomation.
- @param[out] Buffer Data of the returned file information.
-
- @retval EFI_SUCCESS File information set.
- @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 information was not set due to lack of
- resources.
-
-**/
-EFI_STATUS
-SetFileInfo (
- IN UDF_FILE_INFO *File,
- IN UINT64 FileSize,
- IN CHAR16 *FileName,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- );
-
-/**
- Get volume label of an UDF volume.
-
- @attention This is boundary function that may receive untrusted input.
- @attention The input is from FileSystem.
-
- The File Set Descriptor is external input, so this routine will do basic
- validation for File Set Descriptor and report status.
-
- @param[in] Volume Volume information pointer.
- @param[in] CharMax The maximum number of Unicode char in String,
- including terminating null char.
- @param[out] String String buffer pointer to store the volume label.
-
- @retval EFI_SUCCESS Volume label is returned.
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
- @retval EFI_BUFFER_TOO_SMALL The string buffer String cannot hold the
- volume label.
-
-**/
-EFI_STATUS
-GetVolumeLabel (
- IN UDF_VOLUME_INFO *Volume,
- IN UINTN CharMax,
- OUT CHAR16 *String
- );
-
-/**
- Get volume and free space size information of an UDF volume.
-
- @attention This is boundary function that may receive untrusted input.
- @attention The input is from FileSystem.
-
- The Logical Volume Descriptor and the Logical Volume Integrity Descriptor are
- external inputs, so this routine will do basic validation for both descriptors
- and report status.
-
- @param[in] BlockIo BlockIo interface.
- @param[in] DiskIo DiskIo interface.
- @param[in] Volume UDF volume information structure.
- @param[out] VolumeSize Volume size.
- @param[out] FreeSpaceSize Free space size.
-
- @retval EFI_SUCCESS Volume and free space size calculated.
- @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 volume and free space size were not
- calculated due to lack of resources.
-
-**/
-EFI_STATUS
-GetVolumeSize (
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- IN EFI_DISK_IO_PROTOCOL *DiskIo,
- IN UDF_VOLUME_INFO *Volume,
- OUT UINT64 *VolumeSize,
- OUT UINT64 *FreeSpaceSize
- );
-
-/**
- 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
- );
-
-/**
- Check if ControllerHandle supports an UDF file system.
-
- @param[in] This Protocol instance pointer.
- @param[in] ControllerHandle Handle of device to test.
-
- @retval EFI_SUCCESS UDF file system found.
- @retval EFI_UNSUPPORTED UDF file system not found.
-
-**/
-EFI_STATUS
-SupportUdfFileSystem (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle
- );
-
-/**
- Mangle a filename by cutting off trailing whitespaces, "\\", "." and "..".
-
- @param[in] FileName Filename.
-
- @retval The mangled Filename.
-
-**/
-CHAR16 *
-MangleFileName (
- IN CHAR16 *FileName
- );
-
-/**
- Test to see if this driver supports ControllerHandle. Any ControllerHandle
- than contains a BlockIo and DiskIo protocol can be supported.
-
- @param This Protocol instance pointer.
- @param ControllerHandle Handle of device to test
- @param RemainingDevicePath Optional parameter use to pick a specific child
- device to start.
-
- @retval EFI_SUCCESS This driver supports this device
- @retval EFI_ALREADY_STARTED This driver is already running on this device
- @retval other This driver does not support this device
-
-**/
-EFI_STATUS
-EFIAPI
-UdfDriverBindingSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- );
-
-/**
- Start this driver on ControllerHandle by opening a Block IO and Disk IO
- protocol, reading Device Path, and creating a child handle with a
- Disk IO and device path protocol.
-
- @param This Protocol instance pointer.
- @param ControllerHandle Handle of device to bind driver to
- @param RemainingDevicePath Optional parameter use to pick a specific child
- device to start.
-
- @retval EFI_SUCCESS This driver is added to ControllerHandle
- @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
- @retval other This driver does not support this device
-
-**/
-EFI_STATUS
-EFIAPI
-UdfDriverBindingStart (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- );
-
-/**
- Stop this driver on ControllerHandle. Support stopping any child handles
- created by this driver.
-
- @param This Protocol instance pointer.
- @param ControllerHandle Handle of device to stop driver on
- @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
- children is zero stop the entire bus driver.
- @param ChildHandleBuffer List of Child Handles to Stop.
-
- @retval EFI_SUCCESS This driver is removed ControllerHandle
- @retval other This driver was not removed from this device
-
-**/
-EFI_STATUS
-EFIAPI
-UdfDriverBindingStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer
- );
-
-//
-// EFI Component Name Functions
-//
-
-/**
- Retrieves a Unicode string that is the user readable name of the driver.
-
- This function retrieves the user readable name of a driver in the form of a
- Unicode string. If the driver specified by This has a user readable name in
- the language specified by Language, then a pointer to the driver name is
- returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
- by This does not support the language specified by Language,
- then EFI_UNSUPPORTED is returned.
-
- @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
- EFI_COMPONENT_NAME_PROTOCOL instance.
-
- @param Language[in] A pointer to a Null-terminated ASCII string
- array indicating the language. This is the
- language of the driver name that the caller is
- requesting, and it must match one of the
- languages specified in SupportedLanguages. The
- number of languages supported by a driver is up
- to the driver writer. Language is specified
- in RFC 4646 or ISO 639-2 language code format.
-
- @param DriverName[out] A pointer to the Unicode string to return.
- This Unicode string is the name of the
- driver specified by This in the language
- specified by Language.
-
- @retval EFI_SUCCESS The Unicode string for the Driver specified by
- This and the language specified by Language was
- returned in DriverName.
-
- @retval EFI_INVALID_PARAMETER Language is NULL.
-
- @retval EFI_INVALID_PARAMETER DriverName is NULL.
-
- @retval EFI_UNSUPPORTED The driver specified by This does not support
- the language specified by Language.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfComponentNameGetDriverName (
- IN EFI_COMPONENT_NAME_PROTOCOL *This,
- IN CHAR8 *Language,
- OUT CHAR16 **DriverName
- );
-
-/**
- Retrieves a Unicode string that is the user readable name of the controller
- that is being managed by a driver.
-
- This function retrieves the user readable name of the controller specified by
- ControllerHandle and ChildHandle in the form of a Unicode string. If the
- driver specified by This has a user readable name in the language specified by
- Language, then a pointer to the controller name is returned in ControllerName,
- and EFI_SUCCESS is returned. If the driver specified by This is not currently
- managing the controller specified by ControllerHandle and ChildHandle,
- then EFI_UNSUPPORTED is returned. If the driver specified by This does not
- support the language specified by Language, then EFI_UNSUPPORTED is returned.
-
- @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
- EFI_COMPONENT_NAME_PROTOCOL instance.
-
- @param ControllerHandle[in] The handle of a controller that the driver
- specified by This is managing. This handle
- specifies the controller whose name is to be
- returned.
-
- @param ChildHandle[in] The handle of the child controller to retrieve
- the name of. This is an optional parameter that
- may be NULL. It will be NULL for device
- drivers. It will also be NULL for a bus drivers
- that wish to retrieve the name of the bus
- controller. It will not be NULL for a bus
- driver that wishes to retrieve the name of a
- child controller.
-
- @param Language[in] A pointer to a Null-terminated ASCII string
- array indicating the language. This is the
- language of the driver name that the caller is
- requesting, and it must match one of the
- languages specified in SupportedLanguages. The
- number of languages supported by a driver is up
- to the driver writer. Language is specified in
- RFC 4646 or ISO 639-2 language code format.
-
- @param ControllerName[out] A pointer to the Unicode string to return.
- This Unicode string is the name of the
- controller specified by ControllerHandle and
- ChildHandle in the language specified by
- Language from the point of view of the driver
- specified by This.
-
- @retval EFI_SUCCESS The Unicode string for the user readable name in
- the language specified by Language for the
- driver specified by This was returned in
- DriverName.
-
- @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
-
- @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
- EFI_HANDLE.
-
- @retval EFI_INVALID_PARAMETER Language is NULL.
-
- @retval EFI_INVALID_PARAMETER ControllerName is NULL.
-
- @retval EFI_UNSUPPORTED The driver specified by This is not currently
- managing the controller specified by
- ControllerHandle and ChildHandle.
-
- @retval EFI_UNSUPPORTED The driver specified by This does not support
- the language specified by Language.
-
-**/
-EFI_STATUS
-EFIAPI
-UdfComponentNameGetControllerName (
- IN EFI_COMPONENT_NAME_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_HANDLE ChildHandle OPTIONAL,
- IN CHAR8 *Language,
- OUT CHAR16 **ControllerName
- );
-
-#endif // _UDF_H_
+/** @file
+ UDF/ECMA-167 file system driver.
+
+ Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
+ Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _UDF_H_
+#define _UDF_H_
+
+#include <Uefi.h>
+#include <Base.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/DiskIo.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include <Guid/FileInfo.h>
+#include <Guid/FileSystemInfo.h>
+#include <Guid/FileSystemVolumeLabelInfo.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+
+#include <IndustryStandard/ElTorito.h>
+#include <IndustryStandard/Udf.h>
+
+//
+// C5BD4D42-1A76-4996-8956-73CDA326CD0A
+//
+#define EFI_UDF_DEVICE_PATH_GUID \
+ { 0xC5BD4D42, 0x1A76, 0x4996, \
+ { 0x89, 0x56, 0x73, 0xCD, 0xA3, 0x26, 0xCD, 0x0A } \
+ }
+
+#define FE_ICB_FILE_TYPE(_Ptr) \
+ (UDF_FILE_ENTRY_TYPE)( \
+ ((UDF_DESCRIPTOR_TAG *)(_Ptr))->TagIdentifier == UdfFileEntry ? \
+ ((UDF_FILE_ENTRY *)(_Ptr))->IcbTag.FileType : \
+ ((UDF_EXTENDED_FILE_ENTRY *)(_Ptr))->IcbTag.FileType)
+
+typedef enum {
+ UdfFileEntryDirectory = 4,
+ UdfFileEntryStandardFile = 5,
+ UdfFileEntrySymlink = 12,
+} UDF_FILE_ENTRY_TYPE;
+
+#define HIDDEN_FILE (1 << 0)
+#define DIRECTORY_FILE (1 << 1)
+#define DELETED_FILE (1 << 2)
+#define PARENT_FILE (1 << 3)
+
+#define IS_FID_HIDDEN_FILE(_Fid) \
+ (BOOLEAN)((_Fid)->FileCharacteristics & HIDDEN_FILE)
+#define IS_FID_DIRECTORY_FILE(_Fid) \
+ (BOOLEAN)((_Fid)->FileCharacteristics & DIRECTORY_FILE)
+#define IS_FID_DELETED_FILE(_Fid) \
+ (BOOLEAN)((_Fid)->FileCharacteristics & DELETED_FILE)
+#define IS_FID_PARENT_FILE(_Fid) \
+ (BOOLEAN)((_Fid)->FileCharacteristics & PARENT_FILE)
+#define IS_FID_NORMAL_FILE(_Fid) \
+ (BOOLEAN)(!IS_FID_DIRECTORY_FILE (_Fid) && \
+ !IS_FID_PARENT_FILE (_Fid))
+
+typedef enum {
+ ShortAdsSequence,
+ LongAdsSequence,
+ ExtendedAdsSequence,
+ InlineData
+} UDF_FE_RECORDING_FLAGS;
+
+#define GET_FE_RECORDING_FLAGS(_Fe) \
+ ((UDF_FE_RECORDING_FLAGS)((UDF_ICB_TAG *)( \
+ (UINT8 *)(_Fe) + \
+ sizeof (UDF_DESCRIPTOR_TAG)))->Flags & 0x07)
+
+typedef enum {
+ ExtentRecordedAndAllocated,
+ ExtentNotRecordedButAllocated,
+ ExtentNotRecordedNotAllocated,
+ ExtentIsNextExtent,
+} UDF_EXTENT_FLAGS;
+
+#define AD_LENGTH(_RecFlags) \
+ ((_RecFlags) == ShortAdsSequence ? \
+ ((UINT64)(sizeof (UDF_SHORT_ALLOCATION_DESCRIPTOR))) : \
+ ((UINT64)(sizeof (UDF_LONG_ALLOCATION_DESCRIPTOR))))
+
+#define GET_EXTENT_FLAGS(_RecFlags, _Ad) \
+ ((_RecFlags) == ShortAdsSequence ? \
+ ((UDF_EXTENT_FLAGS)((((UDF_SHORT_ALLOCATION_DESCRIPTOR *)(_Ad))->ExtentLength >> \
+ 30) & 0x3)) : \
+ ((UDF_EXTENT_FLAGS)((((UDF_LONG_ALLOCATION_DESCRIPTOR *)(_Ad))->ExtentLength >> \
+ 30) & 0x3)))
+
+#define GET_EXTENT_LENGTH(_RecFlags, _Ad) \
+ ((_RecFlags) == ShortAdsSequence ? \
+ ((UINT32)((((UDF_SHORT_ALLOCATION_DESCRIPTOR *)(_Ad))->ExtentLength & \
+ ~0xC0000000UL))) : \
+ ((UINT32)((((UDF_LONG_ALLOCATION_DESCRIPTOR *)(_Ad))->ExtentLength & \
+ ~0xC0000000UL))))
+
+#define UDF_FILENAME_LENGTH 128
+#define UDF_PATH_LENGTH 512
+
+#define GET_FID_FROM_ADS(_Data, _Offs) \
+ ((UDF_FILE_IDENTIFIER_DESCRIPTOR *)((UINT8 *)(_Data) + (_Offs)))
+
+#define IS_VALID_COMPRESSION_ID(_CompId) \
+ ((BOOLEAN)((_CompId) == 8 || (_CompId) == 16))
+
+#define UDF_STANDARD_IDENTIFIER_LENGTH 5
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 StandardIdentifier[UDF_STANDARD_IDENTIFIER_LENGTH];
+} UDF_STANDARD_IDENTIFIER;
+
+#pragma pack()
+
+typedef enum {
+ ReadFileGetFileSize,
+ ReadFileAllocateAndRead,
+ ReadFileSeekAndRead,
+} UDF_READ_FILE_FLAGS;
+
+typedef struct {
+ VOID *FileData;
+ UDF_READ_FILE_FLAGS Flags;
+ UINT64 FileDataSize;
+ UINT64 FilePosition;
+ UINT64 FileSize;
+ UINT64 ReadLength;
+} UDF_READ_FILE_INFO;
+
+#pragma pack(1)
+
+typedef struct {
+ UINT16 TypeAndTimezone;
+ INT16 Year;
+ UINT8 Month;
+ UINT8 Day;
+ UINT8 Hour;
+ UINT8 Minute;
+ UINT8 Second;
+ UINT8 Centiseconds;
+ UINT8 HundredsOfMicroseconds;
+ UINT8 Microseconds;
+} UDF_TIMESTAMP;
+
+typedef struct {
+ UDF_DESCRIPTOR_TAG DescriptorTag;
+ UINT32 PrevAllocationExtentDescriptor;
+ UINT32 LengthOfAllocationDescriptors;
+} UDF_ALLOCATION_EXTENT_DESCRIPTOR;
+
+typedef struct {
+ UINT8 StructureType;
+ UINT8 StandardIdentifier[UDF_STANDARD_IDENTIFIER_LENGTH];
+ UINT8 StructureVersion;
+ UINT8 Reserved;
+ UINT8 StructureData[2040];
+} UDF_VOLUME_DESCRIPTOR;
+
+typedef struct {
+ UDF_DESCRIPTOR_TAG DescriptorTag;
+ UDF_TIMESTAMP RecordingDateTime;
+ UINT32 IntegrityType;
+ UDF_EXTENT_AD NextIntegrityExtent;
+ UINT8 LogicalVolumeContentsUse[32];
+ UINT32 NumberOfPartitions;
+ UINT32 LengthOfImplementationUse;
+ UINT8 Data[0];
+} UDF_LOGICAL_VOLUME_INTEGRITY;
+
+typedef struct {
+ UDF_DESCRIPTOR_TAG DescriptorTag;
+ UINT32 VolumeDescriptorSequenceNumber;
+ UINT16 PartitionFlags;
+ UINT16 PartitionNumber;
+ UDF_ENTITY_ID PartitionContents;
+ UINT8 PartitionContentsUse[128];
+ UINT32 AccessType;
+ UINT32 PartitionStartingLocation;
+ UINT32 PartitionLength;
+ UDF_ENTITY_ID ImplementationIdentifier;
+ UINT8 ImplementationUse[128];
+ UINT8 Reserved[156];
+} UDF_PARTITION_DESCRIPTOR;
+
+typedef struct {
+ UDF_DESCRIPTOR_TAG DescriptorTag;
+ UDF_TIMESTAMP RecordingDateAndTime;
+ UINT16 InterchangeLevel;
+ UINT16 MaximumInterchangeLevel;
+ UINT32 CharacterSetList;
+ UINT32 MaximumCharacterSetList;
+ UINT32 FileSetNumber;
+ UINT32 FileSetDescriptorNumber;
+ UDF_CHAR_SPEC LogicalVolumeIdentifierCharacterSet;
+ UINT8 LogicalVolumeIdentifier[128];
+ UDF_CHAR_SPEC FileSetCharacterSet;
+ UINT8 FileSetIdentifier[32];
+ UINT8 CopyrightFileIdentifier[32];
+ UINT8 AbstractFileIdentifier[32];
+ UDF_LONG_ALLOCATION_DESCRIPTOR RootDirectoryIcb;
+ UDF_ENTITY_ID DomainIdentifier;
+ UDF_LONG_ALLOCATION_DESCRIPTOR NextExtent;
+ UDF_LONG_ALLOCATION_DESCRIPTOR SystemStreamDirectoryIcb;
+ UINT8 Reserved[32];
+} UDF_FILE_SET_DESCRIPTOR;
+
+typedef struct {
+ UINT32 ExtentLength;
+ UINT32 ExtentPosition;
+} UDF_SHORT_ALLOCATION_DESCRIPTOR;
+
+typedef struct {
+ UDF_DESCRIPTOR_TAG DescriptorTag;
+ UINT16 FileVersionNumber;
+ UINT8 FileCharacteristics;
+ UINT8 LengthOfFileIdentifier;
+ UDF_LONG_ALLOCATION_DESCRIPTOR Icb;
+ UINT16 LengthOfImplementationUse;
+ UINT8 Data[0];
+} UDF_FILE_IDENTIFIER_DESCRIPTOR;
+
+typedef struct {
+ UINT32 PriorRecordNumberOfDirectEntries;
+ UINT16 StrategyType;
+ UINT16 StrategyParameter;
+ UINT16 MaximumNumberOfEntries;
+ UINT8 Reserved;
+ UINT8 FileType;
+ UDF_LB_ADDR ParentIcbLocation;
+ UINT16 Flags;
+} UDF_ICB_TAG;
+
+typedef struct {
+ UDF_DESCRIPTOR_TAG DescriptorTag;
+ UDF_ICB_TAG IcbTag;
+ UINT32 Uid;
+ UINT32 Gid;
+ UINT32 Permissions;
+ UINT16 FileLinkCount;
+ UINT8 RecordFormat;
+ UINT8 RecordDisplayAttributes;
+ UINT32 RecordLength;
+ UINT64 InformationLength;
+ UINT64 LogicalBlocksRecorded;
+ UDF_TIMESTAMP AccessTime;
+ UDF_TIMESTAMP ModificationTime;
+ UDF_TIMESTAMP AttributeTime;
+ UINT32 CheckPoint;
+ UDF_LONG_ALLOCATION_DESCRIPTOR ExtendedAttributeIcb;
+ UDF_ENTITY_ID ImplementationIdentifier;
+ UINT64 UniqueId;
+ UINT32 LengthOfExtendedAttributes;
+ UINT32 LengthOfAllocationDescriptors;
+ UINT8 Data[0]; // L_EA + L_AD
+} UDF_FILE_ENTRY;
+
+typedef struct {
+ UDF_DESCRIPTOR_TAG DescriptorTag;
+ UDF_ICB_TAG IcbTag;
+ UINT32 Uid;
+ UINT32 Gid;
+ UINT32 Permissions;
+ UINT16 FileLinkCount;
+ UINT8 RecordFormat;
+ UINT8 RecordDisplayAttributes;
+ UINT32 RecordLength;
+ UINT64 InformationLength;
+ UINT64 ObjectSize;
+ UINT64 LogicalBlocksRecorded;
+ UDF_TIMESTAMP AccessTime;
+ UDF_TIMESTAMP ModificationTime;
+ UDF_TIMESTAMP CreationTime;
+ UDF_TIMESTAMP AttributeTime;
+ UINT32 CheckPoint;
+ UINT32 Reserved;
+ UDF_LONG_ALLOCATION_DESCRIPTOR ExtendedAttributeIcb;
+ UDF_LONG_ALLOCATION_DESCRIPTOR StreamDirectoryIcb;
+ UDF_ENTITY_ID ImplementationIdentifier;
+ UINT64 UniqueId;
+ UINT32 LengthOfExtendedAttributes;
+ UINT32 LengthOfAllocationDescriptors;
+ UINT8 Data[0]; // L_EA + L_AD
+} UDF_EXTENDED_FILE_ENTRY;
+
+typedef struct {
+ UINT8 ComponentType;
+ UINT8 LengthOfComponentIdentifier;
+ UINT16 ComponentFileVersionNumber;
+ UINT8 ComponentIdentifier[0];
+} UDF_PATH_COMPONENT;
+
+#pragma pack()
+
+//
+// UDF filesystem driver's private data
+//
+typedef struct {
+ UINT64 MainVdsStartLocation;
+ UDF_LOGICAL_VOLUME_DESCRIPTOR LogicalVolDesc;
+ UDF_PARTITION_DESCRIPTOR PartitionDesc;
+ UDF_FILE_SET_DESCRIPTOR FileSetDesc;
+ UINTN FileEntrySize;
+} UDF_VOLUME_INFO;
+
+typedef struct {
+ VOID *FileEntry;
+ UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc;
+} UDF_FILE_INFO;
+
+typedef struct {
+ VOID *DirectoryData;
+ UINT64 DirectoryLength;
+ UINT64 FidOffset;
+} UDF_READ_DIRECTORY_INFO;
+
+#define PRIVATE_UDF_FILE_DATA_SIGNATURE SIGNATURE_32 ('U', 'd', 'f', 'f')
+
+#define PRIVATE_UDF_FILE_DATA_FROM_THIS(a) \
+ CR ( \
+ a, \
+ PRIVATE_UDF_FILE_DATA, \
+ FileIo, \
+ PRIVATE_UDF_FILE_DATA_SIGNATURE \
+ )
+
+typedef struct {
+ UINTN Signature;
+ BOOLEAN IsRootDirectory;
+ UDF_FILE_INFO *Root;
+ UDF_FILE_INFO File;
+ UDF_READ_DIRECTORY_INFO ReadDirInfo;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;
+ EFI_FILE_PROTOCOL FileIo;
+ CHAR16 AbsoluteFileName[UDF_PATH_LENGTH];
+ CHAR16 FileName[UDF_FILENAME_LENGTH];
+ UINT64 FileSize;
+ UINT64 FilePosition;
+} PRIVATE_UDF_FILE_DATA;
+
+#define PRIVATE_UDF_SIMPLE_FS_DATA_SIGNATURE SIGNATURE_32 ('U', 'd', 'f', 's')
+
+#define PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS(a) \
+ CR ( \
+ a, \
+ PRIVATE_UDF_SIMPLE_FS_DATA, \
+ SimpleFs, \
+ PRIVATE_UDF_SIMPLE_FS_DATA_SIGNATURE \
+ )
+
+typedef struct {
+ UINTN Signature;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFs;
+ UDF_VOLUME_INFO Volume;
+ UDF_FILE_INFO Root;
+ UINTN OpenFiles;
+ EFI_HANDLE Handle;
+} PRIVATE_UDF_SIMPLE_FS_DATA;
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gUdfDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gUdfComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gUdfComponentName2;
+
+//
+// Function Prototypes
+//
+
+/**
+ Open the root directory on a volume.
+
+ @param This Protocol instance pointer.
+ @param Root Returns an Open file handle for the root directory
+
+ @retval EFI_SUCCESS The device was opened.
+ @retval EFI_UNSUPPORTED This volume does not support the file system.
+ @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_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfOpenVolume (
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **Root
+ );
+
+/**
+ Opens a new file relative to the source file's location.
+
+ @param This The protocol instance pointer.
+ @param NewHandle Returns File Handle for FileName.
+ @param FileName Null terminated string. "\", ".", and ".." are supported.
+ @param OpenMode Open mode for file.
+ @param Attributes Only used for EFI_FILE_MODE_CREATE.
+
+ @retval EFI_SUCCESS The device was opened.
+ @retval EFI_NOT_FOUND The specified file could not be found on the device.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_MEDIA_CHANGED The media has changed.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfOpen (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ );
+
+/**
+ Read data from the file.
+
+ @param This Protocol instance pointer.
+ @param BufferSize On input size of buffer, on output amount of data in buffer.
+ @param Buffer The buffer in which data is read.
+
+ @retval EFI_SUCCESS Data was read.
+ @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_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfRead (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Close the file handle.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The file was closed.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfClose (
+ IN EFI_FILE_PROTOCOL *This
+ );
+
+/**
+ Close and delete the file handle.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The file was closed and deleted.
+ @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not
+ deleted.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfDelete (
+ IN EFI_FILE_PROTOCOL *This
+ );
+
+/**
+ Write data to a file.
+
+ @param This Protocol instance pointer.
+ @param BufferSize On input size of buffer, on output amount of data in buffer.
+ @param Buffer The buffer in which data to write.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfWrite (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+ Get file's current position.
+
+ @param This Protocol instance pointer.
+ @param Position Byte position from the start of the file.
+
+ @retval EFI_SUCCESS Position was updated.
+ @retval EFI_UNSUPPORTED Seek request for directories is not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfGetPosition (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT UINT64 *Position
+ );
+
+/**
+ Set file's current position.
+
+ @param This Protocol instance pointer.
+ @param Position Byte position from the start of the file.
+
+ @retval EFI_SUCCESS Position was updated.
+ @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfSetPosition (
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINT64 Position
+ );
+
+/**
+ Get information about a file.
+
+ @attention This is boundary function that may receive untrusted input.
+ @attention The input is from FileSystem.
+
+ The File Set Descriptor is external input, so this routine will do basic
+ validation for File Set Descriptor and report status.
+
+ @param This Protocol instance pointer.
+ @param InformationType Type of information to return in Buffer.
+ @param BufferSize On input size of buffer, on output amount of data in
+ buffer.
+ @param Buffer The buffer to return data.
+
+ @retval EFI_SUCCESS Data was returned.
+ @retval EFI_UNSUPPORTED InformationType is 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_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in
+ BufferSize.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfGetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Set information about a file.
+
+ @param This Protocol instance pointer.
+ @param InformationType Type of information in Buffer.
+ @param BufferSize Size of buffer.
+ @param Buffer The data to write.
+
+ @retval EFI_SUCCESS Data was set.
+ @retval EFI_UNSUPPORTED InformationType is 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_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfSetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+ Flush data back for the file handle.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS Data was flushed.
+ @retval EFI_UNSUPPORTED Writes to Open directory are 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_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfFlush (
+ IN EFI_FILE_PROTOCOL *This
+ );
+
+/**
+ Read volume information on a medium which contains a valid UDF file system.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[out] Volume UDF volume information structure.
+
+ @retval EFI_SUCCESS Volume information read.
+ @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 volume was not read due to lack of resources.
+
+**/
+EFI_STATUS
+ReadUdfVolumeInformation (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ OUT UDF_VOLUME_INFO *Volume
+ );
+
+/**
+ Find the root directory on an UDF volume.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[out] File Root directory file.
+
+ @retval EFI_SUCCESS Root directory found.
+ @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 root directory was not found due to lack of
+ resources.
+
+**/
+EFI_STATUS
+FindRootDirectory (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ OUT UDF_FILE_INFO *File
+ );
+
+/**
+ Find either a File Entry or a Extended File Entry from a given ICB.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[in] Icb ICB of the FID.
+ @param[out] FileEntry File Entry or Extended File Entry.
+
+ @retval EFI_SUCCESS File Entry or Extended File Entry found.
+ @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 FE/EFE entry was not found due to lack of
+ resources.
+
+**/
+EFI_STATUS
+FindFileEntry (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb,
+ OUT VOID **FileEntry
+ );
+
+/**
+ Find a file given its absolute path on an UDF volume.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[in] FilePath File's absolute path.
+ @param[in] Root Root directory file.
+ @param[in] Parent Parent directory file.
+ @param[in] Icb ICB of Parent.
+ @param[out] File Found file.
+
+ @retval EFI_SUCCESS FilePath was found.
+ @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 FilePath file was not found due to lack of
+ resources.
+
+**/
+EFI_STATUS
+FindFile (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN CHAR16 *FilePath,
+ IN UDF_FILE_INFO *Root,
+ IN UDF_FILE_INFO *Parent,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb,
+ OUT UDF_FILE_INFO *File
+ );
+
+/**
+ Read a directory entry at a time on an UDF volume.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[in] ParentIcb ICB of the parent file.
+ @param[in] FileEntryData FE/EFE of the parent file.
+ @param[in, out] ReadDirInfo Next read directory listing structure
+ information.
+ @param[out] FoundFid File Identifier Descriptor pointer.
+
+ @retval EFI_SUCCESS Directory entry 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 directory entry was not read due to lack of
+ resources.
+
+**/
+EFI_STATUS
+ReadDirectoryEntry (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,
+ IN VOID *FileEntryData,
+ IN OUT UDF_READ_DIRECTORY_INFO *ReadDirInfo,
+ OUT UDF_FILE_IDENTIFIER_DESCRIPTOR **FoundFid
+ );
+
+/**
+ Get a filename (encoded in OSTA-compressed format) from a File Identifier
+ Descriptor on an UDF volume.
+
+ @attention This is boundary function that may receive untrusted input.
+ @attention The input is from FileSystem.
+
+ The File Identifier Descriptor is external input, so this routine will do
+ basic validation for File Identifier Descriptor and report status.
+
+ @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
+ @param[in] CharMax The maximum number of FileName Unicode char,
+ including terminating null char.
+ @param[out] FileName Decoded filename.
+
+ @retval EFI_SUCCESS Filename decoded and read.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TOO_SMALL The string buffer FileName cannot hold the
+ decoded filename.
+**/
+EFI_STATUS
+GetFileNameFromFid (
+ IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc,
+ IN UINTN CharMax,
+ OUT CHAR16 *FileName
+ );
+
+/**
+ Resolve a symlink file on an UDF volume.
+
+ @attention This is boundary function that may receive untrusted input.
+ @attention The input is from FileSystem.
+
+ The Path Component is external input, so this routine will do basic
+ validation for Path Component and report status.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[in] Parent Parent file.
+ @param[in] FileEntryData FE/EFE structure pointer.
+ @param[out] File Resolved file.
+
+ @retval EFI_SUCCESS Symlink file resolved.
+ @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 symlink file was not resolved due to lack of
+ resources.
+
+**/
+EFI_STATUS
+ResolveSymlink (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_FILE_INFO *Parent,
+ IN VOID *FileEntryData,
+ OUT UDF_FILE_INFO *File
+ );
+
+/**
+ Clean up in-memory UDF file information.
+
+ @param[in] File File information pointer.
+
+**/
+VOID
+CleanupFileInformation (
+ IN UDF_FILE_INFO *File
+ );
+
+/**
+ Find a file from its absolute path 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[out] Size Size of the file.
+
+ @retval EFI_SUCCESS File size calculated and set in Size.
+ @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 size was not calculated due to lack of
+ resources.
+
+**/
+EFI_STATUS
+GetFileSize (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ IN UDF_FILE_INFO *File,
+ OUT UINT64 *Size
+ );
+
+/**
+ Set information about a file on an UDF volume.
+
+ @param[in] File File pointer.
+ @param[in] FileSize Size of the file.
+ @param[in] FileName Filename of the file.
+ @param[in, out] BufferSize Size of the returned file infomation.
+ @param[out] Buffer Data of the returned file information.
+
+ @retval EFI_SUCCESS File information set.
+ @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 information was not set due to lack of
+ resources.
+
+**/
+EFI_STATUS
+SetFileInfo (
+ IN UDF_FILE_INFO *File,
+ IN UINT64 FileSize,
+ IN CHAR16 *FileName,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Get volume label of an UDF volume.
+
+ @attention This is boundary function that may receive untrusted input.
+ @attention The input is from FileSystem.
+
+ The File Set Descriptor is external input, so this routine will do basic
+ validation for File Set Descriptor and report status.
+
+ @param[in] Volume Volume information pointer.
+ @param[in] CharMax The maximum number of Unicode char in String,
+ including terminating null char.
+ @param[out] String String buffer pointer to store the volume label.
+
+ @retval EFI_SUCCESS Volume label is returned.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TOO_SMALL The string buffer String cannot hold the
+ volume label.
+
+**/
+EFI_STATUS
+GetVolumeLabel (
+ IN UDF_VOLUME_INFO *Volume,
+ IN UINTN CharMax,
+ OUT CHAR16 *String
+ );
+
+/**
+ Get volume and free space size information of an UDF volume.
+
+ @attention This is boundary function that may receive untrusted input.
+ @attention The input is from FileSystem.
+
+ The Logical Volume Descriptor and the Logical Volume Integrity Descriptor are
+ external inputs, so this routine will do basic validation for both descriptors
+ and report status.
+
+ @param[in] BlockIo BlockIo interface.
+ @param[in] DiskIo DiskIo interface.
+ @param[in] Volume UDF volume information structure.
+ @param[out] VolumeSize Volume size.
+ @param[out] FreeSpaceSize Free space size.
+
+ @retval EFI_SUCCESS Volume and free space size calculated.
+ @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 volume and free space size were not
+ calculated due to lack of resources.
+
+**/
+EFI_STATUS
+GetVolumeSize (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN UDF_VOLUME_INFO *Volume,
+ OUT UINT64 *VolumeSize,
+ OUT UINT64 *FreeSpaceSize
+ );
+
+/**
+ 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
+ );
+
+/**
+ Check if ControllerHandle supports an UDF file system.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] ControllerHandle Handle of device to test.
+
+ @retval EFI_SUCCESS UDF file system found.
+ @retval EFI_UNSUPPORTED UDF file system not found.
+
+**/
+EFI_STATUS
+SupportUdfFileSystem (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle
+ );
+
+/**
+ Mangle a filename by cutting off trailing whitespaces, "\\", "." and "..".
+
+ @param[in] FileName Filename.
+
+ @retval The mangled Filename.
+
+**/
+CHAR16 *
+MangleFileName (
+ IN CHAR16 *FileName
+ );
+
+/**
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ than contains a BlockIo and DiskIo protocol can be supported.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to test
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS This driver supports this device
+ @retval EFI_ALREADY_STARTED This driver is already running on this device
+ @retval other This driver does not support this device
+
+**/
+EFI_STATUS
+EFIAPI
+UdfDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Start this driver on ControllerHandle by opening a Block IO and Disk IO
+ protocol, reading Device Path, and creating a child handle with a
+ Disk IO and device path protocol.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to bind driver to
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS This driver is added to ControllerHandle
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
+ @retval other This driver does not support this device
+
+**/
+EFI_STATUS
+EFIAPI
+UdfDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop this driver on ControllerHandle. Support stopping any child handles
+ created by this driver.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to stop driver on
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
+ children is zero stop the entire bus driver.
+ @param ChildHandleBuffer List of Child Handles to Stop.
+
+ @retval EFI_SUCCESS This driver is removed ControllerHandle
+ @retval other This driver was not removed from this device
+
+**/
+EFI_STATUS
+EFIAPI
+UdfDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// EFI Component Name Functions
+//
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UdfComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+#endif // _UDF_H_
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf b/MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
index 16c411b6b0..08f15b95e6 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
@@ -1,62 +1,62 @@
-## @file
-# UDF/ECMA-167 file system driver.
-#
-# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
-# Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-##
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = UdfDxe
- FILE_GUID = 905f13b0-8f91-4b0a-bd76-e1e78f9422e4
- MODULE_TYPE = UEFI_DRIVER
- VERSION_STRING = 1.0
- ENTRY_POINT = InitializeUdf
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64 EBC
-#
-# DRIVER_BINDING = gUdfDriverBinding
-# COMPONENT_NAME = gUdfComponentName
-# COMPONENT_NAME2 = gUdfComponentName2
-#
-
-[Sources]
- ComponentName.c
- FileSystemOperations.c
- FileName.c
- File.c
- Udf.c
- Udf.h
-
-
-[Packages]
- MdePkg/MdePkg.dec
-
-
-[LibraryClasses]
- DevicePathLib
- UefiBootServicesTableLib
- MemoryAllocationLib
- BaseMemoryLib
- UefiLib
- BaseLib
- UefiDriverEntryPoint
- DebugLib
-
-
-[Guids]
- gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## Protocol
- gEfiFileSystemInfoGuid ## SOMETIMES_CONSUMES ## Protocol
- gEfiFileSystemVolumeLabelInfoIdGuid ## SOMETIMES_CONSUMES ## Protocol
-
-
-[Protocols]
- gEfiSimpleFileSystemProtocolGuid ## BY_START
- gEfiDevicePathProtocolGuid ## BY_START
- gEfiBlockIoProtocolGuid ## TO_START
- gEfiDiskIoProtocolGuid ## TO_START
+## @file
+# UDF/ECMA-167 file system driver.
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UdfDxe
+ FILE_GUID = 905f13b0-8f91-4b0a-bd76-e1e78f9422e4
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeUdf
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+# DRIVER_BINDING = gUdfDriverBinding
+# COMPONENT_NAME = gUdfComponentName
+# COMPONENT_NAME2 = gUdfComponentName2
+#
+
+[Sources]
+ ComponentName.c
+ FileSystemOperations.c
+ FileName.c
+ File.c
+ Udf.c
+ Udf.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+
+[LibraryClasses]
+ DevicePathLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ UefiLib
+ BaseLib
+ UefiDriverEntryPoint
+ DebugLib
+
+
+[Guids]
+ gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## Protocol
+ gEfiFileSystemInfoGuid ## SOMETIMES_CONSUMES ## Protocol
+ gEfiFileSystemVolumeLabelInfoIdGuid ## SOMETIMES_CONSUMES ## Protocol
+
+
+[Protocols]
+ gEfiSimpleFileSystemProtocolGuid ## BY_START
+ gEfiDevicePathProtocolGuid ## BY_START
+ gEfiBlockIoProtocolGuid ## TO_START
+ gEfiDiskIoProtocolGuid ## TO_START