mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 10:40:00 +00:00
Stage 8
This commit is contained in:
12
Makefile
12
Makefile
@@ -91,6 +91,7 @@ C_SOURCES := \
|
||||
clks/kernel/ramdisk.c \
|
||||
clks/kernel/fs.c \
|
||||
clks/kernel/userland.c \
|
||||
clks/kernel/driver.c \
|
||||
clks/lib/string.c \
|
||||
clks/drivers/serial/serial.c \
|
||||
clks/drivers/video/framebuffer.c \
|
||||
@@ -112,8 +113,9 @@ USER_COMMON_OBJECTS := $(patsubst %.c,$(USER_OBJ_ROOT)/%.o,$(USER_COMMON_SOURCES
|
||||
USER_SHELL_OBJECT := $(USER_OBJ_ROOT)/cleonos/c/apps/shell_main.o
|
||||
USER_ELFRUNNER_OBJECT := $(USER_OBJ_ROOT)/cleonos/c/apps/elfrunner_main.o
|
||||
USER_MEMC_OBJECT := $(USER_OBJ_ROOT)/cleonos/c/apps/memc_main.o
|
||||
USER_TTYDRV_OBJECT := $(USER_OBJ_ROOT)/cleonos/c/apps/ttydrv_main.o
|
||||
USER_RUST_LIB := $(USER_LIB_DIR)/libcleonos_user_rust.a
|
||||
USER_APPS := $(USER_APP_DIR)/shell.elf $(USER_APP_DIR)/elfrunner.elf $(USER_APP_DIR)/memc.elf
|
||||
USER_APPS := $(USER_APP_DIR)/shell.elf $(USER_APP_DIR)/elfrunner.elf $(USER_APP_DIR)/memc.elf $(USER_APP_DIR)/ttydrv.elf
|
||||
|
||||
CFLAGS_COMMON := -std=c11 -ffreestanding -fno-stack-protector -fno-builtin -Wall -Wextra -Werror -Iclks/include
|
||||
ASFLAGS_COMMON := -ffreestanding -Iclks/include
|
||||
@@ -202,10 +204,11 @@ ramdisk-root: userapps
|
||||
> @rm -rf $(RAMDISK_ROOT)
|
||||
> @mkdir -p $(RAMDISK_ROOT)
|
||||
> @cp -a ramdisk/. $(RAMDISK_ROOT)/
|
||||
> @mkdir -p $(RAMDISK_ROOT)/system $(RAMDISK_ROOT)/shell
|
||||
> @mkdir -p $(RAMDISK_ROOT)/system $(RAMDISK_ROOT)/shell $(RAMDISK_ROOT)/driver
|
||||
> @cp $(USER_APP_DIR)/shell.elf $(RAMDISK_ROOT)/shell/shell.elf
|
||||
> @cp $(USER_APP_DIR)/elfrunner.elf $(RAMDISK_ROOT)/system/elfrunner.elf
|
||||
> @cp $(USER_APP_DIR)/memc.elf $(RAMDISK_ROOT)/system/memc.elf
|
||||
> @cp $(USER_APP_DIR)/ttydrv.elf $(RAMDISK_ROOT)/driver/ttydrv.elf
|
||||
|
||||
ramdisk: $(RAMDISK_IMAGE)
|
||||
|
||||
@@ -249,6 +252,11 @@ $(USER_APP_DIR)/memc.elf: $(USER_COMMON_OBJECTS) $(USER_MEMC_OBJECT) $(USER_LINK
|
||||
> @mkdir -p $(dir $@)
|
||||
> @$(USER_LD) $(USER_LDFLAGS) -o $@ $(USER_COMMON_OBJECTS) $(USER_MEMC_OBJECT)
|
||||
|
||||
$(USER_APP_DIR)/ttydrv.elf: $(USER_COMMON_OBJECTS) $(USER_TTYDRV_OBJECT) $(USER_LINKER_SCRIPT)
|
||||
> $(call log_step,linking user ttydrv.elf)
|
||||
> @mkdir -p $(dir $@)
|
||||
> @$(USER_LD) $(USER_LDFLAGS) -o $@ $(USER_COMMON_OBJECTS) $(USER_TTYDRV_OBJECT)
|
||||
|
||||
$(RAMDISK_IMAGE): ramdisk-root Makefile
|
||||
> $(call log_step,packing ramdisk -> $(RAMDISK_IMAGE))
|
||||
> @mkdir -p $(dir $@)
|
||||
|
||||
8
cleonos/c/apps/ttydrv_main.c
Normal file
8
cleonos/c/apps/ttydrv_main.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <cleonos_syscall.h>
|
||||
|
||||
static const char ttydrv_banner[] = "[DRIVER][TTYDRV] ttydrv.elf online";
|
||||
|
||||
int cleonos_app_main(void) {
|
||||
cleonos_sys_log_write(ttydrv_banner, (u64)(sizeof(ttydrv_banner) - 1U));
|
||||
return 0;
|
||||
}
|
||||
35
clks/include/clks/driver.h
Normal file
35
clks/include/clks/driver.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef CLKS_DRIVER_H
|
||||
#define CLKS_DRIVER_H
|
||||
|
||||
#include <clks/types.h>
|
||||
|
||||
#define CLKS_DRIVER_NAME_MAX 32U
|
||||
|
||||
enum clks_driver_kind {
|
||||
CLKS_DRIVER_KIND_BUILTIN_CHAR = 1,
|
||||
CLKS_DRIVER_KIND_BUILTIN_VIDEO = 2,
|
||||
CLKS_DRIVER_KIND_BUILTIN_TTY = 3,
|
||||
CLKS_DRIVER_KIND_ELF = 4,
|
||||
};
|
||||
|
||||
enum clks_driver_state {
|
||||
CLKS_DRIVER_STATE_OFFLINE = 0,
|
||||
CLKS_DRIVER_STATE_READY = 1,
|
||||
CLKS_DRIVER_STATE_FAILED = 2,
|
||||
};
|
||||
|
||||
struct clks_driver_info {
|
||||
char name[CLKS_DRIVER_NAME_MAX];
|
||||
enum clks_driver_kind kind;
|
||||
enum clks_driver_state state;
|
||||
clks_bool from_elf;
|
||||
u64 image_size;
|
||||
u64 elf_entry;
|
||||
};
|
||||
|
||||
void clks_driver_init(void);
|
||||
u64 clks_driver_count(void);
|
||||
u64 clks_driver_elf_count(void);
|
||||
clks_bool clks_driver_get(u64 index, struct clks_driver_info *out_info);
|
||||
|
||||
#endif
|
||||
210
clks/kernel/driver.c
Normal file
210
clks/kernel/driver.c
Normal file
@@ -0,0 +1,210 @@
|
||||
#include <clks/driver.h>
|
||||
#include <clks/elf64.h>
|
||||
#include <clks/framebuffer.h>
|
||||
#include <clks/fs.h>
|
||||
#include <clks/log.h>
|
||||
#include <clks/string.h>
|
||||
#include <clks/types.h>
|
||||
|
||||
#define CLKS_DRIVER_MAX 32U
|
||||
#define CLKS_DRIVER_CHILD_NAME_MAX 96U
|
||||
#define CLKS_DRIVER_PATH_MAX 224U
|
||||
|
||||
static struct clks_driver_info clks_driver_table[CLKS_DRIVER_MAX];
|
||||
static u64 clks_driver_table_count = 0ULL;
|
||||
static u64 clks_driver_table_elf_count = 0ULL;
|
||||
|
||||
static void clks_driver_copy_name(char *dst, usize dst_size, const char *src) {
|
||||
usize i = 0U;
|
||||
|
||||
if (dst == CLKS_NULL || dst_size == 0U) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (src == CLKS_NULL) {
|
||||
dst[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
while (i + 1U < dst_size && src[i] != '\0') {
|
||||
dst[i] = src[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
dst[i] = '\0';
|
||||
}
|
||||
|
||||
static clks_bool clks_driver_has_elf_suffix(const char *name) {
|
||||
usize len;
|
||||
|
||||
if (name == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
len = clks_strlen(name);
|
||||
|
||||
if (len < 4U) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
return (name[len - 4U] == '.' &&
|
||||
name[len - 3U] == 'e' &&
|
||||
name[len - 2U] == 'l' &&
|
||||
name[len - 1U] == 'f') ? CLKS_TRUE : CLKS_FALSE;
|
||||
}
|
||||
|
||||
static clks_bool clks_driver_build_path(const char *child_name, char *out_path, usize out_size) {
|
||||
static const char prefix[] = "/driver/";
|
||||
usize prefix_len = sizeof(prefix) - 1U;
|
||||
usize child_len;
|
||||
|
||||
if (child_name == CLKS_NULL || out_path == CLKS_NULL || out_size == 0U) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
child_len = clks_strlen(child_name);
|
||||
|
||||
if (prefix_len + child_len + 1U > out_size) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_memcpy(out_path, prefix, prefix_len);
|
||||
clks_memcpy(out_path + prefix_len, child_name, child_len);
|
||||
out_path[prefix_len + child_len] = '\0';
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static clks_bool clks_driver_push(const char *name,
|
||||
enum clks_driver_kind kind,
|
||||
enum clks_driver_state state,
|
||||
clks_bool from_elf,
|
||||
u64 image_size,
|
||||
u64 elf_entry) {
|
||||
struct clks_driver_info *slot;
|
||||
|
||||
if (clks_driver_table_count >= CLKS_DRIVER_MAX) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
slot = &clks_driver_table[clks_driver_table_count];
|
||||
clks_memset(slot, 0, sizeof(*slot));
|
||||
|
||||
clks_driver_copy_name(slot->name, sizeof(slot->name), name);
|
||||
slot->kind = kind;
|
||||
slot->state = state;
|
||||
slot->from_elf = from_elf;
|
||||
slot->image_size = image_size;
|
||||
slot->elf_entry = elf_entry;
|
||||
|
||||
clks_driver_table_count++;
|
||||
|
||||
if (from_elf == CLKS_TRUE) {
|
||||
clks_driver_table_elf_count++;
|
||||
}
|
||||
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static void clks_driver_register_builtins(void) {
|
||||
clks_driver_push("serial", CLKS_DRIVER_KIND_BUILTIN_CHAR, CLKS_DRIVER_STATE_READY, CLKS_FALSE, 0ULL, 0ULL);
|
||||
|
||||
if (clks_fb_ready() == CLKS_TRUE) {
|
||||
clks_driver_push("framebuffer", CLKS_DRIVER_KIND_BUILTIN_VIDEO, CLKS_DRIVER_STATE_READY, CLKS_FALSE, 0ULL, 0ULL);
|
||||
clks_driver_push("tty", CLKS_DRIVER_KIND_BUILTIN_TTY, CLKS_DRIVER_STATE_READY, CLKS_FALSE, 0ULL, 0ULL);
|
||||
} else {
|
||||
clks_driver_push("framebuffer", CLKS_DRIVER_KIND_BUILTIN_VIDEO, CLKS_DRIVER_STATE_FAILED, CLKS_FALSE, 0ULL, 0ULL);
|
||||
clks_driver_push("tty", CLKS_DRIVER_KIND_BUILTIN_TTY, CLKS_DRIVER_STATE_FAILED, CLKS_FALSE, 0ULL, 0ULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_driver_probe_driver_dir(void) {
|
||||
u64 child_count;
|
||||
u64 i;
|
||||
|
||||
if (clks_fs_is_ready() == CLKS_FALSE) {
|
||||
clks_log(CLKS_LOG_ERROR, "DRV", "FS NOT READY FOR DRIVER PROBE");
|
||||
return;
|
||||
}
|
||||
|
||||
child_count = clks_fs_count_children("/driver");
|
||||
|
||||
for (i = 0ULL; i < child_count; i++) {
|
||||
char child_name[CLKS_DRIVER_CHILD_NAME_MAX];
|
||||
char full_path[CLKS_DRIVER_PATH_MAX];
|
||||
const void *image;
|
||||
u64 image_size = 0ULL;
|
||||
struct clks_elf64_info info;
|
||||
|
||||
clks_memset(child_name, 0, sizeof(child_name));
|
||||
clks_memset(full_path, 0, sizeof(full_path));
|
||||
|
||||
if (clks_fs_get_child_name("/driver", i, child_name, sizeof(child_name)) == CLKS_FALSE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (clks_driver_has_elf_suffix(child_name) == CLKS_FALSE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (clks_driver_build_path(child_name, full_path, sizeof(full_path)) == CLKS_FALSE) {
|
||||
clks_driver_push(child_name, CLKS_DRIVER_KIND_ELF, CLKS_DRIVER_STATE_FAILED, CLKS_TRUE, 0ULL, 0ULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
image = clks_fs_read_all(full_path, &image_size);
|
||||
|
||||
if (image == CLKS_NULL) {
|
||||
clks_log(CLKS_LOG_ERROR, "DRV", "DRIVER ELF MISSING");
|
||||
clks_log(CLKS_LOG_ERROR, "DRV", full_path);
|
||||
clks_driver_push(child_name, CLKS_DRIVER_KIND_ELF, CLKS_DRIVER_STATE_FAILED, CLKS_TRUE, 0ULL, 0ULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (clks_elf64_inspect(image, image_size, &info) == CLKS_FALSE) {
|
||||
clks_log(CLKS_LOG_ERROR, "DRV", "DRIVER ELF INVALID");
|
||||
clks_log(CLKS_LOG_ERROR, "DRV", full_path);
|
||||
clks_driver_push(child_name, CLKS_DRIVER_KIND_ELF, CLKS_DRIVER_STATE_FAILED, CLKS_TRUE, image_size, 0ULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "DRV", "DRIVER ELF READY");
|
||||
clks_log(CLKS_LOG_INFO, "DRV", full_path);
|
||||
clks_log_hex(CLKS_LOG_INFO, "DRV", "ENTRY", info.entry);
|
||||
|
||||
clks_driver_push(child_name, CLKS_DRIVER_KIND_ELF, CLKS_DRIVER_STATE_READY, CLKS_TRUE, image_size, info.entry);
|
||||
}
|
||||
}
|
||||
|
||||
void clks_driver_init(void) {
|
||||
clks_memset(clks_driver_table, 0, sizeof(clks_driver_table));
|
||||
clks_driver_table_count = 0ULL;
|
||||
clks_driver_table_elf_count = 0ULL;
|
||||
|
||||
clks_driver_register_builtins();
|
||||
clks_driver_probe_driver_dir();
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "DRV", "DRIVER MANAGER ONLINE");
|
||||
clks_log_hex(CLKS_LOG_INFO, "DRV", "REGISTERED", clks_driver_table_count);
|
||||
clks_log_hex(CLKS_LOG_INFO, "DRV", "ELF_DRIVERS", clks_driver_table_elf_count);
|
||||
}
|
||||
|
||||
u64 clks_driver_count(void) {
|
||||
return clks_driver_table_count;
|
||||
}
|
||||
|
||||
u64 clks_driver_elf_count(void) {
|
||||
return clks_driver_table_elf_count;
|
||||
}
|
||||
|
||||
clks_bool clks_driver_get(u64 index, struct clks_driver_info *out_info) {
|
||||
if (out_info == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (index >= clks_driver_table_count) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
*out_info = clks_driver_table[index];
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <clks/boot.h>
|
||||
#include <clks/cpu.h>
|
||||
#include <clks/driver.h>
|
||||
#include <clks/elfrunner.h>
|
||||
#include <clks/framebuffer.h>
|
||||
#include <clks/fs.h>
|
||||
@@ -40,7 +41,7 @@ void clks_kernel_main(void) {
|
||||
clks_tty_init();
|
||||
}
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE7 START");
|
||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE8 START");
|
||||
|
||||
if (boot_fb == CLKS_NULL) {
|
||||
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
||||
@@ -107,6 +108,8 @@ void clks_kernel_main(void) {
|
||||
clks_cpu_halt_forever();
|
||||
}
|
||||
|
||||
clks_driver_init();
|
||||
|
||||
clks_scheduler_init();
|
||||
|
||||
if (clks_scheduler_add_kernel_task("klogd", 4U) == CLKS_FALSE) {
|
||||
|
||||
36
docs/stage8.md
Normal file
36
docs/stage8.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# CLeonOS Stage8
|
||||
|
||||
## Stage Goal
|
||||
- Add kernel driver abstraction and registration framework.
|
||||
- Register built-in drivers (serial, framebuffer, tty) under a unified manager.
|
||||
- Probe `/driver` directory ELF drivers from ramdisk and validate ELF metadata.
|
||||
- Extend user app packaging to include driver ELF in `/driver`.
|
||||
|
||||
## Acceptance Criteria
|
||||
- Kernel boots and prints `CLEONOS STAGE8 START`.
|
||||
- Driver framework logs `DRIVER MANAGER ONLINE`.
|
||||
- Built-in drivers are registered and total driver count is logged.
|
||||
- `/driver/*.elf` files are discovered, validated, and logged as `DRIVER ELF READY`.
|
||||
- System continues to scheduler/interrupt/syscall idle loop without panic.
|
||||
|
||||
## Build Targets
|
||||
- `make setup`
|
||||
- `make userapps`
|
||||
- `make iso`
|
||||
- `make run`
|
||||
- `make debug`
|
||||
|
||||
## QEMU Command
|
||||
- `qemu-system-x86_64 -M q35 -m 1024M -cdrom build/CLeonOS-x86_64.iso -serial stdio`
|
||||
|
||||
## Common Bugs and Debugging
|
||||
- `DRIVER ELF INVALID`:
|
||||
- Verify ELF is built as x86_64 ELF64 and has valid program headers.
|
||||
- `DRIVER ELF MISSING`:
|
||||
- Ensure `make userapps` finished and ramdisk staging copied files to `/driver`.
|
||||
- Driver count is lower than expected:
|
||||
- Check `clks_driver_init()` call order occurs after `clks_fs_init()`.
|
||||
- Build failure for `ttydrv_main.c` symbols:
|
||||
- Confirm `cleonos/c/apps/ttydrv_main.c` exists and `USER_TTYDRV_OBJECT` is in Makefile.
|
||||
- No driver logs on boot:
|
||||
- Confirm kernel includes `clks/kernel/driver.c` in `C_SOURCES`.
|
||||
Reference in New Issue
Block a user