mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 10:40:00 +00:00
初始化
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
build/
|
||||||
|
*.iso
|
||||||
|
*.tar
|
||||||
226
Makefile
Normal file
226
Makefile
Normal 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
8
cleonos/c/stub.c
Normal 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
13
cleonos/rust/Cargo.toml
Normal 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
6
cleonos/rust/src/lib.rs
Normal 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
7
clks/arch/aarch64/boot.c
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include <clks/cpu.h>
|
||||||
|
#include <clks/kernel.h>
|
||||||
|
|
||||||
|
void _start(void) {
|
||||||
|
clks_kernel_main();
|
||||||
|
clks_cpu_halt_forever();
|
||||||
|
}
|
||||||
38
clks/arch/aarch64/linker.ld
Normal file
38
clks/arch/aarch64/linker.ld
Normal 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
7
clks/arch/x86_64/boot.c
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include <clks/cpu.h>
|
||||||
|
#include <clks/kernel.h>
|
||||||
|
|
||||||
|
void _start(void) {
|
||||||
|
clks_kernel_main();
|
||||||
|
clks_cpu_halt_forever();
|
||||||
|
}
|
||||||
42
clks/arch/x86_64/linker.ld
Normal file
42
clks/arch/x86_64/linker.ld
Normal 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.*)
|
||||||
|
}
|
||||||
|
}
|
||||||
68
clks/drivers/serial/serial.c
Normal file
68
clks/drivers/serial/serial.c
Normal 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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
75
clks/drivers/video/font8x8.c
Normal file
75
clks/drivers/video/font8x8.c
Normal 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;
|
||||||
|
}
|
||||||
8
clks/drivers/video/font8x8.h
Normal file
8
clks/drivers/video/font8x8.h
Normal 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
|
||||||
95
clks/drivers/video/framebuffer.c
Normal file
95
clks/drivers/video/framebuffer.c
Normal 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
10
clks/include/clks/boot.h
Normal 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
|
||||||
17
clks/include/clks/compiler.h
Normal file
17
clks/include/clks/compiler.h
Normal 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
24
clks/include/clks/cpu.h
Normal 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
|
||||||
20
clks/include/clks/framebuffer.h
Normal file
20
clks/include/clks/framebuffer.h
Normal 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
|
||||||
6
clks/include/clks/kernel.h
Normal file
6
clks/include/clks/kernel.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef CLKS_KERNEL_H
|
||||||
|
#define CLKS_KERNEL_H
|
||||||
|
|
||||||
|
void clks_kernel_main(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
56
clks/include/clks/limine.h
Normal file
56
clks/include/clks/limine.h
Normal 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
16
clks/include/clks/log.h
Normal 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
|
||||||
8
clks/include/clks/serial.h
Normal file
8
clks/include/clks/serial.h
Normal 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
|
||||||
12
clks/include/clks/string.h
Normal file
12
clks/include/clks/string.h
Normal 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
12
clks/include/clks/tty.h
Normal 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
23
clks/include/clks/types.h
Normal 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
48
clks/kernel/kmain.c
Normal 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();
|
||||||
|
}
|
||||||
36
clks/kernel/limine_requests.c
Normal file
36
clks/kernel/limine_requests.c
Normal 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
96
clks/kernel/log.c
Normal 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
194
clks/kernel/tty.c
Normal 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
70
clks/lib/string.c
Normal 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
7
configs/limine.conf
Normal 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
46
docs/stage1.md
Normal 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
1
limine
Submodule
Submodule limine added at 6dc556ea77
6
ramdisk/README.txt
Normal file
6
ramdisk/README.txt
Normal 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
0
ramdisk/driver/.keep
Normal file
0
ramdisk/shell/.keep
Normal file
0
ramdisk/shell/.keep
Normal file
0
ramdisk/system/.keep
Normal file
0
ramdisk/system/.keep
Normal file
0
ramdisk/temp/.keep
Normal file
0
ramdisk/temp/.keep
Normal file
Reference in New Issue
Block a user