# =============================================================================
# SUB-OS Master Multi-Architecture Linux-Style Makefile
# Supports: x86_64, aarch64, armv8i
# Features: Linux Kconfig TUI (make menuconfig), multi-arch cross-compilation
# =============================================================================

-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 \
              -O2 \
              -Iinclude \
              -D__x86_64__

    ASMFLAGS_ELF  = -f elf64
    ASMFLAGS_BOOT = -f bin -I$(BOOT_DIR)/
    LDFLAGS       = -nostdlib -no-pie -T linker.ld

    # 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)
FS_C_SRCS       = $(shell find fs -name '*.c' 2>/dev/null)
NET_C_SRCS      = $(shell find net -name '*.c' 2>/dev/null)
CRYPTO_C_SRCS   = $(shell find crypto -name '*.c' 2>/dev/null)
LIB_C_SRCS      = $(shell find lib -name '*.c' 2>/dev/null)
USERLAND_C_SRCS = $(shell find userland -name '*.c' 2>/dev/null)
CERTS_C_SRCS    = $(shell find certs -name '*.c' 2>/dev/null)
INIT_C_SRCS     = $(shell find init -name '*.c' 2>/dev/null)
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)

ALL_C_SRCS = $(ARCH_C_SRCS) $(KERNEL_C_SRCS) $(MM_C_SRCS) $(DRIVERS_C_SRCS) \
             $(FS_C_SRCS) $(NET_C_SRCS) $(CRYPTO_C_SRCS) $(LIB_C_SRCS) $(USERLAND_C_SRCS) \
             $(CERTS_C_SRCS) $(INIT_C_SRCS) $(IO_URING_C_SRCS) $(SECURITY_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))

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

.PHONY: all clean run debug info menuconfig config defconfig x86_64_defconfig aarch64_defconfig armv8_defconfig armv8i_defconfig qemu

all: $(TARGET)

# -----------------------------------------------------------------------------
# Configuration Targets (Linux Kconfig TUI)
# -----------------------------------------------------------------------------
menuconfig config:
	@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:
	@python3 scripts/kconfig/menuconfig.py --armv8i

# -----------------------------------------------------------------------------
# Compilation Rules
# -----------------------------------------------------------------------------
# C Source Files
$(BUILD_DIR)/%.o: %.c
	@mkdir -p $(dir $@)
	$(CC) $(CFLAGS) -c $< -o $@

# x86_64 NASM Assembly Files
$(BUILD_DIR)/%.o: %.asm
	@mkdir -p $(dir $@)
	$(ASM) $(ASMFLAGS_ELF) $< -o $@

# 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))] ==="

$(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
# -----------------------------------------------------------------------------
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

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 "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)
