mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-25 16:52:29 +00:00
The visible goal was a Web app: type a URL, see the page, fetched over the TCP stack SUB-OS built. Getting there surfaced -- and forced fixes to -- two deeper problems. Async HTTP client (net/http_client.c) tcp_connect/recv all block, so fetching from the GUI would freeze the compositor. Fetches now run on one long-lived kernel worker thread that services a single-slot mailbox; the requester posts a job and polls its state. Ownership follows the state, and the two hand-off points (worker completion, requester release) run under interrupts-off, so a window can close mid-fetch with neither leak nor use-after-free. do_fetch returns its terminal state rather than publishing it, closing a window where the requester could free the job before finalize read it. Cooperative scheduling for the idle thread (the core fix) The login prompt, the shell and the GUI compositor all run on the pid-0 idle thread, which the scheduler by design never preempts (sched_tick skips pid 0) and never requeues on a yield (weave_on clear). So it could neither be preempted to let the worker run, nor cleanly yield -- the worker was simply starved, and an early attempt to yield from it froze the shell outright. The idle thread now joins the weave rotation once hardware interrupts are live, and the network wait loops (tcp, dns, ping, the worker's idle) yield through a new net_wait() instead of halting the CPU. The compositor spends its frame-budget slack yielding too. Result: a background fetch progresses while the desktop holds 54 FPS. Web app (gui/gui_app_web.c) A text browser: URL bar, Go, and a Raw/Reader toggle. Raw shows the response verbatim; Reader strips markup (dropping <script>/<style> bodies), decodes the common entities, and word-wraps the body. The line index is cached against content/view/width so scrolling and idle repaints are free. It only ever polls the worker, so it never stalls. TCP throughput (the limit flagged last time) The 32-slot table with a 2 s TIME_WAIT linger capped sustained serving at ~16 req/s. The table is now 64 slots, a connection this end closed after serving a request lingers 250 ms rather than 2 s, and expired TIME_WAIT entries are reaped from the count path so a quiet table still drains. netstat/netmon gained served-since-boot and peak-slots counters. Also: a `webget` CLI (the async client from a shell), listen/accept introspection already present, and a globe icon for the app. Verified on x86_64: `webget` fetched an 812-byte page (HTTP 200, 10 ms) on the worker thread; the GUI Web app rendered the same page in Reader mode while the desktop held 54 FPS; an 80-request burst through the 64-slot table returned 80/80 (was 39/40 before) and netstat reported "80 served, peak 33 of 64 slots" -- a peak that would have overflowed the old table. Builds clean on x86_64, aarch64 and armv8i. Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01Fh5z6V7nGPbHvqVG5p4CXX
542 lines
21 KiB
Makefile
542 lines
21 KiB
Makefile
# =============================================================================
|
|
# SUB-OS Master Multi-Architecture Linux-Style Makefile
|
|
# Supports: x86_64, aarch64, armv8i
|
|
# Features: Linux Kconfig TUI (make configure / make menuconfig), dynamic Kbuild
|
|
# =============================================================================
|
|
|
|
-include .config
|
|
|
|
# Architecture Selection (Default: x86_64)
|
|
ifdef CONFIG_ARCH
|
|
ARCH ?= $(CONFIG_ARCH)
|
|
else
|
|
ARCH ?= x86_64
|
|
endif
|
|
|
|
BUILD_DIR = build
|
|
BOOT_DIR = boot
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 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
|
|
|
|
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 \
|
|
$(if $(CONFIG_OPTIMIZATION),$(CONFIG_OPTIMIZATION),-O2) \
|
|
-Iinclude \
|
|
-D__x86_64__
|
|
|
|
ASMFLAGS_ELF = -f elf64
|
|
ASMFLAGS_BOOT = -f bin -I$(BOOT_DIR)/
|
|
LDFLAGS = -nostdlib -no-pie -T linker.ld
|
|
|
|
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 -display none
|
|
|
|
else ifneq ($(filter $(ARCH), aarch64 arm64),)
|
|
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 \
|
|
$(if $(CONFIG_OPTIMIZATION),$(CONFIG_OPTIMIZATION),-O2) \
|
|
-Iinclude \
|
|
-D__aarch64__ \
|
|
-march=armv8-a
|
|
|
|
LDFLAGS = -nostdlib -no-pie -T arch/aarch64/linker.ld
|
|
|
|
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 ifneq ($(filter $(ARCH), armv8i armv81 arm32 arm armv7 armv7-a armv7a aarch32),)
|
|
CROSS_COMPILE ?= arm-linux-gnueabihf-
|
|
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 \
|
|
$(if $(CONFIG_OPTIMIZATION),$(CONFIG_OPTIMIZATION),-O2) \
|
|
-Iinclude \
|
|
-D__arm__ \
|
|
-D__armv8i__ \
|
|
-mcpu=cortex-a15 \
|
|
-mfpu=neon-vfpv4 \
|
|
-mfloat-abi=hard \
|
|
-marm
|
|
|
|
LDFLAGS = -nostdlib -no-pie -T arch/armv8i/linker.ld
|
|
|
|
ARCH_C_SRCS = $(shell find arch/armv8i -name '*.c' 2>/dev/null)
|
|
ARCH_S_SRCS = $(shell find arch/armv8i -name '*.S' 2>/dev/null)
|
|
ENTRY_OBJ = $(BUILD_DIR)/arch/armv8i/boot/entry.o
|
|
TARGET = $(BUILD_DIR)/kernel.elf
|
|
QEMU_CMD = qemu-system-arm -M virt -cpu cortex-a15 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf
|
|
|
|
else
|
|
$(error Unsupported Architecture '$(ARCH)'. Supported: x86_64, aarch64, armv8i)
|
|
endif
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Linux-Style Configurable Kernel Subsystems (Kbuild-Style)
|
|
# -----------------------------------------------------------------------------
|
|
CORE_SRCS = kernel/main.c kernel/task.c kernel/sync.c kernel/timer.c kernel/printk.c \
|
|
kernel/panic.c kernel/trace.c kernel/sched.c kernel/cron.c kernel/syscall.c \
|
|
kernel/syslog.c kernel/module.c kernel/kobject.c kernel/metrics.c kernel/namespace.c \
|
|
kernel/signal.c kernel/workqueue.c kernel/tsc.c kernel/vt_art.c \
|
|
kernel/sub/sub_runtime.c kernel/sub/sub_vm.c kernel/nt/ob.c kernel/nt/reg.c kernel/nt/io.c \
|
|
kernel/wait.c kernel/futex.c kernel/rcu.c kernel/ktest.c kernel/time/ktime.c \
|
|
kernel/elf.c kernel/exec.c \
|
|
lib/string.c lib/vsprintf.c lib/bitmap.c lib/rbtree.c lib/kfifo.c lib/hashtable.c lib/font8x8.c \
|
|
init/cmdline.c init/service.c init/bootlogo.c init/logo_data.c usr/initramfs.c block/block.c block/elevator.c \
|
|
ipc/sem.c ipc/shm.c ipc/shm_posix.c ipc/pipe.c ipc/ipc.c ipc/msg.c \
|
|
crypto/sha256.c crypto/md5.c crypto/crc32.c crypto/prng.c sound/beep.c
|
|
|
|
# If no .config exists, default all core options to y
|
|
ifeq ($(wildcard .config),)
|
|
CONFIG_MM_PMM = y
|
|
CONFIG_MM_SLAB = y
|
|
CONFIG_MM_VMA = y
|
|
CONFIG_FS_VFS = y
|
|
CONFIG_FS_FAT32 = y
|
|
CONFIG_FS_EXT2 = y
|
|
CONFIG_FS_SYSFS = y
|
|
CONFIG_DRV_RAMDISK = y
|
|
CONFIG_DRV_AHCI = y
|
|
CONFIG_DRV_NVME = y
|
|
CONFIG_DRV_ATA = y
|
|
CONFIG_DRV_VIRTIO_BLK = y
|
|
CONFIG_NET_STACK = y
|
|
CONFIG_NET_FILTER = y
|
|
CONFIG_NET_HTTPD = y
|
|
CONFIG_NET_SSHD = y
|
|
CONFIG_DRV_E1000 = y
|
|
CONFIG_DRV_RTL8139 = y
|
|
CONFIG_DRV_VIRTIO_NET = y
|
|
CONFIG_DRV_PTY = y
|
|
CONFIG_DRV_VIRTIO_RNG = y
|
|
CONFIG_DRV_CANVAS_2D = y
|
|
CONFIG_DRV_BOCHS_VBE = y
|
|
CONFIG_DRV_SOUND_HDA = y
|
|
CONFIG_DRV_SOUND_AC97 = y
|
|
CONFIG_DRV_USB_XHCI = y
|
|
CONFIG_DRV_HWMON = y
|
|
CONFIG_SECURITY_LSM = y
|
|
CONFIG_SECURITY_KEYRING = y
|
|
CONFIG_BPF_VM = y
|
|
CONFIG_IO_URING = y
|
|
CONFIG_USERLAND_LAZYBOX = y
|
|
endif
|
|
|
|
CONFIG_SRCS-y := $(CORE_SRCS)
|
|
|
|
ifeq ($(CONFIG_MM_PMM), y)
|
|
CONFIG_SRCS-y += mm/pmm.c mm/kmalloc.c mm/page_cache.c
|
|
endif
|
|
ifeq ($(CONFIG_MM_SLAB), y)
|
|
CONFIG_SRCS-y += mm/slab.c
|
|
endif
|
|
ifeq ($(CONFIG_MM_VMA), y)
|
|
CONFIG_SRCS-y += mm/vma.c
|
|
endif
|
|
|
|
ifeq ($(CONFIG_BPF_VM), y)
|
|
CONFIG_SRCS-y += kernel/bpf.c
|
|
endif
|
|
ifeq ($(CONFIG_IO_URING), y)
|
|
CONFIG_SRCS-y += io_uring/io_uring.c
|
|
endif
|
|
ifeq ($(CONFIG_SECURITY_LSM), y)
|
|
CONFIG_SRCS-y += security/lsm.c security/auth.c
|
|
endif
|
|
ifeq ($(CONFIG_SECURITY_KEYRING), y)
|
|
CONFIG_SRCS-y += certs/x509.c
|
|
endif
|
|
|
|
# Filesystems
|
|
ifeq ($(CONFIG_FS_VFS), y)
|
|
CONFIG_SRCS-y += fs/vfs.c fs/ramfs.c fs/devfs.c fs/procfs.c
|
|
endif
|
|
ifeq ($(CONFIG_FS_FAT32), y)
|
|
CONFIG_SRCS-y += fs/fat32.c
|
|
endif
|
|
ifeq ($(CONFIG_FS_EXT2), y)
|
|
CONFIG_SRCS-y += fs/ext2.c
|
|
endif
|
|
ifeq ($(CONFIG_FS_SYSFS), y)
|
|
CONFIG_SRCS-y += fs/sysfs.c
|
|
endif
|
|
|
|
# Storage Drivers
|
|
ifeq ($(CONFIG_DRV_RAMDISK), y)
|
|
CONFIG_SRCS-y += drivers/block/ramdisk.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_AHCI), y)
|
|
CONFIG_SRCS-y += drivers/block/ahci.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_NVME), y)
|
|
CONFIG_SRCS-y += drivers/block/nvme.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_ATA), y)
|
|
CONFIG_SRCS-y += drivers/block/ata.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_VIRTIO_BLK), y)
|
|
CONFIG_SRCS-y += drivers/virtio/virtio_blk.c virt/virtio.c virt/hypervisor.c
|
|
endif
|
|
|
|
# Network Subsystem
|
|
ifeq ($(CONFIG_NET_STACK), y)
|
|
CONFIG_SRCS-y += net/core/net.c net/core/socket.c net/ipv4/tcp.c net/ipv4/udp.c net/ipv4/dhcp.c net/ipv4/dns.c net/ipv4/dns_cache.c net/http_client.c
|
|
endif
|
|
ifeq ($(CONFIG_NET_FILTER), y)
|
|
CONFIG_SRCS-y += net/filter.c
|
|
endif
|
|
ifeq ($(CONFIG_NET_HTTPD), y)
|
|
CONFIG_SRCS-y += net/httpd.c
|
|
endif
|
|
ifeq ($(CONFIG_NET_SSHD), y)
|
|
CONFIG_SRCS-y += net/ssh.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_E1000), y)
|
|
CONFIG_SRCS-y += drivers/net/e1000.c drivers/pci/pci.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_RTL8139), y)
|
|
CONFIG_SRCS-y += drivers/net/rtl8139.c drivers/pci/pci.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_VIRTIO_NET), y)
|
|
CONFIG_SRCS-y += drivers/virtio/virtio_net.c virt/virtio.c
|
|
endif
|
|
|
|
# Character, Audio, Video Drivers
|
|
ifeq ($(CONFIG_DRV_PTY), y)
|
|
CONFIG_SRCS-y += drivers/char/pty.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_VIRTIO_RNG), y)
|
|
CONFIG_SRCS-y += drivers/char/virtio_rng.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_USB_XHCI), y)
|
|
CONFIG_SRCS-y += drivers/usb/xhci.c drivers/usb/usb.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_HWMON), y)
|
|
CONFIG_SRCS-y += drivers/hwmon/coretemp.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_CANVAS_2D), y)
|
|
CONFIG_SRCS-y += drivers/video/canvas.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_BOCHS_VBE), y)
|
|
CONFIG_SRCS-y += drivers/video/bochs.c drivers/video/fb.c drivers/video/fbcon.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_SOUND_HDA), y)
|
|
CONFIG_SRCS-y += sound/hda.c sound/sound.c sound/pcm.c sound/tts.c sound/melody.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_SOUND_AC97), y)
|
|
CONFIG_SRCS-y += sound/ac97.c sound/sound.c sound/pcm.c
|
|
endif
|
|
|
|
# Common Input/Display/Power/GPU/Networking Drivers
|
|
CONFIG_SRCS-y += drivers/char/tty.c drivers/char/keyboard.c drivers/char/serial.c drivers/char/vga.c \
|
|
drivers/input/mouse.c drivers/power/acpi.c drivers/power/cpufreq.c drivers/rtc/rtc.c drivers/sound/speaker.c \
|
|
drivers/net/e1000e.c drivers/virtio/virtio_gpu.c drivers/virtio/virtio_input.c \
|
|
drivers/timer/hpet.c drivers/char/lpt.c drivers/char/nvram.c
|
|
|
|
# Userland & GUI Desktop Subsystem
|
|
ifeq ($(CONFIG_USERLAND_LAZYBOX), y)
|
|
CONFIG_SRCS-y += userland/lazybox/lazybox.c userland/lazybox/shell.c userland/lazybox/sh.c userland/lazybox/nano.c userland/lazybox/snake.c userland/lazybox/tree.c userland/lazybox/coreutils.c
|
|
endif
|
|
|
|
CONFIG_SRCS-y += gui/gui.c gui/gui_gfx.c gui/gui_cursor.c gui/gui_wm.c gui/gui_desktop.c gui/gui_apps.c \
|
|
gui/gui_widgets.c gui/gui_icons.c gui/gui_dialog.c gui/gui_apps_ext.c gui/gui_terminal.c \
|
|
gui/gui_app_sorry.c gui/gui_app_netmon.c gui/gui_app_web.c
|
|
|
|
# Deduplicate
|
|
CONFIG_SRCS-y := $(sort $(CONFIG_SRCS-y))
|
|
|
|
# Rust & C++ Layer Configuration
|
|
ifeq ($(ARCH), x86_64)
|
|
RUSTC ?= rustc
|
|
RUST_SRCS = $(shell find rust/src -name '*.rs' 2>/dev/null)
|
|
RUST_LIB = $(BUILD_DIR)/rust/librust_kernel.a
|
|
CXX ?= g++
|
|
CXXFLAGS = -ffreestanding -fno-pie -fno-pic -mno-red-zone -mno-mmx -mno-sse -mno-sse2 \
|
|
-mcmodel=kernel -Wall -Wextra -Wno-unused-function -Wno-unused-parameter \
|
|
$(if $(CONFIG_OPTIMIZATION),$(CONFIG_OPTIMIZATION),-O2) -Iinclude -D__x86_64__ \
|
|
-std=c++17 -fno-exceptions -fno-rtti -fno-threadsafe-statics -fno-use-cxa-atexit
|
|
CPP_SRCS = $(shell find kernel/cpp -name '*.cpp' 2>/dev/null)
|
|
CPP_OBJS = $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(CPP_SRCS))
|
|
ALL_C_SRCS = $(ARCH_C_SRCS) $(CONFIG_SRCS-y)
|
|
C_OBJS = $(patsubst %.c, $(BUILD_DIR)/%.o, $(ALL_C_SRCS))
|
|
ASM_OBJS = $(patsubst %.asm, $(BUILD_DIR)/%.o, $(ARCH_ASM_SRCS))
|
|
|
|
# Userland /sbin/init, linked separately and carried inside the kernel image.
|
|
INIT_SRC = userland/init/init.c
|
|
INIT_LD = userland/init/user.ld
|
|
INIT_OBJ = $(BUILD_DIR)/userland/init/init.o
|
|
INIT_ELF = $(BUILD_DIR)/userland/init/init.elf
|
|
INIT_BLOB_SRC = $(BUILD_DIR)/usr/init_blob.c
|
|
INIT_BLOB_OBJ = $(BUILD_DIR)/usr/init_blob.o
|
|
|
|
OTHER_OBJS = $(filter-out $(ENTRY_OBJ), $(ASM_OBJS) $(C_OBJS)) $(CPP_OBJS) $(INIT_BLOB_OBJ) $(RUST_LIB)
|
|
else
|
|
CONFIG_SRCS-y += rust/rust_fallback.c kernel/cpp/cpp_fallback.c
|
|
ALL_C_SRCS = $(ARCH_C_SRCS) $(CONFIG_SRCS-y)
|
|
C_OBJS = $(patsubst %.c, $(BUILD_DIR)/%.o, $(ALL_C_SRCS))
|
|
S_OBJS = $(patsubst %.S, $(BUILD_DIR)/%.o, $(ARCH_S_SRCS))
|
|
OTHER_OBJS = $(filter-out $(ENTRY_OBJ), $(S_OBJS) $(C_OBJS))
|
|
endif
|
|
|
|
# Generated dependency files, one per object. The include lives at the very
|
|
# end of this file: a .d file's first rule would otherwise become make's
|
|
# default goal and turn a bare `make` into a no-op.
|
|
DEPS = $(C_OBJS:.o=.d) $(CPP_OBJS:.o=.d) $(S_OBJS:.o=.d)
|
|
|
|
.DEFAULT_GOAL := all
|
|
|
|
.PHONY: all clean run run-headless run-fullscreen run-vnc run-server debug info configure menuconfig config tui nconfig defconfig x86_64_defconfig aarch64_defconfig armv8_defconfig armv8i_defconfig armv81_defconfig arm32_defconfig qemu help
|
|
|
|
all: $(TARGET)
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Configuration Targets (Linux Kconfig TUI Configurator)
|
|
# -----------------------------------------------------------------------------
|
|
configure menuconfig config tui nconfig:
|
|
@python3 scripts/kconfig/menuconfig.py
|
|
|
|
defconfig:
|
|
@python3 scripts/kconfig/menuconfig.py --defconfig $(ARCH)
|
|
|
|
x86_64_defconfig:
|
|
@python3 scripts/kconfig/menuconfig.py --x86_64
|
|
|
|
aarch64_defconfig:
|
|
@python3 scripts/kconfig/menuconfig.py --aarch64
|
|
|
|
armv8_defconfig armv8i_defconfig armv81_defconfig arm32_defconfig:
|
|
@python3 scripts/kconfig/menuconfig.py --armv8i
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Compilation Rules
|
|
# -----------------------------------------------------------------------------
|
|
# Header dependency tracking: without this a header change leaves stale objects
|
|
# behind, and a struct layout edit silently corrupts every unrebuilt caller.
|
|
DEPFLAGS = -MMD -MP
|
|
|
|
# C Source Files
|
|
$(BUILD_DIR)/%.o: %.c include/config/autoconf.h
|
|
@mkdir -p $(dir $@)
|
|
$(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
|
|
# C++ Source Files
|
|
$(BUILD_DIR)/%.o: %.cpp include/config/autoconf.h
|
|
@mkdir -p $(dir $@)
|
|
$(CXX) $(CXXFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
|
|
# x86_64 NASM Assembly Files
|
|
$(BUILD_DIR)/%.o: %.asm
|
|
@mkdir -p $(dir $@)
|
|
$(ASM) $(ASMFLAGS_ELF) $< -o $@
|
|
|
|
# ARM/AArch64 GNU Assembly Files (.S)
|
|
$(BUILD_DIR)/%.o: %.S
|
|
@mkdir -p $(dir $@)
|
|
$(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
|
|
# Userland Program Compilation
|
|
#
|
|
# /sbin/init is a separate freestanding executable, not kernel code: it is
|
|
# linked at the user base from userland/user.ld and must never see the kernel's
|
|
# -mcmodel=kernel, which cannot reach the user half of the address space.
|
|
USER_CFLAGS = -ffreestanding -nostdlib -fno-pie -fno-pic -mno-red-zone \
|
|
-mcmodel=large -mno-sse -mno-mmx -mno-sse2 \
|
|
-Wall -Wextra -Wno-unused-function \
|
|
$(if $(CONFIG_OPTIMIZATION),$(CONFIG_OPTIMIZATION),-O2)
|
|
|
|
$(INIT_OBJ): $(INIT_SRC)
|
|
@mkdir -p $(dir $@)
|
|
$(CC) $(USER_CFLAGS) -c $< -o $@
|
|
|
|
$(INIT_ELF): $(INIT_OBJ) $(INIT_LD)
|
|
@mkdir -p $(dir $@)
|
|
$(LD) -nostdlib -no-pie -T $(INIT_LD) -o $@ $(INIT_OBJ)
|
|
@echo "=== [Userland init linked: $@] ==="
|
|
|
|
$(INIT_BLOB_SRC): $(INIT_ELF) scripts/mkblob.py
|
|
@mkdir -p $(dir $@)
|
|
@python3 scripts/mkblob.py $(INIT_ELF) $@ subos_init_elf
|
|
|
|
$(INIT_BLOB_OBJ): $(INIT_BLOB_SRC) include/config/autoconf.h
|
|
@mkdir -p $(dir $@)
|
|
$(CC) $(CFLAGS) -c $< -o $@
|
|
|
|
# Rust Source Compilation
|
|
$(RUST_LIB): rust/src/lib.rs $(RUST_SRCS)
|
|
@mkdir -p $(dir $@)
|
|
$(RUSTC) --crate-type staticlib -C panic=abort -C relocation-model=static -C opt-level=2 -C no-redzone=y -o $@ rust/src/lib.rs
|
|
|
|
|
|
# Header Generation Fallback
|
|
include/config/autoconf.h:
|
|
@mkdir -p include/config
|
|
@if [ ! -f .config ]; then python3 scripts/kconfig/menuconfig.py --defconfig $(ARCH); fi
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Link & Image Assembly
|
|
# -----------------------------------------------------------------------------
|
|
$(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
|
|
|
|
LIBGCC ?= $(shell $(CC) $(CFLAGS) -print-libgcc-file-name 2>/dev/null)
|
|
|
|
$(BUILD_DIR)/kernel.elf: $(ENTRY_OBJ) $(OTHER_OBJS)
|
|
$(LD) $(LDFLAGS) -o $@ $(ENTRY_OBJ) $(OTHER_OBJS) $(LIBGCC)
|
|
@echo "=== [Kernel ELF Linked: $@ (Architecture: $(ARCH))] ==="
|
|
|
|
$(BUILD_DIR)/kernel.bin: $(BUILD_DIR)/kernel.elf
|
|
$(OBJCOPY) -O binary $< $@
|
|
|
|
$(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 x86_64 Disk Image Built: $@ (Size: $$(du -h $@ | cut -f1))] ==="
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Execution & Emulation Targets
|
|
# -----------------------------------------------------------------------------
|
|
# -vga std gives the Bochs VBE adapter the kernel drives. vgamem_mb is raised
|
|
# because a 1280x720 32-bit framebuffer needs more than the 8 MB default.
|
|
QEMU_VGA = -device VGA,vgamem_mb=64
|
|
|
|
# `make run` boots straight into the SUB-OS Graphical Desktop Environment. The
|
|
# guest window scales with zoom-to-fit; pass `nogui`/`text` on the kernel
|
|
# command line for the emergency TTY. Use `make run-headless` for serial only.
|
|
run qemu: $(TARGET)
|
|
ifeq ($(ARCH), x86_64)
|
|
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) -m 512M \
|
|
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
|
|
-device e1000,netdev=net0 $(QEMU_VGA) -display gtk,zoom-to-fit=on -serial stdio
|
|
else ifneq ($(filter $(ARCH), aarch64 arm64),)
|
|
qemu-system-aarch64 -M virt -cpu cortex-a57 -m 256M -kernel $(BUILD_DIR)/kernel.elf -device virtio-gpu-pci -serial stdio
|
|
else
|
|
qemu-system-arm -M virt -cpu cortex-a15 -m 256M -kernel $(BUILD_DIR)/kernel.elf -device virtio-gpu-pci -serial stdio
|
|
endif
|
|
|
|
# Headless: no graphical window, kernel console on the serial line only. Boot
|
|
# with `nogui` on the kernel command line to reach the TTY in this mode.
|
|
run-headless: $(TARGET)
|
|
$(QEMU_CMD)
|
|
|
|
# Fullscreen without distortion: zoom-to-fit scales the guest while preserving
|
|
# its aspect ratio, letterboxing rather than stretching on a wider panel.
|
|
run-fullscreen: $(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 $(QEMU_VGA) \
|
|
-display gtk,zoom-to-fit=on,show-cursor=on -full-screen -serial stdio
|
|
else
|
|
@echo "run-fullscreen targets x86_64 only"
|
|
endif
|
|
|
|
run-vnc: $(TARGET)
|
|
ifeq ($(ARCH), x86_64)
|
|
@echo "=== [QEMU VNC Server running at localhost:5900 (VNC Display :0)] ==="
|
|
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 $(QEMU_VGA) -vnc :0 -serial stdio
|
|
else
|
|
@echo "=== [QEMU VNC Server running at localhost:5900 (VNC Display :0)] ==="
|
|
qemu-system-aarch64 -M virt -cpu cortex-a57 -m 128M -kernel $(BUILD_DIR)/kernel.elf -device virtio-gpu-pci -vnc :0 -serial stdio
|
|
endif
|
|
|
|
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
|
|
|
|
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 ifneq ($(filter $(ARCH), aarch64 arm64),)
|
|
qemu-system-aarch64 -M virt -cpu cortex-a57 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf -s -S
|
|
else
|
|
qemu-system-arm -M virt -cpu cortex-a15 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf -s -S
|
|
endif
|
|
|
|
info:
|
|
@echo "Target Architecture: $(ARCH)"
|
|
@echo "Cross Compiler: $(CROSS_COMPILE)"
|
|
@echo "Compiled Sources: $(words $(ALL_C_SRCS)) C files"
|
|
@echo "Target Binary: $(TARGET)"
|
|
|
|
help:
|
|
@echo "SUB-OS Kernel Build System (Linux-Style Kconfig)"
|
|
@echo "=================================================="
|
|
@echo " make configure - Launch interactive Linux-style TUI Configurator"
|
|
@echo " make menuconfig - Alias for make configure"
|
|
@echo " make defconfig - Reset to default configuration for active ARCH"
|
|
@echo " make x86_64_defconfig - Load x86_64 default configuration"
|
|
@echo " make aarch64_defconfig- Load AArch64 default configuration"
|
|
@echo " make armv8i_defconfig - Load ARMv8i (32-bit ARM) default configuration"
|
|
@echo " make all [ARCH=...] - Compile kernel image for selected architecture"
|
|
@echo " make run [ARCH=...] - Boot into the SUB-OS Graphical Desktop in QEMU"
|
|
@echo " make run-headless - Boot in QEMU with serial console only (no window)"
|
|
@echo " make run-fullscreen - Boot the desktop in a full-screen QEMU window"
|
|
@echo " make run-vnc - Boot the desktop and expose it over VNC :0"
|
|
@echo " make clean - Remove all compiled objects and disk images"
|
|
@echo " make info - Display build configuration and source metrics"
|
|
|
|
clean:
|
|
rm -rf $(BUILD_DIR) $(IMAGE)
|
|
|
|
-include $(DEPS)
|