From aaa076ff1d68545085fb85ee24d5410b60a123bd Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Tue, 14 Oct 2025 20:23:19 -0400 Subject: kern: dms: Make DMS block size aware In order to safely copy between disk and host memory through a programming interface, DMS must be aware of the hardware disk block size Signed-off-by: Ian Moffett --- src/sys/dms/dms_subr.c | 35 +++++++++++++++++++++++++++++++++-- src/sys/include/dms/dms.h | 7 ++++++- src/sys/io/ic/ahci.c | 1 + 3 files changed, 40 insertions(+), 3 deletions(-) (limited to 'src/sys') diff --git a/src/sys/dms/dms_subr.c b/src/sys/dms/dms_subr.c index 240449a..085633b 100644 --- a/src/sys/dms/dms_subr.c +++ b/src/sys/dms/dms_subr.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -100,6 +101,9 @@ dms_get(disk_id_t disk_id) ssize_t dms_write(struct dms_disk *dp, void *p, off_t off, size_t len) { + void *buf; + size_t real_len; + int error; struct dms_ops *ops; if (dp == NULL || p == NULL) { @@ -114,13 +118,25 @@ dms_write(struct dms_disk *dp, void *p, off_t off, size_t len) return -ENOTSUP; } - return ops->write(dp, p, off, len); + real_len = ALIGN_UP(len, dp->bsize); + if ((buf = kalloc(real_len)) == NULL) { + return -ENOMEM; + } + + memset(buf, 0, real_len); + memcpy(buf, p, len); + error = ops->write(dp, buf, off, real_len); + kfree(buf); + return error; } ssize_t dms_read(struct dms_disk *dp, void *p, off_t off, size_t len) { + void *buf; struct dms_ops *ops; + size_t real_len; + int error; if (dp == NULL || p == NULL) { return -EINVAL; @@ -134,5 +150,20 @@ dms_read(struct dms_disk *dp, void *p, off_t off, size_t len) return -ENOTSUP; } - return ops->read(dp, p, off, len); + /* Allocate a real sized buffer */ + real_len = ALIGN_UP(len, dp->bsize); + if ((buf = kalloc(real_len)) == NULL) { + return -ENOMEM; + } + + memset(buf, 0, real_len); + error = ops->read(dp, buf, off, real_len); + if (error < 0) { + kfree(buf); + return error; + } + + memcpy(p, buf, len); + kfree(buf); + return 0; } diff --git a/src/sys/include/dms/dms.h b/src/sys/include/dms/dms.h index fca40b4..06e78ac 100644 --- a/src/sys/include/dms/dms.h +++ b/src/sys/include/dms/dms.h @@ -74,14 +74,19 @@ struct dms_ops { * * @name: Name of this device * @ops: Operations that can be performed - * @data: Driver specific data + * @data: Driver specific data [set by driver] + * @bsize: Disk block size [set by driver] * @id: ID of the disk * @link: Internal queue link + * + * XXX: The `data' and `bsize' fields must be set by + * the driver */ struct dms_disk { char name[DISKNAME_MAX]; struct dms_ops *ops; void *data; + uint16_t bsize; disk_id_t id; TAILQ_ENTRY(dms_disk) link; }; diff --git a/src/sys/io/ic/ahci.c b/src/sys/io/ic/ahci.c index 9aa19b4..48560a8 100644 --- a/src/sys/io/ic/ahci.c +++ b/src/sys/io/ic/ahci.c @@ -236,6 +236,7 @@ ahci_register(struct ata_identity *identity, struct ahci_port *port) return error; } + dp->bsize = port->bsize; dp->data = (void *)port; return 0; } -- cgit v1.2.3