diff --git a/kernel/include/fs/FileDescriptor.h b/kernel/include/fs/FileDescriptor.h index f5b83c23..9e34df83 100644 --- a/kernel/include/fs/FileDescriptor.h +++ b/kernel/include/fs/FileDescriptor.h @@ -32,6 +32,9 @@ struct Descriptor ssize_t read(size_t size, char* buffer); ssize_t write(size_t size, const char* buffer); + ssize_t user_read(size_t size, char* buffer); + ssize_t user_write(size_t size, const char* buffer); + uintptr_t mmap(uintptr_t addr, size_t size, int prot, off_t offset); long ioctl(int cmd, uintptr_t arg); diff --git a/kernel/src/fs/FileDescriptor.cpp b/kernel/src/fs/FileDescriptor.cpp index 96266068..26dee2bc 100644 --- a/kernel/src/fs/FileDescriptor.cpp +++ b/kernel/src/fs/FileDescriptor.cpp @@ -1,5 +1,7 @@ #include "fs/FileDescriptor.h" #include "std/errno.h" +#include "std/stdlib.h" +#include "sys/UserMemory.h" Descriptor::Descriptor() : m_is_open(false) { @@ -37,17 +39,39 @@ ssize_t Descriptor::write(size_t size, const char* buffer) return result; } +ssize_t Descriptor::user_read(size_t size, char* buffer) +{ + char* buf = (char*)kmalloc(size); + if (!buf) return -ENOMEM; + ssize_t result = read(size, buf); + if (!copy_to_user(buffer, buf, size)) result = -EFAULT; + kfree(buf); + return result; +} + +ssize_t Descriptor::user_write(size_t size, const char* buffer) +{ + char* buf = (char*)kmalloc(size); + if (!buf) return -ENOMEM; + ssize_t result; + if (!copy_from_user(buffer, buf, size)) result = -EFAULT; + else + result = write(size, buf); + kfree(buf); + return result; +} + #define MAP_FAIL(errno) 0xffffffffffffff00 | (unsigned char)(errno) uintptr_t Descriptor::mmap(uintptr_t addr, size_t size, int prot, off_t offset) { - if(!m_node->mmap_func) return MAP_FAIL(ENOTSUP); + if (!m_node->mmap_func) return MAP_FAIL(ENOTSUP); return m_node->mmap_func(m_node, addr, size, prot, offset); } long Descriptor::ioctl(int cmd, uintptr_t arg) { - if(!m_node->ioctl_func) return MAP_FAIL(ENOTSUP); + if (!m_node->ioctl_func) return MAP_FAIL(ENOTSUP); return m_node->ioctl_func(m_node, cmd, arg); } diff --git a/kernel/src/sys/stdio.cpp b/kernel/src/sys/stdio.cpp index d4e85bfb..adc8206b 100644 --- a/kernel/src/sys/stdio.cpp +++ b/kernel/src/sys/stdio.cpp @@ -155,9 +155,7 @@ void sys_write(Context* context, int fd, size_t size, const char* addr) context->rax = -EBADF; return; } - ssize_t result = file->write( - size, (const char*)VMM::get_physical((uint64_t)addr)); // FIXME: Handle buffers bigger than one page, which may - // not be contiguous in physical memory. + ssize_t result = file->user_write(size, addr); context->rax = (size_t)result; return; } @@ -298,13 +296,11 @@ void sys_read(Context* context, int fd, size_t size, char* buffer) current_task->state = current_task->Blocking; current_task->block_reason = BlockReason::Reading; current_task->blocking_read_info.fd = fd; - current_task->blocking_read_info.buf = (char*)VMM::get_physical((uint64_t)buffer); // FIXME: Handle errors. + current_task->blocking_read_info.buf = buffer; current_task->blocking_read_info.size = size; return Scheduler::task_yield(context); } - ssize_t result = - file->read(size, (char*)VMM::get_physical((uint64_t)buffer)); // FIXME: Handle big buffers which may - // not be across continuous physical pages. + ssize_t result = file->user_read(size, buffer); context->rax = (size_t)result; return; } diff --git a/kernel/src/thread/Task.cpp b/kernel/src/thread/Task.cpp index 29b11ced..b241d6f5 100644 --- a/kernel/src/thread/Task.cpp +++ b/kernel/src/thread/Task.cpp @@ -74,7 +74,7 @@ bool Task::has_died() void Task::resume_read() { - regs.rax = files[blocking_read_info.fd].read(blocking_read_info.size, blocking_read_info.buf); + regs.rax = files[blocking_read_info.fd].user_read(blocking_read_info.size, blocking_read_info.buf); } bool Task::is_read_still_blocking() @@ -86,7 +86,7 @@ void Task::resume() { VMM::switch_back_to_kernel_address_space(); VMM::apply_address_space(); - VMM::switch_to_previous_user_address_space(); + VMM::switch_to_user_address_space(address_space); switch (block_reason) { case BlockReason::None: return;