2 # SPDX-License-Identifier: GPL-2.0-or-later
4 # Author: Jason Wu <jason.hy.wu@gmail.com>
5 # with modifications for multi-DTB-same-image by:
6 # Mathew McBride <matt@traverse.com.au>
8 # U-Boot firmware supports the booting of images in the Flattened Image
9 # Tree (FIT) format. The FIT format uses a device tree structure to
10 # describe a kernel image, device tree blob, ramdisk, etc. This script
11 # creates an Image Tree Source (.its file) which can be passed to the
12 # 'mkimage' utility to generate an Image Tree Blob (.itb file). The .itb
13 # file can then be booted by U-Boot (or other bootloaders which support
14 # FIT images). See doc/uImage.FIT/howto.txt in U-Boot source code for
15 # additional information on FIT images.
17 # This tools supports:
18 # - multi-configuration
19 # - multi-image support - multiple kernel/fdt/ramdsik
20 # - per image configuration:
21 # - hash algorithm and generated required subnodes
23 # - signature and generated required subnodes
32 # declare main data array
36 # initialize array with empty values
37 for (( index
=1; index
<=$MAX_IMG; index
++ )); do
40 eval img
${index}[$i]=""
44 for (( index
=1; index
<=$MAX_CONF; index
++ )); do
47 eval conf
${index}[$i]=""
51 # imgX array index information
52 # 0: type of image - kernel, fdt, ramdsik
55 # 3: loadaddr of image
56 # 4: entrypoint of image
59 # 7: part of the configuration
60 # 8: Human friend name for the image
63 # 11: conf friendly name
65 # confX array index information
73 # 7: kernel sign_algorithm
74 # 8: fdt sign_algorithm
75 # 9: rootfs sign_algorithm
76 # 10: conf friendly name
79 echo "Usage: `basename $0` -A arch -v version -o its_file" \
80 "-k kernel -a addr -e entry [-C none] [-h sha1] [-c conf]"
81 echo -e "Example1:\n\tkernel image ker_img1 with no compression +"
82 echo -e "\tsha1 hash + fdt dtb1 with sha1 and crc32 hash for conf 1"
83 echo -e "\t $ `basename $0` -A arm -v 4.4 \ "
84 echo -e "\t -k ker_img1 -C none -h sha1 -e 0x8000 -a 0x8000 -c 1 \ "
85 echo -e "\t -d dtb1 -h sha1 -h crc32 -c 1\n"
86 echo "General settings:"
87 echo -e "\t-A ==> set architecture to 'arch'"
88 echo -e "\t-v ==> set kernel version to 'version'"
89 echo -e "\t-o ==> create output file 'its_file' [optional]"
90 echo "Input image type:"
91 echo -e "\t-k ==> kernel image 'kernel'"
92 echo -e "\t-d ==> Device Tree Blob 'dtb'"
93 echo -e "\t-r ==> ramdisk image 'ramdisk"
94 echo "Per image configurations:"
95 echo -e "\t-C ==> set compression type 'comp'"
96 echo -e "\t-c ==> set image config (multiple -c allowed)"
97 echo -e "\t-a ==> set load address to 'addr' (hex)"
98 echo -e "\t-e ==> set entry point to 'entry' (hex)"
99 echo -e "\t-D ==> human friendly 'name' (one word only)"
100 echo -e "\t-h ==> set hash algorithm (multiple -h allowed)"
101 echo -e "\t-s ==> set signature for given config image"
102 echo -e "\t-K ==> set key file for given config image"
112 if echo $1 |
grep -q img
; then
115 let a
=$
(echo $1 |
awk -F "img" '{print $2}')
116 elif echo $1 |
grep -q conf
; then
119 let a
=$
(echo $1 |
awk -F "conf" '{print $2}')
121 if [ ${a} -lt 0 -o ${a} -gt ${max_a} -o \
122 ${2} -lt 0 -o ${2} -gt ${max_i} ]; then
123 echo "WARNING: Invalid array name, skipping!!!"
132 # $4: append operation
136 # check if array is declared
137 array_check
$1 $2 ||
return 0
141 eval $1[$2]=\"\
${$1[$2]} $3\"
157 local i
=-1 k
=-1 d
=-1 r
=-1
158 while getopts ":A:a:C:c:D:d:e:h:k:K:o:v:r:s:n:" OPTION
; do
161 a
) array_put img
$i 3 $OPTARG;;
162 C
) value_sanity_chk compression
$OPTARG;
163 array_put img
$i 5 $OPTARG;;
164 c
) array_put img
$i 7 $OPTARG append
;;
165 D
) array_put img
$i 8 $OPTARG;;
169 array_put img
$i 0 fdt
;
170 array_put img
$i 1 $OPTARG;
171 array_put img
$i 2 $d;
173 e
) array_put img
$i 4 $OPTARG;;
174 h
) value_sanity_chk
hash $OPTARG;
175 array_put img
$i 6 $OPTARG append
;;
179 array_put img
$i 0 "kernel";
180 array_put img
$i 1 $OPTARG;
181 array_put img
$i 2 $k;
183 K
) array_put img
$i 9 $OPTARG;;
184 n
) array_put img
$i 11 $OPTARG;;
186 v
) VERSION
=$OPTARG;;
190 array_put img
$i 0 "ramdisk";
191 array_put img
$i 1 $OPTARG;
192 array_put img
$i 2 $r;
194 s
) value_sanity_chk signature
$OPTARG;
195 array_put img
$i 10 $OPTARG;
197 * ) echo "Invalid option passed to '$0' (options:$@)"
201 [ -n "${OUTPUT}" ] || OUTPUT
=fitimage.its
202 [ -n "${VERSION}" ] || VERSION
="Unknown"
203 [ -n "${ARCH}" ] || ARCH
=arm
207 # sanity check for signature, compression and hash
213 signature
) valid
="sha-1,rsa-2048 sha-256,rsa-2048 sha-256,rsa-4096";;
214 compression
) valid
="gzip bzip2 none";;
215 hash) valid
="sha1 md5 crc32";;
217 if ! echo $valid |
grep -q "$2"; then
218 echo "Error: Invalid $1 provided '$2'"
219 echo "Valid options are: $valid"
225 # Emit the fitImage section bits
227 # $1: Section bit type: fitstart - its header
228 # imagestart - image section start
229 # confstart - configuration section start
230 # sectend - section end
231 # fitend - fitimage end
232 # $2: optional variable for confstart section
237 cat << EOF > ${OUTPUT}
241 description = "U-Boot fitImage for ${VERSION} kernel";
242 #address-cells = <1>;
246 echo -e "\n\timages {" >> ${OUTPUT};;
248 # echo -e "\tconfigurations {\n\t\tdefault = \"conf@${2:-0}\";" \
249 echo -e "\tconfigurations {\n" \
252 echo -e "\t};" >> ${OUTPUT};;
254 echo -e "};" >> ${OUTPUT};;
259 # Emit kernel image node
263 local count
=${2:-${MAX_IMG}}
264 local loaddaddr
=${3:-0x8000}
265 local entrypoint
=${4:-0x8000}
266 local compresson
=${5:-none}
267 local checksum
=${6:-sha1}
270 [ -z "${name}" ] || name
=" ${name}"
271 cat << EOF >> ${OUTPUT}
273 description = "Linux Kernel${name}";
274 data = /incbin/("${image}");
278 compression = "${compresson}";
279 load = <${loaddaddr}>;
280 entry = <${entrypoint}>;
282 emit_cksum
${checksum}
284 if [ -z "$SIGN_IN_CONF" ] ; then
285 emit_signature
"$9" "" "" "$8" "" ""
288 echo " };" >> ${OUTPUT}
296 local count
=${2:-${MAX_IMG}}
297 local compresson
=${3:-none}
298 local checksum
=${4:-sha1}
302 [ -z "${name}" ] || name
=" ${name}"
303 cat << EOF >> ${OUTPUT}
305 description = "Flattened Device Tree blob${name}";
306 data = /incbin/("${image}");
309 load = <${loadaddr}>;
310 compression = "none";
312 emit_cksum
${checksum}
313 if [ -z "$SIGN_IN_CONF" ] ; then
314 emit_signature
"" "$7" "" "" "$6" ""
316 echo " };" >> ${OUTPUT}
324 local count
=${2:-${MAX_IMG}}
325 local compresson
=${3:-none}
326 local checksum
=${4:-sha1}
329 [ -z "${name}" ] || name
=" ${name}"
330 cat << EOF >> ${OUTPUT}
332 description = "ramdisk${name}";
333 data = /incbin/("${image}");
337 compression = "${compresson}";
339 emit_cksum
${checksum}
340 if [ -z "$SIGN_IN_CONF" ] ; then
341 emit_signature
"" "" "$7" "" "" "$6"
343 echo " };" >> ${OUTPUT}
347 # Emit check sum sub node
352 for csum
in ${csum_list}; do
353 cat << EOF >> ${OUTPUT}
358 count
=`expr ${count} + 1`
363 # Emit signature sub node
374 local chk_list
="" algo
="" algos
="" i
=""
376 for i
in kernel fdt rootfs
; do
379 [ -n "$algo" ] ||
continue
380 if ! echo "$algos" |
grep -q $algo; then
381 if [ -z "$algos" ]; then
384 algos
="${algos} $algo"
387 if ! echo "$keys" |
grep -q $key; then
388 if [ -z "$keys" ]; then
396 for algo
in $algos; do
399 for i
in kernel fdt rootfs
; do
401 eval tmp_key
=\$
${i}_key
402 [ "$tmp_algo" == "$algo" ] ||
continue
403 [ "$tmp_key" == "$key" ] ||
continue
404 if [ -z "$img" ]; then
411 [ -n "$img" ] ||
continue
412 cat << EOF >> ${OUTPUT}
415 key-name-hint = "${key}";
417 if [ -n "$SIGN_IN_CONF" ] ; then
418 echo " sign-images = \"$img\";" >> ${OUTPUT}
420 echo " };" >> ${OUTPUT}
422 count
=`expr ${count} + 1`
428 # Emit config sub nodes
431 local conf_csum
="sha1"
433 config_name
="conf@${1}"
434 if [ ! -z "${11}" ]; then
437 if [ -z "${2}" ]; then
438 echo "Error: config has no kernel img, skipping conf node!"
442 # Test if we have any DTBs at all
443 if [ -z "${3}" ] ; then
444 conf_desc
="Boot Linux kernel"
447 conf_desc
="Boot Linux kernel with FDT blob"
452 # Test if we have any ROOTFS at all
453 if [ -n "${4}" ] ; then
454 conf_desc
="$conf_desc + ramdisk"
455 fdt_line
="${fdt_line}
456 ramdisk = \"ramdisk@${4}\";"
459 kernel_line
="kernel = \"kernel@${2}\";"
461 cat << EOF >> ${OUTPUT}
463 description = "${conf_desc}";
464 ${kernel_line}${fdt_line}
466 algo = "${conf_csum}";
469 if [ -n "$SIGN_IN_CONF" ] ; then
470 emit_signature
"$5" "$6" "$7" "$8" "$9" "${10}"
473 echo " };" >> ${OUTPUT}
477 # remove prefix space
479 remove_prefix_space
()
481 echo "$@" |
sed "s:^ ::g"
485 # generate image nodes and its subnodes
489 local t img_c img_i img_index chk
490 local img_type img_path img_count img_loadadr img_entrypoint \
491 img_compression img_hash img_conf img_name img_key img_sign \
495 for t
in "kernel" "fdt" "ramdisk"; do
497 for a
in ${img_array[@]}; do
498 img_type
=$
(array_get
$a 0)
499 img_path
=$
(array_get
$a 1)
500 img_count
=$
(array_get
$a 2)
501 img_loadadr
=$
(array_get
$a 3)
502 img_entrypoint
=$
(array_get
$a 4)
503 img_compression
=$
(array_get
$a 5)
504 img_hash
=$
(array_get
$a 6)
505 img_conf
=$
(array_get
$a 7)
506 img_name
=$
(array_get
$a 8)
507 img_key
=$
(array_get
$a 9)
508 img_sign
=$
(array_get
$a 10)
509 img_cname
=$
(array_get
$a 11)
511 img_conf
=$
(remove_prefix_space
$img_conf)
512 img_hash
=$
(remove_prefix_space
$img_hash)
514 [ "${img_type}" == $t ] ||
continue
517 [ -n "${chk}" ] ||
eval DEF_
$t=$img_count
519 kernel
) emit_kernel
"$img_path" "$img_count" \
520 "$img_loadadr" "$img_entrypoint" \
521 "$img_compression" "$img_hash" \
522 "$img_name" "$img_key" "$img_sign";;
523 fdt
) emit_fdt
"$img_path" "$img_count" \
524 "$img_compression" "$img_hash" \
525 "$img_name" "$img_loadadr" "$img_key" "$img_sign" ;;
527 ramdisk
) emit_ramdisk
"$img_path" "$img_count" \
528 "$img_compression" "$img_hash" \
529 "$img_name" "$img_key" "$img_sign";;
532 # set up configuration data
533 for img_c
in $img_conf; do
535 #set up default configuration if its not set
536 [ -n "$DEF_CONFIG" ] || DEF_CONFIG
=$img_c
537 [ -z "${img_c}" ] || conf_array
[$img_c]=conf
$img_c
538 array_put conf
$img_c 0 ${img_c}
544 array_put conf
$img_c $img_i $img_index
545 array_put conf
$img_c $
(($img_i + 3)) ${img_sign}
546 array_put conf
$img_c $
(($img_i + 6)) ${img_key}
547 array_put conf
$img_c 10 $img_cname
549 img_index
=$
((img_index
+ 1))
556 # generate configuration node and its subnodes
558 emit_configuration_nodes
()
560 local count kernel fdt ramdisk ker_file fdt_file rfs_file ker_sign \
562 emit_its confstart
$DEF_CONFIG
563 for a
in ${conf_array[@]}; do
564 count
=$
(array_get
$a 0)
565 kernel
=$
(array_get
$a 1)
566 fdt
=$
(array_get
$a 2)
567 ramdisk
=$
(array_get
$a 3)
568 er_file
=$
(array_get
$a 4)
569 fdt_file
=$
(array_get
$a 5)
570 rfs_file
=$
(array_get
$a 6)
571 ker_sign
=$
(array_get
$a 7)
572 fdt_sign
=$
(array_get
$a 8)
573 rfs_sign
=$
(array_get
$a 9)
574 cname
=$
(array_get
$a 10)
575 emit_config
"$count" "$kernel" "$fdt" "$ramdisk" "$ker_file" \
576 "$fdt_file" "$rfs_file" "$ker_sign" "$fdt_sign" \
577 "$rfs_sign" "${cname}"
579 if [ -z "${DEF_CONFIG}" ]; then
580 emit_config
"0" "$DEF_kernel" "$DEF_fdt" "$DEF_ramdisk"
585 # Set to none empty to create signature sub node under images node
586 SIGN_IN_CONF
=${SIGN_IN_CONF:-""}
587 # Set to default config used
588 DEF_CONFIG
=${DEF_CONFIG:-""}
594 emit_configuration_nodes