#!/usr/bin/make -f

SHELL=/bin/bash

include /usr/share/dpkg/default.mk

BUILD_TYPE ?= RELEASE
EDK2_TOOLCHAIN = GCC5
export $(EDK2_TOOLCHAIN)_AARCH64_PREFIX=aarch64-linux-gnu-
export $(EDK2_TOOLCHAIN)_ARM_PREFIX=arm-linux-gnueabi-
export $(EDK2_TOOLCHAIN)_RISCV64_PREFIX=riscv64-linux-gnu-

export PYTHON3_ENABLE=TRUE

ifeq ($(DEB_BUILD_ARCH),amd64)
	EDK2_BUILD_ARCH=X64
endif
ifeq ($(DEB_BUILD_ARCH),i386)
	EDK2_BUILD_ARCH=IA32
endif
ifeq ($(DEB_BUILD_ARCH),arm64)
	EDK2_BUILD_ARCH=AARCH64
endif

PCD_RELEASE_DATE = $(shell date -d@$(SOURCE_DATE_EPOCH) "+%m/%d/%Y")
PCD_FLAGS  = --pcd PcdFirmwareVendor=L"$(shell lsb_release -is) distribution of EDK II\\0"
PCD_FLAGS += --pcd PcdFirmwareVersionString=L"$(DEB_VERSION)\\0"
PCD_FLAGS += --pcd PcdFirmwareReleaseDateString=L"$(PCD_RELEASE_DATE)\\0"
COMMON_FLAGS  = -DCC_MEASUREMENT_ENABLE=TRUE
COMMON_FLAGS += -DNETWORK_HTTP_BOOT_ENABLE=TRUE
COMMON_FLAGS += -DNETWORK_IP6_ENABLE=TRUE
COMMON_FLAGS += -DNETWORK_TLS_ENABLE
COMMON_FLAGS += $(PCD_FLAGS)
OVMF_COMMON_FLAGS  = $(COMMON_FLAGS)
OVMF_COMMON_FLAGS += -DTPM2_ENABLE=TRUE
OVMF_4M_FLAGS = $(OVMF_COMMON_FLAGS) -DFD_SIZE_4MB
OVMF_4M_SECBOOT_FLAGS = $(OVMF_4M_FLAGS) -DBUILD_SHELL=FALSE -DSECURE_BOOT_ENABLE=TRUE -DSMM_REQUIRE=TRUE
OVMF32_4M_FLAGS = $(OVMF_COMMON_FLAGS) -DFD_SIZE_4MB
OVMF32_4M_SECBOOT_FLAGS =  $(OVMF32_4M_FLAGS) -DBUILD_SHELL=FALSE -DSECURE_BOOT_ENABLE=TRUE -DSMM_REQUIRE=TRUE

AAVMF_COMMON_FLAGS  = $(COMMON_FLAGS)
AAVMF_COMMON_FLAGS += -DTPM2_ENABLE=TRUE
AAVMF_COMMON_FLAGS += -DTPM2_CONFIG_ENABLE=TRUE
AAVMF_COMMON_FLAGS += -DCAVIUM_ERRATUM_27456=TRUE
AAVMF_SECBOOT_FLAGS = $(AAVMF_COMMON_FLAGS) -DBUILD_SHELL=FALSE -DSECURE_BOOT_ENABLE=TRUE

RISCV64_FLAGS = $(COMMON_FLAGS)

# Clear variables used internally by the edk2 build system
undefine WORKSPACE
undefine ECP_SOURCE
undefine EDK_SOURCE
undefine EFI_SOURCE
undefine EDK_TOOLS_PATH
undefine CONF_PATH

%:
	dh $@

override_dh_auto_build: build-qemu-efi-aarch64 build-qemu-efi-arm build-ovmf build-ovmf32 build-qemu-efi-riscv64

debian/setup-build-stamp:
	set -e; . ./edksetup.sh; \
	make -C BaseTools ARCH=$(EDK2_BUILD_ARCH)
	touch $@

OVMF_INSTALL_DIR = debian/ovmf-install
OVMF64_BUILD_ROOT = Build/OvmfX64
OVMF64_BUILD_DIR = $(OVMF64_BUILD_ROOT)/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
AMDSEV_BUILD_ROOT = Build/AmdSev
AMDSEV_BUILD_DIR = $(AMDSEV_BUILD_ROOT)/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
OVMF_ENROLL = $(OVMF_INSTALL_DIR)/EnrollDefaultKeys.efi
OVMF_SHELL =  $(OVMF_INSTALL_DIR)/Shell.efi
OVMF_BINARIES = $(OVMF_ENROLL) $(OVMF_SHELL)
OVMF_IMAGES := $(addprefix $(OVMF_INSTALL_DIR)/,OVMF_CODE_4M.fd OVMF_CODE_4M.secboot.fd OVMF_VARS_4M.fd OVMF.amdsev.fd)
OVMF_PREENROLLED_VARS := $(addprefix $(OVMF_INSTALL_DIR)/,OVMF_VARS_4M.ms.fd OVMF_VARS_4M.snakeoil.fd)

OVMF32_INSTALL_DIR = debian/ovmf32-install
OVMF32_BUILD_ROOT = Build/OvmfIa32
OVMF32_BUILD_DIR = $(OVMF32_BUILD_ROOT)/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
OVMF32_SHELL = $(OVMF32_BUILD_DIR)/IA32/Shell.efi
OVMF32_BINARIES = $(OVMF32_SHELL)
OVMF32_IMAGES  := $(addprefix $(OVMF32_INSTALL_DIR)/,OVMF32_CODE_4M.fd OVMF32_CODE_4M.secboot.fd OVMF32_VARS_4M.fd)

AAVMF_INSTALL_DIR = debian/aavmf-install
AAVMF_BUILD_ROOT = Build/ArmVirtQemu-AARCH64
AAVMF_BUILD_DIR = $(AAVMF_BUILD_ROOT)/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
AAVMF_ENROLL    = $(AAVMF_INSTALL_DIR)/EnrollDefaultKeys.efi
AAVMF_SHELL     = $(AAVMF_INSTALL_DIR)/Shell.efi
AAVMF_BINARIES  = $(AAVMF_ENROLL) $(AAVMF_SHELL)
AAVMF_IMAGES    = $(addprefix $(AAVMF_INSTALL_DIR)/,AAVMF_CODE.no-secboot.fd AAVMF_CODE.secboot.fd AAVMF_VARS.fd)
AAVMF_PREENROLLED_VARS = $(addprefix $(AAVMF_INSTALL_DIR)/,AAVMF_VARS.ms.fd AAVMF_VARS.snakeoil.fd)

AAVMF32_INSTALL_DIR = debian/aavmf32-install
AAVMF32_BUILD_ROOT = Build/ArmVirtQemu-ARM
AAVMF32_BUILD_DIR = $(AAVMF32_BUILD_ROOT)/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
AAVMF32_IMAGES    = $(addprefix $(AAVMF32_INSTALL_DIR)/,AAVMF32_CODE.fd AAVMF32_VARS.fd)

RISCV64_INSTALL_DIR = debian/riscv64-install
RISCV64_BUILD_ROOT = Build/RiscVVirtQemu
RISCV64_BUILD_DIR = $(RISCV64_BUILD_ROOT)/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
RISCV64_IMAGES    = $(addprefix $(RISCV64_INSTALL_DIR)/,RISCV_VIRT_CODE.fd RISCV_VIRT_VARS.fd)

build-ovmf32: $(OVMF32_BINARIES) $(OVMF32_IMAGES)
$(OVMF32_BINARIES) $(OVMF32_IMAGES): debian/setup-build-stamp
	rm -rf $(OVMF32_INSTALL_DIR)
	mkdir $(OVMF32_INSTALL_DIR)
	set -e; . ./edksetup.sh; \
		build -a IA32 \
			-t $(EDK2_TOOLCHAIN) \
			-p OvmfPkg/OvmfPkgIa32.dsc \
			$(OVMF32_4M_FLAGS) -b $(BUILD_TYPE)
	cp $(OVMF32_BUILD_DIR)/IA32/Shell.efi \
		$(OVMF32_INSTALL_DIR)/
	cp $(OVMF32_BUILD_DIR)/FV/OVMF_CODE.fd \
		$(OVMF32_INSTALL_DIR)/OVMF32_CODE_4M.fd
	cp $(OVMF32_BUILD_DIR)/FV/OVMF_VARS.fd \
		$(OVMF32_INSTALL_DIR)/OVMF32_VARS_4M.fd
	rm -rf $(OVMF32_BUILD_ROOT)
	set -e; . ./edksetup.sh; \
	build -a IA32 \
		-t $(EDK2_TOOLCHAIN) \
		-p OvmfPkg/OvmfPkgIa32.dsc \
		$(OVMF32_4M_SECBOOT_FLAGS) -b $(BUILD_TYPE)
	cp $(OVMF32_BUILD_DIR)/FV/OVMF_CODE.fd \
		$(OVMF32_INSTALL_DIR)/OVMF32_CODE_4M.secboot.fd

build-ovmf: $(OVMF_BINARIES) $(OVMF_IMAGES) $(OVMF_PREENROLLED_VARS)
$(OVMF_BINARIES) $(OVMF_IMAGES): debian/setup-build-stamp
	rm -rf $(OVMF_INSTALL_DIR)
	mkdir $(OVMF_INSTALL_DIR)
	rm -rf $(OVMF64_BUILD_ROOT)
	set -e; . ./edksetup.sh; \
		build -a X64 \
			-t $(EDK2_TOOLCHAIN) \
			-p OvmfPkg/OvmfPkgX64.dsc \
			$(OVMF_4M_FLAGS) -b $(BUILD_TYPE)
	cp $(OVMF64_BUILD_DIR)/X64/Shell.efi \
		$(OVMF_INSTALL_DIR)/
	cp $(OVMF64_BUILD_DIR)/FV/OVMF.fd $(OVMF_INSTALL_DIR)/
	cp $(OVMF64_BUILD_DIR)/FV/OVMF_CODE.fd \
		$(OVMF_INSTALL_DIR)/OVMF_CODE_4M.fd
	cp $(OVMF64_BUILD_DIR)/FV/OVMF_VARS.fd \
		$(OVMF_INSTALL_DIR)/OVMF_VARS_4M.fd
	rm -rf $(OVMF64_BUILD_ROOT)
	set -e; . ./edksetup.sh; \
		build -a X64 \
			-t $(EDK2_TOOLCHAIN) \
			-p OvmfPkg/OvmfPkgX64.dsc \
			$(OVMF_4M_SECBOOT_FLAGS) -b $(BUILD_TYPE)
	cp $(OVMF64_BUILD_DIR)/X64/EnrollDefaultKeys.efi \
		$(OVMF_INSTALL_DIR)/
	cp $(OVMF64_BUILD_DIR)/FV/OVMF_CODE.fd \
		$(OVMF_INSTALL_DIR)/OVMF_CODE_4M.secboot.fd
	rm -rf $(AMDSEV_BUILD_ROOT)
	touch OvmfPkg/AmdSev/Grub/grub.efi
	set -e; . ./edksetup.sh; \
		build -a X64 \
			-t $(EDK2_TOOLCHAIN) \
			-p OvmfPkg/AmdSev/AmdSevX64.dsc \
			$(OVMF_COMMON_FLAGS) -b $(BUILD_TYPE)
	cp $(AMDSEV_BUILD_DIR)/FV/OVMF.fd \
		$(OVMF_INSTALL_DIR)/OVMF.amdsev.fd

ifeq ($(call dpkg_vendor_derives_from_v1,ubuntu),yes)
debian/PkKek-1-vendor.pem: debian/PkKek-1-Ubuntu.pem
else
debian/PkKek-1-vendor.pem: debian/PkKek-1-Debian.pem
endif
	ln -sf `basename $<` $@

debian/oem-string-%: debian/PkKek-1-%.pem
	tr -d '\n' < $< | \
		sed -e 's/.*-----BEGIN CERTIFICATE-----/4e32566d-8e9e-4f52-81d3-5bb9715f9727:/' -e 's/-----END CERTIFICATE-----//' > $@

%/AAVMF_VARS.ms.fd: %/AAVMF_CODE.secboot.fd %/AAVMF_VARS.fd debian/oem-string-vendor $(AAVMF_ENROLL) $(AAVMF_SHELL)
	PYTHONPATH=$(CURDIR)/debian/python \
	python3 ./debian/edk2-vars-generator.py -d \
		-f AAVMF -e $(AAVMF_ENROLL) -s $(AAVMF_SHELL) \
		-c $(AAVMF_INSTALL_DIR)/AAVMF_CODE.secboot.fd \
		-V $(AAVMF_INSTALL_DIR)/AAVMF_VARS.fd \
		-C `< debian/oem-string-vendor` -o $@

%/AAVMF_VARS.snakeoil.fd: %/AAVMF_CODE.no-secboot.fd %/AAVMF_VARS.fd debian/oem-string-snakeoil $(AAVMF_ENROLL) $(AAVMF_SHELL)
	PYTHONPATH=$(CURDIR)/debian/python \
	python3 ./debian/edk2-vars-generator.py -d \
		-f AAVMF -e $(AAVMF_ENROLL) -s $(AAVMF_SHELL) \
		-c $(AAVMF_INSTALL_DIR)/AAVMF_CODE.secboot.fd \
		-V $(AAVMF_INSTALL_DIR)/AAVMF_VARS.fd \
		--no-default \
		-C `< debian/oem-string-snakeoil` -o $@

%/OVMF_VARS.ms.fd: %/OVMF_CODE.secboot.fd %/OVMF_VARS.fd debian/oem-string-vendor $(OVMF_ENROLL) $(OVMF_SHELL)
	PYTHONPATH=$(CURDIR)/debian/python \
	python3 ./debian/edk2-vars-generator.py -d \
		-f OVMF -e $(OVMF_ENROLL) -s $(OVMF_SHELL) \
		-c $(OVMF_INSTALL_DIR)/OVMF_CODE.secboot.fd \
		-V $(OVMF_INSTALL_DIR)/OVMF_VARS.fd \
		-C `< debian/oem-string-vendor` -o $@

%/OVMF_VARS_4M.ms.fd: %/OVMF_CODE_4M.secboot.fd %/OVMF_VARS_4M.fd debian/oem-string-vendor $(OVMF_ENROLL) $(OVMF_SHELL)
	PYTHONPATH=$(CURDIR)/debian/python \
	python3 ./debian/edk2-vars-generator.py -d \
		-f OVMF_4M -e $(OVMF_ENROLL) -s $(OVMF_SHELL) \
		-c $(OVMF_INSTALL_DIR)/OVMF_CODE_4M.secboot.fd \
		-V $(OVMF_INSTALL_DIR)/OVMF_VARS_4M.fd \
		-C `< debian/oem-string-vendor` -o $@

%/OVMF_VARS_4M.snakeoil.fd: %/OVMF_CODE_4M.fd %/OVMF_VARS_4M.fd debian/oem-string-snakeoil $(OVMF_ENROLL) $(OVMF_SHELL)
	PYTHONPATH=$(CURDIR)/debian/python \
	python3 ./debian/edk2-vars-generator.py -d \
		-f OVMF_4M -e $(OVMF_ENROLL) -s $(OVMF_SHELL) \
		-c $(OVMF_INSTALL_DIR)/OVMF_CODE_4M.secboot.fd \
		-V $(OVMF_INSTALL_DIR)/OVMF_VARS_4M.fd \
		--no-default \
		-C `< debian/oem-string-snakeoil` -o $@

ArmPkg/Library/GccLto/liblto-aarch64.a:	ArmPkg/Library/GccLto/liblto-aarch64.s
	$($(EDK2_TOOLCHAIN)_AARCH64_PREFIX)gcc -c -fpic $< -o $@

ArmPkg/Library/GccLto/liblto-arm.a: ArmPkg/Library/GccLto/liblto-arm.s
	$($(EDK2_TOOLCHAIN)_ARM_PREFIX)gcc -c -fpic $< -o $@

build-qemu-efi-aarch64: $(AAVMF_BINARIES) $(AAVMF_IMAGES) $(AAVMF_PREENROLLED_VARS)
$(AAVMF_BINARIES) $(AAVMF_IMAGES): debian/setup-build-stamp ArmPkg/Library/GccLto/liblto-aarch64.a
	rm -rf $(AAVMF_INSTALL_DIR)
	mkdir $(AAVMF_INSTALL_DIR)
	set -e; . ./edksetup.sh; \
		build -a AARCH64 \
			-t $(EDK2_TOOLCHAIN) \
			-p ArmVirtPkg/ArmVirtQemu.dsc \
			$(AAVMF_SECBOOT_FLAGS) -b $(BUILD_TYPE)
	cp $(AAVMF_BUILD_DIR)/AARCH64/EnrollDefaultKeys.efi \
		$(AAVMF_INSTALL_DIR)/
	cp $(AAVMF_BUILD_DIR)/FV/QEMU_EFI.fd $(AAVMF_INSTALL_DIR)
	cp $(AAVMF_BUILD_DIR)/FV/QEMU_EFI.fd \
		$(AAVMF_INSTALL_DIR)/AAVMF_CODE.secboot.fd
	cp $(AAVMF_BUILD_DIR)/FV/QEMU_VARS.fd \
		$(AAVMF_INSTALL_DIR)/AAVMF_VARS.fd
	rm -rf $(AAVMF_BUILD_ROOT)
	set -e; . ./edksetup.sh; \
		build -a AARCH64 \
			-t $(EDK2_TOOLCHAIN) \
			-p ArmVirtPkg/ArmVirtQemu.dsc \
			$(AAVMF_COMMON_FLAGS) -b $(BUILD_TYPE)
	cp $(AAVMF_BUILD_DIR)/AARCH64/Shell.efi \
		$(AAVMF_INSTALL_DIR)/
	cp $(AAVMF_BUILD_DIR)/FV/QEMU_EFI.fd \
		$(AAVMF_INSTALL_DIR)/AAVMF_CODE.no-secboot.fd
	# QEMU expects 64MiB CODE and VARS files on ARM/AARCH64 architectures
	# Truncate the firmware files to the expected size
	truncate -s 64M $(AAVMF_INSTALL_DIR)/AAVMF_CODE.no-secboot.fd
	truncate -s 64M $(AAVMF_INSTALL_DIR)/AAVMF_CODE.secboot.fd
	truncate -s 64M $(AAVMF_INSTALL_DIR)/AAVMF_VARS.fd

build-qemu-efi-arm: $(AAVMF32_IMAGES)
$(AAVMF32_IMAGES): debian/setup-build-stamp ArmPkg/Library/GccLto/liblto-arm.a
	rm -rf $(AAVMF32_INSTALL_DIR)
	mkdir $(AAVMF32_INSTALL_DIR)
	set -e; . ./edksetup.sh; \
		build -a ARM \
			-t $(EDK2_TOOLCHAIN) \
			-p ArmVirtPkg/ArmVirtQemu.dsc \
			$(AAVMF32_FLAGS) -b $(BUILD_TYPE)
	cp $(AAVMF32_BUILD_DIR)/ARM/Shell.efi \
		$(AAVMF32_INSTALL_DIR)/
	cp $(AAVMF32_BUILD_DIR)/FV/QEMU_EFI.fd $(AAVMF32_INSTALL_DIR)
	cp $(AAVMF32_BUILD_DIR)/FV/QEMU_EFI.fd \
		$(AAVMF32_INSTALL_DIR)/AAVMF32_CODE.fd
	cp $(AAVMF32_BUILD_DIR)/FV/QEMU_VARS.fd \
		$(AAVMF32_INSTALL_DIR)/AAVMF32_VARS.fd
	# QEMU expects 64MiB CODE and VARS files on ARM/AARCH64 architectures
	# Truncate the firmware files to the expected size
	truncate -s 64M $(AAVMF32_INSTALL_DIR)/AAVMF32_CODE.fd
	truncate -s 64M $(AAVMF32_INSTALL_DIR)/AAVMF32_VARS.fd

build-qemu-efi-riscv64:  $(RISCV64_IMAGES)
$(RISCV64_IMAGES): debian/setup-build-stamp
	rm -rf $(RISCV64_INSTALL_DIR)
	mkdir $(RISCV64_INSTALL_DIR)
	set -e; . ./edksetup.sh; \
		build -a RISCV64 \
			-t $(EDK2_TOOLCHAIN) \
			-p OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc \
			$(RISCV64_FLAGS) -b $(BUILD_TYPE)
	cp $(RISCV64_BUILD_DIR)/RISCV64/Shell.efi \
		$(RISCV64_INSTALL_DIR)/
	cp $(RISCV64_BUILD_DIR)/FV/RISCV_VIRT_CODE.fd \
		$(RISCV64_INSTALL_DIR)/
	cp $(RISCV64_BUILD_DIR)/FV/RISCV_VIRT_VARS.fd \
		$(RISCV64_INSTALL_DIR)/
	truncate -s 32M $(RISCV64_INSTALL_DIR)/RISCV_VIRT_CODE.fd
	truncate -s 32M $(RISCV64_INSTALL_DIR)/RISCV_VIRT_VARS.fd

override_dh_auto_clean:
	-. ./edksetup.sh; build clean
	make -C BaseTools clean

# Only embed code that is actually used; requested by the Ubuntu Security Team
EMBEDDED_SUBMODULES += CryptoPkg/Library/OpensslLib/openssl
EMBEDDED_SUBMODULES += ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3
EMBEDDED_SUBMODULES += MdeModulePkg/Library/BrotliCustomDecompressLib/brotli
EMBEDDED_SUBMODULES += MdePkg/Library/MipiSysTLib/mipisyst
get-orig-source:
	# Should be executed on a checkout of the upstream master branch,
	# with the debian/ directory manually copied in.
	rm -rf edk2.tmp && git clone . edk2.tmp
	# Embed submodules. Don't recurse - openssl will bring in MBs of
	# stuff we don't need
	set -e; cd edk2.tmp; \
	for submodule in $(EMBEDDED_SUBMODULES); do \
		git submodule update --depth 1 --init $$submodule; \
	done
	rm -rf edk2-$(DEB_VERSION_UPSTREAM) && \
		mkdir edk2-$(DEB_VERSION_UPSTREAM)
	cd edk2.tmp && git archive HEAD | \
		tar xv -C ../edk2-$(DEB_VERSION_UPSTREAM)
	cd edk2.tmp && git submodule foreach \
		'git archive HEAD | tar xv -C $$toplevel/../edk2-$(DEB_VERSION_UPSTREAM)/$$sm_path'
	ln -s ../debian edk2-$(DEB_VERSION_UPSTREAM)
	# Remove known-binary files
	cd edk2-$(DEB_VERSION_UPSTREAM) && python3 ./debian/remove-binaries.py
	# Look for possible unknown binary files
	cd edk2-$(DEB_VERSION_UPSTREAM) && python3 ./debian/find-binaries.py
	rm edk2-$(DEB_VERSION_UPSTREAM)/debian
	tar Jcvf ../edk2_$(DEB_VERSION_UPSTREAM).orig.tar.xz \
		edk2-$(DEB_VERSION_UPSTREAM)
	rm -rf edk2.tmp edk2-$(DEB_VERSION_UPSTREAM)

.PHONY: build-ovmf build-ovmf32 build-qemu-efi build-qemu-efi-aarch64 build-qemu-efi-arm build-qemu-efi-riscv64
