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