From 84a792a2accb94d792bfe43f20f407b0c90fbffa Mon Sep 17 00:00:00 2001 From: Baikal Electronics Date: Mon, 26 Sep 2022 03:03:39 +0300 Subject: [PATCH] Add functions for building fit-image --- .../images/core-image-minimal.bbappend | 2 +- .../recipes-kernel/linux/linux-baikal_5.15.bb | 1 + .../recipes-kernel/linux/linux-fit.inc | 371 ++++++++++++++++++ .../recipes-kernel/linux/linux-umulti.inc | 76 ++++ 4 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 meta-baikal/recipes-kernel/linux/linux-fit.inc create mode 100644 meta-baikal/recipes-kernel/linux/linux-umulti.inc diff --git a/meta-baikal/recipes-core/images/core-image-minimal.bbappend b/meta-baikal/recipes-core/images/core-image-minimal.bbappend index 55efb8c..3e58b35 100644 --- a/meta-baikal/recipes-core/images/core-image-minimal.bbappend +++ b/meta-baikal/recipes-core/images/core-image-minimal.bbappend @@ -1,4 +1,4 @@ -IMAGE_ROOTFS_SIZE = "16384" +IMAGE_ROOTFS_SIZE = "32768" IMAGE_NAME = "${PN}-baikal" RDEPENDS:append = " kernel-modules" diff --git a/meta-baikal/recipes-kernel/linux/linux-baikal_5.15.bb b/meta-baikal/recipes-kernel/linux/linux-baikal_5.15.bb index f564546..3d43ae8 100644 --- a/meta-baikal/recipes-kernel/linux/linux-baikal_5.15.bb +++ b/meta-baikal/recipes-kernel/linux/linux-baikal_5.15.bb @@ -1,4 +1,5 @@ require recipes-kernel/linux/linux-baikal.inc +require recipes-kernel/linux/linux-umulti.inc inherit externalsrc inherit kernel-uimage diff --git a/meta-baikal/recipes-kernel/linux/linux-fit.inc b/meta-baikal/recipes-kernel/linux/linux-fit.inc new file mode 100644 index 0000000..a1ec87c --- /dev/null +++ b/meta-baikal/recipes-kernel/linux/linux-fit.inc @@ -0,0 +1,371 @@ +inherit kernel-uboot kernel-artifact-names uboot-sign + +DEPENDS:append = " u-boot-tools-native dtc-native" + +FIT_GENERATE_KEYS = "1" +UBOOT_SIGN_ENABLE = "1" + +FIT_DESC ?= "Kernel fitImage for ${DISTRO_NAME}/${PV}/${MACHINE}" +FIT_CONF_PREFIX ?= "conf-" +FIT_HASH_ALG ?= "sha1" +FIT_SIGN_ALG ?= "rsa2048" + +UBOOT_SIGN_KEYDIR = "keys" +UBOOT_SIGN_KEYNAME = "baikal" +UBOOT_SIGN_IMG_KEYNAME = "baikal" +UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" + +fitimage_emit_fit_header() { + cat << EOF >> $1 +/dts-v1/; + +/ { + description = "${FIT_DESC}"; + #address-cells = <1>; +EOF +} + +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 +} + +fitimage_emit_section_kernel() { + + kernel_csum="crc32" + kernel_sign_algo="${FIT_SIGN_ALG}" + kernel_sign_keyname="${UBOOT_SIGN_IMG_KEYNAME}" + + ENTRYPOINT="${UBOOT_ENTRYPOINT}" + if [ -n "${UBOOT_ENTRYSYMBOL}" ]; then + cd ${B} + ENTRYPOINT=`${HOST_PREFIX}nm vmlinux | \ + awk '$3=="${UBOOT_ENTRYSYMBOL}" {print "0x"$1;exit}'` + cd - + fi + + cat << EOF >> $1 + kernel-$2 { + description = "Linux kernel"; + data = /incbin/("$3"); + type = "${UBOOT_MKIMAGE_KERNEL_TYPE}"; + arch = "${UBOOT_ARCH}"; + os = "linux"; + compression = "$4"; + 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 +} + +fitimage_emit_section_dtb() { + + dtb_csum="crc32" + 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"; + data = /incbin/("$3"); + type = "flat_dt"; + arch = "${UBOOT_ARCH}"; + compression = "none"; + $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 +} + +fitimage_emit_section_ramdisk() { + + ramdisk_csum="crc32" + 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}"; + data = /incbin/("$3"); + type = "ramdisk"; + arch = "${UBOOT_ARCH}"; + os = "linux"; + compression = "$4"; + $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 +} + +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" + config_id="$5" + default_flag="$6" + + # Test if we have any DTBs at all + sep="" + conf_desc="" + conf_node="${FIT_CONF_PREFIX}" + kernel_line="" + fdt_line="" + ramdisk_line="" + default_line="" + + # conf node name is selected based on dtb ID if it is present, + # otherwise its selected based on kernel ID + conf_node=$conf_node$5 + + 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\";" + fi + + if [ -n "$ramdisk_id" ]; then + conf_desc="$conf_desc${sep}ramdisk" + sep=", " + ramdisk_line="ramdisk = \"ramdisk-$ramdisk_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 + default_line="default = \"${FIT_CONF_PREFIX}$dtb_image\";" + else + default_line="default = \"${FIT_CONF_PREFIX}$kernel_id\";" + fi + fi + + cat << EOF >> $its_file + $default_line + $conf_node { + description = "$conf_desc"; + $kernel_line + $fdt_line + $ramdisk_line + hash-1 { + algo = "$conf_csum"; + }; +EOF + + if [ -n "$conf_sign_keyname" ] ; then + cat << EOF >> $its_file + signature-1 { + algo = "$conf_csum,$conf_sign_algo"; + key-name-hint = "$conf_sign_keyname"; + }; +EOF + fi + + cat << EOF >> $its_file + }; +EOF +} + +fitimage_assemble() { + rm -f $1 + + fitimage_emit_fit_header $1 + + fitimage_emit_section_maint $1 imagestart + + fitimage_emit_section_kernel $1 1 "${BAIKAL_KERNEL}" "${BAIKAL_COMP_ALG}" + + dtbcount=1 + fitimage_emit_section_dtb $1 ${MACHINE}.dtb ${MACHINE}.dtb + + initramfs_path="${BAIKAL_INITRAMFS}" + if [ -e "$initramfs_path" ]; then + bbnote "Found initramfs image: $initramfs_path" + fitimage_emit_section_ramdisk $1 1 "$initramfs_path" "${BAIKAL_COMP_ALG}" + break + else + bbfatal "Did not find initramfs image: $initramfs_path" + fi + + initrd_path="${BAIKAL_INITRD}" + if [ -e "$initrd_path" ]; then + bbnote "Found initramfs image: $initrd_path" + fitimage_emit_section_ramdisk $1 2 "$initrd_path" "${BAIKAL_COMP_ALG}" + break + else + bbfatal "Did not find initramfs image: $initrd_path" + fi + + fitimage_emit_section_maint $1 sectend + + fitimage_emit_section_maint $1 confstart + + fitimage_emit_section_config $1 1 1 2 1 1 + fitimage_emit_section_config $1 1 1 1 2 0 + + fitimage_emit_section_maint $1 sectend + + fitimage_emit_section_maint $1 fitend + + ${UBOOT_MKIMAGE} \ + ${@'-D "${UBOOT_MKIMAGE_DTCOPTS}"' if len('${UBOOT_MKIMAGE_DTCOPTS}') else ''} \ + -f $1 $2 + + if [ "x${UBOOT_SIGN_ENABLE}" = "x1" ] ; then + add_key_to_u_boot="" + if [ -n "${UBOOT_DTB_BINARY}" ]; then + add_key_to_u_boot="-K ${UBOOT_DTB_BINARY}" + fi + ${UBOOT_MKIMAGE_SIGN} \ + ${@'-D "${UBOOT_MKIMAGE_DTCOPTS}"' if len('${UBOOT_MKIMAGE_DTCOPTS}') else ''} \ + -F -k "${UBOOT_SIGN_KEYDIR}" \ + $add_key_to_u_boot \ + -r $2 \ + ${UBOOT_MKIMAGE_SIGN_ARGS} + fi +} + +do_assemble_fitimage_initramfs() { + cd ${BAIKAL_IMAGES} + do_baikal_generate_rsa_keys + if [ -n "${INITRAMFS_IMAGE}" ]; then + fitimage_assemble umulti.its uMulti 1 + fi +} + +do_baikal_generate_rsa_keys() { + if [ "${UBOOT_SIGN_ENABLE}" = "0" ] && [ "${FIT_GENERATE_KEYS}" = "1" ]; then + bbwarn "FIT_GENERATE_KEYS is set to 1 even though UBOOT_SIGN_ENABLE is set to 0. The keys will not be generated as they won't be used." + fi + + if [ "${UBOOT_SIGN_ENABLE}" = "1" ] && [ "${FIT_GENERATE_KEYS}" = "1" ]; then + + # Generate keys to sign configuration nodes, only if they don't already exist + if [ ! -f "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_KEYNAME}".key ] || \ + [ ! -f "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_KEYNAME}".crt ]; then + + # make directory if it does not already exist + mkdir -p "${UBOOT_SIGN_KEYDIR}" + + bbnote "Generating RSA private key for signing fitImage" + openssl genrsa ${FIT_KEY_GENRSA_ARGS} -out \ + "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_KEYNAME}".key \ + "${FIT_SIGN_NUMBITS}" + + bbnote "Generating certificate for signing fitImage" + openssl req ${FIT_KEY_REQ_ARGS} "${FIT_KEY_SIGN_PKCS}" \ + -key "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_KEYNAME}".key \ + -out "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_KEYNAME}".crt + fi + + # Generate keys to sign image nodes, only if they don't already exist + if [ ! -f "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_IMG_KEYNAME}".key ] || \ + [ ! -f "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_IMG_KEYNAME}".crt ]; then + + # make directory if it does not already exist + mkdir -p "${UBOOT_SIGN_KEYDIR}" + + bbnote "Generating RSA private key for signing fitImage" + openssl genrsa ${FIT_KEY_GENRSA_ARGS} -out \ + "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_IMG_KEYNAME}".key \ + "${FIT_SIGN_NUMBITS}" + + bbnote "Generating certificate for signing fitImage" + openssl req ${FIT_KEY_REQ_ARGS} "${FIT_KEY_SIGN_PKCS}" \ + -key "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_IMG_KEYNAME}".key \ + -out "${UBOOT_SIGN_KEYDIR}/${UBOOT_SIGN_IMG_KEYNAME}".crt + fi + fi +} diff --git a/meta-baikal/recipes-kernel/linux/linux-umulti.inc b/meta-baikal/recipes-kernel/linux/linux-umulti.inc new file mode 100644 index 0000000..5b850f8 --- /dev/null +++ b/meta-baikal/recipes-kernel/linux/linux-umulti.inc @@ -0,0 +1,76 @@ +require recipes-kernel/linux/linux-fit.inc + +UBOOT_RD_LOADADDRESS ?= "0x80000000" +UBOOT_RD_ENTRYPOINT ?= "0x80000000" + +UBOOT_RDI_LOADADDRESS ?= "0x86000000" +UBOOT_RDI_ENTRYPOINT ?= "0x86000000" + +BAIKAL_COMP_ALG ?= "lzma" +BAIKAL_COMP_ALG_EXTENSION ?= ".lzma" + +BAIKAL_KERNEL = "${MACHINE}.vmlinux.bin${BAIKAL_COMP_ALG_EXTENSION}" +BAIKAL_INITRAMFS = "initramfs${BAIKAL_COMP_ALG_EXTENSION}" +BAIKAL_INITRD = "initrd${BAIKAL_COMP_ALG_EXTENSION}" + +UBOOT_DTB_BINARY = "${WORKDIR}/baikal.dtb" +UBOOT_DTS_FILE = "${WORKDIR}/baikal.dts" + +baikal_do_uinitramfs () { + uboot-mkimage -A ${UBOOT_ARCH} -O linux -T ramdisk -C ${BAIKAL_COMP_ALG} \ + -a ${UBOOT_RD_LOADADDRESS} -e ${UBOOT_RD_ENTRYPOINT} \ + -d "${BAIKAL_IMAGES}/initramfs${BAIKAL_COMP_ALG_EXTENSION}" \ + -n "-" \ + ${BAIKAL_IMAGES}/${MACHINE}.uInitramfs +} + +baikal_do_uinitrd () { + uboot-mkimage -A ${UBOOT_ARCH} -O linux -T ramdisk -C ${BAIKAL_COMP_ALG} \ + -a ${UBOOT_RDI_LOADADDRESS} -e ${UBOOT_RDI_ENTRYPOINT} \ + -d "${BAIKAL_IMAGES}/initrd${BAIKAL_COMP_ALG_EXTENSION}" \ + -n "+" \ + ${BAIKAL_IMAGES}/${MACHINE}.uInitrd +} + +baikal_do_ubootdtb () { + cat << EOF >> ${UBOOT_DTS_FILE} +/dts-v1/; + +/ { + model = "Keys"; + compatible = "be,baikal-t"; + + signature { + key-baikal { + required = "conf"; + algo = "sha1,rsa2048"; + key-name-hint = "baikal"; + sign-images = "fdt", "kernel"; + }; + }; +}; +EOF + dtc -I dts -O dtb ${UBOOT_DTS_FILE} -o ${UBOOT_DTB_BINARY} +} + +python baikal_entrysymbol () { + sys_map = d.getVar('B') + 'System.map' + with open(sys_map) as smap: + ln = smap.readline() + d.setVar('UBOOT_LOADADDRESS', '0x' + ln[8:16]) + while True: + ln = smap.readline().split() + if ln[2] != 'kernel_entry': + continue + d.setVar('UBOOT_ENTRYPOINT', '0x' + ln[0][8:16]) + break +} + +baikal_do_umulti () { + baikal_do_ubootdtb + do_assemble_fitimage_initramfs +} + +do_deploy[prefuncs] += "baikal_entrysymbol" + +do_deploy[prefuncs] += "baikal_do_umulti" -- 2.39.5