mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 18:44:01 +00:00
Stage 7
This commit is contained in:
73
Makefile
73
Makefile
@@ -5,10 +5,16 @@ NO_COLOR ?= 0
|
|||||||
BUILD_ROOT := build/x86_64
|
BUILD_ROOT := build/x86_64
|
||||||
OBJ_ROOT := $(BUILD_ROOT)/obj
|
OBJ_ROOT := $(BUILD_ROOT)/obj
|
||||||
ISO_ROOT := $(BUILD_ROOT)/iso_root
|
ISO_ROOT := $(BUILD_ROOT)/iso_root
|
||||||
|
RAMDISK_ROOT := $(BUILD_ROOT)/ramdisk_root
|
||||||
KERNEL_ELF := $(BUILD_ROOT)/clks_kernel.elf
|
KERNEL_ELF := $(BUILD_ROOT)/clks_kernel.elf
|
||||||
RAMDISK_IMAGE := $(BUILD_ROOT)/cleonos_ramdisk.tar
|
RAMDISK_IMAGE := $(BUILD_ROOT)/cleonos_ramdisk.tar
|
||||||
ISO_IMAGE := build/CLeonOS-x86_64.iso
|
ISO_IMAGE := build/CLeonOS-x86_64.iso
|
||||||
|
|
||||||
|
USER_BUILD_ROOT := $(BUILD_ROOT)/user
|
||||||
|
USER_OBJ_ROOT := $(USER_BUILD_ROOT)/obj
|
||||||
|
USER_APP_DIR := $(USER_BUILD_ROOT)/apps
|
||||||
|
USER_LIB_DIR := $(USER_BUILD_ROOT)/lib
|
||||||
|
|
||||||
LIMINE_DIR ?= limine
|
LIMINE_DIR ?= limine
|
||||||
LIMINE_REPO ?= https://gh-proxy.com/https://github.com/limine-bootloader/limine.git
|
LIMINE_REPO ?= https://gh-proxy.com/https://github.com/limine-bootloader/limine.git
|
||||||
LIMINE_REF ?=
|
LIMINE_REF ?=
|
||||||
@@ -33,6 +39,13 @@ LINKER_SCRIPT := clks/arch/x86_64/linker.ld
|
|||||||
RUN_COMMAND := $(QEMU_X86_64) -M q35 -m 1024M -cdrom $(ISO_IMAGE) -serial stdio
|
RUN_COMMAND := $(QEMU_X86_64) -M q35 -m 1024M -cdrom $(ISO_IMAGE) -serial stdio
|
||||||
DEBUG_COMMAND := $(QEMU_X86_64) -M q35 -m 1024M -cdrom $(ISO_IMAGE) -serial stdio -s -S
|
DEBUG_COMMAND := $(QEMU_X86_64) -M q35 -m 1024M -cdrom $(ISO_IMAGE) -serial stdio -s -S
|
||||||
|
|
||||||
|
USER_CC ?= cc
|
||||||
|
USER_LD ?= ld
|
||||||
|
RUSTC ?= rustc
|
||||||
|
USER_LINKER_SCRIPT := cleonos/c/user.ld
|
||||||
|
USER_CFLAGS := -std=c11 -ffreestanding -fno-stack-protector -fno-builtin -Wall -Wextra -Werror -Icleonos/c/include
|
||||||
|
USER_LDFLAGS := -nostdlib -z max-page-size=0x1000 -T $(USER_LINKER_SCRIPT)
|
||||||
|
|
||||||
ifeq ($(NO_COLOR),1)
|
ifeq ($(NO_COLOR),1)
|
||||||
COLOR_RESET :=
|
COLOR_RESET :=
|
||||||
COLOR_INFO :=
|
COLOR_INFO :=
|
||||||
@@ -77,6 +90,7 @@ C_SOURCES := \
|
|||||||
clks/kernel/syscall.c \
|
clks/kernel/syscall.c \
|
||||||
clks/kernel/ramdisk.c \
|
clks/kernel/ramdisk.c \
|
||||||
clks/kernel/fs.c \
|
clks/kernel/fs.c \
|
||||||
|
clks/kernel/userland.c \
|
||||||
clks/lib/string.c \
|
clks/lib/string.c \
|
||||||
clks/drivers/serial/serial.c \
|
clks/drivers/serial/serial.c \
|
||||||
clks/drivers/video/framebuffer.c \
|
clks/drivers/video/framebuffer.c \
|
||||||
@@ -90,11 +104,22 @@ C_OBJECTS := $(patsubst %.c,$(OBJ_ROOT)/%.o,$(C_SOURCES))
|
|||||||
ASM_OBJECTS := $(patsubst %.S,$(OBJ_ROOT)/%.o,$(ASM_SOURCES))
|
ASM_OBJECTS := $(patsubst %.S,$(OBJ_ROOT)/%.o,$(ASM_SOURCES))
|
||||||
OBJECTS := $(C_OBJECTS) $(ASM_OBJECTS)
|
OBJECTS := $(C_OBJECTS) $(ASM_OBJECTS)
|
||||||
|
|
||||||
|
USER_COMMON_SOURCES := \
|
||||||
|
cleonos/c/src/runtime.c \
|
||||||
|
cleonos/c/src/syscall.c
|
||||||
|
|
||||||
|
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_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
|
||||||
|
|
||||||
CFLAGS_COMMON := -std=c11 -ffreestanding -fno-stack-protector -fno-builtin -Wall -Wextra -Werror -Iclks/include
|
CFLAGS_COMMON := -std=c11 -ffreestanding -fno-stack-protector -fno-builtin -Wall -Wextra -Werror -Iclks/include
|
||||||
ASFLAGS_COMMON := -ffreestanding -Iclks/include
|
ASFLAGS_COMMON := -ffreestanding -Iclks/include
|
||||||
LDFLAGS_COMMON := -nostdlib -z max-page-size=0x1000
|
LDFLAGS_COMMON := -nostdlib -z max-page-size=0x1000
|
||||||
|
|
||||||
.PHONY: all setup setup-tools setup-limine kernel ramdisk iso run debug clean clean-all help
|
.PHONY: all setup setup-tools setup-limine kernel userapps ramdisk-root ramdisk iso run debug clean clean-all help
|
||||||
|
|
||||||
all: iso
|
all: iso
|
||||||
|
|
||||||
@@ -111,6 +136,9 @@ setup-tools:
|
|||||||
> @command -v $(OBJCOPY_FOR_TARGET) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(OBJCOPY_FOR_TARGET)" && exit 1)
|
> @command -v $(OBJCOPY_FOR_TARGET) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(OBJCOPY_FOR_TARGET)" && exit 1)
|
||||||
> @command -v $(OBJDUMP_FOR_TARGET) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(OBJDUMP_FOR_TARGET)" && exit 1)
|
> @command -v $(OBJDUMP_FOR_TARGET) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(OBJDUMP_FOR_TARGET)" && exit 1)
|
||||||
> @command -v $(READELF_FOR_TARGET) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(READELF_FOR_TARGET)" && exit 1)
|
> @command -v $(READELF_FOR_TARGET) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(READELF_FOR_TARGET)" && exit 1)
|
||||||
|
> @command -v $(USER_CC) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(USER_CC)" && exit 1)
|
||||||
|
> @command -v $(USER_LD) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(USER_LD)" && exit 1)
|
||||||
|
> @command -v $(RUSTC) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(RUSTC)" && exit 1)
|
||||||
> $(call log_info,required tools are available)
|
> $(call log_info,required tools are available)
|
||||||
|
|
||||||
setup-limine:
|
setup-limine:
|
||||||
@@ -166,6 +194,19 @@ setup-limine:
|
|||||||
|
|
||||||
kernel: $(KERNEL_ELF)
|
kernel: $(KERNEL_ELF)
|
||||||
|
|
||||||
|
userapps: $(USER_APPS)
|
||||||
|
> $(call log_info,user elf apps ready)
|
||||||
|
|
||||||
|
ramdisk-root: userapps
|
||||||
|
> $(call log_step,staging ramdisk root -> $(RAMDISK_ROOT))
|
||||||
|
> @rm -rf $(RAMDISK_ROOT)
|
||||||
|
> @mkdir -p $(RAMDISK_ROOT)
|
||||||
|
> @cp -a ramdisk/. $(RAMDISK_ROOT)/
|
||||||
|
> @mkdir -p $(RAMDISK_ROOT)/system $(RAMDISK_ROOT)/shell
|
||||||
|
> @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
|
||||||
|
|
||||||
ramdisk: $(RAMDISK_IMAGE)
|
ramdisk: $(RAMDISK_IMAGE)
|
||||||
|
|
||||||
$(KERNEL_ELF): $(OBJECTS) $(LINKER_SCRIPT) Makefile
|
$(KERNEL_ELF): $(OBJECTS) $(LINKER_SCRIPT) Makefile
|
||||||
@@ -183,11 +224,35 @@ $(OBJ_ROOT)/%.o: %.S Makefile
|
|||||||
> @mkdir -p $(dir $@)
|
> @mkdir -p $(dir $@)
|
||||||
> @$(CC) $(ASFLAGS_COMMON) $(ARCH_CFLAGS) -c $< -o $@
|
> @$(CC) $(ASFLAGS_COMMON) $(ARCH_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(USER_OBJ_ROOT)/%.o: %.c Makefile
|
||||||
|
> $(call log_step,compiling user $<)
|
||||||
|
> @mkdir -p $(dir $@)
|
||||||
|
> @$(USER_CC) $(USER_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
$(RAMDISK_IMAGE):
|
$(USER_RUST_LIB): cleonos/rust/src/lib.rs Makefile
|
||||||
|
> $(call log_step,building rust user lib)
|
||||||
|
> @mkdir -p $(dir $@)
|
||||||
|
> @$(RUSTC) --crate-type staticlib -C panic=abort -O $< -o $@
|
||||||
|
|
||||||
|
$(USER_APP_DIR)/shell.elf: $(USER_COMMON_OBJECTS) $(USER_SHELL_OBJECT) $(USER_RUST_LIB) $(USER_LINKER_SCRIPT)
|
||||||
|
> $(call log_step,linking user shell.elf)
|
||||||
|
> @mkdir -p $(dir $@)
|
||||||
|
> @$(USER_LD) $(USER_LDFLAGS) -o $@ $(USER_COMMON_OBJECTS) $(USER_SHELL_OBJECT) $(USER_RUST_LIB)
|
||||||
|
|
||||||
|
$(USER_APP_DIR)/elfrunner.elf: $(USER_COMMON_OBJECTS) $(USER_ELFRUNNER_OBJECT) $(USER_LINKER_SCRIPT)
|
||||||
|
> $(call log_step,linking user elfrunner.elf)
|
||||||
|
> @mkdir -p $(dir $@)
|
||||||
|
> @$(USER_LD) $(USER_LDFLAGS) -o $@ $(USER_COMMON_OBJECTS) $(USER_ELFRUNNER_OBJECT)
|
||||||
|
|
||||||
|
$(USER_APP_DIR)/memc.elf: $(USER_COMMON_OBJECTS) $(USER_MEMC_OBJECT) $(USER_LINKER_SCRIPT)
|
||||||
|
> $(call log_step,linking user memc.elf)
|
||||||
|
> @mkdir -p $(dir $@)
|
||||||
|
> @$(USER_LD) $(USER_LDFLAGS) -o $@ $(USER_COMMON_OBJECTS) $(USER_MEMC_OBJECT)
|
||||||
|
|
||||||
|
$(RAMDISK_IMAGE): ramdisk-root Makefile
|
||||||
> $(call log_step,packing ramdisk -> $(RAMDISK_IMAGE))
|
> $(call log_step,packing ramdisk -> $(RAMDISK_IMAGE))
|
||||||
> @mkdir -p $(dir $@)
|
> @mkdir -p $(dir $@)
|
||||||
> @$(TAR) -C ramdisk -cf $@ .
|
> @$(TAR) -C $(RAMDISK_ROOT) -cf $@ .
|
||||||
|
|
||||||
iso: setup-tools setup-limine $(KERNEL_ELF) $(RAMDISK_IMAGE) configs/limine.conf
|
iso: setup-tools setup-limine $(KERNEL_ELF) $(RAMDISK_IMAGE) configs/limine.conf
|
||||||
> $(call log_step,assembling iso root)
|
> $(call log_step,assembling iso root)
|
||||||
@@ -241,8 +306,8 @@ help:
|
|||||||
> @echo " make setup LIMINE_SKIP_CONFIGURE=1"
|
> @echo " make setup LIMINE_SKIP_CONFIGURE=1"
|
||||||
> @echo " make setup LIMINE_CONFIGURE_FLAGS='--enable-bios-cd --enable-uefi-cd --enable-uefi-x86-64'"
|
> @echo " make setup LIMINE_CONFIGURE_FLAGS='--enable-bios-cd --enable-uefi-cd --enable-uefi-x86-64'"
|
||||||
> @echo " make setup OBJCOPY_FOR_TARGET=llvm-objcopy OBJDUMP_FOR_TARGET=llvm-objdump READELF_FOR_TARGET=llvm-readelf"
|
> @echo " make setup OBJCOPY_FOR_TARGET=llvm-objcopy OBJDUMP_FOR_TARGET=llvm-objdump READELF_FOR_TARGET=llvm-readelf"
|
||||||
|
> @echo " make userapps"
|
||||||
> @echo " make iso"
|
> @echo " make iso"
|
||||||
> @echo " make run"
|
> @echo " make run"
|
||||||
> @echo " make debug"
|
> @echo " make debug"
|
||||||
> @echo " make NO_COLOR=1 <target>"
|
> @echo " make NO_COLOR=1 <target>"
|
||||||
|
|
||||||
|
|||||||
8
cleonos/c/apps/elfrunner_main.c
Normal file
8
cleonos/c/apps/elfrunner_main.c
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include <cleonos_syscall.h>
|
||||||
|
|
||||||
|
static const char elfrunner_banner[] = "[KAPP][ELFRUNNER] elfrunner.elf online";
|
||||||
|
|
||||||
|
int cleonos_app_main(void) {
|
||||||
|
cleonos_sys_log_write(elfrunner_banner, (u64)(sizeof(elfrunner_banner) - 1U));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
10
cleonos/c/apps/memc_main.c
Normal file
10
cleonos/c/apps/memc_main.c
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include <cleonos_syscall.h>
|
||||||
|
|
||||||
|
static const char memc_banner[] = "[KAPP][MEMC] memc.elf online";
|
||||||
|
|
||||||
|
int cleonos_app_main(void) {
|
||||||
|
u64 ticks = cleonos_sys_timer_ticks();
|
||||||
|
(void)ticks;
|
||||||
|
cleonos_sys_log_write(memc_banner, (u64)(sizeof(memc_banner) - 1U));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
13
cleonos/c/apps/shell_main.c
Normal file
13
cleonos/c/apps/shell_main.c
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include <cleonos_rust_bridge.h>
|
||||||
|
#include <cleonos_syscall.h>
|
||||||
|
|
||||||
|
static const char shell_banner[] = "[USER][SHELL] shell.elf online";
|
||||||
|
static const char shell_status[] = "[USER][SHELL] syscall int80 path ok";
|
||||||
|
|
||||||
|
int cleonos_app_main(void) {
|
||||||
|
u64 len = cleonos_rust_guarded_len((const unsigned char *)shell_banner, (usize)(sizeof(shell_banner) - 1U));
|
||||||
|
|
||||||
|
cleonos_sys_log_write(shell_banner, len);
|
||||||
|
cleonos_sys_log_write(shell_status, (u64)(sizeof(shell_status) - 1U));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
9
cleonos/c/include/cleonos_rust_bridge.h
Normal file
9
cleonos/c/include/cleonos_rust_bridge.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef CLEONOS_RUST_BRIDGE_H
|
||||||
|
#define CLEONOS_RUST_BRIDGE_H
|
||||||
|
|
||||||
|
typedef unsigned long long u64;
|
||||||
|
typedef unsigned long long usize;
|
||||||
|
|
||||||
|
u64 cleonos_rust_guarded_len(const unsigned char *ptr, usize max_len);
|
||||||
|
|
||||||
|
#endif
|
||||||
16
cleonos/c/include/cleonos_syscall.h
Normal file
16
cleonos/c/include/cleonos_syscall.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef CLEONOS_SYSCALL_H
|
||||||
|
#define CLEONOS_SYSCALL_H
|
||||||
|
|
||||||
|
typedef unsigned long long u64;
|
||||||
|
typedef unsigned long long usize;
|
||||||
|
|
||||||
|
#define CLEONOS_SYSCALL_LOG_WRITE 0ULL
|
||||||
|
#define CLEONOS_SYSCALL_TIMER_TICKS 1ULL
|
||||||
|
#define CLEONOS_SYSCALL_TASK_COUNT 2ULL
|
||||||
|
#define CLEONOS_SYSCALL_CUR_TASK 3ULL
|
||||||
|
|
||||||
|
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
||||||
|
u64 cleonos_sys_log_write(const char *message, u64 length);
|
||||||
|
u64 cleonos_sys_timer_ticks(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
16
cleonos/c/src/runtime.c
Normal file
16
cleonos/c/src/runtime.c
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include <cleonos_syscall.h>
|
||||||
|
|
||||||
|
typedef int (*cleonos_entry_fn)(void);
|
||||||
|
|
||||||
|
extern int cleonos_app_main(void);
|
||||||
|
|
||||||
|
void _start(void) {
|
||||||
|
volatile int code;
|
||||||
|
|
||||||
|
code = ((cleonos_entry_fn)cleonos_app_main)();
|
||||||
|
(void)code;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
__asm__ volatile("pause");
|
||||||
|
}
|
||||||
|
}
|
||||||
22
cleonos/c/src/syscall.c
Normal file
22
cleonos/c/src/syscall.c
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include <cleonos_syscall.h>
|
||||||
|
|
||||||
|
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2) {
|
||||||
|
u64 ret;
|
||||||
|
|
||||||
|
__asm__ volatile(
|
||||||
|
"int $0x80"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "a"(id), "b"(arg0), "c"(arg1), "d"(arg2)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 cleonos_sys_log_write(const char *message, u64 length) {
|
||||||
|
return cleonos_syscall(CLEONOS_SYSCALL_LOG_WRITE, (u64)message, length, 0ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 cleonos_sys_timer_ticks(void) {
|
||||||
|
return cleonos_syscall(CLEONOS_SYSCALL_TIMER_TICKS, 0ULL, 0ULL, 0ULL);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* CLeonOS user-space C toolchain stub.
|
* CLeonOS user-space bootstrap placeholder kept for compatibility.
|
||||||
* Stage1 only defines build skeleton. Real shell/user ELF apps start in later stages.
|
* Stage7 introduces real user ELF apps under cleonos/c/apps.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int cleonos_c_stub(void) {
|
int cleonos_c_stub(void) {
|
||||||
|
|||||||
29
cleonos/c/user.ld
Normal file
29
cleonos/c/user.ld
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
OUTPUT_FORMAT(elf64-x86-64)
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
PHDRS {
|
||||||
|
text PT_LOAD FLAGS(5);
|
||||||
|
rodata PT_LOAD FLAGS(4);
|
||||||
|
data PT_LOAD FLAGS(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x00400000;
|
||||||
|
|
||||||
|
.text : ALIGN(0x1000) {
|
||||||
|
*(.text .text.*)
|
||||||
|
} :text
|
||||||
|
|
||||||
|
.rodata : ALIGN(0x1000) {
|
||||||
|
*(.rodata .rodata.*)
|
||||||
|
} :rodata
|
||||||
|
|
||||||
|
.data : ALIGN(0x1000) {
|
||||||
|
*(.data .data.*)
|
||||||
|
} :data
|
||||||
|
|
||||||
|
.bss : ALIGN(0x1000) {
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss .bss.*)
|
||||||
|
} :data
|
||||||
|
}
|
||||||
@@ -1,6 +1,31 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[no_mangle]
|
use core::panic::PanicInfo;
|
||||||
pub extern "C" fn cleonos_rust_stub() -> u64 {
|
|
||||||
0
|
#[panic_handler]
|
||||||
|
fn panic(_info: &PanicInfo) -> ! {
|
||||||
|
loop {
|
||||||
|
core::hint::spin_loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn cleonos_rust_guarded_len(ptr: *const u8, max_len: usize) -> u64 {
|
||||||
|
let mut i: usize = 0;
|
||||||
|
|
||||||
|
if ptr.is_null() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while i < max_len {
|
||||||
|
let ch = unsafe { *ptr.add(i) };
|
||||||
|
|
||||||
|
if ch == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i as u64
|
||||||
}
|
}
|
||||||
@@ -116,3 +116,4 @@ clks_isr_common:
|
|||||||
|
|
||||||
add rsp, 16
|
add rsp, 16
|
||||||
iretq
|
iretq
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
||||||
|
|||||||
8
clks/include/clks/userland.h
Normal file
8
clks/include/clks/userland.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef CLKS_USERLAND_H
|
||||||
|
#define CLKS_USERLAND_H
|
||||||
|
|
||||||
|
#include <clks/types.h>
|
||||||
|
|
||||||
|
clks_bool clks_userland_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <clks/syscall.h>
|
#include <clks/syscall.h>
|
||||||
#include <clks/tty.h>
|
#include <clks/tty.h>
|
||||||
#include <clks/types.h>
|
#include <clks/types.h>
|
||||||
|
#include <clks/userland.h>
|
||||||
|
|
||||||
void clks_kernel_main(void) {
|
void clks_kernel_main(void) {
|
||||||
const struct limine_framebuffer *boot_fb;
|
const struct limine_framebuffer *boot_fb;
|
||||||
@@ -39,7 +40,7 @@ void clks_kernel_main(void) {
|
|||||||
clks_tty_init();
|
clks_tty_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE6 START");
|
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE7 START");
|
||||||
|
|
||||||
if (boot_fb == CLKS_NULL) {
|
if (boot_fb == CLKS_NULL) {
|
||||||
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
||||||
@@ -101,6 +102,11 @@ void clks_kernel_main(void) {
|
|||||||
clks_cpu_halt_forever();
|
clks_cpu_halt_forever();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (clks_userland_init() == CLKS_FALSE) {
|
||||||
|
clks_log(CLKS_LOG_ERROR, "USER", "USERLAND INIT FAILED");
|
||||||
|
clks_cpu_halt_forever();
|
||||||
|
}
|
||||||
|
|
||||||
clks_scheduler_init();
|
clks_scheduler_init();
|
||||||
|
|
||||||
if (clks_scheduler_add_kernel_task("klogd", 4U) == CLKS_FALSE) {
|
if (clks_scheduler_add_kernel_task("klogd", 4U) == CLKS_FALSE) {
|
||||||
@@ -133,4 +139,3 @@ void clks_kernel_main(void) {
|
|||||||
|
|
||||||
clks_cpu_halt_forever();
|
clks_cpu_halt_forever();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
49
clks/kernel/userland.c
Normal file
49
clks/kernel/userland.c
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#include <clks/elf64.h>
|
||||||
|
#include <clks/fs.h>
|
||||||
|
#include <clks/log.h>
|
||||||
|
#include <clks/types.h>
|
||||||
|
#include <clks/userland.h>
|
||||||
|
|
||||||
|
static clks_bool clks_userland_probe_elf(const char *path, const char *tag) {
|
||||||
|
const void *image;
|
||||||
|
u64 size = 0ULL;
|
||||||
|
struct clks_elf64_info info;
|
||||||
|
|
||||||
|
image = clks_fs_read_all(path, &size);
|
||||||
|
|
||||||
|
if (image == CLKS_NULL) {
|
||||||
|
clks_log(CLKS_LOG_ERROR, "USER", "ELF FILE MISSING");
|
||||||
|
clks_log(CLKS_LOG_ERROR, "USER", path);
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_elf64_inspect(image, size, &info) == CLKS_FALSE) {
|
||||||
|
clks_log(CLKS_LOG_ERROR, "USER", "ELF INSPECT FAILED");
|
||||||
|
clks_log(CLKS_LOG_ERROR, "USER", path);
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_log(CLKS_LOG_INFO, "USER", tag);
|
||||||
|
clks_log_hex(CLKS_LOG_INFO, "USER", "ELF_SIZE", size);
|
||||||
|
clks_log_hex(CLKS_LOG_INFO, "USER", "ENTRY", info.entry);
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_bool clks_userland_init(void) {
|
||||||
|
clks_log(CLKS_LOG_INFO, "USER", "USERLAND FRAMEWORK ONLINE");
|
||||||
|
|
||||||
|
if (clks_userland_probe_elf("/shell/shell.elf", "SHELL ELF READY") == CLKS_FALSE) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_userland_probe_elf("/system/elfrunner.elf", "ELFRUNNER ELF READY") == CLKS_FALSE) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clks_userland_probe_elf("/system/memc.elf", "MEMC ELF READY") == CLKS_FALSE) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
39
docs/stage7.md
Normal file
39
docs/stage7.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# CLeonOS Stage7
|
||||||
|
|
||||||
|
## Stage Goal
|
||||||
|
- Add user-space foundation under `/cleonos/` with C + Rust mixed development.
|
||||||
|
- Build first ELF app set: `/shell/shell.elf`, `/system/elfrunner.elf`, `/system/memc.elf`.
|
||||||
|
- Add user syscall wrapper (`int 0x80`) and minimal user runtime entry (`_start`).
|
||||||
|
- Integrate user ELF packaging into ramdisk build pipeline.
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
- Kernel boots and prints `CLEONOS STAGE7 START`.
|
||||||
|
- FS and userland framework initialize without panic.
|
||||||
|
- Kernel logs `USERLAND FRAMEWORK ONLINE`.
|
||||||
|
- Kernel can probe and inspect all required ELF files:
|
||||||
|
- `/shell/shell.elf`
|
||||||
|
- `/system/elfrunner.elf`
|
||||||
|
- `/system/memc.elf`
|
||||||
|
- `make userapps` outputs 3 ELF files and `make iso` packs them into ramdisk.
|
||||||
|
|
||||||
|
## 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
|
||||||
|
- `missing tool: rustc` in `make setup`:
|
||||||
|
- Install Rust toolchain or set `RUSTC` to valid executable path.
|
||||||
|
- User ELF linking fails:
|
||||||
|
- Verify `USER_CC`, `USER_LD`, and `cleonos/c/user.ld` are valid.
|
||||||
|
- `USERLAND INIT FAILED` at boot:
|
||||||
|
- Confirm ramdisk contains `shell.elf`, `elfrunner.elf`, `memc.elf` in expected directories.
|
||||||
|
- `ELF INSPECT FAILED` on user files:
|
||||||
|
- Ensure built apps are ELF64 and not stripped into unsupported format.
|
||||||
|
- Ramdisk missing user apps:
|
||||||
|
- Run `make userapps` then `make iso`; check staging path `build/x86_64/ramdisk_root`.
|
||||||
Reference in New Issue
Block a user