# HDGL Bootloader Makefile (v2.1 - Fixed)
# Builds an EFI bootloader for HDGL lattice-based booting with enhanced compatibility

# Configuration
TARGET = hdgl_bootloader.efi
SOURCE = hdgl_bootloader.c
BUILD_DIR = build
EFI_ARCH = x86_64

# Tools
CC = gcc
LD = ld
OBJCOPY = objcopy
MKDIR = mkdir -p
RM = rm -rf
QEMU = qemu-system-$(EFI_ARCH)

# Auto-detect GNU-EFI installation
# Try multiple common locations
GNU_EFI_SEARCH_PATHS = /usr /usr/local /opt/gnu-efi
GNU_EFI_BASE = $(firstword $(foreach path,$(GNU_EFI_SEARCH_PATHS),$(if $(wildcard $(path)/include/efi/efi.h),$(path))))

# Fallback if pkg-config available
ifeq ($(GNU_EFI_BASE),)
    GNU_EFI_BASE = $(shell pkg-config --variable=prefix gnu-efi 2>/dev/null || echo /usr)
endif

# Validate GNU-EFI installation
ifeq ($(wildcard $(GNU_EFI_BASE)/include/efi/efi.h),)
    $(error GNU-EFI not found. Please install gnu-efi-dev or run ./setup.sh)
endif

# GNU-EFI paths
GNU_EFI_INC = $(GNU_EFI_BASE)/include/efi
GNU_EFI_LIB = $(GNU_EFI_BASE)/lib
GNU_EFI_CRT = $(GNU_EFI_LIB)/crt0-efi-$(EFI_ARCH).o
GNU_EFI_LDS = $(GNU_EFI_LIB)/elf_$(EFI_ARCH)_efi.lds

# Alternative library locations
ifeq ($(wildcard $(GNU_EFI_CRT)),)
    GNU_EFI_LIB := $(GNU_EFI_BASE)/lib64
    GNU_EFI_CRT := $(GNU_EFI_LIB)/crt0-efi-$(EFI_ARCH).o
    GNU_EFI_LDS := $(GNU_EFI_LIB)/elf_$(EFI_ARCH)_efi.lds
endif

# Final validation
ifeq ($(wildcard $(GNU_EFI_CRT)),)
    $(error GNU-EFI runtime not found at $(GNU_EFI_CRT). Check your gnu-efi installation)
endif

# Compiler and linker flags
CFLAGS = -I$(GNU_EFI_INC) \
         -I$(GNU_EFI_INC)/$(EFI_ARCH) \
         -I$(GNU_EFI_INC)/protocol \
         -fno-stack-protector \
         -fpic \
         -fshort-wchar \
         -mno-red-zone \
         -DGNU_EFI_USE_MS_ABI \
         -DEFI_FUNCTION_WRAPPER \
         -std=c11 \
         -O2 \
         -Wall \
         -Wextra \
         -Werror=implicit-function-declaration

LDFLAGS = -nostdlib \
          -znocombreloc \
          -T $(GNU_EFI_LDS) \
          -shared \
          -Bsymbolic \
          -L$(GNU_EFI_LIB)

OBJCOPY_FLAGS = -j .text -j .sdata -j .data -j .dynamic \
                -j .dynsym -j .rel -j .rela -j .reloc \
                --target=efi-app-$(EFI_ARCH) \
                --subsystem=10

# Libraries to link
LIBS = -lefi -lgnuefi

# Source and object files
OBJECTS = $(BUILD_DIR)/hdgl_bootloader.o

# Phony targets
.PHONY: all clean install test iso setup info check-deps

# Default target
all: check-deps $(BUILD_DIR)/$(TARGET)

# Show build information
info:
	@echo "HDGL Bootloader Build Information"
	@echo "================================="
	@echo "GNU-EFI Base: $(GNU_EFI_BASE)"
	@echo "GNU-EFI Include: $(GNU_EFI_INC)"
	@echo "GNU-EFI Library: $(GNU_EFI_LIB)"
	@echo "GNU-EFI Runtime: $(GNU_EFI_CRT)"
	@echo "GNU-EFI Linker Script: $(GNU_EFI_LDS)"
	@echo "Target: $(TARGET)"
	@echo "Architecture: $(EFI_ARCH)"

# Check dependencies
check-deps:
	@echo "Checking build dependencies..."
	@which $(CC) >/dev/null || { echo "Error: GCC not found"; exit 1; }
	@which $(LD) >/dev/null || { echo "Error: ld not found"; exit 1; }
	@which $(OBJCOPY) >/dev/null || { echo "Error: objcopy not found"; exit 1; }
	@test -f "$(GNU_EFI_CRT)" || { echo "Error: GNU-EFI runtime not found at $(GNU_EFI_CRT)"; exit 1; }
	@test -f "$(GNU_EFI_LDS)" || { echo "Error: GNU-EFI linker script not found at $(GNU_EFI_LDS)"; exit 1; }
	@echo "✓ All dependencies found"

# Create build directory
$(BUILD_DIR):
	$(MKDIR) $(BUILD_DIR)

# Compile source to object
$(BUILD_DIR)/%.o: %.c | $(BUILD_DIR)
	@echo "Compiling $<..."
	$(CC) $(CFLAGS) -c $< -o $@

# Link and create EFI executable
$(BUILD_DIR)/$(TARGET): $(OBJECTS)
	@echo "Linking EFI executable..."
	$(LD) $(LDFLAGS) $(GNU_EFI_CRT) $(OBJECTS) -o $(BUILD_DIR)/hdgl_bootloader.so $(LIBS)
	@echo "Creating EFI application..."
	$(OBJCOPY) $(OBJCOPY_FLAGS) $(BUILD_DIR)/hdgl_bootloader.so $@
	@echo "✓ HDGL bootloader built successfully: $@"

# Clean build artifacts
clean:
	$(RM) $(BUILD_DIR)
	@echo "✓ Build directory cleaned"

# Install to EFI directory (configurable via EFI_DEST)
EFI_DEST ?= /boot/efi/EFI/BOOT
install: $(BUILD_DIR)/$(TARGET)
	@echo "Installing to $(EFI_DEST)/BOOTX64.EFI (requires root)"
	@test -d "$(dir $(EFI_DEST))" || { echo "Error: EFI destination directory not found"; exit 1; }
	sudo install -D -m 644 $(BUILD_DIR)/$(TARGET) $(EFI_DEST)/BOOTX64.EFI
	@echo "✓ HDGL bootloader installed"

# Test in QEMU with OVMF
OVMF_LOCATIONS = /usr/share/ovmf/OVMF.fd /usr/share/edk2-ovmf/OVMF_CODE.fd /usr/share/OVMF/OVMF_CODE.fd
OVMF = $(firstword $(foreach ovmf,$(OVMF_LOCATIONS),$(if $(wildcard $(ovmf)),$(ovmf))))

test: $(BUILD_DIR)/$(TARGET)
	@if [ -z "$(OVMF)" ]; then \
		echo "Error: OVMF firmware not found in standard locations"; \
		echo "Install ovmf package or set OVMF variable"; \
		exit 1; \
	fi
	@echo "Testing with OVMF: $(OVMF)"
	$(QEMU) -bios $(OVMF) \
		-drive format=raw,file=fat:rw:$(BUILD_DIR) \
		-m 256M \
		-nographic \
		$(shell test -r /dev/kvm && echo "-enable-kvm")

# Create ISO (requires hdgl_install.sh)
iso: $(BUILD_DIR)/$(TARGET)
	@test -x ./hdgl_install.sh || { echo "Error: hdgl_install.sh not found or not executable"; exit 1; }
	./hdgl_install.sh

# Setup dependencies
setup:
	@test -x ./setup.sh || { echo "Error: setup.sh not found or not executable"; exit 1; }
	./setup.sh

# Quick test compile to verify environment
test-compile: check-deps | $(BUILD_DIR)
	@echo "Testing compilation environment..."
	@echo '#include <efi.h>' > $(BUILD_DIR)/test.c
	@echo '#include <efilib.h>' >> $(BUILD_DIR)/test.c
	@echo 'EFI_STATUS EFIAPI efi_main(EFI_HANDLE h, EFI_SYSTEM_TABLE *st) { return EFI_SUCCESS; }' >> $(BUILD_DIR)/test.c
	$(CC) $(CFLAGS) -c $(BUILD_DIR)/test.c -o $(BUILD_DIR)/test.o
	@$(RM) $(BUILD_DIR)/test.c $(BUILD_DIR)/test.o
	@echo "✓ Compilation environment OK"

# Help target
help:
	@echo "HDGL Bootloader Makefile"
	@echo "======================="
	@echo "Targets:"
	@echo "  all          - Build the HDGL bootloader (default)"
	@echo "  info         - Show build configuration"
	@echo "  check-deps   - Check build dependencies"
	@echo "  test-compile - Quick compilation test"
	@echo "  clean        - Remove build artifacts"
	@echo "  install      - Install to EFI system partition"
	@echo "  test         - Test in QEMU with OVMF"
	@echo "  iso          - Create bootable ISO"
	@echo "  setup        - Install build dependencies"
	@echo "  help         - Show this help"
	@echo ""
	@echo "Variables:"
	@echo "  EFI_DEST     - Installation destination (default: /boot/efi/EFI/BOOT)"
	@echo "  OVMF         - OVMF firmware path for testing"

# Dependency generation
depend: .depend
.depend: $(SOURCE)
	$(CC) $(CFLAGS) -MM $(SOURCE) > .depend
-include .depend