#!/bin/bash

#  helper script: downloads coreboot and patches/deblobs it
#
#	Copyright (C) 2014, 2015, 2016 Francis Rowe <info@gluglug.org.uk>
#	Copyright (C) 2015 Paul Kocialkowski <contact@paulk.fr>
#
#    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/>.
#

# This script assumes that the working directory is the
# root of libreboot_src or libreboot git.

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

if [ -f "version" ]; then
	# _src release archive is being used
	version="libreboot-$(cat version)"
else
	# git repo is being used
	version="libreboot-$(git describe --tags HEAD)"
fi

# sanity check (check for invalid paths in the reused.list patch lists before proceeding)
for payloads in resources/libreboot/config/*; do

	if [ ! -d "${payloads}/" ]; then
		continue
	fi

	payload="${payloads##*/}"

	for boardconfig in resources/libreboot/config/${payload}/*; do

		if [ ! -d "${boardconfig}/" ]; then
			continue
		fi

		boardname="${boardconfig##*/}"
		cbrevision=$(cat "${boardconfig}/cbrevision")
		vbootrevision=$(cat "${boardconfig}/vbootrevision")

		reused_coreboot_patches="resources/libreboot/patch/coreboot/${cbrevision}/${payload}/${boardname}/reused.list"
		reused_vboot_patches="resources/libreboot/patch/vboot/${vbootrevision}/${payload}/${boardname}/reused.list"
		for reused_patches in "${reused_coreboot_patches}" "${reused_vboot_patches}"; do
			if [ -f "${reused_patches}" ]; then
				for patch in $(cat "${reused_patches}"); do
					if [ ! -f "./${patch}" ]; then
						printf "%s listed in %s does not exist\n" "${patch}" "${reused_patches}"
						exit 1
					fi
				done
			fi
		done

	done
done

# in ascending filename order, apply patches from a directory
apply_patches_from_directory() {
	patch_directory="${1}" # directory containing the patch files

	if [ -d "${patch_directory}" ]; then
		for patch in ${patch_directory}/*.patch;  do

			if [ "${patch##*/}" = "*.patch" ]; then # oh so ugly
				continue # ugly ugly ugly ugly ugly
			fi # most hideous thing you've ever seen

			git am "${patch}" || return 1
		done
	fi
}
# files listed in the file (if found) are absolute paths, relative to the root of the libreboot src directory
# the file lists patches patches that should be applied
apply_patches_from_file() {
	patch_list="${1}" # file listing the paths to all the patches
	libreboot_src_root="${2}" # path to the root of the libreboot_src directory

	if [ -f "${patch_list}" ]; then
		for patchname in $(cat "${patch_list}"); do
			git am "${libreboot_src_root}/${patchname}" || return 1
		done
	fi
}
make_coreboot_src_directory() {
	payload="${1}"
	boardname="${2}"
	firmwarepath="${3}" # libreboot_src/coreboot/
(
	cd "${firmwarepath}/"
	# copy coreboot directory there
	rm -Rf "${payload:?}/${boardname:?}/"
	if [ ! -d "${payload}/" ]; then
		mkdir -p "${payload}/"
	fi
	cp -R "coreboot/" "${payload}/${boardname}/"
)
}
reset_at_revision() {
	revision="${1}"
	git reset --hard ${revision}
}

printf "Downloading coreboot, patching coreboot and deblobbing coreboot\n"

# This grabs current base used, and applies patches
# This is also used to run the deblob scripts.

# Remove the old version that may exist
# ------------------------------------------------------------------------------

rm -Rf "coreboot/"

mkdir "coreboot/"

cd "coreboot/"

# Get latest coreboot:
# ------------------------------------------------------------------------------

# download it using git
git clone https://review.coreboot.org/coreboot

# there are modifications required
cd "coreboot/"

# Define a common version (based on the libreboot version)
# Most likely redundant, because the build system needs to update
# this every time when building a ROM image anyway
printf '%s\n' "${version}" >".coreboot-version"

# vboot submodule is needed
# ------------------------------------------------------------------------------

git submodule update --init --checkout -- 3rdparty/vboot/

# Create branches, with patches in each branch
# Create separate coreboot source directories *for each board*
# ------------------------------------------------------------------------------

for payloads in ../../resources/libreboot/config/*; do

	if [ ! -d "${payloads}/" ]; then
		continue
	fi

	payload="${payloads##*/}"

	for boardconfig in ../../resources/libreboot/config/${payload}/*; do

		if [ ! -d "${boardconfig}/" ]; then
			continue
		fi

		boardname="${boardconfig##*/}"
		cbrevision=$(cat "${boardconfig}/cbrevision")
		vbootrevision=$(cat "${boardconfig}/vbootrevision")

		make_coreboot_src_directory ${payload} ${boardname} ..

		# patch that version
		(

			cd "../${payload}/${boardname}/"
			reset_at_revision ${cbrevision}

			# apply patches (coreboot, common to all systems using this revision)
			apply_patches_from_directory "../../../resources/libreboot/patch/common/coreboot/${cbrevision}"
			# apply patches re-used from other boards, before applying main patches (common patches for similar boards)
			apply_patches_from_file "../../../resources/libreboot/patch/coreboot/${cbrevision}/${payload}/${boardname}/reused.list" ../../..
			# apply patches (coreboot, machine-specific for this revision)
			apply_patches_from_directory "../../../resources/libreboot/patch/coreboot/${cbrevision}/${payload}/${boardname}"

			cd "3rdparty/vboot/"
			# reset to known revision (vboot)
			reset_at_revision ${vbootrevision}

			# apply patches (vboot, common to all systems using this revision)
			apply_patches_from_directory "../../../../../resources/libreboot/patch/common/vboot/${vbootrevision}"
			# apply patches re-used from other boards, before applying main patches (common patches for similar boards)
			apply_patches_from_file "../../../../../resources/libreboot/patch/vboot/${vbootrevision}/${payload}/${boardname}/reused.list" ../../../../..
			# apply patches (vboot, machine-specific for this revision)
			apply_patches_from_directory "../../../../../resources/libreboot/patch/vboot/${vbootrevision}/${payload}/${boardname}"

		)
	done
done

# prepare directories for crossgcc
for payloads in ../../resources/libreboot/config/*; do

	if [ ! -d "${payloads}/" ]; then
		continue
	fi

	payload="${payloads##*/}"

	for boardconfig in ../../resources/libreboot/config/${payload}/*; do

		if [ ! -d "${boardconfig}/" ]; then
			continue
		fi

		boardname="${boardconfig##*/}"
		cbrevision=$(cat "${boardconfig}/cbrevision")
		vbootrevision=$(cat "${boardconfig}/vbootrevision")

		# Create coreboot directory for compiling crossgcc
		if [ ! -d "../crossgcc/${cbrevision}" ]; then
			make_coreboot_src_directory crossgcc ${cbrevision} ..
			(
				cd "../crossgcc/${cbrevision}/"
				# reset to known revision (coreboot)
				reset_at_revision ${cbrevision}
				# no way to know which vboot revision is used here, so delete 3rdparty
				rm -Rf "3rdparty/"
			)
		fi
	done
done

# go back to _src/coreboot/ (containing all coreboot directories)
cd "../"
# delete the gitted one (not needed anymore)
rm -Rf "coreboot/"

# Run coreboot-libre deblob scripts
# ------------------------------------------------------------------------------

printf "Deleting .git* in coreboot/ (history inside .git contains the blobs that were deleted)\n"
rm -Rf */*/.git*
rm -Rf */*/3rdparty/*/.git*

# Delete crossgcc from non-crossgcc coreboot archives
# (the build system will create symlinks later when building the ROM images)
for payload in *; do
	if [ "${payload##*/}" != "crossgcc" ]; then
		rm -Rf ${payload:?}/*/util/crossgcc/
	fi
done
cd "../"

printf "Deblobbing coreboot\n"
./resources/utilities/coreboot-libre/deblob

printf "\n\n"