MdeModulePkg: Initial UDF/ECMA-167 file system support
This patch introduces UDF file system support in EDK2. All block devices that support BlockIo and DiskIo protocols and contain a valid UDF file system - as specified by OSTA Universal Disk Format (revisions 1.02 through 2.60) - will be installed EFI_SIMPLE_FILE_SYSTEM_PROTOCOL to provide access to underlying file system. File system operations on regular, directory and symlink files are supported. Cc: Star Zeng <star.zeng@intel.com> Cc: Eric Dong <eric.dong@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pcacjr@zytor.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
This commit is contained in:
committed by
Laszlo Ersek
parent
8aafec2c13
commit
99c9b94905
344
MdeModulePkg/Universal/Disk/UdfDxe/Udf.c
Normal file
344
MdeModulePkg/Universal/Disk/UdfDxe/Udf.c
Normal file
@@ -0,0 +1,344 @@
|
||||
/** @file
|
||||
UDF/ECMA-167 file system driver.
|
||||
|
||||
Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
|
||||
|
||||
This program and the accompanying materials are licensed and made available
|
||||
under the terms and conditions of the BSD License which accompanies this
|
||||
distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
**/
|
||||
|
||||
#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
|
||||
);
|
||||
|
||||
//
|
||||
// Check if there's any open file. If so, clean them up.
|
||||
//
|
||||
if (PrivFsData->OpenFiles > 0) {
|
||||
CleanupVolumeInformation (&PrivFsData->Volume);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
Reference in New Issue
Block a user