xref: /rkbin/tools/fit-unpack.sh (revision 88d46662a9b833dd2b9b75c73637916247e51450)
1#!/bin/bash
2#
3# Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
4#
5# SPDX-License-Identifier: GPL-2.0
6#
7set -e
8
9function usage()
10{
11	echo
12	echo "usage:"
13	echo "    $0 -f [fit/itb] -o [out]"
14	echo
15}
16
17function args_process()
18{
19	if [ $# -ne 4 -a $# -ne 2 ]; then
20		usage
21		exit 1
22	fi
23
24	while [ $# -gt 0 ]; do
25		case $1 in
26			-f)
27				ITB=$2
28				shift 2
29				;;
30			-o)
31				OUT=$2
32				shift 2
33				;;
34			*)
35				usage
36				exit 1
37				;;
38		esac
39	done
40
41	if [ ! -f ${ITB} ]; then
42		echo "ERROR: No ${ITB}"
43		exit 1
44	elif ! file ${ITB} | grep 'Device Tree Blob' ; then
45		echo "ERROR: ${ITB} is not FIT image"
46		exit 1
47	fi
48
49	if [ -z ${OUT} ]; then
50		OUT="out"
51	fi
52}
53
54unpack_itb()
55{
56	mkdir -p ${OUT}
57	echo "Unpack to directory ${OUT}:"
58
59	for NAME in `fdtget -l ${ITB} /images`
60	do
61		# generate ITB
62		NODE="/images/${NAME}"
63		OFFS=`fdtget -ti ${ITB} ${NODE} data-position`
64		SIZE=`fdtget -ti ${ITB} ${NODE} data-size`
65		if [ -z ${OFFS} ]; then
66			continue;
67		fi
68
69		if [ ${SIZE} -ne 0 ]; then
70			dd if=${ITB} of=${OUT}/${NAME} bs=${SIZE} count=1 skip=${OFFS} iflag=skip_bytes >/dev/null 2>&1
71		else
72			touch ${OUT}/${NAME}
73		fi
74
75		# hash verify
76		ALGO=`fdtget -ts ${ITB} ${NODE}/hash algo`
77		if [ -z ${ALGO} ]; then
78			printf "    %-20s: %d bytes" ${NAME} ${SIZE}
79		else
80			VALUE=`fdtget -tx ${ITB} ${NODE}/hash value`
81			VALUE=`echo " "${VALUE} | sed "s/ / 0x/g"`
82			CSUM=`"${ALGO}"sum ${OUT}/${NAME} | awk '{ print $1}'`
83
84			HASH=""
85			for((i=1;;i++));
86			do
87				HEX=`echo ${VALUE} | awk -v idx=$i '{ print $idx }'`
88				if [ -z ${HEX} ]; then
89					break;
90				fi
91
92				HEX=`printf "%08x" ${HEX}`
93				HASH="${HASH}${HEX}"
94			done
95
96			printf "  %-20s: %d bytes... %s" ${NAME} ${SIZE} ${ALGO}
97			if [ "${CSUM}" == "${HASH}" -o ${SIZE} -eq 0 ]; then
98				echo "+"
99			else
100				echo "-"
101			fi
102		fi
103	done
104	echo
105}
106
107function gen_its()
108{
109	ITS=${OUT}/image.its
110	TMP_ITB=${OUT}/image.tmp
111
112	# add placeholder
113	cp -a ${ITB} ${TMP_ITB}
114
115	# data and digest value
116	for NAME in `fdtget -l ${ITB} /images`; do
117		COMPRESSION=`fdtget -ts ${ITB} /images/${NAME} compression`
118		if [ "${COMPRESSION}" == "gzip" ] && fdtget -l "${TMP_ITB}" /images/${NAME}/digest >/dev/null 2>&1; then
119			fdtput -t s ${TMP_ITB} /images/${NAME} data "/INCBIN/(${NAME}.gz)"
120
121			mv ${OUT}/${NAME} ${OUT}/${NAME}.gz
122			gzip -dk ${OUT}/${NAME}.gz
123			openssl dgst -sha256 -binary -out ${OUT}/${NAME}.digest ${OUT}/${NAME}
124			fdtput -t s ${TMP_ITB} /images/${NAME}/digest digest "/INCBIN/(${NAME}.digest)"
125		elif [ "${COMPRESSION}" == "lzma" ] && fdtget -l "${TMP_ITB}" /images/${NAME}/digest >/dev/null 2>&1; then
126			fdtput -t s ${TMP_ITB} /images/${NAME} data "/INCBIN/(${NAME}.lzma)"
127
128			SIZE=`ls -l ${OUT}/${NAME} | awk '{ print $5 }'`
129			SIZE=$(echo "obase=10;$(($SIZE-4))"|bc)
130			cp ${OUT}/${NAME} ${OUT}/${NAME}.lzma.bak
131			dd if=${OUT}/${NAME} of=${OUT}/${NAME}.lzma bs=${SIZE} count=1 >/dev/null 2>&1
132			lzma -df ${OUT}/${NAME}.lzma
133			openssl dgst -sha256 -binary -out ${OUT}/${NAME}.digest ${OUT}/${NAME}
134			mv ${OUT}/${NAME}.lzma.bak ${OUT}/${NAME}.lzma
135			fdtput -t s ${TMP_ITB} /images/${NAME}/digest digest "/INCBIN/(${NAME}.digest)"
136		else
137			fdtput -t s ${TMP_ITB} /images/${NAME} data "/INCBIN/(${NAME})"
138		fi
139	done
140
141	dtc -I dtb -O dts ${TMP_ITB} -o ${ITS}
142	rm -f ${TMP_ITB}
143
144	# fixup placeholder: data = "/INCBIN/(...)"; -> data = /incbin/("...");
145	sed -i "s/\"\/INCBIN\/(\(.*\))\"/\/incbin\/(\"\1\")/" ${ITS}
146
147	# remove
148	sed -i "/memreserve/d"		${ITS}
149	sed -i "/timestamp/d"		${ITS}
150	sed -i "/data-size/d"		${ITS}
151	sed -i "/data-position/d"	${ITS}
152	sed -i "/value/d"		${ITS}
153	sed -i "/hashed-strings/d"	${ITS}
154	sed -i "/hashed-nodes/d"	${ITS}
155	sed -i "/signer-version/d"	${ITS}
156	sed -i "/signer-name/d"		${ITS}
157	sed -i "/version/d"		${ITS}
158	sed -i "/totalsize/d"		${ITS}
159	sed -i "s/digest =/value =/g"	${ITS}
160}
161
162args_process $*
163unpack_itb
164gen_its
165
166