diff options
author | Ian Moffett <ian@osmora.org> | 2025-10-14 20:23:19 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-10-14 20:23:19 -0400 |
commit | aaa076ff1d68545085fb85ee24d5410b60a123bd (patch) | |
tree | 98b1642cd6aae676b15318e376661e7b343196f9 /src/sys | |
parent | 6a0c08f51e59328d9a158bb521b1f1cf57663962 (diff) |
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 <ian@osmora.org>
Diffstat (limited to 'src/sys')
-rw-r--r-- | src/sys/dms/dms_subr.c | 35 | ||||
-rw-r--r-- | src/sys/include/dms/dms.h | 7 | ||||
-rw-r--r-- | src/sys/io/ic/ahci.c | 1 |
3 files changed, 40 insertions, 3 deletions
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 <sys/types.h> #include <sys/errno.h> #include <sys/queue.h> +#include <sys/param.h> #include <os/kalloc.h> #include <dms/dms.h> #include <string.h> @@ -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; } |