/** @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; | |
} |