blob: 1744bd95c230a67d53ddb98e2789071ddae7972b [file]
# Licensed under the Apache-2.0 license
# SPDX-License-Identifier: Apache-2.0
load("@pigweed//pw_kernel/tooling:system_image.bzl", "SystemImageInfo")
load("//target/earlgrey/tooling:qemu.bzl", "gen_flash")
load("//target/earlgrey/tooling/signing:defs.bzl", "KeySetInfo", "sign_binary")
def _target_type_transition_impl(_, attr):
if attr.interface == "hyper310" or attr.interface == "hyper340":
return {"//target/earlgrey:target_type": "fpga"}
if attr.interface == "verilator":
return {"//target/earlgrey:target_type": "verilator"}
if attr.interface == "qemu":
return {"//target/earlgrey:target_type": "qemu"}
return {"//target/earlgrey:target_type": "silicon"}
_target_type_transition = transition(
implementation = _target_type_transition_impl,
inputs = [],
outputs = ["//target/earlgrey:target_type"],
)
def _opentitan_runner_impl(ctx):
system_image_info = ctx.attr.target[0][SystemImageInfo]
elf_file = system_image_info.elf
bin_file = system_image_info.bin
runner = ctx.executable._opentitan_runner
if ctx.attr.ecdsa_key:
result = sign_binary(
ctx,
ctx.executable._opentitantool,
bin = bin_file,
basename = ctx.attr.name,
)
bin_file = result["signed"]
optional_args = ""
if hasattr(ctx.attr, "exit_success") and ctx.attr.exit_success:
optional_args += " --exit-success='{}'".format(ctx.attr.exit_success)
if hasattr(ctx.attr, "exit_failure") and ctx.attr.exit_failure:
optional_args += " --exit-failure='{}'".format(ctx.attr.exit_failure)
if ctx.attr.interface == "qemu":
flash_file = gen_flash(
ctx,
flashgen = ctx.attr._flashgen,
firmware_bin = bin_file,
firmware_elf = elf_file,
)
cfg_file = ctx.attr._qemu_cfg[DefaultInfo].files.to_list()[0]
otp_file = ctx.attr._qemu_otp[DefaultInfo].files.to_list()[0]
qemu_bin = ctx.file._qemu_bin
qemu_rom = ctx.file._qemu_rom
qemu_start = ctx.file._qemu_start
qemu_runner_exe = ctx.executable._qemu_runner
run_script = ctx.actions.declare_file(ctx.attr.name + ".sh")
ctx.actions.write(
output = run_script,
is_executable = True,
content = """#!/bin/bash
{runner} \
--qemu-start {qemu_start} \
--qemu-bin {qemu_bin} \
--qemu-config {cfg} \
--qemu-rom {rom} \
--qemu-otp {otp} \
--qemu-flash {flash} \
--firmware-elf {elf} \
--icount 6 \
--timeout-seconds 120 \
{optional_args}
""".format(
runner = qemu_runner_exe.short_path,
qemu_start = qemu_start.short_path,
qemu_bin = qemu_bin.short_path,
cfg = cfg_file.short_path,
rom = qemu_rom.short_path,
otp = otp_file.short_path,
flash = flash_file.short_path,
elf = elf_file.short_path,
optional_args = optional_args,
),
)
qemu_runner_runfiles = ctx.attr._qemu_runner[DefaultInfo].default_runfiles.files
return [DefaultInfo(
runfiles = ctx.runfiles(
files = [elf_file, bin_file, qemu_bin, qemu_rom, qemu_start, cfg_file, otp_file, flash_file],
transitive_files = qemu_runner_runfiles,
),
executable = run_script,
)]
if ctx.attr.interface == "hyper310" or ctx.attr.interface == "hyper340":
load_bitstream = "--load-bitstream"
mechanism = "--mechanism=bootstrap"
elif ctx.attr.interface == "teacup":
load_bitstream = ""
mechanism = "--mechanism=rescue"
else:
load_bitstream = ""
mechanism = ""
run_script = ctx.actions.declare_file(ctx.attr.name + ".sh")
ctx.actions.write(
output = run_script,
is_executable = True,
content = """#!/bin/bash
{runner} --interface {interface} {load_bitstream} {mechanism} --elf {elf} --bin {bin} {optional_args} "$@"
""".format(
runner = runner.short_path,
interface = ctx.attr.interface,
load_bitstream = load_bitstream,
mechanism = mechanism,
elf = elf_file.short_path,
bin = bin_file.short_path,
optional_args = optional_args,
),
)
runner_files_depset = ctx.attr._opentitan_runner[DefaultInfo].default_runfiles.files
return [DefaultInfo(
runfiles = ctx.runfiles(
files = [elf_file, bin_file, runner],
transitive_files = runner_files_depset,
),
executable = run_script,
)]
_BASE_ATTRS = {
"ecdsa_key": attr.label_keyed_string_dict(
allow_files = True,
providers = [KeySetInfo],
doc = "ECDSA public key to validate this image",
),
"interface": attr.string(
values = ["hyper310", "hyper340", "qemu", "teacup", "verilator"],
mandatory = True,
),
"manifest": attr.label(
allow_single_file = True,
doc = "A json manifest to apply to the image being signed",
),
"spx_key": attr.label_keyed_string_dict(
allow_files = True,
providers = [KeySetInfo],
doc = "SPX public key to validate this image",
),
"target": attr.label(
doc = "The system_image target to run.",
mandatory = True,
providers = [SystemImageInfo],
cfg = _target_type_transition,
),
"_opentitan_runner": attr.label(
executable = True,
cfg = "exec",
default = "//target/earlgrey/tooling:opentitan_runner",
),
"_opentitantool": attr.label(
executable = True,
allow_single_file = True,
cfg = "exec",
default = "@opentitan_devbundle//:opentitantool/opentitantool",
doc = "opentitantool",
),
}
# Hidden attrs for the qemu interface. Kept separate from _BASE_ATTRS because
# several of these deps are testonly=True; merging them into _BASE_ATTRS would
# prevent non-test opentitan_runner targets from loading without errors.
_QEMU_ATTRS = {
"_flashgen": attr.label(
executable = True,
cfg = "exec",
default = "//third_party/qemu:flashgen",
),
"_qemu_bin": attr.label(
allow_single_file = True,
cfg = "exec",
default = "//third_party/qemu:qemu-system-riscv32",
),
"_qemu_cfg": attr.label(
default = "//target/earlgrey/tooling:qemu_earlgrey_cfg",
),
"_qemu_otp": attr.label(
default = "//target/earlgrey/tooling:qemu_rma_otp",
),
"_qemu_rom": attr.label(
allow_single_file = True,
cfg = "exec",
default = "@opentitan_devbundle//:earlgrey/test_rom/test_rom_sim_verilator.elf",
),
"_qemu_runner": attr.label(
executable = True,
cfg = "exec",
default = "//target/earlgrey/tooling:qemu_runner",
),
"_qemu_start": attr.label(
allow_single_file = True,
cfg = "exec",
default = "//target/earlgrey/tooling:qemu_start.sh",
),
}
opentitan_runner = rule(
implementation = _opentitan_runner_impl,
executable = True,
attrs = _BASE_ATTRS,
)
opentitan_test = rule(
implementation = _opentitan_runner_impl,
test = True,
attrs = _BASE_ATTRS | _QEMU_ATTRS | {
"exit_failure": attr.string(
default = "FAIL: .+\\n",
doc = "The regex to look for in the output to determine failure.",
),
"exit_success": attr.string(
default = "PASS\\n",
doc = "The regex to look for in the output to determine success.",
),
},
)