aboutsummaryrefslogtreecommitdiffstats
path: root/meta-xilinx-core/classes
diff options
context:
space:
mode:
Diffstat (limited to 'meta-xilinx-core/classes')
-rw-r--r--meta-xilinx-core/classes/amd_spi_image.bbclass142
-rw-r--r--meta-xilinx-core/classes/dfx_user_dts.bbclass267
-rw-r--r--meta-xilinx-core/classes/fpgamanager_custom.bbclass24
-rw-r--r--meta-xilinx-core/classes/gen-machine-conf.bbclass6
-rw-r--r--meta-xilinx-core/classes/image-types-xilinx-qemu.bbclass59
-rw-r--r--meta-xilinx-core/classes/image-wic-utils.bbclass54
-rw-r--r--meta-xilinx-core/classes/kernel-simpleimage.bbclass35
-rw-r--r--meta-xilinx-core/classes/qemuboot-xilinx.bbclass140
-rw-r--r--meta-xilinx-core/classes/xilinx-deprecated.bbclass18
-rw-r--r--meta-xilinx-core/classes/xilinx-fetch-restricted.bbclass35
-rw-r--r--meta-xilinx-core/classes/xilinx-microblaze.bbclass11
-rw-r--r--meta-xilinx-core/classes/xilinx-platform-init.bbclass14
-rw-r--r--meta-xilinx-core/classes/xilinx-testimage.bbclass10
-rw-r--r--meta-xilinx-core/classes/xilinx-vars.bbclass32
14 files changed, 847 insertions, 0 deletions
diff --git a/meta-xilinx-core/classes/amd_spi_image.bbclass b/meta-xilinx-core/classes/amd_spi_image.bbclass
new file mode 100644
index 00000000..ed4c1f87
--- /dev/null
+++ b/meta-xilinx-core/classes/amd_spi_image.bbclass
@@ -0,0 +1,142 @@
+#
+# Copyright (C) 2023, Advanced Micro Devices, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: MIT
+#
+
+QSPI_SIZE ?= "0x2280000"
+
+# Register values
+IDN_REG ?= "0x4D554241"
+VERSION_REG ?= "0x1"
+LENGTH_REG ?= "0x4"
+PERSISTENT_REG ?= "0x01010000"
+
+# QSPI Offsets
+IMAGE_SELECTOR_OFFSET ?= "0x0"
+IMAGE_SELECTOR_BACKUP_OFFSET ?= "0x80000"
+PERSISTENT_REG_OFFSET ?= "0x100000"
+PERSISTENT_REG_BACKUP_OFFSET ?= "0x120000"
+IMAGE_A_OFFSET ?= "0x200000"
+IMAGE_A_IMGSEL_OFFSET ?= "0xF00000"
+IMAGE_B_OFFSET ?= "0xF80000"
+IMAGE_B_IMGSEL_OFFSET ?= "0x1C80000"
+IMAGE_RCVRY_OFFSET ?= "0x1E00000"
+IMAGE_RCVRY_BACKUP_OFFSET ?= "0x2000000"
+VERSION_OFFSET ?= "0x2240000"
+CHECKSUM_OFFSET ?= "0x2250000"
+
+def generate_spi_image(d):
+
+ import io
+ import hashlib
+ import time
+
+ qspi_size = int(d.getVar("QSPI_SIZE") or '0', 0)
+ int(d.getVar("QSPI_SIZE") or '0', 0)
+
+ # Register values
+ idn_reg = int(d.getVar("IDN_REG") or '0', 0)
+ version_reg = int(d.getVar("VERSION_REG") or '0', 0)
+ length_reg = int(d.getVar("LENGTH_REG") or '0', 0)
+ persistent_reg = int(d.getVar("PERSISTENT_REG") or '0', 0)
+
+ # QSPI Offsets
+ image_selector_offset = int(d.getVar("IMAGE_SELECTOR_OFFSET") or '0', 0)
+ image_selector_backup_offset = int(d.getVar("IMAGE_SELECTOR_BACKUP_OFFSET") or '0', 0)
+ persistent_reg_offset = int(d.getVar("PERSISTENT_REG_OFFSET") or '0', 0)
+ persistent_reg_backup_offset = int(d.getVar("PERSISTENT_REG_BACKUP_OFFSET") or '0', 0)
+ image_a_offset = int(d.getVar("IMAGE_A_OFFSET") or '0', 0)
+ image_a_imgsel_offset = int(d.getVar("IMAGE_A_IMGSEL_OFFSET") or '0', 0)
+ image_b_offset = int(d.getVar("IMAGE_B_OFFSET") or '0', 0)
+ image_b_imgsel_offset = int(d.getVar("IMAGE_B_IMGSEL_OFFSET") or '0', 0)
+ image_rcvry_offset = int(d.getVar("IMAGE_RCVRY_OFFSET") or '0', 0)
+ image_rcvry_backup_offset = int(d.getVar("IMAGE_RCVRY_BACKUP_OFFSET") or '0', 0)
+ version_offset = int(d.getVar("VERSION_OFFSET") or '0', 0)
+ checksum_offset = int(d.getVar("CHECKSUM_OFFSET") or '0', 0)
+
+ # QSPI data
+ qspi_data = io.BytesIO()
+ qspi_data.write(b'\xFF' * qspi_size)
+
+ # Image Selector - Primary, Backup, Image A and Image B
+ imgsel_file = d.getVar("DEPLOY_DIR_IMAGE")+"/imgsel-"+d.getVar("MACHINE")+".bin"
+ try:
+ with open(imgsel_file, "rb") as il:
+ imgsel = il.read(-1)
+ except OSError as err:
+ bb.fatal("Unable to open imgsel file: " + str(err))
+
+ qspi_data.seek(image_selector_offset)
+ qspi_data.write(imgsel)
+ qspi_data.seek(image_selector_backup_offset)
+ qspi_data.write(imgsel)
+ qspi_data.seek(image_a_imgsel_offset)
+ qspi_data.write(imgsel)
+ qspi_data.seek(image_b_imgsel_offset)
+ qspi_data.write(imgsel)
+
+ # Persistent Registers - Primary and Backup
+ p_reg = [idn_reg, version_reg, length_reg, persistent_reg, \
+ image_a_offset, image_b_offset, image_rcvry_offset]
+ checksum = 0xffffffff - (0xffffffff & sum(p_reg))
+ p_reg.insert(3, checksum)
+
+ qspi_data.seek(persistent_reg_offset)
+ for value in p_reg:
+ qspi_data.write(value.to_bytes(4, byteorder="little"))
+
+ qspi_data.seek(persistent_reg_backup_offset)
+ for value in p_reg:
+ qspi_data.write(value.to_bytes(4, byteorder="little"))
+
+ # Image A and B - boot.bin
+ try:
+ with open(d.getVar("DEPLOY_DIR_IMAGE")+"/boot.bin", "rb") as bo:
+ bootbin = bo.read(-1)
+ except OSError as err:
+ bb.fatal("Unable to open boot.bin file: " + str(err))
+
+ qspi_data.seek(image_a_offset)
+ qspi_data.write(bootbin)
+ qspi_data.seek(image_b_offset)
+ qspi_data.write(bootbin)
+
+ # Recovery Image & Recovery Image Backup
+ imgrcry_file = d.getVar("DEPLOY_DIR_IMAGE")+"/imgrcry-"+d.getVar("MACHINE")+".bin"
+ try:
+ with open(imgrcry_file, "rb") as iy:
+ imgrcry = iy.read(-1)
+ except OSError as err:
+ bb.fatal("Unable to open imgrcry file: " + str(err))
+
+ qspi_data.seek(image_rcvry_offset)
+ qspi_data.write(imgrcry)
+ qspi_data.seek(image_rcvry_backup_offset)
+ qspi_data.write(imgrcry)
+
+ # Version string and checksum
+ version = d.getVar("QSPI_IMAGE_VERSION")
+ date = time.strftime("%m%d%H%M")
+ machine = d.getVar("MACHINE")[:3]
+ image_name = d.getVar("QSPI_IMAGE_NAME")
+
+ qspi_version = f"{image_name}-{machine}-v{version}-{date}\x00"
+ qspi_data.seek(version_offset)
+ qspi_data.write(qspi_version.encode())
+
+ qspi_sha = hashlib.sha256(qspi_data.getbuffer())
+ qspi_data.seek(checksum_offset)
+ qspi_data.write(qspi_sha.digest())
+
+ # Write the QSPI data to file
+ with open(d.getVar("B") + "/" + d.getVar("IMAGE_NAME") + ".bin", "wb") as sq:
+ sq.write(qspi_data.getbuffer())
+
+do_compile[depends] += "virtual/boot-bin:do_deploy virtual/imgsel:do_deploy virtual/imgrcry:do_deploy"
+
+python amd_spi_image_do_compile() {
+ generate_spi_image(d)
+}
+
+EXPORT_FUNCTIONS do_compile
diff --git a/meta-xilinx-core/classes/dfx_user_dts.bbclass b/meta-xilinx-core/classes/dfx_user_dts.bbclass
new file mode 100644
index 00000000..4404aa05
--- /dev/null
+++ b/meta-xilinx-core/classes/dfx_user_dts.bbclass
@@ -0,0 +1,267 @@
+# This bbclass is inherited by flat, DFx Static and DFx RP firmware recipes.
+# dfx_user_dts.bbclass expects user to generate pl dtsi for flat, DFx Static
+# and DFx RP xsa outside of yocto.
+
+inherit devicetree
+
+DEPENDS = "dtc-native bootgen-native"
+
+# recipes that inherit from this class need to use an appropriate machine
+# override for COMPATIBLE_MACHINE to build successfully; don't allow building
+# for microblaze MACHINE
+COMPATIBLE_MACHINE ?= "^$"
+COMPATIBLE_MACHINE:microblaze = "^$"
+
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+
+PROVIDES = ""
+
+do_fetch[cleandirs] = "${B}"
+
+DT_PADDING_SIZE = "0x1000"
+BOOTGEN_FLAGS ?= " -arch ${SOC_FAMILY} -w ${@bb.utils.contains('SOC_FAMILY','zynqmp','','-process_bitstream bin',d)}"
+
+S ?= "${WORKDIR}"
+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"))
+ else:
+ dtsi_found = False
+ dtbo_found = False
+ bit_found = False
+ bin_found = False
+ pdi_found = False
+
+ # Required Inputs
+ 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 or '.dts' in a][0].lstrip('file://')))
+
+ if '.dtbo' in d.getVar("SRC_URI"):
+ dtbo_found = True
+ d.setVar("DTBO_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.dtbo' in a][0].lstrip('file://')))
+
+ if '.bit' in d.getVar("SRC_URI") and soc_family != "versal":
+ bit_found = True
+ d.setVar("BIT_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.bit' in a][0].lstrip('file://')))
+
+ if '.bin' in d.getVar("SRC_URI") and soc_family != "versal":
+ bin_found = True
+ d.setVar("BIT_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.bin' in a][0].lstrip('file://')))
+
+ if '.pdi' in d.getVar("SRC_URI") and soc_family == "versal":
+ pdi_found = True
+ d.setVar("PDI_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.pdi' in a][0].lstrip('file://')))
+
+ # Check for valid combination of input files in SRC_URI
+ if dtsi_found or dtbo_found:
+ bb.debug(2, "dtsi or dtbo found in SRC_URI")
+ if bit_found or pdi_found or bin_found:
+ bb.debug(2, "bitstream or pdi found in SRC_URI")
+ elif bit_found and bin_found:
+ raise bb.parse.SkipRecipe("Both '.bit' and '.bin' file found in SRC_URI, either .bit or .bin file is supported but not both.")
+ else:
+ raise bb.parse.SkipRecipe("Need one '.bit' or one '.pdi' file added to SRC_URI ")
+ 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://')))
+
+ 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")
+
+ if bb.utils.contains('MACHINE_FEATURES', 'fpga-overlay', False, True, d):
+ bb.warn("Using fpga-manager.bbclass requires fpga-overlay MACHINE_FEATURE to be enabled")
+
+ # Renaming firmware-name using $PN as bitstream/PDI will be renamed using
+ # $PN when generating the bin/pdi file.
+ 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:
+ for line in olddtsi:
+ if soc_family == 'versal':
+ newdtsi.write(re.sub('firmware-name.*\".*\"','firmware-name = \"'+d.getVar('PN')+'.pdi\"',line))
+ else:
+ newdtsi.write(re.sub('firmware-name.*\".*\"','firmware-name = \"'+d.getVar('PN')+'.bit.bin\"',line))
+ 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")
+
+ dtbo_count = sum(1 for f in glob.iglob((d.getVar('S') + '/*.dtbo'),recursive=True) if os.path.isfile(f))
+
+ # Skip devicetree do_compile task if input file is dtbo in SRC_URI
+ if not dtbo_count:
+ # Convert .bit to bit.bin format only if dtsi is input.
+ # 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') + '/' + d.getVar('FIRMWARE_NAME_DT_FILE')):
+ pn = d.getVar('PN')
+ biffile = pn + '.bif'
+
+ with open(biffile, 'w') as f:
+ f.write('all:\n{\n\t' + glob.glob(d.getVar('S')+(d.getVar('BIT_PATH') or '') + '/*.bit')[0] + '\n}')
+
+ bootgenargs = ["bootgen"] + (d.getVar("BOOTGEN_FLAGS") or "").split()
+ bootgenargs += ["-image", biffile, "-o", pn + ".bit.bin"]
+ subprocess.run(bootgenargs, check = True)
+
+ # In Zynq7k using both "-process_bitstream bin" and "-o" in bootgen flag,
+ # to convert bit file to bin format, "-o" option will not be effective
+ # and generated output file name is ${S}+${BIT_PATH}/<bit_file_name>.bit.bin
+ # file, Hence we need to rename this file from <bit_file_name>.bit.bin to
+ # ${PN}.bit.bin which matches the firmware name in dtbo and move
+ # ${PN}.bit.bin to ${B} directory.
+ if soc_family == 'zynq':
+ src_bitbin_file = glob.glob(d.getVar('S') + (d.getVar('BIT_PATH') or '') + '/*.bit.bin')[0]
+ dst_bitbin_file = d.getVar('B') + '/' + pn + '.bit.bin'
+ shutil.move(src_bitbin_file, dst_bitbin_file)
+
+ if not os.path.isfile(pn + ".bit.bin"):
+ bb.fatal("Couldn't find %s file, Enable '-log trace' in BOOTGEN_FLAGS" \
+ "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 >=0 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 [ `ls ${S}/*.dtbo | wc -l` -eq 1 ]; then
+ install -Dm 0644 ${S}/*.dtbo ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/
+ 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
+
+ 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 [ `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 [ `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 .bin will be copied from directly
+ # from ${S} without renaming the .bit/.bin name to ${PN}.bit/${PN}.bin
+ # if more than one .bit/.bin file is found then fail the task.
+ if [ `ls ${S}/*.bit | wc -l` -gt 1 ]; then
+ bbfatal "Multiple .bit found, use the right .bit in SRC_URI from the following:\n$(basename -a ${S}/*.bit)"
+ elif [ `ls ${S}/*.bin | wc -l` -gt 1 ]; then
+ bbfatal "Multiple .bin found, use the right .bin in SRC_URI from the following:\n$(basename -a ${S}/*.bin)"
+ elif [ `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 [ `ls ${S}/*.bin | wc -l` -eq 1 ] && [ `ls ${S}/*.dtbo | wc -l` -eq 1 ]; then
+ install -Dm 0644 ${S}/*.bin ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/
+ 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 '.bin' expected but not found"
+ fi
+ fi
+
+ if ls ${S}/${XCL_PATH}/*.xclbin >/dev/null 2>&1; then
+ install -Dm 0644 ${S}/${XCL_PATH}/*.xclbin ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.xclbin
+ fi
+
+ if [ -f ${S}/${JSON_PATH}/shell.json ] || [ -f ${S}/${JSON_PATH}/accel.json ]; then
+ install -Dm 0644 ${S}/${JSON_PATH}/*.json ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/
+ fi
+}
+
+do_deploy[noexec] = "1"
+
+FILES:${PN} += "${nonarch_base_libdir}/firmware/xilinx/${PN}"
diff --git a/meta-xilinx-core/classes/fpgamanager_custom.bbclass b/meta-xilinx-core/classes/fpgamanager_custom.bbclass
new file mode 100644
index 00000000..8c8997a1
--- /dev/null
+++ b/meta-xilinx-core/classes/fpgamanager_custom.bbclass
@@ -0,0 +1,24 @@
+# This class inherits dfx_user_dts.bbclass for below use cases.
+# Zynq-7000 and ZynqMP: Full bitstream loading.
+# ZynqMP: DFx Static and Partial bitstream loading.
+# Versal: DFx Static and Parial pdi loading.
+# Versal: Full PDI loading.
+
+inherit dfx_user_dts
+
+python fpgamanager_warn_msg () {
+ if not d.getVar("FPGAMANAGER_NO_WARN"):
+ arch = d.getVar('SOC_FAMILY')
+ pn = d.getVar('PN')
+ warn_msg = 'Users should start using dfx_user_dts bbclass for '
+ if arch == 'zynq':
+ warn_msg += 'Zynq-7000 Full bitstream loading use case.'
+ elif arch == 'zynqmp':
+ warn_msg += 'ZynqMP Full or DFx Static or DFx Partial bitstream loading use case.'
+ elif arch == 'versal':
+ warn_msg += 'Versal DFx Static or DFx Partial or Full PDI loading use case.'
+
+ bb.warn("Recipe %s has inherited fpgamanager_custom bbclass which will be deprecated in 2024.1 release. \n%s" % (pn, warn_msg))
+}
+
+do_install[postfuncs] += "fpgamanager_warn_msg" \ No newline at end of file
diff --git a/meta-xilinx-core/classes/gen-machine-conf.bbclass b/meta-xilinx-core/classes/gen-machine-conf.bbclass
new file mode 100644
index 00000000..25960cd1
--- /dev/null
+++ b/meta-xilinx-core/classes/gen-machine-conf.bbclass
@@ -0,0 +1,6 @@
+#Add scripts path with the tools to PATH to be able to use from eSDK
+sdk_ext_postinst:append() {
+ if [ -d $target_sdk_dir/layers/meta-xilinx/meta-xilinx-core/gen-machine-conf ]; then
+ echo "export PATH=$target_sdk_dir/layers/meta-xilinx/meta-xilinx-core/gen-machine-conf:\$PATH" >> $env_setup_script
+ fi
+}
diff --git a/meta-xilinx-core/classes/image-types-xilinx-qemu.bbclass b/meta-xilinx-core/classes/image-types-xilinx-qemu.bbclass
new file mode 100644
index 00000000..b4de5ee1
--- /dev/null
+++ b/meta-xilinx-core/classes/image-types-xilinx-qemu.bbclass
@@ -0,0 +1,59 @@
+# Define the 'qemu-sd' conversion type
+#
+# This conversion type pads any image to the 512K boundary to ensure that the
+# image file can be used directly with QEMU's SD emulation which requires the
+# block device to match that of valid SD card sizes (which are multiples of
+# 512K).
+
+CONVERSIONTYPES:append = " qemu-sd qemu-sd-fatimg"
+CONVERSION_CMD:qemu-sd () {
+ cp ${IMGDEPLOYDIR}/${IMAGE_NAME}.${type} ${IMGDEPLOYDIR}/${IMAGE_NAME}.${type}.qemu-sd
+ # Get the wic.qemu-sd file size
+ file_size=`stat -c '%s' ${IMGDEPLOYDIR}/${IMAGE_NAME}.${type}.qemu-sd`
+ powerof2=1
+ file_size=${file_size%.*}
+ # Get the next power of 2 value for the image size value
+ while [ ${powerof2} -lt ${file_size} ]; do
+ powerof2=$(expr $powerof2 \* 2)
+ done
+ # Resize the image using qemu-img
+ qemu-img resize -f raw ${IMGDEPLOYDIR}/${IMAGE_NAME}.${type}.qemu-sd ${powerof2}
+}
+
+BOOT_VOLUME_ID ?= "BOOT"
+BOOT_SPACE ?= "1047552"
+IMAGE_ALIGNMENT ?= "1024"
+
+# Create SD image in case of INITRAMFS_IMAGE set due to circular dependencies.
+# This creates FAT partitioned SD image containing boot.bin,boot.scr and rootfs.cpio.gz.u-boot files.
+# This is a workaround fix until we fix the circular dependencies
+# Usage: IMAGE_FSTYPES:append = " cpio.gz.u-boot.qemu-sd-fatimg"
+CONVERSION_CMD:qemu-sd-fatimg () {
+ QEMU_IMG="${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.${type}.qemu-sd-fatimg"
+ BOOT_SPACE_ALIGNED=$(expr ${BOOT_SPACE} + ${IMAGE_ALIGNMENT} - 1)
+ BOOT_SPACE_ALIGNED=$(expr ${BOOT_SPACE_ALIGNED} - ${BOOT_SPACE_ALIGNED} % ${IMAGE_ALIGNMENT})
+ QEMUIMG_SIZE=$(expr ${IMAGE_ALIGNMENT} + ${BOOT_SPACE_ALIGNED})
+ dd if=/dev/zero of=${QEMU_IMG} bs=1024 count=0 seek=${QEMUIMG_SIZE}
+ parted -s ${QEMU_IMG} mklabel msdos
+ parted -s ${QEMU_IMG} unit KiB mkpart primary fat32 ${IMAGE_ALIGNMENT} $(expr ${BOOT_SPACE_ALIGNED} \+ ${IMAGE_ALIGNMENT} \- 1)
+ parted -s ${QEMU_IMG} set 1 boot on
+ parted ${QEMU_IMG} print
+ BOOT_BLOCKS=$(LC_ALL=C parted -s ${QEMU_IMG} unit b print | awk '/ 1 / { print substr($4, 1, length($4 -1)) / 512 /2 }')
+ rm -f ${WORKDIR}/${BOOT_VOLUME_ID}.img
+ mkfs.vfat -n "${BOOT_VOLUME_ID}" -S 512 -C ${WORKDIR}/${BOOT_VOLUME_ID}.img $BOOT_BLOCKS
+ if [ -e ${DEPLOY_DIR_IMAGE}/boot.bin ]; then
+ mcopy -i ${WORKDIR}/${BOOT_VOLUME_ID}.img -s ${DEPLOY_DIR_IMAGE}/boot.bin ::/
+ fi
+ if [ -e ${DEPLOY_DIR_IMAGE}/boot.scr ]; then
+ mcopy -i ${WORKDIR}/${BOOT_VOLUME_ID}.img -s ${DEPLOY_DIR_IMAGE}/boot.scr ::/
+ fi
+ if [ ${INITRAMFS_IMAGE} = ${IMAGE_BASENAME} ] && [ x"${INITRAMFS_IMAGE_BUNDLE}" != "x1" ]; then
+ mcopy -i ${WORKDIR}/${BOOT_VOLUME_ID}.img -s ${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.${type} ::rootfs.cpio.gz.u-boot
+ fi
+ dd if=${WORKDIR}/${BOOT_VOLUME_ID}.img of=${QEMU_IMG} conv=notrunc seek=1 bs=$(expr ${IMAGE_ALIGNMENT} \* 1024)
+}
+
+CONVERSION_DEPENDS_qemu-sd = "qemu-system-native"
+CONVERSION_DEPENDS_qemu-sd-fatimg = "mtools-native:do_populate_sysroot \
+ dosfstools-native:do_populate_sysroot \
+ parted-native:do_populate_sysroot"
diff --git a/meta-xilinx-core/classes/image-wic-utils.bbclass b/meta-xilinx-core/classes/image-wic-utils.bbclass
new file mode 100644
index 00000000..41ad8148
--- /dev/null
+++ b/meta-xilinx-core/classes/image-wic-utils.bbclass
@@ -0,0 +1,54 @@
+# Helper/utility functions to work with the IMAGE_BOOT_FILES variable and its
+# expected behvaior with regards to the contents of the DEPLOY_DIR_IMAGE.
+#
+# The use of these functions assume that the deploy directory is populated with
+# any dependent files/etc. Such that the recipe using these functions depends
+# on the recipe that provides the files being used/queried.
+
+def boot_files_split_expand(d):
+ # IMAGE_BOOT_FILES has extra renaming info in the format '<source>;<target>'
+ for f in (d.getVar("IMAGE_BOOT_FILES") or "").split(" "):
+ parts = f.split(";", 1)
+ sources = [parts[0].strip()]
+ if "*" in parts[0]:
+ # has glob part
+ import glob
+ deployroot = d.getVar("DEPLOY_DIR_IMAGE")
+ sources = []
+ for i in glob.glob(os.path.join(deployroot, parts[0])):
+ sources.append(os.path.basename(i))
+
+ # for all sources, yield an entry
+ for s in sources:
+ if len(parts) == 2:
+ if parts[1].endswith('/'):
+ yield s, '%s%s' % (parts[1].strip(), s)
+ else:
+ yield s, parts[1].strip()
+ yield s, s
+
+def boot_files_bitstream(d):
+ expectedfiles = [("bitstream", True)]
+ expectedexts = [(".bit", True), (".bin", False)]
+ # search for bitstream paths, use the renamed file. First matching is used
+ for source, target in boot_files_split_expand(d):
+ # skip boot.bin and u-boot.bin, it is not a bitstream
+ skip = ["boot.bin", "u-boot.bin"]
+ if source in skip or target in skip:
+ continue
+
+ for e, t in expectedfiles:
+ if source == e or target == e:
+ return target, t
+ for e, t in expectedexts:
+ if source.endswith(e) or target.endswith(e):
+ return target, t
+ return "", False
+
+def boot_files_dtb_filepath(d):
+ dtbs = (d.getVar("IMAGE_BOOT_FILES") or "").split(" ")
+ for source, target in boot_files_split_expand(d):
+ if target.endswith(".dtb"):
+ return target
+ return ""
+
diff --git a/meta-xilinx-core/classes/kernel-simpleimage.bbclass b/meta-xilinx-core/classes/kernel-simpleimage.bbclass
new file mode 100644
index 00000000..110ee254
--- /dev/null
+++ b/meta-xilinx-core/classes/kernel-simpleimage.bbclass
@@ -0,0 +1,35 @@
+python __anonymous () {
+ kerneltypes = set((d.getVar("KERNEL_IMAGETYPE") or "").split())
+ kerneltypes |= set((d.getVar("KERNEL_IMAGETYPES") or "").split())
+ if any(t.startswith("simpleImage.") for t in kerneltypes):
+ # Enable building of simpleImage
+ bb.build.addtask('do_prep_simpleimage', 'do_compile', 'do_configure', d)
+ uarch = d.getVar("UBOOT_ARCH")
+ if uarch == "microblaze":
+ d.appendVarFlag('do_prep_simpleimage', 'depends', ' virtual/dtb:do_populate_sysroot')
+}
+
+do_prep_simpleimage[dirs] += "${B}"
+do_prep_simpleimage () {
+ install -d ${B}/arch/${ARCH}/boot/dts
+ for type in ${KERNEL_IMAGETYPES} ; do
+ if [ -z "${type##*simpleImage*}" ] && [ ${ARCH} = "microblaze" ]; then
+ ext="${type##*.}"
+ # Microblaze simpleImage only works with dts file
+ cp ${RECIPE_SYSROOT}/boot/devicetree/${ext}.dts ${B}/arch/${ARCH}/boot/dts/
+ fi
+ done
+}
+
+do_deploy:append () {
+ for type in ${KERNEL_IMAGETYPES} ; do
+ if [ -z "${type##*simpleImage*}" ] && [ ${ARCH} = "microblaze" ]; then
+ base_name=${type}-${KERNEL_IMAGE_NAME}
+ install -m 0644 ${KERNEL_OUTPUT_DIR}/${type}.strip $deployDir/${base_name}.strip
+ install -m 0644 ${KERNEL_OUTPUT_DIR}/${type}.unstrip $deployDir/${base_name}.unstrip
+ symlink_name=${type}-${KERNEL_IMAGE_LINK_NAME}
+ ln -sf ${base_name}.strip $deployDir/${symlink_name}.strip
+ ln -sf ${base_name}.unstrip $deployDir/${symlink_name}.unstrip
+ fi
+ done
+}
diff --git a/meta-xilinx-core/classes/qemuboot-xilinx.bbclass b/meta-xilinx-core/classes/qemuboot-xilinx.bbclass
new file mode 100644
index 00000000..7466ab5e
--- /dev/null
+++ b/meta-xilinx-core/classes/qemuboot-xilinx.bbclass
@@ -0,0 +1,140 @@
+
+# enable the overrides for the context of the conf only
+OVERRIDES .= ":qemuboot-xilinx"
+
+# Default machine targets for Xilinx QEMU (FDT Generic)
+# Allow QB_MACHINE to be overridden by a BSP config
+QB_MACHINE ?= "${QB_MACHINE_XILINX}"
+QB_RNG=""
+QB_MACHINE_XILINX:aarch64 = "-machine arm-generic-fdt"
+QB_MACHINE_XILINX:arm = "-M arm-generic-fdt-7series"
+QB_MACHINE_XILINX:microblaze = "-M microblaze-fdt-plnx"
+
+QB_SYSTEM_NAME ?= "${@qemu_target_binary(d)}"
+QB_DEFAULT_FSTYPE ?= "${@qemu_rootfs_params(d,'fstype')}"
+QB_ROOTFS ?= "${@qemu_rootfs_params(d,'rootfs')}"
+QB_ROOTFS_OPT ?= "${@qemu_rootfs_params(d,'rootfs-opt')}"
+QB_DTB ?= "${@qemu_default_dtb(d)}"
+
+# defaults
+QB_DEFAULT_KERNEL ?= "none"
+QB_DEFAULT_KERNEL:zynq ?= "${@'zImage' if \
+ d.getVar('INITRAMFS_IMAGE_BUNDLE') != '1' else 'zImage-initramfs-${MACHINE}.bin'}"
+QB_DEFAULT_KERNEL:microblaze ?= "${@'simpleImage.mb' if \
+ d.getVar('INITRAMFS_IMAGE_BUNDLE') != '1' else 'simpleImage.mb-initramfs-${MACHINE}.bin'}"
+
+inherit qemuboot
+
+def qemu_target_binary(data):
+ package_arch = data.getVar("PACKAGE_ARCH")
+ qemu_target_binary = (data.getVar("QEMU_TARGET_BINARY_%s" % package_arch) or "")
+ if qemu_target_binary:
+ return qemu_target_binary
+
+ target_arch = data.getVar("TARGET_ARCH")
+ if target_arch == "microblazeeb":
+ target_arch = "microblaze"
+ elif target_arch == "aarch64":
+ target_arch += "-multiarch"
+ elif target_arch == "arm":
+ target_arch = "aarch64"
+ return "qemu-system-%s" % target_arch
+
+def qemu_add_extra_args(data):
+ initramfs_image = data.getVar('INITRAMFS_IMAGE') or ""
+ bundle_image = data.getVar('INITRAMFS_IMAGE_BUNDLE') or ""
+ deploy_dir = data.getVar('DEPLOY_DIR_IMAGE') or ""
+ machine_name = data.getVar('MACHINE') or ""
+ soc_family = data.getVar('SOC_FAMILY') or ""
+ qb_extra_args = ''
+ # Add kernel image and boot.scr to qemu boot command when initramfs_image supplied
+ kernel_name = ''
+ bootscr_image = '%s/boot.scr' % deploy_dir
+ if soc_family in ('zynqmp', 'versal'):
+ kernel_name = 'Image'
+ bootscr_loadaddr = '0x20000000'
+ if initramfs_image:
+ kernel_image = '%s/%s' % (deploy_dir, kernel_name)
+ if bundle_image == "1":
+ kernel_image = '%s/%s-initramfs-%s.bin' % (deploy_dir, kernel_name, machine_name)
+ kernel_loadaddr = '0x200000'
+ if kernel_name:
+ qb_extra_args = ' -device loader,file=%s,addr=%s,force-raw=on' % (kernel_image, kernel_loadaddr)
+ qb_extra_args += ' -device loader,file=%s,addr=%s,force-raw=on' % (bootscr_image, bootscr_loadaddr)
+ if soc_family == 'versal':
+ qb_extra_args += ' -boot mode=5'
+ else:
+ if soc_family in ('zynqmp', 'versal'):
+ qb_extra_args = ' -boot mode=5'
+ return qb_extra_args
+
+def qemu_rootfs_params(data, param):
+ initramfs_image = data.getVar('INITRAMFS_IMAGE') or ""
+ bundle_image = data.getVar('INITRAMFS_IMAGE_BUNDLE') or ""
+ soc_family = data.getVar('SOC_FAMILY') or ""
+ tune_features = (data.getVar('TUNE_FEATURES') or []).split()
+ if 'microblaze' in tune_features:
+ soc_family = 'microblaze'
+ soc_variant = data.getVar('SOC_VARIANT') or ""
+
+ if param == 'rootfs':
+ return 'none' if bundle_image == "1" else ''
+
+ elif param == 'fstype':
+ fstype_dict = {
+ "microblaze": "cpio.gz",
+ "zynq": "cpio.gz",
+ "zynqmp": "cpio.gz.u-boot",
+ "versal": "cpio.gz.u-boot.qemu-sd-fatimg"
+ }
+ if not initramfs_image:
+ image_fs = data.getVar('IMAGE_FSTYPES')
+ if 'wic.qemu-sd' in image_fs:
+ return 'wic.qemu-sd'
+ if soc_family not in fstype_dict:
+ return ""
+ return fstype_dict[soc_family]
+
+ elif param == 'rootfs-opt':
+ sd_index = "1"
+ if soc_family == 'zynq':
+ sd_index = "0"
+ if soc_family == 'versal' and soc_variant == 'net':
+ sd_index = "0"
+
+ # Device is using a disk
+ if not initramfs_image:
+ return ' -drive if=sd,index=%s,file=@ROOTFS@,format=raw' % (sd_index)
+
+ # Device is using a ramdisk
+ if soc_family not in ('zynq', 'microblaze'):
+ return ' -device loader,file=@ROOTFS@,addr=0x04000000,force-raw=on'
+
+ # Ramdisk must be compiled into the kernel
+ return ''
+
+def qemu_default_dtb(data):
+ if data.getVar("IMAGE_BOOT_FILES", True):
+ dtbs = data.getVar("IMAGE_BOOT_FILES", True).split(" ")
+ # IMAGE_BOOT_FILES has extra renaming info in the format '<source>;<target>'
+ # Note: Wildcard sources work here only because runqemu expands them at run time
+ dtbs = [f.split(";")[0] for f in dtbs]
+ dtbs = [f for f in dtbs if f.endswith(".dtb")]
+ if len(dtbs) != 0:
+ return dtbs[0]
+ return ""
+
+def qemu_default_serial(data):
+ if data.getVar("SERIAL_CONSOLES", True):
+ first_console = data.getVar("SERIAL_CONSOLES", True).split(" ")[0]
+ speed, console = first_console.split(";", 1)
+ # zynqmp uses earlycon and stdout (in dtb)
+ if "zynqmp" in data.getVar("MACHINEOVERRIDES", True).split(":"):
+ return ""
+ return "console=%s,%s earlyprintk" % (console, speed)
+ return ""
+
+def qemu_zynqmp_unhalt(data, multiarch):
+ if multiarch:
+ return "-global xlnx,zynqmp-boot.cpu-num=0 -global xlnx,zynqmp-boot.use-pmufw=true"
+ return "-device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4 -device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4"
diff --git a/meta-xilinx-core/classes/xilinx-deprecated.bbclass b/meta-xilinx-core/classes/xilinx-deprecated.bbclass
new file mode 100644
index 00000000..1aee2fe1
--- /dev/null
+++ b/meta-xilinx-core/classes/xilinx-deprecated.bbclass
@@ -0,0 +1,18 @@
+# Class to add a deprecated warning from various configuration files.
+
+# Immediately after the ConfigParsed event handler, warn the user of any
+# deprecated files the user has used.
+addhandler xilinx_deprecated_config_eventhandler
+xilinx_deprecated_config_eventhandler[eventmask] = "bb.event.ConfigParsed"
+python xilinx_deprecated_config_eventhandler () {
+ # Check for BOARD & BOARD_VARIANT usage
+ if d.getVar('BOARD') or d.getVar('BOARD_VARIANT'):
+ bb.error("Deprecated BOARD (%s) or BOARD_VARIANT (%s) is being used, they are no longer supported and are ignored." % (d.getVar('BOARD'), d.getVar('BOARD_VARIANT')))
+
+ msg_list = d.getVarFlags('XILINX_DEPRECATED') or []
+ for msg_source in msg_list:
+ if msg_source == "doc":
+ continue
+ msg = d.getVarFlag('XILINX_DEPRECATED', msg_source) or ""
+ bb.warn('%s: %s' % (msg_source, msg))
+}
diff --git a/meta-xilinx-core/classes/xilinx-fetch-restricted.bbclass b/meta-xilinx-core/classes/xilinx-fetch-restricted.bbclass
new file mode 100644
index 00000000..a778ec7d
--- /dev/null
+++ b/meta-xilinx-core/classes/xilinx-fetch-restricted.bbclass
@@ -0,0 +1,35 @@
+# This class is setup to override the default fetching for the target recipe.
+# When fetching it forces PREMIRROR only fetching so that no attempts are made
+# to fetch the Xilinx downloads that are restricted to authenticated users only.
+#
+# The purpose of this class is to allow for automatation with pre-downloaded
+# content or content that is available with curated/user defined pre-mirrors
+# and or pre-populated downloads/ directories.
+
+python do_fetch() {
+ xilinx_restricted_url = "xilinx.com/member/forms/download"
+
+ src_uri = (d.getVar('SRC_URI') or "").split()
+ if len(src_uri) == 0:
+ return
+
+ for i in src_uri:
+ if xilinx_restricted_url in i:
+ # force the use of premirrors only, do not attempt download from xilinx.com
+ d.setVar("BB_FETCH_PREMIRRORONLY", "1")
+ break
+
+ try:
+ fetcher = bb.fetch2.Fetch(src_uri, d)
+ fetcher.download()
+ except bb.fetch2.NetworkAccess as e:
+ if xilinx_restricted_url in e.url:
+ # fatal on access to xilinx.com restricted downloads, print the url for manual download
+ bb.fatal("The following download cannot be fetched automatically. " \
+ "Please manually download the file and place it in the 'downloads' directory (or on an available PREMIRROR).\n" \
+ " %s" % (e.url.split(";")[0]))
+ else:
+ bb.fatal(str(e))
+ except bb.fetch2.BBFetchException as e:
+ bb.fatal(str(e))
+}
diff --git a/meta-xilinx-core/classes/xilinx-microblaze.bbclass b/meta-xilinx-core/classes/xilinx-microblaze.bbclass
new file mode 100644
index 00000000..ed231a3a
--- /dev/null
+++ b/meta-xilinx-core/classes/xilinx-microblaze.bbclass
@@ -0,0 +1,11 @@
+# Class to add a deprecated warning from various configuration files.
+
+# Immediately after the ConfigParsed event handler, warn the user of any
+# deprecated files the user has used.
+addhandler xilinx_microblaze_config_eventhandler
+xilinx_microblaze_config_eventhandler[eventmask] = "bb.event.ConfigParsed"
+python xilinx_microblaze_config_eventhandler () {
+ if d.getVar('DEFAULTTUNE').startswith('microblaze'):
+ if 'xilinx-microblaze' not in d.getVar('BBFILE_COLLECTIONS').split():
+ bb.fatal('You must include the meta-microblaze layer to build for this configuration.')
+}
diff --git a/meta-xilinx-core/classes/xilinx-platform-init.bbclass b/meta-xilinx-core/classes/xilinx-platform-init.bbclass
new file mode 100644
index 00000000..99f7863a
--- /dev/null
+++ b/meta-xilinx-core/classes/xilinx-platform-init.bbclass
@@ -0,0 +1,14 @@
+# This class should be included by any recipe that wants to access or provide
+# the platform init source files which are used to initialize a Zynq or ZynqMP
+# SoC.
+
+# Define the path to the xilinx platform init code/headers
+PLATFORM_INIT_DIR ?= "/usr/src/xilinx-platform-init"
+
+PLATFORM_INIT_STAGE_DIR = "${STAGING_DIR_HOST}${PLATFORM_INIT_DIR}"
+
+# Target files use for platform init
+PLATFORM_INIT_FILES ?= ""
+PLATFORM_INIT_FILES:zynq = "ps7_init_gpl.c ps7_init_gpl.h"
+PLATFORM_INIT_FILES:zynqmp = "psu_init_gpl.c psu_init_gpl.h"
+
diff --git a/meta-xilinx-core/classes/xilinx-testimage.bbclass b/meta-xilinx-core/classes/xilinx-testimage.bbclass
new file mode 100644
index 00000000..74020da1
--- /dev/null
+++ b/meta-xilinx-core/classes/xilinx-testimage.bbclass
@@ -0,0 +1,10 @@
+inherit testimage
+
+HOSTTOOLS += 'ip ping ps scp ssh stty'
+
+python do_testimage:prepend () {
+ from oeqa.core.target.qemu import supported_fstypes
+ supported_fstypes.append('wic.qemu-sd')
+}
+
+IMAGE_FSTYPES = "wic.qemu-sd"
diff --git a/meta-xilinx-core/classes/xilinx-vars.bbclass b/meta-xilinx-core/classes/xilinx-vars.bbclass
new file mode 100644
index 00000000..51d3cd87
--- /dev/null
+++ b/meta-xilinx-core/classes/xilinx-vars.bbclass
@@ -0,0 +1,32 @@
+# Check variable usage to make sure that the machine is probably configured
+# properly.
+addhandler xilinx_variables_config_eventhandler
+xilinx_variables_config_eventhandler[eventmask] = "bb.event.ConfigParsed"
+
+# It's up to the base sytem to define the variables being used here, we're
+# only going to check them.
+python xilinx_variables_config_eventhandler () {
+ # Verify HDF_MACHINE
+ hdf_prior = d.getVar('HDF_MACHINE_PRIOR')
+ hdf_final = d.getVar('HDF_MACHINE')
+
+ if hdf_prior and hdf_prior != hdf_final:
+ bb.fatal("HDF_MACHINE is set to %s, it appears you intended %s. " \
+ "This is usually as a result of specifying it in the local.conf or before the 'require' in the machine .conf file. " \
+ "See meta-xilinx-core/conf/machine/README." % (hdf_final, hdf_prior))
+
+ # Verify DEFAULTTUNE
+ tune_prior = d.getVar('DEFAULTTUNE_PRIOR')
+ tune_final = d.getVar('DEFAULTTUNE')
+
+ if tune_prior and tune_prior != tune_final:
+ bb.fatal("The loaded DEFAULTTUNE is %s, but it appears you intended %s. " \
+ "This is usually as a result of specifying it after the 'require' in the machine .conf file. " \
+ "See meta-xilinx-core/conf/machine/README." % (tune_prior, tune_final))
+
+ # Verify 'xilinx' is in LICENSE_FLAGS_ACCEPTED
+ license_flags = d.getVar('LICENSE_FLAGS_ACCEPTED') or ""
+ if 'xilinx' not in license_flags.split():
+ bb.warn("The ZynqMP pmu-rom is not enabled, qemu may not be able to emulate a ZynqMP system without it. " \
+ "To enable this you must add 'xilinx' to the LICENSE_FLAGS_ACCEPTED to indicate you accept the software license.")
+}