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