diff --git a/Makefile b/Makefile index 6874f22..d460bc1 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,14 @@ include tools/make/gcc-cross-compile.mk BUILD_DIR := build CONFIG_DIR := .config +#################################### +# If the user has selected some kernel extensions to include +# in the kernel image, include the file that describes the +# extension source files to build +#################################### + +-include $(CONFIG_DIR)/extensions.mk + #################################### # Architecture-specific source files #################################### @@ -20,7 +28,7 @@ include arch/$(SOCKS_ARCH)/config.mk # Platform-independent kernel source files #################################### -KERNEL_SRC_DIRS := init kernel vm ds util obj sched dev test +KERNEL_SRC_DIRS := init kernel vm ds util obj sched dev test kxld KERNEL_C_FILES := $(foreach dir,$(KERNEL_SRC_DIRS),$(wildcard $(dir)/*.c)) KERNEL_CXX_FILES := $(foreach dir,$(KERNEL_SRC_DIRS),$(wildcard $(dir)/*.cpp)) KERNEL_OBJ := $(addprefix $(BUILD_DIR)/,$(KERNEL_C_FILES:.c=.o) $(KERNEL_CXX_FILES:.cpp=.o)) @@ -42,13 +50,15 @@ OPTIMISATION_LEVEL := -O2 CFLAGS := $(CFLAGS) -DBUILD_ID=\"$(BUILD_ID)\" $(OPTIMISATION_LEVEL) -g -fPIC -std=gnu17 \ -Iinclude -Iarch/$(SOCKS_ARCH)/include -Ilibc/include $(CWARNINGS) +KERNEL_DEFINES := -DSOCKS_INTERNAL=1 + CXXFLAGS := $(CXXFLAGS) -DBUILD_ID=\"$(BUILD_ID)\" $(OPTIMISATION_LEVEL) -g -fPIC -std=gnu++17 \ -Iinclude -Iarch/$(SOCKS_ARCH)/include -Ilibc/include -Wno-language-extension-token $(CWARNINGS) ASMFLAGS := $(ASMFLAGS) -DBUILD_ID=\"$(BUILD_ID)\" LDFLAGS := $(LDFLAGS) -g -lgcc $(OPTIMISATION_LEVEL) -ALL_KERNEL_OBJECT_FILES := $(KERNEL_OBJ) $(ARCH_OBJ) $(LIBC_OBJ) +ALL_KERNEL_OBJECT_FILES := $(KERNEL_OBJ) $(ARCH_OBJ) $(LIBC_OBJ) $(INTERNAL_KEXT_OBJ) ALL_KERNEL_DEPS := $(ALL_KERNEL_OBJECT_FILES:.o=.d) all: $(BUILD_DIR)/$(KERNEL_EXEC) tools @@ -70,12 +80,12 @@ $(BUILD_DIR)/%.o: %.S $(BUILD_DIR)/%.o: %.c @printf " \033[1;32mCC\033[0m \033[35m$(KERNEL_EXEC)\033[0m/$<\n" @mkdir -p $(@D) - @$(CC) $< -o $@ -c $(CFLAGS) $(ARCH_CFLAGS) -MMD + @$(CC) $< -o $@ -c $(CFLAGS) $(ARCH_CFLAGS) -MMD $(KERNEL_DEFINES) $(BUILD_DIR)/%.o: %.cpp @printf " \033[1;32mCXX\033[0m \033[35m$(KERNEL_EXEC)\033[0m/$<\n" @mkdir -p $(@D) - @$(CXX) $< -o $@ -c $(CXXFLAGS) $(ARCH_CXXFLAGS) -MMD + @$(CXX) $< -o $@ -c $(CXXFLAGS) $(ARCH_CXXFLAGS) -MMD $(KERNEL_DEFINES) clean: @printf " \033[1;93mRM\033[0m Deleting build files.\n" diff --git a/arch/x86_64/layout.ld b/arch/x86_64/layout.ld index 64ff918..1312c04 100644 --- a/arch/x86_64/layout.ld +++ b/arch/x86_64/layout.ld @@ -31,6 +31,19 @@ SECTIONS { *(.data) } + .rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_VMA) + { + _rodata = .; + *(.rodata*) + } + + .kexts ALIGN(4K) : AT(ADDR(.kexts) - KERNEL_VMA) + { + __kexts_start = .; + *(.kextinfo) + __kexts_end = .; + } + .data.percpu ALIGN(4K) : AT(ADDR(.data.percpu) - KERNEL_VMA) { __percpu_start = .; diff --git a/include/socks/kext.h b/include/socks/kext.h new file mode 100644 index 0000000..3c0919e --- /dev/null +++ b/include/socks/kext.h @@ -0,0 +1,81 @@ +#ifndef SOCKS_KEXT_H_ +#define SOCKS_KEXT_H_ + +#include +#include + +#define KERNEL_KEXT_ID "net.doorstuck.socks-kernel" +#define KEXT_IDENT_MAX 80 + +#define __KEXT_INFO_VARNAME_2(a, b) a ## b +#define __KEXT_INFO_VARNAME_1(a, b) __KEXT_INFO_VARNAME_2(a, b) + +#ifdef SOCKS_INTERNAL +#define __KEXT_INFO_LINKAGE static +#define __KEXT_INFO_VARNAME() __KEXT_INFO_VARNAME_1(__kext_info, __LINE__) +#define __KEXT_INFO_DEPNAME() __KEXT_INFO_VARNAME_1(__kext_deps, __LINE__) +#define __KEXT_INFO_FLAGS KEXT_INTERNAL +#else +#define __KEXT_INFO_LINKAGE +#define __KEXT_INFO_VARNAME() __kext_info +#define __KEXT_INFO_DEPNAME() __kext_deps +#define __KEXT_INFO_FLAGS KEXT_NONE +#endif + +#ifdef __cplusplus +#define DEFINE_KEXT(ident, online, offline, ...) \ + static const char *__KEXT_INFO_DEPNAME()[] = { \ + __VA_ARGS__ \ + }; \ + static struct kext_info __section(".kextinfo") __used __KEXT_INFO_VARNAME() = { \ + __KEXT_INFO_FLAGS, \ + ident, \ + online, \ + offline, \ + __KEXT_INFO_DEPNAME(), \ + } +#else +#define DEFINE_KEXT(ident, online, offline, ...) \ + static const char *__kext_deps[] = { \ + __VA_ARGS__ \ + }; \ + static struct kext_info __section(".kextinfo") __used __kext_info = { \ + .k_flags = __KEXT_INFO_FLAGS, \ + .k_ident = ident, \ + .k_online = online, \ + .k_offline = offline, \ + .k_dependencies = __kext_deps, \ + } +#endif + +struct kext; + +enum kext_flags { + KEXT_NONE = 0x00u, + KEXT_INTERNAL = 0x01u, + KEXT_ONLINE = 0x02u, +}; + +struct kext_info { + enum kext_flags k_flags; + char k_ident[KEXT_IDENT_MAX]; + kern_status_t(*k_online)(struct kext *); + kern_status_t(*k_offline)(struct kext *); + const char **k_dependencies; +}; + +struct kext { + enum kext_flags k_flags; + char k_ident[KEXT_IDENT_MAX]; + + kern_status_t(*k_online)(struct kext *); + kern_status_t(*k_offline)(struct kext *); + + unsigned int k_nr_dependencies; + struct kext **k_dependencies; +}; + +extern kern_status_t scan_internal_kexts(void); +extern kern_status_t bring_internal_kexts_online(void); + +#endif diff --git a/init/main.c b/init/main.c index e4810aa..6e698c0 100644 --- a/init/main.c +++ b/init/main.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,8 @@ void kernel_init(uintptr_t arg) { ml_init(arg); + scan_internal_kexts(); + printk("kernel_init() running on processor %u", this_cpu()); run_all_tests(); diff --git a/kexts/hello-world/hello-world.c b/kexts/hello-world/hello-world.c index c90d00c..7936e36 100644 --- a/kexts/hello-world/hello-world.c +++ b/kexts/hello-world/hello-world.c @@ -6,3 +6,7 @@ kern_status_t online(struct kext *self) printk("Hello, world!"); return KERN_OK; } + +DEFINE_KEXT("net.doorstuck.socks.hello-world", + online, NULL, + "net.doorstuck.socks-kernel"); diff --git a/kxld/internal.c b/kxld/internal.c new file mode 100644 index 0000000..2c577ea --- /dev/null +++ b/kxld/internal.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +static vm_cache_t kext_cache = { .c_obj_size = sizeof(struct kext) }; +static struct kext *self = NULL; + +extern char __kexts_start[]; +extern char __kexts_end[]; + +kern_status_t scan_internal_kexts(void) +{ + vm_cache_init(&kext_cache); + + self = vm_cache_alloc(&kext_cache, 0); + snprintf(self->k_ident, sizeof self->k_ident, "%s", KERNEL_KEXT_ID); + self->k_flags = KEXT_INTERNAL | KEXT_ONLINE; + + self->k_nr_dependencies = 0; + self->k_dependencies = NULL; + + struct kext_info *cur = (struct kext_info *)__kexts_start; + struct kext_info *end = (struct kext_info *)__kexts_end; + while (cur < end) { + printk("kext: found internal kext '%s'", cur->k_ident); + cur++; + } + + return KERN_OK; +} + +kern_status_t bring_internal_kexts_online(void) +{ + return KERN_OK; +}