diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/FatPkg/EnhancedFatDxe/Fat.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/FatPkg/EnhancedFatDxe/Fat.c | 525 |
1 files changed, 525 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/FatPkg/EnhancedFatDxe/Fat.c b/src/VBox/Devices/EFI/Firmware/FatPkg/EnhancedFatDxe/Fat.c new file mode 100644 index 00000000..40c5f343 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/FatPkg/EnhancedFatDxe/Fat.c @@ -0,0 +1,525 @@ +/** @file + Fat File System driver routines that support EFI driver model. + +Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Fat.h" + +/** + + Register Driver Binding protocol for this driver. + + @param ImageHandle - Handle for the image of this driver. + @param SystemTable - Pointer to the EFI System Table. + + @retval EFI_SUCCESS - Driver loaded. + @return other - Driver not loaded. + +**/ +EFI_STATUS +EFIAPI +FatEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + + Unload function for this image. Uninstall DriverBinding protocol. + + @param ImageHandle - Handle for the image of this driver. + + @retval EFI_SUCCESS - Driver unloaded successfully. + @return other - Driver can not unloaded. + +**/ +EFI_STATUS +EFIAPI +FatUnload ( + IN EFI_HANDLE ImageHandle + ); + +/** + + Test to see if this driver can add a file system to ControllerHandle. + ControllerHandle must support both Disk IO and Block IO protocols. + + @param This - Protocol instance pointer. + @param ControllerHandle - Handle of device to test. + @param RemainingDevicePath - Not used. + + @retval EFI_SUCCESS - This driver supports this device. + @retval EFI_ALREADY_STARTED - This driver is already running on this device. + @return other - This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +FatDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + + Start this driver on ControllerHandle by opening a Block IO and Disk IO + protocol, reading Device Path. Add a Simple File System protocol to + ControllerHandle if the media contains a valid file system. + + @param This - Protocol instance pointer. + @param ControllerHandle - Handle of device to bind driver to. + @param RemainingDevicePath - Not used. + + @retval EFI_SUCCESS - This driver is added to DeviceHandle. + @retval EFI_ALREADY_STARTED - This driver is already running on DeviceHandle. + @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory. + @return other - This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +FatDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + + Stop this driver on ControllerHandle. + + @param This - Protocol instance pointer. + @param ControllerHandle - Handle of device to stop driver on. + @param NumberOfChildren - Not used. + @param ChildHandleBuffer - Not used. + + @retval EFI_SUCCESS - This driver is removed DeviceHandle. + @return other - This driver was not removed from this device. + +**/ +EFI_STATUS +EFIAPI +FatDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// DriverBinding protocol instance +// +EFI_DRIVER_BINDING_PROTOCOL gFatDriverBinding = { + FatDriverBindingSupported, + FatDriverBindingStart, + FatDriverBindingStop, + 0xa, + NULL, + NULL +}; + +/** + + Register Driver Binding protocol for this driver. + + @param ImageHandle - Handle for the image of this driver. + @param SystemTable - Pointer to the EFI System Table. + + @retval EFI_SUCCESS - Driver loaded. + @return other - Driver not loaded. + +**/ +EFI_STATUS +EFIAPI +FatEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Initialize the EFI Driver Library + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gFatDriverBinding, + ImageHandle, + &gFatComponentName, + &gFatComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + + Unload function for this image. Uninstall DriverBinding protocol. + + @param ImageHandle - Handle for the image of this driver. + + @retval EFI_SUCCESS - Driver unloaded successfully. + @return other - Driver can not unloaded. + +**/ +EFI_STATUS +EFIAPI +FatUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_HANDLE *DeviceHandleBuffer; + UINTN DeviceHandleCount; + UINTN Index; + VOID *ComponentName; + VOID *ComponentName2; + + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &DeviceHandleCount, + &DeviceHandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < DeviceHandleCount; Index++) { + Status = EfiTestManagedDevice (DeviceHandleBuffer[Index], ImageHandle, &gEfiDiskIoProtocolGuid); + if (!EFI_ERROR (Status)) { + Status = gBS->DisconnectController ( + DeviceHandleBuffer[Index], + ImageHandle, + NULL + ); + if (EFI_ERROR (Status)) { + break; + } + } + } + + if (Index == DeviceHandleCount) { + // + // Driver is stopped successfully. + // + Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentNameProtocolGuid, &ComponentName); + if (EFI_ERROR (Status)) { + ComponentName = NULL; + } + + Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentName2ProtocolGuid, &ComponentName2); + if (EFI_ERROR (Status)) { + ComponentName2 = NULL; + } + + if (ComponentName == NULL) { + if (ComponentName2 == NULL) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + ImageHandle, + &gEfiDriverBindingProtocolGuid, &gFatDriverBinding, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + ImageHandle, + &gEfiDriverBindingProtocolGuid, &gFatDriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + NULL + ); + } + } else { + if (ComponentName2 == NULL) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + ImageHandle, + &gEfiDriverBindingProtocolGuid, &gFatDriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + ImageHandle, + &gEfiDriverBindingProtocolGuid, &gFatDriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + NULL + ); + } + } + } + + if (DeviceHandleBuffer != NULL) { + FreePool (DeviceHandleBuffer); + } + + return Status; +} + +/** + + Test to see if this driver can add a file system to ControllerHandle. + ControllerHandle must support both Disk IO and Block IO protocols. + + @param This - Protocol instance pointer. + @param ControllerHandle - Handle of device to test. + @param RemainingDevicePath - Not used. + + @retval EFI_SUCCESS - This driver supports this device. + @retval EFI_ALREADY_STARTED - This driver is already running on this device. + @return other - This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +FatDriverBindingSupported ( + 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 the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &DiskIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + 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 and Disk IO + protocol, reading Device Path. Add a Simple File System protocol to + ControllerHandle if the media contains a valid file system. + + @param This - Protocol instance pointer. + @param ControllerHandle - Handle of device to bind driver to. + @param RemainingDevicePath - Not used. + + @retval EFI_SUCCESS - This driver is added to DeviceHandle. + @retval EFI_ALREADY_STARTED - This driver is already running on DeviceHandle. + @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory. + @return other - This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +FatDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_DISK_IO2_PROTOCOL *DiskIo2; + BOOLEAN LockedByMe; + + LockedByMe = FALSE; + // + // Acquire the lock. + // If caller has already acquired the lock, cannot lock it again. + // + Status = FatAcquireLockOrFail (); + if (!EFI_ERROR (Status)) { + LockedByMe = TRUE; + } + + Status = InitializeUnicodeCollationSupport (This->DriverBindingHandle); + if (EFI_ERROR (Status)) { + goto Exit; + } + // + // Open our required BlockIo and DiskIo + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &DiskIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDiskIo2ProtocolGuid, + (VOID **) &DiskIo2, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + DiskIo2 = NULL; + } + + // + // Allocate Volume structure. In FatAllocateVolume(), Resources + // are allocated with protocol installed and cached initialized + // + Status = FatAllocateVolume (ControllerHandle, DiskIo, DiskIo2, BlockIo); + + // + // When the media changes on a device it will Reinstall the BlockIo interface. + // This will cause a call to our Stop(), and a subsequent reentrant call to our + // Start() successfully. We should leave the device open when this happen. + // + if (EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIo2ProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + } + +Exit: + // + // Unlock if locked by myself. + // + if (LockedByMe) { + FatReleaseLock (); + } + return Status; +} + +/** + + Stop this driver on ControllerHandle. + + @param This - Protocol instance pointer. + @param ControllerHandle - Handle of device to stop driver on. + @param NumberOfChildren - Not used. + @param ChildHandleBuffer - Not used. + + @retval EFI_SUCCESS - This driver is removed DeviceHandle. + @return other - This driver was not removed from this device. + +**/ +EFI_STATUS +EFIAPI +FatDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem; + FAT_VOLUME *Volume; + EFI_DISK_IO2_PROTOCOL *DiskIo2; + + DiskIo2 = NULL; + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID **) &FileSystem, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (!EFI_ERROR (Status)) { + Volume = VOLUME_FROM_VOL_INTERFACE (FileSystem); + DiskIo2 = Volume->DiskIo2; + Status = FatAbandonVolume (Volume); + } + + if (!EFI_ERROR (Status)) { + if (DiskIo2 != NULL) { + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIo2ProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + ASSERT_EFI_ERROR (Status); + } + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + ASSERT_EFI_ERROR (Status); + } + + return Status; +} |