syscall: add lots of syscalls
This commit is contained in:
@@ -1,13 +1,165 @@
|
||||
#include <mango/handle.h>
|
||||
#include <mango/printk.h>
|
||||
#include <mango/vm-region.h>
|
||||
#include <kernel/handle.h>
|
||||
#include <kernel/printk.h>
|
||||
#include <kernel/sched.h>
|
||||
#include <kernel/syscall.h>
|
||||
#include <kernel/vm-object.h>
|
||||
#include <kernel/vm-region.h>
|
||||
|
||||
kern_status_t sys_vm_object_create(
|
||||
const char *name,
|
||||
size_t len,
|
||||
enum vm_prot prot,
|
||||
size_t name_len,
|
||||
size_t data_len,
|
||||
vm_prot_t prot,
|
||||
kern_handle_t *out_handle)
|
||||
{
|
||||
printk("sys_vm_object_create()");
|
||||
return KERN_UNIMPLEMENTED;
|
||||
struct task *self = current_task();
|
||||
|
||||
if ((name || name_len) && !validate_access_r(self, name, name_len)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
if (!validate_access_w(self, out_handle, sizeof *out_handle)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
struct vm_object *obj
|
||||
= vm_object_create(name, name_len, data_len, prot);
|
||||
if (!obj) {
|
||||
return KERN_NO_MEMORY;
|
||||
}
|
||||
|
||||
kern_status_t status
|
||||
= task_open_handle(self, &obj->vo_base, 0, out_handle);
|
||||
if (status != KERN_OK) {
|
||||
object_unref(&obj->vo_base);
|
||||
return status;
|
||||
}
|
||||
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
kern_status_t sys_vm_object_read(
|
||||
kern_handle_t object,
|
||||
void *dst,
|
||||
off_t offset,
|
||||
size_t count,
|
||||
size_t *nr_read)
|
||||
{
|
||||
struct task *self = current_task();
|
||||
|
||||
if (!validate_access_w(self, dst, count)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
if (nr_read && !validate_access_w(self, nr_read, sizeof *nr_read)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
struct object *obj = NULL;
|
||||
handle_flags_t flags = 0;
|
||||
kern_status_t status = task_resolve_handle(self, object, &obj, &flags);
|
||||
if (status != KERN_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
struct vm_object *vmo = vm_object_cast(obj);
|
||||
if (!vmo) {
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return vm_object_read(vmo, dst, offset, count, nr_read);
|
||||
}
|
||||
|
||||
kern_status_t sys_vm_object_write(
|
||||
kern_handle_t object,
|
||||
const void *src,
|
||||
off_t offset,
|
||||
size_t count,
|
||||
size_t *nr_written)
|
||||
{
|
||||
struct task *self = current_task();
|
||||
|
||||
if (!validate_access_r(self, src, count)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
if (nr_written
|
||||
&& !validate_access_w(self, nr_written, sizeof *nr_written)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
struct object *obj = NULL;
|
||||
handle_flags_t flags = 0;
|
||||
kern_status_t status = task_resolve_handle(self, object, &obj, &flags);
|
||||
if (status != KERN_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
struct vm_object *vmo = vm_object_cast(obj);
|
||||
if (!vmo) {
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return vm_object_write(vmo, src, offset, count, nr_written);
|
||||
}
|
||||
|
||||
kern_status_t sys_vm_object_copy(
|
||||
kern_handle_t dst,
|
||||
off_t dst_offset,
|
||||
kern_handle_t src,
|
||||
off_t src_offset,
|
||||
size_t count,
|
||||
size_t *nr_copied)
|
||||
{
|
||||
struct task *self = current_task();
|
||||
|
||||
if (nr_copied
|
||||
&& !validate_access_w(self, nr_copied, sizeof *nr_copied)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
unsigned long flags;
|
||||
task_lock_irqsave(self, &flags);
|
||||
|
||||
kern_status_t status;
|
||||
struct object *dst_obj = NULL, *src_obj = NULL;
|
||||
handle_flags_t dst_flags = 0, src_flags = 0;
|
||||
|
||||
status = task_resolve_handle(self, dst, &dst_obj, &dst_flags);
|
||||
if (status != KERN_OK) {
|
||||
task_unlock_irqrestore(self, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = task_resolve_handle(self, src, &src_obj, &src_flags);
|
||||
if (status != KERN_OK) {
|
||||
task_unlock_irqrestore(self, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
object_ref(src_obj);
|
||||
object_ref(dst_obj);
|
||||
|
||||
task_unlock_irqrestore(self, flags);
|
||||
|
||||
struct vm_object *dst_vmo = vm_object_cast(dst_obj);
|
||||
struct vm_object *src_vmo = vm_object_cast(src_obj);
|
||||
if (!dst_vmo || !src_vmo) {
|
||||
object_unref(src_obj);
|
||||
object_unref(dst_obj);
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
status = vm_object_copy(
|
||||
dst_vmo,
|
||||
dst_offset,
|
||||
src_vmo,
|
||||
src_offset,
|
||||
count,
|
||||
nr_copied);
|
||||
|
||||
object_unref(src_obj);
|
||||
object_unref(dst_obj);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user