mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-25 16:52:29 +00:00
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:
1 parent
125a891621
commit
70d5925b16
41 files changed
+1926
-187
No files matched your search
@@ -8,3 +8,4 @@ build/
|
||||
*.tmp
|
||||
.DS_Store
|
||||
.system_generated/
|
||||
.config
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 = .;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
Executable
+386
@@ -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()
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user