diff options
| author | Sandeep Gundlupet Raju <sandeep.gundlupet-raju@amd.com> | 2023-11-30 22:07:47 -0700 |
|---|---|---|
| committer | Mark Hatle <mark.hatle@amd.com> | 2023-12-08 11:30:55 -0600 |
| commit | 9b391bbaf9ed0b83a493f20e48594a1c1e3004ce (patch) | |
| tree | d03c7dacabb3b02841fb9845495589ab5ea69443 /meta-xilinx-core/classes-recipe | |
| parent | 9461f910a0b4415941d2bbac4406b37236d0a6de (diff) | |
| download | meta-xilinx-9b391bbaf9ed0b83a493f20e48594a1c1e3004ce.tar.gz | |
classes: Move classes to match bbclass scope functionality
Move classes to classes-global or classes-recipe as appropriate to
match bbclass scope functionality. Below is the list.
classes-recipe: (inherited by recipes)
amd_spi_image.bbclass
dfx_user_dts.bbclass
image-wic-utils.bbclass
kernel-simpleimage.bbclass
qemuboot-xilinx.bbclass
xilinx-fetch-restricted.bbclass
xilinx-platform-init.bbclass
classes-global: (inherited globally)
xilinx-microblaze.bbclass
classes: (usage context is not clearly defined)
gen-machine-conf.bbclass
image-types-xilinx-qemu.bbclass
xilinx-testimage.bbclass
xilinx-vars.bbclass
xilinx-deprecated.bbclass
Signed-off-by: Sandeep Gundlupet Raju <sandeep.gundlupet-raju@amd.com>
Signed-off-by: Mark Hatle <mark.hatle@amd.com>
Diffstat (limited to 'meta-xilinx-core/classes-recipe')
7 files changed, 687 insertions, 0 deletions
diff --git a/meta-xilinx-core/classes-recipe/amd_spi_image.bbclass b/meta-xilinx-core/classes-recipe/amd_spi_image.bbclass new file mode 100644 index 00000000..ed4c1f87 --- /dev/null +++ b/meta-xilinx-core/classes-recipe/amd_spi_image.bbclass | |||
| @@ -0,0 +1,142 @@ | |||
| 1 | # | ||
| 2 | # Copyright (C) 2023, Advanced Micro Devices, Inc. All rights reserved. | ||
| 3 | # | ||
| 4 | # SPDX-License-Identifier: MIT | ||
| 5 | # | ||
| 6 | |||
| 7 | QSPI_SIZE ?= "0x2280000" | ||
| 8 | |||
| 9 | # Register values | ||
| 10 | IDN_REG ?= "0x4D554241" | ||
| 11 | VERSION_REG ?= "0x1" | ||
| 12 | LENGTH_REG ?= "0x4" | ||
| 13 | PERSISTENT_REG ?= "0x01010000" | ||
| 14 | |||
| 15 | # QSPI Offsets | ||
| 16 | IMAGE_SELECTOR_OFFSET ?= "0x0" | ||
| 17 | IMAGE_SELECTOR_BACKUP_OFFSET ?= "0x80000" | ||
| 18 | PERSISTENT_REG_OFFSET ?= "0x100000" | ||
| 19 | PERSISTENT_REG_BACKUP_OFFSET ?= "0x120000" | ||
| 20 | IMAGE_A_OFFSET ?= "0x200000" | ||
| 21 | IMAGE_A_IMGSEL_OFFSET ?= "0xF00000" | ||
| 22 | IMAGE_B_OFFSET ?= "0xF80000" | ||
| 23 | IMAGE_B_IMGSEL_OFFSET ?= "0x1C80000" | ||
| 24 | IMAGE_RCVRY_OFFSET ?= "0x1E00000" | ||
| 25 | IMAGE_RCVRY_BACKUP_OFFSET ?= "0x2000000" | ||
| 26 | VERSION_OFFSET ?= "0x2240000" | ||
| 27 | CHECKSUM_OFFSET ?= "0x2250000" | ||
| 28 | |||
| 29 | def generate_spi_image(d): | ||
| 30 | |||
| 31 | import io | ||
| 32 | import hashlib | ||
| 33 | import time | ||
| 34 | |||
| 35 | qspi_size = int(d.getVar("QSPI_SIZE") or '0', 0) | ||
| 36 | int(d.getVar("QSPI_SIZE") or '0', 0) | ||
| 37 | |||
| 38 | # Register values | ||
| 39 | idn_reg = int(d.getVar("IDN_REG") or '0', 0) | ||
| 40 | version_reg = int(d.getVar("VERSION_REG") or '0', 0) | ||
| 41 | length_reg = int(d.getVar("LENGTH_REG") or '0', 0) | ||
| 42 | persistent_reg = int(d.getVar("PERSISTENT_REG") or '0', 0) | ||
| 43 | |||
| 44 | # QSPI Offsets | ||
| 45 | image_selector_offset = int(d.getVar("IMAGE_SELECTOR_OFFSET") or '0', 0) | ||
| 46 | image_selector_backup_offset = int(d.getVar("IMAGE_SELECTOR_BACKUP_OFFSET") or '0', 0) | ||
| 47 | persistent_reg_offset = int(d.getVar("PERSISTENT_REG_OFFSET") or '0', 0) | ||
| 48 | persistent_reg_backup_offset = int(d.getVar("PERSISTENT_REG_BACKUP_OFFSET") or '0', 0) | ||
| 49 | image_a_offset = int(d.getVar("IMAGE_A_OFFSET") or '0', 0) | ||
| 50 | image_a_imgsel_offset = int(d.getVar("IMAGE_A_IMGSEL_OFFSET") or '0', 0) | ||
| 51 | image_b_offset = int(d.getVar("IMAGE_B_OFFSET") or '0', 0) | ||
| 52 | image_b_imgsel_offset = int(d.getVar("IMAGE_B_IMGSEL_OFFSET") or '0', 0) | ||
| 53 | image_rcvry_offset = int(d.getVar("IMAGE_RCVRY_OFFSET") or '0', 0) | ||
| 54 | image_rcvry_backup_offset = int(d.getVar("IMAGE_RCVRY_BACKUP_OFFSET") or '0', 0) | ||
| 55 | version_offset = int(d.getVar("VERSION_OFFSET") or '0', 0) | ||
| 56 | checksum_offset = int(d.getVar("CHECKSUM_OFFSET") or '0', 0) | ||
| 57 | |||
| 58 | # QSPI data | ||
| 59 | qspi_data = io.BytesIO() | ||
| 60 | qspi_data.write(b'\xFF' * qspi_size) | ||
| 61 | |||
| 62 | # Image Selector - Primary, Backup, Image A and Image B | ||
| 63 | imgsel_file = d.getVar("DEPLOY_DIR_IMAGE")+"/imgsel-"+d.getVar("MACHINE")+".bin" | ||
| 64 | try: | ||
| 65 | with open(imgsel_file, "rb") as il: | ||
| 66 | imgsel = il.read(-1) | ||
| 67 | except OSError as err: | ||
| 68 | bb.fatal("Unable to open imgsel file: " + str(err)) | ||
| 69 | |||
| 70 | qspi_data.seek(image_selector_offset) | ||
| 71 | qspi_data.write(imgsel) | ||
| 72 | qspi_data.seek(image_selector_backup_offset) | ||
| 73 | qspi_data.write(imgsel) | ||
| 74 | qspi_data.seek(image_a_imgsel_offset) | ||
| 75 | qspi_data.write(imgsel) | ||
| 76 | qspi_data.seek(image_b_imgsel_offset) | ||
| 77 | qspi_data.write(imgsel) | ||
| 78 | |||
| 79 | # Persistent Registers - Primary and Backup | ||
| 80 | p_reg = [idn_reg, version_reg, length_reg, persistent_reg, \ | ||
| 81 | image_a_offset, image_b_offset, image_rcvry_offset] | ||
| 82 | checksum = 0xffffffff - (0xffffffff & sum(p_reg)) | ||
| 83 | p_reg.insert(3, checksum) | ||
| 84 | |||
| 85 | qspi_data.seek(persistent_reg_offset) | ||
| 86 | for value in p_reg: | ||
| 87 | qspi_data.write(value.to_bytes(4, byteorder="little")) | ||
| 88 | |||
| 89 | qspi_data.seek(persistent_reg_backup_offset) | ||
| 90 | for value in p_reg: | ||
| 91 | qspi_data.write(value.to_bytes(4, byteorder="little")) | ||
| 92 | |||
| 93 | # Image A and B - boot.bin | ||
| 94 | try: | ||
| 95 | with open(d.getVar("DEPLOY_DIR_IMAGE")+"/boot.bin", "rb") as bo: | ||
| 96 | bootbin = bo.read(-1) | ||
| 97 | except OSError as err: | ||
| 98 | bb.fatal("Unable to open boot.bin file: " + str(err)) | ||
| 99 | |||
| 100 | qspi_data.seek(image_a_offset) | ||
| 101 | qspi_data.write(bootbin) | ||
| 102 | qspi_data.seek(image_b_offset) | ||
| 103 | qspi_data.write(bootbin) | ||
| 104 | |||
| 105 | # Recovery Image & Recovery Image Backup | ||
| 106 | imgrcry_file = d.getVar("DEPLOY_DIR_IMAGE")+"/imgrcry-"+d.getVar("MACHINE")+".bin" | ||
| 107 | try: | ||
| 108 | with open(imgrcry_file, "rb") as iy: | ||
| 109 | imgrcry = iy.read(-1) | ||
| 110 | except OSError as err: | ||
| 111 | bb.fatal("Unable to open imgrcry file: " + str(err)) | ||
| 112 | |||
| 113 | qspi_data.seek(image_rcvry_offset) | ||
| 114 | qspi_data.write(imgrcry) | ||
| 115 | qspi_data.seek(image_rcvry_backup_offset) | ||
| 116 | qspi_data.write(imgrcry) | ||
| 117 | |||
| 118 | # Version string and checksum | ||
| 119 | version = d.getVar("QSPI_IMAGE_VERSION") | ||
| 120 | date = time.strftime("%m%d%H%M") | ||
| 121 | machine = d.getVar("MACHINE")[:3] | ||
| 122 | image_name = d.getVar("QSPI_IMAGE_NAME") | ||
| 123 | |||
| 124 | qspi_version = f"{image_name}-{machine}-v{version}-{date}\x00" | ||
| 125 | qspi_data.seek(version_offset) | ||
| 126 | qspi_data.write(qspi_version.encode()) | ||
| 127 | |||
| 128 | qspi_sha = hashlib.sha256(qspi_data.getbuffer()) | ||
| 129 | qspi_data.seek(checksum_offset) | ||
| 130 | qspi_data.write(qspi_sha.digest()) | ||
| 131 | |||
| 132 | # Write the QSPI data to file | ||
| 133 | with open(d.getVar("B") + "/" + d.getVar("IMAGE_NAME") + ".bin", "wb") as sq: | ||
| 134 | sq.write(qspi_data.getbuffer()) | ||
| 135 | |||
| 136 | do_compile[depends] += "virtual/boot-bin:do_deploy virtual/imgsel:do_deploy virtual/imgrcry:do_deploy" | ||
| 137 | |||
| 138 | python amd_spi_image_do_compile() { | ||
| 139 | generate_spi_image(d) | ||
| 140 | } | ||
| 141 | |||
| 142 | EXPORT_FUNCTIONS do_compile | ||
diff --git a/meta-xilinx-core/classes-recipe/dfx_user_dts.bbclass b/meta-xilinx-core/classes-recipe/dfx_user_dts.bbclass new file mode 100644 index 00000000..4404aa05 --- /dev/null +++ b/meta-xilinx-core/classes-recipe/dfx_user_dts.bbclass | |||
| @@ -0,0 +1,267 @@ | |||
| 1 | # This bbclass is inherited by flat, DFx Static and DFx RP firmware recipes. | ||
| 2 | # dfx_user_dts.bbclass expects user to generate pl dtsi for flat, DFx Static | ||
| 3 | # and DFx RP xsa outside of yocto. | ||
| 4 | |||
| 5 | inherit devicetree | ||
| 6 | |||
| 7 | DEPENDS = "dtc-native bootgen-native" | ||
| 8 | |||
| 9 | # recipes that inherit from this class need to use an appropriate machine | ||
| 10 | # override for COMPATIBLE_MACHINE to build successfully; don't allow building | ||
| 11 | # for microblaze MACHINE | ||
| 12 | COMPATIBLE_MACHINE ?= "^$" | ||
| 13 | COMPATIBLE_MACHINE:microblaze = "^$" | ||
| 14 | |||
| 15 | PACKAGE_ARCH = "${MACHINE_ARCH}" | ||
| 16 | |||
| 17 | PROVIDES = "" | ||
| 18 | |||
| 19 | do_fetch[cleandirs] = "${B}" | ||
| 20 | |||
| 21 | DT_PADDING_SIZE = "0x1000" | ||
| 22 | BOOTGEN_FLAGS ?= " -arch ${SOC_FAMILY} -w ${@bb.utils.contains('SOC_FAMILY','zynqmp','','-process_bitstream bin',d)}" | ||
| 23 | |||
| 24 | S ?= "${WORKDIR}" | ||
| 25 | FW_DIR ?= "" | ||
| 26 | DTSI_PATH ?= "" | ||
| 27 | DTBO_PATH ?= "" | ||
| 28 | DT_FILES_PATH = "${S}/${DTSI_PATH}" | ||
| 29 | FIRMWARE_NAME_DT_FILE ?= "" | ||
| 30 | USER_DTS_FILE ?= "" | ||
| 31 | |||
| 32 | FIRMWARE_NAME_DT_FILE[doc] = "DT file which has firmware-name device-tree property" | ||
| 33 | USER_DTS_FILE[doc] = "Final DTSI or DTS file which is used for packaging final DT overlay" | ||
| 34 | |||
| 35 | python() { | ||
| 36 | import re | ||
| 37 | soc_family = d.getVar("SOC_FAMILY") | ||
| 38 | if "git://" in d.getVar("SRC_URI") or "https://" in d.getVar("SRC_URI"): | ||
| 39 | d.setVar("S",'${WORKDIR}/git/'+d.getVar("FW_DIR")) | ||
| 40 | else: | ||
| 41 | dtsi_found = False | ||
| 42 | dtbo_found = False | ||
| 43 | bit_found = False | ||
| 44 | bin_found = False | ||
| 45 | pdi_found = False | ||
| 46 | |||
| 47 | # Required Inputs | ||
| 48 | if '.dtsi' in d.getVar("SRC_URI") or '.dts' in d.getVar("SRC_URI"): | ||
| 49 | dtsi_found = True | ||
| 50 | 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://'))) | ||
| 51 | |||
| 52 | if '.dtbo' in d.getVar("SRC_URI"): | ||
| 53 | dtbo_found = True | ||
| 54 | d.setVar("DTBO_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.dtbo' in a][0].lstrip('file://'))) | ||
| 55 | |||
| 56 | if '.bit' in d.getVar("SRC_URI") and soc_family != "versal": | ||
| 57 | bit_found = True | ||
| 58 | d.setVar("BIT_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.bit' in a][0].lstrip('file://'))) | ||
| 59 | |||
| 60 | if '.bin' in d.getVar("SRC_URI") and soc_family != "versal": | ||
| 61 | bin_found = True | ||
| 62 | d.setVar("BIT_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.bin' in a][0].lstrip('file://'))) | ||
| 63 | |||
| 64 | if '.pdi' in d.getVar("SRC_URI") and soc_family == "versal": | ||
| 65 | pdi_found = True | ||
| 66 | d.setVar("PDI_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.pdi' in a][0].lstrip('file://'))) | ||
| 67 | |||
| 68 | # Check for valid combination of input files in SRC_URI | ||
| 69 | if dtsi_found or dtbo_found: | ||
| 70 | bb.debug(2, "dtsi or dtbo found in SRC_URI") | ||
| 71 | if bit_found or pdi_found or bin_found: | ||
| 72 | bb.debug(2, "bitstream or pdi found in SRC_URI") | ||
| 73 | elif bit_found and bin_found: | ||
| 74 | raise bb.parse.SkipRecipe("Both '.bit' and '.bin' file found in SRC_URI, either .bit or .bin file is supported but not both.") | ||
| 75 | else: | ||
| 76 | raise bb.parse.SkipRecipe("Need one '.bit' or one '.pdi' file added to SRC_URI ") | ||
| 77 | else: | ||
| 78 | raise bb.parse.SkipRecipe("Need one '.dtsi' or one '.dtbo' file added to SRC_URI ") | ||
| 79 | |||
| 80 | # Check for valid combination of dtsi and dts files in SRC_URI | ||
| 81 | # Following file combinations are not supported use case. | ||
| 82 | # 1. More than one '.dtsi' and zero '.dts' file. | ||
| 83 | # 2. More than one '.dts' and zero or more than one '.dtsi'file . | ||
| 84 | pattern_dts = re.compile(r'[.]+dts\b') | ||
| 85 | pattern_dtsi = re.compile(r'[.]+dtsi\b') | ||
| 86 | dts_count = len([*re.finditer(pattern_dts, d.getVar('SRC_URI'))]) | ||
| 87 | dtsi_count = len([*re.finditer(pattern_dtsi, d.getVar("SRC_URI"))]) | ||
| 88 | |||
| 89 | if dtsi_count > 1 and dts_count == 0: | ||
| 90 | raise bb.parse.SkipRecipe("Recipe has more than one '.dtsi' and zero '.dts' found, this is an unsupported use case") | ||
| 91 | elif dts_count > 1: | ||
| 92 | raise bb.parse.SkipRecipe("Recipe has more than one '.dts' and zero or more than one '.dtsi' found, this is an unsupported use case") | ||
| 93 | |||
| 94 | # Optional input | ||
| 95 | if '.json' in d.getVar("SRC_URI"): | ||
| 96 | d.setVar("JSON_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.json' in a][0].lstrip('file://'))) | ||
| 97 | |||
| 98 | if '.xclbin' in d.getVar("SRC_URI"): | ||
| 99 | d.setVar("XCL_PATH",os.path.dirname([a for a in d.getVar('SRC_URI').split() if '.xclbin' in a][0].lstrip('file://'))) | ||
| 100 | } | ||
| 101 | |||
| 102 | # Function to get dts or dtsi file count. | ||
| 103 | def get_dt_count(d, dt_ext): | ||
| 104 | import glob | ||
| 105 | 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)) | ||
| 106 | return dt_count | ||
| 107 | |||
| 108 | # Function to search for dt firmware-name property in dts or dtsi file. | ||
| 109 | python find_firmware_file() { | ||
| 110 | import glob | ||
| 111 | pattern_fw = 'firmware-name' | ||
| 112 | search_count = 0 | ||
| 113 | for dt_files in glob.iglob((d.getVar('S') + (d.getVar('DTSI_PATH')) + '/*.dts*'),recursive=True): | ||
| 114 | with open(dt_files, "r") as f: | ||
| 115 | current_fd = f.read() | ||
| 116 | if pattern_fw in current_fd: | ||
| 117 | search_count += 1 | ||
| 118 | if search_count > 1: | ||
| 119 | bb.error("firmware-name dt property found in more than one dt files! Please fix the dts or dtsi file.") | ||
| 120 | break | ||
| 121 | else: | ||
| 122 | d.setVar('FIRMWARE_NAME_DT_FILE', os.path.basename(dt_files)) | ||
| 123 | } | ||
| 124 | |||
| 125 | do_configure[prefuncs] += "find_firmware_file" | ||
| 126 | |||
| 127 | python do_configure() { | ||
| 128 | import glob, re, shutil | ||
| 129 | soc_family = d.getVar("SOC_FAMILY") | ||
| 130 | |||
| 131 | if bb.utils.contains('MACHINE_FEATURES', 'fpga-overlay', False, True, d): | ||
| 132 | bb.warn("Using fpga-manager.bbclass requires fpga-overlay MACHINE_FEATURE to be enabled") | ||
| 133 | |||
| 134 | # Renaming firmware-name using $PN as bitstream/PDI will be renamed using | ||
| 135 | # $PN when generating the bin/pdi file. | ||
| 136 | if os.path.isfile(d.getVar('S') + (d.getVar('DTSI_PATH') or '') + '/' + d.getVar('FIRMWARE_NAME_DT_FILE')): | ||
| 137 | orig_dtsi = glob.glob(d.getVar('S')+ (d.getVar('DTSI_PATH') or '') + '/' + d.getVar('FIRMWARE_NAME_DT_FILE'))[0] | ||
| 138 | new_dtsi = d.getVar('S') + '/pl.dtsi_firmwarename' | ||
| 139 | with open(new_dtsi, 'w') as newdtsi: | ||
| 140 | with open(orig_dtsi) as olddtsi: | ||
| 141 | for line in olddtsi: | ||
| 142 | if soc_family == 'versal': | ||
| 143 | newdtsi.write(re.sub('firmware-name.*\".*\"','firmware-name = \"'+d.getVar('PN')+'.pdi\"',line)) | ||
| 144 | else: | ||
| 145 | newdtsi.write(re.sub('firmware-name.*\".*\"','firmware-name = \"'+d.getVar('PN')+'.bit.bin\"',line)) | ||
| 146 | shutil.move(new_dtsi,orig_dtsi) | ||
| 147 | } | ||
| 148 | |||
| 149 | do_compile[prefuncs] += "find_firmware_file" | ||
| 150 | |||
| 151 | python devicetree_do_compile:append() { | ||
| 152 | import glob, subprocess, shutil | ||
| 153 | soc_family = d.getVar("SOC_FAMILY") | ||
| 154 | |||
| 155 | dtbo_count = sum(1 for f in glob.iglob((d.getVar('S') + '/*.dtbo'),recursive=True) if os.path.isfile(f)) | ||
| 156 | |||
| 157 | # Skip devicetree do_compile task if input file is dtbo in SRC_URI | ||
| 158 | if not dtbo_count: | ||
| 159 | # Convert .bit to bit.bin format only if dtsi is input. | ||
| 160 | # In case of dtbo as input, bbclass doesn't know if firmware-name is .bit or | ||
| 161 | # .bit.bin format and corresponding file name. Hence we are not doing | ||
| 162 | # bit.bin conversion. | ||
| 163 | if soc_family != 'versal' and glob.glob(d.getVar('S') + '/' + d.getVar('FIRMWARE_NAME_DT_FILE')): | ||
| 164 | pn = d.getVar('PN') | ||
| 165 | biffile = pn + '.bif' | ||
| 166 | |||
| 167 | with open(biffile, 'w') as f: | ||
| 168 | f.write('all:\n{\n\t' + glob.glob(d.getVar('S')+(d.getVar('BIT_PATH') or '') + '/*.bit')[0] + '\n}') | ||
| 169 | |||
| 170 | bootgenargs = ["bootgen"] + (d.getVar("BOOTGEN_FLAGS") or "").split() | ||
| 171 | bootgenargs += ["-image", biffile, "-o", pn + ".bit.bin"] | ||
| 172 | subprocess.run(bootgenargs, check = True) | ||
| 173 | |||
| 174 | # In Zynq7k using both "-process_bitstream bin" and "-o" in bootgen flag, | ||
| 175 | # to convert bit file to bin format, "-o" option will not be effective | ||
| 176 | # and generated output file name is ${S}+${BIT_PATH}/<bit_file_name>.bit.bin | ||
| 177 | # file, Hence we need to rename this file from <bit_file_name>.bit.bin to | ||
| 178 | # ${PN}.bit.bin which matches the firmware name in dtbo and move | ||
| 179 | # ${PN}.bit.bin to ${B} directory. | ||
| 180 | if soc_family == 'zynq': | ||
| 181 | src_bitbin_file = glob.glob(d.getVar('S') + (d.getVar('BIT_PATH') or '') + '/*.bit.bin')[0] | ||
| 182 | dst_bitbin_file = d.getVar('B') + '/' + pn + '.bit.bin' | ||
| 183 | shutil.move(src_bitbin_file, dst_bitbin_file) | ||
| 184 | |||
| 185 | if not os.path.isfile(pn + ".bit.bin"): | ||
| 186 | bb.fatal("Couldn't find %s file, Enable '-log trace' in BOOTGEN_FLAGS" \ | ||
| 187 | "and check bootgen_log.txt" % (d.getVar('B') + '/' + pn + '.bit.bin')) | ||
| 188 | } | ||
| 189 | |||
| 190 | # If user inputs both dtsi and dts files then device-tree will generate dtbo | ||
| 191 | # files for each dt file, Hence to package the firmware pick the right user dt | ||
| 192 | # overlay file. | ||
| 193 | python find_user_dts_overlay_file() { | ||
| 194 | import glob | ||
| 195 | dtbo_count = sum(1 for f in glob.iglob((d.getVar('S') + '/*.dtbo'),recursive=True) if os.path.isfile(f)) | ||
| 196 | # Skip if input file is dtbo in SRC_URI | ||
| 197 | if not dtbo_count: | ||
| 198 | dts_count = get_dt_count(d, 'dts') | ||
| 199 | dtsi_count = get_dt_count(d, 'dtsi') | ||
| 200 | if dtsi_count == 1 and dts_count == 0: | ||
| 201 | dts_file =glob.glob(d.getVar('S')+ (d.getVar('DTSI_PATH') or '') + '/*.dtsi')[0] | ||
| 202 | elif dtsi_count >=0 and dts_count == 1: | ||
| 203 | dts_file = glob.glob(d.getVar('S')+ (d.getVar('DTSI_PATH') or '') + '/*.dts')[0] | ||
| 204 | |||
| 205 | d.setVar('USER_DTS_FILE', os.path.splitext(os.path.basename(dts_file))[0]) | ||
| 206 | } | ||
| 207 | |||
| 208 | do_install[prefuncs] += "find_user_dts_overlay_file" | ||
| 209 | |||
| 210 | do_install() { | ||
| 211 | install -d ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ | ||
| 212 | |||
| 213 | # In case of dtbo as input, dtbo will be copied from directly from ${S} | ||
| 214 | # In case of dtsi as input, dtbo will be copied from directly from ${B} | ||
| 215 | if [ `ls ${S}/*.dtbo | wc -l` -eq 1 ]; then | ||
| 216 | install -Dm 0644 ${S}/*.dtbo ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ | ||
| 217 | elif [ `ls ${S}/*.dtbo | wc -l` -gt 1 ]; then | ||
| 218 | bbfatal "Multiple DTBO found, use the right DTBO in SRC_URI from the following:\n$(basename -a ${S}/*.dtbo)" | ||
| 219 | elif [ -f ${B}/${USER_DTS_FILE}.dtbo ]; then | ||
| 220 | install -Dm 0644 ${B}/${USER_DTS_FILE}.dtbo ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.dtbo | ||
| 221 | else | ||
| 222 | bbfatal "A dtbo ending '.dtbo' expected but not found" | ||
| 223 | fi | ||
| 224 | |||
| 225 | if [ "${SOC_FAMILY}" == "versal" ]; then | ||
| 226 | # In case of dtbo as input, pdi will be copied from directly from ${S} | ||
| 227 | # without renaming the pdi name to ${PN}.pdi | ||
| 228 | if [ `ls ${S}/*.pdi | wc -l` -eq 1 ] && [ `ls ${S}/*.dtbo | wc -l` -eq 1 ]; then | ||
| 229 | install -Dm 0644 ${S}/*.pdi ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ | ||
| 230 | elif [ `ls ${S}/*.pdi | wc -l` -gt 1 ]; then | ||
| 231 | bbfatal "Multiple PDI found, use the right PDI in SRC_URI from the following:\n$(basename -a ${S}/*.pdi)" | ||
| 232 | elif [ `ls ${S}/*.pdi | wc -l` -eq 1 ] && [ -f ${B}/${USER_DTS_FILE}.dtbo ]; then | ||
| 233 | install -Dm 0644 ${S}/*.pdi ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.pdi | ||
| 234 | else | ||
| 235 | bbfatal "A PDI file with '.pdi' expected but not found" | ||
| 236 | fi | ||
| 237 | else | ||
| 238 | # In case of dtbo as input, .bit or .bin will be copied from directly | ||
| 239 | # from ${S} without renaming the .bit/.bin name to ${PN}.bit/${PN}.bin | ||
| 240 | # if more than one .bit/.bin file is found then fail the task. | ||
| 241 | if [ `ls ${S}/*.bit | wc -l` -gt 1 ]; then | ||
| 242 | bbfatal "Multiple .bit found, use the right .bit in SRC_URI from the following:\n$(basename -a ${S}/*.bit)" | ||
| 243 | elif [ `ls ${S}/*.bin | wc -l` -gt 1 ]; then | ||
| 244 | bbfatal "Multiple .bin found, use the right .bin in SRC_URI from the following:\n$(basename -a ${S}/*.bin)" | ||
| 245 | elif [ `ls ${S}/*.bit | wc -l` -eq 1 ] && [ `ls ${S}/*.dtbo | wc -l` -eq 1 ]; then | ||
| 246 | install -Dm 0644 ${S}/*.bit ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ | ||
| 247 | elif [ `ls ${S}/*.bin | wc -l` -eq 1 ] && [ `ls ${S}/*.dtbo | wc -l` -eq 1 ]; then | ||
| 248 | install -Dm 0644 ${S}/*.bin ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ | ||
| 249 | elif [ -f ${B}/${PN}.bit.bin ] && [ -f ${B}/${USER_DTS_FILE}.dtbo ]; then | ||
| 250 | install -Dm 0644 ${B}/${PN}.bit.bin ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.bit.bin | ||
| 251 | else | ||
| 252 | bbfatal "A bitstream file with '.bit' or '.bin' expected but not found" | ||
| 253 | fi | ||
| 254 | fi | ||
| 255 | |||
| 256 | if ls ${S}/${XCL_PATH}/*.xclbin >/dev/null 2>&1; then | ||
| 257 | install -Dm 0644 ${S}/${XCL_PATH}/*.xclbin ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/${PN}.xclbin | ||
| 258 | fi | ||
| 259 | |||
| 260 | if [ -f ${S}/${JSON_PATH}/shell.json ] || [ -f ${S}/${JSON_PATH}/accel.json ]; then | ||
| 261 | install -Dm 0644 ${S}/${JSON_PATH}/*.json ${D}/${nonarch_base_libdir}/firmware/xilinx/${PN}/ | ||
| 262 | fi | ||
| 263 | } | ||
| 264 | |||
| 265 | do_deploy[noexec] = "1" | ||
| 266 | |||
| 267 | FILES:${PN} += "${nonarch_base_libdir}/firmware/xilinx/${PN}" | ||
diff --git a/meta-xilinx-core/classes-recipe/image-wic-utils.bbclass b/meta-xilinx-core/classes-recipe/image-wic-utils.bbclass new file mode 100644 index 00000000..41ad8148 --- /dev/null +++ b/meta-xilinx-core/classes-recipe/image-wic-utils.bbclass | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | # Helper/utility functions to work with the IMAGE_BOOT_FILES variable and its | ||
| 2 | # expected behvaior with regards to the contents of the DEPLOY_DIR_IMAGE. | ||
| 3 | # | ||
| 4 | # The use of these functions assume that the deploy directory is populated with | ||
| 5 | # any dependent files/etc. Such that the recipe using these functions depends | ||
| 6 | # on the recipe that provides the files being used/queried. | ||
| 7 | |||
| 8 | def boot_files_split_expand(d): | ||
| 9 | # IMAGE_BOOT_FILES has extra renaming info in the format '<source>;<target>' | ||
| 10 | for f in (d.getVar("IMAGE_BOOT_FILES") or "").split(" "): | ||
| 11 | parts = f.split(";", 1) | ||
| 12 | sources = [parts[0].strip()] | ||
| 13 | if "*" in parts[0]: | ||
| 14 | # has glob part | ||
| 15 | import glob | ||
| 16 | deployroot = d.getVar("DEPLOY_DIR_IMAGE") | ||
| 17 | sources = [] | ||
| 18 | for i in glob.glob(os.path.join(deployroot, parts[0])): | ||
| 19 | sources.append(os.path.basename(i)) | ||
| 20 | |||
| 21 | # for all sources, yield an entry | ||
| 22 | for s in sources: | ||
| 23 | if len(parts) == 2: | ||
| 24 | if parts[1].endswith('/'): | ||
| 25 | yield s, '%s%s' % (parts[1].strip(), s) | ||
| 26 | else: | ||
| 27 | yield s, parts[1].strip() | ||
| 28 | yield s, s | ||
| 29 | |||
| 30 | def boot_files_bitstream(d): | ||
| 31 | expectedfiles = [("bitstream", True)] | ||
| 32 | expectedexts = [(".bit", True), (".bin", False)] | ||
| 33 | # search for bitstream paths, use the renamed file. First matching is used | ||
| 34 | for source, target in boot_files_split_expand(d): | ||
| 35 | # skip boot.bin and u-boot.bin, it is not a bitstream | ||
| 36 | skip = ["boot.bin", "u-boot.bin"] | ||
| 37 | if source in skip or target in skip: | ||
| 38 | continue | ||
| 39 | |||
| 40 | for e, t in expectedfiles: | ||
| 41 | if source == e or target == e: | ||
| 42 | return target, t | ||
| 43 | for e, t in expectedexts: | ||
| 44 | if source.endswith(e) or target.endswith(e): | ||
| 45 | return target, t | ||
| 46 | return "", False | ||
| 47 | |||
| 48 | def boot_files_dtb_filepath(d): | ||
| 49 | dtbs = (d.getVar("IMAGE_BOOT_FILES") or "").split(" ") | ||
| 50 | for source, target in boot_files_split_expand(d): | ||
| 51 | if target.endswith(".dtb"): | ||
| 52 | return target | ||
| 53 | return "" | ||
| 54 | |||
diff --git a/meta-xilinx-core/classes-recipe/kernel-simpleimage.bbclass b/meta-xilinx-core/classes-recipe/kernel-simpleimage.bbclass new file mode 100644 index 00000000..110ee254 --- /dev/null +++ b/meta-xilinx-core/classes-recipe/kernel-simpleimage.bbclass | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | python __anonymous () { | ||
| 2 | kerneltypes = set((d.getVar("KERNEL_IMAGETYPE") or "").split()) | ||
| 3 | kerneltypes |= set((d.getVar("KERNEL_IMAGETYPES") or "").split()) | ||
| 4 | if any(t.startswith("simpleImage.") for t in kerneltypes): | ||
| 5 | # Enable building of simpleImage | ||
| 6 | bb.build.addtask('do_prep_simpleimage', 'do_compile', 'do_configure', d) | ||
| 7 | uarch = d.getVar("UBOOT_ARCH") | ||
| 8 | if uarch == "microblaze": | ||
| 9 | d.appendVarFlag('do_prep_simpleimage', 'depends', ' virtual/dtb:do_populate_sysroot') | ||
| 10 | } | ||
| 11 | |||
| 12 | do_prep_simpleimage[dirs] += "${B}" | ||
| 13 | do_prep_simpleimage () { | ||
| 14 | install -d ${B}/arch/${ARCH}/boot/dts | ||
| 15 | for type in ${KERNEL_IMAGETYPES} ; do | ||
| 16 | if [ -z "${type##*simpleImage*}" ] && [ ${ARCH} = "microblaze" ]; then | ||
| 17 | ext="${type##*.}" | ||
| 18 | # Microblaze simpleImage only works with dts file | ||
| 19 | cp ${RECIPE_SYSROOT}/boot/devicetree/${ext}.dts ${B}/arch/${ARCH}/boot/dts/ | ||
| 20 | fi | ||
| 21 | done | ||
| 22 | } | ||
| 23 | |||
| 24 | do_deploy:append () { | ||
| 25 | for type in ${KERNEL_IMAGETYPES} ; do | ||
| 26 | if [ -z "${type##*simpleImage*}" ] && [ ${ARCH} = "microblaze" ]; then | ||
| 27 | base_name=${type}-${KERNEL_IMAGE_NAME} | ||
| 28 | install -m 0644 ${KERNEL_OUTPUT_DIR}/${type}.strip $deployDir/${base_name}.strip | ||
| 29 | install -m 0644 ${KERNEL_OUTPUT_DIR}/${type}.unstrip $deployDir/${base_name}.unstrip | ||
| 30 | symlink_name=${type}-${KERNEL_IMAGE_LINK_NAME} | ||
| 31 | ln -sf ${base_name}.strip $deployDir/${symlink_name}.strip | ||
| 32 | ln -sf ${base_name}.unstrip $deployDir/${symlink_name}.unstrip | ||
| 33 | fi | ||
| 34 | done | ||
| 35 | } | ||
diff --git a/meta-xilinx-core/classes-recipe/qemuboot-xilinx.bbclass b/meta-xilinx-core/classes-recipe/qemuboot-xilinx.bbclass new file mode 100644 index 00000000..7466ab5e --- /dev/null +++ b/meta-xilinx-core/classes-recipe/qemuboot-xilinx.bbclass | |||
| @@ -0,0 +1,140 @@ | |||
| 1 | |||
| 2 | # enable the overrides for the context of the conf only | ||
| 3 | OVERRIDES .= ":qemuboot-xilinx" | ||
| 4 | |||
| 5 | # Default machine targets for Xilinx QEMU (FDT Generic) | ||
| 6 | # Allow QB_MACHINE to be overridden by a BSP config | ||
| 7 | QB_MACHINE ?= "${QB_MACHINE_XILINX}" | ||
| 8 | QB_RNG="" | ||
| 9 | QB_MACHINE_XILINX:aarch64 = "-machine arm-generic-fdt" | ||
| 10 | QB_MACHINE_XILINX:arm = "-M arm-generic-fdt-7series" | ||
| 11 | QB_MACHINE_XILINX:microblaze = "-M microblaze-fdt-plnx" | ||
| 12 | |||
| 13 | QB_SYSTEM_NAME ?= "${@qemu_target_binary(d)}" | ||
| 14 | QB_DEFAULT_FSTYPE ?= "${@qemu_rootfs_params(d,'fstype')}" | ||
| 15 | QB_ROOTFS ?= "${@qemu_rootfs_params(d,'rootfs')}" | ||
| 16 | QB_ROOTFS_OPT ?= "${@qemu_rootfs_params(d,'rootfs-opt')}" | ||
| 17 | QB_DTB ?= "${@qemu_default_dtb(d)}" | ||
| 18 | |||
| 19 | # defaults | ||
| 20 | QB_DEFAULT_KERNEL ?= "none" | ||
| 21 | QB_DEFAULT_KERNEL:zynq ?= "${@'zImage' if \ | ||
| 22 | d.getVar('INITRAMFS_IMAGE_BUNDLE') != '1' else 'zImage-initramfs-${MACHINE}.bin'}" | ||
| 23 | QB_DEFAULT_KERNEL:microblaze ?= "${@'simpleImage.mb' if \ | ||
| 24 | d.getVar('INITRAMFS_IMAGE_BUNDLE') != '1' else 'simpleImage.mb-initramfs-${MACHINE}.bin'}" | ||
| 25 | |||
| 26 | inherit qemuboot | ||
| 27 | |||
| 28 | def qemu_target_binary(data): | ||
| 29 | package_arch = data.getVar("PACKAGE_ARCH") | ||
| 30 | qemu_target_binary = (data.getVar("QEMU_TARGET_BINARY_%s" % package_arch) or "") | ||
| 31 | if qemu_target_binary: | ||
| 32 | return qemu_target_binary | ||
| 33 | |||
| 34 | target_arch = data.getVar("TARGET_ARCH") | ||
| 35 | if target_arch == "microblazeeb": | ||
| 36 | target_arch = "microblaze" | ||
| 37 | elif target_arch == "aarch64": | ||
| 38 | target_arch += "-multiarch" | ||
| 39 | elif target_arch == "arm": | ||
| 40 | target_arch = "aarch64" | ||
| 41 | return "qemu-system-%s" % target_arch | ||
| 42 | |||
| 43 | def qemu_add_extra_args(data): | ||
| 44 | initramfs_image = data.getVar('INITRAMFS_IMAGE') or "" | ||
| 45 | bundle_image = data.getVar('INITRAMFS_IMAGE_BUNDLE') or "" | ||
| 46 | deploy_dir = data.getVar('DEPLOY_DIR_IMAGE') or "" | ||
| 47 | machine_name = data.getVar('MACHINE') or "" | ||
| 48 | soc_family = data.getVar('SOC_FAMILY') or "" | ||
| 49 | qb_extra_args = '' | ||
| 50 | # Add kernel image and boot.scr to qemu boot command when initramfs_image supplied | ||
| 51 | kernel_name = '' | ||
| 52 | bootscr_image = '%s/boot.scr' % deploy_dir | ||
| 53 | if soc_family in ('zynqmp', 'versal'): | ||
| 54 | kernel_name = 'Image' | ||
| 55 | bootscr_loadaddr = '0x20000000' | ||
| 56 | if initramfs_image: | ||
| 57 | kernel_image = '%s/%s' % (deploy_dir, kernel_name) | ||
| 58 | if bundle_image == "1": | ||
| 59 | kernel_image = '%s/%s-initramfs-%s.bin' % (deploy_dir, kernel_name, machine_name) | ||
| 60 | kernel_loadaddr = '0x200000' | ||
| 61 | if kernel_name: | ||
| 62 | qb_extra_args = ' -device loader,file=%s,addr=%s,force-raw=on' % (kernel_image, kernel_loadaddr) | ||
| 63 | qb_extra_args += ' -device loader,file=%s,addr=%s,force-raw=on' % (bootscr_image, bootscr_loadaddr) | ||
| 64 | if soc_family == 'versal': | ||
| 65 | qb_extra_args += ' -boot mode=5' | ||
| 66 | else: | ||
| 67 | if soc_family in ('zynqmp', 'versal'): | ||
| 68 | qb_extra_args = ' -boot mode=5' | ||
| 69 | return qb_extra_args | ||
| 70 | |||
| 71 | def qemu_rootfs_params(data, param): | ||
| 72 | initramfs_image = data.getVar('INITRAMFS_IMAGE') or "" | ||
| 73 | bundle_image = data.getVar('INITRAMFS_IMAGE_BUNDLE') or "" | ||
| 74 | soc_family = data.getVar('SOC_FAMILY') or "" | ||
| 75 | tune_features = (data.getVar('TUNE_FEATURES') or []).split() | ||
| 76 | if 'microblaze' in tune_features: | ||
| 77 | soc_family = 'microblaze' | ||
| 78 | soc_variant = data.getVar('SOC_VARIANT') or "" | ||
| 79 | |||
| 80 | if param == 'rootfs': | ||
| 81 | return 'none' if bundle_image == "1" else '' | ||
| 82 | |||
| 83 | elif param == 'fstype': | ||
| 84 | fstype_dict = { | ||
| 85 | "microblaze": "cpio.gz", | ||
| 86 | "zynq": "cpio.gz", | ||
| 87 | "zynqmp": "cpio.gz.u-boot", | ||
| 88 | "versal": "cpio.gz.u-boot.qemu-sd-fatimg" | ||
| 89 | } | ||
| 90 | if not initramfs_image: | ||
| 91 | image_fs = data.getVar('IMAGE_FSTYPES') | ||
| 92 | if 'wic.qemu-sd' in image_fs: | ||
| 93 | return 'wic.qemu-sd' | ||
| 94 | if soc_family not in fstype_dict: | ||
| 95 | return "" | ||
| 96 | return fstype_dict[soc_family] | ||
| 97 | |||
| 98 | elif param == 'rootfs-opt': | ||
| 99 | sd_index = "1" | ||
| 100 | if soc_family == 'zynq': | ||
| 101 | sd_index = "0" | ||
| 102 | if soc_family == 'versal' and soc_variant == 'net': | ||
| 103 | sd_index = "0" | ||
| 104 | |||
| 105 | # Device is using a disk | ||
| 106 | if not initramfs_image: | ||
| 107 | return ' -drive if=sd,index=%s,file=@ROOTFS@,format=raw' % (sd_index) | ||
| 108 | |||
| 109 | # Device is using a ramdisk | ||
| 110 | if soc_family not in ('zynq', 'microblaze'): | ||
| 111 | return ' -device loader,file=@ROOTFS@,addr=0x04000000,force-raw=on' | ||
| 112 | |||
| 113 | # Ramdisk must be compiled into the kernel | ||
| 114 | return '' | ||
| 115 | |||
| 116 | def qemu_default_dtb(data): | ||
| 117 | if data.getVar("IMAGE_BOOT_FILES", True): | ||
| 118 | dtbs = data.getVar("IMAGE_BOOT_FILES", True).split(" ") | ||
| 119 | # IMAGE_BOOT_FILES has extra renaming info in the format '<source>;<target>' | ||
| 120 | # Note: Wildcard sources work here only because runqemu expands them at run time | ||
| 121 | dtbs = [f.split(";")[0] for f in dtbs] | ||
| 122 | dtbs = [f for f in dtbs if f.endswith(".dtb")] | ||
| 123 | if len(dtbs) != 0: | ||
| 124 | return dtbs[0] | ||
| 125 | return "" | ||
| 126 | |||
| 127 | def qemu_default_serial(data): | ||
| 128 | if data.getVar("SERIAL_CONSOLES", True): | ||
| 129 | first_console = data.getVar("SERIAL_CONSOLES", True).split(" ")[0] | ||
| 130 | speed, console = first_console.split(";", 1) | ||
| 131 | # zynqmp uses earlycon and stdout (in dtb) | ||
| 132 | if "zynqmp" in data.getVar("MACHINEOVERRIDES", True).split(":"): | ||
| 133 | return "" | ||
| 134 | return "console=%s,%s earlyprintk" % (console, speed) | ||
| 135 | return "" | ||
| 136 | |||
| 137 | def qemu_zynqmp_unhalt(data, multiarch): | ||
| 138 | if multiarch: | ||
| 139 | return "-global xlnx,zynqmp-boot.cpu-num=0 -global xlnx,zynqmp-boot.use-pmufw=true" | ||
| 140 | 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-recipe/xilinx-fetch-restricted.bbclass b/meta-xilinx-core/classes-recipe/xilinx-fetch-restricted.bbclass new file mode 100644 index 00000000..a778ec7d --- /dev/null +++ b/meta-xilinx-core/classes-recipe/xilinx-fetch-restricted.bbclass | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | # This class is setup to override the default fetching for the target recipe. | ||
| 2 | # When fetching it forces PREMIRROR only fetching so that no attempts are made | ||
| 3 | # to fetch the Xilinx downloads that are restricted to authenticated users only. | ||
| 4 | # | ||
| 5 | # The purpose of this class is to allow for automatation with pre-downloaded | ||
| 6 | # content or content that is available with curated/user defined pre-mirrors | ||
| 7 | # and or pre-populated downloads/ directories. | ||
| 8 | |||
| 9 | python do_fetch() { | ||
| 10 | xilinx_restricted_url = "xilinx.com/member/forms/download" | ||
| 11 | |||
| 12 | src_uri = (d.getVar('SRC_URI') or "").split() | ||
| 13 | if len(src_uri) == 0: | ||
| 14 | return | ||
| 15 | |||
| 16 | for i in src_uri: | ||
| 17 | if xilinx_restricted_url in i: | ||
| 18 | # force the use of premirrors only, do not attempt download from xilinx.com | ||
| 19 | d.setVar("BB_FETCH_PREMIRRORONLY", "1") | ||
| 20 | break | ||
| 21 | |||
| 22 | try: | ||
| 23 | fetcher = bb.fetch2.Fetch(src_uri, d) | ||
| 24 | fetcher.download() | ||
| 25 | except bb.fetch2.NetworkAccess as e: | ||
| 26 | if xilinx_restricted_url in e.url: | ||
| 27 | # fatal on access to xilinx.com restricted downloads, print the url for manual download | ||
| 28 | bb.fatal("The following download cannot be fetched automatically. " \ | ||
| 29 | "Please manually download the file and place it in the 'downloads' directory (or on an available PREMIRROR).\n" \ | ||
| 30 | " %s" % (e.url.split(";")[0])) | ||
| 31 | else: | ||
| 32 | bb.fatal(str(e)) | ||
| 33 | except bb.fetch2.BBFetchException as e: | ||
| 34 | bb.fatal(str(e)) | ||
| 35 | } | ||
diff --git a/meta-xilinx-core/classes-recipe/xilinx-platform-init.bbclass b/meta-xilinx-core/classes-recipe/xilinx-platform-init.bbclass new file mode 100644 index 00000000..99f7863a --- /dev/null +++ b/meta-xilinx-core/classes-recipe/xilinx-platform-init.bbclass | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | # This class should be included by any recipe that wants to access or provide | ||
| 2 | # the platform init source files which are used to initialize a Zynq or ZynqMP | ||
| 3 | # SoC. | ||
| 4 | |||
| 5 | # Define the path to the xilinx platform init code/headers | ||
| 6 | PLATFORM_INIT_DIR ?= "/usr/src/xilinx-platform-init" | ||
| 7 | |||
| 8 | PLATFORM_INIT_STAGE_DIR = "${STAGING_DIR_HOST}${PLATFORM_INIT_DIR}" | ||
| 9 | |||
| 10 | # Target files use for platform init | ||
| 11 | PLATFORM_INIT_FILES ?= "" | ||
| 12 | PLATFORM_INIT_FILES:zynq = "ps7_init_gpl.c ps7_init_gpl.h" | ||
| 13 | PLATFORM_INIT_FILES:zynqmp = "psu_init_gpl.c psu_init_gpl.h" | ||
| 14 | |||
