From 65a7511e36064bfd42c70fce4de1111a48c5225b Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Mon, 16 Mar 2026 21:20:00 +0100 Subject: [PATCH] Implement environment variables --- include/syscall_defs.h | 2 + kernel/amd64/proc.c | 3 ++ kernel/proc/env.c | 83 ++++++++++++++++++++++++++++++++++++++++ kernel/proc/env.h | 28 ++++++++++++++ kernel/proc/proc.h | 2 + kernel/proc/src.mk | 6 ++- kernel/syscall/syscall.c | 76 ++++++++++++++++++++++++++++++++++++ libsystem/system.c | 8 ++++ libsystem/system.h | 6 +++ make/apps.mk | 1 + sdutil/.gitignore | 5 +++ sdutil/Makefile | 3 ++ sdutil/app.mk | 1 + sdutil/sdutil.c | 3 ++ sdutil/src.mk | 3 ++ 15 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 kernel/proc/env.c create mode 100644 kernel/proc/env.h create mode 100644 sdutil/.gitignore create mode 100644 sdutil/Makefile create mode 100644 sdutil/app.mk create mode 100644 sdutil/sdutil.c create mode 100644 sdutil/src.mk diff --git a/include/syscall_defs.h b/include/syscall_defs.h index d33c71a..f5309ff 100644 --- a/include/syscall_defs.h +++ b/include/syscall_defs.h @@ -30,5 +30,7 @@ #define SYS_CREATE_DIR 27 #define SYS_REMOVE 28 #define SYS_CREATE_VOLUME 29 +#define SYS_ENV_SET 30 +#define SYS_ENV_GET 31 #endif // _M_SYSCALL_DEFS_H diff --git a/kernel/amd64/proc.c b/kernel/amd64/proc.c index 5e55730..a7a5fa5 100644 --- a/kernel/amd64/proc.c +++ b/kernel/amd64/proc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -138,6 +139,8 @@ void proc_cleanup (struct proc* proc, struct reschedule_ctx* rctx) { proc_sqs_cleanup (proc); proc_mutexes_cleanup (proc, rctx); + proc_env_cleanup (proc); + pmm_free (proc->pdata.kernel_stack, KSTACK_SIZE / PAGE_SIZE); procgroup_unmap (proc->procgroup, proc->pdata.tls_vaddr, proc->procgroup->tls.tls_tmpl_pages); diff --git a/kernel/proc/env.c b/kernel/proc/env.c new file mode 100644 index 0000000..65adb13 --- /dev/null +++ b/kernel/proc/env.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void proc_env_cleanup (struct proc* proc) { + for (size_t i = 0; i < fieldlengthof (struct proc_env, env_var_buckets); i++) { + struct hash_node_link* link = proc->env.env_var_buckets[i]; + + if (link == NULL) + continue; + + struct proc_env_var* var = hash_entry (link, struct proc_env_var, env_link); + + free (var->buffer); + free (var); + } +} + +int proc_env_set (struct proc* proc, const char* key, void* buffer, size_t data_size) { + uint64_t fp; + + struct proc_env_var* var = malloc (sizeof (*var)); + + if (var == NULL) + return -ST_OOM_ERROR; + + memset (var, 0, sizeof (*var)); + + var->buffer = malloc (data_size); + + if (var->buffer == NULL) { + free (var); + return -ST_OOM_ERROR; + } + + var->data_size = data_size; + memcpy (var->key, key, strlen_null (key)); + memcpy (var->buffer, buffer, data_size); + + uint32_t env_hash = hash_fnv32 (var->key, strlen_null (var->key)); + + spin_lock (&proc->lock, &fp); + + hash_insert (&proc->env, &var->env_link, env_hash, lengthof (proc->env.env_var_buckets), + env_var_buckets); + + spin_unlock (&proc->lock, fp); + + return ST_OK; +} + +int proc_env_get (struct proc* proc, const char* key, void* buffer, size_t size) { + uint64_t fp; + + struct hash_node_link* found_link = NULL; + size_t key_len = strlen_null (key); + uint32_t hash = hash_fnv32 (key, key_len); + + spin_lock (&proc->lock, &fp); + + hash_find (&proc->env, key, key_len, hash, lengthof (proc->env.env_var_buckets), env_var_buckets, + struct proc_env_var, env_link, key, found_link); + + if (found_link == NULL) { + spin_unlock (&proc->lock, fp); + return -ST_NOT_FOUND; + } + + struct proc_env_var* var = hash_entry (found_link, struct proc_env_var, env_link); + + memcpy (buffer, var->buffer, min (size, var->data_size)); + + spin_unlock (&proc->lock, fp); + + return ST_OK; +} diff --git a/kernel/proc/env.h b/kernel/proc/env.h new file mode 100644 index 0000000..9f26ba7 --- /dev/null +++ b/kernel/proc/env.h @@ -0,0 +1,28 @@ +#ifndef _KERNEL_PROC_ENV_H +#define _KERNEL_PROC_ENV_H + +#include +#include + +#define PROC_ENV_VAR_MAX 128 + +struct proc; + +struct proc_env_var { + char key[PROC_ENV_VAR_MAX]; + void* buffer; + size_t data_size; + struct hash_node_link env_link; +}; + +struct proc_env { + struct hash_node_link* env_var_buckets[64]; +}; + +void proc_env_cleanup (struct proc* proc); + +int proc_env_set (struct proc* proc, const char* key, void* buffer, size_t data_size); + +int proc_env_get (struct proc* proc, const char* key, void* buffer, size_t size); + +#endif // _KERNEL_PROC_ENV_H diff --git a/kernel/proc/proc.h b/kernel/proc/proc.h index 20cfd13..b4eddfc 100644 --- a/kernel/proc/proc.h +++ b/kernel/proc/proc.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ struct proc { size_t mail_recv_size; char cwv[VOLUME_MAX]; struct proc_suspension_q done_sq; + struct proc_env env; }; void proc_sched (void); diff --git a/kernel/proc/src.mk b/kernel/proc/src.mk index 5b1510f..357f4b6 100644 --- a/kernel/proc/src.mk +++ b/kernel/proc/src.mk @@ -3,11 +3,13 @@ c += proc/proc.c \ proc/mutex.c \ proc/procgroup.c \ proc/suspension_q.c \ - proc/mail.c + proc/mail.c \ + proc/env.c o += proc/proc.o \ proc/resource.o \ proc/mutex.o \ proc/procgroup.o \ proc/suspension_q.o \ - proc/mail.o + proc/mail.o \ + proc/env.o diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 2760288..6fabb0b 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -827,6 +827,80 @@ DEFINE_SYSCALL (sys_create_volume) { return SYSRESULT (vfs_create_volume (proc, rctx, key, type, device, false)); } +/* int env_set (char* key, void* buffer, size_t size) */ +DEFINE_SYSCALL (sys_env_set) { + uint64_t fp, fpg; + + uintptr_t uvaddr_key = a1; + uintptr_t uvaddr_buffer = a2; + size_t size = (size_t)a3; + + struct limine_hhdm_response* hhdm = limine_hhdm_request.response; + + uintptr_t out_paddr; + + spin_lock (&proc->lock, &fp); + struct procgroup* procgroup = proc->procgroup; + spin_unlock (&proc->lock, fp); + + spin_lock (&procgroup->lock, &fpg); + + out_paddr = mm_v2p (&procgroup->pd, uvaddr_key); + + if (out_paddr == 0) { + spin_unlock (&procgroup->lock, fpg); + return SYSRESULT (-ST_BAD_ADDRESS_SPACE); + } + + const char* key = (const char*)((uintptr_t)hhdm->offset + out_paddr); + + spin_unlock (&procgroup->lock, fpg); + + void* buffer = sys_get_user_buffer (procgroup, uvaddr_buffer, size); + + if (buffer == NULL) + return SYSRESULT (-ST_BAD_ADDRESS_SPACE); + + return SYSRESULT (proc_env_set (proc, key, buffer, size)); +} + +/* int env_get (char* key, void* buffer, size_t size) */ +DEFINE_SYSCALL (sys_env_get) { + uint64_t fp, fpg; + + uintptr_t uvaddr_key = a1; + uintptr_t uvaddr_buffer = a2; + size_t size = (size_t)a3; + + struct limine_hhdm_response* hhdm = limine_hhdm_request.response; + + uintptr_t out_paddr; + + spin_lock (&proc->lock, &fp); + struct procgroup* procgroup = proc->procgroup; + spin_unlock (&proc->lock, fp); + + spin_lock (&procgroup->lock, &fpg); + + out_paddr = mm_v2p (&procgroup->pd, uvaddr_key); + + if (out_paddr == 0) { + spin_unlock (&procgroup->lock, fpg); + return SYSRESULT (-ST_BAD_ADDRESS_SPACE); + } + + const char* key = (const char*)((uintptr_t)hhdm->offset + out_paddr); + + spin_unlock (&procgroup->lock, fpg); + + void* buffer = sys_get_user_buffer (procgroup, uvaddr_buffer, size); + + if (buffer == NULL) + return SYSRESULT (-ST_BAD_ADDRESS_SPACE); + + return SYSRESULT (proc_env_set (proc, key, buffer, size)); +} + static syscall_handler_func_t handler_table[] = { [SYS_QUIT] = &sys_quit, [SYS_TEST] = &sys_test, @@ -857,6 +931,8 @@ static syscall_handler_func_t handler_table[] = { [SYS_CREATE_DIR] = &sys_create_dir, [SYS_REMOVE] = &sys_remove, [SYS_CREATE_VOLUME] = &sys_create_volume, + [SYS_ENV_SET] = &sys_env_set, + [SYS_ENV_GET] = &sys_env_get, }; syscall_handler_func_t syscall_find_handler (int syscall_num) { diff --git a/libsystem/system.c b/libsystem/system.c index 47b07a7..ffd3c47 100644 --- a/libsystem/system.c +++ b/libsystem/system.c @@ -86,3 +86,11 @@ int remove (const char* path) { return (int)do_syscall (SYS_REMOVE, path); } int create_volume (const char* key, int fs_type, const char* device_key) { return (int)do_syscall (SYS_CREATE_VOLUME, key, fs_type, device_key); } + +int env_set (const char* key, void* buffer, size_t len) { + return (int)do_syscall (SYS_ENV_SET, key, buffer, len); +} + +int env_get (const char* key, void* buffer, size_t len) { + return (int)do_syscall (SYS_ENV_GET, key, buffer, len); +} diff --git a/libsystem/system.h b/libsystem/system.h index 99c0d42..18c525c 100644 --- a/libsystem/system.h +++ b/libsystem/system.h @@ -93,4 +93,10 @@ int remove (const char* path); /* mount a volume */ int create_volume (const char* key, int fs_type, const char* device_key); +/* Set environment variable */ +int env_set (const char* key, void* buffer, size_t len); + +/* Get environment variable */ +int env_get (const char* key, void* buffer, size_t len); + #endif // _LIBMSL_M_SYSTEM_H diff --git a/make/apps.mk b/make/apps.mk index d322ed8..5663637 100644 --- a/make/apps.mk +++ b/make/apps.mk @@ -2,6 +2,7 @@ apps := \ init \ spin \ ce \ + sdutil all_apps: @for d in $(apps); do make -C $$d platform=$(platform) all; done diff --git a/sdutil/.gitignore b/sdutil/.gitignore new file mode 100644 index 0000000..5efb1aa --- /dev/null +++ b/sdutil/.gitignore @@ -0,0 +1,5 @@ +*.o +*.json +docs/ +.cache/ +sdutil diff --git a/sdutil/Makefile b/sdutil/Makefile new file mode 100644 index 0000000..697fdc4 --- /dev/null +++ b/sdutil/Makefile @@ -0,0 +1,3 @@ +include ../make/ufuncs.mk + +include ../make/user.mk diff --git a/sdutil/app.mk b/sdutil/app.mk new file mode 100644 index 0000000..92e89f0 --- /dev/null +++ b/sdutil/app.mk @@ -0,0 +1 @@ +app := sdutil diff --git a/sdutil/sdutil.c b/sdutil/sdutil.c new file mode 100644 index 0000000..497bdbb --- /dev/null +++ b/sdutil/sdutil.c @@ -0,0 +1,3 @@ +#include + +void app_main (void) {} diff --git a/sdutil/src.mk b/sdutil/src.mk new file mode 100644 index 0000000..32359af --- /dev/null +++ b/sdutil/src.mk @@ -0,0 +1,3 @@ +c += sdutil.c + +o += sdutil.o