#!/usr/bin/env sh

#  helper script: builds U-Boot source code
#
#	Copyright (C) 2022 Alper Nebi Yasak <alpernebiyasak@gmail.com>
#	Copyright (C) 2023 Leah Rowe <leah@libreboot.org>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

[ "x${DEBUG+set}" = 'xset' ] && set -v
set -u -e

RET=0
pdir="payload/u-boot"
ubdir=""
arch=""
ubtree=""
config_name=""
board_dir=""

our_version="$(cat version)"
projectname="$(cat projectname)"

export LOCALVERSION="-${projectname}-${our_version}"

main()
{
	printf "Building U-Boot payloads\n"

	# Build for all boards if no argument is given
	if [ "$#" -eq 0 ]; then
		for board_dir in resources/u-boot/*; do
			[ ! -d "${board_dir}/config/" ] && \
				continue
			set -- "$@" "${board_dir#resources/u-boot/}"
		done
	fi

	[ ! -d "payload/" ] && \
		mkdir -p payload/
	[ ! -d "${pdir}" ] && \
		mkdir -p ${pdir}/

	for board in "$@"; do
		build_uboot_payloads "${board}" || continue
	done

	printf "Done! U-Boot files are in %s/\n\n" ${pdir}
	exit $RET
}

build_uboot_payloads()
{
	board=${1}

	handle_dependencies "${board}" || return 1

	for config in "${board_dir}/config"/*; do
		config_name="${config#$board_dir/config/}"

		check_config "${board}" "${config}" || continue
		build_uboot_elf "${config}"

		printf "build/u-boot %s: build config %s\n" \
				"${board}" "${config_name}"
	done
}

handle_dependencies()
{
	board=${1}

	board_dir="resources/u-boot/${board}"
	rm -rf "${pdir}/${board}"
	mkdir -p "${pdir}/${board}"

	ubtree="undefined"
	arch="undefined"

	if [ ! -f "${board_dir}/board.cfg" ]; then
		printf "build/u-boot %s: Missing board.cfg.\n" \
				"${board}"
		RET=1
		return 1
	fi

	# Override the above defaults using board.cfg
	source "${board_dir}/board.cfg" # source

	if [ "${ubtree}" = "undefined" ]; then
		printf "build/u-boot %s: ubtree undefined\n" \
				"${board}"
		RET=1
		return 1
	fi
	if [ "${arch}" = "undefined" ]; then
		printf "build/u-boot %s: undefined cpu type\n" \
				"${board}"
		RET=1
		return 1
	fi

	ubdir="u-boot/${board}"
	if [ "${board}" != "${ubtree}" ]; then
		ubdir="u-boot/${ubtree}"
	fi

	if [ ! -d "${ubdir}" ]; then
		./download u-boot "$board"
	fi

	if [ ! -d "${ubdir}" ]; then
		printf "build/u-boot %s: uboot download failed\n" \
				"${board}"
		RET=1
		return 1
	fi
}

check_config()
{
	board=${1}
	config=${2}

	if [ ! -f "${config}" ]; then
		printf "build/u-boot %s: configs missing\n" \
				${board}
		RET=1
		return 1
	fi

	if [ "$config_name" = "default" ]; then
		dest_dir="${pdir}/${board}"
	else
		dest_dir="${pdir}/${board}/${config_name}"
	fi
	mkdir -p "${dest_dir}"

	printf "build/u-boot %s: building config %s).\n" \
			${board} ${config_name}
}

build_uboot_elf()
{
	config=${1}

	make -C "${ubdir}" distclean

	cp "${config}" "${ubdir}/.config"
	make -C "${ubdir}" olddefconfig
	make -C "${ubdir}" -j"$(nproc)" all

	for f in "${ubdir}"/u-boot{,.bin,.dtb,.img,.itb,.elf}; do
		if [ -f "$f" ]; then
			mv "$f" "${dest_dir}/"
		fi
	done

	make -C "${ubdir}" distclean
}

main $@