#! /bin/bash

. /etc/uboot.cfg

UBOOTENV=$(mktemp)

# default values
UBOOT_ROOT_PART=${UBOOT_ROOT_PART-/dev/mmcblk0p2}
UBOOT_KERNEL_ARGS=${UBOOT_KERNEL_ARGS-rootfstype=btrfs quiet splash logo.nologo}
UBOOT_MENU_TIMEOUT=${UBOOT_MENU_TIMEOUT-2}
UBOOT_DEFAULT=${UBOOT_DEFAULT-boot0}
UBOOT_PREPEND_FW_KERNEL_ARGS=${UBOOT_PREPEND_FW_KERNEL_ARGS-1}

# check if mkimage tool is installed
which mkimage >/dev/null || { echo "missing mkimage"; exit 1; }

# load custom configuration
UBOOT_USER_CFG=${UBOOT_USER_CFG-/etc/uboot.user.cfg}
if [ "${UBOOT_USER_CFG}" != "" ]; then
	[[ -x "${UBOOT_USER_CFG}" ]] && source "${UBOOT_USER_CFG}"
fi

echo -n "" > "${UBOOTENV}"


# override boot procedure by GPIO state?
if [ "${UBOOT_FAILSAFE_GPIO_PIN}" != "" ]; then
	# if GPIO pin is high, execute command
	echo "if gpio input ${UBOOT_FAILSAFE_GPIO_PIN}; then ; else setenv stdout serial,lcd ; echo \"failsafe pin set\"; ${UBOOT_FAILSAFE_COMMAND}; fi" >> "${UBOOTENV}"
fi

# override U-Boot output
if [ "${UBOOT_STDOUT}" != "" ]; then
	echo "setenv stdout ${UBOOT_STDOUT}" >> "${UBOOTENV}"
fi

# override device tree?
if [ "${UBOOT_DEVICE_TREE}" != "" ]; then
	echo "fatload mmc 0:1 \${fdt_addr} ${UBOOT_DEVICE_TREE}" >> "${UBOOTENV}"
fi

# check if device tree is available in memory. If yes, get bootargs set by
# firmware and store them in $fw_bootargs. If not, load bcm2709-rpi-2-b.dtb
# into memory for safety and backwards compatibility
echo "if fdt addr \${fdt_addr}; then fdt get value fw_bootargs /chosen bootargs; printenv fw_bootargs; else fatload mmc 0:1 \${fdt_addr} bcm2709-rpi-2-b.dtb; fi;"  >> "${UBOOTENV}"

# set default kernel args
if [ "${UBOOT_PREPEND_FW_KERNEL_ARGS}" == "1" ]; then
	# do not append fw_bootargs as it contains rootfstype=ext4
	echo "setenv bootargs \"\${fw_bootargs} root=${UBOOT_ROOT_PART} rw rootwait ${UBOOT_KERNEL_ARGS}\"" >> "${UBOOTENV}"
else
	echo "setenv bootargs \"root=${UBOOT_ROOT_PART} rw rootwait ${UBOOT_KERNEL_ARGS}\"" >> "${UBOOTENV}"
fi

# menu header
echo "echo ' '
echo 'Available boot options:'
echo '-----------------------'" >> "${UBOOTENV}"


# callback for each kernel
function vmlinuz_cb() {
	kernel=$1
	version=$2
	
	echo -n "Found kernel ${kernel}"
	echo "" >> "${UBOOTENV}"
	
	if [ -f /boot/initrd.img-${version} ] || [ -f /boot/initrd.uimg-${version} ]; then
		echo " with initrd"
		UBOOT_INITRD=\${ramdisk_addr_r}
		PRECMDS="${PRECMDS}fatload mmc 0:1 \${ramdisk_addr_r} initrd.uimg-${version}; "
		
		if [ ! -f /boot/initrd.uimg-${version} ]; then
			echo "Creating U-Boot image for /boot/initrd.img-${version}"
			mkimage -n "Ramdisk Image ${version}"  -A arm -O linux -T ramdisk -C gzip -d /boot/initrd.img-${version} /boot/initrd.uimg-${version} || { echo "error creating initrd.uimg"; exit 1; }
		else
			echo "Using cached U-Boot image for /boot/initrd.img-${version}"
		fi
	else
		echo ""
		UBOOT_INITRD=-
	fi
	
	if [ -f /boot/cmdline-${version} ]; then
		echo "setenv bootargs${i} 'setenv bootargs \"$(cat /boot/cmdline-${version} | tr '\n' ' ' | sed "s/[[:space:]]*$//")\"'" >> "${UBOOTENV}"
		PRECMDS="${PRECMDS}run bootargs${i}; "
	fi
	
	echo "setenv boot${i} '${PRECMDS}fatload mmc 0:1 \${kernel_addr_r} ${kernel}; bootz \${kernel_addr_r} ${UBOOT_INITRD} \${fdt_addr}'" >> "${UBOOTENV}"
	
	echo "echo '   \"run boot${i}\" will boot ${kernel}'" >> "${UBOOTENV}"
}

# register callback
UBOOT_KERNEL_FCTS="${UBOOT_KERNEL_FCTS} vmlinuz_cb"

# look for kernels and execute callbacks
i=0
for k in $(ls -vr /boot/vmlinuz*); do
	PRECMDS=""
	kernel=$(basename "${k}")
	version=$(basename "${k}" | cut -d "-" -f2-)
	
	# execute all registered callbacks for this kernel
	for cb in ${UBOOT_KERNEL_FCTS}; do
		${cb} ${kernel} ${version}
	done
	
	i=$(( $i + 1 ))
done
echo "echo ' '" >> "${UBOOTENV}"

# do we alter boot procedure if failsafe file does not exist?
if [ "${UBOOT_FAILSAFE_FILE}" != "" ]; then
	# if file exists, execute command, else create file
	echo "if test -e mmc 0:1 ${UBOOT_FAILSAFE_FILE}; then setenv stdout serial,lcd ; echo \"failsafe file ${UBOOT_FAILSAFE_FILE} present\"; ${UBOOT_FAILSAFE_COMMAND}; else fatwrite mmc 0:1 0x02050000 ${UBOOT_FAILSAFE_FILE} 1; fi" >> "${UBOOTENV}"
fi

echo "
setenv autoboot run distro_bootcmd

echo 'Will execute \"run ${UBOOT_DEFAULT}\" in ${UBOOT_MENU_TIMEOUT} seconds, abort with CTRL+c...'
sleep ${UBOOT_MENU_TIMEOUT} && run ${UBOOT_DEFAULT}
" >> "${UBOOTENV}"

# create an image from the config in a format uboot understands
echo "Building U-Boot config image ..."
mkimage -A arm -O linux -T script -C none -a 0x00000000 -e 0x00000000 -n "RPi2 Boot Script" -d "${UBOOTENV}" /boot/boot.scr || { echo "error creating uboot config image"; exit 1; }

#cat "${UBOOTENV}"
rm "${UBOOTENV}"
