2023-09-05 02:09:05 +01:00

153 lines
4.4 KiB
C

/*
* ext_disk_io.c
*
* Copyright (c) 2020-2023, DarkMatterCore <pabloacurielz@gmail.com>.
*
* This file is part of libusbhsfs (https://github.com/DarkMatterCore/libusbhsfs).
*/
#include "ext.h"
#include "../usbhsfs_scsi.h"
/* Function prototypes. */
static int ext_blockdev_open(struct ext4_blockdev *bdev);
static int ext_blockdev_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id, uint32_t blk_cnt);
static int ext_blockdev_bwrite(struct ext4_blockdev *bdev, const void *buf, uint64_t blk_id, uint32_t blk_cnt);
static int ext_blockdev_close(struct ext4_blockdev *bdev);
static int ext_blockdev_lock(struct ext4_blockdev *bdev);
static int ext_blockdev_unlock(struct ext4_blockdev *bdev);
/* Global variables. */
static const struct ext4_blockdev_iface ext_blockdev_usbhsfs_iface = {
.open = ext_blockdev_open,
.bread = ext_blockdev_bread,
.bwrite = ext_blockdev_bwrite,
.close = ext_blockdev_close,
.lock = ext_blockdev_lock,
.unlock = ext_blockdev_unlock,
.ph_bsize = 0,
.ph_bcnt = 0,
.ph_bbuf = NULL,
.ph_refctr = 0,
.bread_ctr = 0,
.bwrite_ctr = 0,
.p_user = NULL
};
struct ext4_blockdev *ext_disk_io_alloc_blockdev(void *p_user, u64 part_lba, u64 part_size)
{
UsbHsFsDriveLogicalUnitContext *lun_ctx = (UsbHsFsDriveLogicalUnitContext*)p_user;
struct ext4_blockdev *bdev = NULL;
bool success = false;
/* Allocate memory for ext4_blockdev object. */
bdev = calloc(1, sizeof(struct ext4_blockdev));
if (!bdev)
{
USBHSFS_LOG_MSG("Failed to allocate memory for ext4_blockdev object!");
goto end;
}
/* Allocate memory for ext4_blockdev_iface object. */
bdev->bdif = calloc(1, sizeof(struct ext4_blockdev_iface));
if (!bdev->bdif)
{
USBHSFS_LOG_MSG("Failed to allocate memory for ext4_blockdev_iface object!");
goto end;
}
/* Copy ext4_blockdev_iface object data. */
memcpy(bdev->bdif, &ext_blockdev_usbhsfs_iface, sizeof(struct ext4_blockdev_iface));
/* Allocate memory for block size buffer. */
bdev->bdif->ph_bbuf = calloc(1, lun_ctx->block_length);
if (!bdev->bdif->ph_bbuf)
{
USBHSFS_LOG_MSG("Failed to allocate 0x%X bytes for block size buffer!", lun_ctx->block_length);
goto end;
}
/* Fill ext4_blockdev object. */
bdev->part_offset = (part_lba * (u64)lun_ctx->block_length);
bdev->part_size = (part_size * (u64)lun_ctx->block_length);
/* Fill ext4_blockdev_iface object. */
bdev->bdif->ph_bsize = lun_ctx->block_length;
bdev->bdif->ph_bcnt = part_size;
bdev->bdif->p_user = lun_ctx;
/* Update flag. */
success = true;
end:
if (!success && bdev)
{
ext_disk_io_free_blockdev(bdev);
bdev = NULL;
}
return bdev;
}
void ext_disk_io_free_blockdev(struct ext4_blockdev *bdev)
{
if (!bdev) return;
if (bdev->bdif)
{
if (bdev->bdif->ph_bbuf) free(bdev->bdif->ph_bbuf);
free(bdev->bdif);
}
free(bdev);
}
static int ext_blockdev_open(struct ext4_blockdev *bdev)
{
(void)bdev;
/* Low level block device initialization is handled by us. */
return 0;
}
static int ext_blockdev_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id, uint32_t blk_cnt)
{
/* Get LUN context and read sectors. */
UsbHsFsDriveLogicalUnitContext *lun_ctx = (UsbHsFsDriveLogicalUnitContext*)bdev->bdif->p_user;
return (usbHsFsScsiReadLogicalUnitBlocks(lun_ctx, buf, blk_id, blk_cnt) ? 0 : EIO);
}
static int ext_blockdev_bwrite(struct ext4_blockdev *bdev, const void *buf, uint64_t blk_id, uint32_t blk_cnt)
{
/* Get LUN context and write sectors. */
UsbHsFsDriveLogicalUnitContext *lun_ctx = (UsbHsFsDriveLogicalUnitContext*)bdev->bdif->p_user;
return (usbHsFsScsiWriteLogicalUnitBlocks(lun_ctx, buf, blk_id, blk_cnt) ? 0 : EIO);
}
static int ext_blockdev_close(struct ext4_blockdev *bdev)
{
(void)bdev;
/* Low level block device deinitialization is handled by us. */
return 0;
}
static int ext_blockdev_lock(struct ext4_blockdev *bdev)
{
(void)bdev;
/* Mutex locking is handled by us. */
return 0;
}
static int ext_blockdev_unlock(struct ext4_blockdev *bdev)
{
(void)bdev;
/* Mutex unlocking is handled by us. */
return 0;
}