summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSandeep Gundlupet Raju <sandeep.gundlupet-raju@amd.com>2024-03-12 19:20:24 -0600
committerMark Hatle <mark.hatle@amd.com>2024-03-15 13:08:07 -0500
commit3a9cd6df2cda6e502c2e4556303ef77006d8387a (patch)
tree030322e7f935e14ed1a22e64ad83ca8f81f06758
parentd10b2f6f3c502265830583f994d31de7d5d6e48b (diff)
downloadmeta-xilinx-3a9cd6df2cda6e502c2e4556303ef77006d8387a.tar.gz
boot-jtag.py: Add devtool script for jtag boot mode
This script uses devtool and creates a boot-jtag.tcl script in ${DEPLOY_DIR_IMAGE} directory. This script is executed by xsdb tool to boot yocto generated images on HW via jtag boot mode. Signed-off-by: Sandeep Gundlupet Raju <sandeep.gundlupet-raju@amd.com> Signed-off-by: Mark Hatle <mark.hatle@amd.com>
-rw-r--r--meta-xilinx-core/lib/devtool/boot-jtag.py272
1 files changed, 272 insertions, 0 deletions
diff --git a/meta-xilinx-core/lib/devtool/boot-jtag.py b/meta-xilinx-core/lib/devtool/boot-jtag.py
new file mode 100644
index 00000000..53d70262
--- /dev/null
+++ b/meta-xilinx-core/lib/devtool/boot-jtag.py
@@ -0,0 +1,272 @@
1# Copyright (C) 2021-2022, Xilinx, Inc. All rights reserved.
2# Copyright (C) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
3#
4# SPDX-License-Identifier: MIT
5#
6# This script uses devtool and creates a boot-jtag.tcl script in
7# ${DEPLOY_DIR_IMAGE} directory. This script is executed by xsdb tool to boot
8# yocto generated images on HW via jtag boot mode.
9
10import os
11import logging
12import argparse
13from devtool import setup_tinfoil, parse_recipe, DevtoolError
14import yaml
15import sys
16import glob
17
18logger = logging.getLogger('devtool')
19
20def bootjtag(args, config, basepath, workspace):
21 """Entry point for the devtool 'boot-jtag' subcommand"""
22
23 if not args.image:
24 print('\nINFO: Please specify the target image name. \n\nExample: --image core-image-minimal or petalinux-image-minimal')
25 return
26
27 # Get required boot variables
28 tinfoil = setup_tinfoil(basepath=basepath)
29 try:
30 rd = tinfoil.parse_recipe('u-boot-xlnx-scr')
31 deploy_dir = rd.getVar('DEPLOY_DIR_IMAGE')
32 machine = rd.getVar('MACHINE')
33 arch = rd.getVar('TARGET_ARCH')
34 soc = rd.getVar("SOC_FAMILY")
35 soc_variant = rd.getVar("SOC_VARIANT")
36 ddr_base_addr = rd.getVar('DDR_BASEADDR')
37 kernel_img_name = rd.getVar('KERNEL_IMAGE')
38 kernel_load_addr = rd.getVar('KERNEL_LOAD_ADDRESS')
39 dtb_load_addr = rd.getVar('DEVICETREE_ADDRESS')
40 rootfs_load_addr = rd.getVar('RAMDISK_IMAGE_ADDRESS')
41 machine_features = rd.getVar('MACHINE_FEATURES')
42 boot_mode = rd.getVar('BOOTMODE')
43 finally:
44 tinfoil.shutdown()
45
46 if not args.hw_server:
47 print("\nINFO: --hw_server is null so default URL description of hw_server/TCF agent and port number is set to: " + str(args.hw_server))
48
49 print("INFO: HW_SERVER Connected to: " + str(args.hw_server))
50 print("INFO: Using DISTRO IMAGE: " + str(args.image))
51
52 # Use arch for MB and SOC Family other devices.
53 if arch == 'microblazeel':
54 print("INFO: ARCH: " + arch)
55 else:
56 print("INFO: SOC FAMILY: " + soc)
57
58 # Load Address of boot.scr in DDR(Except for QSPI/OSPI/NAND boot)
59 # MB = (DDR base address + DDR Size) - 0xe00000
60 # Zynq 7000 = DDR base address + 0x3000000
61 # ZynqMP = DDR base address + 0x20000000
62 # Versal = DDR base address + 0x20000000
63 if arch == 'microblazeel':
64 # Assuming DDR size is 2GB
65 bootscr_addr = hex(int(ddr_base_addr, 16) + 0x80000000 - 0xe00000)
66 elif soc == 'zynq':
67 bootscr_addr = hex(int(ddr_base_addr, 16) + 0x3000000)
68 else:
69 bootscr_addr = hex(int(ddr_base_addr, 16) + 0x20000000)
70
71 print("INFO: MACHINE: " + machine)
72
73 if arch != 'microblazeel':
74 if "fpga-overaly" in machine_features:
75 print("INFO: fpga-overlay MACHINE_FEATURES is enabled, Hence PL bitstream or PDI will not be loaded at initial boot, User can load from u-boot or linux.")
76 else:
77 print("INFO: fpga-overlay MACHINE_FEATURES is not enabled, Hence PL bitstream or PDI will be loaded at initial boot.")
78
79 #dictionary with all required artifacts
80 data = {}
81
82 # For MB, Zynq 7000 and ZynqMP.
83 if arch == 'microblazeel' or soc == 'zynq' or soc == 'zynqmp':
84 if not "fpga-overaly" in machine_features:
85 data['bit'] = glob.glob(os.path.join(deploy_dir, '*' + machine + '.bit'))[0]
86 data['uboot'] = os.path.join(deploy_dir, 'u-boot.elf')
87 data['dtb'] = os.path.join(deploy_dir, machine + '-system.dtb')
88
89 if soc == 'zynq' or soc == 'zynqmp':
90 data['fsbl'] = os.path.join(deploy_dir, 'fsbl-' + machine + '.elf')
91
92 if soc == 'zynqmp':
93 data['atf'] = os.path.join(deploy_dir, 'arm-trusted-firmware.elf')
94 data['pmufw'] = os.path.join(deploy_dir, 'pmu-firmware-' + machine + '.elf')
95
96 if soc == 'versal':
97 data['bootbin'] = os.path.join(deploy_dir, 'boot.bin')
98
99 data['bootscr'] = os.path.join(deploy_dir, 'boot.scr')
100 data['kernel'] = os.path.join(deploy_dir, kernel_img_name)
101
102 if not args.norootfs:
103 data['rfs'] = os.path.join(deploy_dir, args.image + '-' + machine + '.cpio.gz.u-boot')
104
105 # Check if all the required boot images exists
106 for key in data:
107 if not os.path.isfile(data[key]):
108 print('INFO:' + key + ' does not exist.')
109 print('INFO: Please make sure you have run: \n\'MACHINE=' + machine + ' devtool build-image ' + args.image + '\'')
110 return
111
112 # Enable verbose mode
113 if args.verbose:
114 print("The following artifacts are being loaded:")
115 for key in data:
116 print('INFO: ' + key + ": " + data[key])
117
118 # Start writing xsdb script
119 lines = []
120 lines.append('# Run \'xsdb ' + deploy_dir + '/boot-jtag.tcl\' to execute this script.')
121 lines.append('connect -url ' + args.hw_server)
122
123 if arch == 'microblazeel' or soc == 'zynq' or soc == 'zynqmp':
124 lines.append('for {set i 0} {$i < 20} {incr i} {')
125 lines.append(' if { [ta] != "" } break;')
126 lines.append(' after 50')
127 lines.append('}')
128 if not "fpga-overaly" in machine_features:
129 lines.append('')
130 lines.append('puts stderr "INFO: Configuring the PL ..."')
131 lines.append('puts stderr "INFO: Downloading bitstream: ' + data['bit'] + '"')
132 lines.append('fpga -no-revision-check \"' + data['bit'] + '\"')
133
134 if soc == 'zynqmp':
135 # Disable Security gates to view PMU MB target
136 lines.append('')
137 lines.append('targets -set -nocase -filter {name =~ \"*PSU*\"}')
138
139 # By default, JTAG security gates are enabled. This disables security gates for DAP, PLTAP and PMU.
140 lines.append('mask_write 0xFFCA0038 0x1C0 0x1C0')
141 lines.append('targets -set -nocase -filter {name =~ \"*MicroBlaze PMU*\"}')
142 lines.append('')
143
144 # Check if the target is already stopped or cannot be stopped.
145 lines.append('catch {stop}; after 1000')
146 lines.append('')
147
148 # Download the pmufw.elf and run PMUFW
149 lines.append('puts stderr "INFO: Downloading PMUFW ELF file: ' + data['pmufw'] + '"')
150 lines.append('dow \"' + data['pmufw'] + '\"')
151 lines.append('con')
152
153 # Select A53 Core 0 to load and run FSBL
154 lines.append('targets -set -nocase -filter {name =~ \"*A53*#0\"}')
155
156 # Reset A53, If the reset is being triggered after powering on the device,
157 # write bootloop at reset vector address (0xffff0000), or use
158 # -clear-registers option, to avoid unpredictable behavior.
159 # Further warnings will be suppressed
160 lines.append('rst -processor -clear-registers')
161 lines.append('')
162 elif soc == 'versal':
163 # Download boot.bin to versal device
164 lines.append('targets -set -nocase -filter {name =~ \"*PMC*\"}')
165 lines.append('puts stderr "INFO: Downloading BOOT bin file: ' + data['bootbin'] + '"')
166 lines.append('device program \"' + data['bootbin'] + '\"')
167 lines.append('')
168
169 if soc_variant == 'net':
170 lines.append('targets -set -nocase -filter {name =~ \"*A78*#0\"}')
171 else:
172 lines.append('targets -set -nocase -filter {name =~ \"*A72*#0\"}')
173
174 lines.append('stop')
175 lines.append('')
176 lines.append('targets -set -nocase -filter {name =~ \"*Versal*\"}')
177 elif soc == 'zynq':
178 lines.append('targets -set -nocase -filter {name =~ \"arm*#0\"}')
179 # Check if the target is already stopped or cannot be stopped.
180 lines.append('catch {stop}; after 1000')
181 lines.append('')
182 else:
183 lines.append('targets -set -nocase -filter {name =~ \"microblaze*#0\"}')
184 # Check if the target is already stopped or cannot be stopped.
185 lines.append('catch {stop}; after 1000')
186 lines.append('')
187
188
189 if soc == 'zynq' or soc == 'zynqmp':
190 # Download FSBL for Zynq 7000 and ZynqMP
191 lines.append('puts stderr "INFO: Downloading FSBL ELF file: ' + data['fsbl'] + '"')
192 lines.append('dow \"' + data['fsbl'] + '\"')
193 lines.append('con')
194 lines.append('after 4000; stop')
195 lines.append('')
196
197 # Download U-boot and DTB for MB, Zynq 7000 and ZynqMP
198 if arch == 'microblazeel' or soc == 'zynq' or soc == 'zynqmp':
199 lines.append('puts stderr "INFO: Downloading U-boot ELF file: ' + data['uboot'] + '"')
200 lines.append('dow \"' + data['uboot'] + '\"')
201 lines.append('')
202 # For MB and Zynq 7000 we need to connect and stop before loading
203 # kernel images
204 if soc != 'zynqmp':
205 lines.append('con')
206 lines.append('after 1000; stop')
207 lines.append('puts stderr "INFO: Downloading DTB file: ' + data['dtb'] + ' at ' + dtb_load_addr + '"')
208 lines.append('dow -data \"' + data['dtb'] + '\" ' + dtb_load_addr)
209 lines.append('')
210
211 # Download Trusted Firmware-A(TF-A) for ZynqMP
212 # Note: TF-A elf should be loaded after u-boot elf in JTAG boot mode else
213 # TF-A elf will not be loaded.
214 if soc == 'zynqmp':
215 lines.append('puts stderr "INFO: Downloading Trusted Firmware-A(TF-A) ELF file: ' + data['atf'] + '"')
216 lines.append('dow \"' + data['atf'] + '\"')
217 lines.append('')
218
219 # If BOOTMODE is xen then boot till u-boot only.
220 # Download Kernel Image for all architecture
221 if boot_mode != 'xen':
222 lines.append('puts stderr "INFO: Downloading Kernel Image file: ' + data['kernel'] + ' at ' + kernel_load_addr + '"')
223 lines.append('dow -data \"' + data['kernel'] + '\" ' + kernel_load_addr)
224 lines.append('')
225
226 # Download Rootfs
227 if not args.norootfs and boot_mode != 'xen':
228 lines.append('puts stderr "INFO: Downloading Rootfs file: ' + data['rfs'] + ' at ' + rootfs_load_addr + '"')
229 lines.append('dow -data \"' + data['rfs'] + '\" ' + rootfs_load_addr)
230 lines.append('')
231
232 lines.append('puts stderr "INFO: Downloading U-boot boot script: ' + data['bootscr'] + ' at ' + bootscr_addr + '"')
233 lines.append('dow -data \"' + data['bootscr'] + '\" ' + bootscr_addr)
234 lines.append('')
235
236 # Select A72 Core 0 to load and run Versal images
237 if soc == 'versal':
238 if soc_variant == 'net':
239 lines.append('targets -set -nocase -filter {name =~ \"*A78*#0\"}')
240 else:
241 lines.append('targets -set -nocase -filter {name =~ \"*A72*#0\"}')
242
243 lines.append('con')
244 lines.append('exit\n')
245
246 script = os.path.join(deploy_dir, "boot-jtag.tcl")
247 with open(script, "w") as f:
248 f.write('\n'.join(lines))
249
250 print('INFO: HW JTAG boot tcl script written to '+ script + "\n" \
251 + 'INFO: User can run \'xsdb ' + script + '\' to execute.')
252
253 return 0
254
255def register_commands(subparsers, context):
256 """Register devtool subcommands from this plugin"""
257 parser_bootjtag = subparsers.add_parser('boot-jtag',
258 help='Script to deploy target images on HW via JTAG boot mode.',
259 description='Script to deploy target images on HW via JTAG boot mode. \
260 Example command: MACHINE=zcu102-zynqmp devtool boot-jtag --image ${image_name} --hw_server ${hw_server}')
261 required = parser_bootjtag.add_argument_group('required arguments')
262 required.add_argument('--image',
263 help='Specify target image name. Example: core-image-minimal or petalinux-image-minimal')
264 parser_bootjtag.add_argument('--hw_server', nargs='?', default='TCP:localhost:3121',
265 help='URL description of hw_server/TCF agent and port number. (default: %(default)s) \
266 Example: --hw_server TCP:puffball12:3121')
267
268 parser_bootjtag.add_argument('-v', '--verbose',
269 help='verbose mode', action="store_true")
270 parser_bootjtag.add_argument('-n', '--norootfs',
271 help='Don\'t include rootfs', action='store_true')
272 parser_bootjtag.set_defaults(func=bootjtag, no_workspace=True)