3 # Licensed under the terms of the GNU GPL License version 2 or later.
5 # Author: Jason Wu <jason.hy.wu@gmail.com>
6 # with modifications for multi-DTB-same-image by:
7 # Mathew McBride <matt@traverse.com.au>
9 # U-Boot firmware supports the booting of images in the Flattened Image
10 # Tree (FIT) format. The FIT format uses a device tree structure to
11 # describe a kernel image, device tree blob, ramdisk, etc. This script
12 # creates an Image Tree Source (.its file) which can be passed to the
13 # 'mkimage' utility to generate an Image Tree Blob (.itb file). The .itb
14 # file can then be booted by U-Boot (or other bootloaders which support
15 # FIT images). See doc/uImage.FIT/howto.txt in U-Boot source code for
16 # additional information on FIT images.
18 # This tools supports:
19 # - multi-configuration
20 # - multi-image support - multiple kernel/fdt/ramdsik
21 # - per image configuration:
22 # - hash algorithm and generated required subnodes
24 # - signature and generated required subnodes
33 # declare main data array
37 # initialize array with empty values
38 for (( index
=1; index
<=$MAX_IMG; index
++ )); do
41 eval img
${index}[$i]=""
45 for (( index
=1; index
<=$MAX_CONF; index
++ )); do
48 eval conf
${index}[$i]=""
52 # imgX array index information
53 # 0: type of image - kernel, fdt, ramdsik
56 # 3: loadaddr of image
57 # 4: entrypoint of image
60 # 7: part of the configuration
61 # 8: Human friend name for the image
64 # 11: conf friendly name
66 # confX array index information
74 # 7: kernel sign_algorithm
75 # 8: fdt sign_algorithm
76 # 9: rootfs sign_algorithm
77 # 10: conf friendly name
80 echo "Usage: `basename $0` -A arch -v version -o its_file" \
81 "-k kernel -a addr -e entry [-C none] [-h sha1] [-c conf]"
82 echo -e "Example1:\n\tkernel image ker_img1 with no compression +"
83 echo -e "\tsha1 hash + fdt dtb1 with sha1 and crc32 hash for conf 1"
84 echo -e "\t $ `basename $0` -A arm -v 4.4 \ "
85 echo -e "\t -k ker_img1 -C none -h sha1 -e 0x8000 -a 0x8000 -c 1 \ "
86 echo -e "\t -d dtb1 -h sha1 -h crc32 -c 1\n"
87 echo "General settings:"
88 echo -e "\t-A ==> set architecture to 'arch'"
89 echo -e "\t-v ==> set kernel version to 'version'"
90 echo -e "\t-o ==> create output file 'its_file' [optional]"
91 echo "Input image type:"
92 echo -e "\t-k ==> kernel image 'kernel'"
93 echo -e "\t-d ==> Device Tree Blob 'dtb'"
94 echo -e "\t-r ==> ramdisk image 'ramdisk"
95 echo "Per image configurations:"
96 echo -e "\t-C ==> set compression type 'comp'"
97 echo -e "\t-c ==> set image config (multiple -c allowed)"
98 echo -e "\t-a ==> set load address to 'addr' (hex)"
99 echo -e "\t-e ==> set entry point to 'entry' (hex)"
100 echo -e "\t-D ==> human friendly 'name' (one word only)"
101 echo -e "\t-h ==> set hash algorithm (multiple -h allowed)"
102 echo -e "\t-s ==> set signature for given config image"
103 echo -e "\t-K ==> set key file for given config image"
113 if echo $1 |
grep -q img
; then
116 let a
=$
(echo $1 |
awk -F "img" '{print $2}')
117 elif echo $1 |
grep -q conf
; then
120 let a
=$
(echo $1 |
awk -F "conf" '{print $2}')
122 if [ ${a} -lt 0 -o ${a} -gt ${max_a} -o \
123 ${2} -lt 0 -o ${2} -gt ${max_i} ]; then
124 echo "WARNING: Invalid array name, skipping!!!"
133 # $4: append operation
137 # check if array is declared
138 array_check
$1 $2 ||
return 0
142 eval $1[$2]=\"\
${$1[$2]} $3\"
158 local i
=-1 k
=-1 d
=-1 r
=-1
159 while getopts ":A:a:C:c:D:d:e:h:k:K:o:v:r:s:n:" OPTION
; do
162 a
) array_put img
$i 3 $OPTARG;;
163 C
) value_sanity_chk compression
$OPTARG;
164 array_put img
$i 5 $OPTARG;;
165 c
) array_put img
$i 7 $OPTARG append
;;
166 D
) array_put img
$i 8 $OPTARG;;
170 array_put img
$i 0 fdt
;
171 array_put img
$i 1 $OPTARG;
172 array_put img
$i 2 $d;
174 e
) array_put img
$i 4 $OPTARG;;
175 h
) value_sanity_chk
hash $OPTARG;
176 array_put img
$i 6 $OPTARG append
;;
180 array_put img
$i 0 "kernel";
181 array_put img
$i 1 $OPTARG;
182 array_put img
$i 2 $k;
184 K
) array_put img
$i 9 $OPTARG;;
185 n
) array_put img
$i 11 $OPTARG;;
187 v
) VERSION
=$OPTARG;;
191 array_put img
$i 0 "ramdisk";
192 array_put img
$i 1 $OPTARG;
193 array_put img
$i 2 $r;
195 s
) value_sanity_chk signature
$OPTARG;
196 array_put img
$i 10 $OPTARG;
198 * ) echo "Invalid option passed to '$0' (options:$@)"
202 [ -n "${OUTPUT}" ] || OUTPUT
=fitimage.its
203 [ -n "${VERSION}" ] || VERSION
="Unknown"
204 [ -n "${ARCH}" ] || ARCH
=arm
208 # sanity check for signature, compression and hash
214 signature
) valid
="sha-1,rsa-2048 sha-256,rsa-2048 sha-256,rsa-4096";;
215 compression
) valid
="gzip bzip2 none";;
216 hash) valid
="sha1 md5 crc32";;
218 if ! echo $valid |
grep -q "$2"; then
219 echo "Error: Invalid $1 provided '$2'"
220 echo "Valid options are: $valid"
226 # Emit the fitImage section bits
228 # $1: Section bit type: fitstart - its header
229 # imagestart - image section start
230 # confstart - configuration section start
231 # sectend - section end
232 # fitend - fitimage end
233 # $2: optional variable for confstart section
238 cat << EOF > ${OUTPUT}
242 description = "U-Boot fitImage for ${VERSION} kernel";
243 #address-cells = <1>;
247 echo -e "\n\timages {" >> ${OUTPUT};;
249 # echo -e "\tconfigurations {\n\t\tdefault = \"conf@${2:-0}\";" \
250 echo -e "\tconfigurations {\n" \
253 echo -e "\t};" >> ${OUTPUT};;
255 echo -e "};" >> ${OUTPUT};;
260 # Emit kernel image node
264 local count
=${2:-${MAX_IMG}}
265 local loaddaddr
=${3:-0x8000}
266 local entrypoint
=${4:-0x8000}
267 local compresson
=${5:-none}
268 local checksum
=${6:-sha1}
271 [ -z "${name}" ] || name
=" ${name}"
272 cat << EOF >> ${OUTPUT}
274 description = "Linux Kernel${name}";
275 data = /incbin/("${image}");
279 compression = "${compresson}";
280 load = <${loaddaddr}>;
281 entry = <${entrypoint}>;
283 emit_cksum
${checksum}
285 if [ -z "$SIGN_IN_CONF" ] ; then
286 emit_signature
"$9" "" "" "$8" "" ""
289 echo " };" >> ${OUTPUT}
297 local count
=${2:-${MAX_IMG}}
298 local compresson
=${3:-none}
299 local checksum
=${4:-sha1}
303 [ -z "${name}" ] || name
=" ${name}"
304 cat << EOF >> ${OUTPUT}
306 description = "Flattened Device Tree blob${name}";
307 data = /incbin/("${image}");
310 load = <${loadaddr}>;
311 compression = "none";
313 emit_cksum
${checksum}
314 if [ -z "$SIGN_IN_CONF" ] ; then
315 emit_signature
"" "$7" "" "" "$6" ""
317 echo " };" >> ${OUTPUT}
325 local count
=${2:-${MAX_IMG}}
326 local compresson
=${3:-none}
327 local checksum
=${4:-sha1}
330 [ -z "${name}" ] || name
=" ${name}"
331 cat << EOF >> ${OUTPUT}
333 description = "ramdisk${name}";
334 data = /incbin/("${image}");
338 compression = "${compresson}";
340 emit_cksum
${checksum}
341 if [ -z "$SIGN_IN_CONF" ] ; then
342 emit_signature
"" "" "$7" "" "" "$6"
344 echo " };" >> ${OUTPUT}
348 # Emit check sum sub node
353 for csum
in ${csum_list}; do
354 cat << EOF >> ${OUTPUT}
359 count
=`expr ${count} + 1`
364 # Emit signature sub node
375 local chk_list
="" algo
="" algos
="" i
=""
377 for i
in kernel fdt rootfs
; do
380 [ -n "$algo" ] ||
continue
381 if ! echo "$algos" |
grep -q $algo; then
382 if [ -z "$algos" ]; then
385 algos
="${algos} $algo"
388 if ! echo "$keys" |
grep -q $key; then
389 if [ -z "$keys" ]; then
397 for algo
in $algos; do
400 for i
in kernel fdt rootfs
; do
402 eval tmp_key
=\$
${i}_key
403 [ "$tmp_algo" == "$algo" ] ||
continue
404 [ "$tmp_key" == "$key" ] ||
continue
405 if [ -z "$img" ]; then
412 [ -n "$img" ] ||
continue
413 cat << EOF >> ${OUTPUT}
416 key-name-hint = "${key}";
418 if [ -n "$SIGN_IN_CONF" ] ; then
419 echo " sign-images = \"$img\";" >> ${OUTPUT}
421 echo " };" >> ${OUTPUT}
423 count
=`expr ${count} + 1`
429 # Emit config sub nodes
432 local conf_csum
="sha1"
434 config_name
="conf@${1}"
435 if [ ! -z "${11}" ]; then
438 if [ -z "${2}" ]; then
439 echo "Error: config has no kernel img, skipping conf node!"
443 # Test if we have any DTBs at all
444 if [ -z "${3}" ] ; then
445 conf_desc
="Boot Linux kernel"
448 conf_desc
="Boot Linux kernel with FDT blob"
453 # Test if we have any ROOTFS at all
454 if [ -n "${4}" ] ; then
455 conf_desc
="$conf_desc + ramdisk"
456 fdt_line
="${fdt_line}
457 ramdisk = \"ramdisk@${4}\";"
460 kernel_line
="kernel = \"kernel@${2}\";"
462 cat << EOF >> ${OUTPUT}
464 description = "${conf_desc}";
465 ${kernel_line}${fdt_line}
467 algo = "${conf_csum}";
470 if [ -n "$SIGN_IN_CONF" ] ; then
471 emit_signature
"$5" "$6" "$7" "$8" "$9" "${10}"
474 echo " };" >> ${OUTPUT}
478 # remove prefix space
480 remove_prefix_space
()
482 echo "$@" |
sed "s:^ ::g"
486 # generate image nodes and its subnodes
490 local t img_c img_i img_index chk
491 local img_type img_path img_count img_loadadr img_entrypoint \
492 img_compression img_hash img_conf img_name img_key img_sign \
496 for t
in "kernel" "fdt" "ramdisk"; do
498 for a
in ${img_array[@]}; do
499 img_type
=$
(array_get
$a 0)
500 img_path
=$
(array_get
$a 1)
501 img_count
=$
(array_get
$a 2)
502 img_loadadr
=$
(array_get
$a 3)
503 img_entrypoint
=$
(array_get
$a 4)
504 img_compression
=$
(array_get
$a 5)
505 img_hash
=$
(array_get
$a 6)
506 img_conf
=$
(array_get
$a 7)
507 img_name
=$
(array_get
$a 8)
508 img_key
=$
(array_get
$a 9)
509 img_sign
=$
(array_get
$a 10)
510 img_cname
=$
(array_get
$a 11)
512 img_conf
=$
(remove_prefix_space
$img_conf)
513 img_hash
=$
(remove_prefix_space
$img_hash)
515 [ "${img_type}" == $t ] ||
continue
518 [ -n "${chk}" ] ||
eval DEF_
$t=$img_count
520 kernel
) emit_kernel
"$img_path" "$img_count" \
521 "$img_loadadr" "$img_entrypoint" \
522 "$img_compression" "$img_hash" \
523 "$img_name" "$img_key" "$img_sign";;
524 fdt
) emit_fdt
"$img_path" "$img_count" \
525 "$img_compression" "$img_hash" \
526 "$img_name" "$img_loadadr" "$img_key" "$img_sign" ;;
528 ramdisk
) emit_ramdisk
"$img_path" "$img_count" \
529 "$img_compression" "$img_hash" \
530 "$img_name" "$img_key" "$img_sign";;
533 # set up configuration data
534 for img_c
in $img_conf; do
536 #set up default configuration if its not set
537 [ -n "$DEF_CONFIG" ] || DEF_CONFIG
=$img_c
538 [ -z "${img_c}" ] || conf_array
[$img_c]=conf
$img_c
539 array_put conf
$img_c 0 ${img_c}
545 array_put conf
$img_c $img_i $img_index
546 array_put conf
$img_c $
(($img_i + 3)) ${img_sign}
547 array_put conf
$img_c $
(($img_i + 6)) ${img_key}
548 array_put conf
$img_c 10 $img_cname
550 img_index
=$
((img_index
+ 1))
557 # generate configuration node and its subnodes
559 emit_configuration_nodes
()
561 local count kernel fdt ramdisk ker_file fdt_file rfs_file ker_sign \
563 emit_its confstart
$DEF_CONFIG
564 for a
in ${conf_array[@]}; do
565 count
=$
(array_get
$a 0)
566 kernel
=$
(array_get
$a 1)
567 fdt
=$
(array_get
$a 2)
568 ramdisk
=$
(array_get
$a 3)
569 er_file
=$
(array_get
$a 4)
570 fdt_file
=$
(array_get
$a 5)
571 rfs_file
=$
(array_get
$a 6)
572 ker_sign
=$
(array_get
$a 7)
573 fdt_sign
=$
(array_get
$a 8)
574 rfs_sign
=$
(array_get
$a 9)
575 cname
=$
(array_get
$a 10)
576 emit_config
"$count" "$kernel" "$fdt" "$ramdisk" "$ker_file" \
577 "$fdt_file" "$rfs_file" "$ker_sign" "$fdt_sign" \
578 "$rfs_sign" "${cname}"
580 if [ -z "${DEF_CONFIG}" ]; then
581 emit_config
"0" "$DEF_kernel" "$DEF_fdt" "$DEF_ramdisk"
586 # Set to none empty to create signature sub node under images node
587 SIGN_IN_CONF
=${SIGN_IN_CONF:-""}
588 # Set to default config used
589 DEF_CONFIG
=${DEF_CONFIG:-""}
595 emit_configuration_nodes