1*15dc9023SJoseph Chen#!/bin/bash 2*15dc9023SJoseph Chen# 3*15dc9023SJoseph Chen# Copyright (c) 2021 Rockchip Electronics Co., Ltd 4*15dc9023SJoseph Chen# SPDX-License-Identifier: GPL-2.0 5*15dc9023SJoseph Chen# 6*15dc9023SJoseph Chen# The script to generate splited image and update.hdr for TFTP image upgrade. 7*15dc9023SJoseph Chen# 1. U-Boot have limited tftp download buffer, we have to split images into pieces for download 8*15dc9023SJoseph Chen# 2. Use FIT mechanism to record image pieces information in update.hdr: order, hash, signature, etc. 9*15dc9023SJoseph Chen# 3. The TFTP client download update.hdr and verify it (if need) 10*15dc9023SJoseph Chen# 4. The TFTP client download => verify => flash image pieces accorrding to update.hdr. 11*15dc9023SJoseph Chen# 12*15dc9023SJoseph Chen 13*15dc9023SJoseph Chenset -e 14*15dc9023SJoseph Chen 15*15dc9023SJoseph ChenHDR_SIZE=0x10000 # 64KB 16*15dc9023SJoseph ChenARG_VERSION=0 17*15dc9023SJoseph ChenARG_ROLLBACK_IDX=0 18*15dc9023SJoseph ChenARG_FORCE_UPDATE=0 19*15dc9023SJoseph ChenSUFFIX=".part.img" 20*15dc9023SJoseph ChenGPT="gpt_env.txt" 21*15dc9023SJoseph Chen 22*15dc9023SJoseph Chenfunction help() 23*15dc9023SJoseph Chen{ 24*15dc9023SJoseph Chen echo 25*15dc9023SJoseph Chen echo "Usage:" 26*15dc9023SJoseph Chen echo " $0 --image <dir> --size-MB <size> [optional args]" 27*15dc9023SJoseph Chen echo 28*15dc9023SJoseph Chen echo " Mandory args:" 29*15dc9023SJoseph Chen echo " --image <dir>: directory of image to upgrade" 30*15dc9023SJoseph Chen echo " --size-MB <size>: MB size unit for image to split into pieces. In Decimal integer: 1, 2, 3 ..." 31*15dc9023SJoseph Chen echo 32*15dc9023SJoseph Chen echo " Optional args:" 33*15dc9023SJoseph Chen echo " --sign: sign firmware with RSA key-pair in \"./keys\" directory" 34*15dc9023SJoseph Chen echo " --rollback-index <index>: rollback index in Decimal integer. It depends on \"--sign\"" 35*15dc9023SJoseph Chen echo " --force-update: enable force upgrade" 36*15dc9023SJoseph Chen echo " --config <file>: config file" 37*15dc9023SJoseph Chen echo " --version <ver>: firmware version in Decimal integer" 38*15dc9023SJoseph Chen echo " --clean: clean generated files" 39*15dc9023SJoseph Chen echo 40*15dc9023SJoseph Chen} 41*15dc9023SJoseph Chen 42*15dc9023SJoseph Chenfunction check_decimal() 43*15dc9023SJoseph Chen{ 44*15dc9023SJoseph Chen if [ -z $1 ]; then 45*15dc9023SJoseph Chen help 46*15dc9023SJoseph Chen exit 1 47*15dc9023SJoseph Chen fi 48*15dc9023SJoseph Chen 49*15dc9023SJoseph Chen DECIMAL=`echo $1 |sed 's/[0-9]//g'` 50*15dc9023SJoseph Chen if [ ! -z ${DECIMAL} ]; then 51*15dc9023SJoseph Chen echo "ERROR: $1 is not decimal integer" 52*15dc9023SJoseph Chen help 53*15dc9023SJoseph Chen exit 1 54*15dc9023SJoseph Chen fi 55*15dc9023SJoseph Chen} 56*15dc9023SJoseph Chen 57*15dc9023SJoseph Chenfunction process_args() 58*15dc9023SJoseph Chen{ 59*15dc9023SJoseph Chen while [ $# -gt 0 ]; do 60*15dc9023SJoseph Chen case $1 in 61*15dc9023SJoseph Chen --help|-help|help|--h|-h) 62*15dc9023SJoseph Chen help 63*15dc9023SJoseph Chen exit 64*15dc9023SJoseph Chen ;; 65*15dc9023SJoseph Chen --force-update) 66*15dc9023SJoseph Chen ARG_FORCE_UPDATE="1" 67*15dc9023SJoseph Chen shift 1 68*15dc9023SJoseph Chen ;; 69*15dc9023SJoseph Chen --image) 70*15dc9023SJoseph Chen ARG_IMAGE_DIR=$2 71*15dc9023SJoseph Chen OUTPUT_DIR=${ARG_IMAGE_DIR}/output 72*15dc9023SJoseph Chen shift 2 73*15dc9023SJoseph Chen ;; 74*15dc9023SJoseph Chen --config) 75*15dc9023SJoseph Chen ARG_CONFIG_FILE=$2 76*15dc9023SJoseph Chen if [ ! -f ${ARG_CONFIG_FILE} ]; then 77*15dc9023SJoseph Chen echo "ERROR: No ${ARG_CONFIG_FILE}" 78*15dc9023SJoseph Chen exit 1 79*15dc9023SJoseph Chen fi 80*15dc9023SJoseph Chen shift 2 81*15dc9023SJoseph Chen ;; 82*15dc9023SJoseph Chen --rollback-index) 83*15dc9023SJoseph Chen ARG_ROLLBACK_IDX=$2 84*15dc9023SJoseph Chen check_decimal $2 85*15dc9023SJoseph Chen shift 2 86*15dc9023SJoseph Chen ;; 87*15dc9023SJoseph Chen --sign) 88*15dc9023SJoseph Chen ARG_SIGN="y" 89*15dc9023SJoseph Chen shift 1 90*15dc9023SJoseph Chen ;; 91*15dc9023SJoseph Chen --size-MB) 92*15dc9023SJoseph Chen ARG_IMG_MB=$2 93*15dc9023SJoseph Chen check_decimal $2 94*15dc9023SJoseph Chen shift 2 95*15dc9023SJoseph Chen ;; 96*15dc9023SJoseph Chen --version) 97*15dc9023SJoseph Chen ARG_VERSION=$2 98*15dc9023SJoseph Chen check_decimal $2 99*15dc9023SJoseph Chen shift 2 100*15dc9023SJoseph Chen ;; 101*15dc9023SJoseph Chen --clean) 102*15dc9023SJoseph Chen rm -f *${SUFFIX} *.itb *.its *.dtb *.dts data2sign* *.hdr *.hash orderlist.txt 103*15dc9023SJoseph Chen exit 0 104*15dc9023SJoseph Chen ;; 105*15dc9023SJoseph Chen *) 106*15dc9023SJoseph Chen echo "Invalid arg: $1" 107*15dc9023SJoseph Chen help 108*15dc9023SJoseph Chen exit 1 109*15dc9023SJoseph Chen ;; 110*15dc9023SJoseph Chen esac 111*15dc9023SJoseph Chen done 112*15dc9023SJoseph Chen 113*15dc9023SJoseph Chen if [ -z ${ARG_IMG_MB} ]; then 114*15dc9023SJoseph Chen help 115*15dc9023SJoseph Chen exit 1 116*15dc9023SJoseph Chen elif [ -z ${ARG_IMAGE_DIR} ]; then 117*15dc9023SJoseph Chen help 118*15dc9023SJoseph Chen exit 1 119*15dc9023SJoseph Chen elif [ ! -d ${ARG_IMAGE_DIR} ]; then 120*15dc9023SJoseph Chen echo "ERROR: No directory ${ARG_IMAGE_DIR}" 121*15dc9023SJoseph Chen exit 1 122*15dc9023SJoseph Chen fi 123*15dc9023SJoseph Chen 124*15dc9023SJoseph Chen if [ "${ARG_SIGN}" == "y" ]; then 125*15dc9023SJoseph Chen if [ ! -f keys/dev.key ]; then 126*15dc9023SJoseph Chen echo "ERROR: No keys/dev.key" 127*15dc9023SJoseph Chen exit 1 128*15dc9023SJoseph Chen elif [ ! -f keys/dev.crt ]; then 129*15dc9023SJoseph Chen echo "ERROR: No keys/dev.crt" 130*15dc9023SJoseph Chen exit 1 131*15dc9023SJoseph Chen fi 132*15dc9023SJoseph Chen else 133*15dc9023SJoseph Chen ARG_ROLLBACK_IDX=0 134*15dc9023SJoseph Chen fi 135*15dc9023SJoseph Chen} 136*15dc9023SJoseph Chen 137*15dc9023SJoseph Chenfunction split_image() 138*15dc9023SJoseph Chen{ 139*15dc9023SJoseph Chen rm -rf ${OUTPUT_DIR} 140*15dc9023SJoseph Chen 141*15dc9023SJoseph Chen if [ "${ARG_CONFIG_FILE}" ]; then 142*15dc9023SJoseph Chen cp ${ARG_CONFIG_FILE} orderlist.txt 143*15dc9023SJoseph Chen else 144*15dc9023SJoseph Chen ls ${ARG_IMAGE_DIR} > orderlist.txt 145*15dc9023SJoseph Chen fi 146*15dc9023SJoseph Chen 147*15dc9023SJoseph Chen SEQ=0 148*15dc9023SJoseph Chen cat orderlist.txt | while read IMAGE 149*15dc9023SJoseph Chen do 150*15dc9023SJoseph Chen if [ "${IMAGE}" == "${GPT}" ]; then 151*15dc9023SJoseph Chen continue; 152*15dc9023SJoseph Chen fi 153*15dc9023SJoseph Chen 154*15dc9023SJoseph Chen NAME=`echo ${IMAGE} | awk -F "." '{ print $1 }'` 155*15dc9023SJoseph Chen echo "=> split: ${IMAGE}" 156*15dc9023SJoseph Chen if [ ! -f ${ARG_IMAGE_DIR}/${IMAGE} ]; then 157*15dc9023SJoseph Chen echo "ERROR: No ${ARG_IMAGE_DIR}/${IMAGE}" 158*15dc9023SJoseph Chen exit 1 159*15dc9023SJoseph Chen fi 160*15dc9023SJoseph Chen 161*15dc9023SJoseph Chen if [ ${SEQ} -lt 10 ]; then 162*15dc9023SJoseph Chen SEQ_NAME="seq0${SEQ}-${NAME}" 163*15dc9023SJoseph Chen else 164*15dc9023SJoseph Chen SEQ_NAME="seq${SEQ}-${NAME}" 165*15dc9023SJoseph Chen fi 166*15dc9023SJoseph Chen 167*15dc9023SJoseph Chen split -b ${ARG_IMG_MB}M ${ARG_IMAGE_DIR}/${IMAGE} ${SEQ_NAME}- -d --additional-suffix=${SUFFIX} 168*15dc9023SJoseph Chen SEQ=`expr ${SEQ} + 1` 169*15dc9023SJoseph Chen ls ${SEQ_NAME}-* 170*15dc9023SJoseph Chen done 171*15dc9023SJoseph Chen echo 172*15dc9023SJoseph Chen} 173*15dc9023SJoseph Chen 174*15dc9023SJoseph Chenfunction gen_its() 175*15dc9023SJoseph Chen{ 176*15dc9023SJoseph Chencat > update.its << EOF 177*15dc9023SJoseph Chen/* 178*15dc9023SJoseph Chen * Copyright (C) 2021 Rockchip Electronic Co.,Ltd 179*15dc9023SJoseph Chen * 180*15dc9023SJoseph Chen */ 181*15dc9023SJoseph Chen 182*15dc9023SJoseph Chen/dts-v1/; 183*15dc9023SJoseph Chen 184*15dc9023SJoseph Chen/ { 185*15dc9023SJoseph Chen description = "FIT Image with ATF/OP-TEE/U-Boot"; 186*15dc9023SJoseph Chen #address-cells = <1>; 187*15dc9023SJoseph Chen 188*15dc9023SJoseph Chen images { 189*15dc9023SJoseph ChenEOF 190*15dc9023SJoseph Chen if [ -f ${ARG_IMAGE_DIR}/${GPT} ]; then 191*15dc9023SJoseph Chen cp ${ARG_IMAGE_DIR}/${GPT} ./ 192*15dc9023SJoseph Chen echo " ${GPT} { 193*15dc9023SJoseph Chen data = /incbin/(\"./${GPT}\"); 194*15dc9023SJoseph Chen hash { 195*15dc9023SJoseph Chen algo = \"sha256\"; 196*15dc9023SJoseph Chen }; 197*15dc9023SJoseph Chen };" >> update.its 198*15dc9023SJoseph Chen fi 199*15dc9023SJoseph Chen 200*15dc9023SJoseph Chen NUM=0 201*15dc9023SJoseph Chen MAX=`ls -l *part* | wc -l` 202*15dc9023SJoseph Chen for IMG in `ls -l *part* | awk '{ print $9 }'` 203*15dc9023SJoseph Chen do 204*15dc9023SJoseph Chen NAME=`echo ${IMG} | awk -F "." '{ print $1 }'` 205*15dc9023SJoseph Chen echo " ${NAME} { 206*15dc9023SJoseph Chen data = /incbin/(\"./${NAME}${SUFFIX}\"); 207*15dc9023SJoseph Chen hash { 208*15dc9023SJoseph Chen algo = \"sha256\"; 209*15dc9023SJoseph Chen }; 210*15dc9023SJoseph Chen };" >> update.its 211*15dc9023SJoseph Chen 212*15dc9023SJoseph Chen NUM=`expr ${NUM} + 1` 213*15dc9023SJoseph Chen if [ ${NUM} -lt ${MAX} ]; then 214*15dc9023SJoseph Chen FIRMWARES=${FIRMWARES}"\"${NAME}\", " 215*15dc9023SJoseph Chen else 216*15dc9023SJoseph Chen FIRMWARES=${FIRMWARES}"\"${NAME}\"" 217*15dc9023SJoseph Chen LAST_IMG=${NAME} 218*15dc9023SJoseph Chen fi 219*15dc9023SJoseph Chen done 220*15dc9023SJoseph Chencat >> update.its << EOF 221*15dc9023SJoseph Chen }; 222*15dc9023SJoseph Chen 223*15dc9023SJoseph Chen configurations { 224*15dc9023SJoseph Chen default = "conf"; 225*15dc9023SJoseph Chen conf { 226*15dc9023SJoseph Chen rollback-index = <${ARG_ROLLBACK_IDX}>; 227*15dc9023SJoseph Chen force-update = <${ARG_FORCE_UPDATE}>; 228*15dc9023SJoseph Chen image-size-MB = <${ARG_IMG_MB}>; 229*15dc9023SJoseph Chen firmware = ${FIRMWARES}; 230*15dc9023SJoseph Chen signature { 231*15dc9023SJoseph Chen algo = "sha256,rsa2048"; 232*15dc9023SJoseph Chen padding = "pss"; 233*15dc9023SJoseph Chen key-name-hint = "dev"; 234*15dc9023SJoseph Chen sign-images = "firmware"; 235*15dc9023SJoseph Chen }; 236*15dc9023SJoseph Chen }; 237*15dc9023SJoseph Chen }; 238*15dc9023SJoseph Chen}; 239*15dc9023SJoseph ChenEOF 240*15dc9023SJoseph Chen} 241*15dc9023SJoseph Chen 242*15dc9023SJoseph Chenfunction gen_update_hdr() 243*15dc9023SJoseph Chen{ 244*15dc9023SJoseph Chen # generate itb 245*15dc9023SJoseph Chen if [ "${ARG_SIGN}" == "y" ]; then 246*15dc9023SJoseph Chen # create a temporary dtb to store public-key, just for mkimage work normal. 247*15dc9023SJoseph Chen SIGNED="signed" 248*15dc9023SJoseph Chen cp update.its key.its 249*15dc9023SJoseph Chen sed -i "/data =/d" key.its 250*15dc9023SJoseph Chen dtc -I dts -O dtb key.its -o key.dtb 251*15dc9023SJoseph Chen 252*15dc9023SJoseph Chen ./mkimage -f update.its -k keys/ -K key.dtb -E -p ${HDR_SIZE} -r update.itb -v ${ARG_VERSION} 253*15dc9023SJoseph Chen ./fit_check_sign -f update.itb -k key.dtb 254*15dc9023SJoseph Chen else 255*15dc9023SJoseph Chen SIGNED="no-signed" 256*15dc9023SJoseph Chen ./mkimage -f update.its -E -p ${HDR_SIZE} update.itb -v ${ARG_VERSION} 257*15dc9023SJoseph Chen fi 258*15dc9023SJoseph Chen 259*15dc9023SJoseph Chen fdtdump update.itb > update.hdr.dts 260*15dc9023SJoseph Chen 261*15dc9023SJoseph Chen # validate update.hdr 262*15dc9023SJoseph Chen if [ "${ARG_SIGN}" == "y" ]; then 263*15dc9023SJoseph Chen NUM=`grep "${LAST_IMG}" update.hdr.dts | wc -l` 264*15dc9023SJoseph Chen if [ ${NUM} -lt 3 ]; then 265*15dc9023SJoseph Chen echo "ERROR: mkimage can't makeup full \"hashed-nodes\" property list" 266*15dc9023SJoseph Chen exit 1 267*15dc9023SJoseph Chen fi 268*15dc9023SJoseph Chen fi 269*15dc9023SJoseph Chen 270*15dc9023SJoseph Chen # Remove binary from update.itb 271*15dc9023SJoseph Chen BYTE=`sed -n "/totalsize:/p" update.hdr.dts | awk '{ print $4 }' | tr -d '(' | tr -d ')'` 272*15dc9023SJoseph Chen dd if=update.itb of=update.hdr bs=${BYTE} count=1 273*15dc9023SJoseph Chen 274*15dc9023SJoseph Chen # Append checksum 275*15dc9023SJoseph Chen openssl dgst -sha256 -binary -out update.hash update.hdr 276*15dc9023SJoseph Chen cat update.hash >> update.hdr 277*15dc9023SJoseph Chen 278*15dc9023SJoseph Chen rm -f *.itb *.its *.dtb *.dts data2sign* *.hash orderlist.txt 279*15dc9023SJoseph Chen mkdir -p ${OUTPUT_DIR} 280*15dc9023SJoseph Chen ls ${GPT} >/dev/null 2>&1 && mv ${GPT} ${OUTPUT_DIR} 281*15dc9023SJoseph Chen mv -f *${SUFFIX} update.hdr ${OUTPUT_DIR} 282*15dc9023SJoseph Chen 283*15dc9023SJoseph Chen echo 284*15dc9023SJoseph Chen echo "Success: [${SIGNED}] TFTP upgrade images(unit: ${ARG_IMG_MB}MB) are ready in directory: ${OUTPUT_DIR}." 285*15dc9023SJoseph Chen echo 286*15dc9023SJoseph Chen} 287*15dc9023SJoseph Chen 288*15dc9023SJoseph Chen############################################################### 289*15dc9023SJoseph Chenprocess_args $* 290*15dc9023SJoseph Chensplit_image 291*15dc9023SJoseph Chengen_its 292*15dc9023SJoseph Chengen_update_hdr 293