Compare commits

...

17 Commits

Author SHA1 Message Date
wash 54d5d9dca7 services: add a test service to test bshell 2026-05-31 17:35:30 +01:00
wash 82b3c597f1 programs: add Bshell command interpreter 2026-05-31 17:34:50 +01:00
wash 000cb5c35d cmake: rosetta_wrap_library now handles target prefix and soname configuration 2026-05-31 17:29:53 +01:00
wash 616ad0d0cc cmake: support services that are not based on cmake executable targets 2026-05-31 17:29:06 +01:00
wash 4b917550f4 herdd: support updated service config layout 2026-05-31 17:27:55 +01:00
wash a4ca7058d1 services: exec key in service manifest is now an array of executable arguments 2026-05-31 17:26:50 +01:00
wash e492ac7974 ld: get_dynsym can now resolve references to global symbols 2026-05-31 17:25:53 +01:00
wash 9af325cdee lib: update libfx 2026-05-31 17:25:09 +01:00
wash 5888136db7 libc: io: formatting cleanup 2026-05-31 17:23:23 +01:00
wash 2dc68a33ab libc: malloc: fix heap_expand being called with a size measured in pages rather than bytes 2026-05-31 17:23:12 +01:00
wash 1b7c3b1b0d libc: malloc: store the global heap in a fixed region of virtual memory 2026-05-31 17:22:47 +01:00
wash b773439aa1 libc: io: temporarily switch stderr to line-buffered mode
no-buffering isn't compatible with kern_log (used by bootstrap), as it
automatically appends a newline to every string written. this will
be switched back once kern_log isn't being used anymore.
2026-05-31 17:21:15 +01:00
wash d47260dd13 libc: io: implement (v)fprintf 2026-05-31 17:20:57 +01:00
wash c9a87457b8 libc: core: set up NSD remote channel on startup 2026-05-31 17:20:31 +01:00
wash 474f228c98 libc: core: print error message on assertion failure 2026-05-31 17:20:00 +01:00
wash 64dd5d15a8 meta: move target definition files to services/targets/ 2026-05-30 19:48:20 +01:00
wash 277d87adb0 herdd: rename runlevels to targets 2026-05-30 19:47:49 +01:00
39 changed files with 425 additions and 197 deletions
+3
View File
@@ -7,3 +7,6 @@
[submodule "lib/libfx"]
path = lib/libfx
url = https://g.wash.red/wash/fx.git
[submodule "programs/bshell"]
path = programs/bshell
url = https://g.wash.red/wash/bshell.git
+1 -1
View File
@@ -16,6 +16,7 @@ include(BSP)
include(Arch)
include(Msg-Interface)
include(Templates)
include(Service)
bsp_reset()
sysroot_reset()
@@ -28,7 +29,6 @@ add_subdirectory(interface)
add_subdirectory(sys)
add_subdirectory(lib)
add_subdirectory(services)
add_subdirectory(runlevel)
add_subdirectory(programs)
sysroot_add_program(NAME ${kernel_name} BIN_DIR /boot)
+29 -5
View File
@@ -115,19 +115,43 @@ function(bsp_add_service)
get_property(bsp_targets GLOBAL PROPERTY bsp_target_list)
get_property(cfg_file TARGET ${arg_NAME} PROPERTY service_cfg_path)
get_property(file_list TARGET ${arg_NAME} PROPERTY service_file_list)
get_property(target_type TARGET ${arg_NAME} PROPERTY TYPE)
list(LENGTH bsp_targets nr_bsp_targets)
list(LENGTH file_list nr_service_files)
if (${nr_bsp_targets} GREATER 0)
math(EXPR serialiser_index "${nr_bsp_targets}-1")
list(GET bsp_targets ${serialiser_index} serialiser)
endif ()
add_custom_target(${bsp_target_name}
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
add-binary ${bsp_manifest} ${target_name}
${arg_BIN_DIR} $<TARGET_FILE:${target_name}>
set(commands
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
add-binary ${bsp_manifest} ${target_name}-cfg
${arg_SVC_DIR} ${cfg_file}
${arg_SVC_DIR} ${cfg_file})
if (target_type STREQUAL "EXECUTABLE")
set(commands ${commands}
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
add-binary ${bsp_manifest} ${target_name}
${arg_BIN_DIR} $<TARGET_FILE:${target_name}>)
endif ()
if (nr_service_files GREATER 0)
math(EXPR nr_service_files "${nr_service_files}-1")
foreach (i RANGE 0 ${nr_service_files} 2)
math(EXPR i2 "${i}+1")
list(GET file_list ${i} src_file)
list(GET file_list ${i2} dest_dir)
set(commands ${commands}
COMMAND ${Python_EXECUTABLE} ${bsp_tool}
add-binary ${bsp_manifest} ${target_name}-${i}
${dest_dir} ${src_file})
endforeach (i)
endif ()
add_custom_target(${bsp_target_name}
${commands}
COMMENT "Preparing bsp component: ${target_name}"
DEPENDS ${target_name} ${serialiser})
+52
View File
@@ -0,0 +1,52 @@
function(rosetta_add_service)
set(options)
set(one_value_args NAME CFG_FILE)
set(multi_value_args SOURCES)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}"
"${one_value_args}"
"${multi_value_args}")
set(exec_name ${arg_NAME})
get_property(programs GLOBAL PROPERTY rosetta_program_list)
set_property(GLOBAL PROPERTY rosetta_program_list ${programs} ${exec_name})
message(STATUS "Building service ${exec_name}")
add_executable(${exec_name} ${arg_SOURCES})
set_target_properties(${exec_name} PROPERTIES
POSITION_INDEPENDENT_CODE ON
service_cfg_path ${arg_CFG_FILE})
install(TARGETS ${exec_name}
DESTINATION ${arg_SYSROOT_PATH})
endfunction(rosetta_add_service)
function(rosetta_add_misc_service)
set(options)
set(one_value_args NAME CFG_FILE)
set(multi_value_args SOURCES)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}"
"${one_value_args}"
"${multi_value_args}")
message(STATUS "Building service ${arg_NAME}")
add_custom_target(${arg_NAME})
set_target_properties(${arg_NAME} PROPERTIES
service_cfg_path ${arg_CFG_FILE})
endfunction(rosetta_add_misc_service)
function(rosetta_service_add_file)
set(options)
set(one_value_args NAME SRC_FILE DEST_DIR)
set(multi_value_args)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}"
"${one_value_args}"
"${multi_value_args}")
get_property(file_list TARGET ${arg_NAME} PROPERTY service_file_list)
set(file_list ${file_list} ${arg_SRC_FILE} ${arg_DEST_DIR})
set_property(TARGET ${arg_NAME} PROPERTY service_file_list ${file_list})
endfunction(rosetta_service_add_file)
+30 -5
View File
@@ -170,19 +170,44 @@ function(sysroot_add_service)
get_property(sysroot_targets GLOBAL PROPERTY sysroot_target_list)
get_property(cfg_file TARGET ${arg_NAME} PROPERTY service_cfg_path)
get_property(file_list TARGET ${arg_NAME} PROPERTY service_file_list)
get_property(target_type TARGET ${arg_NAME} PROPERTY TYPE)
list(LENGTH sysroot_targets nr_sysroot_targets)
list(LENGTH file_list nr_service_files)
if (${nr_sysroot_targets} GREATER 0)
math(EXPR serialiser_index "${nr_sysroot_targets}-1")
list(GET sysroot_targets ${serialiser_index} serialiser)
endif ()
add_custom_target(${sysroot_target_name}
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
add-binary ${sysroot_manifest} ${target_name}
${arg_BIN_DIR} $<TARGET_FILE:${target_name}>
set(commands
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
add-binary ${sysroot_manifest} ${target_name}-cfg
${arg_SVC_DIR} ${cfg_file}
${arg_SVC_DIR} ${cfg_file})
if (target_type STREQUAL "EXECUTABLE")
set(commands ${commands}
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
add-binary ${sysroot_manifest} ${target_name}
${arg_BIN_DIR} $<TARGET_FILE:${target_name}>)
endif ()
if (nr_service_files GREATER 0)
math(EXPR nr_service_files "${nr_service_files}-1")
foreach (i RANGE 0 ${nr_service_files} 2)
math(EXPR i2 "${i}+1")
list(GET file_list ${i} src_file)
list(GET file_list ${i2} dest_dir)
set(commands ${commands}
COMMAND ${Python_EXECUTABLE} ${sysroot_tool}
add-binary ${sysroot_manifest} ${target_name}-${i}
${dest_dir} ${src_file})
endforeach (i)
endif ()
add_custom_target(${sysroot_target_name}
${commands}
COMMENT "Preparing sysroot component: ${target_name}"
DEPENDS ${target_name} ${serialiser})
+6 -25
View File
@@ -32,29 +32,6 @@ function(rosetta_add_executable)
DESTINATION ${arg_SYSROOT_PATH})
endfunction(rosetta_add_executable)
function(rosetta_add_service)
set(options)
set(one_value_args NAME CFG_FILE)
set(multi_value_args SOURCES)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}"
"${one_value_args}"
"${multi_value_args}")
set(exec_name ${arg_NAME})
get_property(programs GLOBAL PROPERTY rosetta_program_list)
set_property(GLOBAL PROPERTY rosetta_program_list ${programs} ${exec_name})
message(STATUS "Building service ${exec_name}")
add_executable(${exec_name} ${arg_SOURCES})
set_target_properties(${exec_name} PROPERTIES
POSITION_INDEPENDENT_CODE ON
service_cfg_path ${arg_CFG_FILE})
install(TARGETS ${exec_name}
DESTINATION ${arg_SYSROOT_PATH})
endfunction(rosetta_add_service)
function(rosetta_add_library)
set(options STATIC SHARED)
set(one_value_args NAME)
@@ -156,7 +133,7 @@ endfunction(rosetta_add_object_library)
function(rosetta_wrap_library)
set(options)
set(one_value_args NAME)
set(one_value_args NAME SONAME PREFIX)
set(multi_value_args
PUBLIC_INCLUDE_DIRS)
cmake_parse_arguments(PARSE_ARGV 0 arg
@@ -174,10 +151,14 @@ function(rosetta_wrap_library)
PATH ${arg_PUBLIC_INCLUDE_DIRS})
endif ()
if (arg_SONAME)
target_link_options(${lib_name} PRIVATE -Wl,--soname,${arg_SONAME}.so)
endif ()
set_target_properties(${lib_name} PROPERTIES
POSITION_INDEPENDENT_CODE ON
src_header_dir ${CMAKE_CURRENT_SOURCE_DIR}/include
PREFIX "")
PREFIX "${arg_PREFIX}")
endfunction(rosetta_wrap_library)
function(rosetta_add_object_library)
+2 -1
View File
@@ -31,9 +31,10 @@ endforeach (item)
foreach (assembly ${fx_assemblies})
target_link_libraries(${assembly} libc libpthread)
target_link_options(${assembly} PRIVATE -Wl,--soname,lib${assembly}.so)
# target_link_options(${assembly} PRIVATE -Wl,--soname,lib${assembly}.so)
rosetta_wrap_library(
NAME ${assembly}
SONAME lib${assembly}
PUBLIC_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/libfx/${module}/include)
set_target_properties(${assembly} PROPERTIES
PREFIX "lib")
+3
View File
@@ -1,3 +1,5 @@
#include <magenta/log.h>
#include <stdio.h>
#include <stdlib.h>
extern void __libc_assert_failed(
@@ -6,5 +8,6 @@ extern void __libc_assert_failed(
const char *func,
const char *cond)
{
kern_logf("ASSERT: %s failed (%s in %s:%d)", cond, func, file, line);
abort();
}
+3 -1
View File
@@ -1,7 +1,8 @@
#include <errno.h>
#include <magenta/log.h>
#include <rosetta/bootstrap.h>
#include <stdio.h>
#include <errno.h>
#include <sys/remote.h>
extern int main(int, const char **, const char **);
@@ -13,6 +14,7 @@ void *__attribute__((weak)) pthread_self(void)
int __libc_init(const struct rosetta_bootstrap *bsinfo)
{
sys_remote_set(SYS_REMOTE_NSD, 0, 0);
(volatile void)pthread_self();
__set_errno(SUCCESS);
return 0;
+1
View File
@@ -25,6 +25,7 @@ typedef struct __opaque_file FILE;
extern int printf(const char *format, ...);
extern int vprintf(const char *format, va_list arg);
extern int fprintf(FILE *stream, const char *format, ...);
extern int vfprintf(FILE *stream, const char *format, va_list arg);
extern int snprintf(char *buffer, size_t count, const char *format, ...);
extern int vsnprintf(
char *buffer,
+1
View File
@@ -57,6 +57,7 @@ int __libc_dir_refill(struct __opaque_dir *d)
int __libc_dir_move_next(struct __opaque_dir *d)
{
if (d->d_fd < 0) {
return -EBADF;
}
+8 -1
View File
@@ -1,6 +1,13 @@
#include "file.h"
#include <stdio.h>
int fprintf(struct __opaque_file *stream, const char *format, ...)
{
return 0;
va_list arg;
va_start(arg, format);
int ret = vfprintf(stream, format, arg);
va_end(arg);
return ret;
}
+1 -1
View File
@@ -5,7 +5,7 @@ int printf(const char *format, ...)
{
va_list arg;
va_start(arg, format);
int ret = vprintf(format, arg);
int ret = vfprintf(stdout, format, arg);
va_end(arg);
return ret;
+3 -1
View File
@@ -5,7 +5,9 @@
static struct __opaque_file __stderr = {
.f_fd = 2,
.f_flags = FILE_STATIC,
.f_buffer_mode = _IONBF,
/* TODO change this back to _IONBF once we're no longer using kern_log()
* in bootstrap */
.f_buffer_mode = _IOLBF,
};
extern struct __opaque_file *__libc_file_stderr(void)
+35
View File
@@ -0,0 +1,35 @@
#include "file.h"
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
extern int __libc_fctprintf(
int (*out)(char character, void *arg),
void *arg,
const char *format,
va_list va);
extern int __fputc(int c, struct __opaque_file *stream);
static inline int _out_file(char character, void *arg)
{
FILE *fp = arg;
return __fputc(character, fp);
}
int vfprintf(FILE *fp, const char *format, va_list arg)
{
__libc_file_lock(fp);
int ret = __libc_fctprintf(_out_file, fp, format, arg);
if (errno != SUCCESS) {
ret = -1;
}
if (ferror(fp)) {
ret = -1;
}
__libc_file_unlock(fp);
return ret;
}
+2 -14
View File
@@ -1,7 +1,7 @@
#include "file.h"
#include <stddef.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
extern int __libc_fctprintf(
@@ -19,17 +19,5 @@ static inline int _out_file(char character, void *arg)
int vprintf(const char *format, va_list arg)
{
__libc_file_lock(stdout);
int ret = __libc_fctprintf(_out_file, stdout, format, arg);
if (errno != SUCCESS) {
ret = -1;
}
if (ferror(stdout)) {
ret = -1;
}
__libc_file_unlock(stdout);
return ret;
return vfprintf(stdout, format, arg);
}
+1 -1
View File
@@ -30,5 +30,5 @@ sysroot_add_library(
HEADER_DIR /usr/include
LIB_DIR /usr/lib)
target_compile_definitions(libc-malloc PRIVATE ENABLE_GLOBAL_HEAP=1)
target_compile_definitions(libc-malloc PRIVATE LIBC_STATIC=1 ENABLE_GLOBAL_HEAP=1)
target_link_libraries(libc-malloc libc-core libmagenta)
+7 -1
View File
@@ -8,6 +8,12 @@
#include <magenta/vm.h>
#include <stdio.h>
#if defined(LIBC_STATIC)
#define HEAP_REGION_BASE 0x20000000000
#else
#define HEAP_REGION_BASE 0x60000000000
#endif
#define HEAP_REGION_SIZE 0x40000000
#define HEAP_EXPAND_INCREMENT 0x100000
@@ -40,7 +46,7 @@ static kern_status_t init_heap_region(heap_t *heap)
kern_status_t status = address_space_reserve(
address_space,
MAP_ADDRESS_ANY,
HEAP_REGION_BASE,
HEAP_REGION_SIZE,
&heap->heap_base);
+14 -8
View File
@@ -1,5 +1,10 @@
#include "liballoc.h"
#include <magenta/config.h>
#include <magenta/types.h>
#include <stdio.h>
#include <string.h>
/** Durand's Amazing Super Duper Memory functions. */
#define VERSION "1.1"
@@ -206,6 +211,8 @@ static struct liballoc_major *allocate_new_page(heap_t *heap, unsigned int size)
return NULL; // uh oh, we ran out of memory.
}
memset(maj, 0x0, sizeof *maj);
maj->prev = NULL;
maj->next = NULL;
maj->pages = st;
@@ -455,12 +462,10 @@ void *PREFIX(malloc)(heap_t *heap, size_t req_size)
if (diff
>= (size + sizeof(struct liballoc_minor))) {
// yay....
min->next
= (struct liballoc_minor
min->next = (struct liballoc_minor
*)((uintptr_t)min
+ sizeof(
struct
liballoc_minor)
struct liballoc_minor)
+ min->size);
min->next->prev = min;
min = min->next;
@@ -506,8 +511,7 @@ void *PREFIX(malloc)(heap_t *heap, size_t req_size)
new_min = (struct liballoc_minor
*)((uintptr_t)min
+ sizeof(
struct
liballoc_minor)
struct liballoc_minor)
+ min->size);
new_min->magic = LIBALLOC_MAGIC;
@@ -822,9 +826,11 @@ int liballoc_unlock(heap_t *heap)
return 0;
}
void *liballoc_alloc(heap_t *heap, size_t sz)
void *liballoc_alloc(heap_t *heap, size_t nr_pages)
{
return heap_expand(heap, sz);
size_t page_size = 0;
kern_config_get(KERN_CFG_PAGE_SIZE, &page_size, sizeof page_size);
return heap_expand(heap, nr_pages * page_size);
}
int liballoc_free(heap_t *heap, void *p, size_t sz)
+41
View File
@@ -1,5 +1,9 @@
file(GLOB items *)
set(bshell_interactive 0)
set(bshell_verbose 0)
set(bshell_enable_floating_point 0)
foreach(item ${items})
if (NOT IS_DIRECTORY ${item})
continue()
@@ -7,3 +11,40 @@ foreach(item ${items})
add_subdirectory(${item})
endforeach (item)
target_link_libraries(bshell libc libc-runtime libpthread)
target_link_libraries(bshell.core libc libpthread)
target_link_libraries(bshell.runtime libc libpthread)
sysroot_add_program(
NAME bshell
BIN_DIR /usr/bin)
bsp_add_program(
NAME bshell
BIN_DIR /usr/bin)
rosetta_wrap_library(
NAME bshell.runtime
SONAME libbshell.runtime
PREFIX lib
PUBLIC_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/bshell/bshell.runtime/include)
rosetta_wrap_library(
NAME bshell.core
PREFIX lib
SONAME libbshell.core)
sysroot_add_library(
NAME bshell.runtime
HEADER_DIR /usr/include
LIB_DIR /usr/lib)
bsp_add_library(
NAME bshell.runtime
LIB_DIR /usr/lib)
sysroot_add_library(
NAME bshell.core
LIB_DIR /usr/lib)
bsp_add_library(
NAME bshell.core
LIB_DIR /usr/lib)
+1
Submodule programs/bshell added at 8843f2d2a9
-12
View File
@@ -1,12 +0,0 @@
file(GLOB runlevels *.runlevel)
foreach (f ${runlevels})
get_filename_component(name ${f} NAME_WLE)
bsp_add_file(
ID runlevel-${name}
SRC_PATH ${f}
DEST_DIR /etc/herdd/runlevels)
sysroot_add_file(
ID runlevel-${name}
SRC_PATH ${f}
DEST_DIR /etc/herdd/runlevels)
endforeach (f)
-8
View File
@@ -1,8 +0,0 @@
# vim ft=toml
[runlevel]
name = "single-user"
description = "Single-User"
requires = [
"nsd",
"devmd"
]
+17
View File
@@ -0,0 +1,17 @@
rosetta_add_misc_service(
NAME bshell-test
CFG_FILE ${CMAKE_CURRENT_SOURCE_DIR}/bshell-test.service)
rosetta_service_add_file(
NAME bshell-test
SRC_FILE ${CMAKE_CURRENT_SOURCE_DIR}/test.bshell
DEST_DIR /sbin)
sysroot_add_service(
NAME bshell-test
BIN_DIR /usr/bin
SVC_DIR /etc/herdd/services)
bsp_add_service(
NAME bshell-test
BIN_DIR /usr/bin
SVC_DIR /etc/herdd/services)
+9
View File
@@ -0,0 +1,9 @@
# vim ft=toml
[unit]
description = "BShell Test Script"
[service]
exec = [
"/usr/bin/bshell",
"/sbin/test.bshell"
]
+2
View File
@@ -0,0 +1,2 @@
$x = "Jonh"
echo "Hello, $x!"
+1 -2
View File
@@ -1,10 +1,9 @@
# vim ft=toml
[unit]
name = "devmd"
description = "Device Management Service"
[service]
exec = "/usr/bin/devmd"
exec = [ "/usr/bin/devmd" ]
roles = [
"DeviceManager"
]
+11 -11
View File
@@ -1,8 +1,8 @@
#include "log.h"
#include "queue.h"
#include "runlevel.h"
#include "service.h"
#include "spawn.h"
#include "target.h"
#include <dirent.h>
#include <errno.h>
@@ -46,7 +46,7 @@ static int load_services(const char *dir, struct queue *out)
snprintf(filepath, sizeof filepath, "%s/%s", dir, dent->d_name);
tracef(" - %s\n", dent->d_name);
struct service *s = NULL;
int err = service_load(filepath, &s);
int err = service_load(dent->d_name, filepath, &s);
if (err != SUCCESS) {
printf("failed to load %s (%s)\n",
filepath,
@@ -60,7 +60,7 @@ static int load_services(const char *dir, struct queue *out)
return SUCCESS;
}
static int load_runlevels(const char *dir, struct queue *out)
static int load_targets(const char *dir, struct queue *out)
{
DIR *d = opendir(dir);
if (!d) {
@@ -74,8 +74,8 @@ static int load_runlevels(const char *dir, struct queue *out)
char filepath[4096];
snprintf(filepath, sizeof filepath, "%s/%s", dir, dent->d_name);
tracef(" - %s\n", dent->d_name);
struct runlevel *rl = NULL;
int err = runlevel_load(filepath, &rl);
struct target *rl = NULL;
int err = target_load(dent->d_name, filepath, &rl);
if (err != SUCCESS) {
printf("failed to load %s (%s)\n",
filepath,
@@ -83,7 +83,7 @@ static int load_runlevels(const char *dir, struct queue *out)
continue;
}
tracef("runlevel: %s\n", rl->rl_description);
tracef("target: %s\n", rl->rl_description);
for (size_t i = 0; i < rl->rl_requires_count; i++) {
tracef(" requires: %s\n", rl->rl_requires[i]);
}
@@ -99,19 +99,19 @@ int main(int argc, const char *argv[], const char *envp[])
{
sys_remote_set(SYS_REMOTE_NSD, 0, 0);
struct queue *runlevels = global_runlevels();
struct queue *targets = global_targets();
struct queue *services = global_services();
int err = load_runlevels("/etc/herdd/runlevels", runlevels);
int err = load_targets("/etc/herdd/targets", targets);
err = load_services("/etc/herdd/services", services);
struct runlevel *rl = runlevel_find("single-user");
struct target *rl = target_find("single-user.target");
if (!rl) {
log_fail("Cannot find runlevel single-user.");
log_fail("Cannot find target single-user.");
return -1;
}
runlevel_activate(rl);
target_activate(rl);
#if 1
pid_t child = fork();
kern_logf(" fork returned %d", child);
-22
View File
@@ -1,22 +0,0 @@
#ifndef RUNLEVEL_H_
#define RUNLEVEL_H_
#include "queue.h"
#include <stddef.h>
struct runlevel {
char *rl_name;
char *rl_description;
char **rl_requires;
size_t rl_requires_count;
struct queue_entry rl_entry;
};
extern struct queue *global_runlevels(void);
extern int runlevel_load(const char *path, struct runlevel **out);
extern struct runlevel *runlevel_find(const char *name);
extern int runlevel_activate(struct runlevel *rl);
#endif
+29 -27
View File
@@ -9,7 +9,6 @@
#include <fx/string.h>
#include <fx/stringstream.h>
#include <launch.h>
#include <magenta/log.h>
#include <rosetta/bootstrap.h>
#include <spawn.h>
#include <stdio.h>
@@ -43,13 +42,6 @@ static int parse_service_data(fx_object *in, struct service *out)
fx_hashtable *in_unit = NULL;
fx_value_get_object(unit_v, &in_unit);
const fx_value *name_v = fx_hashtable_get(in_unit, &FX_CSTR("name"));
if (!name_v || !fx_value_is_type(name_v, FX_TYPE_STRING)) {
return -1;
}
fx_string *name = NULL;
fx_value_get_object(name_v, &name);
const fx_value *description_v
= fx_hashtable_get(in_unit, &FX_CSTR("description"));
if (!description_v
@@ -60,11 +52,11 @@ static int parse_service_data(fx_object *in, struct service *out)
fx_value_get_object(description_v, &description);
const fx_value *exec_v = fx_hashtable_get(in_service, &FX_CSTR("exec"));
if (!exec_v || !fx_value_is_type(exec_v, FX_TYPE_STRING)) {
if (exec_v && !fx_value_is_type(exec_v, FX_TYPE_ARRAY)) {
return -1;
}
fx_string *exec = NULL;
fx_value_get_object(exec_v, &exec);
fx_value_get_object(exec_v, &out->s_exec);
fx_object_ref(out->s_exec);
const fx_value *roles_v
= fx_hashtable_get(in_service, &FX_CSTR("roles"));
@@ -101,24 +93,22 @@ static int parse_service_data(fx_object *in, struct service *out)
}
fx_iterator_unref(it);
out->s_name = fx_string_steal(name);
out->s_description = fx_string_steal(description);
out->s_exec = fx_string_steal(exec);
return 0;
}
int service_load(const char *path, struct service **out)
int service_load(const char *name, const char *path, struct service **out)
{
struct service *rl = malloc(sizeof *rl);
if (!rl) {
struct service *svc = malloc(sizeof *svc);
if (!svc) {
errno = ENOMEM;
return -1;
}
FILE *fp = fopen(path, "r");
if (!fp) {
free(rl);
free(svc);
return -1;
}
@@ -128,30 +118,32 @@ int service_load(const char *path, struct service **out)
fx_result result = fx_serial_ctx_deserialise(ctx, in, &data, 0);
if (fx_result_is_error(result)) {
fx_throw(result);
free(rl);
free(svc);
errno = EFTYPE;
return -1;
}
if (!fx_value_is_type(&data, FX_TYPE_HASHTABLE)) {
fx_value_unset(&data);
free(rl);
free(svc);
errno = EFTYPE;
return -1;
}
if (parse_service_data(data.v_object, rl) != 0) {
free(rl);
if (parse_service_data(data.v_object, svc) != 0) {
free(svc);
errno = EFTYPE;
return -1;
}
svc->s_name = fx_strdup(name);
fx_stream_unref(in);
fx_value_unset(&data);
fclose(fp);
*out = rl;
*out = svc;
return 0;
}
@@ -176,12 +168,22 @@ int service_start(struct service *svc)
log("Starting %s...", svc->s_description);
pid_t child = 0;
char *const argv[] = {
svc->s_name,
NULL,
};
size_t nr_args = fx_array_get_size(svc->s_exec);
int err = posix_spawn(&child, svc->s_exec, NULL, NULL, argv, NULL);
const char **argv = calloc(nr_args + 1, sizeof *argv);
for (size_t i = 0; i < nr_args; i++) {
const fx_value *str = fx_array_get_ref(svc->s_exec, i);
fx_value_get_cstr(str, &argv[i]);
}
int err = posix_spawn(
&child,
argv[0],
NULL,
NULL,
(char *const *)argv,
NULL);
free(argv);
if (err == 0) {
log_ok("Started %s.", svc->s_description);
+7 -2
View File
@@ -3,6 +3,8 @@
#include "queue.h"
#include <fx/collections/array.h>
enum service_role {
SVC_ROLE_NONE = 0x00u,
SVC_ROLE_NAMESPACE_PROVIDER = 0x01u,
@@ -11,14 +13,17 @@ enum service_role {
struct service {
char *s_name;
char *s_description;
char *s_exec;
fx_array *s_exec;
enum service_role s_roles;
struct queue_entry s_entry;
};
extern struct queue *global_services(void);
extern int service_load(const char *path, struct service **out);
extern int service_load(
const char *name,
const char *path,
struct service **out);
extern struct service *service_find(const char *name);
extern int service_start(struct service *svc);
@@ -1,4 +1,4 @@
#include "runlevel.h"
#include "target.h"
#include "log.h"
#include "service.h"
@@ -14,36 +14,35 @@
#include <stdlib.h>
#include <string.h>
static struct queue runlevels = QUEUE_INIT;
static struct queue targets = QUEUE_INIT;
struct queue *global_runlevels(void)
struct queue *global_targets(void)
{
return &runlevels;
return &targets;
}
static int parse_runlevel_data(fx_object *in, struct runlevel *out)
static int parse_target_data(fx_object *in, struct target *out)
{
if (!fx_object_is_type(in, FX_TYPE_HASHTABLE)) {
return -1;
}
const fx_value *runlevel_v = fx_hashtable_get(in, &FX_CSTR("runlevel"));
if (!runlevel_v || !fx_value_is_type(runlevel_v, FX_TYPE_HASHTABLE)) {
const fx_value *target_v = fx_hashtable_get(in, &FX_CSTR("target"));
if (!target_v || !fx_value_is_type(target_v, FX_TYPE_HASHTABLE)) {
return -1;
}
fx_hashtable *in_runlevel = NULL;
fx_value_get_object(runlevel_v, &in_runlevel);
fx_hashtable *in_target = NULL;
fx_value_get_object(target_v, &in_target);
const fx_value *name_v
= fx_hashtable_get(in_runlevel, &FX_CSTR("name"));
if (!name_v || !fx_value_is_type(name_v, FX_TYPE_STRING)) {
const fx_value *unit_v = fx_hashtable_get(in, &FX_CSTR("unit"));
if (!unit_v || !fx_value_is_type(unit_v, FX_TYPE_HASHTABLE)) {
return -1;
}
fx_string *name = NULL;
fx_value_get_object(name_v, &name);
fx_hashtable *in_unit = NULL;
fx_value_get_object(unit_v, &in_unit);
const fx_value *description_v
= fx_hashtable_get(in_runlevel, &FX_CSTR("description"));
= fx_hashtable_get(in_unit, &FX_CSTR("description"));
if (!description_v
|| !fx_value_is_type(description_v, FX_TYPE_STRING)) {
return -1;
@@ -52,7 +51,7 @@ static int parse_runlevel_data(fx_object *in, struct runlevel *out)
fx_value_get_object(description_v, &description);
const fx_value *deps_v
= fx_hashtable_get(in_runlevel, &FX_CSTR("requires"));
= fx_hashtable_get(in_target, &FX_CSTR("requires"));
if (deps_v && !fx_value_is_type(deps_v, FX_TYPE_ARRAY)) {
return -1;
}
@@ -87,15 +86,14 @@ static int parse_runlevel_data(fx_object *in, struct runlevel *out)
}
fx_iterator_unref(it);
out->rl_name = fx_string_steal(name);
out->rl_description = fx_string_steal(description);
return 0;
}
int runlevel_load(const char *path, struct runlevel **out)
int target_load(const char *name, const char *path, struct target **out)
{
struct runlevel *rl = malloc(sizeof *rl);
struct target *rl = malloc(sizeof *rl);
if (!rl) {
errno = ENOMEM;
return -1;
@@ -124,12 +122,14 @@ int runlevel_load(const char *path, struct runlevel **out)
return -1;
}
if (parse_runlevel_data(data.v_object, rl) != 0) {
if (parse_target_data(data.v_object, rl) != 0) {
free(rl);
errno = EFTYPE;
return -1;
}
rl->rl_name = fx_strdup(name);
fx_stream_unref(in);
fx_value_unset(&data);
@@ -139,12 +139,12 @@ int runlevel_load(const char *path, struct runlevel **out)
return 0;
}
struct runlevel *runlevel_find(const char *name)
struct target *target_find(const char *name)
{
struct queue_entry *cur = queue_first(&runlevels);
struct queue_entry *cur = queue_first(&targets);
while (cur) {
struct runlevel *rl
= QUEUE_CONTAINER(struct runlevel, rl_entry, cur);
struct target *rl
= QUEUE_CONTAINER(struct target, rl_entry, cur);
if (!strcmp(rl->rl_name, name)) {
return rl;
}
@@ -155,7 +155,7 @@ struct runlevel *runlevel_find(const char *name)
return NULL;
}
int runlevel_activate(struct runlevel *rl)
int target_activate(struct target *rl)
{
for (size_t i = 0; i < rl->rl_requires_count; i++) {
const char *svc_name = rl->rl_requires[i];
@@ -171,6 +171,6 @@ int runlevel_activate(struct runlevel *rl)
}
}
log_ok("Reached runlevel %s.", rl->rl_description);
log_ok("Reached target %s.", rl->rl_description);
return 0;
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef TARGET_H_
#define TARGET_H_
#include "queue.h"
#include <stddef.h>
struct target {
char *rl_name;
char *rl_description;
char **rl_requires;
size_t rl_requires_count;
struct queue_entry rl_entry;
};
extern struct queue *global_targets(void);
extern int target_load(const char *name, const char *path, struct target **out);
extern struct target *target_find(const char *name);
extern int target_activate(struct target *rl);
#endif
+1 -2
View File
@@ -1,10 +1,9 @@
# vim ft=toml
[unit]
name = "nsd"
description = "Namespace Service"
[service]
exec = "/usr/bin/nsd"
exec = [ "/usr/bin/nsd" ]
roles = [
"NamespaceProvider"
]
+13
View File
@@ -0,0 +1,13 @@
file(GLOB targets *.target)
foreach (f ${targets})
get_filename_component(name ${f} NAME_WLE)
bsp_add_file(
ID target-${name}
SRC_PATH ${f}
DEST_DIR /etc/herdd/targets)
sysroot_add_file(
ID target-${name}
SRC_PATH ${f}
DEST_DIR /etc/herdd/targets)
endforeach (f)
@@ -1,8 +1,9 @@
# vim ft=toml
[runlevel]
name = "minimal"
[unit]
description = "Minimal"
[target]
requires = [
"nsd",
"devmd"
"nsd.service",
"devmd.service"
]
+10
View File
@@ -0,0 +1,10 @@
# vim ft=toml
[unit]
description = "Single-User"
[target]
requires = [
"nsd.service",
"devmd.service",
"bshell-test.service"
]
+23 -11
View File
@@ -261,16 +261,24 @@ static int parse_phdr(struct elf_image *image)
}
#if 1
static elf_sym_t *get_dynsym(struct elf_image *image, size_t index)
static virt_addr_t get_dynsym(struct elf_image *image, size_t index)
{
elf_sym_t *sym = (elf_sym_t *)(image->e_base + image->e_dynsym
+ (index * image->e_dynsym_entsize));
const char *sym_name = (const char *)(image->e_base + image->e_strtab
+ sym->st_name);
if (!sym->st_value) {
return NULL;
if (sym->st_value) {
return image->e_base + sym->st_value;
}
return sym;
virt_addr_t sym_addr = find_global_symbol(sym_name);
if (sym_addr) {
return sym_addr;
}
kern_tracef("cannot resolve symbol %s", sym_name);
return 0;
}
static void resolve_symbol(unsigned int slot)
@@ -289,7 +297,7 @@ static int do_rela(struct elf_image *image, elf_rela_t *rela, bool lazy)
rela->r_offset);
#endif
int type = ELF64_R_TYPE(rela->r_info);
elf_sym_t *sym = NULL;
virt_addr_t v = 0;
switch (type) {
case R_X86_64_JUMP_SLOT:
@@ -303,13 +311,13 @@ static int do_rela(struct elf_image *image, elf_rela_t *rela, bool lazy)
#endif
break;
case R_X86_64_GLOB_DAT:
sym = get_dynsym(image, ELF64_R_SYM(rela->r_info));
if (!sym) {
v = get_dynsym(image, ELF64_R_SYM(rela->r_info));
if (!v) {
return ENOEXEC;
}
*(uint64_t *)(image->e_base + rela->r_offset)
= image->e_base + sym->st_value + rela->r_addend;
= v + rela->r_addend;
#if 0
kern_tracef(
"GLOB_DAT: offset=%zx, symbol=%zu, addend=%zx",
@@ -319,13 +327,13 @@ static int do_rela(struct elf_image *image, elf_rela_t *rela, bool lazy)
#endif
break;
case R_X86_64_64:
sym = get_dynsym(image, ELF64_R_SYM(rela->r_info));
if (!sym) {
v = get_dynsym(image, ELF64_R_SYM(rela->r_info));
if (!v) {
return ENOEXEC;
}
*(uint64_t *)(image->e_base + rela->r_offset)
= image->e_base + sym->st_value + rela->r_addend;
= v + rela->r_addend;
#if 0
kern_tracef(
"64: offset=%zx, symbol=%zu, addend=%zx",
@@ -404,6 +412,7 @@ static int relocate_rel(
size_t size,
size_t entsize)
{
kern_tracef("relocate_rel (unsupported)");
return ENOEXEC;
}
@@ -624,16 +633,19 @@ int elf_image_load(struct elf_image *img)
int e = reserve_exec_region(img);
if (e != SUCCESS) {
kern_log("error 1");
return e;
}
e = map_image(img);
if (e != SUCCESS) {
kern_log("error 2");
return e;
}
e = elf_image_parse_dynamic(img);
if (e != SUCCESS) {
kern_log("error 3");
return e;
}