#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0
#
# Generate assembly source to embed firmware binary
#
# Usage: gen-fw-s <fwname> <fwdir> <secprefix> [secflags] [fwobjdir]

fwname=$1
fwdir=$2
secprefix=$3
secflags=$4
fwobjdir=$5

fwstr=$(echo "$fwname" | tr '/.-' '___')
fwpath="$fwdir/$fwname"

fw_uncompressed=0
if [ -f "$fwpath" ]; then
	fw_uncompressed=$(stat -c %s "$fwpath")
fi

sha=$(sha256sum "$fwpath" 2>/dev/null | sed 's/ .*$//;s/../0x&, /g;s/, $//')

echo "/* Generated by scripts/gen-fw-s */"
echo "#include <asm-generic/pointer.h>"
echo ".section .note.GNU-stack,\"\",%progbits"

# include firmware if exists, otherwise include a reference to
# the firmware filename in the .missing_fw section
echo "    .section ${secprefix}.${fwstr},\"${secflags}\""
echo "    .p2align ASM_LGPTR"
echo ".global _fw_${fwstr}_start"
echo "_fw_${fwstr}_start:"
if [ -f "$fwpath" ]; then
	echo ".incbin \"${fwpath}\""
else
	echo "#if defined(__PBL__)"
	echo "ASM_PTR _fwname_${fwstr}"
	echo "#endif"
fi
echo ".global _fw_${fwstr}_end"
echo "_fw_${fwstr}_end:"

# include compressed firmware if exists, otherwise include a reference to
# the firmware filename in the .missing_fw section
echo "#if defined(__PBL__)"
echo "    .section .fwz.rodata.${fwstr},\"a\""
echo "    .p2align ASM_LGPTR"
echo ".global _fw_z_${fwstr}_uncompressed_size"
echo ".set _fw_z_${fwstr}_uncompressed_size, ${fw_uncompressed}"
echo ".global _fw_z_${fwstr}_start"
echo "_fw_z_${fwstr}_start:"
if [ -f "$fwpath" ]; then
	echo ".incbin \"${fwobjdir}/${fwname}.z\""
else
	echo "ASM_PTR _fwname_${fwstr}"
fi
echo ".global _fw_z_${fwstr}_end"
echo "_fw_z_${fwstr}_end:"
echo "#endif"

# include sha256, needed for external firmware
echo "    .section .rodata.${fwstr}.sha"
echo "    .p2align ASM_LGPTR"
echo ".global _fw_${fwstr}_sha_start"
echo "_fw_${fwstr}_sha_start:"
echo "    .byte ${sha}"
echo ".global _fw_${fwstr}_sha_end"
echo "_fw_${fwstr}_sha_end:"
if [ -f "$fwpath" ]; then
	echo ".if _fw_${fwstr}_sha_start + 32 - _fw_${fwstr}_sha_end"
	echo ".error \"sha256sum invalid\""
	echo ".endif"
fi

# include a string containing the firmware name. When a non existing
# firmware is referenced in the PBL then _fwname_${fwstr} is referenced
# above rather than the firmware itself. The barebox build system checks
# if the missing_fw section is empty. If it is, then we have all necessary
# firmware files. If not, then we either fail the compilation
# (CONFIG_MISSING_FIRMWARE_ERROR=y) or print a missing firmware warning
# (CONFIG_MISSING_FIRMWARE_ERROR=n).
echo "#ifdef __PBL__"
echo "    .section .missing_fw,\"a\""
echo "_fwname_${fwstr}:"
printf '.ascii "%s"\n' "firmware/${fwname}\\n"
echo "#endif"
