295 lines
9.4 KiB
Makefile
295 lines
9.4 KiB
Makefile
PROJECT_NAME = ipxe-stub
|
|
SRC_DIR = src
|
|
BUILD_DIR = build
|
|
GNU_EFI_DIR = includes/deps/gnu-efi
|
|
OUTPUT_DIR = output
|
|
KEYS_DIR = keys
|
|
SHIM_DIR = input/shim
|
|
OPENSSL_CNF = openssl.cnf
|
|
|
|
SIGNING_KEY = $(KEYS_DIR)/signing.key
|
|
SIGNING_CERT = $(KEYS_DIR)/signing.crt
|
|
SIGNING_DER = $(KEYS_DIR)/signing.der
|
|
|
|
HOST_ARCH := $(shell uname -m)
|
|
ARCH ?= $(HOST_ARCH)
|
|
|
|
ifeq ($(ARCH),x86_64)
|
|
TARGET_ARCH = x86_64
|
|
EFI_BINARY = BOOTX64.EFI
|
|
STUB_BINARY = stubx64.efi
|
|
ENROLL_BINARY = enroll-x64.efi
|
|
ARCH_CFLAGS = -mno-red-zone
|
|
else ifeq ($(ARCH),aarch64)
|
|
TARGET_ARCH = aarch64
|
|
EFI_BINARY = BOOTAA64.EFI
|
|
STUB_BINARY = stubaa64.efi
|
|
ENROLL_BINARY = enroll-aa64.efi
|
|
ARCH_CFLAGS =
|
|
else ifeq ($(ARCH),ia32)
|
|
TARGET_ARCH = ia32
|
|
EFI_BINARY = BOOTIA32.EFI
|
|
STUB_BINARY = stubia32.efi
|
|
ENROLL_BINARY = enroll-ia32.efi
|
|
ARCH_CFLAGS =
|
|
else
|
|
$(error Unsupported ARCH=$(ARCH). Use x86_64, aarch64, or ia32)
|
|
endif
|
|
|
|
ifeq ($(HOST_ARCH),x86_64)
|
|
HOST_ARCH_NORM = x86_64
|
|
else ifeq ($(HOST_ARCH),aarch64)
|
|
HOST_ARCH_NORM = aarch64
|
|
else ifeq ($(HOST_ARCH),i686)
|
|
HOST_ARCH_NORM = ia32
|
|
else
|
|
HOST_ARCH_NORM = unknown
|
|
endif
|
|
|
|
ifneq ($(HOST_ARCH_NORM),$(TARGET_ARCH))
|
|
CROSS = 1
|
|
else
|
|
CROSS = 0
|
|
endif
|
|
|
|
ifeq ($(CROSS),1)
|
|
ifeq ($(TARGET_ARCH),x86_64)
|
|
CROSS_PREFIX = x86_64-linux-gnu-
|
|
else ifeq ($(TARGET_ARCH),aarch64)
|
|
CROSS_PREFIX = aarch64-linux-gnu-
|
|
else ifeq ($(TARGET_ARCH),ia32)
|
|
CROSS_PREFIX = i686-linux-gnu-
|
|
endif
|
|
CC = $(CROSS_PREFIX)gcc
|
|
LD = $(CROSS_PREFIX)ld
|
|
AR = $(CROSS_PREFIX)ar
|
|
OBJCOPY = $(CROSS_PREFIX)objcopy
|
|
else
|
|
CC = gcc
|
|
LD = ld
|
|
AR = ar
|
|
OBJCOPY = objcopy
|
|
endif
|
|
|
|
GNU_EFI_INC = $(GNU_EFI_DIR)/inc
|
|
GNU_EFI_LIB_DIR = $(GNU_EFI_DIR)/$(TARGET_ARCH)/lib
|
|
GNU_EFI_GNUEFI = $(GNU_EFI_DIR)/gnuefi
|
|
|
|
ARCH_BUILD_DIR = $(BUILD_DIR)/$(TARGET_ARCH)
|
|
EFI_BUILD_DIR = $(ARCH_BUILD_DIR)/efi
|
|
EFI_CRT0 = $(EFI_BUILD_DIR)/crt0-efi-$(TARGET_ARCH).o
|
|
EFI_RELOC = $(EFI_BUILD_DIR)/reloc_$(TARGET_ARCH).o
|
|
EFI_LIBEFI = $(GNU_EFI_LIB_DIR)/libefi.a
|
|
EFI_LIBGNUEFI = $(EFI_BUILD_DIR)/libgnuefi.a
|
|
EFI_LDS = $(GNU_EFI_GNUEFI)/elf_$(TARGET_ARCH)_efi.lds
|
|
|
|
CFLAGS = -I$(GNU_EFI_INC) \
|
|
-I$(GNU_EFI_INC)/$(TARGET_ARCH) \
|
|
-I$(GNU_EFI_INC)/protocol \
|
|
-Iincludes \
|
|
-fno-stack-protector \
|
|
-fpic \
|
|
-fshort-wchar \
|
|
$(ARCH_CFLAGS) \
|
|
-DEFI_FUNCTION_WRAPPER
|
|
|
|
LDFLAGS = -nostdlib \
|
|
-znocombreloc \
|
|
-T $(EFI_LDS) \
|
|
-shared \
|
|
-Bsymbolic \
|
|
-L$(GNU_EFI_LIB_DIR) \
|
|
-L$(EFI_BUILD_DIR) \
|
|
$(EFI_CRT0)
|
|
|
|
LIBS = -l:libgnuefi.a -l:libefi.a
|
|
|
|
OBJCOPY_FLAGS = -j .text \
|
|
-j .sdata \
|
|
-j .data \
|
|
-j .rodata \
|
|
-j .dynamic \
|
|
-j .dynsym \
|
|
-j .rel \
|
|
-j .rela \
|
|
-j .reloc \
|
|
--target=efi-app-$(TARGET_ARCH)
|
|
|
|
LOADER_OBJ = $(ARCH_BUILD_DIR)/loader.o
|
|
LOADER_SO = $(ARCH_BUILD_DIR)/loader.so
|
|
TARGET_EFI = $(OUTPUT_DIR)/$(EFI_BINARY)
|
|
|
|
STUB_OBJ = $(ARCH_BUILD_DIR)/stub.o
|
|
STUB_SO = $(ARCH_BUILD_DIR)/stub.so
|
|
TARGET_STUB = $(OUTPUT_DIR)/$(STUB_BINARY)
|
|
|
|
ENROLL_OBJ = $(ARCH_BUILD_DIR)/enroll.o
|
|
ENROLL_SO = $(ARCH_BUILD_DIR)/enroll.so
|
|
TARGET_ENROLL = $(OUTPUT_DIR)/$(ENROLL_BINARY)
|
|
|
|
.PHONY: all enroll clean distclean all-arches check-deps test-efi info keygen sign iso
|
|
|
|
all: check-deps $(TARGET_EFI) $(TARGET_STUB) $(TARGET_ENROLL)
|
|
@echo "✓ Built: $(TARGET_EFI) (loader → $(STUB_BINARY))"
|
|
@echo "✓ Built: $(TARGET_STUB)"
|
|
@echo "✓ Built: $(TARGET_ENROLL) (→ mm$(TARGET_ARCH).efi on ISO)"
|
|
|
|
all-arches:
|
|
$(MAKE) all ARCH=x86_64
|
|
$(MAKE) all ARCH=aarch64
|
|
$(MAKE) all ARCH=ia32
|
|
|
|
enroll: check-deps $(TARGET_ENROLL)
|
|
@echo "✓ Built: $(TARGET_ENROLL)"
|
|
|
|
check-deps:
|
|
@echo "Host: $(HOST_ARCH) Target: $(TARGET_ARCH) Mode: $(if $(filter 1,$(CROSS)),cross,native)"
|
|
ifeq ($(CROSS),1)
|
|
@which $(CC) > /dev/null 2>&1 || \
|
|
(echo "Install: sudo apt install gcc-$(TARGET_ARCH)-linux-gnu binutils-$(TARGET_ARCH)-linux-gnu" && exit 1)
|
|
endif
|
|
|
|
$(EFI_LIBEFI):
|
|
@echo "→ Building libefi.a"
|
|
@if [ "$(CROSS)" = "1" ]; then \
|
|
$(MAKE) -C $(GNU_EFI_DIR) ARCH=$(TARGET_ARCH) CROSS_COMPILE=$(CROSS_PREFIX) lib; \
|
|
else \
|
|
$(MAKE) -C $(GNU_EFI_DIR) ARCH=$(TARGET_ARCH) lib; \
|
|
fi
|
|
|
|
$(EFI_CRT0): | $(EFI_BUILD_DIR)
|
|
$(CC) -I$(GNU_EFI_INC) -I$(GNU_EFI_INC)/$(TARGET_ARCH) \
|
|
-fno-stack-protector -fpic \
|
|
-c -o $@ $(GNU_EFI_GNUEFI)/crt0-efi-$(TARGET_ARCH).S
|
|
|
|
$(EFI_RELOC): | $(EFI_BUILD_DIR)
|
|
$(CC) -I$(GNU_EFI_INC) -I$(GNU_EFI_INC)/$(TARGET_ARCH) \
|
|
-fno-stack-protector -fpic -fshort-wchar $(ARCH_CFLAGS) \
|
|
-c -o $@ $(GNU_EFI_GNUEFI)/reloc_$(TARGET_ARCH).c
|
|
|
|
$(EFI_LIBGNUEFI): $(EFI_RELOC) | $(EFI_BUILD_DIR)
|
|
$(AR) rcs $@ $(EFI_RELOC)
|
|
|
|
$(BUILD_DIR) $(ARCH_BUILD_DIR) $(OUTPUT_DIR) $(EFI_BUILD_DIR):
|
|
@mkdir -p $@
|
|
|
|
$(LOADER_OBJ): src/loader.c | $(ARCH_BUILD_DIR)
|
|
$(CC) $(CFLAGS) -DSTUB_NAME='"$(STUB_BINARY)"' -c $< -o $@
|
|
|
|
$(LOADER_SO): $(LOADER_OBJ) $(EFI_CRT0) $(EFI_LIBGNUEFI) $(EFI_LIBEFI)
|
|
$(LD) $(LDFLAGS) $(LOADER_OBJ) -o $@ $(LIBS)
|
|
|
|
$(TARGET_EFI): $(LOADER_SO) | $(OUTPUT_DIR)
|
|
$(OBJCOPY) $(OBJCOPY_FLAGS) $(LOADER_SO) $@
|
|
|
|
$(STUB_OBJ): src/stub.c | $(ARCH_BUILD_DIR)
|
|
$(CC) $(CFLAGS) -c $< -o $@
|
|
|
|
$(STUB_SO): $(STUB_OBJ) $(EFI_CRT0) $(EFI_LIBGNUEFI) $(EFI_LIBEFI)
|
|
$(LD) $(LDFLAGS) $(STUB_OBJ) -o $@ $(LIBS)
|
|
|
|
$(TARGET_STUB): $(STUB_SO) | $(OUTPUT_DIR)
|
|
$(OBJCOPY) $(OBJCOPY_FLAGS) $(STUB_SO) $@
|
|
|
|
$(ENROLL_OBJ): src/enroll.c | $(ARCH_BUILD_DIR)
|
|
$(CC) $(CFLAGS) -c $< -o $@
|
|
|
|
$(ENROLL_SO): $(ENROLL_OBJ) $(EFI_CRT0) $(EFI_LIBGNUEFI) $(EFI_LIBEFI)
|
|
$(LD) $(LDFLAGS) $(ENROLL_OBJ) -o $@ $(LIBS)
|
|
|
|
$(TARGET_ENROLL): $(ENROLL_SO) | $(OUTPUT_DIR)
|
|
$(OBJCOPY) $(OBJCOPY_FLAGS) $(ENROLL_SO) $@
|
|
|
|
test-efi:
|
|
@if [ -f "$(TARGET_EFI)" ]; then \
|
|
echo -n " Type: "; file $(TARGET_EFI) | grep -oE "PE32\+? executable.*EFI" || echo "unknown"; \
|
|
echo -n " Size: "; ls -lh $(TARGET_EFI) | awk '{print $$5}'; \
|
|
fi
|
|
|
|
keygen:
|
|
@if [ -f $(SIGNING_KEY) ]; then \
|
|
echo "Keys already exist. Delete keys/ to regenerate."; exit 1; \
|
|
fi
|
|
bash gen-key.sh
|
|
@echo " openssl.cnf — config used for key generation"
|
|
@echo "✓ Keys generated in $(KEYS_DIR)/"
|
|
@echo " signing.key — keep private"
|
|
@echo " signing.crt — PEM cert"
|
|
@echo " signing.der — DER cert (place at EFI/BOOT/cert.der on ISO)"
|
|
|
|
sign: all-arches
|
|
@if [ ! -f $(SIGNING_KEY) ]; then \
|
|
echo "No signing key found. Run: make keygen"; exit 1; \
|
|
fi
|
|
@which sbsign > /dev/null 2>&1 || \
|
|
(echo "Install: sudo apt install sbsigntool" && exit 1)
|
|
|
|
@for efi in $(OUTPUT_DIR)/BOOT*.EFI $(OUTPUT_DIR)/stub*.efi; do \
|
|
[ -f "$$efi" ] || continue; \
|
|
sbsign --key $(SIGNING_KEY) --cert $(SIGNING_CERT) \
|
|
--output "$$efi" "$$efi" 2>&1 | grep -v "^warning:"; \
|
|
echo "✓ Signed: $$efi"; \
|
|
done
|
|
|
|
@[ -f $(OUTPUT_DIR)/enroll-x64.efi ] && \
|
|
sbsign --key $(SIGNING_KEY) --cert $(SIGNING_CERT) \
|
|
--output $(OUTPUT_DIR)/mmx64.efi $(OUTPUT_DIR)/enroll-x64.efi 2>&1 | grep -v "^warning:" && \
|
|
echo "✓ Signed: $(OUTPUT_DIR)/mmx64.efi" || true
|
|
|
|
@[ -f $(OUTPUT_DIR)/enroll-aa64.efi ] && \
|
|
sbsign --key $(SIGNING_KEY) --cert $(SIGNING_CERT) \
|
|
--output $(OUTPUT_DIR)/mmaa64.efi $(OUTPUT_DIR)/enroll-aa64.efi 2>&1 | grep -v "^warning:" && \
|
|
echo "✓ Signed: $(OUTPUT_DIR)/mmaa64.efi" || true
|
|
|
|
@[ -f $(OUTPUT_DIR)/enroll-ia32.efi ] && \
|
|
sbsign --key $(SIGNING_KEY) --cert $(SIGNING_CERT) \
|
|
--output $(OUTPUT_DIR)/mmia32.efi $(OUTPUT_DIR)/enroll-ia32.efi 2>&1 | grep -v "^warning:" && \
|
|
echo "✓ Signed: $(OUTPUT_DIR)/mmia32.efi" || true
|
|
|
|
iso: sign
|
|
@which xorriso > /dev/null 2>&1 || \
|
|
(echo "Install: sudo apt install xorriso" && exit 1)
|
|
@if [ ! -f $(SIGNING_DER) ]; then \
|
|
echo "No signing.der found. Run: make keygen"; exit 1; \
|
|
fi
|
|
@rm -rf iso_root
|
|
@mkdir -p iso_root/EFI/BOOT iso_root/IPXE
|
|
@# Our signed stubs — firmware picks the right arch automatically
|
|
cp $(OUTPUT_DIR)/BOOTX64.EFI iso_root/EFI/BOOT/BOOTX64.EFI
|
|
@[ -f $(OUTPUT_DIR)/BOOTAA64.EFI ] && \
|
|
cp $(OUTPUT_DIR)/BOOTAA64.EFI iso_root/EFI/BOOT/BOOTAA64.EFI || true
|
|
@[ -f $(OUTPUT_DIR)/BOOTIA32.EFI ] && \
|
|
cp $(OUTPUT_DIR)/BOOTIA32.EFI iso_root/EFI/BOOT/BOOTIA32.EFI || true
|
|
@# stub.efi — arch-neutral, loaded by all BOOT*.EFI stubs
|
|
cp $(OUTPUT_DIR)/stub.efi iso_root/EFI/BOOT/stub.efi
|
|
@# Pre-signed + renamed MOK manager binaries
|
|
@[ -f $(OUTPUT_DIR)/mmx64.efi ] && \
|
|
cp $(OUTPUT_DIR)/mmx64.efi iso_root/EFI/BOOT/mmx64.efi || true
|
|
@[ -f $(OUTPUT_DIR)/mmaa64.efi ] && \
|
|
cp $(OUTPUT_DIR)/mmaa64.efi iso_root/EFI/BOOT/mmaa64.efi || true
|
|
@[ -f $(OUTPUT_DIR)/mmia32.efi ] && \
|
|
cp $(OUTPUT_DIR)/mmia32.efi iso_root/EFI/BOOT/mmia32.efi || true
|
|
@# Signing cert — enroll.efi reads this; also enrollable via UEFI setup
|
|
cp $(SIGNING_DER) iso_root/EFI/BOOT/cert.der
|
|
@# iPXE binaries
|
|
@if [ -f ipxe/ipxe.efi ]; then cp ipxe/ipxe.efi iso_root/IPXE/ipxe.efi; \
|
|
else echo "Warning: ipxe/ipxe.efi not found — IPXE/ will be empty"; fi
|
|
@if [ -f ipxe/ipxe-snp.efi ]; then cp ipxe/ipxe-snp.efi iso_root/IPXE/ipxe-snp.efi; \
|
|
else echo "Warning: ipxe/ipxe-snp.efi not found"; fi
|
|
xorriso -as mkisofs \
|
|
-o output/ipxe-boot.iso \
|
|
-e EFI/BOOT/BOOTX64.EFI \
|
|
-no-emul-boot \
|
|
-isohybrid-gpt-basdat \
|
|
iso_root
|
|
@echo "✓ ISO: output/ipxe-boot.iso"
|
|
|
|
clean:
|
|
rm -rf $(BUILD_DIR) $(OUTPUT_DIR) iso_root
|
|
|
|
distclean: clean
|
|
$(MAKE) -C $(GNU_EFI_DIR) clean > /dev/null 2>&1 || true
|
|
|
|
info:
|
|
@echo "Target: $(TARGET_ARCH) Binary: $(EFI_BINARY) Compiler: $(CC)"
|