diff --git a/definitions/syscalls.def b/definitions/syscalls.def index e7442a1..ccc40ed 100644 --- a/definitions/syscalls.def +++ b/definitions/syscalls.def @@ -34,4 +34,12 @@ interface syscalls [syscall] { function handle_list { param handles object kobject [list inout optional] # A list of handles to be filled } + + # Create a clone of an existing handle, possibly with + # some capabilities masked out. + function handle_clone { + param handle object kobject [handle] # The handle to clone + param clone object kobject [out] # The new handle + param mask uint32 # The capability bitmask + } } diff --git a/scripts/definitions/types/object.py b/scripts/definitions/types/object.py index b0061ba..47ae0cf 100644 --- a/scripts/definitions/types/object.py +++ b/scripts/definitions/types/object.py @@ -10,8 +10,7 @@ class Object: self.super = typename self.methods = children self.cname = cname or name - - self.caps = set(caps) + self.caps = caps from . import ObjectRef self.__ref = ObjectRef(name) diff --git a/src/kernel/objects/handle.h b/src/kernel/objects/handle.h index 2fa4995..f77941d 100644 --- a/src/kernel/objects/handle.h +++ b/src/kernel/objects/handle.h @@ -9,11 +9,18 @@ namespace obj { struct handle { + constexpr static uint64_t id_mask = 0x00000000ffffffff; + constexpr static uint64_t cap_mask = 0x00ffffff00000000; + constexpr static uint64_t type_mask = 0xff00000000000000; + + constexpr static unsigned cap_shift = 32; + constexpr static unsigned type_shift = 56; + // A j6_handle_t is an id in the low 32 bits, caps in bits 32-55, and type in 56-63 static inline j6_handle_t make_id(j6_handle_t id, j6_cap_t caps, kobject *obj) { return (id & 0xffffffffull) | - static_cast(caps) << 32 | - static_cast(obj ? obj->get_type() : kobject::type::none) << 56; + ((static_cast(caps) << cap_shift) & cap_mask) | + static_cast(obj ? obj->get_type() : kobject::type::none) << type_shift; } inline handle(j6_handle_t in_id, kobject *in_obj, j6_cap_t caps) : @@ -50,7 +57,7 @@ struct handle if (object) object->handle_release(); } - inline j6_cap_t caps() const { return id >> 32; } + inline j6_cap_t caps() const { return (id & cap_mask) >> cap_shift; } inline bool has_cap(j6_cap_t test) const { return (caps() & test) == test; diff --git a/src/kernel/syscalls/handle.cpp b/src/kernel/syscalls/handle.cpp index f65a3c6..31639c5 100644 --- a/src/kernel/syscalls/handle.cpp +++ b/src/kernel/syscalls/handle.cpp @@ -2,6 +2,7 @@ #include #include "objects/process.h" +#include "syscalls/helpers.h" using namespace obj; @@ -24,4 +25,19 @@ handle_list(j6_handle_t *handles, size_t *handles_len) return j6_status_ok; } +j6_status_t +handle_clone(j6_handle_t orig, j6_handle_t *clone, uint32_t mask) +{ + handle *orig_handle = get_handle(orig); + if (!orig_handle) + return j6_err_invalid_arg; + + process &p = process::current(); + *clone = p.add_handle( + orig_handle->object, + orig_handle->caps() & mask); + + return j6_status_ok; +} + } // namespace syscalls diff --git a/src/user/srv.init/loader.cpp b/src/user/srv.init/loader.cpp index 7805fc4..8272934 100644 --- a/src/user/srv.init/loader.cpp +++ b/src/user/srv.init/loader.cpp @@ -20,7 +20,7 @@ constexpr size_t stack_size = 0x10000; constexpr uintptr_t stack_top = 0x80000000000; bool -load_program(const module_program &prog, char *err_msg) +load_program(const module_program &prog, j6_handle_t sys, char *err_msg) { if (prog.mod_flags && module_flags::no_load) { sprintf(err_msg, " skipping pre-loaded program module '%s' at %lx", prog.filename, prog.base_address); @@ -55,7 +55,7 @@ load_program(const module_program &prog, char *err_msg) return false; } - res = j6_process_give_handle(proc, __handle_sys, nullptr); + res = j6_process_give_handle(proc, sys, nullptr); if (res != j6_status_ok) { sprintf(err_msg, " ** error loading program '%s': giving system handle: %lx", prog.filename, res); return false; diff --git a/src/user/srv.init/loader.h b/src/user/srv.init/loader.h index fd32403..d8b14a6 100644 --- a/src/user/srv.init/loader.h +++ b/src/user/srv.init/loader.h @@ -2,8 +2,10 @@ /// \file loader.h /// Routines for loading and starting other programs +#include + namespace bootproto { struct module_program; } -bool load_program(const bootproto::module_program &prog, char *err_msg); +bool load_program(const bootproto::module_program &prog, j6_handle_t sys, char *err_msg); diff --git a/src/user/srv.init/main.cpp b/src/user/srv.init/main.cpp index 18624b4..616ae53 100644 --- a/src/user/srv.init/main.cpp +++ b/src/user/srv.init/main.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -29,6 +30,12 @@ main(int argc, const char **argv) modules mods = modules::load_modules(_arg_modules_phys, __handle_sys, __handle_self); + j6_handle_t drv_sys_handle = j6_handle_invalid; + j6_status_t s = j6_handle_clone(__handle_sys, &drv_sys_handle, + j6_cap_system_bind_irq | j6_cap_system_map_phys | j6_cap_system_change_iopl); + if (s != j6_status_ok) + return s; + for (auto &mod : mods.of_type(module_type::program)) { auto &prog = static_cast(mod); @@ -36,7 +43,7 @@ main(int argc, const char **argv) sprintf(message, " loading program module '%s' at %lx", prog.filename, prog.base_address); j6_log(message); - if (!load_program(prog, message)) { + if (!load_program(prog, __handle_sys, message)) { j6_log(message); return 1; }