]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core-contrib.git/commitdiff
kernel-fitimage: re-write its code in Python
authorAdrian Freihofer <adrian.freihofer@siemens.com>
Tue, 3 Jun 2025 08:23:28 +0000 (10:23 +0200)
committerRichard Purdie <richard.purdie@linuxfoundation.org>
Thu, 5 Jun 2025 10:01:24 +0000 (11:01 +0100)
Rewrite the kernel-fitimage.bbclass file in Python. This allows the
reuse of the new fitimage Python library and a clear alignment of the
two implementations.

Actually, the motivation for an implementation in Python was different.
During the transition from the kernel-fitimage.bbclass to the new
linux-yocto-fitimage.bb, the existing shell code was rewritten in Python
so that the fitimage.py library could be extracted. The new
kernel-fit-image.bbclass and linux-yocto-fitimage.bb were then developed
on this basis.
This approach makes it possible to run the same tests for all different
implementations:
- kernel-fitimage.bbclass in Shell
- kernel-fitimage.bbclass in Python
- linux-yocto-fitimage.bb

Changing the commit order now enables a smooth transition. The two
implementations can coexist. Maintenance and testing should be feasible
for a few months with reasonable effort as they share most of the code.
But of course, the goal is to remove the kernel-fitimage.bbclass as soon
as possible.

This commit opens the path for different strategies going forward:
- Just replace the old implementations with the new one and ignoring
  this commit.
- Add the new implementation and keep the old implementation without any
  change.
- Add the new implementation and this commit and support the old
  architecture sharing most of the code with the new architecture and
  implementatiion.

Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
meta/classes-recipe/kernel-fitimage.bbclass
meta/classes-recipe/kernel-uboot.bbclass

index 8e66f3267664783ce63f33e7c2f9f9b27ae6b9b4..a253b210ef54ec408254802dce18443afe269f17 100644 (file)
@@ -56,680 +56,174 @@ python __anonymous () {
         d.setVar('EXTERNAL_KERNEL_DEVICETREE', "${RECIPE_SYSROOT}/boot/devicetree")
 }
 
-#
-# Emit the fitImage ITS header
-#
-# $1 ... .its filename
-fitimage_emit_fit_header() {
-       cat << EOF >> $1
-/dts-v1/;
-
-/ {
-        description = "${FIT_DESC}";
-        #address-cells = <${FIT_ADDRESS_CELLS}>;
-EOF
-}
-
-#
-# Emit the fitImage section bits
-#
-# $1 ... .its filename
-# $2 ... Section bit type: imagestart - image section start
-#                          confstart  - configuration section start
-#                          sectend    - section end
-#                          fitend     - fitimage end
-#
-fitimage_emit_section_maint() {
-       case $2 in
-       imagestart)
-               cat << EOF >> $1
-
-        images {
-EOF
-       ;;
-       confstart)
-               cat << EOF >> $1
-
-        configurations {
-EOF
-       ;;
-       sectend)
-               cat << EOF >> $1
-       };
-EOF
-       ;;
-       fitend)
-               cat << EOF >> $1
-};
-EOF
-       ;;
-       esac
-}
-
-#
-# Emit the fitImage ITS kernel section
-#
-# $1 ... .its filename
-# $2 ... Image counter
-# $3 ... Path to kernel image
-# $4 ... Compression type
-fitimage_emit_section_kernel() {
-
-       kernel_csum="${FIT_HASH_ALG}"
-       kernel_sign_algo="${FIT_SIGN_ALG}"
-       kernel_sign_keyname="${UBOOT_SIGN_IMG_KEYNAME}"
-
-       ENTRYPOINT="${UBOOT_ENTRYPOINT}"
-       if [ -n "${UBOOT_ENTRYSYMBOL}" ]; then
-               ENTRYPOINT=`${HOST_PREFIX}nm vmlinux | \
-                       awk '$3=="${UBOOT_ENTRYSYMBOL}" {print "0x"$1;exit}'`
-       fi
-
-       cat << EOF >> $1
-                kernel-$2 {
-                        description = "Linux kernel";
-                        type = "${UBOOT_MKIMAGE_KERNEL_TYPE}";
-                        compression = "$4";
-                        data = /incbin/("$3");
-                        arch = "${UBOOT_ARCH}";
-                        os = "linux";
-                        load = <${UBOOT_LOADADDRESS}>;
-                        entry = <$ENTRYPOINT>;
-                        hash-1 {
-                                algo = "$kernel_csum";
-                        };
-                };
-EOF
-
-       if [ "${UBOOT_SIGN_ENABLE}" = "1" -a "${FIT_SIGN_INDIVIDUAL}" = "1" -a -n "$kernel_sign_keyname" ] ; then
-               sed -i '$ d' $1
-               cat << EOF >> $1
-                        signature-1 {
-                                algo = "$kernel_csum,$kernel_sign_algo";
-                                key-name-hint = "$kernel_sign_keyname";
-                        };
-                };
-EOF
-       fi
-}
-
-#
-# Emit the fitImage ITS DTB section
-#
-# $1 ... .its filename
-# $2 ... Image counter
-# $3 ... Path to DTB image
-fitimage_emit_section_dtb() {
-
-       dtb_csum="${FIT_HASH_ALG}"
-       dtb_sign_algo="${FIT_SIGN_ALG}"
-       dtb_sign_keyname="${UBOOT_SIGN_IMG_KEYNAME}"
-
-       dtb_loadline=""
-       dtb_ext=${DTB##*.}
-       if [ "${dtb_ext}" = "dtbo" ]; then
-               if [ -n "${UBOOT_DTBO_LOADADDRESS}" ]; then
-                       dtb_loadline="load = <${UBOOT_DTBO_LOADADDRESS}>;"
-               fi
-       elif [ -n "${UBOOT_DTB_LOADADDRESS}" ]; then
-               dtb_loadline="load = <${UBOOT_DTB_LOADADDRESS}>;"
-       fi
-       cat << EOF >> $1
-                fdt-$2 {
-                        description = "Flattened Device Tree blob";
-                        type = "flat_dt";
-                        compression = "none";
-                        data = /incbin/("$3");
-                        arch = "${UBOOT_ARCH}";
-                        $dtb_loadline
-                        hash-1 {
-                                algo = "$dtb_csum";
-                        };
-                };
-EOF
-
-       if [ "${UBOOT_SIGN_ENABLE}" = "1" -a "${FIT_SIGN_INDIVIDUAL}" = "1" -a -n "$dtb_sign_keyname" ] ; then
-               sed -i '$ d' $1
-               cat << EOF >> $1
-                        signature-1 {
-                                algo = "$dtb_csum,$dtb_sign_algo";
-                                key-name-hint = "$dtb_sign_keyname";
-                        };
-                };
-EOF
-       fi
-}
-
-#
-# Emit the fitImage ITS u-boot script section
-#
-# $1 ... .its filename
-# $2 ... Image counter
-# $3 ... Path to boot script image
-fitimage_emit_section_boot_script() {
-
-       bootscr_csum="${FIT_HASH_ALG}"
-       bootscr_sign_algo="${FIT_SIGN_ALG}"
-       bootscr_sign_keyname="${UBOOT_SIGN_IMG_KEYNAME}"
-
-        cat << EOF >> $1
-                bootscr-$2 {
-                        description = "U-boot script";
-                        type = "script";
-                        compression = "none";
-                        data = /incbin/("$3");
-                        arch = "${UBOOT_ARCH}";
-                        hash-1 {
-                                algo = "$bootscr_csum";
-                        };
-                };
-EOF
-
-       if [ "${UBOOT_SIGN_ENABLE}" = "1" -a "${FIT_SIGN_INDIVIDUAL}" = "1" -a -n "$bootscr_sign_keyname" ] ; then
-               sed -i '$ d' $1
-               cat << EOF >> $1
-                        signature-1 {
-                                algo = "$bootscr_csum,$bootscr_sign_algo";
-                                key-name-hint = "$bootscr_sign_keyname";
-                        };
-                };
-EOF
-       fi
-}
-
-#
-# Emit the fitImage ITS setup section
-#
-# $1 ... .its filename
-# $2 ... Image counter
-# $3 ... Path to setup image
-fitimage_emit_section_setup() {
-
-       setup_csum="${FIT_HASH_ALG}"
-       setup_sign_algo="${FIT_SIGN_ALG}"
-       setup_sign_keyname="${UBOOT_SIGN_IMG_KEYNAME}"
-
-       cat << EOF >> $1
-                setup-$2 {
-                        description = "Linux setup.bin";
-                        type = "x86_setup";
-                        compression = "none";
-                        data = /incbin/("$3");
-                        arch = "${UBOOT_ARCH}";
-                        os = "linux";
-                        load = <0x00090000>;
-                        entry = <0x00090000>;
-                        hash-1 {
-                                algo = "$setup_csum";
-                        };
-                };
-EOF
-
-       if [ "${UBOOT_SIGN_ENABLE}" = "1" -a "${FIT_SIGN_INDIVIDUAL}" = "1" -a -n "$setup_sign_keyname" ] ; then
-               sed -i '$ d' $1
-               cat << EOF >> $1
-                        signature-1 {
-                                algo = "$setup_csum,$setup_sign_algo";
-                                key-name-hint = "$setup_sign_keyname";
-                        };
-                };
-EOF
-       fi
-}
-
-#
-# Emit the fitImage ITS ramdisk section
-#
-# $1 ... .its filename
-# $2 ... Image counter
-# $3 ... Path to ramdisk image
-fitimage_emit_section_ramdisk() {
-
-       ramdisk_csum="${FIT_HASH_ALG}"
-       ramdisk_sign_algo="${FIT_SIGN_ALG}"
-       ramdisk_sign_keyname="${UBOOT_SIGN_IMG_KEYNAME}"
-       ramdisk_loadline=""
-       ramdisk_entryline=""
-
-       if [ -n "${UBOOT_RD_LOADADDRESS}" ]; then
-               ramdisk_loadline="load = <${UBOOT_RD_LOADADDRESS}>;"
-       fi
-       if [ -n "${UBOOT_RD_ENTRYPOINT}" ]; then
-               ramdisk_entryline="entry = <${UBOOT_RD_ENTRYPOINT}>;"
-       fi
-
-       cat << EOF >> $1
-                ramdisk-$2 {
-                        description = "${INITRAMFS_IMAGE}";
-                        type = "ramdisk";
-                        compression = "none";
-                        data = /incbin/("$3");
-                        arch = "${UBOOT_ARCH}";
-                        os = "linux";
-                        $ramdisk_loadline
-                        $ramdisk_entryline
-                        hash-1 {
-                                algo = "$ramdisk_csum";
-                        };
-                };
-EOF
-
-       if [ "${UBOOT_SIGN_ENABLE}" = "1" -a "${FIT_SIGN_INDIVIDUAL}" = "1" -a -n "$ramdisk_sign_keyname" ] ; then
-               sed -i '$ d' $1
-               cat << EOF >> $1
-                        signature-1 {
-                                algo = "$ramdisk_csum,$ramdisk_sign_algo";
-                                key-name-hint = "$ramdisk_sign_keyname";
-                        };
-                };
-EOF
-       fi
-}
-
-#
-# echoes symlink destination if it points below directory
-#
-# $1 ... file that's a potential symlink
-# $2 ... expected parent directory
-symlink_points_below() {
-       file="$2/$1"
-       dir=$2
-
-       if ! [ -L "$file" ]; then
-               return
-       fi
-
-       realpath="$(realpath --relative-to=$dir $file)"
-       if [ -z "${realpath%%../*}" ]; then
-               return
-       fi
-
-       echo "$realpath"
-}
-
-#
-# Emit the fitImage ITS configuration section
-#
-# $1 ... .its filename
-# $2 ... Linux kernel ID
-# $3 ... DTB image name
-# $4 ... ramdisk ID
-# $5 ... u-boot script ID
-# $6 ... config ID
-# $7 ... default flag
-# $8 ... default DTB image name
-fitimage_emit_section_config() {
-
-       conf_csum="${FIT_HASH_ALG}"
-       conf_sign_algo="${FIT_SIGN_ALG}"
-       conf_padding_algo="${FIT_PAD_ALG}"
-       if [ "${UBOOT_SIGN_ENABLE}" = "1" ] ; then
-               conf_sign_keyname="${UBOOT_SIGN_KEYNAME}"
-       fi
-
-       its_file="$1"
-       kernel_id="$2"
-       dtb_image="$3"
-       ramdisk_id="$4"
-       bootscr_id="$5"
-       config_id="$6"
-       default_flag="$7"
-       default_dtb_image="$8"
-
-       # Test if we have any DTBs at all
-       sep=""
-       conf_desc=""
-       conf_node="${FIT_CONF_PREFIX}"
-       kernel_line=""
-       fdt_line=""
-       ramdisk_line=""
-       bootscr_line=""
-       setup_line=""
-       default_line=""
-       compatible_line=""
-
-       dtb_image_sect=$(symlink_points_below $dtb_image "${EXTERNAL_KERNEL_DEVICETREE}")
-       if [ -z "$dtb_image_sect" ]; then
-               dtb_image_sect=$dtb_image
-       fi
-
-       dtb_path="${EXTERNAL_KERNEL_DEVICETREE}/${dtb_image_sect}"
-       if [ -f "$dtb_path" ] || [ -L "$dtb_path" ]; then
-               compat=$(fdtget -t s "$dtb_path" / compatible | sed 's/ /", "/g')
-               if [ -n "$compat" ]; then
-                       compatible_line="compatible = \"$compat\";"
-               fi
-       fi
-
-       dtb_image=$(echo $dtb_image | tr '/' '_')
-       dtb_image_sect=$(echo "${dtb_image_sect}" | tr '/' '_')
-
-       # conf node name is selected based on dtb ID if it is present,
-       # otherwise its selected based on kernel ID
-       if [ -n "$dtb_image" ]; then
-               conf_node=$conf_node$dtb_image
-       else
-               conf_node=$conf_node$kernel_id
-       fi
-
-       if [ -n "$kernel_id" ]; then
-               conf_desc="Linux kernel"
-               sep=", "
-               kernel_line="kernel = \"kernel-$kernel_id\";"
-       fi
-
-       if [ -n "$dtb_image" ]; then
-               conf_desc="$conf_desc${sep}FDT blob"
-               sep=", "
-               fdt_line="fdt = \"fdt-$dtb_image_sect\";"
-       fi
-
-       if [ -n "$ramdisk_id" ]; then
-               conf_desc="$conf_desc${sep}ramdisk"
-               sep=", "
-               ramdisk_line="ramdisk = \"ramdisk-$ramdisk_id\";"
-       fi
-
-       if [ -n "$bootscr_id" ]; then
-               conf_desc="$conf_desc${sep}u-boot script"
-               sep=", "
-               bootscr_line="bootscr = \"bootscr-$bootscr_id\";"
-       fi
-
-       if [ -n "$config_id" ]; then
-               conf_desc="$conf_desc${sep}setup"
-               setup_line="setup = \"setup-$config_id\";"
-       fi
-
-       if [ "$default_flag" = "1" ]; then
-               # default node is selected based on dtb ID if it is present,
-               # otherwise its selected based on kernel ID
-               if [ -n "$dtb_image" ]; then
-                       # Select default node as user specified dtb when
-                       # multiple dtb exists.
-                       if [ -n "$default_dtb_image" ]; then
-                               default_line="default = \"${FIT_CONF_PREFIX}$default_dtb_image\";"
-                       else
-                               default_line="default = \"${FIT_CONF_PREFIX}$dtb_image\";"
-                       fi
-               else
-                       default_line="default = \"${FIT_CONF_PREFIX}$kernel_id\";"
-               fi
-       fi
-
-       cat << EOF >> $its_file
-                $default_line
-                $conf_node {
-                        description = "$default_flag $conf_desc";
-                        $compatible_line
-                        $kernel_line
-                        $fdt_line
-                        $ramdisk_line
-                        $bootscr_line
-                        $setup_line
-                        hash-1 {
-                                algo = "$conf_csum";
-                        };
-EOF
-
-       if [ -n "$conf_sign_keyname" ] ; then
-
-               sign_line="sign-images = "
-               sep=""
-
-               if [ -n "$kernel_id" ]; then
-                       sign_line="$sign_line${sep}\"kernel\""
-                       sep=", "
-               fi
-
-               if [ -n "$dtb_image" ]; then
-                       sign_line="$sign_line${sep}\"fdt\""
-                       sep=", "
-               fi
-
-               if [ -n "$ramdisk_id" ]; then
-                       sign_line="$sign_line${sep}\"ramdisk\""
-                       sep=", "
-               fi
-
-               if [ -n "$bootscr_id" ]; then
-                       sign_line="$sign_line${sep}\"bootscr\""
-                       sep=", "
-               fi
-
-               if [ -n "$config_id" ]; then
-                       sign_line="$sign_line${sep}\"setup\""
-               fi
-
-               sign_line="$sign_line;"
-
-               cat << EOF >> $its_file
-                        signature-1 {
-                                algo = "$conf_csum,$conf_sign_algo";
-                                key-name-hint = "$conf_sign_keyname";
-                                padding = "$conf_padding_algo";
-                                $sign_line
-                        };
-EOF
-       fi
-
-       cat << EOF >> $its_file
-                };
-EOF
-}
-
-#
-# Assemble fitImage
-#
-# $1 ... .its filename
-# $2 ... fitImage name
-# $3 ... include ramdisk
-fitimage_assemble() {
-       kernelcount=1
-       dtbcount=""
-       DTBS=""
-       ramdiskcount=$3
-       setupcount=""
-       bootscr_id=""
-       default_dtb_image=""
-       rm -f $1 arch/${ARCH}/boot/$2
-
-       if [ -n "${UBOOT_SIGN_IMG_KEYNAME}" -a "${UBOOT_SIGN_KEYNAME}" = "${UBOOT_SIGN_IMG_KEYNAME}" ]; then
-               bbfatal "Keys used to sign images and configuration nodes must be different."
-       fi
-
-       fitimage_emit_fit_header $1
-
-       #
-       # Step 1: Prepare a kernel image section.
-       #
-       fitimage_emit_section_maint $1 imagestart
-
-       uboot_prep_kimage
-       fitimage_emit_section_kernel $1 $kernelcount linux.bin "$linux_comp"
-
-       #
-       # Step 2: Prepare a DTB image section
-       #
-
-       if [ -n "${KERNEL_DEVICETREE}" ]; then
-               dtbcount=1
-               for DTB in ${KERNEL_DEVICETREE}; do
-                       if echo $DTB | grep -q '/dts/'; then
-                               bbwarn "$DTB contains the full path to the the dts file, but only the dtb name should be used."
-                               DTB=`basename $DTB | sed 's,\.dts$,.dtb,g'`
-                       fi
-
-                       # Skip ${DTB} if it's also provided in ${EXTERNAL_KERNEL_DEVICETREE}
-                       if [ -n "${EXTERNAL_KERNEL_DEVICETREE}" ] && [ -s ${EXTERNAL_KERNEL_DEVICETREE}/${DTB} ]; then
-                               continue
-                       fi
-
-                       DTB_PATH="${KERNEL_OUTPUT_DIR}/dts/$DTB"
-                       if [ ! -e "$DTB_PATH" ]; then
-                               DTB_PATH="${KERNEL_OUTPUT_DIR}/$DTB"
-                       fi
-
-                       # Strip off the path component from the filename
-                       if "${@'false' if oe.types.boolean(d.getVar('KERNEL_DTBVENDORED')) else 'true'}"; then
-                               DTB=`basename $DTB`
-                       fi
-
-                       # Set the default dtb image if it exists in the devicetree.
-                       if [ "${FIT_CONF_DEFAULT_DTB}" = "$DTB" ];then
-                               default_dtb_image=$(echo "$DTB" | tr '/' '_')
-                       fi
-
-                       DTB=$(echo "$DTB" | tr '/' '_')
-
-                       # Skip DTB if we've picked it up previously
-                       echo "$DTBS" | tr ' ' '\n' | grep -xq "$DTB" && continue
-
-                       DTBS="$DTBS $DTB"
-                       DTB=$(echo $DTB | tr '/' '_')
-                       fitimage_emit_section_dtb $1 $DTB $DTB_PATH
-               done
-       fi
-
-       if [ -n "${EXTERNAL_KERNEL_DEVICETREE}" ]; then
-               dtbcount=1
-               for DTB in $(find "${EXTERNAL_KERNEL_DEVICETREE}" -name '*.dtb' -printf '%P\n' | sort) \
-               $(find "${EXTERNAL_KERNEL_DEVICETREE}" -name '*.dtbo' -printf '%P\n' | sort); do
-                       # Set the default dtb image if it exists in the devicetree.
-                       if [ ${FIT_CONF_DEFAULT_DTB} = $DTB ];then
-                               default_dtb_image=$(echo "$DTB" | tr '/' '_')
-                       fi
-
-                       DTB=$(echo "$DTB" | tr '/' '_')
-
-                       # Skip DTB/DTBO if we've picked it up previously
-                       echo "$DTBS" | tr ' ' '\n' | grep -xq "$DTB" && continue
-
-                       DTBS="$DTBS $DTB"
-
-                       # Also skip if a symlink. We'll later have each config section point at it
-                       [ $(symlink_points_below $DTB "${EXTERNAL_KERNEL_DEVICETREE}") ] && continue
-
-                       DTB=$(echo $DTB | tr '/' '_')
-                       fitimage_emit_section_dtb $1 $DTB "${EXTERNAL_KERNEL_DEVICETREE}/$DTB"
-               done
-       fi
-
-       if [ -n "${FIT_CONF_DEFAULT_DTB}" ] && [ -z $default_dtb_image ]; then 
-               bbwarn "${FIT_CONF_DEFAULT_DTB} is not available in the list of device trees."
-       fi
-
-       #
-       # Step 3: Prepare a u-boot script section
-       #
-
-       if [ -n "${FIT_UBOOT_ENV}" ]; then
-               cp ${UNPACKDIR}/${FIT_UBOOT_ENV} ${B}
-               bootscr_id="${FIT_UBOOT_ENV}"
-               fitimage_emit_section_boot_script $1 "$bootscr_id" ${FIT_UBOOT_ENV}
-       fi
-
-       #
-       # Step 4: Prepare a setup section. (For x86)
-       #
-       if [ -e ${KERNEL_OUTPUT_DIR}/setup.bin ]; then
-               setupcount=1
-               fitimage_emit_section_setup $1 $setupcount ${KERNEL_OUTPUT_DIR}/setup.bin
-       fi
-
-       #
-       # Step 5: Prepare a ramdisk section.
-       #
-       if [ "x${ramdiskcount}" = "x1" ] && [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ]; then
-               # Find and use the first initramfs image archive type we find
-               found=
-               for img in ${FIT_SUPPORTED_INITRAMFS_FSTYPES}; do
-                       initramfs_path="${INITRAMFS_DEPLOY_DIR_IMAGE}/${INITRAMFS_IMAGE_NAME}.$img"
-                       if [ -e "$initramfs_path" ]; then
-                               bbnote "Found initramfs image: $initramfs_path"
-                               found=true
-                               fitimage_emit_section_ramdisk $1 "$ramdiskcount" "$initramfs_path"
-                               break
-                       else
-                               bbnote "Did not find initramfs image: $initramfs_path"
-                       fi
-               done
-
-               if [ -z "$found" ]; then
-                       bbfatal "Could not find a valid initramfs type for ${INITRAMFS_IMAGE_NAME}, the supported types are: ${FIT_SUPPORTED_INITRAMFS_FSTYPES}"
-               fi
-       fi
-
-       fitimage_emit_section_maint $1 sectend
-
-       # Force the first Kernel and DTB in the default config
-       kernelcount=1
-       if [ -n "$dtbcount" ]; then
-               dtbcount=1
-       fi
-
-       #
-       # Step 6: Prepare a configurations section
-       #
-       fitimage_emit_section_maint $1 confstart
-
-       # kernel-fitimage.bbclass currently only supports a single kernel (no less or
-       # more) to be added to the FIT image along with 0 or more device trees and
-       # 0 or 1 ramdisk.
-       # It is also possible to include an initramfs bundle (kernel and rootfs in one binary)
-       # When the initramfs bundle is used ramdisk is disabled.
-       # If a device tree is to be part of the FIT image, then select
-       # the default configuration to be used is based on the dtbcount. If there is
-       # no dtb present than select the default configuation to be based on
-       # the kernelcount.
-       if [ -n "$DTBS" ]; then
-               i=1
-               for DTB in ${DTBS}; do
-                       dtb_ext=${DTB##*.}
-                       if [ "$dtb_ext" = "dtbo" ]; then
-                               fitimage_emit_section_config $1 "" "$DTB" "" "$bootscr_id" "" "`expr $i = $dtbcount`" "$default_dtb_image"
-                       else
-                               fitimage_emit_section_config $1 $kernelcount "$DTB" "$ramdiskcount" "$bootscr_id" "$setupcount" "`expr $i = $dtbcount`" "$default_dtb_image"
-                       fi
-                       i=`expr $i + 1`
-               done
-       else
-               defaultconfigcount=1
-               fitimage_emit_section_config $1 $kernelcount "" "$ramdiskcount" "$bootscr_id"  "$setupcount" $defaultconfigcount "$default_dtb_image"
-       fi
-
-       fitimage_emit_section_maint $1 sectend
-
-       fitimage_emit_section_maint $1 fitend
-
-       #
-       # Step 7: Assemble the image
-       #
-       ${UBOOT_MKIMAGE} \
-               ${@'-D "${UBOOT_MKIMAGE_DTCOPTS}"' if len('${UBOOT_MKIMAGE_DTCOPTS}') else ''} \
-               -f $1 \
-               ${KERNEL_OUTPUT_DIR}/$2
-
-       #
-       # Step 8: Sign the image
-       #
-       if [ "x${UBOOT_SIGN_ENABLE}" = "x1" ] ; then
-               ${UBOOT_MKIMAGE_SIGN} \
-                       ${@'-D "${UBOOT_MKIMAGE_DTCOPTS}"' if len('${UBOOT_MKIMAGE_DTCOPTS}') else ''} \
-                       -F -k "${UBOOT_SIGN_KEYDIR}" \
-                       -r ${KERNEL_OUTPUT_DIR}/$2 \
-                       ${UBOOT_MKIMAGE_SIGN_ARGS}
-       fi
-}
-
-do_assemble_fitimage() {
-       if echo ${KERNEL_IMAGETYPES} | grep -wq "fitImage"; then
-               cd ${B}
-               fitimage_assemble fit-image.its fitImage-none ""
-               if [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ]; then
-                       ln -sf fitImage-none ${B}/${KERNEL_OUTPUT_DIR}/fitImage
-               fi
-       fi
+def fitimage_assemble(d, itsfile, fitname, ramdiskcount):
+    import shutil
+    import glob
+    import oe.fitimage
+
+    DTBS=""
+    default_dtb_image=""
+
+    for f in [itsfile, os.path.join("arch", d.getVar("ARCH"), "boot", fitname)]:
+        if os.path.exists(f):
+            os.remove(f)
+
+    root_node = oe.fitimage.ItsNodeRootKernel(
+        d.getVar("FIT_DESC"), d.getVar("FIT_ADDRESS_CELLS"),
+        d.getVar('HOST_PREFIX'), d.getVar('UBOOT_ARCH'),  d.getVar("FIT_CONF_PREFIX"),
+        d.getVar('UBOOT_SIGN_ENABLE') == "1", d.getVar("UBOOT_SIGN_KEYDIR"),
+        d.getVar("UBOOT_MKIMAGE"), d.getVar("UBOOT_MKIMAGE_DTCOPTS"),
+        d.getVar("UBOOT_MKIMAGE_SIGN"), d.getVar("UBOOT_MKIMAGE_SIGN_ARGS"),
+        d.getVar('FIT_HASH_ALG'), d.getVar('FIT_SIGN_ALG'), d.getVar('FIT_PAD_ALG'),
+        d.getVar('UBOOT_SIGN_KEYNAME'),
+        d.getVar('FIT_SIGN_INDIVIDUAL') == "1", d.getVar('UBOOT_SIGN_IMG_KEYNAME')
+    )
+
+    #
+    # Step 1: Prepare a kernel image section.
+    #
+    linux_comp = uboot_prep_kimage_py(d)
+    root_node.fitimage_emit_section_kernel("kernel-1", "linux.bin", linux_comp,
+        d.getVar('UBOOT_LOADADDRESS'), d.getVar('UBOOT_ENTRYPOINT'),
+        d.getVar('UBOOT_MKIMAGE_KERNEL_TYPE'), d.getVar("UBOOT_ENTRYSYMBOL"))
+
+    #
+    # Step 2: Prepare a DTB image section
+    #
+    kernel_devicetree = d.getVar('KERNEL_DEVICETREE')
+    external_kernel_devicetree = d.getVar("EXTERNAL_KERNEL_DEVICETREE")
+    if kernel_devicetree:
+        for DTB in kernel_devicetree.split():
+            if "/dts/" in DTB:
+                bb.warn(f"{DTB} contains the full path to the dts file, but only the dtb name should be used.")
+                DTB = os.path.basename(DTB).replace(".dts", ".dtb")
+
+            # Skip DTB if it's also provided in EXTERNAL_KERNEL_DEVICETREE
+            if external_kernel_devicetree:
+                ext_dtb_path = os.path.join(external_kernel_devicetree, DTB)
+                if os.path.exists(ext_dtb_path) and os.path.getsize(ext_dtb_path) > 0:
+                    continue
+
+            DTB_PATH = os.path.join(d.getVar("KERNEL_OUTPUT_DIR"), "dts", DTB)
+            if not os.path.exists(DTB_PATH):
+                DTB_PATH = os.path.join(d.getVar("KERNEL_OUTPUT_DIR"), DTB)
+
+            # Strip off the path component from the filename
+            if not oe.types.boolean(d.getVar("KERNEL_DTBVENDORED")):
+                DTB = os.path.basename(DTB)
+
+            # Set the default dtb image if it exists in the devicetree.
+            if d.getVar("FIT_CONF_DEFAULT_DTB") == DTB:
+                default_dtb_image = DTB.replace("/", "_")
+
+            DTB = DTB.replace("/", "_")
+
+            # Skip DTB if we've picked it up previously
+            if DTB in DTBS.split():
+                continue
+
+            DTBS += " " + DTB
+
+            root_node.fitimage_emit_section_dtb(DTB, DTB_PATH,
+                d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS"))
+
+    if external_kernel_devicetree:
+        dtb_files = []
+        for ext in ['*.dtb', '*.dtbo']:
+            dtb_files.extend(sorted(glob.glob(os.path.join(external_kernel_devicetree, ext))))
+
+        for dtb_path in dtb_files:
+            dtb_name = os.path.relpath(dtb_path, external_kernel_devicetree)
+            dtb_name_underscore = dtb_name.replace('/', '_')
+
+            # Set the default dtb image if it exists in the devicetree.
+            if d.getVar("FIT_CONF_DEFAULT_DTB") == dtb_name:
+                default_dtb_image = dtb_name_underscore
+
+            # Skip DTB/DTBO if we've picked it up previously
+            if dtb_name_underscore in DTBS.split():
+                continue
+
+            DTBS += " " + dtb_name_underscore
+
+            # For symlinks, add a configuration node that refers to the DTB image node to which the symlink points
+            symlink_target = oe.fitimage.symlink_points_below(dtb_name, external_kernel_devicetree)
+            if symlink_target:
+                root_node.fitimage_emit_section_dtb_alias(dtb_name, symlink_target, True)
+            # For real DTB files add an image node and a configuration node
+            else:
+                root_node.fitimage_emit_section_dtb(dtb_name_underscore, dtb_path,
+                    d.getVar("UBOOT_DTB_LOADADDRESS"), d.getVar("UBOOT_DTBO_LOADADDRESS"), True)
+
+    if d.getVar("FIT_CONF_DEFAULT_DTB") and not default_dtb_image:
+        bb.warn("%s is not available in the list of device trees." % d.getVar('FIT_CONF_DEFAULT_DTB'))
+
+    #
+    # Step 3: Prepare a u-boot script section
+    #
+    fit_uboot_env = d.getVar("FIT_UBOOT_ENV")
+    if fit_uboot_env:
+        unpack_dir = d.getVar("UNPACKDIR")
+        shutil.copy(os.path.join(unpack_dir, fit_uboot_env), fit_uboot_env)
+        root_node.fitimage_emit_section_boot_script("bootscr-"+fit_uboot_env , fit_uboot_env)
+
+    #
+    # Step 4: Prepare a setup section. (For x86)
+    #
+    setup_bin_path = os.path.join(d.getVar("KERNEL_OUTPUT_DIR"), "setup.bin")
+    if os.path.exists(setup_bin_path):
+        root_node.fitimage_emit_section_setup("setup-1", setup_bin_path)
+
+    #
+    # Step 5: Prepare a ramdisk section.
+    #
+    if ramdiskcount == 1 and d.getVar("INITRAMFS_IMAGE_BUNDLE") != "1":
+        # Find and use the first initramfs image archive type we find
+        found = False
+        for img in d.getVar("FIT_SUPPORTED_INITRAMFS_FSTYPES").split():
+            initramfs_path = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), "%s.%s" % (d.getVar('INITRAMFS_IMAGE_NAME'), img))
+            if os.path.exists(initramfs_path):
+                bb.note("Found initramfs image: " + initramfs_path)
+                found = True
+                root_node.fitimage_emit_section_ramdisk("ramdisk-%d" % ramdiskcount, initramfs_path,
+                    d.getVar('INITRAMFS_IMAGE'),
+                    d.getVar("UBOOT_RD_LOADADDRESS"),
+                    d.getVar("UBOOT_RD_ENTRYPOINT"))
+                break
+            else:
+                bb.note("Did not find initramfs image: " + initramfs_path)
+
+        if not found:
+            bb.fatal("Could not find a valid initramfs type for %s, the supported types are: %s" % (d.getVar('INITRAMFS_IMAGE_NAME'), d.getVar('FIT_SUPPORTED_INITRAMFS_FSTYPES')))
+
+    # Generate the configuration section
+    root_node.fitimage_emit_section_config(default_dtb_image)
+
+    #
+    # Write the ITS file
+    root_node.write_its_file(itsfile)
+
+    #
+    # Step 7: Assemble the image
+    #
+    fitfile = os.path.join(d.getVar("KERNEL_OUTPUT_DIR"), fitname)
+    root_node.run_mkimage_assemble(itsfile, fitfile)
+
+    #
+    # Step 8: Sign the image if required
+    #
+    root_node.run_mkimage_sign(fitfile)
+
+
+python do_assemble_fitimage() {
+    if "fitImage" in d.getVar("KERNEL_IMAGETYPES").split():
+        os.chdir(d.getVar("B"))
+        fitimage_assemble(d, "fit-image.its", "fitImage-none", "")
+        if d.getVar("INITRAMFS_IMAGE_BUNDLE") != "1":
+            link_name = os.path.join(d.getVar("B"), d.getVar("KERNEL_OUTPUT_DIR"), "fitImage")
+            if os.path.islink(link_name):
+                os.unlink(link_name)
+            os.symlink("fitImage-none", link_name)
 }
 
 addtask assemble_fitimage before do_install after do_compile
@@ -742,17 +236,17 @@ do_install:append() {
        fi
 }
 
-do_assemble_fitimage_initramfs() {
-       if echo ${KERNEL_IMAGETYPES} | grep -wq "fitImage" && \
-               test -n "${INITRAMFS_IMAGE}" ; then
-               cd ${B}
-               if [ "${INITRAMFS_IMAGE_BUNDLE}" = "1" ]; then
-                       fitimage_assemble fit-image-${INITRAMFS_IMAGE}.its fitImage-bundle ""
-                       ln -sf fitImage-bundle ${B}/${KERNEL_OUTPUT_DIR}/fitImage
-               else
-                       fitimage_assemble fit-image-${INITRAMFS_IMAGE}.its fitImage-${INITRAMFS_IMAGE} 1
-               fi
-       fi
+python do_assemble_fitimage_initramfs() {
+    if "fitImage" in d.getVar("KERNEL_IMAGETYPES").split() and d.getVar("INITRAMFS_IMAGE"):
+        os.chdir(d.getVar("B"))
+        if d.getVar("INITRAMFS_IMAGE_BUNDLE") == "1":
+            fitimage_assemble(d, "fit-image-%s.its" % d.getVar("INITRAMFS_IMAGE"), "fitImage-bundle", "")
+            link_name =  os.path.join(d.getVar("B"), d.getVar("KERNEL_OUTPUT_DIR"), "fitImage")
+            if os.path.islink(link_name):
+                os.unlink(link_name)
+            os.symlink("fitImage-bundle", link_name)
+        else:
+            fitimage_assemble(d, "fit-image-%s.its" % d.getVar("INITRAMFS_IMAGE"), "fitImage-%s" % d.getVar("INITRAMFS_IMAGE"), 1)
 }
 
 addtask assemble_fitimage_initramfs before do_deploy after do_bundle_initramfs
index d2a63524ece3e45d21dc61720a1f6fdd68881c6d..6d365355e3677b485e3e7c1028703f022ab38de2 100644 (file)
@@ -56,4 +56,49 @@ uboot_prep_kimage() {
        fi
 
        printf "$linux_comp" > "$output_dir/linux_comp"
-}
\ No newline at end of file
+}
+
+def uboot_prep_kimage_py(d):
+    import subprocess
+
+    arch = d.getVar('ARCH')
+    initramfs_image_bundle = d.getVar('INITRAMFS_IMAGE_BUNDLE')
+    fit_kernel_comp_alg = d.getVar('FIT_KERNEL_COMP_ALG') or 'gzip'
+    fit_kernel_comp_alg_extension = d.getVar('FIT_KERNEL_COMP_ALG_EXTENSION') or '.gz'
+    kernel_objcopy = d.getVar('KERNEL_OBJCOPY')
+
+    vmlinux_path = ""
+    linux_suffix = ""
+    linux_comp = "none"
+
+    if os.path.exists(f'arch/{arch}/boot/compressed/vmlinux'):
+        vmlinux_path = f'arch/{arch}/boot/compressed/vmlinux'
+    elif os.path.exists(f'arch/{arch}/boot/vmlinuz.bin'):
+        if os.path.exists('linux.bin'):
+            os.remove('linux.bin')
+        os.link(f'arch/{arch}/boot/vmlinuz.bin', 'linux.bin')
+    else:
+        vmlinux_path = 'vmlinux'
+        # Use vmlinux.initramfs for linux.bin when INITRAMFS_IMAGE_BUNDLE set
+        # As per the implementation in kernel.bbclass.
+        # See do_bundle_initramfs function
+        if initramfs_image_bundle == '1' and os.path.exists('vmlinux.initramfs'):
+            vmlinux_path = 'vmlinux.initramfs'
+        linux_suffix = fit_kernel_comp_alg_extension
+        linux_comp = fit_kernel_comp_alg
+
+    if vmlinux_path:
+        subprocess.run([kernel_objcopy.strip(), '-O', 'binary', '-R', '.note', '-R', '.comment', '-S', os.path.abspath(vmlinux_path), 'linux.bin'], check=True)
+        # if ret.returncode != 0:
+        # bb.fatal(f"Error: stderr: {ret.stderr.decode('utf-8')}   stdout: {ret.stdout.decode('utf-8')}, vmlinux_path: {os.path.abspath(vmlinux_path)}, pwd: {os.getcwd()}, args: {ret.args}")
+
+    if linux_comp != "none":
+        if linux_comp == "gzip":
+            subprocess.run(['gzip', '-9', 'linux.bin'], check=True)
+        elif linux_comp == "lzo":
+            subprocess.run(['lzop', '-9', 'linux.bin'], check=True)
+        elif linux_comp == "lzma":
+            subprocess.run(['xz', '--format=lzma', '-f', '-6', 'linux.bin'], check=True)
+        os.rename(f'linux.bin{linux_suffix}', 'linux.bin')
+
+    return linux_comp