ifeq "$(CONFIG_COREBOOT)" "y"

CONFIG_COREBOOT_ROM			?= coreboot.rom
CONFIG_COREBOOT_BOOTBLOCK	?=

ifeq "$(CONFIG_TARGET_ARCH)" "x86"
	COREBOOT_TARGET := i386
	LINUX_IMAGE_FILE := bzImage
	COREBOOT_TARGET_CROSS :=
else ifeq "$(CONFIG_TARGET_ARCH)" "ppc64"
	COREBOOT_TARGET := ppc64
	LINUX_IMAGE_FILE := zImage
	# skiboot payload needs the Heads toolchain as it is little-endian (like
	# Linux), but coreboot is big-endian on PPC64.
	COREBOOT_TARGET_CROSS := CROSS=$(CROSS)
else
	$(error "$(CONFIG_TARGET_ARCH) target isn't supported by this module")
endif

# Each coreboot version is defined as a separate module, but only the needed
# modules become dependencies of the current board.  One coreboot version is
# selected for the toolchain build and firmware build.  These can be the same
# (when using a coreboot release) or different (when using a fork that reuses a
# release's toolchain).

# Define a coreboot module.  Parameters:
# $1 - module version
# $2 - toolchain coreboot version - if nonempty, uses the toolchain from this
#      version (use for forks to avoid building extra copies of the same
#      toolchain)
#
# For a coreboot release:
# - the version is the coreboot release version
# - set coreboot-<version>_hash to the tarball hash
# - set coreboot-blobs-<version>_hash to the blobs tarball hash
#
# For a git fork:
# - the version is the name of the fork (just controls the build directory used)
# - set coreboot-<version>_repo to the git repo address
# - set coreboot-<version>_commit_hash to the git commit
define coreboot_module =
	coreboot-$(1)_version := $(1)
	coreboot-$(1)_module_file := coreboot
	coreboot-$(1)_base_dir := coreboot-$(1)
	coreboot-$(1)_dir := coreboot-$(1)/$(BOARD)
	coreboot-$(1)_toolchain := $(2)
	# These are ignored if this version is a git fork
	coreboot-$(1)_tar := coreboot-$(1).tar.xz
	coreboot-$(1)_url := https://www.coreboot.org/releases/coreboot-$(1).tar.xz
	# These are only used for releases, git forks don't use upstream blobs
	coreboot-blobs-$(1)_version := $(1)
	coreboot-blobs-$(1)_module_file := coreboot
	coreboot-blobs-$(1)_dir := coreboot-$(1)/3rdparty
	coreboot-blobs-$(1)_tar := coreboot-blobs-$(1).tar.xz
	coreboot-blobs-$(1)_url := https://www.coreboot.org/releases/coreboot-blobs-$(1).tar.xz
	coreboot-blobs-$(1)_tar_opt := --strip 2
endef

# coreboot releases

coreboot-4.11_hash := 97fd859b4c39a25534fe33c30eb86e54a233952e08a024c55858d11598a8ad87
coreboot-blobs-4.11_hash := aa7855c5bd385b3360dadc043ea6bc93f564e6e4840d9b3ee5b9e696bbd055db
$(eval $(call coreboot_module,4.11,))

coreboot-4.19_hash := 65ccb2f46535b996e0066a1b76f81c8cf1ff3e27df84b3f97d8ad7b3e7cf0a43
coreboot-blobs-4.19_hash := 30214caed07b25f11e47bec022ff6234841376e36689eb674de2330a3e980cbc
$(eval $(call coreboot_module,4.19,))

coreboot-4.20.1_hash := b41539a8c2eab2fec752157eb4acbd0e2a637a7203530c12e66b43a5c3c3a931
coreboot-blobs-4.20.1_hash := 30f9d8618e78d483d0903976982485e70825ca3469efd17902c9246aaefd7c4a
$(eval $(call coreboot_module,4.20.1,))

# coreboot git forks

# talos_2 could use the 4.20.1 toolchain, but it's the only ppc64 fork, so
# there is no point preparing another coreboot module that won't be shared with
# anything.
coreboot-talos_2_repo := https://github.com/Dasharo/coreboot
coreboot-talos_2_commit_hash := fc47236e9877f4113dfcce07fa928f52d4d2c8ee
$(eval $(call coreboot_module,talos_2,))

# Similarly, purism is based on 4.21, but nothing builds against 4.21 itself
# or any other fork - no benefit to sharing the toolchain yet.
coreboot-purism_repo := https://source.puri.sm/firmware/coreboot.git
coreboot-purism_commit_hash := 0d57cff58fba2f3a4d3a714a4eae65753e58c6ff
$(eval $(call coreboot_module,purism,))

#Nitrokey nv41/ns50 are based on Dasharo coreboot port,
# with patches staging under coreboot-clevo_release
coreboot-nitrokey_repo := https://github.com/dasharo/coreboot
coreboot-nitrokey_commit_hash := 1bcb338682b612cfcca8bba02846f78139b2e0c8
coreboot-nitrokey_patch_version := clevo_release
#We use clevo_release's crossgcc for now, unshared but between nitropad nv41/ns50
$(eval $(call coreboot_module,nitrokey,))

# Check that the board configured the coreboot version correctly
ifeq "$(CONFIG_COREBOOT_VERSION)" ""
	$(error "$(BOARD): does not specify coreboot version under CONFIG_COREBOOT_VERSION")
else ifeq "$(coreboot-$(CONFIG_COREBOOT_VERSION)_dir)" ""
	$(error "$(BOARD): coreboot version $(CONFIG_COREBOOT_VERSION) not known"
endif 

coreboot_module := coreboot-$(CONFIG_COREBOOT_VERSION)
modules-y += $(coreboot_module)
# Don't make everyone type $($(coreboot_module)_dir)
coreboot_dir := $($(coreboot_module)_dir)
coreboot_base_dir := $($(coreboot_module)_base_dir)

$(coreboot_module)_depends += $(if $(CONFIG_PURISM_BLOBS), purism-blobs)
$(coreboot_module)_depends += $(if $(CONFIG_NITROKEY_BLOBS), nitrokey-blobs)

# coreboot builds are specialized on a per-target basis.
# The builds are done in a per-target subdirectory
CONFIG_COREBOOT_CONFIG ?= config/coreboot-$(BOARD).config

# Ensure that touching the config file will force a rebuild
$(build)/$(coreboot_dir)/.configured: $(CONFIG_COREBOOT_CONFIG)

EXTRA_FLAGS ?= -fdebug-prefix-map=$(pwd)=heads -gno-record-gcc-switches -Wno-error=packed-not-aligned -Wno-address-of-packed-member

# Select the coreboot version to use for the toolchain
ifeq "$($(coreboot_module)_toolchain)" ""
	# Use the same module
	coreboot_toolchain_module := $(coreboot_module)
else
	# Use a different module
	coreboot_toolchain_module := coreboot-$($(coreboot_module)_toolchain)
	modules-y += $(coreboot_toolchain_module)
	# The toolchain module won't build anything for this board, we just need
	# the module prepped so we can hook up the toolchain target
	$(coreboot_toolchain_module)_output := .nobuild
	$(coreboot-toolchain_module)_configure := echo -e 'all:\n\ttouch .nobuild' > Makefile.nobuild
	$(coreboot-toolchain_module)_target := -f Makefile.nobuild
endif

$(coreboot_module)_configure := \
	mkdir -p "$(build)/$(coreboot_dir)" \
	&& $(call install_config,$(pwd)/$(CONFIG_COREBOOT_CONFIG),$(build)/$(coreboot_dir)/.config) \
	&& echo 'CONFIG_LOCALVERSION="$(BRAND_NAME)-$(HEADS_GIT_VERSION)"' >> $(build)/$(coreboot_dir)/.config \
	&& echo 'CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME="$(BOARD)"' >> $(build)/$(coreboot_dir)/.config \
	&& $(MAKE) olddefconfig \
		-C "$(build)/$(coreboot_base_dir)" \
		obj="$(build)/$(coreboot_dir)" \
		DOTCONFIG="$(build)/$(coreboot_dir)/.config" \
		BUILD_TIMELESS=1 \
		CFLAGS_x86_32="$(EXTRA_FLAGS)" \
		CFLAGS_x86_64="$(EXTRA_FLAGS)" \

# Create a dependency from coreboot to the toolchain.  Use .heads-toolchain to
# mark that the toolchain was built.
COREBOOT_TOOLCHAIN=$(build)/$($(coreboot_toolchain_module)_base_dir)/.heads-toolchain
$(COREBOOT_TOOLCHAIN): $(build)/$($(coreboot_toolchain_module)_base_dir)/.canary
	$(MAKE) -C "$(build)/$($(coreboot_toolchain_module)_base_dir)" CPUS=$(CPUS) "crossgcc-$(COREBOOT_TARGET)"
	touch "$@"

$(build)/$(coreboot_dir)/.configured: $(COREBOOT_TOOLCHAIN)

# Build with the cross toolchain from the toolchain module (which might be the
# same coreboot module or a different one).
$(coreboot_module)_target := \
	-C "$(build)/$(coreboot_base_dir)" \
	obj="$(build)/$(coreboot_dir)" \
	DOTCONFIG="$(build)/$(coreboot_dir)/.config" \
	XGCCPATH="$(build)/$($(coreboot_toolchain_module)_base_dir)/util/crossgcc/xgcc/bin/" \
	$(COREBOOT_TARGET_CROSS) \
	BUILD_TIMELESS=1 \
	CFLAGS_x86_32="$(EXTRA_FLAGS)" \
	CFLAGS_x86_64="$(EXTRA_FLAGS)" \
	$(MAKE_JOBS)

$(coreboot_module)_output := $(CONFIG_COREBOOT_ROM)
$(coreboot_module)_output += $(CONFIG_COREBOOT_BOOTBLOCK)

# Force a rebuild if the inputs have changed
$(build)/$(coreboot_dir)/.build: \
	$(build)/$(BOARD)/$(LINUX_IMAGE_FILE) \
	$(build)/$(BOARD)/initrd.cpio.xz \

# This produces a ROM image that is written with the flashrom program
ifneq ($(CONFIG_COREBOOT),)

$(build)/$(BOARD)/$(CB_OUTPUT_FILE): $(build)/$(coreboot_dir)/.build
	# Use coreboot.rom, because custom output files might not be processed by cbfstool
	"$(build)/$(coreboot_dir)/cbfstool" "$(dir $<)coreboot.rom" print
	$(call do-copy,$(dir $<)$(CONFIG_COREBOOT_ROM),$@)
	@touch $@   # update the time stamp

ifneq ($(CONFIG_COREBOOT_BOOTBLOCK),)
$(build)/$(BOARD)/$(CB_BOOTBLOCK_FILE): $(build)/$(coreboot_dir)/.build
	$(call do-copy,$(dir $<)$(CONFIG_COREBOOT_BOOTBLOCK),$@)
	@touch $@   # update the time stamp
endif

endif

#
# Helpful target for reconfiguring the coreboot target
#
coreboot.save_in_defconfig_format_in_place:
	mkdir -p "$(build)/$(coreboot_dir)" && \
	cp "$(pwd)/$(CONFIG_COREBOOT_CONFIG)" "$(build)/$(coreboot_dir)/.config" && \
	$(MAKE) \
		-C "$(build)/$(coreboot_base_dir)" \
		DOTCONFIG="$(build)/$(coreboot_dir)/.config" \
		olddefconfig && \
	$(MAKE) \
		-C "$(build)/$(coreboot_base_dir)" \
 		DOTCONFIG="$(build)/$(coreboot_dir)/.config" \
		savedefconfig && \
	mv "$(build)/$(coreboot_base_dir)/defconfig" "$(pwd)/$(CONFIG_COREBOOT_CONFIG)"
	
coreboot.save_in_oldconfig_format_in_place:
	mkdir -p "$(build)/$(coreboot_dir)" && \
	cp "$(pwd)/$(CONFIG_COREBOOT_CONFIG)" "$(build)/$(coreboot_dir)/.config" && \
	$(MAKE) \
		-C "$(build)/$(coreboot_base_dir)" \
		DOTCONFIG="$(build)/$(coreboot_dir)/.config" \
		olddefconfig \
	&& mv "$(build)/$(coreboot_dir)/.config" "$(pwd)/$(CONFIG_COREBOOT_CONFIG)"

coreboot.modify_defconfig_in_place:
	mkdir -p "$(build)/$(coreboot_dir)" && \
	cp "$(pwd)/$(CONFIG_COREBOOT_CONFIG)" "$(build)/$(coreboot_dir)/.config" && \
	$(MAKE) \
		-C "$(build)/$(coreboot_base_dir)" \
		DOTCONFIG="$(build)/$(coreboot_dir)/.config" \
		menuconfig \
	&& $(MAKE) \
		-C "$(build)/$(coreboot_base_dir)" \
		DOTCONFIG="$(build)/$(coreboot_dir)/.config" \
		DEFCONFIG="$(pwd)/$(CONFIG_COREBOOT_CONFIG)" \
		savedefconfig

coreboot.modify_and_save_oldconfig_in_place:
	mkdir -p "$(build)/$(coreboot_dir)" && \
	$(MAKE) menuconfig \
		-C "$(build)/$(coreboot_base_dir)" \
		obj="$(build)/$(coreboot_dir)" \
		DOTCONFIG="$(pwd)/$(CONFIG_COREBOOT_CONFIG)"

# if we are not building from a git checkout,
# we must also download the coreboot-blobs tree
ifeq "$($(coreboot_module)_repo)" ""

coreboot-blobs_module := coreboot-blobs-$(CONFIG_COREBOOT_VERSION)

$(coreboot_module)_depends += $(coreboot-blobs_module)
modules-y += $(coreboot-blobs_module)

## there is nothing to build for the blobs, this should be
## made easier to make happen
$(coreboot-blobs_module)_output := .built
$(coreboot-blobs_module)_configure := echo -e 'all:\n\ttouch .built' > Makefile

endif
endif
