# ================================================================
# Sample MIPS32 Flat Firmware - Build System
#
# Prerequisites:
#   sudo apt install gcc-mipsel-linux-gnu binutils-mipsel-linux-gnu
#   sudo apt install python3-capstone   # for the scripts under tools/
#
# Targets:
#   make              - Build firmware.bin (flat binary) and firmware.elf
#                       (intermediate ELF with DWARF symbols, used by
#                       Ghidra in Part 4)
#   make v2           - Build firmware_v2.bin (Part 5: fixed route engine)
#   make clean        - Remove build artifacts
#   make dump         - Hexdump first 256 bytes
#   make disasm       - Disassemble with objdump (ELF version)
#   make info         - Show binary size and section info
# ================================================================

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

# Compiler flags matching real embedded firmware. We build with -g
# unconditionally so firmware.elf carries DWARF debug info for Ghidra in
# Part 4. The objcopy -O binary step below strips all of that out, so
# firmware.bin is unaffected.
CFLAGS   = -mips32r2 -EL -O1 -std=gnu89 -g \
           -fno-builtin -ffreestanding -nostdlib \
           -mno-abicalls -fno-pic \
           -G0 -mno-gpopt \
           -Wall

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

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

# Source files
SRCS     = main.c
ASM_SRCS = startup.S
OBJS     = startup.o main.o

# ---- Main targets ----

.PHONY: all clean dump disasm info pack v2

all: firmware.bin

# Compile C source
main.o: main.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 "========================================"
	@echo ""
	@echo "This file has NO ELF headers."
	@echo "objdump cannot open it directly!"
	@echo "Use Capstone or Ghidra to analyze."

# Build v2 firmware (fixed route engine — table-driven dispatch)
v2: firmware_v2.bin

main_v2.o: main_v2.c
	$(CC) $(CFLAGS) -c -o $@ $<

firmware_v2.elf: startup.o main_v2.o linker.ld
	$(LD) $(LDFLAGS) -o $@ startup.o main_v2.o

firmware_v2.bin: firmware_v2.elf
	$(OBJCOPY) -O binary $< $@
	@echo ""
	@echo "========================================"
	@echo "  firmware_v2.bin: $$(wc -c < $@) bytes"
	@echo "  Format: Raw MIPS32 LE flat binary"
	@echo "  Base:   0x80000000"
	@echo "  Version: v3.0.0 (fixed route engine)"
	@echo "========================================"

# ---- Utility targets ----

# Pack into multi-partition firmware image (header + CRC + partitions)
pack: firmware.bin
	python3 fwpack.py firmware.bin firmware.img

clean:
	rm -f *.o *.elf firmware.bin firmware_v2.bin firmware.img firmware_debug.elf

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

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

info: firmware.elf firmware.bin
	@echo "=== ELF sections (intermediate) ==="
	$(SIZE) firmware.elf
	@echo ""
	@echo "=== Symbol count ==="
	@$(NM) firmware.elf | wc -l
	@echo " total symbols in ELF"
	@echo ""
	@echo "=== Flat binary (final) ==="
	@ls -la firmware.bin
	@echo ""
	@echo "=== String table preview ==="
	@strings firmware.bin | head -20
