diff --git a/kernel-src/arch/x86-64/e9.c b/kernel-src/arch/x86-64/e9.c index 7c01f239..4043b0d0 100644 --- a/kernel-src/arch/x86-64/e9.c +++ b/kernel-src/arch/x86-64/e9.c @@ -18,12 +18,10 @@ void arch_e9_puts(char *c) { } #ifdef X86_64_ENABLE_E9 -static int devwrite(int minor, void *bufferp, size_t count, uintmax_t offset, int flags, size_t *wcount) { - uint8_t *buffer = bufferp; - +static int devwrite(int minor, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, int flags, size_t *wcount) { for (uintmax_t i = 0; i < count; ++i) { char c; - int error = USERCOPY_POSSIBLY_FROM_USER(&c, &buffer[i], 1); + int error = iovec_iterator_copy_to_buffer(iovec_iterator, &c, 1); if (error) return error; diff --git a/kernel-src/fs/devfs.c b/kernel-src/fs/devfs.c index 2d0818d0..f63f0a4e 100644 --- a/kernel-src/fs/devfs.c +++ b/kernel-src/fs/devfs.c @@ -85,7 +85,16 @@ int devfs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int f if (devnode->devops->read == NULL) return ENODEV; - return devnode->devops->read(devnode->attr.rdevminor, buffer, size, offset, flags, readc); + // TODO remove this once the whole fs uses iovec + iovec_iterator_t iovec_iterator; + iovec_t iovec = { + .addr = buffer, + .len = size + }; + + iovec_iterator_init(&iovec_iterator, &iovec, 1); + + return devnode->devops->read(devnode->attr.rdevminor, &iovec_iterator, size, offset, flags, readc); } int devfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) { @@ -102,7 +111,16 @@ int devfs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int if (devnode->devops->write == NULL) return ENODEV; - return devnode->devops->write(devnode->attr.rdevminor, buffer, size, offset, flags, writec); + // TODO remove this once the whole fs uses iovec + iovec_iterator_t iovec_iterator; + iovec_t iovec = { + .addr = buffer, + .len = size + }; + + iovec_iterator_init(&iovec_iterator, &iovec, 1); + + return devnode->devops->write(devnode->attr.rdevminor, &iovec_iterator, size, offset, flags, writec); } int devfs_lookup(vnode_t *node, char *name, vnode_t **result, cred_t *cred) { diff --git a/kernel-src/include/kernel/block.h b/kernel-src/include/kernel/block.h index 82324497..891a6e1a 100644 --- a/kernel-src/include/kernel/block.h +++ b/kernel-src/include/kernel/block.h @@ -3,6 +3,7 @@ #include #include +#include #define BLOCK_TYPE_DISK 0 #define BLOCK_TYPE_PART 1 @@ -15,8 +16,8 @@ typedef struct { uintmax_t lbaoffset; size_t blockcapacity; size_t blocksize; - int (*write)(void *private, void *buffer, uintmax_t lba, size_t count); - int (*read)(void *private, void *buffer, uintmax_t lba, size_t count); + int (*write)(void *private, iovec_iterator_t *buffer, uintmax_t lba, size_t count); + int (*read)(void *private, iovec_iterator_t *buffer, uintmax_t lba, size_t count); } blockdesc_t; void block_register(blockdesc_t *desc, char *name); diff --git a/kernel-src/include/kernel/devfs.h b/kernel-src/include/kernel/devfs.h index 90180d83..5400d251 100644 --- a/kernel-src/include/kernel/devfs.h +++ b/kernel-src/include/kernel/devfs.h @@ -5,6 +5,7 @@ #include #include +#include #define DEV_MAJOR_NULL 1 #define DEV_MAJOR_FULL 2 @@ -23,8 +24,8 @@ typedef struct { int (*open)(int minor, vnode_t **vnode, int flags); int (*close)(int minor, int flags); - int (*read)(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc); - int (*write)(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec); + int (*read)(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc); + int (*write)(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec); int (*poll)(int minor, polldata_t *data, int events); int (*mmap)(int minor, void *addr, uintmax_t offset, int flags); int (*munmap)(int minor, void *addr, uintmax_t offset, int flags); diff --git a/kernel-src/io/acpi/dev.c b/kernel-src/io/acpi/dev.c index 1702a20a..d83edb68 100644 --- a/kernel-src/io/acpi/dev.c +++ b/kernel-src/io/acpi/dev.c @@ -28,7 +28,7 @@ static int internalpoll(polldata_t *data, int events) { return revents; } -static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) { +static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) { *readc = 0; if (size < 1) @@ -62,7 +62,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag // this abuses a behavior of how the ringbuffer works to not need a lock for reading // (as it would need interrupts to be off) - *readc = ringbuffer_read(&ringbuffer, buffer, size); + *readc = iovec_iterator_read_from_ringbuffer(iovec_iterator, &ringbuffer, size); if (*readc == RINGBUFFER_USER_COPY_FAILED) error = EFAULT; @@ -73,14 +73,18 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag return error; } -static int write(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec) { +static int write(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec) { if (size < 1) { *writec = 0; return 0; } - char *c = buffer; - switch (*c) { + char c; + int error = iovec_iterator_copy_to_buffer(iovec_iterator, &c, 1); + if (error) + return error; + + switch (c) { case 'p': acpi_poweroff(); break; @@ -89,7 +93,7 @@ static int write(int minor, void *buffer, size_t size, uintmax_t offset, int fla break; } - return EIO; + return error; } static int poll(int minor, polldata_t *data, int events) { diff --git a/kernel-src/io/block/block.c b/kernel-src/io/block/block.c index a22416ed..18522308 100644 --- a/kernel-src/io/block/block.c +++ b/kernel-src/io/block/block.c @@ -8,8 +8,8 @@ #include #include -#define DISK_READ(desc, buf, lba, size) (desc)->read(desc->private, buf, lba, size) -#define DISK_WRITE(desc, buf, lba, size) (desc)->write(desc->private, buf, lba, size) +#define DISK_READ(desc, it, lba, size) (desc)->read(desc->private, it, lba, size) +#define DISK_WRITE(desc, it, lba, size) (desc)->write(desc->private, it, lba, size) typedef struct { char signature[8]; @@ -72,10 +72,34 @@ static void bytestolba(blockdesc_t *desc, uintmax_t offset, size_t size, uintmax *lbacount = toplba - *lbaoffset; } +static inline int disk_read_direct(blockdesc_t *desc, void *buffer, size_t lba_offset, size_t block_count) { + iovec_t iovec = { + .addr = buffer, + .len = block_count * desc->blocksize + }; + + iovec_iterator_t iovec_iterator; + iovec_iterator_init(&iovec_iterator, &iovec, 1); + + return DISK_READ(desc, &iovec_iterator, lba_offset, block_count); +} + +static inline int disk_write_direct(blockdesc_t *desc, void *buffer, size_t lba_offset, size_t block_count) { + iovec_t iovec = { + .addr = buffer, + .len = block_count * desc->blocksize + }; + + iovec_iterator_t iovec_iterator; + iovec_iterator_init(&iovec_iterator, &iovec, 1); + + return DISK_WRITE(desc, &iovec_iterator, lba_offset, block_count); +} + #define MAP_FLAGS (ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC) // this is only really called by the page cache VOP_GETPAGE and VOP_PUTPAGE functions, so we can make a few assumptions -static int rwblock(int minor, void *buffer, size_t size, uintmax_t offset, int flags, bool write, size_t *done) { +static int rwblock(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, bool write, size_t *done) { blockdesc_t *desc = getdesc(minor); if (desc == NULL) return ENODEV; @@ -104,28 +128,27 @@ static int rwblock(int minor, void *buffer, size_t size, uintmax_t offset, int f int error = 0; if (write) { - error = DISK_WRITE(desc, buffer, lbaoffset + desc->lbaoffset, lbacount); + error = DISK_WRITE(desc, iovec_iterator, lbaoffset + desc->lbaoffset, lbacount); if (error) goto cleanup; } else { - error = DISK_READ(desc, buffer, lbaoffset + desc->lbaoffset, lbacount); + error = DISK_READ(desc, iovec_iterator, lbaoffset + desc->lbaoffset, lbacount); if (error) goto cleanup; } - *done = size; cleanup: return error; } -static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) { - return rwblock(minor, buffer, size, offset, flags, false, readc); +static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) { + return rwblock(minor, iovec_iterator, size, offset, flags, false, readc); } -static int write(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec) { - return rwblock(minor, buffer, size, offset, flags, true, writec); +static int write(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec) { + return rwblock(minor, iovec_iterator, size, offset, flags, true, writec); } static int ioctl(int minor, unsigned long request, void *arg, int *result, cred_t *cred) { @@ -177,7 +200,7 @@ static int detectpart(blockdesc_t *desc) { // read first two sectors void *sects = vmm_map(NULL, desc->blocksize * 2, VMM_FLAGS_ALLOCATE, MAP_FLAGS, NULL); __assert(sects); - __assert(DISK_READ(desc, sects, 0, 2) == 0); + __assert(disk_read_direct(desc, sects, 0, 2) == 0); void *lba0 = sects; void *lba1 = (void *)((uintptr_t)lba0 + desc->blocksize); @@ -199,7 +222,7 @@ static void dogpt(blockdesc_t *desc, char *name) { // get header void *lba1 = vmm_map(NULL, desc->blocksize, VMM_FLAGS_ALLOCATE, MAP_FLAGS, NULL); __assert(lba1); - __assert(DISK_READ(desc, lba1, 1, 1) == 0); + __assert(disk_read_direct(desc, lba1, 1, 1) == 0); gptheader_t *header = lba1; // get partition table @@ -207,7 +230,7 @@ static void dogpt(blockdesc_t *desc, char *name) { size_t tablelbasize = ROUND_UP(tablebytesize, desc->blocksize) / desc->blocksize; void *tablebuffer = vmm_map(NULL, tablelbasize * desc->blocksize, VMM_FLAGS_ALLOCATE, MAP_FLAGS, NULL); __assert(tablebuffer); - __assert(DISK_READ(desc, tablebuffer, header->entryarraylbastart, tablelbasize) == 0); + __assert(disk_read_direct(desc, tablebuffer, header->entryarraylbastart, tablelbasize) == 0); // name + 'p' + 3 digits (max gpt partition count is 128) + '\0' size_t namebuflen = strlen(name) + 5; @@ -241,7 +264,7 @@ static void dombr(blockdesc_t *desc, char *name) { // get entries void *lba0 = vmm_map(NULL, desc->blocksize, VMM_FLAGS_ALLOCATE, MAP_FLAGS, NULL); __assert(lba0); - __assert(DISK_READ(desc, lba0, 0, 1) == 0); + __assert(disk_read_direct(desc, lba0, 0, 1) == 0); mbrentry_t *mbrents = (mbrentry_t *)((uintptr_t)lba0 + MBR_ENTRIES_OFFSET); // name + 'p' + single digit (max mbr partition count is 4) + '\0' diff --git a/kernel-src/io/block/nvme.c b/kernel-src/io/block/nvme.c index 704e0348..86c72083 100644 --- a/kernel-src/io/block/nvme.c +++ b/kernel-src/io/block/nvme.c @@ -503,22 +503,35 @@ static int iowrite(nvmenamespace_t *namespace, uint64_t prp[2], uint64_t lba, ui #define PAGES_FLAGS (ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC) -static int rwblocks(nvmenamespace_t *namespace, void *buffer, uintmax_t lba, size_t count, bool write) { +static int rwblocks(nvmenamespace_t *namespace, iovec_iterator_t *iovec_iterator, uintmax_t lba, size_t count, bool write) { __assert(namespace->blocksize <= PAGE_SIZE); int err = 0; uint64_t prp[2] = {0, 0}; - __assert(((uintptr_t)buffer % namespace->blocksize) == 0); - uintmax_t pageoffset = (uintptr_t)buffer - ROUND_DOWN((uintptr_t)buffer, PAGE_SIZE); int done = 0; while (done < count) { - size_t docount = (done == 0) ? (PAGE_SIZE - pageoffset) / namespace->blocksize : PAGE_SIZE / namespace->blocksize; + void *page; + size_t page_offset, page_remaining; + // XXX this takes an entire page from the iovec, though it may not be used fully. + // ATM this does not really matter but it could at one point in the future + err = iovec_iterator_next_page(iovec_iterator, &page_offset, &page_remaining, &page); + + if (err) + break; + + // check that there is enough space to complete the write of this page + __assert(page); + __assert(page_remaining >= min((count - done) * namespace->blocksize, PAGE_SIZE)); + + // and that the space is aligned to the block size + __assert((page_remaining % namespace->blocksize) == 0); + + size_t docount = page_remaining / namespace->blocksize; docount = min(docount, count - done); - prp[0] = (uint64_t)vmm_getphysical((void *)((uintptr_t)buffer + done * namespace->blocksize), true); - __assert(prp[0]); + prp[0] = (uint64_t)page + page_offset; err = write ? iowrite(namespace, prp, lba + done, docount) : ioread(namespace, prp, lba + done, docount); @@ -533,12 +546,12 @@ static int rwblocks(nvmenamespace_t *namespace, void *buffer, uintmax_t lba, siz return err; } -static int read(void *private, void *buffer, uintmax_t lba, size_t count) { - return rwblocks(private, buffer, lba, count, false); +static int read(void *private, iovec_iterator_t *iovec_iterator, uintmax_t lba, size_t count) { + return rwblocks(private, iovec_iterator, lba, count, false); } -static int write(void *private, void *buffer, uintmax_t lba, size_t count) { - return rwblocks(private, buffer, lba, count, true); +static int write(void *private, iovec_iterator_t *iovec_iterator, uintmax_t lba, size_t count) { + return rwblocks(private, iovec_iterator, lba, count, true); } static void initnamespace(nvmecontroller_t *controller, int id) { diff --git a/kernel-src/io/block/vioblk.c b/kernel-src/io/block/vioblk.c index ba8dbf84..aa8502d7 100644 --- a/kernel-src/io/block/vioblk.c +++ b/kernel-src/io/block/vioblk.c @@ -99,7 +99,7 @@ static void vioblk_enqueue(vioblkdev_t *blkdev, requestheader_t *headerphys, voi interrupt_set(intstatus); } -static int vioblk_rw(vioblkdev_t *blkdev, void *buffer, uintmax_t lba, size_t count, bool write) { +static int vioblk_rw(vioblkdev_t *blkdev, iovec_iterator_t *iovec_iterator, uintmax_t lba, size_t count, bool write) { void *physpage = pmm_allocpage(PMM_SECTION_DEFAULT); if (physpage == NULL) return ENOMEM; @@ -112,21 +112,28 @@ static int vioblk_rw(vioblkdev_t *blkdev, void *buffer, uintmax_t lba, size_t co headerhhdm->type = write ? HEADER_TYPE_WRITE : HEADER_TYPE_READ; - __assert(((uintptr_t)buffer % 512) == 0); - uintmax_t pageoffset = (uintptr_t)buffer - ROUND_DOWN((uintptr_t)buffer, PAGE_SIZE); - int done = 0; while (done < count) { + void *page; + size_t page_offset, page_remaining; + err = iovec_iterator_next_page(iovec_iterator, &page_offset, &page_remaining, &page); + if (err) + break; + + // check that there is enough space to complete the write of this page + __assert(page); + __assert(page_remaining >= min((count - done) * 512, PAGE_SIZE)); + + // and that the space is aligned to the block size + __assert((page_remaining % 512) == 0); + headerhhdm->sector = lba + done; - size_t docount = (done == 0) ? (PAGE_SIZE - pageoffset) / 512 : PAGE_SIZE / 512; + size_t docount = page_remaining / 512; docount = min(docount, count - done); - void *bufferphys = vmm_getphysical((void *)((uintptr_t)buffer + done * 512), true); - __assert(bufferphys); + vioblk_enqueue(blkdev, header, (void *)((uintptr_t)page + page_offset), PAGE_SIZE, status, write); - vioblk_enqueue(blkdev, header, bufferphys, docount * 512, status, write); - - pmm_release(bufferphys); + pmm_release(page); if (*statushhdm) { err = EIO; @@ -140,12 +147,12 @@ static int vioblk_rw(vioblkdev_t *blkdev, void *buffer, uintmax_t lba, size_t co return err; } -static int vioblk_write(void *private, void *buffer, uintmax_t lba, size_t count) { - return vioblk_rw(private, buffer, lba, count, true); +static int vioblk_write(void *private, iovec_iterator_t *iovec_iterator, uintmax_t lba, size_t count) { + return vioblk_rw(private, iovec_iterator, lba, count, true); } -static int vioblk_read(void *private, void *buffer, uintmax_t lba, size_t count) { - return vioblk_rw(private, buffer, lba, count, false); +static int vioblk_read(void *private, iovec_iterator_t *iovec_iterator, uintmax_t lba, size_t count) { + return vioblk_rw(private, iovec_iterator, lba, count, false); } int vioblk_newdevice(viodevice_t *viodevice) { diff --git a/kernel-src/io/fb.c b/kernel-src/io/fb.c index f149a15d..0cdb018d 100644 --- a/kernel-src/io/fb.c +++ b/kernel-src/io/fb.c @@ -86,7 +86,7 @@ static int maxseek(int minor, size_t *max) { return 0; } -static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) { +static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) { if (minor >= count) return ENODEV; @@ -99,7 +99,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag if(size + offset > end) size = end - offset; - int error = USERCOPY_POSSIBLY_TO_USER(buffer, (void *)((uintptr_t)fbs[minor]->address + offset), size); + int error = iovec_iterator_copy_from_buffer(iovec_iterator, (void *)((uintptr_t)fbs[minor]->address + offset), size); if (error) return error; @@ -108,7 +108,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag return 0; } -static int write(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec) { +static int write(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec) { if (minor >= count) return ENODEV; @@ -121,7 +121,7 @@ static int write(int minor, void *buffer, size_t size, uintmax_t offset, int fla if(size + offset > end) size = end - offset; - int error = USERCOPY_POSSIBLY_FROM_USER((void *)((uintptr_t)fbs[minor]->address + offset), buffer, size); + int error = iovec_iterator_copy_to_buffer(iovec_iterator, (void *)((uintptr_t)fbs[minor]->address + offset), size); if (error) return error; diff --git a/kernel-src/io/keyboard.c b/kernel-src/io/keyboard.c index aae9333f..a387b3cf 100644 --- a/kernel-src/io/keyboard.c +++ b/kernel-src/io/keyboard.c @@ -154,7 +154,7 @@ static keyboard_t* getkb(int kb) { return kbp; } -static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) { +static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) { keyboard_t *kb = getkb(minor); if (kb == NULL) return ENODEV; @@ -165,7 +165,6 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag return 0; for (int i = 0; i < count; ++i) { - kbpacket_t *buff = (kbpacket_t *)((uintptr_t)buffer + i * sizeof(kbpacket_t)); kbpacket_t packet; bool ok = keyboard_get(kb, &packet); @@ -175,7 +174,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag if (error) return error; - error = USERCOPY_POSSIBLY_TO_USER(buff, &packet, sizeof(kbpacket_t)); + error = iovec_iterator_copy_from_buffer(iovec_iterator, &packet, sizeof(kbpacket_t)); *readc += error ? 0 : sizeof(kbpacket_t); return error; @@ -184,7 +183,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag break; } - int error = USERCOPY_POSSIBLY_TO_USER(buff, &packet, sizeof(kbpacket_t)); + int error = iovec_iterator_copy_from_buffer(iovec_iterator, &packet, sizeof(kbpacket_t)); if (error) return error; diff --git a/kernel-src/io/mouse.c b/kernel-src/io/mouse.c index 61abeb2b..774da4ae 100644 --- a/kernel-src/io/mouse.c +++ b/kernel-src/io/mouse.c @@ -67,7 +67,7 @@ static int internalpoll(mouse_t *mouse, polldata_t *data, int events) { return revents; } -static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) { +static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) { mouse_t *mouse = getmouse(minor); if (mouse == NULL) return ENODEV; @@ -121,7 +121,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag goto leave; } - *readc = ringbuffer_read(&mouse->packetbuffer, buffer, sizeof(mousepacket_t) * packetcount); + *readc = iovec_iterator_read_from_ringbuffer(iovec_iterator, &mouse->packetbuffer, sizeof(mousepacket_t) * packetcount); if (*readc == RINGBUFFER_USER_COPY_FAILED) { error = EFAULT; goto leave; diff --git a/kernel-src/io/pseudodevices.c b/kernel-src/io/pseudodevices.c index 36526ecc..0c16415d 100644 --- a/kernel-src/io/pseudodevices.c +++ b/kernel-src/io/pseudodevices.c @@ -4,22 +4,21 @@ #include #include -static int null_write(int minor, void *buffer, size_t count, uintmax_t offset, int flags, size_t *wcount) { +static int null_write(int minor, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, int flags, size_t *wcount) { *wcount = count; return 0; } -static int full_write(int minor, void *buffer, size_t count, uintmax_t offset, int flags, size_t *wcount) { +static int full_write(int minor, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, int flags, size_t *wcount) { return ENOSPC; } -static int zero_read(int minor, void *buffer, size_t count, uintmax_t offset, int flags, size_t *rcount) { +static int zero_read(int minor, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, int flags, size_t *rcount) { *rcount = count; - memset(buffer, 0, count); - return 0; + return iovec_iterator_memset(iovec_iterator, 0, count); } -static int null_read(int minor, void *buffer, size_t count, uintmax_t offset, int flags, size_t *rcount) { +static int null_read(int minor, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, int flags, size_t *rcount) { *rcount = 0; return 0; } @@ -36,10 +35,13 @@ static uint8_t getrand8() { return current & 0xff; } -static int urandom_read(int minor, void *_buffer, size_t count, uintmax_t offset, int flags, size_t *rcount) { - uint8_t *buffer = _buffer; - for (int i = 0; i < count; ++i) - buffer[i] = getrand8(); +static int urandom_read(int minor, iovec_iterator_t *iovec_iterator, size_t count, uintmax_t offset, int flags, size_t *rcount) { + for (int i = 0; i < count; ++i) { + uint8_t byte = getrand8(); + int error = iovec_iterator_copy_from_buffer(iovec_iterator, &byte, sizeof(byte)); + if (error) + return error; + } *rcount = count; return 0; diff --git a/kernel-src/io/pty.c b/kernel-src/io/pty.c index 9402dfca..987856f2 100644 --- a/kernel-src/io/pty.c +++ b/kernel-src/io/pty.c @@ -127,7 +127,7 @@ static int internalpoll(pty_t *pty, polldata_t *data, int events) { return revents; } -static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) { +static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) { pty_t *pty = ptyget(minor); if (pty == NULL) return ENODEV; @@ -139,27 +139,18 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag if (e) return e; - bool intstatus = interrupt_set(false); - spinlock_acquire(&pty->lock); - int revents = internalpoll(pty, &desc.data[0], POLLIN); if (revents) { - *readc = ringbuffer_read(&pty->ringbuffer, buffer, size); + *readc = iovec_iterator_read_from_ringbuffer(iovec_iterator, &pty->ringbuffer, size); if (*readc == RINGBUFFER_USER_COPY_FAILED) e = EFAULT; - spinlock_release(&pty->lock); - interrupt_set(intstatus); - poll_leave(&desc); poll_destroydesc(&desc); break; } - spinlock_release(&pty->lock); - interrupt_set(intstatus); - if (flags & V_FFLAGS_NONBLOCKING) { poll_leave(&desc); poll_destroydesc(&desc); @@ -210,17 +201,14 @@ static int ioctl(int minor, unsigned long request, void *_arg, int *result, cred return 0; } -static int write(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec) { +static int write(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec) { pty_t *pty = ptyget(minor); if (pty == NULL) return ENODEV; - char *str = buffer; - for (int i = 0; i < size; ++i) { - // bruh char c; - int error = USERCOPY_POSSIBLY_FROM_USER(&c, &str[i], sizeof(char)); + int error = iovec_iterator_copy_to_buffer(iovec_iterator, &c, sizeof(char)); if (error) return error; diff --git a/kernel-src/io/tty.c b/kernel-src/io/tty.c index 7ca3fd8e..01825c64 100644 --- a/kernel-src/io/tty.c +++ b/kernel-src/io/tty.c @@ -170,7 +170,7 @@ static int internalpoll(tty_t *tty, polldata_t *data, int events) { return revents; } -static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) { +static int read(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *readc) { tty_t *tty = ttyget(minor); if (tty == NULL) return ENODEV; @@ -194,7 +194,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag // read data and if theres nothing just return if (min == 0 && time == 0) { MUTEX_ACQUIRE(&tty->readmutex, false); - *readc = ringbuffer_read(&tty->readbuffer, buffer, size); + *readc = iovec_iterator_read_from_ringbuffer(iovec_iterator, &tty->readbuffer, size); int error = 0; if (*readc == RINGBUFFER_USER_COPY_FAILED) @@ -227,7 +227,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag // theres data to read MUTEX_ACQUIRE(&tty->readmutex, false); - size_t actuallyread = ringbuffer_read(&tty->readbuffer, (void *)((uintptr_t)buffer + readcount), spaceleft); + size_t actuallyread = iovec_iterator_read_from_ringbuffer(iovec_iterator, &tty->readbuffer, spaceleft); MUTEX_RELEASE(&tty->readmutex); @@ -274,20 +274,18 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag return error; } -static int write(int minor, void *_buffer, size_t size, uintmax_t offset, int flags, size_t *writec) { +static int write(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *writec) { tty_t *tty = ttyget(minor); if (tty == NULL) return ENODEV; // TODO background process stuff etc - char *buffer = _buffer; - *writec = size; for (int i = 0; i < size; ++i) { // bruh char c; - int error = USERCOPY_POSSIBLY_FROM_USER(&c, &buffer[i], sizeof(char)); + int error = iovec_iterator_copy_to_buffer(iovec_iterator, &c, sizeof(char)); if (error) return error;