# ================================================================
# Extended MIPS32 Flat Firmware - Multi-File Build System
#
# Prerequisites:
#   sudo apt install gcc-14-mipsel-linux-gnu binutils-mipsel-linux-gnu
#
# Targets:
#   make              - Build firmware.bin (flat binary)
#   make debug        - Build firmware_debug.elf (with symbols)
#   make info         - Show binary size, symbol count, strings
#   make clean        - Remove build artifacts
#   make dump         - Hexdump first 512 bytes
#   make disasm       - Disassemble with objdump
# ================================================================

CROSS    ?= mipsel-linux-gnu-
CC       = $(CROSS)gcc-14
AS       = $(CROSS)gcc-14
LD       = $(CROSS)ld
OBJCOPY  = $(CROSS)objcopy
OBJDUMP  = $(CROSS)objdump
NM       = $(CROSS)nm
SIZE     = $(CROSS)size
STRINGS  = strings

# Compiler flags matching real embedded firmware
CFLAGS   = -mips32r2 -EL -O1 -std=gnu89 \
           -fno-builtin -ffreestanding -nostdlib \
           -mno-abicalls -fno-pic \
           -G0 -mno-gpopt \
           -Iinclude \
           -Wall -Wno-unused-function

ASFLAGS  = -mips32r2 -EL -fno-pic -mno-abicalls

LDFLAGS  = -T linker.ld --no-warn-rwx-segments

# ---- Source files (18 C files + 1 assembly) ----

C_SRCS   = core/main.c         \
           core/rtos.c          \
           core/event.c         \
           core/alloc.c         \
           hal/uart.c           \
           hal/gpio.c           \
           hal/timer.c          \
           drivers/port.c       \
           drivers/rule_engine.c \
           drivers/dma.c        \
           protocol/partition.c \
           protocol/routing.c   \
           cli/cmdline.c        \
           cli/diagnostics.c    \
           util/assert.c        \
           util/crc.c           \
           crypto/aes.c         \
           crypto/sha256.c

ASM_SRCS = startup.S

# Object files (preserve directory structure)
C_OBJS   = $(C_SRCS:.c=.o)
ASM_OBJS = $(ASM_SRCS:.S=.o)
OBJS     = $(ASM_OBJS) $(C_OBJS)

# ---- Main targets ----

.PHONY: all clean dump disasm info debug

all: firmware.bin

# Pattern rule for C sources (handles subdirectories)
%.o: %.c
	$(CC) $(CFLAGS) -c -o $@ $<

# Assemble startup code
startup.o: startup.S
	$(AS) $(ASFLAGS) -c -o $@ $<

# Link into ELF (intermediate)
firmware.elf: $(OBJS) linker.ld
	$(LD) $(LDFLAGS) -o $@ $(OBJS)

# Extract flat binary (THE FINAL PRODUCT - no ELF headers!)
firmware.bin: firmware.elf
	$(OBJCOPY) -O binary $< $@
	@echo ""
	@echo "================================================"
	@echo "  firmware.bin: $$(wc -c < $@) bytes"
	@echo "  Format: Raw MIPS32 LE flat binary"
	@echo "  Base:   0x80000000"
	@echo "  Files:  $(words $(C_SRCS)) C + $(words $(ASM_SRCS)) ASM"
	@echo "================================================"
	@echo ""
	@echo "This file has NO ELF headers."
	@echo "Use Ghidra / Capstone / radare2 to analyze."

# Build with debug symbols
debug: firmware_debug.elf

firmware_debug.elf: $(OBJS) linker.ld
	$(LD) $(LDFLAGS) -o $@ $(OBJS)

# ---- Utility targets ----

clean:
	rm -f $(OBJS) firmware.elf firmware_debug.elf firmware.bin
	@echo "Clean."

dump: firmware.bin
	@echo "=== First 512 bytes of firmware.bin ==="
	hexdump -C $< | head -32
	@echo "..."
	@echo "=== No ELF magic (7F 45 4C 46) - flat binary ==="

disasm: firmware.elf
	$(OBJDUMP) -d $< | head -200

info: firmware.elf firmware.bin
	@echo "=== ELF sections ==="
	$(SIZE) firmware.elf
	@echo ""
	@echo "=== Symbol count ==="
	@echo -n "  "; $(NM) firmware.elf | wc -l
	@echo " total symbols"
	@echo ""
	@echo "  Functions:"
	@echo -n "    "; $(NM) firmware.elf | grep ' [Tt] ' | wc -l
	@echo ""
	@echo "  Globals:"
	@echo -n "    "; $(NM) firmware.elf | grep ' [BbDdGgSs] ' | wc -l
	@echo ""
	@echo "=== Flat binary size ==="
	@ls -la firmware.bin
	@echo ""
	@echo "=== String count ==="
	@echo -n "  "; $(STRINGS) firmware.bin | wc -l
	@echo " strings"
	@echo ""
	@echo "=== String preview (first 30) ==="
	@$(STRINGS) firmware.bin | head -30
	@echo ""
	@echo "=== Call sites (JAL instructions) ==="
	@echo -n "  "; $(OBJDUMP) -d firmware.elf | grep '	jal	' | wc -l
	@echo " jal instructions"
