feat(arch): Add AArch64 / ARMv8i CPU support, cross-compilation & Linux Kconfig TUI

- Implement AArch64 HAL, vector table (16 aligned vectors), GICv2, Generic Timer, Stage-1 MMU (39-bit VA), PL011 UART
- Build unified multi-architecture abstraction layer in include/arch/arch.h
- Create interactive Linux-like Kconfig TUI menuconfig in scripts/kconfig/menuconfig.py
- Support make menuconfig, defconfig, x86_64_defconfig, aarch64_defconfig
- Update master Makefile for cross-compiling x86_64 (x86_64-elf-) and AArch64 (aarch64-linux-gnu-)
- Dynamic architecture awareness across printk, uname, neofetch, and LazyBox
This commit is contained in:
subhobhai943 committed 2026-08-18 10:50:58 +05:30
1 parent 125a891621
commit 70d5925b16
41 files changed
+1926 -187

No files matched your search

+1
View File
@@ -8,3 +8,4 @@ build/
*.tmp
.DS_Store
.system_generated/
.config
+147 -68
View File
@@ -1,43 +1,97 @@
# =============================================================================
# SUB-OS Master Makefile - Modular Monolithic Linux-Like Kernel Build System
# SUB-OS Master Multi-Architecture Linux-Style Makefile
# Supports: x86_64, aarch64, armv8i
# Features: Linux Kconfig TUI (make menuconfig), multi-arch cross-compilation
# =============================================================================
# Cross Compiler & Toolchain Detection
CROSS_COMPILE ?= x86_64-elf-
-include .config
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
ASM = nasm
# Architecture Selection (Default: x86_64)
ifdef CONFIG_ARCH
ARCH ?= $(CONFIG_ARCH)
else
ARCH ?= x86_64
endif
# Build Directories
BUILD_DIR = build
BOOT_DIR = boot
# Target Architecture Flags
CFLAGS = -ffreestanding \
-fno-pie \
-fno-pic \
-mno-red-zone \
-mno-mmx \
-mno-sse \
-mno-sse2 \
-mcmodel=kernel \
-Wall \
-Wextra \
-Wno-unused-function \
-Wno-unused-parameter \
-O2 \
-Iinclude
# -----------------------------------------------------------------------------
# Toolchain & Architecture Flags
# -----------------------------------------------------------------------------
ifeq ($(ARCH), x86_64)
CROSS_COMPILE ?= x86_64-elf-
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
ASM = nasm
ASMFLAGS_ELF = -f elf64
ASMFLAGS_BOOT = -f bin -I$(BOOT_DIR)/
CFLAGS = -ffreestanding \
-fno-pie \
-fno-pic \
-mno-red-zone \
-mno-mmx \
-mno-sse \
-mno-sse2 \
-mcmodel=kernel \
-Wall \
-Wextra \
-Wno-unused-function \
-Wno-unused-parameter \
-O2 \
-Iinclude \
-D__x86_64__
LDFLAGS = -nostdlib -no-pie -T linker.ld
ASMFLAGS_ELF = -f elf64
ASMFLAGS_BOOT = -f bin -I$(BOOT_DIR)/
LDFLAGS = -nostdlib -no-pie -T linker.ld
# Source Files Discovery
ARCH_C_SRCS = $(shell find arch -name '*.c' 2>/dev/null)
ARCH_ASM_SRCS = $(shell find arch -name '*.asm' 2>/dev/null)
# Source files for x86_64
ARCH_C_SRCS = $(shell find arch/x86_64 -name '*.c' 2>/dev/null)
ARCH_ASM_SRCS = $(shell find arch/x86_64 -name '*.asm' 2>/dev/null)
ENTRY_OBJ = $(BUILD_DIR)/arch/x86_64/boot/entry.o
IMAGE = SUB-OS.img
TARGET = $(IMAGE)
QEMU_CMD = qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
-device e1000,netdev=net0 -serial stdio
else ifneq ($(filter $(ARCH), aarch64 armv8 armv8i),)
CROSS_COMPILE ?= aarch64-linux-gnu-
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
AS = $(CROSS_COMPILE)as
CFLAGS = -ffreestanding \
-fno-pie \
-fno-pic \
-Wall \
-Wextra \
-Wno-unused-function \
-Wno-unused-parameter \
-mno-outline-atomics \
-O2 \
-Iinclude \
-D__aarch64__ \
-march=armv8-a
LDFLAGS = -nostdlib -no-pie -T arch/aarch64/linker.ld
# Source files for AArch64
ARCH_C_SRCS = $(shell find arch/aarch64 -name '*.c' 2>/dev/null)
ARCH_S_SRCS = $(shell find arch/aarch64 -name '*.S' 2>/dev/null)
ENTRY_OBJ = $(BUILD_DIR)/arch/aarch64/boot/entry.o
TARGET = $(BUILD_DIR)/kernel.elf
QEMU_CMD = qemu-system-aarch64 -M virt -cpu cortex-a57 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf
else
$(error Unsupported Architecture '$(ARCH)'. Supported: x86_64, aarch64, armv8i)
endif
# -----------------------------------------------------------------------------
# Common Kernel Subsystems
# -----------------------------------------------------------------------------
KERNEL_C_SRCS = $(shell find kernel -name '*.c' 2>/dev/null)
MM_C_SRCS = $(shell find mm -name '*.c' 2>/dev/null)
DRIVERS_C_SRCS = $(shell find drivers -name '*.c' 2>/dev/null)
@@ -52,7 +106,6 @@ IO_URING_C_SRCS = $(shell find io_uring -name '*.c' 2>/dev/null)
SECURITY_C_SRCS = $(shell find security -name '*.c' 2>/dev/null)
USR_C_SRCS = $(shell find usr -name '*.c' 2>/dev/null)
VIRT_C_SRCS = $(shell find virt -name '*.c' 2>/dev/null)
BLOCK_C_SRCS = $(shell find block -name '*.c' 2>/dev/null)
IPC_C_SRCS = $(shell find ipc -name '*.c' 2>/dev/null)
SOUND_C_SRCS = $(shell find sound -name '*.c' 2>/dev/null)
@@ -63,81 +116,107 @@ ALL_C_SRCS = $(ARCH_C_SRCS) $(KERNEL_C_SRCS) $(MM_C_SRCS) $(DRIVERS_C_SRCS) \
$(USR_C_SRCS) $(VIRT_C_SRCS) $(BLOCK_C_SRCS) $(IPC_C_SRCS) $(SOUND_C_SRCS)
# Object Files Mapping
C_OBJS = $(patsubst %.c, $(BUILD_DIR)/%.o, $(ALL_C_SRCS))
ASM_OBJS = $(patsubst %.asm, $(BUILD_DIR)/%.o, $(ARCH_ASM_SRCS))
C_OBJS = $(patsubst %.c, $(BUILD_DIR)/%.o, $(ALL_C_SRCS))
# Put entry.o first in linker sequence
ENTRY_OBJ = $(BUILD_DIR)/arch/x86_64/boot/entry.o
OTHER_OBJS = $(filter-out $(ENTRY_OBJ), $(ASM_OBJS) $(C_OBJS))
ifeq ($(ARCH), x86_64)
ASM_OBJS = $(patsubst %.asm, $(BUILD_DIR)/%.o, $(ARCH_ASM_SRCS))
OTHER_OBJS = $(filter-out $(ENTRY_OBJ), $(ASM_OBJS) $(C_OBJS))
else
S_OBJS = $(patsubst %.S, $(BUILD_DIR)/%.o, $(ARCH_S_SRCS))
OTHER_OBJS = $(filter-out $(ENTRY_OBJ), $(S_OBJS) $(C_OBJS))
endif
IMAGE = SUB-OS.img
.PHONY: all clean run debug info menuconfig config defconfig x86_64_defconfig aarch64_defconfig armv8_defconfig armv8i_defconfig qemu
.PHONY: all clean run debug info
all: $(TARGET)
all: $(IMAGE)
# -----------------------------------------------------------------------------
# Configuration Targets (Linux Kconfig TUI)
# -----------------------------------------------------------------------------
menuconfig config:
@python3 scripts/kconfig/menuconfig.py
# Assemble 16-bit Bootloader Stage 1
$(BUILD_DIR)/boot/boot.bin: $(BOOT_DIR)/boot.asm | $(BUILD_DIR)/boot
$(ASM) $(ASMFLAGS_BOOT) $< -o $@
defconfig:
@python3 scripts/kconfig/menuconfig.py --defconfig $(ARCH)
# Assemble 16/32/64-bit Bootloader Stage 2
$(BUILD_DIR)/boot/stage2.bin: $(BOOT_DIR)/stage2.asm $(BOOT_DIR)/gdt.asm | $(BUILD_DIR)/boot
$(ASM) $(ASMFLAGS_BOOT) $< -o $@
x86_64_defconfig:
@python3 scripts/kconfig/menuconfig.py --x86_64
# Compile 64-bit C source files
aarch64_defconfig:
@python3 scripts/kconfig/menuconfig.py --aarch64
armv8_defconfig armv8i_defconfig:
@python3 scripts/kconfig/menuconfig.py --armv8i
# -----------------------------------------------------------------------------
# Compilation Rules
# -----------------------------------------------------------------------------
# C Source Files
$(BUILD_DIR)/%.o: %.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@
# Assemble 64-bit ASM source files
# x86_64 NASM Assembly Files
$(BUILD_DIR)/%.o: %.asm
@mkdir -p $(dir $@)
$(ASM) $(ASMFLAGS_ELF) $< -o $@
# Link Kernel ELF
$(BUILD_DIR)/kernel.elf: $(ENTRY_OBJ) $(OTHER_OBJS) linker.ld
# AArch64 GNU Assembly Files (.S)
$(BUILD_DIR)/%.o: %.S
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@
# -----------------------------------------------------------------------------
# x86_64 Bootloader & Image Rules
# -----------------------------------------------------------------------------
$(BUILD_DIR)/boot/boot.bin: $(BOOT_DIR)/boot.asm | $(BUILD_DIR)/boot
$(ASM) $(ASMFLAGS_BOOT) $< -o $@
$(BUILD_DIR)/boot/stage2.bin: $(BOOT_DIR)/stage2.asm $(BOOT_DIR)/gdt.asm | $(BUILD_DIR)/boot
$(ASM) $(ASMFLAGS_BOOT) $< -o $@
$(BUILD_DIR)/boot:
mkdir -p $(BUILD_DIR)/boot
$(BUILD_DIR)/kernel.elf: $(ENTRY_OBJ) $(OTHER_OBJS)
$(LD) $(LDFLAGS) -o $@ $(ENTRY_OBJ) $(OTHER_OBJS)
@echo "=== [Kernel ELF Linked: $@ (Architecture: $(ARCH))] ==="
# Convert ELF to Flat Binary
$(BUILD_DIR)/kernel.bin: $(BUILD_DIR)/kernel.elf
$(OBJCOPY) -O binary $< $@
# Create Bootable Floppy / HDD Raw Disk Image
$(IMAGE): $(BUILD_DIR)/boot/boot.bin $(BUILD_DIR)/boot/stage2.bin $(BUILD_DIR)/kernel.bin
dd if=/dev/zero of=$@ bs=512 count=2880 status=none
dd if=$(BUILD_DIR)/boot/boot.bin of=$@ bs=512 conv=notrunc status=none
dd if=$(BUILD_DIR)/boot/stage2.bin of=$@ bs=512 seek=1 conv=notrunc status=none
dd if=$(BUILD_DIR)/kernel.bin of=$@ bs=512 seek=16 conv=notrunc status=none
@echo "=== [SUB-OS Disk Image Built Successfully: $@ (Size: $$(du -h $@ | cut -f1))] ==="
@echo "=== [SUB-OS x86_64 Disk Image Built: $@ (Size: $$(du -h $@ | cut -f1))] ==="
$(BUILD_DIR)/boot:
mkdir -p $(BUILD_DIR)/boot
run: $(IMAGE)
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
-device e1000,netdev=net0 -serial stdio
# -----------------------------------------------------------------------------
# Execution & Emulation Targets
# -----------------------------------------------------------------------------
run qemu: $(TARGET)
$(QEMU_CMD)
run-server: $(IMAGE)
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
-device e1000,netdev=net0 -serial stdio -display none
run-remote: $(IMAGE)
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
-device e1000,netdev=net0 \
-serial telnet:0.0.0.0:2222,server,nowait -display none
debug: $(IMAGE)
debug: $(TARGET)
ifeq ($(ARCH), x86_64)
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
-device e1000,netdev=net0 -serial stdio -s -S
else
qemu-system-aarch64 -M virt -cpu cortex-a57 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf -s -S
endif
info:
@echo "C Sources: $(words $(ALL_C_SRCS)) files"
@echo "ASM Sources: $(words $(ARCH_ASM_SRCS)) files"
@echo "Target: $(IMAGE)"
@echo "Target Architecture: $(ARCH)"
@echo "Cross Compiler: $(CROSS_COMPILE)"
@echo "C Sources: $(words $(ALL_C_SRCS)) files"
@echo "Target Binary: $(TARGET)"
clean:
rm -rf $(BUILD_DIR) $(IMAGE)
+106
View File
@@ -0,0 +1,106 @@
/*
* SUB-OS AArch64 / ARMv8 Bootstrap Entry Point
* Handles EL2/EL3 -> EL1 drop, sets up stack, zeroes BSS, and jumps to kernel_main_aarch64
*/
.section ".text.boot"
.global _start
.global aarch64_entry
_start:
aarch64_entry:
// Early UART debug ping
mov x0, #0x09000000
mov w1, #'['
str w1, [x0]
mov w1, #'S'
str w1, [x0]
mov w1, #'U'
str w1, [x0]
mov w1, #'B'
str w1, [x0]
mov w1, #'-'
str w1, [x0]
mov w1, #'O'
str w1, [x0]
mov w1, #'S'
str w1, [x0]
mov w1, #']'
str w1, [x0]
mov w1, #'\n'
str w1, [x0]
// 1. Primary Core Check (Core 0 proceeds, other cores halt)
mrs x0, mpidr_el1
and x0, x0, #0xFF
cbz x0, .primary_core
.secondary_halt:
wfe
b .secondary_halt
.primary_core:
// 2. Check current Exception Level (EL)
mrs x0, CurrentEL
lsr x0, x0, #2
cmp x0, #2
b.eq .from_el2
cmp x0, #3
b.eq .from_el3
b .in_el1
.from_el3:
// Setup Secure Configuration Register (SCR_EL3)
mov x0, #(1 << 10) // RW=1 (64-bit execution in EL2/EL1)
orr x0, x0, #(1 << 0) // NS=1 (Non-secure)
msr scr_el3, x0
mov x0, #0b01001 // EL2h mode with DAIF masked
msr spsr_el3, x0
adr x0, .from_el2
msr elr_el3, x0
eret
.from_el2:
// Setup Hypervisor Configuration Register (HCR_EL2)
mov x0, #(1 << 31) // RW=1 (64-bit execution in EL1)
msr hcr_el2, x0
// Setup SPSR_EL2 for drop to EL1h (EL1 with dedicated SP_EL1)
mov x0, #0b00101 // M[3:0] = 0101 (EL1h)
orr x0, x0, #(0xF << 6) // Mask DAIF
msr spsr_el2, x0
adr x0, .in_el1
msr elr_el2, x0
eret
.in_el1:
// Enable Floating-Point and Advanced SIMD (NEON) in EL1
mov x0, #(3 << 20)
msr cpacr_el1, x0
isb
// 3. Set up Kernel Stack (64 KB dedicated EL1 stack)
ldr x0, =stack_top
mov sp, x0
// 4. Enable Vector Table
ldr x0, =vectors
msr vbar_el1, x0
// 5. Zero out BSS
ldr x0, =__bss_start
ldr x1, =__bss_end
.bss_loop:
cmp x0, x1
b.ge .bss_done
str xzr, [x0], #8
b .bss_loop
.bss_done:
// 6. Jump to AArch64 C Entry
bl kernel_main_aarch64
.hang:
wfi
b .hang
+36
View File
@@ -0,0 +1,36 @@
#
# Automatically generated by SUB-OS Kconfig for aarch64
#
CONFIG_ARCH=aarch64
CONFIG_ARCH_AARCH64=y
# CONFIG_ARCH_X86_64 is not set
CONFIG_BPF_VM=y
CONFIG_DRV_CANVAS_2D=y
CONFIG_DRV_PTY=y
CONFIG_DRV_RAMDISK=y
CONFIG_DRV_VIRTIO_BLK=y
CONFIG_DRV_VIRTIO_NET=y
CONFIG_DRV_VIRTIO_RNG=y
CONFIG_FS_DEVFS=y
CONFIG_FS_EXT2=y
CONFIG_FS_FAT32=y
CONFIG_FS_PROCFS=y
CONFIG_FS_RAMFS=y
CONFIG_FS_SYSFS=y
CONFIG_FS_VFS=y
CONFIG_IO_URING=y
CONFIG_MM_PMM=y
CONFIG_MM_SLAB=y
CONFIG_MM_VMA=y
CONFIG_NET_FILTER=y
CONFIG_NET_HTTPD=y
CONFIG_NET_SSHD=y
CONFIG_NET_STACK=y
CONFIG_OPTIMIZATION="-O2"
CONFIG_PREEMPT=y
CONFIG_SECURITY_KEYRING=y
CONFIG_SECURITY_LSM=y
CONFIG_SMP=y
CONFIG_SUBOS_HOSTNAME="sub-os"
CONFIG_SUBOS_VERSION="0.2.0-lts"
CONFIG_USERLAND_LAZYBOX=y
+65
View File
@@ -0,0 +1,65 @@
#include <arch/arch.h>
#include <arch/aarch64/cpu.h>
#include <arch/aarch64/gic.h>
#include <arch/aarch64/timer.h>
#include <arch/aarch64/uart.h>
#include <arch/aarch64/mmu.h>
#include <arch/x86_64/cpuid.h>
#include <kernel/printk.h>
#include <lib/string.h>
static cpu_info_t aarch64_compat_cpu;
void arch_early_init(void) {
uart_pl011_init();
}
void arch_init(void) {
aarch64_cpu_init();
gic_init();
aarch64_timer_init(100);
aarch64_mmu_init();
// Populate compatibility CPU info structure for procfs
memset(&aarch64_compat_cpu, 0, sizeof(aarch64_compat_cpu));
const aarch64_cpu_info_t* info = aarch64_get_cpu_info();
strncpy(aarch64_compat_cpu.vendor, "ARM Ltd", sizeof(aarch64_compat_cpu.vendor) - 1);
strncpy(aarch64_compat_cpu.model, info->model_name, sizeof(aarch64_compat_cpu.model) - 1);
aarch64_compat_cpu.has_fpu = true;
arch_enable_interrupts();
}
const char* arch_get_name(void) {
return "aarch64 (ARMv8-A)";
}
uint32_t arch_get_cpu_id(void) {
return (uint32_t)(aarch64_get_mpidr() & 0xFF);
}
// Timer Compatibility Layer for Portable Drivers
uint64_t pit_get_ticks(void) {
return aarch64_timer_get_ticks();
}
void pit_sleep(uint32_t ms) {
uint64_t count = (ms > 10) ? (ms / 10) : 1;
uint64_t target = aarch64_timer_get_ticks() + count;
while (aarch64_timer_get_ticks() < target) {
__asm__ volatile("wfi");
}
}
// Interrupt & CPUID Compatibility Stubs
void isr_register_handler(uint8_t isr, void* handler) {
(void)isr; (void)handler;
}
void pic_clear_mask(uint8_t irq) {
(void)irq;
}
const cpu_info_t* cpuid_get_info(void) {
return &aarch64_compat_cpu;
}
+58
View File
@@ -0,0 +1,58 @@
#include <arch/aarch64/cpu.h>
#include <lib/string.h>
#include <kernel/printk.h>
static aarch64_cpu_info_t cpu_info;
uint64_t aarch64_get_midr(void) {
uint64_t midr;
__asm__ volatile("mrs %0, midr_el1" : "=r"(midr));
return midr;
}
uint64_t aarch64_get_mpidr(void) {
uint64_t mpidr;
__asm__ volatile("mrs %0, mpidr_el1" : "=r"(mpidr));
return mpidr;
}
uint32_t aarch64_get_current_el(void) {
uint64_t cur_el;
__asm__ volatile("mrs %0, CurrentEL" : "=r"(cur_el));
return (uint32_t)(cur_el >> 2);
}
void aarch64_cpu_init(void) {
memset(&cpu_info, 0, sizeof(cpu_info));
uint64_t midr = aarch64_get_midr();
cpu_info.implementer = (uint32_t)((midr >> 24) & 0xFF);
cpu_info.variant = (uint32_t)((midr >> 20) & 0x0F);
cpu_info.architecture = (uint32_t)((midr >> 16) & 0x0F);
cpu_info.part_num = (uint32_t)((midr >> 4) & 0xFFF);
cpu_info.revision = (uint32_t)(midr & 0x0F);
cpu_info.current_el = aarch64_get_current_el();
if (cpu_info.implementer == 0x41) { // ARM Limited
switch (cpu_info.part_num) {
case 0xD03: strcpy(cpu_info.model_name, "ARM Cortex-A53 (ARMv8.0-A)"); break;
case 0xD07: strcpy(cpu_info.model_name, "ARM Cortex-A57 (ARMv8.0-A)"); break;
case 0xD08: strcpy(cpu_info.model_name, "ARM Cortex-A72 (ARMv8.0-A)"); break;
case 0xD09: strcpy(cpu_info.model_name, "ARM Cortex-A73 (ARMv8.0-A)"); break;
case 0xD0B: strcpy(cpu_info.model_name, "ARM Cortex-A76 (ARMv8.2-A)"); break;
case 0xD40: strcpy(cpu_info.model_name, "ARM Neoverse-V1 (ARMv8.4-A)"); break;
default: strcpy(cpu_info.model_name, "ARMv8-A Compatible 64-Bit Processor"); break;
}
} else if (cpu_info.implementer == 0x61) { // Apple Silicon
strcpy(cpu_info.model_name, "Apple Silicon M-Series (ARMv8-A)");
} else {
strcpy(cpu_info.model_name, "Generic AArch64 / ARMv8 64-Bit Core");
}
printk(KERN_INFO "CPU: %s (Implementer: 0x%02x, Part: 0x%03x, EL%u)\n",
cpu_info.model_name, cpu_info.implementer, cpu_info.part_num, cpu_info.current_el);
}
const aarch64_cpu_info_t* aarch64_get_cpu_info(void) {
return &cpu_info;
}
+42
View File
@@ -0,0 +1,42 @@
#include <arch/aarch64/arch.h>
#include <arch/aarch64/gic.h>
#include <kernel/printk.h>
void aarch64_sync_handler(aarch64_context_t* ctx) {
uint64_t esr, elr, far;
__asm__ volatile("mrs %0, esr_el1" : "=r"(esr));
__asm__ volatile("mrs %0, elr_el1" : "=r"(elr));
__asm__ volatile("mrs %0, far_el1" : "=r"(far));
uint32_t ec = (esr >> 26) & 0x3F;
printk(ANSI_BRIGHT_RED "\n[KERNEL PANIC] AArch64 Synchronous Exception!\n" ANSI_RESET);
printk("ESR_EL1: 0x%016llx (EC: 0x%02x, ISS: 0x%08x)\n", esr, ec, (uint32_t)(esr & 0x01FFFFFF));
printk("ELR_EL1 (PC): 0x%016llx FAR_EL1: 0x%016llx\n", elr, far);
printk("Registers:\n");
for (int i = 0; i < 30; i += 2) {
printk(" X%02d: 0x%016llx X%02d: 0x%016llx\n", i, ctx->r[i], i + 1, ctx->r[i + 1]);
}
printk(" X30 (LR): 0x%016llx SP: 0x%016llx\n", ctx->r[30], ctx->sp);
while (1) {
__asm__ volatile("wfe");
}
}
void aarch64_irq_handler(aarch64_context_t* ctx) {
(void)ctx;
gic_handle_irq();
}
void aarch64_fiq_handler(aarch64_context_t* ctx) {
(void)ctx;
printk(KERN_WARNING "AArch64: Unexpected FIQ caught\n");
}
void aarch64_serror_handler(aarch64_context_t* ctx) {
(void)ctx;
printk(ANSI_BRIGHT_RED "[KERNEL PANIC] AArch64 SError Interrupt caught!\n" ANSI_RESET);
while (1) {
__asm__ volatile("wfe");
}
}
+71
View File
@@ -0,0 +1,71 @@
#include <arch/aarch64/gic.h>
#include <arch/aarch64/io.h>
#include <lib/string.h>
#include <kernel/printk.h>
#define MAX_GIC_IRQS 256
static gic_irq_handler_t irq_handlers[MAX_GIC_IRQS];
void gic_init(void) {
memset(irq_handlers, 0, sizeof(irq_handlers));
// 1. Disable Distributor
mmio_write32(GIC_DIST_BASE + GICD_CTLR, 0);
// 2. Clear pending and enable default priorities
uint32_t typer = mmio_read32(GIC_DIST_BASE + GICD_TYPER);
uint32_t num_irqs = 32 * ((typer & 0x1F) + 1);
if (num_irqs > MAX_GIC_IRQS) num_irqs = MAX_GIC_IRQS;
for (uint32_t i = 32; i < num_irqs; i += 32) {
mmio_write32(GIC_DIST_BASE + GICD_ICENABLER(i / 32), 0xFFFFFFFF);
}
for (uint32_t i = 0; i < num_irqs; i += 4) {
mmio_write32(GIC_DIST_BASE + GICD_IPRIORITYR(i / 4), 0xA0A0A0A0);
}
for (uint32_t i = 32; i < num_irqs; i += 4) {
mmio_write32(GIC_DIST_BASE + GICD_ITARGETSR(i / 4), 0x01010101); // Target Core 0
}
// 3. Enable Distributor
mmio_write32(GIC_DIST_BASE + GICD_CTLR, 1);
// 4. Enable CPU Interface
mmio_write32(GIC_CPU_BASE + GICC_PMR, 0xF0); // Priority mask
mmio_write32(GIC_CPU_BASE + GICC_CTLR, 1); // Enable signaling
printk(KERN_INFO "GIC: ARM Generic Interrupt Controller v2 initialized (%u IRQ lines)\n", num_irqs);
}
void gic_enable_irq(uint32_t irq) {
if (irq >= MAX_GIC_IRQS) return;
mmio_write32(GIC_DIST_BASE + GICD_ISENABLER(irq / 32), (1U << (irq % 32)));
}
void gic_disable_irq(uint32_t irq) {
if (irq >= MAX_GIC_IRQS) return;
mmio_write32(GIC_DIST_BASE + GICD_ICENABLER(irq / 32), (1U << (irq % 32)));
}
void gic_register_handler(uint32_t irq, gic_irq_handler_t handler) {
if (irq < MAX_GIC_IRQS) {
irq_handlers[irq] = handler;
gic_enable_irq(irq);
}
}
void gic_handle_irq(void) {
uint32_t iar = mmio_read32(GIC_CPU_BASE + GICC_IAR);
uint32_t irq = iar & 0x3FF;
if (irq < 1020) {
if (irq_handlers[irq]) {
irq_handlers[irq](irq);
}
// End of Interrupt (EOIR)
mmio_write32(GIC_CPU_BASE + GICC_EOIR, iar);
}
}
+49
View File
@@ -0,0 +1,49 @@
#include <arch/aarch64/timer.h>
#include <arch/aarch64/gic.h>
#include <kernel/timer.h>
#include <kernel/printk.h>
static uint64_t timer_ticks = 0;
static uint64_t timer_freq = 62500000; // Standard 62.5MHz QEMU virt frequency
static uint32_t tick_interval = 0;
void aarch64_timer_handle_irq(void) {
timer_ticks++;
// Reset next comparator interval
__asm__ volatile("msr cntv_tval_el0, %0" :: "r"((uint64_t)tick_interval));
// Call generic kernel timer tick
timer_tick();
}
static void gic_timer_wrapper(uint32_t irq) {
(void)irq;
aarch64_timer_handle_irq();
}
void aarch64_timer_init(uint32_t freq_hz) {
if (freq_hz == 0) freq_hz = 100;
__asm__ volatile("mrs %0, cntfrq_el0" : "=r"(timer_freq));
tick_interval = (uint32_t)(timer_freq / freq_hz);
// Register with GIC (PPI 27 = Virtual Timer IRQ)
gic_register_handler(ARCH_TIMER_VIRT_IRQ, gic_timer_wrapper);
// Set countdown and enable virtual timer
__asm__ volatile("msr cntv_tval_el0, %0" :: "r"((uint64_t)tick_interval));
uint64_t ctl = 1; // Enable=1, IMASK=0
__asm__ volatile("msr cntv_ctl_el0, %0" :: "r"(ctl));
printk(KERN_INFO "Timer: ARM Generic Arch Timer active (%u Hz, Base Clock: %llu MHz)\n",
freq_hz, timer_freq / 1000000);
}
uint64_t aarch64_timer_get_ticks(void) {
return timer_ticks;
}
uint64_t aarch64_timer_get_freq(void) {
return timer_freq;
}
+117
View File
@@ -0,0 +1,117 @@
/*
* SUB-OS AArch64 Exception Vector Table
* 16 vectors aligned on 128-byte (0x80) boundaries
*/
.macro SAVE_ALL
sub sp, sp, #272
stp x0, x1, [sp, #0]
stp x2, x3, [sp, #16]
stp x4, x5, [sp, #32]
stp x6, x7, [sp, #48]
stp x8, x9, [sp, #64]
stp x10, x11, [sp, #80]
stp x12, x13, [sp, #96]
stp x14, x15, [sp, #112]
stp x16, x17, [sp, #128]
stp x18, x19, [sp, #144]
stp x20, x21, [sp, #160]
stp x22, x23, [sp, #176]
stp x24, x25, [sp, #192]
stp x26, x27, [sp, #208]
stp x28, x29, [sp, #224]
mrs x0, elr_el1
mrs x1, spsr_el1
stp x30, x0, [sp, #240]
str x1, [sp, #256]
.endm
.macro RESTORE_ALL
ldr x1, [sp, #256]
msr spsr_el1, x1
ldp x30, x0, [sp, #240]
msr elr_el1, x0
ldp x28, x29, [sp, #224]
ldp x26, x27, [sp, #208]
ldp x24, x25, [sp, #192]
ldp x22, x23, [sp, #176]
ldp x20, x21, [sp, #160]
ldp x18, x19, [sp, #144]
ldp x16, x17, [sp, #128]
ldp x14, x15, [sp, #112]
ldp x12, x13, [sp, #96]
ldp x10, x11, [sp, #80]
ldp x8, x9, [sp, #64]
ldp x6, x7, [sp, #48]
ldp x4, x5, [sp, #32]
ldp x2, x3, [sp, #16]
ldp x0, x1, [sp, #0]
add sp, sp, #272
eret
.endm
.section ".vectors", "ax"
.align 11
.global vectors
vectors:
// 1. Current EL with SP0
.align 7; b handle_sync_curr_sp0
.align 7; b handle_irq_curr_sp0
.align 7; b handle_fiq_curr_sp0
.align 7; b handle_serror_curr_sp0
// 2. Current EL with SPx
.align 7; b handle_sync_curr_spx
.align 7; b handle_irq_curr_spx
.align 7; b handle_fiq_curr_spx
.align 7; b handle_serror_curr_spx
// 3. Lower EL using AArch64
.align 7; b handle_sync_lower_aarch64
.align 7; b handle_irq_lower_aarch64
.align 7; b handle_fiq_lower_aarch64
.align 7; b handle_serror_lower_aarch64
// 4. Lower EL using AArch32
.align 7; b handle_sync_lower_aarch32
.align 7; b handle_irq_lower_aarch32
.align 7; b handle_fiq_lower_aarch32
.align 7; b handle_serror_lower_aarch32
// Common Vector Handlers
handle_sync_curr_sp0:
handle_sync_curr_spx:
handle_sync_lower_aarch64:
handle_sync_lower_aarch32:
SAVE_ALL
mov x0, sp
bl aarch64_sync_handler
RESTORE_ALL
handle_irq_curr_sp0:
handle_irq_curr_spx:
handle_irq_lower_aarch64:
handle_irq_lower_aarch32:
SAVE_ALL
mov x0, sp
bl aarch64_irq_handler
RESTORE_ALL
handle_fiq_curr_sp0:
handle_fiq_curr_spx:
handle_fiq_lower_aarch64:
handle_fiq_lower_aarch32:
SAVE_ALL
mov x0, sp
bl aarch64_fiq_handler
RESTORE_ALL
handle_serror_curr_sp0:
handle_serror_curr_spx:
handle_serror_lower_aarch64:
handle_serror_lower_aarch32:
SAVE_ALL
mov x0, sp
bl aarch64_serror_handler
RESTORE_ALL
+38
View File
@@ -0,0 +1,38 @@
#include <arch/aarch64/uart.h>
#include <arch/aarch64/io.h>
void uart_pl011_init(void) {
// Enable UART, TX, and RX (bits 0, 8, 9)
mmio_write32(PL011_UART0_BASE + UARTCR, (1 << 0) | (1 << 8) | (1 << 9));
}
void uart_pl011_putc(char c) {
if (c == '\n') {
while (mmio_read32(PL011_UART0_BASE + UARTFR) & UARTFR_TXFF) {
__asm__ volatile("nop");
}
mmio_write32(PL011_UART0_BASE + UARTDR, '\r');
}
while (mmio_read32(PL011_UART0_BASE + UARTFR) & UARTFR_TXFF) {
__asm__ volatile("nop");
}
mmio_write32(PL011_UART0_BASE + UARTDR, (uint32_t)(uint8_t)c);
}
void uart_pl011_puts(const char* str) {
if (!str) return;
while (*str) {
uart_pl011_putc(*str++);
}
}
char uart_pl011_getc(void) {
while (mmio_read32(PL011_UART0_BASE + UARTFR) & UARTFR_RXFE) {
__asm__ volatile("wfe");
}
return (char)(mmio_read32(PL011_UART0_BASE + UARTDR) & 0xFF);
}
int uart_pl011_has_data(void) {
return !(mmio_read32(PL011_UART0_BASE + UARTFR) & UARTFR_RXFE);
}
+45
View File
@@ -0,0 +1,45 @@
OUTPUT_FORMAT("elf64-littleaarch64")
OUTPUT_ARCH(aarch64)
ENTRY(_start)
SECTIONS
{
. = 0x40080000;
__kernel_start = .;
.text.boot : {
KEEP(*(.text.boot))
}
.vectors : ALIGN(2048) {
KEEP(*(.vectors))
}
.text : ALIGN(4096) {
*(.text .text.*)
}
.rodata : ALIGN(4096) {
*(.rodata .rodata.*)
}
.data : ALIGN(4096) {
*(.data .data.*)
}
.bss : ALIGN(4096) {
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4096);
__bss_end = .;
}
.stack : ALIGN(4096) {
. += 0x20000; /* 128 KB dedicated kernel stack */
stack_top = .;
}
__kernel_end = .;
}
+63
View File
@@ -0,0 +1,63 @@
#include <arch/aarch64/mmu.h>
#include <arch/aarch64/io.h>
#include <lib/string.h>
#include <kernel/printk.h>
// Level 1 Translation Table (PUD / L1, 512 x 1GB entries, root table for 39-bit VA)
static uint64_t __attribute__((aligned(4096))) l1_table[512];
// Level 2 Translation Table (PMD / L2, 512 x 2MB entries for first 1GB: 0x00000000 - 0x3FFFFFFF Device MMIO)
static uint64_t __attribute__((aligned(4096))) l2_dev_table[512];
// Level 2 Translation Table (PMD / L2, 512 x 2MB entries for second 1GB: 0x40000000 - 0x7FFFFFFF RAM)
static uint64_t __attribute__((aligned(4096))) l2_ram_table[512];
void aarch64_mmu_init(void) {
memset(l1_table, 0, sizeof(l1_table));
memset(l2_dev_table, 0, sizeof(l2_dev_table));
memset(l2_ram_table, 0, sizeof(l2_ram_table));
// L1 Table Entry 0 points to L2 Device Table (0 - 1GB)
l1_table[0] = ((uint64_t)l2_dev_table) | PTE_VALID | PTE_TABLE;
// L1 Table Entry 1 points to L2 RAM Table (1GB - 2GB: QEMU virt RAM is 0x40000000)
l1_table[1] = ((uint64_t)l2_ram_table) | PTE_VALID | PTE_TABLE;
// 1. Identity map Device MMIO (0x00000000 - 0x3FFFFFFF) as Device-nGnRnE
for (uint64_t i = 0; i < 512; i++) {
uint64_t phys = i * 0x200000; // 2MB blocks
l2_dev_table[i] = phys | PTE_VALID | PTE_AF | PTE_SH_INNER | PTE_ATTRINDX(MT_DEVICE_nGnRnE);
}
// 2. Identity map System RAM (0x40000000 - 0x7FFFFFFF, 1GB) as Normal Cacheable
for (uint64_t i = 0; i < 512; i++) {
uint64_t phys = 0x40000000 + (i * 0x200000);
l2_ram_table[i] = phys | PTE_VALID | PTE_AF | PTE_SH_INNER | PTE_ATTRINDX(MT_NORMAL_WB);
}
// 3. Set Memory Attribute Indirection Register (MAIR_EL1)
__asm__ volatile("msr mair_el1, %0" :: "r"((uint64_t)MAIR_VAL));
// 4. Configure Translation Control Register (TCR_EL1)
// T0SZ=25 (39-bit VA starting at L1 / 1GB chunks), TG0=0 (4KB granule), Inner/Outer WBWA, Inner Shareable
uint64_t tcr = (25ULL << 0) | // T0SZ = 25 (39-bit VA)
(1ULL << 8) | // IRGN0 = Normal WBWA
(1ULL << 10) | // ORGN0 = Normal WBWA
(3ULL << 12) | // SH0 = Inner Shareable
(0ULL << 14) | // TG0 = 4KB
(1ULL << 23) | // EPD1 = Disable TTBR1 translations
(2ULL << 32); // IPS = 40-bit Physical Address (1TB)
__asm__ volatile("msr tcr_el1, %0" :: "r"(tcr));
// 5. Load Translation Table Base Register 0 (TTBR0_EL1)
__asm__ volatile("msr ttbr0_el1, %0" :: "r"((uint64_t)l1_table));
isb();
// 6. Enable MMU and Caching in SCTLR_EL1 (M=1, C=1, I=1)
uint64_t sctlr;
__asm__ volatile("mrs %0, sctlr_el1" : "=r"(sctlr));
sctlr |= (1 << 0) | // M: Enable MMU
(1 << 2) | // C: Enable Data Cache
(1 << 12); // I: Enable Instruction Cache
__asm__ volatile("msr sctlr_el1, %0" :: "r"(sctlr));
isb();
}
+45
View File
@@ -0,0 +1,45 @@
#
# Automatically generated by SUB-OS Kconfig for x86_64
#
CONFIG_ARCH=x86_64
CONFIG_ARCH_X86_64=y
CONFIG_BPF_VM=y
CONFIG_DRV_AHCI=y
CONFIG_DRV_ATA=y
CONFIG_DRV_BOCHS_VBE=y
CONFIG_DRV_CANVAS_2D=y
CONFIG_DRV_E1000=y
CONFIG_DRV_HWMON=y
CONFIG_DRV_NVME=y
CONFIG_DRV_PTY=y
CONFIG_DRV_RAMDISK=y
CONFIG_DRV_RTL8139=y
CONFIG_DRV_SOUND_AC97=y
CONFIG_DRV_SOUND_HDA=y
CONFIG_DRV_USB_XHCI=y
CONFIG_DRV_VIRTIO_BLK=y
CONFIG_DRV_VIRTIO_NET=y
CONFIG_DRV_VIRTIO_RNG=y
CONFIG_FS_DEVFS=y
CONFIG_FS_EXT2=y
CONFIG_FS_FAT32=y
CONFIG_FS_PROCFS=y
CONFIG_FS_RAMFS=y
CONFIG_FS_SYSFS=y
CONFIG_FS_VFS=y
CONFIG_IO_URING=y
CONFIG_MM_PMM=y
CONFIG_MM_SLAB=y
CONFIG_MM_VMA=y
CONFIG_NET_FILTER=y
CONFIG_NET_HTTPD=y
CONFIG_NET_SSHD=y
CONFIG_NET_STACK=y
CONFIG_OPTIMIZATION="-O2"
CONFIG_PREEMPT=y
CONFIG_SECURITY_KEYRING=y
CONFIG_SECURITY_LSM=y
CONFIG_SMP=y
CONFIG_SUBOS_HOSTNAME="sub-os"
CONFIG_SUBOS_VERSION="0.2.0-lts"
CONFIG_USERLAND_LAZYBOX=y
+32
View File
@@ -0,0 +1,32 @@
#include <arch/arch.h>
#include <arch/x86_64/gdt.h>
#include <arch/x86_64/idt.h>
#include <arch/x86_64/isr.h>
#include <arch/x86_64/pic.h>
#include <arch/x86_64/pit.h>
#include <arch/x86_64/cpuid.h>
#include <kernel/timer.h>
void arch_early_init(void) {
// x86_64 serial and tty initialized in main
}
void arch_init(void) {
gdt_init();
idt_init();
isr_init();
pic_init();
pit_init(100);
timer_wheel_init();
arch_enable_interrupts();
}
const char* arch_get_name(void) {
return "x86_64 (AMD64)";
}
uint32_t arch_get_cpu_id(void) {
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
cpuid(1, &eax, &ebx, &ecx, &edx);
return (ebx >> 24) & 0xFF;
}
+20 -4
View File
@@ -1,8 +1,6 @@
#include <drivers/keyboard.h>
#include <drivers/tty.h>
#include <arch/x86_64/isr.h>
#include <arch/x86_64/pic.h>
#include <arch/x86_64/io.h>
#include <arch/arch.h>
#define KEYBOARD_DATA_PORT 0x60
#define KEYBOARD_STATUS_PORT 0x64
@@ -44,6 +42,7 @@ static void buffer_enqueue(uint16_t key) {
}
}
#if defined(__x86_64__)
static void keyboard_interrupt_handler(registers_t* regs) {
(void)regs;
uint8_t scancode = inb(KEYBOARD_DATA_PORT);
@@ -112,23 +111,40 @@ static void keyboard_interrupt_handler(registers_t* regs) {
buffer_enqueue((uint16_t)c);
}
}
#endif
void keyboard_init(void) {
buffer_head = 0;
buffer_tail = 0;
#if defined(__x86_64__)
isr_register_handler(33, keyboard_interrupt_handler); // IRQ1
pic_clear_mask(1);
#endif
}
#if defined(__aarch64__)
#include <arch/aarch64/uart.h>
#endif
bool keyboard_has_key(void) {
#if defined(__aarch64__)
if (uart_pl011_has_data()) return true;
#endif
return buffer_head != buffer_tail;
}
uint16_t keyboard_get_key(void) {
while (!keyboard_has_key()) {
hlt();
arch_halt();
}
#if defined(__aarch64__)
if (uart_pl011_has_data()) {
char c = uart_pl011_getc();
if (c == '\r') c = '\n';
return (uint16_t)(uint8_t)c;
}
#endif
uint16_t key = key_buffer[buffer_tail];
buffer_tail = (buffer_tail + 1) % KEYBOARD_BUFFER_SIZE;
return key;
+8 -3
View File
@@ -12,16 +12,17 @@ typedef struct {
static tty_t ttys[MAX_TTYS];
static int current_tty = 0;
static volatile uint16_t* const VGA_MEM = (uint16_t*)VGA_MEMORY;
static void tty_render_current(void) {
#if defined(__x86_64__)
volatile uint16_t* const vga_mem = (uint16_t*)VGA_MEMORY;
tty_t* t = &ttys[current_tty];
for (int y = 0; y < TTY_HEIGHT; y++) {
for (int x = 0; x < TTY_WIDTH; x++) {
VGA_MEM[y * TTY_WIDTH + x] = t->buffer[y][x];
vga_mem[y * TTY_WIDTH + x] = t->buffer[y][x];
}
}
vga_set_cursor(t->cursor_row, t->cursor_col);
#endif
}
void tty_switch(int index) {
@@ -62,7 +63,9 @@ void tty_set_cursor(int row, int col) {
tty_t* t = &ttys[current_tty];
t->cursor_row = row;
t->cursor_col = col;
#if defined(__x86_64__)
vga_set_cursor(row, col);
#endif
}
void tty_write(const char* data, size_t size) {
@@ -150,7 +153,9 @@ void tty_write_string(const char* data) {
}
void tty_init(void) {
#if defined(__x86_64__)
vga_init();
#endif
for (int i = 0; i < MAX_TTYS; i++) {
ttys[i].cursor_row = 0;
ttys[i].cursor_col = 0;
+16
View File
@@ -0,0 +1,16 @@
#ifndef _ARCH_AARCH64_ARCH_H
#define _ARCH_AARCH64_ARCH_H
#include <stdint.h>
#include <stdbool.h>
typedef struct {
uint64_t r[31]; // X0 - X30
uint64_t sp;
uint64_t pc;
uint64_t pstate;
} __attribute__((packed)) aarch64_context_t;
void aarch64_init(void);
#endif // _ARCH_AARCH64_ARCH_H
+24
View File
@@ -0,0 +1,24 @@
#ifndef _ARCH_AARCH64_CPU_H
#define _ARCH_AARCH64_CPU_H
#include <stdint.h>
#include <stdbool.h>
typedef struct {
uint32_t implementer;
uint32_t variant;
uint32_t architecture;
uint32_t part_num;
uint32_t revision;
char model_name[64];
uint32_t current_el;
uint64_t core_frequency_hz;
} aarch64_cpu_info_t;
void aarch64_cpu_init(void);
const aarch64_cpu_info_t* aarch64_get_cpu_info(void);
uint32_t aarch64_get_current_el(void);
uint64_t aarch64_get_midr(void);
uint64_t aarch64_get_mpidr(void);
#endif // _ARCH_AARCH64_CPU_H
+34
View File
@@ -0,0 +1,34 @@
#ifndef _ARCH_AARCH64_GIC_H
#define _ARCH_AARCH64_GIC_H
#include <stdint.h>
#include <stdbool.h>
#define GIC_DIST_BASE 0x08000000
#define GIC_CPU_BASE 0x08010000
// GIC Distributor Registers
#define GICD_CTLR 0x000
#define GICD_TYPER 0x004
#define GICD_ISENABLER(n) (0x100 + ((n) * 4))
#define GICD_ICENABLER(n) (0x180 + ((n) * 4))
#define GICD_IPRIORITYR(n) (0x400 + ((n) * 4))
#define GICD_ITARGETSR(n) (0x800 + ((n) * 4))
#define GICD_ICFGR(n) (0xC00 + ((n) * 4))
// GIC CPU Interface Registers
#define GICC_CTLR 0x0000
#define GICC_PMR 0x0004
#define GICC_BPR 0x0008
#define GICC_IAR 0x000C
#define GICC_EOIR 0x0010
typedef void (*gic_irq_handler_t)(uint32_t irq);
void gic_init(void);
void gic_enable_irq(uint32_t irq);
void gic_disable_irq(uint32_t irq);
void gic_register_handler(uint32_t irq, gic_irq_handler_t handler);
void gic_handle_irq(void);
#endif // _ARCH_AARCH64_GIC_H
+95
View File
@@ -0,0 +1,95 @@
#ifndef _ARCH_AARCH64_IO_H
#define _ARCH_AARCH64_IO_H
#include <stdint.h>
static inline void mmio_write8(uintptr_t reg, uint8_t val) {
*(volatile uint8_t*)reg = val;
}
static inline uint8_t mmio_read8(uintptr_t reg) {
return *(volatile uint8_t*)reg;
}
static inline void mmio_write16(uintptr_t reg, uint16_t val) {
*(volatile uint16_t*)reg = val;
}
static inline uint16_t mmio_read16(uintptr_t reg) {
return *(volatile uint16_t*)reg;
}
static inline void mmio_write32(uintptr_t reg, uint32_t val) {
*(volatile uint32_t*)reg = val;
}
static inline uint32_t mmio_read32(uintptr_t reg) {
return *(volatile uint32_t*)reg;
}
static inline void mmio_write64(uintptr_t reg, uint64_t val) {
*(volatile uint64_t*)reg = val;
}
static inline uint64_t mmio_read64(uintptr_t reg) {
return *(volatile uint64_t*)reg;
}
// Memory barriers
static inline void dsb(void) {
__asm__ volatile("dsb sy" ::: "memory");
}
static inline void dmb(void) {
__asm__ volatile("dmb sy" ::: "memory");
}
static inline void isb(void) {
__asm__ volatile("isb" ::: "memory");
}
// x86 I/O Port Emulation / Stubs for Portable Device Drivers
static inline void outb(uint16_t port, uint8_t val) {
(void)port; (void)val;
}
static inline uint8_t inb(uint16_t port) {
(void)port;
return 0;
}
static inline void outw(uint16_t port, uint16_t val) {
(void)port; (void)val;
}
static inline uint16_t inw(uint16_t port) {
(void)port;
return 0;
}
static inline void outl(uint16_t port, uint32_t val) {
(void)port; (void)val;
}
static inline uint32_t inl(uint16_t port) {
(void)port;
return 0;
}
static inline void io_wait(void) {
__asm__ volatile("nop");
}
static inline void cli(void) {
__asm__ volatile("msr daifset, #2" ::: "memory");
}
static inline void sti(void) {
__asm__ volatile("msr daifclr, #2" ::: "memory");
}
static inline void hlt(void) {
__asm__ volatile("wfi");
}
#endif // _ARCH_AARCH64_IO_H
+39
View File
@@ -0,0 +1,39 @@
#ifndef _ARCH_AARCH64_MMU_H
#define _ARCH_AARCH64_MMU_H
#include <stdint.h>
#include <stdbool.h>
#define MMU_PAGE_SIZE 4096
// Memory Types / Attributes index for MAIR_EL1
#define MT_DEVICE_nGnRnE 0
#define MT_NORMAL_NC 1
#define MT_NORMAL_WB 2
#define MAIR_DEVICE_nGnRnE 0x00
#define MAIR_NORMAL_NC 0x44
#define MAIR_NORMAL_WB 0xFF
#define MAIR_VAL ((MAIR_DEVICE_nGnRnE << (MT_DEVICE_nGnRnE * 8)) | \
(MAIR_NORMAL_NC << (MT_NORMAL_NC * 8)) | \
(MAIR_NORMAL_WB << (MT_NORMAL_WB * 8)))
// Page descriptor bits
#define PTE_VALID (1ULL << 0)
#define PTE_TABLE (1ULL << 1)
#define PTE_BLOCK (0ULL << 1)
#define PTE_USER (1ULL << 6)
#define PTE_RO (1ULL << 7)
#define PTE_SH_INNER (3ULL << 8)
#define PTE_AF (1ULL << 10)
#define PTE_NG (1ULL << 11)
#define PTE_PXN (1ULL << 53)
#define PTE_UXN (1ULL << 54)
#define PTE_ATTRINDX(x) (((uint64_t)(x)) << 2)
void aarch64_mmu_init(void);
void aarch64_mmu_map_2mb(uint64_t virt_addr, uint64_t phys_addr, uint32_t mem_type);
#endif // _ARCH_AARCH64_MMU_H
+13
View File
@@ -0,0 +1,13 @@
#ifndef _ARCH_AARCH64_TIMER_H
#define _ARCH_AARCH64_TIMER_H
#include <stdint.h>
#define ARCH_TIMER_VIRT_IRQ 27
void aarch64_timer_init(uint32_t freq_hz);
uint64_t aarch64_timer_get_ticks(void);
uint64_t aarch64_timer_get_freq(void);
void aarch64_timer_handle_irq(void);
#endif // _ARCH_AARCH64_TIMER_H
+34
View File
@@ -0,0 +1,34 @@
#ifndef _ARCH_AARCH64_UART_H
#define _ARCH_AARCH64_UART_H
#include <stdint.h>
#include <stddef.h>
#define PL011_UART0_BASE 0x09000000
// PL011 Registers
#define UARTDR 0x000
#define UARTRSR 0x004
#define UARTFR 0x018
#define UARTILPR 0x020
#define UARTIBRD 0x024
#define UARTFBRD 0x028
#define UARTLCR 0x02C
#define UARTCR 0x030
#define UARTIFLS 0x034
#define UARTIMSC 0x038
#define UARTRIS 0x03C
#define UARTMIS 0x040
#define UARTICR 0x044
// Flag register bits
#define UARTFR_TXFF (1 << 5)
#define UARTFR_RXFE (1 << 4)
void uart_pl011_init(void);
void uart_pl011_putc(char c);
void uart_pl011_puts(const char* str);
char uart_pl011_getc(void);
int uart_pl011_has_data(void);
#endif // _ARCH_AARCH64_UART_H
+96
View File
@@ -0,0 +1,96 @@
#ifndef _ARCH_ARCH_H
#define _ARCH_ARCH_H
#include <stdint.h>
#include <stdbool.h>
#if defined(__x86_64__)
#define ARCH_NAME "x86_64"
#define ARCH_IS_64BIT 1
#include <arch/x86_64/gdt.h>
#include <arch/x86_64/idt.h>
#include <arch/x86_64/isr.h>
#include <arch/x86_64/pic.h>
#include <arch/x86_64/pit.h>
#include <arch/x86_64/cpuid.h>
#include <arch/x86_64/paging.h>
#include <arch/x86_64/io.h>
static inline void arch_enable_interrupts(void) {
__asm__ volatile("sti");
}
static inline void arch_disable_interrupts(void) {
__asm__ volatile("cli");
}
static inline void arch_halt(void) {
__asm__ volatile("hlt");
}
static inline void arch_wait_for_interrupt(void) {
__asm__ volatile("sti; hlt");
}
static inline uint64_t arch_get_ticks(void) {
return pit_get_ticks();
}
static inline void arch_sleep(uint32_t ms) {
pit_sleep(ms);
}
#elif defined(__aarch64__) || defined(__arm64__)
#define ARCH_NAME "aarch64"
#define ARCH_IS_64BIT 1
#include <arch/aarch64/arch.h>
#include <arch/aarch64/cpu.h>
#include <arch/aarch64/gic.h>
#include <arch/aarch64/timer.h>
#include <arch/aarch64/mmu.h>
#include <arch/aarch64/uart.h>
#include <arch/aarch64/io.h>
static inline void arch_enable_interrupts(void) {
__asm__ volatile("msr daifclr, #2" ::: "memory");
}
static inline void arch_disable_interrupts(void) {
__asm__ volatile("msr daifset, #2" ::: "memory");
}
static inline void arch_halt(void) {
__asm__ volatile("wfi");
}
static inline void arch_wait_for_interrupt(void) {
__asm__ volatile("msr daifclr, #2; wfi" ::: "memory");
}
static inline uint64_t arch_get_ticks(void) {
return aarch64_timer_get_ticks();
}
static inline void arch_sleep(uint32_t ms) {
uint64_t count = (ms > 10) ? (ms / 10) : 1;
uint64_t target = aarch64_timer_get_ticks() + count;
while (aarch64_timer_get_ticks() < target) {
__asm__ volatile("wfi");
}
}
// Prototype declarations for timer/interrupt compatibility
uint64_t pit_get_ticks(void);
void pit_sleep(uint32_t ms);
#else
#error "Unsupported Target CPU Architecture!"
#endif
// Generic Architecture API
void arch_early_init(void);
void arch_init(void);
const char* arch_get_name(void);
uint32_t arch_get_cpu_id(void);
#endif // _ARCH_ARCH_H
+8
View File
@@ -25,9 +25,17 @@ typedef struct {
} cpu_info_t;
static inline void cpuid(uint32_t leaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
#if defined(__x86_64__)
__asm__ volatile("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(leaf), "c"(0));
#else
(void)leaf;
if (eax) *eax = 0;
if (ebx) *ebx = 0;
if (ecx) *ecx = 0;
if (edx) *edx = 0;
#endif
}
void cpuid_detect(cpu_info_t* info);
+18
View File
@@ -3,6 +3,8 @@
#include <stdint.h>
#if defined(__x86_64__)
static inline void outb(uint16_t port, uint8_t val) {
__asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
}
@@ -49,4 +51,20 @@ static inline void hlt(void) {
__asm__ volatile ("hlt");
}
#else
// Portable Stubs for non-x86 architectures
static inline void outb(uint16_t port, uint8_t val) { (void)port; (void)val; }
static inline uint8_t inb(uint16_t port) { (void)port; return 0; }
static inline void outw(uint16_t port, uint16_t val) { (void)port; (void)val; }
static inline uint16_t inw(uint16_t port) { (void)port; return 0; }
static inline void outl(uint16_t port, uint32_t val) { (void)port; (void)val; }
static inline uint32_t inl(uint16_t port) { (void)port; return 0; }
static inline void io_wait(void) { }
static inline void cli(void) { __asm__ volatile("msr daifset, #2" ::: "memory"); }
static inline void sti(void) { __asm__ volatile("msr daifclr, #2" ::: "memory"); }
static inline void hlt(void) { __asm__ volatile("wfi"); }
#endif
#endif // _ARCH_X86_64_IO_H
+48
View File
@@ -0,0 +1,48 @@
/* Automatically generated by SUB-OS Kconfig. Do not edit. */
#ifndef _AUTOCONF_H
#define _AUTOCONF_H
#define CONFIG_ARCH "aarch64"
#define CONFIG_ARCH_AARCH64 1
#define CONFIG_BPF_VM 1
#define CONFIG_DRV_AHCI 1
#define CONFIG_DRV_ATA 1
#define CONFIG_DRV_BOCHS_VBE 1
#define CONFIG_DRV_CANVAS_2D 1
#define CONFIG_DRV_E1000 1
#define CONFIG_DRV_HWMON 1
#define CONFIG_DRV_NVME 1
#define CONFIG_DRV_PTY 1
#define CONFIG_DRV_RAMDISK 1
#define CONFIG_DRV_RTL8139 1
#define CONFIG_DRV_SOUND_AC97 1
#define CONFIG_DRV_SOUND_HDA 1
#define CONFIG_DRV_USB_XHCI 1
#define CONFIG_DRV_VIRTIO_BLK 1
#define CONFIG_DRV_VIRTIO_NET 1
#define CONFIG_DRV_VIRTIO_RNG 1
#define CONFIG_FS_DEVFS 1
#define CONFIG_FS_EXT2 1
#define CONFIG_FS_FAT32 1
#define CONFIG_FS_PROCFS 1
#define CONFIG_FS_RAMFS 1
#define CONFIG_FS_SYSFS 1
#define CONFIG_FS_VFS 1
#define CONFIG_IO_URING 1
#define CONFIG_MM_PMM 1
#define CONFIG_MM_SLAB 1
#define CONFIG_MM_VMA 1
#define CONFIG_NET_FILTER 1
#define CONFIG_NET_HTTPD 1
#define CONFIG_NET_SSHD 1
#define CONFIG_NET_STACK 1
#define CONFIG_OPTIMIZATION "-O2"
#define CONFIG_PREEMPT 1
#define CONFIG_SECURITY_KEYRING 1
#define CONFIG_SECURITY_LSM 1
#define CONFIG_SMP 1
#define CONFIG_SUBOS_HOSTNAME "sub-os"
#define CONFIG_SUBOS_VERSION "0.2.0-lts"
#define CONFIG_USERLAND_LAZYBOX 1
#endif /* _AUTOCONF_H */
+12 -1
View File
@@ -5,9 +5,20 @@
#define SUBOS_VERSION_MINOR 2
#define SUBOS_VERSION_PATCH 0
#define SUBOS_VERSION_CODENAME "Titan"
#if defined(__x86_64__)
#define SUBOS_VERSION_STRING "0.2.0-lts (x86_64)"
#define SUBOS_BUILD_TARGET "x86_64-elf-baremetal"
#define SUBOS_COMPILER "x86_64-elf-gcc (Modular Monolithic)"
#define SUBOS_COMPILER "x86_64-elf-gcc"
#elif defined(__aarch64__)
#define SUBOS_VERSION_STRING "0.2.0-lts (aarch64)"
#define SUBOS_BUILD_TARGET "aarch64-linux-gnu-baremetal"
#define SUBOS_COMPILER "aarch64-linux-gnu-gcc"
#else
#define SUBOS_VERSION_STRING "0.2.0-lts (generic)"
#define SUBOS_BUILD_TARGET "generic-elf-baremetal"
#define SUBOS_COMPILER "gcc"
#endif
const char* kernel_get_version(void);
const char* kernel_get_build_banner(void);
+1 -1
View File
@@ -3,7 +3,7 @@
#include "types.h"
#include "printk.h"
#include <arch/x86_64/io.h>
#include <arch/arch.h>
#define KERNEL_NAME "SUB-OS"
#define KERNEL_VERSION "0.2.0-lts"
+6
View File
@@ -16,7 +16,13 @@ static inline void spinlock_init(spinlock_t* lock) {
static inline void spin_lock(spinlock_t* lock) {
while (__atomic_test_and_set(&lock->lock, __ATOMIC_ACQUIRE)) {
#if defined(__x86_64__)
__asm__ volatile ("pause");
#elif defined(__aarch64__)
__asm__ volatile ("yield");
#else
__asm__ volatile ("");
#endif
}
}
+101 -86
View File
@@ -17,13 +17,7 @@
#include <mm/vma.h>
#include <drivers/canvas.h>
#include <drivers/pty.h>
#include <arch/x86_64/gdt.h>
#include <arch/x86_64/idt.h>
#include <arch/x86_64/isr.h>
#include <arch/x86_64/pic.h>
#include <arch/x86_64/pit.h>
#include <arch/x86_64/cpuid.h>
#include <arch/x86_64/paging.h>
#include <arch/arch.h>
#include <mm/pmm.h>
#include <mm/kmalloc.h>
#include <mm/slab.h>
@@ -81,83 +75,41 @@
#include <userland/sh.h>
#include <userland/shell.h>
void kernel_main(void* memory_map, uint64_t memory_map_count) {
// 1. Console & Telemetry
tty_init();
serial_init();
printk_init();
printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET);
printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit Production Modular Monolithic Kernel %s\n" ANSI_RESET, kernel_get_version());
printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET);
// 2. Early Boot Parameters & RTC Real-Time Clock
init_early("root=/dev/sda console=tty1 init=/bin/lazybox quiet");
rtc_init();
// 3. CPU Architecture & Interrupts
printk(KERN_INFO "[1/18] Initializing 64-Bit GDT & TSS... ");
gdt_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[2/18] Initializing Interrupt Descriptor Table (IDT & ISRs)... ");
idt_init();
isr_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[3/18] Remapping Dual 8259A PIC Controller... ");
pic_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[4/18] Configuring 8254 PIT Timer & High-Res Timer Wheel... ");
pit_init(100);
timer_wheel_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 4. Input & Power Drivers
printk(KERN_INFO "[5/18] Initializing PS/2 Keyboard, Mouse & ACPI... ");
keyboard_init();
mouse_init();
acpi_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 5. Memory Management: PMM + Dynamic Heap + SLAB Cache
printk(KERN_INFO "[6/18] Initializing Physical PMM, Dynamic Heap & SLAB Cache... ");
pmm_init(memory_map, memory_map_count);
heap_init();
slab_init();
vma_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 6. Storage & Block Layer
printk(KERN_INFO "[7/18] Initializing Block Layer, Ramdisk & Storage Controllers... ");
static void subos_modular_core_boot(void) {
// Storage & Block Layer
printk(KERN_INFO "[4/14] Initializing Block Layer & Storage Controllers... ");
block_init();
ramdisk_init();
#if defined(__x86_64__)
ata_init();
ahci_init();
nvme_init();
#endif
virtio_blk_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 7. Bus & Devices
printk(KERN_INFO "[8/18] Enumerating PCI Bus, VirtIO, xHCI, VBE, Canvas & PTY... ");
// Bus & Devices
printk(KERN_INFO "[5/14] Enumerating System Devices, Canvas & PTY... ");
#if defined(__x86_64__)
pci_init();
virt_init();
fb_init();
bochs_vbe_init();
canvas_init();
pty_init();
usb_init();
xhci_init();
virtio_rng_init();
hwmon_init();
#endif
canvas_init();
pty_init();
virtio_rng_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 7. Network Subsystem, NetFilter, HTTPD & SSH Server
printk(KERN_INFO "[9/18] Initializing Network Stack, NetFilter, HTTPD & SSHD... ");
// Network Subsystem, NetFilter, HTTPD & SSH Server
printk(KERN_INFO "[6/14] Initializing Network Stack, NetFilter, HTTPD & SSHD... ");
filter_init();
httpd_init();
sshd_init();
#if defined(__x86_64__)
rtl8139_init();
virtio_net_init();
if (e1000_init()) {
@@ -171,16 +123,22 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) {
} else {
printk(ANSI_YELLOW "No NIC detected\n" ANSI_RESET);
}
#else
virtio_net_init();
printk(ANSI_BRIGHT_GREEN "Online\n" ANSI_RESET);
#endif
// 8. Sound & Voice Synthesizer
printk(KERN_INFO "[10/18] Initializing Sound Architecture, Melody Player & Formant TTS... ");
// Sound & Voice Synthesizer
#if defined(__x86_64__)
printk(KERN_INFO "[7/14] Initializing Sound Architecture, Melody Player & Formant TTS... ");
sound_init();
hda_init();
melody_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
#endif
// 9. Crypto, Certificates, LSM Security, Authentication & Namespaces
printk(KERN_INFO "[11/18] Initializing X.509 Keyring, Shadow Auth & Namespaces... ");
// Crypto, Certificates, LSM Security, Authentication & Namespaces
printk(KERN_INFO "[8/14] Initializing X.509 Keyring, Shadow Auth & Namespaces... ");
prng_seed(0, 0);
certs_init();
security_init();
@@ -188,18 +146,18 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) {
namespace_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 10. Inter-Process Communication
printk(KERN_INFO "[12/18] Initializing IPC Engine (Pipes, MsgQueues, SHM, Semaphores)... ");
// Inter-Process Communication
printk(KERN_INFO "[9/14] Initializing IPC Engine (Pipes, MsgQueues, SHM, Semaphores)... ");
ipc_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 11. Asynchronous I/O Engine
printk(KERN_INFO "[13/18] Initializing io_uring Async Ring Engine... ");
// Asynchronous I/O Engine
printk(KERN_INFO "[10/14] Initializing io_uring Async Ring Engine... ");
io_uring_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 12. Virtual File System & Multi-Filesystem Support
printk(KERN_INFO "[14/18] Mounting Virtual File System (VFS, devfs, procfs, sysfs)... ");
// Virtual File System & Multi-Filesystem Support
printk(KERN_INFO "[11/14] Mounting Virtual File System (VFS, devfs, procfs, sysfs)... ");
vfs_init();
sysfs_init();
kobject_subsystem_init();
@@ -208,8 +166,8 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) {
initramfs_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 13. Kernel Core: Signals, Modules, Syscalls, Tracing, Syslog, Metrics, Crond & Systemd
printk(KERN_INFO "[15/18] Initializing Syslog, Metrics, Cron, Tracing, BPF & Services... ");
// Kernel Core: Signals, Modules, Syscalls, Tracing, Syslog, Metrics, Crond & Systemd
printk(KERN_INFO "[12/14] Initializing Syslog, Metrics, Cron, Tracing, BPF & Services... ");
signal_init();
workqueue_init();
syscall_init();
@@ -222,25 +180,82 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) {
service_manager_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 14. Preemptive Multi-Tasking & Userland
printk(KERN_INFO "[16/18] Initializing Preemptive Task Scheduler & LazyBox... ");
// Preemptive Multi-Tasking & Userland
printk(KERN_INFO "[13/14] Initializing Preemptive Task Scheduler & LazyBox... ");
sched_init();
lazybox_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// 15. Hardware Interrupts
printk(KERN_INFO "[17/18] Enabling Hardware Interrupts... ");
sti();
// Hardware Interrupts
printk(KERN_INFO "[14/14] Enabling Hardware Interrupts... ");
arch_enable_interrupts();
printk(ANSI_BRIGHT_GREEN "ACTIVE\n" ANSI_RESET);
// 16. Welcome & Launch Shell
printk(KERN_INFO "[18/18] Launching Userland Shell on TTY1... ");
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Launch Shell
#if defined(__x86_64__)
tty_clear();
#endif
shell_run();
while (1) {
hlt();
arch_halt();
}
}
#if defined(__x86_64__)
void kernel_main(void* memory_map, uint64_t memory_map_count) {
tty_init();
serial_init();
printk_init();
printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET);
printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version());
printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET);
init_early("root=/dev/sda console=tty1 init=/bin/lazybox quiet");
rtc_init();
printk(KERN_INFO "[1/14] Initializing 64-Bit GDT, IDT, PIC & PIT Timer... ");
arch_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[2/14] Initializing PS/2 Keyboard, Mouse & ACPI... ");
keyboard_init();
mouse_init();
acpi_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[3/14] Initializing Physical PMM, Dynamic Heap & SLAB Cache... ");
pmm_init(memory_map, memory_map_count);
heap_init();
slab_init();
vma_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
subos_modular_core_boot();
}
#elif defined(__aarch64__)
void kernel_main_aarch64(void) {
arch_early_init();
printk_init();
printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET);
printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version());
printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET);
init_early("root=/dev/vda console=ttyAMA0 init=/bin/lazybox quiet");
printk(KERN_INFO "[1/14] Initializing AArch64 CPU, GICv2, Generic Timer & MMU... ");
arch_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[2/14] Initializing Physical PMM, Dynamic Heap & SLAB Cache... ");
pmm_init(NULL, 0);
heap_init();
slab_init();
vma_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
subos_modular_core_boot();
}
#endif
+4 -4
View File
@@ -1,10 +1,10 @@
#include <kernel/panic.h>
#include <kernel/printk.h>
#include <drivers/tty.h>
#include <arch/x86_64/io.h>
#include <arch/arch.h>
void panic_with_regs(const char* message, const registers_t* regs) {
cli();
arch_disable_interrupts();
printk("\n" ANSI_BRIGHT_RED "================================================================================" ANSI_RESET "\n");
printk(ANSI_BRIGHT_RED " *** KERNEL PANIC - SYSTEM HALTED *** " ANSI_RESET "\n");
@@ -12,7 +12,7 @@ void panic_with_regs(const char* message, const registers_t* regs) {
printk(ANSI_BRIGHT_WHITE "Reason: " ANSI_YELLOW "%s" ANSI_RESET "\n\n", message ? message : "Unknown Fault");
if (regs) {
printk(ANSI_BRIGHT_CYAN "CPU Register State (x86_64 AMD64 ABI):" ANSI_RESET "\n");
printk(ANSI_BRIGHT_CYAN "CPU Register State:" ANSI_RESET "\n");
printk(" RIP: %016llx CS: %04llx RFLAGS: %016llx\n", regs->rip, regs->cs, regs->rflags);
printk(" RSP: %016llx SS: %04llx RBP: %016llx\n", regs->rsp, regs->ss, regs->rbp);
printk(" RAX: %016llx RBX: %016llx RCX: %016llx RDX: %016llx\n", regs->rax, regs->rbx, regs->rcx, regs->rdx);
@@ -24,7 +24,7 @@ void panic_with_regs(const char* message, const registers_t* regs) {
printk("\n" ANSI_BRIGHT_YELLOW "Please power off or reset your system." ANSI_RESET "\n");
while (1) {
hlt();
arch_halt();
}
}
+8 -1
View File
@@ -45,10 +45,17 @@ int vprintk(const char* fmt, va_list args) {
// 1. Output to active TTY console
tty_write(display_ptr, (size_t)len);
// 2. Output to COM1 serial port for host debugging
// 2. Output to serial console (COM1 on x86, PL011 on AArch64)
#if defined(__aarch64__)
extern void uart_pl011_putc(char c);
for (int i = 0; i < len; i++) {
uart_pl011_putc(display_ptr[i]);
}
#else
for (int i = 0; i < len; i++) {
serial_write_char(display_ptr[i]);
}
#endif
// 3. Store in kernel dmesg ring buffer
dmesg_append(display_ptr, (size_t)len);
+2 -1
View File
@@ -2,6 +2,7 @@
#include <kernel/sched.h>
#include <mm/kmalloc.h>
#include <lib/string.h>
#include <arch/arch.h>
static pid_t next_pid = 1;
static task_t* current_task = NULL;
@@ -55,7 +56,7 @@ void task_exit(int exit_code) {
sched_yield();
}
while (1) {
__asm__ volatile("hlt");
arch_halt();
}
}
+1 -1
View File
@@ -5,7 +5,7 @@
#include <kernel/printk.h>
#define HEAP_MAGIC 0x53554248 // "SUBH"
#define HEAP_INITIAL_PAGES 1024 // 4 MB initial kernel heap
#define HEAP_INITIAL_PAGES 4096 // 16 MB initial kernel heap
typedef struct heap_block {
uint32_t magic;
+25 -5
View File
@@ -49,18 +49,38 @@ void pmm_init(void* memory_map, uint64_t memory_map_count) {
// Fallback if no E820 usable regions
if (usable_memory_bytes == 0 || total_pages == 0) {
#if defined(__aarch64__)
uint64_t dram_start = 0x40000000;
uint64_t dram_size = 128ULL * 1024 * 1024;
uint64_t start_page = dram_start / PMM_PAGE_SIZE;
uint64_t count_pages = dram_size / PMM_PAGE_SIZE;
total_pages = start_page + count_pages;
total_memory_bytes = dram_size;
usable_memory_bytes = dram_size;
for (uint64_t p = 0; p < count_pages; p++) {
bitmap_clear(page_bitmap, start_page + p);
}
// Reserve kernel & boot area (0x40000000 - 0x40800000: 8MB / 2048 pages)
for (uint64_t p = start_page; p < start_page + 2048; p++) {
bitmap_set(page_bitmap, p);
}
#else
total_pages = 32768; // 128 MB
total_memory_bytes = 128ULL * 1024 * 1024;
usable_memory_bytes = 128ULL * 1024 * 1024;
for (uint64_t p = 0; p < total_pages; p++) {
bitmap_clear(page_bitmap, p);
}
}
// Reserve lower 4 MB (bootloader, page tables, kernel image)
size_t kernel_reserved_pages = (4 * 1024 * 1024) / PMM_PAGE_SIZE; // 1024 pages
for (size_t p = 0; p < kernel_reserved_pages; p++) {
bitmap_set(page_bitmap, p);
// Reserve lower 4 MB (bootloader, page tables, kernel image)
size_t kernel_reserved_pages = (4 * 1024 * 1024) / PMM_PAGE_SIZE; // 1024 pages
for (size_t p = 0; p < kernel_reserved_pages; p++) {
bitmap_set(page_bitmap, p);
}
#endif
}
// Count actual used pages (bits set in bitmap up to total_pages)
+2 -2
View File
@@ -5,7 +5,7 @@
#include <lib/string.h>
#include <lib/printf.h>
#include <mm/kmalloc.h>
#include <arch/x86_64/pit.h>
#include <arch/arch.h>
#include <kernel/printk.h>
#define MAX_ARP_ENTRIES 16
@@ -288,7 +288,7 @@ int net_ping(uint32_t target_ip, uint32_t count, uint32_t timeout_ms) {
if (wait_ticks == 0) wait_ticks = 100;
while (!ping_received && (pit_get_ticks() - t_start < wait_ticks)) {
__asm__ volatile ("hlt");
arch_halt();
}
if (ping_received && ping_id == p_id && ping_seq == seq) {
+386
View File
@@ -0,0 +1,386 @@
#!/usr/bin/env python3
"""
SUB-OS Linux-Style Interactive Kconfig Menuconfig (TUI)
Provides a full curses-based terminal configuration UI matching Linux menuconfig.
Generates .config and include/config/autoconf.h.
"""
import sys
import os
import curses
CONFIG_FILE = ".config"
AUTOCONF_HEADER = "include/config/autoconf.h"
DEFAULTS = {
# Architecture
"CONFIG_ARCH": "x86_64",
"CONFIG_ARCH_X86_64": True,
"CONFIG_ARCH_AARCH64": False,
"CONFIG_ARCH_ARMV8I": False,
# General Setup
"CONFIG_SUBOS_HOSTNAME": "sub-os",
"CONFIG_SUBOS_VERSION": "0.2.0-lts",
"CONFIG_SMP": True,
"CONFIG_PREEMPT": True,
"CONFIG_OPTIMIZATION": "-O2",
# Memory Management
"CONFIG_MM_PMM": True,
"CONFIG_MM_SLAB": True,
"CONFIG_MM_VMA": True,
# Filesystems
"CONFIG_FS_VFS": True,
"CONFIG_FS_FAT32": True,
"CONFIG_FS_EXT2": True,
"CONFIG_FS_RAMFS": True,
"CONFIG_FS_DEVFS": True,
"CONFIG_FS_PROCFS": True,
"CONFIG_FS_SYSFS": True,
# Storage Drivers
"CONFIG_DRV_NVME": True,
"CONFIG_DRV_AHCI": True,
"CONFIG_DRV_ATA": True,
"CONFIG_DRV_VIRTIO_BLK": True,
"CONFIG_DRV_RAMDISK": True,
# Network Drivers & Stack
"CONFIG_NET_STACK": True,
"CONFIG_DRV_E1000": True,
"CONFIG_DRV_RTL8139": True,
"CONFIG_DRV_VIRTIO_NET": True,
"CONFIG_NET_HTTPD": True,
"CONFIG_NET_SSHD": True,
"CONFIG_NET_FILTER": True,
# Audio & Display
"CONFIG_DRV_SOUND_HDA": True,
"CONFIG_DRV_SOUND_AC97": True,
"CONFIG_DRV_BOCHS_VBE": True,
"CONFIG_DRV_CANVAS_2D": True,
# Bus, Sensors & Crypto
"CONFIG_DRV_USB_XHCI": True,
"CONFIG_DRV_HWMON": True,
"CONFIG_DRV_VIRTIO_RNG": True,
"CONFIG_DRV_PTY": True,
# Security & Advanced
"CONFIG_SECURITY_LSM": True,
"CONFIG_SECURITY_KEYRING": True,
"CONFIG_BPF_VM": True,
"CONFIG_IO_URING": True,
"CONFIG_USERLAND_LAZYBOX": True,
}
MENU_STRUCTURE = [
{
"title": "Target Architecture Selection",
"type": "submenu",
"items": [
{"name": "CONFIG_ARCH_X86_64", "label": "x86_64 (64-Bit AMD64/Intel x86-64)", "type": "radio", "group": "arch", "val": "x86_64"},
{"name": "CONFIG_ARCH_AARCH64", "label": "aarch64 (ARMv8-A 64-Bit Cortex/Neoverse)", "type": "radio", "group": "arch", "val": "aarch64"},
{"name": "CONFIG_ARCH_ARMV8I", "label": "armv8i (ARMv8 Instruction Set Profile)", "type": "radio", "group": "arch", "val": "armv8i"},
]
},
{
"title": "General Kernel Setup",
"type": "submenu",
"items": [
{"name": "CONFIG_SMP", "label": "Symmetric Multi-Processing (SMP) Support", "type": "bool"},
{"name": "CONFIG_PREEMPT", "label": "Preemptive Kernel Scheduling Model", "type": "bool"},
{"name": "CONFIG_BPF_VM", "label": "In-Kernel eBPF Register Virtual Machine", "type": "bool"},
{"name": "CONFIG_IO_URING", "label": "High-Performance io_uring Ring Buffers", "type": "bool"},
]
},
{
"title": "Virtual File Systems & Storage Drivers",
"type": "submenu",
"items": [
{"name": "CONFIG_FS_FAT32", "label": "FAT32 / VFAT File System Driver", "type": "bool"},
{"name": "CONFIG_FS_EXT2", "label": "Second Extended (EXT2) Linux File System", "type": "bool"},
{"name": "CONFIG_FS_SYSFS", "label": "Sysfs KObject Virtual Hierarchy (/sys)", "type": "bool"},
{"name": "CONFIG_DRV_NVME", "label": "NVM Express (NVMe PCIe SSD) Driver", "type": "bool"},
{"name": "CONFIG_DRV_AHCI", "label": "AHCI SATA 6Gb/s SSD/HDD Controller Driver", "type": "bool"},
{"name": "CONFIG_DRV_VIRTIO_BLK", "label": "VirtIO Paravirtualized Block Storage (/dev/vda)", "type": "bool"},
]
},
{
"title": "Network Subsystem & Hardware Adapters",
"type": "submenu",
"items": [
{"name": "CONFIG_NET_STACK", "label": "TCP/IP Network Stack (IPv4, UDP, TCP)", "type": "bool"},
{"name": "CONFIG_DRV_E1000", "label": "Intel 82540EM Gigabit Ethernet NIC Driver", "type": "bool"},
{"name": "CONFIG_DRV_RTL8139", "label": "Realtek RTL8139 Fast Ethernet NIC Driver", "type": "bool"},
{"name": "CONFIG_DRV_VIRTIO_NET", "label": "VirtIO 10-Gigabit Paravirtualized NIC", "type": "bool"},
{"name": "CONFIG_NET_FILTER", "label": "NetFilter Stateful Packet Firewall (iptables)", "type": "bool"},
{"name": "CONFIG_NET_SSHD", "label": "In-Kernel Secure Shell (SSH) Daemon", "type": "bool"},
]
},
{
"title": "Device Drivers & Multimedia",
"type": "submenu",
"items": [
{"name": "CONFIG_DRV_CANVAS_2D", "label": "2D TrueColor Rasterizer Canvas Graphics Engine", "type": "bool"},
{"name": "CONFIG_DRV_BOCHS_VBE", "label": "Bochs / VBE Dynamic Resolution Display Adapter", "type": "bool"},
{"name": "CONFIG_DRV_SOUND_HDA", "label": "Intel High Definition Audio (Azalia HDA) Driver", "type": "bool"},
{"name": "CONFIG_DRV_SOUND_AC97", "label": "Analog Devices AC'97 Sound Codec Driver", "type": "bool"},
{"name": "CONFIG_DRV_USB_XHCI", "label": "USB 3.0 Extensible Host Controller (xHCI)", "type": "bool"},
{"name": "CONFIG_DRV_HWMON", "label": "HWMON CPU CoreTemp & Fan Tachometer Sensors", "type": "bool"},
{"name": "CONFIG_DRV_VIRTIO_RNG", "label": "VirtIO True Hardware Random Generator (/dev/hwrng)", "type": "bool"},
{"name": "CONFIG_DRV_PTY", "label": "Unix98 Pseudo-Terminal (PTY) Subsystem (/dev/pts)", "type": "bool"},
]
},
{
"title": "Security, LSM & Keyrings",
"type": "submenu",
"items": [
{"name": "CONFIG_SECURITY_LSM", "label": "Linux Security Module (LSM) Mandatory Access Control", "type": "bool"},
{"name": "CONFIG_SECURITY_KEYRING", "label": "X.509 Cryptographic Keyring & Certificates", "type": "bool"},
]
},
{
"title": "Userland Core & LazyBox",
"type": "submenu",
"items": [
{"name": "CONFIG_USERLAND_LAZYBOX", "label": "LazyBox Multi-Call Userland Utility Suite (70+ Tools)", "type": "bool"},
]
}
]
def load_config():
cfg = dict(DEFAULTS)
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, "r") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#"):
continue
if "=" in line:
k, v = line.split("=", 1)
k = k.strip()
v = v.strip().strip('"')
if v == "y":
cfg[k] = True
elif v == "n":
cfg[k] = False
else:
cfg[k] = v
return cfg
def save_config(cfg):
os.makedirs(os.path.dirname(AUTOCONF_HEADER), exist_ok=True)
with open(CONFIG_FILE, "w") as f_cfg, open(AUTOCONF_HEADER, "w") as f_hdr:
f_cfg.write("# Automatically generated by SUB-OS Kconfig TUI Configurator\n# Do not edit directly\n\n")
f_hdr.write("/* Automatically generated by SUB-OS Kconfig. Do not edit. */\n#ifndef _AUTOCONF_H\n#define _AUTOCONF_H\n\n")
# Write Architecture
arch = cfg.get("CONFIG_ARCH", "x86_64")
f_cfg.write(f"CONFIG_ARCH={arch}\n")
f_hdr.write(f'#define CONFIG_ARCH "{arch}"\n')
for k, v in sorted(cfg.items()):
if k == "CONFIG_ARCH":
continue
if isinstance(v, bool):
if v:
f_cfg.write(f"{k}=y\n")
f_hdr.write(f"#define {k} 1\n")
else:
f_cfg.write(f"# {k} is not set\n")
elif isinstance(v, str):
f_cfg.write(f'{k}="{v}"\n')
f_hdr.write(f'#define {k} "{v}"\n')
elif isinstance(v, int):
f_cfg.write(f"{k}={v}\n")
f_hdr.write(f"#define {k} {v}\n")
f_hdr.write("\n#endif /* _AUTOCONF_H */\n")
def run_tui(stdscr):
curses.curs_set(0)
curses.use_default_colors()
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_CYAN) # Header / Bar
curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLUE) # Main background
curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLUE) # Highlight title
curses.init_pair(4, curses.COLOR_BLACK, curses.COLOR_WHITE) # Selected row
curses.init_pair(5, curses.COLOR_CYAN, curses.COLOR_BLUE) # Subtext
cfg = load_config()
current_menu = MENU_STRUCTURE
menu_stack = []
cursor_stack = [0]
while True:
stdscr.bkgd(' ', curses.color_pair(2))
stdscr.clear()
max_y, max_x = stdscr.getmaxyx()
# Top Banner
header = f" SUB-OS v{cfg.get('CONFIG_SUBOS_VERSION', '0.2.0-lts')} ({cfg.get('CONFIG_ARCH', 'x86_64')}) Linux-Style Kernel Configuration "
stdscr.attron(curses.color_pair(1) | curses.A_BOLD)
stdscr.addstr(0, 0, header.center(max_x - 1)[:max_x - 1])
stdscr.attroff(curses.color_pair(1) | curses.A_BOLD)
# Subtitle
stdscr.attron(curses.color_pair(3) | curses.A_BOLD)
title_text = "Main Menu" if not menu_stack else menu_stack[-1]["title"]
stdscr.addstr(2, 4, f"-> {title_text}")
stdscr.attroff(curses.color_pair(3) | curses.A_BOLD)
# Instructions
stdscr.attron(curses.color_pair(5))
stdscr.addstr(3, 4, "Use [UP/DOWN] arrows, [SPACE] to toggle [*], [ENTER] for submenu, [S] to Save, [Q] to Exit")
stdscr.attroff(curses.color_pair(5))
# Items list
items = current_menu if not menu_stack else menu_stack[-1]["items"]
cur_idx = cursor_stack[-1]
if cur_idx >= len(items):
cur_idx = len(items) - 1
if cur_idx < 0:
cur_idx = 0
cursor_stack[-1] = cur_idx
box_top = 5
box_height = max_y - 8
for i, item in enumerate(items):
if i >= box_height:
break
y = box_top + i
is_sel = (i == cur_idx)
if "items" in item: # Submenu
display = f" ---> {item['title']}"
elif item.get("type") == "bool":
val = cfg.get(item["name"], False)
mark = "[*]" if val else "[ ]"
display = f" {mark} {item['label']}"
elif item.get("type") == "radio":
group_val = cfg.get("CONFIG_ARCH", "x86_64")
mark = "(*)" if group_val == item["val"] else "( )"
display = f" {mark} {item['label']}"
else:
display = f" {item.get('label', item.get('title', ''))}"
if is_sel:
stdscr.attron(curses.color_pair(4) | curses.A_BOLD)
stdscr.addstr(y, 4, display.ljust(max_x - 10)[:max_x - 10])
stdscr.attroff(curses.color_pair(4) | curses.A_BOLD)
else:
stdscr.attron(curses.color_pair(2))
stdscr.addstr(y, 4, display[:max_x - 10])
stdscr.attroff(curses.color_pair(2))
# Footer Status Bar
footer = " <Select> <Exit / Return> <Save Configuration> <Help> "
stdscr.attron(curses.color_pair(1))
stdscr.addstr(max_y - 1, 0, footer.center(max_x - 1)[:max_x - 1])
stdscr.attroff(curses.color_pair(1))
stdscr.refresh()
key = stdscr.getch()
if key in [curses.KEY_UP, ord('k')]:
if cursor_stack[-1] > 0:
cursor_stack[-1] -= 1
elif key in [curses.KEY_DOWN, ord('j')]:
if cursor_stack[-1] < len(items) - 1:
cursor_stack[-1] += 1
elif key in [curses.KEY_ENTER, 10, 13]:
sel_item = items[cursor_stack[-1]]
if "items" in sel_item:
menu_stack.append(sel_item)
cursor_stack.append(0)
elif sel_item.get("type") == "bool":
name = sel_item["name"]
cfg[name] = not cfg.get(name, False)
elif sel_item.get("type") == "radio":
cfg["CONFIG_ARCH"] = sel_item["val"]
if sel_item["val"] == "x86_64":
cfg["CONFIG_ARCH_X86_64"] = True
cfg["CONFIG_ARCH_AARCH64"] = False
cfg["CONFIG_ARCH_ARMV8I"] = False
elif sel_item["val"] == "aarch64":
cfg["CONFIG_ARCH_X86_64"] = False
cfg["CONFIG_ARCH_AARCH64"] = True
cfg["CONFIG_ARCH_ARMV8I"] = False
elif sel_item["val"] == "armv8i":
cfg["CONFIG_ARCH_X86_64"] = False
cfg["CONFIG_ARCH_AARCH64"] = False
cfg["CONFIG_ARCH_ARMV8I"] = True
elif key == ord(' '):
sel_item = items[cursor_stack[-1]]
if sel_item.get("type") == "bool":
name = sel_item["name"]
cfg[name] = not cfg.get(name, False)
elif sel_item.get("type") == "radio":
cfg["CONFIG_ARCH"] = sel_item["val"]
if sel_item["val"] == "x86_64":
cfg["CONFIG_ARCH_X86_64"] = True
cfg["CONFIG_ARCH_AARCH64"] = False
cfg["CONFIG_ARCH_ARMV8I"] = False
elif sel_item["val"] == "aarch64":
cfg["CONFIG_ARCH_X86_64"] = False
cfg["CONFIG_ARCH_AARCH64"] = True
cfg["CONFIG_ARCH_ARMV8I"] = False
elif sel_item["val"] == "armv8i":
cfg["CONFIG_ARCH_X86_64"] = False
cfg["CONFIG_ARCH_AARCH64"] = False
cfg["CONFIG_ARCH_ARMV8I"] = True
elif key in [ord('s'), ord('S')]:
save_config(cfg)
stdscr.attron(curses.color_pair(1) | curses.A_BOLD)
stdscr.addstr(max_y - 2, 4, f" Saved configuration to {CONFIG_FILE} and {AUTOCONF_HEADER}! Press any key... ")
stdscr.attroff(curses.color_pair(1) | curses.A_BOLD)
stdscr.refresh()
stdscr.getch()
elif key in [ord('q'), ord('Q'), 27]: # Esc or Q
if menu_stack:
menu_stack.pop()
cursor_stack.pop()
else:
save_config(cfg)
break
def defconfig(arch="x86_64"):
cfg = dict(DEFAULTS)
cfg["CONFIG_ARCH"] = arch
if arch == "x86_64":
cfg["CONFIG_ARCH_X86_64"] = True
cfg["CONFIG_ARCH_AARCH64"] = False
cfg["CONFIG_ARCH_ARMV8I"] = False
elif arch in ["aarch64", "armv8", "armv8i"]:
cfg["CONFIG_ARCH_X86_64"] = False
cfg["CONFIG_ARCH_AARCH64"] = True
cfg["CONFIG_ARCH_ARMV8I"] = (arch == "armv8i")
save_config(cfg)
print(f"*** Default configuration for '{arch}' written to {CONFIG_FILE} and {AUTOCONF_HEADER} ***")
def main():
if len(sys.argv) > 1:
cmd = sys.argv[1]
if cmd in ["--defconfig", "defconfig"]:
arch = sys.argv[2] if len(sys.argv) > 2 else "x86_64"
defconfig(arch)
return
elif cmd == "--x86_64":
defconfig("x86_64")
return
elif cmd in ["--aarch64", "--armv8", "--armv8i"]:
defconfig(cmd.lstrip("-"))
return
try:
curses.wrapper(run_tui)
print(f"*** Configuration saved to {CONFIG_FILE} and {AUTOCONF_HEADER} ***")
except KeyboardInterrupt:
pass
if __name__ == "__main__":
main()
+2 -4
View File
@@ -28,9 +28,7 @@
#include <ipc/ipc.h>
#include <mm/pmm.h>
#include <mm/kmalloc.h>
#include <arch/x86_64/pit.h>
#include <arch/x86_64/cpuid.h>
#include <arch/x86_64/io.h>
#include <arch/arch.h>
#include <kernel/printk.h>
#include <lib/string.h>
#include <lib/printf.h>
@@ -662,7 +660,7 @@ static int applet_mouse(int argc, char** argv) {
static int applet_uname(int argc, char** argv) {
if (argc >= 2 && strcmp(argv[1], "-a") == 0) {
printk("SUB-OS sub-node %s #1 SMP PREEMPT Sun Aug 16 2026 x86_64 GNU/LazyBox\n", kernel_get_version());
printk("SUB-OS sub-node %s #1 SMP PREEMPT 2026 %s GNU/LazyBox\n", kernel_get_version(), arch_get_name());
} else {
printk("SUB-OS\n");
}
+8 -6
View File
@@ -4,9 +4,7 @@
#include <drivers/tty.h>
#include <drivers/keyboard.h>
#include <drivers/speaker.h>
#include <arch/x86_64/pit.h>
#include <arch/x86_64/cpuid.h>
#include <arch/x86_64/io.h>
#include <arch/arch.h>
#include <mm/pmm.h>
#include <mm/kmalloc.h>
#include <kernel/printk.h>
@@ -101,13 +99,17 @@ static void cmd_neofetch(void) {
secs %= 60;
mins %= 60;
const cpu_info_t* cpu = cpuid_get_info();
printk("\n");
printk(ANSI_BRIGHT_CYAN " _____ _ _ ____ " ANSI_BRIGHT_GREEN "OS: " ANSI_RESET "SUB-OS v0.2.0-lts (Modular Monolithic)\n");
printk(ANSI_BRIGHT_CYAN " / ____| | | | _ \\ " ANSI_BRIGHT_GREEN "Arch: " ANSI_RESET "x86_64 (64-Bit Long Mode)\n");
printk(ANSI_BRIGHT_CYAN " / ____| | | | _ \\ " ANSI_BRIGHT_GREEN "Arch: " ANSI_RESET "%s\n", arch_get_name());
printk(ANSI_BRIGHT_CYAN " | (___ | | | | |_) | " ANSI_BRIGHT_GREEN "Kernel: " ANSI_RESET "Modular Drivers + VFS + Crypto + Net\n");
#if defined(__x86_64__)
const cpu_info_t* cpu = cpuid_get_info();
printk(ANSI_BRIGHT_CYAN " \\___ \\| | | | _ < " ANSI_BRIGHT_GREEN "CPU: " ANSI_RESET "%s (%s)\n", cpu->model, cpu->vendor);
#elif defined(__aarch64__)
const aarch64_cpu_info_t* cpu = aarch64_get_cpu_info();
printk(ANSI_BRIGHT_CYAN " \\___ \\| | | | _ < " ANSI_BRIGHT_GREEN "CPU: " ANSI_RESET "%s (EL%u)\n", cpu->model_name, cpu->current_el);
#endif
printk(ANSI_BRIGHT_CYAN " ____) | |__| | |_) | " ANSI_BRIGHT_GREEN "Memory: " ANSI_RESET "%llu MB / %llu MB (Free: %llu MB)\n", used_mb, total_mb, (free * 4096) / (1024 * 1024));
printk(ANSI_BRIGHT_CYAN " |_____/ \\____/|____/ " ANSI_BRIGHT_GREEN "Heap: " ANSI_RESET "%llu KB used / %llu KB total\n", heap_get_used_bytes() / 1024, (heap_get_used_bytes() + heap_get_free_bytes()) / 1024);
printk(ANSI_BRIGHT_CYAN " " ANSI_BRIGHT_GREEN "Uptime: " ANSI_RESET "%02llu:%02llu:%02llu\n", hours, mins, secs);