You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
293 lines
6.2 KiB
293 lines
6.2 KiB
#!/bin/bash
|
|
#
|
|
# Copyright (c) 2021 Rockchip Electronics Co., Ltd
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
#
|
|
# The script to generate splited image and update.hdr for TFTP image upgrade.
|
|
# 1. U-Boot have limited tftp download buffer, we have to split images into pieces for download
|
|
# 2. Use FIT mechanism to record image pieces information in update.hdr: order, hash, signature, etc.
|
|
# 3. The TFTP client download update.hdr and verify it (if need)
|
|
# 4. The TFTP client download => verify => flash image pieces accorrding to update.hdr.
|
|
#
|
|
|
|
set -e
|
|
|
|
HDR_SIZE=0x10000 # 64KB
|
|
ARG_VERSION=0
|
|
ARG_ROLLBACK_IDX=0
|
|
ARG_FORCE_UPDATE=0
|
|
SUFFIX=".part.img"
|
|
GPT="gpt_env.txt"
|
|
|
|
function help()
|
|
{
|
|
echo
|
|
echo "Usage:"
|
|
echo " $0 --image <dir> --size-MB <size> [optional args]"
|
|
echo
|
|
echo " Mandory args:"
|
|
echo " --image <dir>: directory of image to upgrade"
|
|
echo " --size-MB <size>: MB size unit for image to split into pieces. In Decimal integer: 1, 2, 3 ..."
|
|
echo
|
|
echo " Optional args:"
|
|
echo " --sign: sign firmware with RSA key-pair in \"./keys\" directory"
|
|
echo " --rollback-index <index>: rollback index in Decimal integer. It depends on \"--sign\""
|
|
echo " --force-update: enable force upgrade"
|
|
echo " --config <file>: config file"
|
|
echo " --version <ver>: firmware version in Decimal integer"
|
|
echo " --clean: clean generated files"
|
|
echo
|
|
}
|
|
|
|
function check_decimal()
|
|
{
|
|
if [ -z $1 ]; then
|
|
help
|
|
exit 1
|
|
fi
|
|
|
|
DECIMAL=`echo $1 |sed 's/[0-9]//g'`
|
|
if [ ! -z ${DECIMAL} ]; then
|
|
echo "ERROR: $1 is not decimal integer"
|
|
help
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
function process_args()
|
|
{
|
|
while [ $# -gt 0 ]; do
|
|
case $1 in
|
|
--help|-help|help|--h|-h)
|
|
help
|
|
exit
|
|
;;
|
|
--force-update)
|
|
ARG_FORCE_UPDATE="1"
|
|
shift 1
|
|
;;
|
|
--image)
|
|
ARG_IMAGE_DIR=$2
|
|
OUTPUT_DIR=${ARG_IMAGE_DIR}/output
|
|
shift 2
|
|
;;
|
|
--config)
|
|
ARG_CONFIG_FILE=$2
|
|
if [ ! -f ${ARG_CONFIG_FILE} ]; then
|
|
echo "ERROR: No ${ARG_CONFIG_FILE}"
|
|
exit 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
--rollback-index)
|
|
ARG_ROLLBACK_IDX=$2
|
|
check_decimal $2
|
|
shift 2
|
|
;;
|
|
--sign)
|
|
ARG_SIGN="y"
|
|
shift 1
|
|
;;
|
|
--size-MB)
|
|
ARG_IMG_MB=$2
|
|
check_decimal $2
|
|
shift 2
|
|
;;
|
|
--version)
|
|
ARG_VERSION=$2
|
|
check_decimal $2
|
|
shift 2
|
|
;;
|
|
--clean)
|
|
rm -f *${SUFFIX} *.itb *.its *.dtb *.dts data2sign* *.hdr *.hash orderlist.txt
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Invalid arg: $1"
|
|
help
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ -z ${ARG_IMG_MB} ]; then
|
|
help
|
|
exit 1
|
|
elif [ -z ${ARG_IMAGE_DIR} ]; then
|
|
help
|
|
exit 1
|
|
elif [ ! -d ${ARG_IMAGE_DIR} ]; then
|
|
echo "ERROR: No directory ${ARG_IMAGE_DIR}"
|
|
exit 1
|
|
fi
|
|
|
|
if [ "${ARG_SIGN}" == "y" ]; then
|
|
if [ ! -f keys/dev.key ]; then
|
|
echo "ERROR: No keys/dev.key"
|
|
exit 1
|
|
elif [ ! -f keys/dev.crt ]; then
|
|
echo "ERROR: No keys/dev.crt"
|
|
exit 1
|
|
fi
|
|
else
|
|
ARG_ROLLBACK_IDX=0
|
|
fi
|
|
}
|
|
|
|
function split_image()
|
|
{
|
|
rm -rf ${OUTPUT_DIR}
|
|
|
|
if [ "${ARG_CONFIG_FILE}" ]; then
|
|
cp ${ARG_CONFIG_FILE} orderlist.txt
|
|
else
|
|
ls ${ARG_IMAGE_DIR} > orderlist.txt
|
|
fi
|
|
|
|
SEQ=0
|
|
cat orderlist.txt | while read IMAGE
|
|
do
|
|
if [ "${IMAGE}" == "${GPT}" ]; then
|
|
continue;
|
|
fi
|
|
|
|
NAME=`echo ${IMAGE} | awk -F "." '{ print $1 }'`
|
|
echo "=> split: ${IMAGE}"
|
|
if [ ! -f ${ARG_IMAGE_DIR}/${IMAGE} ]; then
|
|
echo "ERROR: No ${ARG_IMAGE_DIR}/${IMAGE}"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ${SEQ} -lt 10 ]; then
|
|
SEQ_NAME="seq0${SEQ}-${NAME}"
|
|
else
|
|
SEQ_NAME="seq${SEQ}-${NAME}"
|
|
fi
|
|
|
|
split -b ${ARG_IMG_MB}M ${ARG_IMAGE_DIR}/${IMAGE} ${SEQ_NAME}- -d --additional-suffix=${SUFFIX}
|
|
SEQ=`expr ${SEQ} + 1`
|
|
ls ${SEQ_NAME}-*
|
|
done
|
|
echo
|
|
}
|
|
|
|
function gen_its()
|
|
{
|
|
cat > update.its << EOF
|
|
/*
|
|
* Copyright (C) 2021 Rockchip Electronic Co.,Ltd
|
|
*
|
|
*/
|
|
|
|
/dts-v1/;
|
|
|
|
/ {
|
|
description = "FIT Image with ATF/OP-TEE/U-Boot";
|
|
#address-cells = <1>;
|
|
|
|
images {
|
|
EOF
|
|
if [ -f ${ARG_IMAGE_DIR}/${GPT} ]; then
|
|
cp ${ARG_IMAGE_DIR}/${GPT} ./
|
|
echo " ${GPT} {
|
|
data = /incbin/(\"./${GPT}\");
|
|
hash {
|
|
algo = \"sha256\";
|
|
};
|
|
};" >> update.its
|
|
fi
|
|
|
|
NUM=0
|
|
MAX=`ls -l *part* | wc -l`
|
|
for IMG in `ls -l *part* | awk '{ print $9 }'`
|
|
do
|
|
NAME=`echo ${IMG} | awk -F "." '{ print $1 }'`
|
|
echo " ${NAME} {
|
|
data = /incbin/(\"./${NAME}${SUFFIX}\");
|
|
hash {
|
|
algo = \"sha256\";
|
|
};
|
|
};" >> update.its
|
|
|
|
NUM=`expr ${NUM} + 1`
|
|
if [ ${NUM} -lt ${MAX} ]; then
|
|
FIRMWARES=${FIRMWARES}"\"${NAME}\", "
|
|
else
|
|
FIRMWARES=${FIRMWARES}"\"${NAME}\""
|
|
LAST_IMG=${NAME}
|
|
fi
|
|
done
|
|
cat >> update.its << EOF
|
|
};
|
|
|
|
configurations {
|
|
default = "conf";
|
|
conf {
|
|
rollback-index = <${ARG_ROLLBACK_IDX}>;
|
|
force-update = <${ARG_FORCE_UPDATE}>;
|
|
image-size-MB = <${ARG_IMG_MB}>;
|
|
firmware = ${FIRMWARES};
|
|
signature {
|
|
algo = "sha256,rsa2048";
|
|
padding = "pss";
|
|
key-name-hint = "dev";
|
|
sign-images = "firmware";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
EOF
|
|
}
|
|
|
|
function gen_update_hdr()
|
|
{
|
|
# generate itb
|
|
if [ "${ARG_SIGN}" == "y" ]; then
|
|
# create a temporary dtb to store public-key, just for mkimage work normal.
|
|
SIGNED="signed"
|
|
cp update.its key.its
|
|
sed -i "/data =/d" key.its
|
|
dtc -I dts -O dtb key.its -o key.dtb
|
|
|
|
./mkimage -f update.its -k keys/ -K key.dtb -E -p ${HDR_SIZE} -r update.itb -v ${ARG_VERSION}
|
|
./fit_check_sign -f update.itb -k key.dtb
|
|
else
|
|
SIGNED="no-signed"
|
|
./mkimage -f update.its -E -p ${HDR_SIZE} update.itb -v ${ARG_VERSION}
|
|
fi
|
|
|
|
fdtdump update.itb > update.hdr.dts
|
|
|
|
# validate update.hdr
|
|
if [ "${ARG_SIGN}" == "y" ]; then
|
|
NUM=`grep "${LAST_IMG}" update.hdr.dts | wc -l`
|
|
if [ ${NUM} -lt 3 ]; then
|
|
echo "ERROR: mkimage can't makeup full \"hashed-nodes\" property list"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Remove binary from update.itb
|
|
BYTE=`sed -n "/totalsize:/p" update.hdr.dts | awk '{ print $4 }' | tr -d '(' | tr -d ')'`
|
|
dd if=update.itb of=update.hdr bs=${BYTE} count=1
|
|
|
|
# Append checksum
|
|
openssl dgst -sha256 -binary -out update.hash update.hdr
|
|
cat update.hash >> update.hdr
|
|
|
|
rm -f *.itb *.its *.dtb *.dts data2sign* *.hash orderlist.txt
|
|
mkdir -p ${OUTPUT_DIR}
|
|
ls ${GPT} >/dev/null 2>&1 && mv ${GPT} ${OUTPUT_DIR}
|
|
mv -f *${SUFFIX} update.hdr ${OUTPUT_DIR}
|
|
|
|
echo
|
|
echo "Success: [${SIGNED}] TFTP upgrade images(unit: ${ARG_IMG_MB}MB) are ready in directory: ${OUTPUT_DIR}."
|
|
echo
|
|
}
|
|
|
|
###############################################################
|
|
process_args $*
|
|
split_image
|
|
gen_its
|
|
gen_update_hdr
|