2007-12-20 10:16:45 +01:00
|
|
|
/*++
|
|
|
|
|
2014-01-09 09:59:24 +01:00
|
|
|
Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>
|
2010-04-26 03:24:39 +02:00
|
|
|
This program and the accompanying materials are licensed and made available
|
2007-12-20 10:16:45 +01:00
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
Module Name:
|
|
|
|
|
|
|
|
Fat.c
|
|
|
|
|
|
|
|
Abstract:
|
|
|
|
|
|
|
|
Fat File System driver routines that support EFI driver model
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#include "Fat.h"
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
FatEntryPoint (
|
|
|
|
IN EFI_HANDLE ImageHandle,
|
|
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
|
|
);
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
FatUnload (
|
|
|
|
IN EFI_HANDLE ImageHandle
|
|
|
|
);
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
FatDriverBindingSupported (
|
|
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
|
|
IN EFI_HANDLE Controller,
|
|
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
|
|
);
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
FatDriverBindingStart (
|
|
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
|
|
IN EFI_HANDLE Controller,
|
|
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
|
|
);
|
|
|
|
|
|
|
|
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
|
|
|
|
};
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
FatEntryPoint (
|
|
|
|
IN EFI_HANDLE ImageHandle,
|
|
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Register Driver Binding protocol for this driver.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
ImageHandle - Handle for the image of this driver.
|
|
|
|
SystemTable - Pointer to the EFI System Table.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
EFI_SUCCESS - Driver loaded.
|
|
|
|
other - Driver not loaded.
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Initialize the EFI Driver Library
|
|
|
|
//
|
|
|
|
Status = EfiLibInstallDriverBindingComponentName2 (
|
|
|
|
ImageHandle,
|
|
|
|
SystemTable,
|
|
|
|
&gFatDriverBinding,
|
|
|
|
ImageHandle,
|
|
|
|
&gFatComponentName,
|
|
|
|
&gFatComponentName2
|
|
|
|
);
|
|
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
FatUnload (
|
|
|
|
IN EFI_HANDLE ImageHandle
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Unload function for this image. Uninstall DriverBinding protocol.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
ImageHandle - Handle for the image of this driver.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
EFI_SUCCESS - Driver unloaded successfully.
|
|
|
|
other - Driver can not unloaded.
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
EFI_HANDLE *DeviceHandleBuffer;
|
|
|
|
UINTN DeviceHandleCount;
|
|
|
|
UINTN Index;
|
2014-01-09 09:59:24 +01:00
|
|
|
VOID *ComponentName;
|
|
|
|
VOID *ComponentName2;
|
2007-12-20 10:16:45 +01:00
|
|
|
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
|
|
AllHandles,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&DeviceHandleCount,
|
|
|
|
&DeviceHandleBuffer
|
|
|
|
);
|
2014-01-09 09:59:24 +01:00
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Index = 0; Index < DeviceHandleCount; Index++) {
|
|
|
|
Status = EfiTestManagedDevice (DeviceHandleBuffer[Index], ImageHandle, &gEfiDiskIoProtocolGuid);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
2007-12-20 10:16:45 +01:00
|
|
|
Status = gBS->DisconnectController (
|
|
|
|
DeviceHandleBuffer[Index],
|
|
|
|
ImageHandle,
|
|
|
|
NULL
|
|
|
|
);
|
2014-01-09 09:59:24 +01:00
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Index == DeviceHandleCount) {
|
|
|
|
//
|
|
|
|
// Driver is stopped successfully.
|
|
|
|
//
|
|
|
|
Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentNameProtocolGuid, &ComponentName);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ComponentName = NULL;
|
2007-12-20 10:16:45 +01:00
|
|
|
}
|
|
|
|
|
2014-01-09 09:59:24 +01:00
|
|
|
Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentName2ProtocolGuid, &ComponentName2);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ComponentName2 = NULL;
|
2007-12-20 10:16:45 +01:00
|
|
|
}
|
2014-01-09 09:59:24 +01:00
|
|
|
|
|
|
|
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);
|
2007-12-20 10:16:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
FatDriverBindingSupported (
|
|
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
|
|
IN EFI_HANDLE ControllerHandle,
|
|
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Test to see if this driver can add a file system to ControllerHandle.
|
|
|
|
ControllerHandle must support both Disk IO and Block IO protocols.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
This - Protocol instance pointer.
|
|
|
|
ControllerHandle - Handle of device to test.
|
|
|
|
RemainingDevicePath - Not used.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
EFI_SUCCESS - This driver supports this device.
|
|
|
|
EFI_ALREADY_STARTED - This driver is already running on this device.
|
|
|
|
other - This driver does not support this device.
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
FatDriverBindingStart (
|
|
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
|
|
IN EFI_HANDLE ControllerHandle,
|
|
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
This - Protocol instance pointer.
|
|
|
|
ControllerHandle - Handle of device to bind driver to.
|
|
|
|
RemainingDevicePath - Not used.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
EFI_SUCCESS - This driver is added to DeviceHandle.
|
|
|
|
EFI_ALREADY_STARTED - This driver is already running on DeviceHandle.
|
|
|
|
EFI_OUT_OF_RESOURCES - Can not allocate the memory.
|
|
|
|
other - This driver does not support this device.
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
|
|
|
EFI_DISK_IO_PROTOCOL *DiskIo;
|
2013-10-30 04:13:16 +01:00
|
|
|
EFI_DISK_IO2_PROTOCOL *DiskIo2;
|
2010-05-07 05:31:16 +02:00
|
|
|
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;
|
|
|
|
}
|
2007-12-20 10:16:45 +01:00
|
|
|
|
|
|
|
Status = InitializeUnicodeCollationSupport (This->DriverBindingHandle);
|
|
|
|
if (EFI_ERROR (Status)) {
|
2010-05-07 05:31:16 +02:00
|
|
|
goto Exit;
|
2007-12-20 10:16:45 +01:00
|
|
|
}
|
|
|
|
//
|
|
|
|
// 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)) {
|
2010-05-07 05:31:16 +02:00
|
|
|
goto Exit;
|
2007-12-20 10:16:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Status = gBS->OpenProtocol (
|
|
|
|
ControllerHandle,
|
|
|
|
&gEfiDiskIoProtocolGuid,
|
|
|
|
(VOID **) &DiskIo,
|
|
|
|
This->DriverBindingHandle,
|
|
|
|
ControllerHandle,
|
|
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
2010-05-07 05:31:16 +02:00
|
|
|
goto Exit;
|
2007-12-20 10:16:45 +01:00
|
|
|
}
|
2013-10-30 04:13:16 +01:00
|
|
|
|
|
|
|
Status = gBS->OpenProtocol (
|
|
|
|
ControllerHandle,
|
|
|
|
&gEfiDiskIo2ProtocolGuid,
|
|
|
|
(VOID **) &DiskIo2,
|
|
|
|
This->DriverBindingHandle,
|
|
|
|
ControllerHandle,
|
|
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
DiskIo2 = NULL;
|
|
|
|
}
|
|
|
|
|
2007-12-20 10:16:45 +01:00
|
|
|
//
|
|
|
|
// Allocate Volume structure. In FatAllocateVolume(), Resources
|
|
|
|
// are allocated with protocol installed and cached initialized
|
|
|
|
//
|
2013-10-30 04:13:16 +01:00
|
|
|
Status = FatAllocateVolume (ControllerHandle, DiskIo, DiskIo2, BlockIo);
|
2007-12-20 10:16:45 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// When the media changes on a device it will Reinstall the BlockIo interaface.
|
|
|
|
// 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
|
|
|
|
);
|
2013-10-30 04:13:16 +01:00
|
|
|
gBS->CloseProtocol (
|
|
|
|
ControllerHandle,
|
|
|
|
&gEfiDiskIo2ProtocolGuid,
|
|
|
|
This->DriverBindingHandle,
|
|
|
|
ControllerHandle
|
|
|
|
);
|
2007-12-20 10:16:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-07 05:31:16 +02:00
|
|
|
Exit:
|
|
|
|
//
|
|
|
|
// Unlock if locked by myself.
|
|
|
|
//
|
|
|
|
if (LockedByMe) {
|
|
|
|
FatReleaseLock ();
|
|
|
|
}
|
2007-12-20 10:16:45 +01:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
FatDriverBindingStop (
|
|
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
|
|
IN EFI_HANDLE ControllerHandle,
|
|
|
|
IN UINTN NumberOfChildren,
|
|
|
|
IN EFI_HANDLE *ChildHandleBuffer
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
Stop this driver on ControllerHandle.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
This - Protocol instance pointer.
|
|
|
|
ControllerHandle - Handle of device to stop driver on.
|
|
|
|
NumberOfChildren - Not used.
|
|
|
|
ChildHandleBuffer - Not used.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
EFI_SUCCESS - This driver is removed DeviceHandle.
|
|
|
|
other - This driver was not removed from this device.
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
|
|
|
|
FAT_VOLUME *Volume;
|
2013-11-22 08:39:02 +01:00
|
|
|
EFI_DISK_IO2_PROTOCOL *DiskIo2;
|
2007-12-20 10:16:45 +01:00
|
|
|
|
2013-11-22 08:39:02 +01:00
|
|
|
DiskIo2 = NULL;
|
2007-12-20 10:16:45 +01:00
|
|
|
//
|
|
|
|
// Get our context back
|
|
|
|
//
|
|
|
|
Status = gBS->OpenProtocol (
|
|
|
|
ControllerHandle,
|
|
|
|
&gEfiSimpleFileSystemProtocolGuid,
|
|
|
|
(VOID **) &FileSystem,
|
|
|
|
This->DriverBindingHandle,
|
|
|
|
ControllerHandle,
|
|
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!EFI_ERROR (Status)) {
|
2013-11-22 08:39:02 +01:00
|
|
|
Volume = VOLUME_FROM_VOL_INTERFACE (FileSystem);
|
|
|
|
DiskIo2 = Volume->DiskIo2;
|
|
|
|
Status = FatAbandonVolume (Volume);
|
2007-12-20 10:16:45 +01:00
|
|
|
}
|
|
|
|
|
2013-11-22 08:39:02 +01:00
|
|
|
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);
|
|
|
|
}
|
2007-12-20 10:16:45 +01:00
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|