blob: abcf370a3eb6a282a8af8f29f858353b6ec629a1 [file] [edit]
# Copyright 2025 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""A rule for running a pigweed system_image on an opentitan board."""
load("@pigweed//pw_kernel/tooling:system_image.bzl", "SystemImageInfo")
load("//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"}
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 == "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(
doc = "The interface to use.",
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 = "//tooling:opentitan_runner",
),
"_opentitantool": attr.label(
executable = True,
allow_single_file = True,
cfg = "exec",
default = "@opentitan_devbundle//:opentitantool/opentitantool",
doc = "opentitantool",
),
}
opentitan_runner = rule(
implementation = _opentitan_runner_impl,
executable = True,
attrs = _BASE_ATTRS,
)
opentitan_test = rule(
implementation = _opentitan_runner_impl,
test = True,
attrs = _BASE_ATTRS | {
"exit_failure": attr.string(
default = "FAIL: \\d+\\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.",
),
},
)