初始化

This commit is contained in:
2026-04-09 21:47:13 +08:00
commit cb952965e6
37 changed files with 1304 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
build/
*.iso
*.tar

226
Makefile Normal file
View File

@@ -0,0 +1,226 @@
.RECIPEPREFIX := >
NO_COLOR ?= 0
BUILD_ROOT := build/x86_64
OBJ_ROOT := $(BUILD_ROOT)/obj
ISO_ROOT := $(BUILD_ROOT)/iso_root
KERNEL_ELF := $(BUILD_ROOT)/clks_kernel.elf
RAMDISK_IMAGE := $(BUILD_ROOT)/cleonos_ramdisk.tar
ISO_IMAGE := build/CLeonOS-x86_64.iso
LIMINE_DIR ?= limine
LIMINE_REPO ?= https://gh-proxy.com/https://github.com/limine-bootloader/limine.git
LIMINE_REF ?=
LIMINE_BIN_DIR ?= $(LIMINE_DIR)/bin
LIMINE_SETUP_STAMP := $(LIMINE_DIR)/.cleonos-limine-setup.stamp
LIMINE_BUILD_STAMP := $(LIMINE_DIR)/.cleonos-limine-build.stamp
LIMINE_CONFIGURE_FLAGS ?= --enable-bios-cd --enable-uefi-cd --enable-uefi-x86-64
LIMINE_SKIP_CONFIGURE ?= 0
OBJCOPY_FOR_TARGET ?= llvm-objcopy
OBJDUMP_FOR_TARGET ?= llvm-objdump
READELF_FOR_TARGET ?= llvm-readelf
XORRISO ?= xorriso
TAR ?= tar
QEMU_X86_64 ?= qemu-system-x86_64
CC ?= x86_64-elf-gcc
LD ?= x86_64-elf-ld
ARCH_CFLAGS := -DCLKS_ARCH_X86_64=1 -m64 -mno-red-zone -mcmodel=kernel -fno-pic -fno-pie
LINKER_SCRIPT := clks/arch/x86_64/linker.ld
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
ifeq ($(NO_COLOR),1)
COLOR_RESET :=
COLOR_INFO :=
COLOR_WARN :=
COLOR_ERROR :=
COLOR_STEP :=
else
COLOR_RESET := \033[0m
COLOR_INFO := \033[1;36m
COLOR_WARN := \033[1;33m
COLOR_ERROR := \033[1;31m
COLOR_STEP := \033[1;35m
endif
define log_info
@printf '%b\n' "$(COLOR_INFO)[INFO]$(COLOR_RESET) $(1)"
endef
define log_warn
@printf '%b\n' "$(COLOR_WARN)[WARN]$(COLOR_RESET) $(1)"
endef
define log_error
@printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) $(1)"
endef
define log_step
@printf '%b\n' "$(COLOR_STEP)[STEP]$(COLOR_RESET) $(1)"
endef
SOURCES := \
clks/kernel/kmain.c \
clks/kernel/log.c \
clks/kernel/limine_requests.c \
clks/kernel/tty.c \
clks/lib/string.c \
clks/drivers/serial/serial.c \
clks/drivers/video/framebuffer.c \
clks/drivers/video/font8x8.c \
clks/arch/x86_64/boot.c
OBJECTS := $(patsubst %.c,$(OBJ_ROOT)/%.o,$(SOURCES))
CFLAGS_COMMON := -std=c11 -ffreestanding -fno-stack-protector -fno-builtin -Wall -Wextra -Werror -Iclks/include
LDFLAGS_COMMON := -nostdlib -z max-page-size=0x1000
.PHONY: all setup setup-tools setup-limine kernel ramdisk iso run debug clean clean-all help
all: iso
setup: setup-tools setup-limine
> $(call log_info,environment ready)
setup-tools:
> $(call log_step,checking host tools)
> @command -v git >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: git" && exit 1)
> @command -v $(TAR) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(TAR)" && exit 1)
> @command -v $(XORRISO) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(XORRISO)" && exit 1)
> @command -v clang >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: clang" && exit 1)
> @command -v ld.lld >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: ld.lld" && 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 $(READELF_FOR_TARGET) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(READELF_FOR_TARGET)" && exit 1)
> $(call log_info,required tools are available)
setup-limine:
> $(call log_step,preparing limine)
> @if [ ! -d "$(LIMINE_DIR)" ]; then \
> if [ -n "$(LIMINE_REF)" ]; then \
> printf '%b\n' "$(COLOR_INFO)[INFO]$(COLOR_RESET) cloning limine ($(LIMINE_REF)) into $(LIMINE_DIR)"; \
> git clone --branch "$(LIMINE_REF)" --depth 1 "$(LIMINE_REPO)" "$(LIMINE_DIR)"; \
> else \
> printf '%b\n' "$(COLOR_INFO)[INFO]$(COLOR_RESET) cloning limine (default branch) into $(LIMINE_DIR)"; \
> git clone --depth 1 "$(LIMINE_REPO)" "$(LIMINE_DIR)"; \
> fi; \
> fi
> @if [ "$(LIMINE_SKIP_CONFIGURE)" = "1" ]; then \
> test -f "$(LIMINE_DIR)/Makefile" || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) LIMINE_SKIP_CONFIGURE=1 but $(LIMINE_DIR)/Makefile is missing" && exit 1); \
> printf '%b\n' "$(COLOR_WARN)[WARN]$(COLOR_RESET) skipping limine Makefile generation (LIMINE_SKIP_CONFIGURE=1)"; \
> else \
> cfg_fingerprint="FLAGS=$(LIMINE_CONFIGURE_FLAGS);OBJCOPY=$(OBJCOPY_FOR_TARGET);OBJDUMP=$(OBJDUMP_FOR_TARGET);READELF=$(READELF_FOR_TARGET)"; \
> need_configure=0; \
> if [ ! -f "$(LIMINE_DIR)/Makefile" ]; then need_configure=1; fi; \
> if [ ! -f "$(LIMINE_SETUP_STAMP)" ]; then need_configure=1; fi; \
> if [ -f "$(LIMINE_SETUP_STAMP)" ] && ! grep -qx "$$cfg_fingerprint" "$(LIMINE_SETUP_STAMP)"; then need_configure=1; fi; \
> if [ "$$need_configure" -eq 1 ]; then \
> printf '%b\n' "$(COLOR_STEP)[STEP]$(COLOR_RESET) generating/reconfiguring limine Makefile"; \
> if [ -x "$(LIMINE_DIR)/bootstrap" ]; then \
> (cd "$(LIMINE_DIR)" && ./bootstrap); \
> fi; \
> test -x "$(LIMINE_DIR)/configure" || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) limine configure script missing" && exit 1); \
> (cd "$(LIMINE_DIR)" && OBJCOPY_FOR_TARGET="$(OBJCOPY_FOR_TARGET)" OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)" READELF_FOR_TARGET="$(READELF_FOR_TARGET)" ./configure $(LIMINE_CONFIGURE_FLAGS)); \
> printf '%s\n' "$$cfg_fingerprint" > "$(LIMINE_SETUP_STAMP)"; \
> rm -f "$(LIMINE_BUILD_STAMP)"; \
> else \
> printf '%b\n' "$(COLOR_INFO)[INFO]$(COLOR_RESET) limine configure state unchanged"; \
> fi; \
> fi
> @need_build=0; \
> if [ ! -f "$(LIMINE_BUILD_STAMP)" ]; then need_build=1; fi; \
> for f in limine limine-bios.sys limine-bios-cd.bin limine-uefi-cd.bin; do \
> if [ ! -f "$(LIMINE_BIN_DIR)/$$f" ]; then need_build=1; fi; \
> done; \
> if [ "$$need_build" -eq 1 ]; then \
> printf '%b\n' "$(COLOR_INFO)[INFO]$(COLOR_RESET) building limine"; \
> $(MAKE) -C "$(LIMINE_DIR)"; \
> touch "$(LIMINE_BUILD_STAMP)"; \
> else \
> printf '%b\n' "$(COLOR_INFO)[INFO]$(COLOR_RESET) limine already built, skipping compile"; \
> fi
> @test -f "$(LIMINE_BIN_DIR)/limine" || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) limine build failed" && exit 1)
> @test -f "$(LIMINE_BIN_DIR)/limine-bios.sys" || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) limine-bios.sys missing" && exit 1)
> @test -f "$(LIMINE_BIN_DIR)/limine-bios-cd.bin" || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) limine-bios-cd.bin missing" && exit 1)
> @test -f "$(LIMINE_BIN_DIR)/limine-uefi-cd.bin" || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) limine-uefi-cd.bin missing" && exit 1)
> $(call log_info,limine artifacts ready)
kernel: $(KERNEL_ELF)
ramdisk: $(RAMDISK_IMAGE)
$(KERNEL_ELF): $(OBJECTS) $(LINKER_SCRIPT) Makefile
> $(call log_step,linking kernel -> $(KERNEL_ELF))
> @mkdir -p $(dir $@)
> @$(LD) $(LDFLAGS_COMMON) -T $(LINKER_SCRIPT) -o $@ $(OBJECTS)
$(OBJ_ROOT)/%.o: %.c Makefile
> $(call log_step,compiling $<)
> @mkdir -p $(dir $@)
> @$(CC) $(CFLAGS_COMMON) $(ARCH_CFLAGS) -c $< -o $@
$(RAMDISK_IMAGE):
> $(call log_step,packing ramdisk -> $(RAMDISK_IMAGE))
> @mkdir -p $(dir $@)
> @$(TAR) -C ramdisk -cf $@ .
iso: setup-tools setup-limine $(KERNEL_ELF) $(RAMDISK_IMAGE) configs/limine.conf
> $(call log_step,assembling iso root)
> @rm -rf $(ISO_ROOT)
> @mkdir -p $(ISO_ROOT)/boot/limine
> @cp $(KERNEL_ELF) $(ISO_ROOT)/boot/clks_kernel.elf
> @cp $(RAMDISK_IMAGE) $(ISO_ROOT)/boot/cleonos_ramdisk.tar
> @cp configs/limine.conf $(ISO_ROOT)/boot/limine/limine.conf
> @cp $(LIMINE_BIN_DIR)/limine-bios.sys $(ISO_ROOT)/boot/limine/
> @cp $(LIMINE_BIN_DIR)/limine-bios-cd.bin $(ISO_ROOT)/boot/limine/
> @cp $(LIMINE_BIN_DIR)/limine-uefi-cd.bin $(ISO_ROOT)/boot/limine/
> @mkdir -p $(dir $(ISO_IMAGE))
> $(call log_step,building iso -> $(ISO_IMAGE))
> @$(XORRISO) -as mkisofs \
> -b boot/limine/limine-bios-cd.bin \
> -no-emul-boot \
> -boot-load-size 4 \
> -boot-info-table \
> --efi-boot boot/limine/limine-uefi-cd.bin \
> -efi-boot-part \
> --efi-boot-image \
> --protective-msdos-label \
> $(ISO_ROOT) \
> -o $(ISO_IMAGE)
> $(call log_step,installing limine boot sectors)
> @$(LIMINE_BIN_DIR)/limine bios-install $(ISO_IMAGE)
> $(call log_info,iso ready: $(ISO_IMAGE))
run: iso
> $(call log_step,launching qemu run)
> @$(RUN_COMMAND)
debug: iso
> $(call log_step,launching qemu debug (-s -S))
> @$(DEBUG_COMMAND)
clean:
> $(call log_step,cleaning $(BUILD_ROOT))
> @rm -rf $(BUILD_ROOT)
> $(call log_info,clean done)
clean-all:
> $(call log_step,cleaning build)
> @rm -rf build
> $(call log_info,clean-all done)
help:
> @echo "CLeonOS build system (x86_64 only)"
> @echo " make setup"
> @echo " make setup LIMINE_REF=<branch-or-tag>"
> @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 OBJCOPY_FOR_TARGET=llvm-objcopy OBJDUMP_FOR_TARGET=llvm-objdump READELF_FOR_TARGET=llvm-readelf"
> @echo " make iso"
> @echo " make run"
> @echo " make debug"
> @echo " make NO_COLOR=1 <target>"

8
cleonos/c/stub.c Normal file
View File

@@ -0,0 +1,8 @@
/*
* CLeonOS user-space C toolchain stub.
* Stage1 only defines build skeleton. Real shell/user ELF apps start in later stages.
*/
int cleonos_c_stub(void) {
return 0;
}

13
cleonos/rust/Cargo.toml Normal file
View File

@@ -0,0 +1,13 @@
[package]
name = "cleonos_user"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

6
cleonos/rust/src/lib.rs Normal file
View File

@@ -0,0 +1,6 @@
#![no_std]
#[no_mangle]
pub extern "C" fn cleonos_rust_stub() -> u64 {
0
}

7
clks/arch/aarch64/boot.c Normal file
View File

@@ -0,0 +1,7 @@
#include <clks/cpu.h>
#include <clks/kernel.h>
void _start(void) {
clks_kernel_main();
clks_cpu_halt_forever();
}

View File

@@ -0,0 +1,38 @@
OUTPUT_FORMAT(elf64-littleaarch64)
ENTRY(_start)
PHDRS {
text PT_LOAD FLAGS(5);
rodata PT_LOAD FLAGS(4);
data PT_LOAD FLAGS(6);
}
SECTIONS {
. = 0x100000;
.text : {
*(.text .text.*)
} :text
.rodata : {
KEEP(*(.limine_requests_start))
KEEP(*(.limine_requests))
KEEP(*(.limine_requests_end))
*(.rodata .rodata.*)
} :rodata
.data : {
*(.data .data.*)
} :data
.bss : {
*(COMMON)
*(.bss .bss.*)
} :data
/DISCARD/ : {
*(.comment)
*(.eh_frame)
*(.note .note.*)
}
}

7
clks/arch/x86_64/boot.c Normal file
View File

@@ -0,0 +1,7 @@
#include <clks/cpu.h>
#include <clks/kernel.h>
void _start(void) {
clks_kernel_main();
clks_cpu_halt_forever();
}

View File

@@ -0,0 +1,42 @@
OUTPUT_FORMAT(elf64-x86-64)
ENTRY(_start)
PHDRS {
text PT_LOAD FLAGS(5);
rodata PT_LOAD FLAGS(4);
data PT_LOAD FLAGS(6);
}
SECTIONS {
. = 0xffffffff80000000;
. = ALIGN(0x1000);
.text : ALIGN(0x1000) {
*(.text .text.*)
} :text
. = ALIGN(0x1000);
.rodata : ALIGN(0x1000) {
KEEP(*(.limine_requests_start))
KEEP(*(.limine_requests))
KEEP(*(.limine_requests_end))
*(.rodata .rodata.*)
} :rodata
. = ALIGN(0x1000);
.data : ALIGN(0x1000) {
*(.data .data.*)
} :data
. = ALIGN(0x1000);
.bss : ALIGN(0x1000) {
*(COMMON)
*(.bss .bss.*)
} :data
/DISCARD/ : {
*(.comment)
*(.eh_frame)
*(.note .note.*)
}
}

View File

@@ -0,0 +1,68 @@
#include <clks/compiler.h>
#include <clks/serial.h>
#include <clks/types.h>
#if defined(CLKS_ARCH_X86_64)
#define CLKS_COM1_PORT 0x3F8
static inline void clks_x86_outb(u16 port, u8 value) {
__asm__ volatile("outb %0, %1" : : "a"(value), "Nd"(port));
}
static inline u8 clks_x86_inb(u16 port) {
u8 value;
__asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
void clks_serial_init(void) {
clks_x86_outb(CLKS_COM1_PORT + 1, 0x00);
clks_x86_outb(CLKS_COM1_PORT + 3, 0x80);
clks_x86_outb(CLKS_COM1_PORT + 0, 0x03);
clks_x86_outb(CLKS_COM1_PORT + 1, 0x00);
clks_x86_outb(CLKS_COM1_PORT + 3, 0x03);
clks_x86_outb(CLKS_COM1_PORT + 2, 0xC7);
clks_x86_outb(CLKS_COM1_PORT + 4, 0x0B);
}
void clks_serial_write_char(char ch) {
while ((clks_x86_inb(CLKS_COM1_PORT + 5) & 0x20) == 0) {
}
clks_x86_outb(CLKS_COM1_PORT, (u8)ch);
}
#elif defined(CLKS_ARCH_AARCH64)
#define CLKS_PL011_BASE 0x09000000ULL
#define CLKS_PL011_DR (*(volatile u32 *)(CLKS_PL011_BASE + 0x00))
#define CLKS_PL011_FR (*(volatile u32 *)(CLKS_PL011_BASE + 0x18))
#define CLKS_PL011_TXFF (1U << 5)
void clks_serial_init(void) {
}
void clks_serial_write_char(char ch) {
while ((CLKS_PL011_FR & CLKS_PL011_TXFF) != 0) {
}
CLKS_PL011_DR = (u32)(u8)ch;
}
#else
#error "Unsupported architecture"
#endif
void clks_serial_write(const char *text) {
usize i = 0;
while (text[i] != '\0') {
if (text[i] == '\n') {
clks_serial_write_char('\r');
}
clks_serial_write_char(text[i]);
i++;
}
}

View File

@@ -0,0 +1,75 @@
#include "font8x8.h"
#include <clks/types.h>
struct clks_glyph8x8 {
char ch;
u8 rows[8];
};
static const struct clks_glyph8x8 clks_font_table[] = {
{' ', {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
{'[', {0x1E, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x00}},
{']', {0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00}},
{':', {0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00}},
{'.', {0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00}},
{'-', {0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00}},
{'/', {0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00}},
{'_', {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00}},
{'?', {0x3C, 0x42, 0x02, 0x0C, 0x10, 0x00, 0x10, 0x00}},
{'0', {0x3C, 0x42, 0x46, 0x4A, 0x52, 0x62, 0x3C, 0x00}},
{'1', {0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00}},
{'2', {0x3C, 0x42, 0x02, 0x0C, 0x30, 0x40, 0x7E, 0x00}},
{'3', {0x3C, 0x42, 0x02, 0x1C, 0x02, 0x42, 0x3C, 0x00}},
{'4', {0x0C, 0x14, 0x24, 0x44, 0x7E, 0x04, 0x04, 0x00}},
{'5', {0x7E, 0x40, 0x7C, 0x02, 0x02, 0x42, 0x3C, 0x00}},
{'6', {0x1C, 0x20, 0x40, 0x7C, 0x42, 0x42, 0x3C, 0x00}},
{'7', {0x7E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00}},
{'8', {0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x3C, 0x00}},
{'9', {0x3C, 0x42, 0x42, 0x3E, 0x02, 0x04, 0x38, 0x00}},
{'A', {0x18, 0x24, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00}},
{'B', {0x7C, 0x42, 0x42, 0x7C, 0x42, 0x42, 0x7C, 0x00}},
{'C', {0x3C, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3C, 0x00}},
{'D', {0x78, 0x44, 0x42, 0x42, 0x42, 0x44, 0x78, 0x00}},
{'E', {0x7E, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x7E, 0x00}},
{'F', {0x7E, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x00}},
{'G', {0x3C, 0x42, 0x40, 0x4E, 0x42, 0x42, 0x3C, 0x00}},
{'H', {0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00}},
{'I', {0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00}},
{'J', {0x1E, 0x04, 0x04, 0x04, 0x44, 0x44, 0x38, 0x00}},
{'K', {0x42, 0x44, 0x48, 0x70, 0x48, 0x44, 0x42, 0x00}},
{'L', {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7E, 0x00}},
{'M', {0x42, 0x66, 0x5A, 0x5A, 0x42, 0x42, 0x42, 0x00}},
{'N', {0x42, 0x62, 0x52, 0x4A, 0x46, 0x42, 0x42, 0x00}},
{'O', {0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00}},
{'P', {0x7C, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x40, 0x00}},
{'Q', {0x3C, 0x42, 0x42, 0x42, 0x4A, 0x44, 0x3A, 0x00}},
{'R', {0x7C, 0x42, 0x42, 0x7C, 0x48, 0x44, 0x42, 0x00}},
{'S', {0x3C, 0x42, 0x40, 0x3C, 0x02, 0x42, 0x3C, 0x00}},
{'T', {0x7F, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00}},
{'U', {0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00}},
{'V', {0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00}},
{'W', {0x42, 0x42, 0x42, 0x5A, 0x5A, 0x66, 0x42, 0x00}},
{'X', {0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x00}},
{'Y', {0x42, 0x42, 0x24, 0x18, 0x08, 0x08, 0x08, 0x00}},
{'Z', {0x7E, 0x02, 0x04, 0x18, 0x20, 0x40, 0x7E, 0x00}},
};
static const u8 clks_unknown[8] = {0x3C, 0x42, 0x02, 0x0C, 0x10, 0x00, 0x10, 0x00};
const u8 *clks_font8x8_get(char ch) {
usize i;
char upper = ch;
if (upper >= 'a' && upper <= 'z') {
upper = (char)(upper - ('a' - 'A'));
}
for (i = 0; i < (sizeof(clks_font_table) / sizeof(clks_font_table[0])); i++) {
if (clks_font_table[i].ch == upper) {
return clks_font_table[i].rows;
}
}
return clks_unknown;
}

View File

@@ -0,0 +1,8 @@
#ifndef CLKS_FONT8X8_H
#define CLKS_FONT8X8_H
#include <clks/types.h>
const u8 *clks_font8x8_get(char ch);
#endif

View File

@@ -0,0 +1,95 @@
#include <clks/framebuffer.h>
#include <clks/string.h>
#include <clks/types.h>
#include "font8x8.h"
struct clks_fb_state {
volatile u8 *address;
struct clks_framebuffer_info info;
clks_bool ready;
};
static struct clks_fb_state clks_fb = {
.address = CLKS_NULL,
.info = {0, 0, 0, 0},
.ready = CLKS_FALSE,
};
static void clks_fb_put_pixel(u32 x, u32 y, u32 rgb) {
volatile u8 *row;
volatile u32 *pixel;
if (clks_fb.ready == CLKS_FALSE) {
return;
}
if (x >= clks_fb.info.width || y >= clks_fb.info.height) {
return;
}
if (clks_fb.info.bpp != 32) {
return;
}
row = clks_fb.address + ((usize)y * (usize)clks_fb.info.pitch);
pixel = (volatile u32 *)(row + ((usize)x * 4));
*pixel = rgb;
}
void clks_fb_init(const struct limine_framebuffer *fb) {
if (fb == CLKS_NULL) {
clks_fb.ready = CLKS_FALSE;
return;
}
clks_fb.address = (volatile u8 *)fb->address;
clks_fb.info.width = (u32)fb->width;
clks_fb.info.height = (u32)fb->height;
clks_fb.info.pitch = (u32)fb->pitch;
clks_fb.info.bpp = fb->bpp;
clks_fb.ready = CLKS_TRUE;
}
clks_bool clks_fb_ready(void) {
return clks_fb.ready;
}
struct clks_framebuffer_info clks_fb_info(void) {
return clks_fb.info;
}
void clks_fb_clear(u32 rgb) {
u32 x;
u32 y;
if (clks_fb.ready == CLKS_FALSE) {
return;
}
for (y = 0; y < clks_fb.info.height; y++) {
for (x = 0; x < clks_fb.info.width; x++) {
clks_fb_put_pixel(x, y, rgb);
}
}
}
void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb) {
const u8 *glyph;
u32 row;
u32 col;
if (clks_fb.ready == CLKS_FALSE) {
return;
}
glyph = clks_font8x8_get(ch);
for (row = 0; row < 8; row++) {
for (col = 0; col < 8; col++) {
u8 mask = (u8)(1U << (7U - col));
u32 color = (glyph[row] & mask) != 0 ? fg_rgb : bg_rgb;
clks_fb_put_pixel(x + col, y + row, color);
}
}
}

10
clks/include/clks/boot.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef CLKS_BOOT_H
#define CLKS_BOOT_H
#include <clks/limine.h>
#include <clks/types.h>
clks_bool clks_boot_base_revision_supported(void);
const struct limine_framebuffer *clks_boot_get_framebuffer(void);
#endif

View File

@@ -0,0 +1,17 @@
#ifndef CLKS_COMPILER_H
#define CLKS_COMPILER_H
#define CLKS_USED __attribute__((used))
#define CLKS_NORETURN __attribute__((noreturn))
#define CLKS_PACKED __attribute__((packed))
#define CLKS_ALIGN(N) __attribute__((aligned(N)))
#if defined(CLKS_ARCH_X86_64) && defined(CLKS_ARCH_AARCH64)
#error "Only one architecture can be selected"
#endif
#if !defined(CLKS_ARCH_X86_64) && !defined(CLKS_ARCH_AARCH64)
#error "Missing architecture define: CLKS_ARCH_X86_64 or CLKS_ARCH_AARCH64"
#endif
#endif

24
clks/include/clks/cpu.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef CLKS_CPU_H
#define CLKS_CPU_H
#include <clks/compiler.h>
static inline void clks_cpu_pause(void) {
#if defined(CLKS_ARCH_X86_64)
__asm__ volatile("pause");
#elif defined(CLKS_ARCH_AARCH64)
__asm__ volatile("yield");
#endif
}
static inline CLKS_NORETURN void clks_cpu_halt_forever(void) {
for (;;) {
#if defined(CLKS_ARCH_X86_64)
__asm__ volatile("hlt");
#elif defined(CLKS_ARCH_AARCH64)
__asm__ volatile("wfe");
#endif
}
}
#endif

View File

@@ -0,0 +1,20 @@
#ifndef CLKS_FRAMEBUFFER_H
#define CLKS_FRAMEBUFFER_H
#include <clks/limine.h>
#include <clks/types.h>
struct clks_framebuffer_info {
u32 width;
u32 height;
u32 pitch;
u16 bpp;
};
void clks_fb_init(const struct limine_framebuffer *fb);
clks_bool clks_fb_ready(void);
struct clks_framebuffer_info clks_fb_info(void);
void clks_fb_clear(u32 rgb);
void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb);
#endif

View File

@@ -0,0 +1,6 @@
#ifndef CLKS_KERNEL_H
#define CLKS_KERNEL_H
void clks_kernel_main(void);
#endif

View File

@@ -0,0 +1,56 @@
#ifndef CLKS_LIMINE_H
#define CLKS_LIMINE_H
#include <clks/types.h>
#define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88ULL
#define LIMINE_REQUEST_MAGIC 0x0a82e883a194f07bULL
#define LIMINE_REQUESTS_START_MARKER \
{ 0xf6b8f4b39de7d1aeULL, 0xfab91a6940fcb9cfULL }
#define LIMINE_REQUESTS_END_MARKER \
{ 0xadc0e0531bb10d03ULL, 0x9572709f31764c62ULL }
#define LIMINE_BASE_REVISION(N) \
{ 0xf9562b2d5c95a6c8ULL, 0x6a7b384944536bdcULL, (N) }
#define LIMINE_FRAMEBUFFER_REQUEST \
{ \
LIMINE_COMMON_MAGIC, \
LIMINE_REQUEST_MAGIC, \
0x9d5827dcd881dd75ULL, \
0xa3148604f6fab11bULL \
}
struct limine_framebuffer {
void *address;
u64 width;
u64 height;
u64 pitch;
u16 bpp;
u8 memory_model;
u8 red_mask_size;
u8 red_mask_shift;
u8 green_mask_size;
u8 green_mask_shift;
u8 blue_mask_size;
u8 blue_mask_shift;
u8 unused[7];
u64 edid_size;
void *edid;
};
struct limine_framebuffer_response {
u64 revision;
u64 framebuffer_count;
struct limine_framebuffer **framebuffers;
};
struct limine_framebuffer_request {
u64 id[4];
u64 revision;
struct limine_framebuffer_response *response;
};
#endif

16
clks/include/clks/log.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef CLKS_LOG_H
#define CLKS_LOG_H
#include <clks/types.h>
enum clks_log_level {
CLKS_LOG_DEBUG = 0,
CLKS_LOG_INFO = 1,
CLKS_LOG_WARN = 2,
CLKS_LOG_ERROR = 3,
};
void clks_log(enum clks_log_level level, const char *tag, const char *message);
void clks_log_hex(enum clks_log_level level, const char *tag, const char *label, u64 value);
#endif

View File

@@ -0,0 +1,8 @@
#ifndef CLKS_SERIAL_H
#define CLKS_SERIAL_H
void clks_serial_init(void);
void clks_serial_write_char(char ch);
void clks_serial_write(const char *text);
#endif

View File

@@ -0,0 +1,12 @@
#ifndef CLKS_STRING_H
#define CLKS_STRING_H
#include <clks/types.h>
usize clks_strlen(const char *str);
void *clks_memset(void *dst, int value, usize count);
void *clks_memcpy(void *dst, const void *src, usize count);
void *clks_memmove(void *dst, const void *src, usize count);
int clks_strcmp(const char *left, const char *right);
#endif

12
clks/include/clks/tty.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef CLKS_TTY_H
#define CLKS_TTY_H
#include <clks/types.h>
void clks_tty_init(void);
void clks_tty_write(const char *text);
void clks_tty_write_char(char ch);
void clks_tty_switch(u32 tty_index);
u32 clks_tty_active(void);
#endif

23
clks/include/clks/types.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef CLKS_TYPES_H
#define CLKS_TYPES_H
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef signed char i8;
typedef signed short i16;
typedef signed int i32;
typedef signed long long i64;
typedef u64 usize;
typedef enum clks_bool {
CLKS_FALSE = 0,
CLKS_TRUE = 1
} clks_bool;
#define CLKS_NULL ((void *)0)
#endif

48
clks/kernel/kmain.c Normal file
View File

@@ -0,0 +1,48 @@
#include <clks/boot.h>
#include <clks/cpu.h>
#include <clks/framebuffer.h>
#include <clks/kernel.h>
#include <clks/log.h>
#include <clks/serial.h>
#include <clks/tty.h>
#include <clks/types.h>
void clks_kernel_main(void) {
const struct limine_framebuffer *boot_fb;
clks_serial_init();
if (clks_boot_base_revision_supported() == CLKS_FALSE) {
clks_serial_write("[ERROR][BOOT] LIMINE BASE REVISION NOT SUPPORTED\n");
clks_cpu_halt_forever();
}
boot_fb = clks_boot_get_framebuffer();
if (boot_fb != CLKS_NULL) {
clks_fb_init(boot_fb);
clks_tty_init();
}
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE1 START");
if (boot_fb == CLKS_NULL) {
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
} else {
clks_log_hex(CLKS_LOG_INFO, "VIDEO", "WIDTH", boot_fb->width);
clks_log_hex(CLKS_LOG_INFO, "VIDEO", "HEIGHT", boot_fb->height);
clks_log_hex(CLKS_LOG_INFO, "VIDEO", "PITCH", boot_fb->pitch);
clks_log_hex(CLKS_LOG_INFO, "VIDEO", "BPP", boot_fb->bpp);
}
#if defined(CLKS_ARCH_X86_64)
clks_log(CLKS_LOG_INFO, "ARCH", "X86_64 ONLINE");
#elif defined(CLKS_ARCH_AARCH64)
clks_log(CLKS_LOG_INFO, "ARCH", "AARCH64 ONLINE");
#endif
clks_log(CLKS_LOG_INFO, "TTY", "VIRTUAL TTY0 READY");
clks_log(CLKS_LOG_DEBUG, "KERNEL", "IDLE LOOP ENTER");
clks_cpu_halt_forever();
}

View File

@@ -0,0 +1,36 @@
#include <clks/boot.h>
#include <clks/compiler.h>
CLKS_USED static volatile u64 limine_requests_start[]
__attribute__((section(".limine_requests_start"))) = LIMINE_REQUESTS_START_MARKER;
CLKS_USED static volatile u64 limine_base_revision[]
__attribute__((section(".limine_requests"))) = LIMINE_BASE_REVISION(3);
CLKS_USED static volatile struct limine_framebuffer_request limine_framebuffer_request
__attribute__((section(".limine_requests"))) = {
.id = LIMINE_FRAMEBUFFER_REQUEST,
.revision = 0,
.response = CLKS_NULL,
};
CLKS_USED static volatile u64 limine_requests_end[]
__attribute__((section(".limine_requests_end"))) = LIMINE_REQUESTS_END_MARKER;
clks_bool clks_boot_base_revision_supported(void) {
return (limine_base_revision[2] == 0) ? CLKS_TRUE : CLKS_FALSE;
}
const struct limine_framebuffer *clks_boot_get_framebuffer(void) {
volatile struct limine_framebuffer_request *request = &limine_framebuffer_request;
if (request->response == CLKS_NULL) {
return CLKS_NULL;
}
if (request->response->framebuffer_count < 1) {
return CLKS_NULL;
}
return request->response->framebuffers[0];
}

96
clks/kernel/log.c Normal file
View File

@@ -0,0 +1,96 @@
#include <clks/log.h>
#include <clks/serial.h>
#include <clks/tty.h>
#include <clks/types.h>
#define CLKS_LOG_LINE_MAX 256
static const char *clks_log_level_name(enum clks_log_level level) {
switch (level) {
case CLKS_LOG_DEBUG:
return "DEBUG";
case CLKS_LOG_INFO:
return "INFO";
case CLKS_LOG_WARN:
return "WARN";
case CLKS_LOG_ERROR:
return "ERROR";
default:
return "UNK";
}
}
static void clks_log_append_char(char *buffer, usize *cursor, char ch) {
if (*cursor >= (CLKS_LOG_LINE_MAX - 1)) {
return;
}
buffer[*cursor] = ch;
(*cursor)++;
}
static void clks_log_append_text(char *buffer, usize *cursor, const char *text) {
usize i = 0;
while (text[i] != '\0') {
clks_log_append_char(buffer, cursor, text[i]);
i++;
}
}
static void clks_log_append_hex_u64(char *buffer, usize *cursor, u64 value) {
int nibble;
clks_log_append_text(buffer, cursor, "0X");
for (nibble = 15; nibble >= 0; nibble--) {
u8 current = (u8)((value >> (nibble * 4)) & 0x0FULL);
char out = (current < 10) ? (char)('0' + current) : (char)('A' + (current - 10));
clks_log_append_char(buffer, cursor, out);
}
}
static void clks_log_emit_line(const char *line) {
clks_serial_write(line);
clks_serial_write("\n");
clks_tty_write(line);
clks_tty_write("\n");
}
void clks_log(enum clks_log_level level, const char *tag, const char *message) {
char line[CLKS_LOG_LINE_MAX];
usize cursor = 0;
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, clks_log_level_name(level));
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, tag);
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, ' ');
clks_log_append_text(line, &cursor, message);
line[cursor] = '\0';
clks_log_emit_line(line);
}
void clks_log_hex(enum clks_log_level level, const char *tag, const char *label, u64 value) {
char line[CLKS_LOG_LINE_MAX];
usize cursor = 0;
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, clks_log_level_name(level));
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, tag);
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, ' ');
clks_log_append_text(line, &cursor, label);
clks_log_append_char(line, &cursor, ':');
clks_log_append_char(line, &cursor, ' ');
clks_log_append_hex_u64(line, &cursor, value);
line[cursor] = '\0';
clks_log_emit_line(line);
}

194
clks/kernel/tty.c Normal file
View File

@@ -0,0 +1,194 @@
#include <clks/framebuffer.h>
#include <clks/string.h>
#include <clks/tty.h>
#include <clks/types.h>
#define CLKS_TTY_COUNT 4
#define CLKS_TTY_MAX_ROWS 128
#define CLKS_TTY_MAX_COLS 256
#define CLKS_TTY_FG 0x00E6E6E6U
#define CLKS_TTY_BG 0x00101010U
static char clks_tty_cells[CLKS_TTY_COUNT][CLKS_TTY_MAX_ROWS][CLKS_TTY_MAX_COLS];
static u32 clks_tty_cursor_row[CLKS_TTY_COUNT];
static u32 clks_tty_cursor_col[CLKS_TTY_COUNT];
static u32 clks_tty_rows = 0;
static u32 clks_tty_cols = 0;
static u32 clks_tty_active_index = 0;
static clks_bool clks_tty_is_ready = CLKS_FALSE;
static void clks_tty_fill_row(u32 tty_index, u32 row, char ch) {
u32 col;
for (col = 0; col < clks_tty_cols; col++) {
clks_tty_cells[tty_index][row][col] = ch;
}
}
static void clks_tty_draw_cell(u32 row, u32 col, char ch) {
clks_fb_draw_char(col * 8U, row * 8U, ch, CLKS_TTY_FG, CLKS_TTY_BG);
}
static void clks_tty_redraw_active(void) {
u32 row;
u32 col;
clks_fb_clear(CLKS_TTY_BG);
for (row = 0; row < clks_tty_rows; row++) {
for (col = 0; col < clks_tty_cols; col++) {
clks_tty_draw_cell(row, col, clks_tty_cells[clks_tty_active_index][row][col]);
}
}
}
static void clks_tty_scroll_up(u32 tty_index) {
u32 row;
for (row = 1; row < clks_tty_rows; row++) {
clks_memcpy(
clks_tty_cells[tty_index][row - 1],
clks_tty_cells[tty_index][row],
clks_tty_cols
);
}
clks_tty_fill_row(tty_index, clks_tty_rows - 1, ' ');
if (tty_index == clks_tty_active_index) {
clks_tty_redraw_active();
}
}
static void clks_tty_put_visible(u32 tty_index, u32 row, u32 col, char ch) {
clks_tty_cells[tty_index][row][col] = ch;
if (tty_index == clks_tty_active_index) {
clks_tty_draw_cell(row, col, ch);
}
}
void clks_tty_init(void) {
struct clks_framebuffer_info info;
u32 tty;
u32 row;
if (clks_fb_ready() == CLKS_FALSE) {
clks_tty_is_ready = CLKS_FALSE;
return;
}
info = clks_fb_info();
clks_tty_rows = info.height / 8U;
clks_tty_cols = info.width / 8U;
if (clks_tty_rows > CLKS_TTY_MAX_ROWS) {
clks_tty_rows = CLKS_TTY_MAX_ROWS;
}
if (clks_tty_cols > CLKS_TTY_MAX_COLS) {
clks_tty_cols = CLKS_TTY_MAX_COLS;
}
if (clks_tty_rows == 0 || clks_tty_cols == 0) {
clks_tty_is_ready = CLKS_FALSE;
return;
}
for (tty = 0; tty < CLKS_TTY_COUNT; tty++) {
clks_tty_cursor_row[tty] = 0;
clks_tty_cursor_col[tty] = 0;
for (row = 0; row < clks_tty_rows; row++) {
clks_tty_fill_row(tty, row, ' ');
}
}
clks_tty_active_index = 0;
clks_tty_is_ready = CLKS_TRUE;
clks_tty_redraw_active();
}
void clks_tty_write_char(char ch) {
u32 tty_index;
u32 row;
u32 col;
if (clks_tty_is_ready == CLKS_FALSE) {
return;
}
tty_index = clks_tty_active_index;
row = clks_tty_cursor_row[tty_index];
col = clks_tty_cursor_col[tty_index];
if (ch == '\r') {
clks_tty_cursor_col[tty_index] = 0;
return;
}
if (ch == '\n') {
clks_tty_cursor_col[tty_index] = 0;
clks_tty_cursor_row[tty_index]++;
if (clks_tty_cursor_row[tty_index] >= clks_tty_rows) {
clks_tty_scroll_up(tty_index);
clks_tty_cursor_row[tty_index] = clks_tty_rows - 1;
}
return;
}
if (ch == '\t') {
clks_tty_write_char(' ');
clks_tty_write_char(' ');
clks_tty_write_char(' ');
clks_tty_write_char(' ');
return;
}
clks_tty_put_visible(tty_index, row, col, ch);
clks_tty_cursor_col[tty_index]++;
if (clks_tty_cursor_col[tty_index] >= clks_tty_cols) {
clks_tty_cursor_col[tty_index] = 0;
clks_tty_cursor_row[tty_index]++;
if (clks_tty_cursor_row[tty_index] >= clks_tty_rows) {
clks_tty_scroll_up(tty_index);
clks_tty_cursor_row[tty_index] = clks_tty_rows - 1;
}
}
}
void clks_tty_write(const char *text) {
usize i = 0;
if (clks_tty_is_ready == CLKS_FALSE) {
return;
}
while (text[i] != '\0') {
clks_tty_write_char(text[i]);
i++;
}
}
void clks_tty_switch(u32 tty_index) {
if (clks_tty_is_ready == CLKS_FALSE) {
return;
}
if (tty_index >= CLKS_TTY_COUNT) {
return;
}
clks_tty_active_index = tty_index;
clks_tty_redraw_active();
}
u32 clks_tty_active(void) {
return clks_tty_active_index;
}

70
clks/lib/string.c Normal file
View File

@@ -0,0 +1,70 @@
#include <clks/string.h>
usize clks_strlen(const char *str) {
usize len = 0;
while (str[len] != '\0') {
len++;
}
return len;
}
void *clks_memset(void *dst, int value, usize count) {
u8 *d = (u8 *)dst;
u8 v = (u8)value;
usize i;
for (i = 0; i < count; i++) {
d[i] = v;
}
return dst;
}
void *clks_memcpy(void *dst, const void *src, usize count) {
u8 *d = (u8 *)dst;
const u8 *s = (const u8 *)src;
usize i;
for (i = 0; i < count; i++) {
d[i] = s[i];
}
return dst;
}
void *clks_memmove(void *dst, const void *src, usize count) {
u8 *d = (u8 *)dst;
const u8 *s = (const u8 *)src;
usize i;
if (d == s || count == 0) {
return dst;
}
if (d < s) {
for (i = 0; i < count; i++) {
d[i] = s[i];
}
} else {
for (i = count; i != 0; i--) {
d[i - 1] = s[i - 1];
}
}
return dst;
}
int clks_strcmp(const char *left, const char *right) {
usize i = 0;
while (left[i] != '\0' && right[i] != '\0') {
if (left[i] != right[i]) {
return (int)((u8)left[i] - (u8)right[i]);
}
i++;
}
return (int)((u8)left[i] - (u8)right[i]);
}

7
configs/limine.conf Normal file
View File

@@ -0,0 +1,7 @@
timeout: 3
verbose: yes
/CLeonOS Stage1
protocol: limine
kernel_path: boot():/boot/clks_kernel.elf
module_path: boot():/boot/cleonos_ramdisk.tar

46
docs/stage1.md Normal file
View File

@@ -0,0 +1,46 @@
# CLeonOS Stage1
## Stage Goal
- Bring up Limine boot path and CLKS kernel skeleton.
- Support x86_64 and aarch64 build targets in one Makefile.
- Initialize serial log channel and framebuffer + virtual TTY output.
- Build ISO with ramdisk root layout module.
## Acceptance Criteria
- Kernel starts via Limine and reaches `clks_kernel_main`.
- Serial output shows boot logs and architecture banner.
- Framebuffer renders TTY text output for kernel logs.
- `make ARCH=x86_64 iso` and `make ARCH=aarch64 iso` produce architecture-specific ISO paths.
- Ramdisk archive is generated from `/ramdisk` and packed into boot image.
## Build Targets
- `make setup`
- `make setup LIMINE_REF=<branch-or-tag>`
- `make ARCH=x86_64 kernel`
- `make ARCH=x86_64 iso`
- `make ARCH=x86_64 run`
- `make ARCH=x86_64 debug`
- `make ARCH=aarch64 kernel`
- `make ARCH=aarch64 iso`
- `make ARCH=aarch64 run AARCH64_EFI=/path/to/QEMU_EFI.fd`
## QEMU Commands
- x86_64:
- `qemu-system-x86_64 -M q35 -m 1024M -cdrom build/CLeonOS-x86_64.iso -serial stdio`
- aarch64:
- `qemu-system-aarch64 -M virt -cpu cortex-a72 -m 1024M -bios QEMU_EFI.fd -cdrom build/CLeonOS-aarch64.iso -serial stdio`
## Common Bugs and Debugging
- No boot entry in Limine menu:
- Check `configs/limine.conf` copy path and ISO folder layout under `/boot/limine`.
- Black screen but serial has output:
- Verify framebuffer request response exists; inspect `[WARN][VIDEO]` line in serial.
- No serial output:
- x86_64: ensure QEMU uses `-serial stdio` and COM1 init path is active.
- aarch64: ensure `virt` machine and PL011 MMIO base `0x09000000` are used.
- Linker errors for wrong architecture:
- Confirm `ARCH` value and matching cross toolchain (`x86_64-elf-*` or `aarch64-elf-*`).
- Setup fails while cloning Limine:
- Check network/proxy and try `make setup LIMINE_REF=<available-ref>`.
- ISO generation failure:
- Ensure `limine` artifacts exist and `LIMINE_DIR` points to valid files.

1
limine Submodule

Submodule limine added at 6dc556ea77

6
ramdisk/README.txt Normal file
View File

@@ -0,0 +1,6 @@
CLeonOS ramdisk root layout
/system : kernel-mode ELF apps and core system components
/shell : user shell and command ELF apps
/temp : runtime temp/cache files
/driver : hardware and peripheral drivers

0
ramdisk/driver/.keep Normal file
View File

0
ramdisk/shell/.keep Normal file
View File

0
ramdisk/system/.keep Normal file
View File

0
ramdisk/temp/.keep Normal file
View File