diff --git a/src/libraries/j6/j6.module b/src/libraries/j6/j6.module index 68e209d..124b8f6 100644 --- a/src/libraries/j6/j6.module +++ b/src/libraries/j6/j6.module @@ -2,8 +2,10 @@ j6 = module("j6", kind = "lib", + deps = [ "util" ], sources = [ "init.cpp", + "protocol_ids.cpp", "syscalls.s.cog", "sysconf.cpp.cog", ], @@ -12,6 +14,8 @@ j6 = module("j6", "j6/errors.h", "j6/flags.h", "j6/init.h", + "j6/protocols.h", + "j6/protocols/service_locator.h", "j6/syscalls.h.cog", "j6/sysconf.h.cog", "j6/types.h", diff --git a/src/libraries/j6/j6/protocols.h b/src/libraries/j6/j6/protocols.h new file mode 100644 index 0000000..3a57fca --- /dev/null +++ b/src/libraries/j6/j6/protocols.h @@ -0,0 +1,12 @@ +#pragma once +/// \file j6/protocols.h +/// Common definition for j6 user-mode IPC protocols + +enum j6_proto_base_tag +{ + j6_proto_base_status, + j6_proto_base_get_proto_id, + j6_proto_base_proto_id, + + j6_proto_base_first_proto_id /// The first protocol-specific ID +}; diff --git a/src/libraries/j6/j6/protocols/service_locator.h b/src/libraries/j6/j6/protocols/service_locator.h new file mode 100644 index 0000000..716d2a5 --- /dev/null +++ b/src/libraries/j6/j6/protocols/service_locator.h @@ -0,0 +1,14 @@ +#pragma once +/// \file j6/protocols/service_locator.h +/// Definitions for the service locator protocol + +#include + +extern const uint64_t j6_proto_sl_id; + +enum j6_proto_sl_tag +{ + j6_proto_sl_register = j6_proto_base_first_proto_id, + j6_proto_sl_find, + j6_proto_sl_result, +}; diff --git a/src/libraries/j6/protocol_ids.cpp b/src/libraries/j6/protocol_ids.cpp new file mode 100644 index 0000000..ea830f1 --- /dev/null +++ b/src/libraries/j6/protocol_ids.cpp @@ -0,0 +1,4 @@ +#include + +extern "C" +const uint64_t j6_proto_sl_id = "jsix.protocol.service_locator"_id; diff --git a/src/user/srv.init/init.module b/src/user/srv.init/init.module index 7ac432e..6025c58 100644 --- a/src/user/srv.init/init.module +++ b/src/user/srv.init/init.module @@ -8,6 +8,7 @@ init = module("srv.init", "loader.cpp", "main.cpp", "modules.cpp", + "service_locator.cpp", "start.s", ]) diff --git a/src/user/srv.init/loader.cpp b/src/user/srv.init/loader.cpp index ff48820..ac6f8f4 100644 --- a/src/user/srv.init/loader.cpp +++ b/src/user/srv.init/loader.cpp @@ -19,7 +19,10 @@ constexpr size_t stack_size = 0x10000; constexpr uintptr_t stack_top = 0x80000000000; bool -load_program(const module_program &prog, j6_handle_t sys, char *err_msg) +load_program( + const module_program &prog, + j6_handle_t sys, j6_handle_t slp, + 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); @@ -60,6 +63,12 @@ load_program(const module_program &prog, j6_handle_t sys, char *err_msg) return false; } + res = j6_process_give_handle(proc, slp, nullptr); + if (res != j6_status_ok) { + sprintf(err_msg, " ** error loading program '%s': giving SLP handle: %lx", prog.filename, res); + return false; + } + for (auto &seg : progelf.programs()) { if (seg.type != elf::segment_type::load) continue; diff --git a/src/user/srv.init/loader.h b/src/user/srv.init/loader.h index d8b14a6..3f6b0f4 100644 --- a/src/user/srv.init/loader.h +++ b/src/user/srv.init/loader.h @@ -8,4 +8,7 @@ namespace bootproto { struct module_program; } -bool load_program(const bootproto::module_program &prog, j6_handle_t sys, char *err_msg); +bool load_program( + const bootproto::module_program &prog, + j6_handle_t sys, j6_handle_t slp, + char *err_msg); diff --git a/src/user/srv.init/main.cpp b/src/user/srv.init/main.cpp index dd53591..ea5db81 100644 --- a/src/user/srv.init/main.cpp +++ b/src/user/srv.init/main.cpp @@ -10,6 +10,7 @@ #include "loader.h" #include "modules.h" +#include "service_locator.h" using bootproto::module; using bootproto::module_type; @@ -28,6 +29,9 @@ main(int argc, const char **argv) { j6_status_t s; + j6_handle_t slp_mb = j6_handle_invalid; + j6_handle_t slp_mb_child = j6_handle_invalid; + j6_handle_t sys = j6_handle_invalid; j6_handle_t sys_child = j6_handle_invalid; @@ -45,6 +49,13 @@ main(int argc, const char **argv) if (s != j6_status_ok) return s; + s = j6_mailbox_create(&slp_mb); + if (s != j6_status_ok) + return s; + + s = j6_handle_clone(slp_mb, &slp_mb_child, + j6_cap_mailbox_send | + j6_cap_object_clone); if (s != j6_status_ok) return s; @@ -57,11 +68,12 @@ 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, sys_child, message)) { + if (!load_program(prog, sys_child, slp_mb_child, message)) { j6_log(message); - return 1; + return 2; } } + service_locator_start(slp_mb); return 0; } diff --git a/src/user/srv.init/service_locator.cpp b/src/user/srv.init/service_locator.cpp new file mode 100644 index 0000000..7b61814 --- /dev/null +++ b/src/user/srv.init/service_locator.cpp @@ -0,0 +1,97 @@ +#include + +#include +#include +#include +#include +#include +#include + +#include "service_locator.h" + +void +service_locator_start(j6_handle_t mb) +{ + // TODO: This should be a multimap + util::map services; + + uint64_t tag; + uint16_t reply_tag; + + uint8_t data[100]; + size_t data_len = sizeof(data); + + j6_handle_t handles[10]; + size_t handles_count = sizeof(handles)/sizeof(j6_handle_t); + + j6_status_t s = j6_mailbox_receive(mb, &tag, + data, &data_len, + handles, &handles_count, + &reply_tag, nullptr, + j6_mailbox_block); + + uint64_t proto_id; + uint64_t *data_words = reinterpret_cast(data); + + while (true) { + j6_handle_t *found = nullptr; + + switch (tag) { + case j6_proto_base_get_proto_id: + tag = j6_proto_base_proto_id; + *data_words = j6_proto_sl_id; + data_len = sizeof(j6_status_t); + handles_count = 0; + break; + + case j6_proto_sl_register: + proto_id = *data_words; + if (handles_count != 1) { + tag = j6_proto_base_status; + *data_words = j6_err_invalid_arg; + data_len = sizeof(j6_status_t); + handles_count = 0; + break; + } + + services.insert( proto_id, handles[0] ); + tag = j6_proto_base_status; + *data_words = j6_status_ok; + data_len = sizeof(j6_status_t); + handles_count = 0; + break; + + case j6_proto_sl_find: + proto_id = *data_words; + tag = j6_proto_sl_result; + data_len = 0; + + found = services.find(proto_id); + if (found) { + handles_count = 1; + handles[0] = *found; + } else { + handles_count = 0; + } + break; + + default: + tag = j6_proto_base_status; + *data_words = j6_err_invalid_arg; + data_len = sizeof(j6_status_t); + handles_count = 0; + break; + } + + size_t data_in = data_len; + size_t handles_in = handles_count; + data_len = sizeof(data); + handles_count = sizeof(handles)/sizeof(j6_handle_t); + + s = j6_mailbox_respond_receive(mb, &tag, + data, &data_len, data_in, + handles, &handles_count, handles_in, + &reply_tag, nullptr, + j6_mailbox_block); + } +} diff --git a/src/user/srv.init/service_locator.h b/src/user/srv.init/service_locator.h new file mode 100644 index 0000000..6d8b85e --- /dev/null +++ b/src/user/srv.init/service_locator.h @@ -0,0 +1,5 @@ +#pragma once +/// \file service_locator.h +/// Definitions for srv.init's implementation of the service locator protocol + +void service_locator_start(j6_handle_t mb);