diff options
| -rw-r--r-- | meta-xilinx-core/recipes-devtools/qemu/files/qemu-system-aarch64-multiarch | 76 |
1 files changed, 59 insertions, 17 deletions
diff --git a/meta-xilinx-core/recipes-devtools/qemu/files/qemu-system-aarch64-multiarch b/meta-xilinx-core/recipes-devtools/qemu/files/qemu-system-aarch64-multiarch index e66c0fd0..d3328fa7 100644 --- a/meta-xilinx-core/recipes-devtools/qemu/files/qemu-system-aarch64-multiarch +++ b/meta-xilinx-core/recipes-devtools/qemu/files/qemu-system-aarch64-multiarch | |||
| @@ -74,7 +74,7 @@ def help(status): | |||
| 74 | if not set(APU_args).intersection(set(help_options)): | 74 | if not set(APU_args).intersection(set(help_options)): |
| 75 | APU_args.append('-help') | 75 | APU_args.append('-help') |
| 76 | print(f"APU Options:\n") | 76 | print(f"APU Options:\n") |
| 77 | print(f" -bootbin <boot.bin> - Use a boot.bin instead of individual firmware, device trees and bootloader\n") | 77 | print(f" -bootbin [arch:]<boot.bin> - Use a boot.bin instead of individual firmware, device trees and bootloader. While arch: is optonal, it is recommended. The default arch is 'versal'.\n") |
| 78 | print(f" -dtb - Specify hardware dtb for the APU\n") | 78 | print(f" -dtb - Specify hardware dtb for the APU\n") |
| 79 | print(f" -kernel - option is filtered out, but is available for compatibility\n") | 79 | print(f" -kernel - option is filtered out, but is available for compatibility\n") |
| 80 | apu_args_s = ' '.join(APU_args) | 80 | apu_args_s = ' '.join(APU_args) |
| @@ -83,6 +83,10 @@ def help(status): | |||
| 83 | print(f" -machine-path <path> - Optional path to use for multiarch files. This path must be less then about 100 characters.\n Note: if specified caller is responsible for cleaning up the directory on exist\n") | 83 | print(f" -machine-path <path> - Optional path to use for multiarch files. This path must be less then about 100 characters.\n Note: if specified caller is responsible for cleaning up the directory on exist\n") |
| 84 | 84 | ||
| 85 | print(f"{help_cmd}\n") | 85 | print(f"{help_cmd}\n") |
| 86 | |||
| 87 | # Without this the Popen below can end up printing before the above | ||
| 88 | sys.stdout.flush() | ||
| 89 | |||
| 86 | process = subprocess.Popen(help_cmd, shell=True, stderr=subprocess.PIPE) | 90 | process = subprocess.Popen(help_cmd, shell=True, stderr=subprocess.PIPE) |
| 87 | status = process.wait() | 91 | status = process.wait() |
| 88 | sys.exit(status) | 92 | sys.exit(status) |
| @@ -121,16 +125,32 @@ if PMU_args: | |||
| 121 | '\nSee "meta-xilinx/README.qemu.md" for more information on accquiring the PMU ROM.\n') | 125 | '\nSee "meta-xilinx/README.qemu.md" for more information on accquiring the PMU ROM.\n') |
| 122 | 126 | ||
| 123 | if bootbin_arg: | 127 | if bootbin_arg: |
| 124 | if not os.path.isfile(bootbin_arg): | 128 | # List of valid bootgen arches and settings |
| 125 | print(f"\nERROR: bootbin file not found at {bootbin_arg}\n") | 129 | archs = [ 'versal' ] |
| 130 | boot_header_addr = {'versal' : '0xf201e000'} | ||
| 131 | |||
| 132 | # The bootbin is separated into "arch:file" | ||
| 133 | # Default to versal for legacy reasons | ||
| 134 | arch = 'versal' | ||
| 135 | bootbin_fn = bootbin_arg | ||
| 136 | |||
| 137 | if ':' in bootbin_arg: | ||
| 138 | (arch, bootbin_fn) = bootbin_arg.split(':', 1) | ||
| 139 | |||
| 140 | if not os.path.isfile(bootbin_fn): | ||
| 141 | print(f"\nERROR: bootbin file not found at {bootbin_fn}\n") | ||
| 142 | sys.exit(1) | ||
| 143 | |||
| 144 | if arch not in archs: | ||
| 145 | print(f"\nERROR: bootbin arch {arch} not valid ({archs})\n") | ||
| 126 | sys.exit(1) | 146 | sys.exit(1) |
| 127 | 147 | ||
| 128 | shutil.copyfile(bootbin_arg, f'{mach_path}/boot.bin') | 148 | shutil.copyfile(bootbin_fn, f'{mach_path}/boot.bin') |
| 129 | 149 | ||
| 130 | bootgen_command = [f'{binpath}/bootgen', '-arch', 'versal', '-dump', 'boot.bin'] | 150 | bootgen_command = [f'{binpath}/bootgen', '-arch', arch, '-dump', 'boot.bin'] |
| 131 | subprocess.run(bootgen_command + ['boot_files'], check=True, cwd=mach_path, stdout=subprocess.DEVNULL) | 151 | subprocess.run(bootgen_command + ['boot_files'], check=True, cwd=mach_path, stdout=subprocess.DEVNULL) |
| 132 | 152 | ||
| 133 | bootgen_command = f"{binpath}/bootgen -arch versal -read {bootbin_arg}" | 153 | bootgen_command = f"{binpath}/bootgen -arch {arch} -read {bootbin_fn}" |
| 134 | result = subprocess.check_output(bootgen_command.split()) | 154 | result = subprocess.check_output(bootgen_command.split()) |
| 135 | bootgen_output = result.decode().splitlines() | 155 | bootgen_output = result.decode().splitlines() |
| 136 | 156 | ||
| @@ -142,15 +162,26 @@ if bootbin_arg: | |||
| 142 | 162 | ||
| 143 | plm_load_addr = re.search(r"exec_addr_lo \(0x10\) : (0x\w*)\s*", plm_line).group(1) | 163 | plm_load_addr = re.search(r"exec_addr_lo \(0x10\) : (0x\w*)\s*", plm_line).group(1) |
| 144 | pmc_load_addr = re.search(r"pmccdo_load_addr \(0x20\) : (0x\w*)", pmc_line).group(1) | 164 | pmc_load_addr = re.search(r"pmccdo_load_addr \(0x20\) : (0x\w*)", pmc_line).group(1) |
| 145 | print(f"qemu-system-aarch64-multiarch: INFO: Using QSPI/OSPI bootbin file\n") | 165 | print(f"qemu-system-aarch64-multiarch: INFO: Using QSPI/OSPI bootbin file") |
| 146 | print(f"qemu-system-aarch64-multiarch: INFO: bootbin file dump PLM load addr: {plm_load_addr}\n") | ||
| 147 | print(f"qemu-system-aarch64-multiarch: INFO: bootbin file dump PMC load addr: {pmc_load_addr}\n") | ||
| 148 | 166 | ||
| 149 | PLM_args.append(f"-device loader,file={mach_path}/boot_bh.bin,addr=0xF201E000,force-raw=on") | 167 | boot_bh_addr = boot_header_addr[arch] |
| 168 | if boot_bh_addr and os.path.exists(f'{mach_path}/boot_bh.bin'): | ||
| 169 | print(f"qemu-system-aarch64-multiarch: INFO: boot header load addr: {boot_bh_addr}") | ||
| 170 | PLM_args.append(f"-device loader,file={mach_path}/boot_bh.bin,addr={boot_bh_addr},force-raw=on") | ||
| 171 | else: | ||
| 172 | print(f"\nERROR: boot header ({mach_path}/boot_bh.bin) or boot header ({boot_bh_addr}) address is missing\n") | ||
| 173 | sys.exit(1) | ||
| 174 | |||
| 175 | print(f"qemu-system-aarch64-multiarch: INFO: bootbin file dump PMC load addr: {pmc_load_addr}") | ||
| 150 | PLM_args.append(f"-device loader,file={mach_path}/pmc_cdo.bin,addr={pmc_load_addr},force-raw=on") | 176 | PLM_args.append(f"-device loader,file={mach_path}/pmc_cdo.bin,addr={pmc_load_addr},force-raw=on") |
| 177 | |||
| 178 | print(f"qemu-system-aarch64-multiarch: INFO: bootbin file dump PLM load addr: {plm_load_addr}") | ||
| 151 | PLM_args.append(f"-device loader,file={mach_path}/plm.bin,addr={plm_load_addr},force-raw=on") | 179 | PLM_args.append(f"-device loader,file={mach_path}/plm.bin,addr={plm_load_addr},force-raw=on") |
| 152 | PLM_args.append(f"-device loader,addr={plm_load_addr},cpu-num=1") | 180 | PLM_args.append(f"-device loader,addr={plm_load_addr},cpu-num=1") |
| 153 | 181 | ||
| 182 | # Add blank to make the above easier to read | ||
| 183 | print() | ||
| 184 | |||
| 154 | # We use the normal -dtb argument to specify the hw-dtb for the multiarch runner, as -dtb is not applicable. | 185 | # We use the normal -dtb argument to specify the hw-dtb for the multiarch runner, as -dtb is not applicable. |
| 155 | if dtb_arg: | 186 | if dtb_arg: |
| 156 | APU_args.append(f"-hw-dtb {dtb_arg}") | 187 | APU_args.append(f"-hw-dtb {dtb_arg}") |
| @@ -184,15 +215,26 @@ if mb_cmd: | |||
| 184 | if apu_cmd: | 215 | if apu_cmd: |
| 185 | process_apu = subprocess.Popen(apu_cmd, shell=True, stderr=subprocess.PIPE) | 216 | process_apu = subprocess.Popen(apu_cmd, shell=True, stderr=subprocess.PIPE) |
| 186 | 217 | ||
| 218 | rc = 0 | ||
| 187 | error_msg = "" | 219 | error_msg = "" |
| 188 | if apu_cmd and process_apu.wait(): | 220 | if apu_cmd: |
| 189 | # We only check for failures on the MB instance if APU fails | 221 | apu_rc = process_apu.wait() |
| 190 | error_msg += '\nQEMU APU instance failed:\n%s' % process_apu.stderr.read().decode() | 222 | if apu_rc: |
| 191 | 223 | rc = apu_rc | |
| 192 | if mb_cmd and process_mb.wait(): | 224 | error_msg += '\nQEMU APU instance failed (%s):\n%s' % (apu_rc, process_apu.stderr.read().decode()) |
| 193 | error_msg += '\nQEMU MB instance failed:\n%s' % process_mb.stderr.read().decode() | 225 | |
| 226 | # We only report errors for MB if the APU failed (or APU wasn't started) | ||
| 227 | # otherwise we assume that the shutdown of the APU is the cause of the error | ||
| 228 | try: | ||
| 229 | if mb_cmd: | ||
| 230 | mb_rc = process_mb.wait(timeout=5) | ||
| 231 | if mb_rc and (apu_cmd and apu_rc): | ||
| 232 | rc += mb_rc | ||
| 233 | error_msg += '\nQEMU MB instance failed (%s):\n%s' % (mb_rc, process_mb.stderr.read().decode()) | ||
| 234 | except subprocess.TimeoutExpired: | ||
| 235 | process_mb.kill() | ||
| 194 | 236 | ||
| 195 | if not mach_path_arg: | 237 | if not mach_path_arg: |
| 196 | shutil.rmtree(mach_path) | 238 | shutil.rmtree(mach_path) |
| 197 | 239 | ||
| 198 | sys.exit(error_msg) | 240 | sys.exit(apu_rc) |
