#!/bin/bash

#  helper script: create ROM images for a given system, with SeaBIOS
#
#	Copyright (C) 2020 Leah Rowe <info@minifree.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/>.
#

# This script assumes that the working directory is the root
# of git or release archive


# TODO: add make -jWHATEVER to "make" command for coreboot
# TODO: check if coreboot supports multi-core building in its build system
[ "x${DEBUG+set}" = 'xset' ] && set -v
set -u -e
if [ -z ${NPROC+x} ]; then
    cores="$(nproc)"
else
    case ${NPROC} in
        ''|*[!0-9]*)
            printf "value '%s' for NPROC is invalid. non-numeric. Exiting.\n" "${NPROC}"
            exit 1
            ;;
    esac
    cores="${NPROC}"
fi

if (( $# != 1 )); then
	printf "Usage: ./build roms withseabios boardname\n"
	printf "Example: ./build roms withseabios x230\n"
	printf "You need to specify exactly 1 argument\n"
	exit 1
fi

board="${1}"
romdir_seabios="bin/seabios_${board}"
cbdir="coreboot/${board}"
cbfstool="${cbdir}/util/cbfstool/cbfstool"
corebootrom="${cbdir}/build/coreboot.rom"
seavgabiosrom="payload/seabios/seavgabios.bin"
optionromdir="resources/coreboot/${board}/optionroms"

# Symlinks go in this directory. They symlink to option roms
# that are to be ignored if libgfxinit used. So for instance if
# using libgfxinit on an X230, don't add PCI option ROM for the Intel GPU
opromignoredir="resources/coreboot/${board}/opromignore"

if [ ! -d "resources/coreboot/${board}" ]; then
    printf "Target %s does not exist in the retroboot build system.\n" "${board}"
    exit 1
fi

if [ ! -d "resources/coreboot/${board}/config/seabios" ]; then
    printf "SeaBIOS payload not supported on target: %s - skipping\n" "${board}"
    exit 0
fi

[ -d "bin/seabios_${board}/" ] || mkdir -p "bin/seabios_${board}/"
rm -f "bin/seabios_${board}"/*

if [ -d "${optionromdir}" ]; then
    cp "${optionromdir}"/pci*.rom "${cbdir}/"
fi

for displaymode in vesafb txtmode; do
    for initmode in libgfxinit vgarom; do

        cbcfgpath="resources/coreboot/${board}/config/seabios/${initmode}_${displaymode}"
        seabioself="payload/seabios/seabios_${initmode}.elf"

        # TODO: make these error out with specific message advising if
        # a single thing is missing. e.g. error says: "Please compile cbfstool"
        if [ ! -f "${cbcfgpath}" ] || [ ! -f "${cbfstool}" ] || \
                [ ! -f "${seabioself}" ] || [ ! -f "${seavgabiosrom}" ]; then
            continue
        fi
        if [ ! -d "${cbdir}" ]; then
            continue
        fi

        (
            cd "${cbdir}"
            make distclean
        )
        cp "${cbcfgpath}" "${cbdir}"/.config
        
        (
            cd "${cbdir}"
            make
        )

        # copy the bootblock, for purpose of internal flashing from lenovobios.
        # when doing that, upper bootblock isn't flashed so you set bucts to
        # use the alt (lower) bootblock. These dd commands make that safe
        if [ "${board}" = "t60_ati_x1400" ]; then
			dd if="${corebootrom}" of=top64k.bin bs=1 skip=$[$(stat -c %s "${corebootrom}") - 0x10000] count=64k
			dd if=top64k.bin of="${corebootrom}" bs=1 seek=$[$(stat -c %s "${corebootrom}") - 0x20000] count=64k conv=notrunc
			rm -f top64k.bin
        fi

        if [ "${initmode}" = "libgfxinit" ]; then
            "${cbfstool}" "${corebootrom}" add -f ${seavgabiosrom} -n vgaroms/seavgabios.bin -t raw            
        fi

        "${cbfstool}" "${corebootrom}" add-int -i 3000 -n etc/ps2-keyboard-spinup

        "${cbfstool}" "${corebootrom}" add-payload -f "${seabioself}" -n fallback/payload -c lzma

        if [ "${displaymode}" = "txtmode" ]; then
            "${cbfstool}" "${corebootrom}" add-payload -f memtest86plus/memtest.bin -n img/memtest.bin -c lzma
        fi

        newrompath="${romdir_seabios}/seabios_${board}_${initmode}_${displaymode}.rom"
        if [ "${board}" = "x230" ] || [ "${board}" = "x230t" ]; then
            printf "\nExtracting 4MiB BIOS region for %s\n" "${newrompath}"
            dd if=${corebootrom} of=${newrompath} bs=1 skip=$[$(stat -c %s ${corebootrom}) - 0x400000] count=4194304
        else
            mv ${corebootrom} ${newrompath}
        fi

    done
done

rm -f "${cbdir}"/pci*.rom

printf "\nDone! Your ROMs are in bin/seabios_%s/\n\n" "${board}"

