From e51efc5983dcc119296f8e55cd5737a733e3f459 Mon Sep 17 00:00:00 2001 From: Sandeep Gundlupet Raju Date: Tue, 11 Jul 2023 15:39:16 -0600 Subject: dfx_user_dts: Add support for single dts input Add support for single dts and multiple dtsi use case. Also check for valid combination of dtsi and dts files in SRC_URI and following file combinations are not supported use case. 1. More than one '.dtsi' and zero '.dts' file. 2. More than one '.dts' and zero or more than one '.dtsi' file. Signed-off-by: Sandeep Gundlupet Raju Signed-off-by: Mark Hatle --- meta-xilinx-core/classes/dfx_user_dts.bbclass | 100 ++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 13 deletions(-) diff --git a/meta-xilinx-core/classes/dfx_user_dts.bbclass b/meta-xilinx-core/classes/dfx_user_dts.bbclass index 1f45cf12..2525a38e 100644 --- a/meta-xilinx-core/classes/dfx_user_dts.bbclass +++ b/meta-xilinx-core/classes/dfx_user_dts.bbclass @@ -26,8 +26,14 @@ FW_DIR ?= "" DTSI_PATH ?= "" DTBO_PATH ?= "" DT_FILES_PATH = "${S}/${DTSI_PATH}" +FIRMWARE_NAME_DT_FILE ?= "" +USER_DTS_FILE ?= "" + +FIRMWARE_NAME_DT_FILE[doc] = "DT file which has firmware-name device-tree property" +USER_DTS_FILE[doc] = "Final DTSI or DTS file which is used for packaging final DT overlay" python() { + import re soc_family = d.getVar("SOC_FAMILY") if "git://" in d.getVar("SRC_URI") or "https://" in d.getVar("SRC_URI"): d.setVar("S",'${WORKDIR}/git/'+d.getVar("FW_DIR")) @@ -38,9 +44,9 @@ python() { pdi_found = False # Required Inputs - if '.dtsi' in d.getVar("SRC_URI"): + if '.dtsi' in d.getVar("SRC_URI") or '.dts' in d.getVar("SRC_URI"): dtsi_found = True - d.setVar("DTSI_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.dtsi' in a][0].lstrip('file://'))) + d.setVar("DTSI_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.dtsi' in a or '.dts' in a][0].lstrip('file://'))) if '.dtbo' in d.getVar("SRC_URI"): dtbo_found = True @@ -64,6 +70,20 @@ python() { else: raise bb.parse.SkipRecipe("Need one '.dtsi' or one '.dtbo' file added to SRC_URI ") + # Check for valid combination of dtsi and dts files in SRC_URI + # Following file combinations are not supported use case. + # 1. More than one '.dtsi' and zero '.dts' file. + # 2. More than one '.dts' and zero or more than one '.dtsi'file . + pattern_dts = re.compile(r'.dts\b') + pattern_dtsi = re.compile(r'.dtsi\b') + dts_count = len([*re.finditer(pattern_dts, d.getVar('SRC_URI'))]) + dtsi_count = len([*re.finditer(pattern_dtsi, d.getVar("SRC_URI"))]) + + if dtsi_count > 1 and dts_count == 0: + raise bb.parse.SkipRecipe("Recipe has more than one '.dtsi' and zero '.dts' found, this is an unsupported use case") + elif dts_count > 1: + raise bb.parse.SkipRecipe("Recipe has more than one '.dts' and zero or more than one '.dtsi' found, this is an unsupported use case") + # Optional input if '.json' in d.getVar("SRC_URI"): d.setVar("JSON_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.json' in a][0].lstrip('file://'))) @@ -71,6 +91,32 @@ python() { if '.xclbin' in d.getVar("SRC_URI"): d.setVar("XCL_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.xclbin' in a][0].lstrip('file://'))) } + +# Function to get dts or dtsi file count. +def get_dt_count(d, dt_ext): + import glob + dt_count = sum(1 for f in glob.iglob((d.getVar('S') + (d.getVar('DTSI_PATH')) + '/*.' + dt_ext),recursive=True) if os.path.isfile(f)) + return dt_count + +# Function to search for dt firmware-name property in dts or dtsi file. +python find_firmware_file() { + import glob + pattern_fw = 'firmware-name' + search_count = 0 + for dt_files in glob.iglob((d.getVar('S') + (d.getVar('DTSI_PATH')) + '/*.dts*'),recursive=True): + with open(dt_files, "r") as f: + current_fd = f.read() + if pattern_fw in current_fd: + search_count += 1 + if search_count > 1: + bb.error("firmware-name dt property found in more than one dt files! Please fix the dts or dtsi file.") + break + else: + d.setVar('FIRMWARE_NAME_DT_FILE', os.path.basename(dt_files)) +} + +do_configure[prefuncs] += "find_firmware_file" + python do_configure() { import glob, re, shutil soc_family = d.getVar("SOC_FAMILY") @@ -80,8 +126,8 @@ python do_configure() { # Renaming firmware-name using $PN as bitstream/PDI will be renamed using # $PN when generating the bin/pdi file. - if '.dtsi' in d.getVar("SRC_URI"): - orig_dtsi = glob.glob(d.getVar('S')+ (d.getVar('DTSI_PATH') or '') + '/*.dtsi')[0] + if os.path.isfile(d.getVar('S') + (d.getVar('DTSI_PATH') or '') + '/' + d.getVar('FIRMWARE_NAME_DT_FILE')): + orig_dtsi = glob.glob(d.getVar('S')+ (d.getVar('DTSI_PATH') or '') + '/' + d.getVar('FIRMWARE_NAME_DT_FILE'))[0] new_dtsi = d.getVar('S') + '/pl.dtsi_firmwarename' with open(new_dtsi, 'w') as newdtsi: with open(orig_dtsi) as olddtsi: @@ -93,6 +139,8 @@ python do_configure() { shutil.move(new_dtsi,orig_dtsi) } +do_compile[prefuncs] += "find_firmware_file" + python devicetree_do_compile:append() { import glob, subprocess, shutil soc_family = d.getVar("SOC_FAMILY") @@ -101,7 +149,7 @@ python devicetree_do_compile:append() { # In case of dtbo as input, bbclass doesn't know if firmware-name is .bit or # .bit.bin format and corresponding file name. Hence we are not doing # bit.bin conversion. - if soc_family != 'versal' and glob.glob(d.getVar('S') + '/*.dtsi'): + if soc_family != 'versal' and glob.glob(d.getVar('S') + '/' + d.getVar('FIRMWARE_NAME_DT_FILE')): pn = d.getVar('PN') biffile = pn + '.bif' @@ -128,15 +176,37 @@ python devicetree_do_compile:append() { "and check bootgen_log.txt" % (d.getVar('B') + '/' + pn + '.bit.bin')) } +# If user inputs both dtsi and dts files then device-tree will generate dtbo +# files for each dt file, Hence to package the firmware pick the right user dt +# overlay file. +python find_user_dts_overlay_file() { + import glob + dtbo_count = sum(1 for f in glob.iglob((d.getVar('S') + '/*.dtbo'),recursive=True) if os.path.isfile(f)) + # Skip if input file is dtbo in SRC_URI + if not dtbo_count: + dts_count = get_dt_count(d, 'dts') + dtsi_count = get_dt_count(d, 'dtsi') + if dtsi_count == 1 and dts_count == 0: + dts_file =glob.glob(d.getVar('S')+ (d.getVar('DTSI_PATH') or '') + '/*.dtsi')[0] + elif dtsi_count > 1 and dts_count == 1: + dts_file = glob.glob(d.getVar('S')+ (d.getVar('DTSI_PATH') or '') + '/*.dts')[0] + + d.setVar('USER_DTS_FILE', os.path.splitext(os.path.basename(dts_file))[0]) +} + +do_install[prefuncs] += "find_user_dts_overlay_file" + do_install() { install -d ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ # In case of dtbo as input, dtbo will be copied from directly from ${S} # In case of dtsi as input, dtbo will be copied from directly from ${B} - if [ -f ${S}/*.dtbo ]; then + if [ `ls ${S}/*.dtbo | wc -l` -eq 1 ]; then install -Dm 0644 ${S}/*.dtbo ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ - elif [ -f ${B}/*.dtbo ]; then - install -Dm 0644 ${B}/*.dtbo ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.dtbo + elif [ `ls ${S}/*.dtbo | wc -l` -gt 1 ]; then + bbfatal "Multiple DTBO found, use the right DTBO in SRC_URI from the following:\n$(basename -a ${S}/*.dtbo)" + elif [ -f ${B}/${USER_DTS_FILE}.dtbo ]; then + install -Dm 0644 ${B}/${USER_DTS_FILE}.dtbo ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.dtbo else bbfatal "A dtbo ending '.dtbo' expected but not found" fi @@ -144,19 +214,23 @@ do_install() { if [ "${SOC_FAMILY}" == "versal" ]; then # In case of dtbo as input, pdi will be copied from directly from ${S} # without renaming the pdi name to ${PN}.pdi - if [ -f ${S}/*.pdi ] && [ -f ${S}/*.dtbo ]; then + if [ `ls ${S}/*.pdi | wc -l` -eq 1 ] && [ `ls ${S}/*.dtbo | wc -l` -eq 1 ]; then install -Dm 0644 ${S}/*.pdi ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ - elif [ -f ${S}/*.pdi ] && [ -f ${B}/*.dtbo ]; then + elif [ `ls ${S}/*.pdi | wc -l` -gt 1 ]; then + bbfatal "Multiple PDI found, use the right PDI in SRC_URI from the following:\n$(basename -a ${S}/*.pdi)" + elif [ `ls ${S}/*.pdi | wc -l` -eq 1 ] && [ -f ${B}/${USER_DTS_FILE}.dtbo ]; then install -Dm 0644 ${S}/*.pdi ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.pdi else bbfatal "A PDI file with '.pdi' expected but not found" fi else - # In case of dtbo as input, .bit or .bit.in will be copied from directly + # In case of dtbo as input, .bit or .bit.bin will be copied from directly # from ${S} without renaming the .bit name to ${PN}.bit.bin - if [ -f ${S}/*.bit* ] && [ -f ${S}/*.dtbo ]; then + if [ `ls ${S}/*.bit* | wc -l` -eq 1 ] && [ `ls ${S}/*.dtbo | wc -l` -eq 1 ]; then install -Dm 0644 ${S}/*.bit* ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ - elif [ -f ${B}/${PN}.bit.bin ] && [ -f ${B}/*.dtbo ]; then + elif [ `ls ${S}/*.bit* | wc -l` -gt 1 ]; then + bbfatal "Multiple bit/bit.bin found, use the right bit/bit.bin in SRC_URI from the following:\n$(basename -a ${S}/*.bit*)" + elif [ -f ${B}/${PN}.bit.bin ] && [ -f ${B}/${USER_DTS_FILE}.dtbo ]; then install -Dm 0644 ${B}/${PN}.bit.bin ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.bit.bin else bbfatal "A bitstream file with '.bit' or '.bit.bin' expected but not found" -- cgit v1.2.3-54-g00ecf