CloverBootloader/Ext4Pkg/Ext4Dxe/Partition.c

133 lines
3.6 KiB
C

/** @file
Driver entry point
Copyright (c) 2021 Pedro Falcato All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "Ext4Dxe.h"
/**
Opens an ext4 partition and installs the Simple File System protocol.
@param[in] DeviceHandle Handle to the block device.
@param[in] DiskIo Pointer to an EFI_DISK_IO_PROTOCOL.
@param[in opt] DiskIo2 Pointer to an EFI_DISK_IO2_PROTOCOL, if supported.
@param[in] BlockIo Pointer to an EFI_BLOCK_IO_PROTOCOL.
@retval EFI_SUCCESS The opening was successful.
!EFI_SUCCESS Opening failed.
**/
EFI_STATUS
Ext4OpenPartition (
IN EFI_HANDLE DeviceHandle,
IN EFI_DISK_IO_PROTOCOL *DiskIo,
IN OPTIONAL EFI_DISK_IO2_PROTOCOL *DiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *BlockIo
)
{
EXT4_PARTITION *Part;
EFI_STATUS Status;
Part = AllocateZeroPool (sizeof (*Part));
if (Part == NULL) {
return EFI_OUT_OF_RESOURCES;
}
InitializeListHead (&Part->OpenFiles);
Part->BlockIo = BlockIo;
Part->DiskIo = DiskIo;
Part->DiskIo2 = DiskIo2;
Status = Ext4OpenSuperblock (Part);
if (EFI_ERROR (Status)) {
FreePool (Part);
return Status;
}
Part->Interface.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
Part->Interface.OpenVolume = Ext4OpenVolume;
Status = gBS->InstallMultipleProtocolInterfaces (
&DeviceHandle,
&gEfiSimpleFileSystemProtocolGuid,
&Part->Interface,
NULL
);
if (EFI_ERROR (Status)) {
FreePool (Part);
return Status;
}
return EFI_SUCCESS;
}
/**
Sets up the protocol and metadata of a file that is being opened.
@param[in out] File Pointer to the file.
@param[in] Partition Pointer to the opened partition.
**/
VOID
Ext4SetupFile (
IN OUT EXT4_FILE *File,
IN EXT4_PARTITION *Partition
)
{
// Note: We don't yet support revision 2 of the file protocol
// (needs DISK_IO2 + asynchronous IO)
File->Protocol.Revision = EFI_FILE_PROTOCOL_REVISION;
File->Protocol.Open = Ext4Open;
File->Protocol.Close = Ext4Close;
File->Protocol.Delete = Ext4Delete;
File->Protocol.Read = Ext4ReadFile;
File->Protocol.Write = Ext4WriteFile;
File->Protocol.SetPosition = Ext4SetPosition;
File->Protocol.GetPosition = Ext4GetPosition;
File->Protocol.GetInfo = Ext4GetInfo;
File->Protocol.SetInfo = Ext4SetInfo;
File->Partition = Partition;
}
/**
Unmounts and frees an ext4 partition.
@param[in] Partition Pointer to the opened partition.
@retval Status of the unmount.
**/
EFI_STATUS
Ext4UnmountAndFreePartition (
IN EXT4_PARTITION *Partition
)
{
LIST_ENTRY *Entry;
LIST_ENTRY *NextEntry;
EXT4_FILE *File;
BOOLEAN DeletedRootDentry;
Partition->Unmounting = TRUE;
Ext4CloseInternal (Partition->Root);
BASE_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Partition->OpenFiles) {
File = EXT4_FILE_FROM_OPEN_FILES_NODE (Entry);
Ext4CloseInternal (File);
}
DeletedRootDentry = Ext4UnrefDentry (Partition->RootDentry);
if (!DeletedRootDentry) {
DEBUG ((DEBUG_ERROR, "[ext4] Failed to delete root dentry - resource leak present.\n"));
}
FreePool (Partition->BlockGroups);
FreePool (Partition);
return EFI_SUCCESS;
}