summaryrefslogtreecommitdiffstats
path: root/meta-xilinx-core/classes-recipe
diff options
context:
space:
mode:
authorSandeep Gundlupet Raju <sandeep.gundlupet-raju@amd.com>2023-11-30 22:07:47 -0700
committerMark Hatle <mark.hatle@amd.com>2023-12-08 11:30:55 -0600
commit9b391bbaf9ed0b83a493f20e48594a1c1e3004ce (patch)
treed03c7dacabb3b02841fb9845495589ab5ea69443 /meta-xilinx-core/classes-recipe
parent9461f910a0b4415941d2bbac4406b37236d0a6de (diff)
downloadmeta-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')
-rw-r--r--meta-xilinx-core/classes-recipe/amd_spi_image.bbclass142
-rw-r--r--meta-xilinx-core/classes-recipe/dfx_user_dts.bbclass267
-rw-r--r--meta-xilinx-core/classes-recipe/image-wic-utils.bbclass54
-rw-r--r--meta-xilinx-core/classes-recipe/kernel-simpleimage.bbclass35
-rw-r--r--meta-xilinx-core/classes-recipe/qemuboot-xilinx.bbclass140
-rw-r--r--meta-xilinx-core/classes-recipe/xilinx-fetch-restricted.bbclass35
-rw-r--r--meta-xilinx-core/classes-recipe/xilinx-platform-init.bbclass14
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
7QSPI_SIZE ?= "0x2280000"
8
9# Register values
10IDN_REG ?= "0x4D554241"
11VERSION_REG ?= "0x1"
12LENGTH_REG ?= "0x4"
13PERSISTENT_REG ?= "0x01010000"
14
15# QSPI Offsets
16IMAGE_SELECTOR_OFFSET ?= "0x0"
17IMAGE_SELECTOR_BACKUP_OFFSET ?= "0x80000"
18PERSISTENT_REG_OFFSET ?= "0x100000"
19PERSISTENT_REG_BACKUP_OFFSET ?= "0x120000"
20IMAGE_A_OFFSET ?= "0x200000"
21IMAGE_A_IMGSEL_OFFSET ?= "0xF00000"
22IMAGE_B_OFFSET ?= "0xF80000"
23IMAGE_B_IMGSEL_OFFSET ?= "0x1C80000"
24IMAGE_RCVRY_OFFSET ?= "0x1E00000"
25IMAGE_RCVRY_BACKUP_OFFSET ?= "0x2000000"
26VERSION_OFFSET ?= "0x2240000"
27CHECKSUM_OFFSET ?= "0x2250000"
28
29def 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
136do_compile[depends] += "virtual/boot-bin:do_deploy virtual/imgsel:do_deploy virtual/imgrcry:do_deploy"
137
138python amd_spi_image_do_compile() {
139 generate_spi_image(d)
140}
141
142EXPORT_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
5inherit devicetree
6
7DEPENDS = "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
12COMPATIBLE_MACHINE ?= "^$"
13COMPATIBLE_MACHINE:microblaze = "^$"
14
15PACKAGE_ARCH = "${MACHINE_ARCH}"
16
17PROVIDES = ""
18
19do_fetch[cleandirs] = "${B}"
20
21DT_PADDING_SIZE = "0x1000"
22BOOTGEN_FLAGS ?= " -arch ${SOC_FAMILY} -w ${@bb.utils.contains('SOC_FAMILY','zynqmp','','-process_bitstream bin',d)}"
23
24S ?= "${WORKDIR}"
25FW_DIR ?= ""
26DTSI_PATH ?= ""
27DTBO_PATH ?= ""
28DT_FILES_PATH = "${S}/${DTSI_PATH}"
29FIRMWARE_NAME_DT_FILE ?= ""
30USER_DTS_FILE ?= ""
31
32FIRMWARE_NAME_DT_FILE[doc] = "DT file which has firmware-name device-tree property"
33USER_DTS_FILE[doc] = "Final DTSI or DTS file which is used for packaging final DT overlay"
34
35python() {
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.
103def 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.
109python 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
125do_configure[prefuncs] += "find_firmware_file"
126
127python 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
149do_compile[prefuncs] += "find_firmware_file"
150
151python 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.
193python 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
208do_install[prefuncs] += "find_user_dts_overlay_file"
209
210do_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
265do_deploy[noexec] = "1"
266
267FILES:${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
8def 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
30def 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
48def 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 @@
1python __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
12do_prep_simpleimage[dirs] += "${B}"
13do_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
24do_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
3OVERRIDES .= ":qemuboot-xilinx"
4
5# Default machine targets for Xilinx QEMU (FDT Generic)
6# Allow QB_MACHINE to be overridden by a BSP config
7QB_MACHINE ?= "${QB_MACHINE_XILINX}"
8QB_RNG=""
9QB_MACHINE_XILINX:aarch64 = "-machine arm-generic-fdt"
10QB_MACHINE_XILINX:arm = "-M arm-generic-fdt-7series"
11QB_MACHINE_XILINX:microblaze = "-M microblaze-fdt-plnx"
12
13QB_SYSTEM_NAME ?= "${@qemu_target_binary(d)}"
14QB_DEFAULT_FSTYPE ?= "${@qemu_rootfs_params(d,'fstype')}"
15QB_ROOTFS ?= "${@qemu_rootfs_params(d,'rootfs')}"
16QB_ROOTFS_OPT ?= "${@qemu_rootfs_params(d,'rootfs-opt')}"
17QB_DTB ?= "${@qemu_default_dtb(d)}"
18
19# defaults
20QB_DEFAULT_KERNEL ?= "none"
21QB_DEFAULT_KERNEL:zynq ?= "${@'zImage' if \
22 d.getVar('INITRAMFS_IMAGE_BUNDLE') != '1' else 'zImage-initramfs-${MACHINE}.bin'}"
23QB_DEFAULT_KERNEL:microblaze ?= "${@'simpleImage.mb' if \
24 d.getVar('INITRAMFS_IMAGE_BUNDLE') != '1' else 'simpleImage.mb-initramfs-${MACHINE}.bin'}"
25
26inherit qemuboot
27
28def 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
43def 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
71def 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
116def 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
127def 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
137def 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
9python 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
6PLATFORM_INIT_DIR ?= "/usr/src/xilinx-platform-init"
7
8PLATFORM_INIT_STAGE_DIR = "${STAGING_DIR_HOST}${PLATFORM_INIT_DIR}"
9
10# Target files use for platform init
11PLATFORM_INIT_FILES ?= ""
12PLATFORM_INIT_FILES:zynq = "ps7_init_gpl.c ps7_init_gpl.h"
13PLATFORM_INIT_FILES:zynqmp = "psu_init_gpl.c psu_init_gpl.h"
14