blob: 0bf7c9617b52ac496defc1471baff042f83bcaf4 [file] [log] [blame]
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
"""Rules for generating OTP images.
The rules in this file are used to generate a JSON file that describe the OTP
configuration which is then consumed to produce the OTP VMEM image file for
preloading the OTP in FPGA synthesis or simulation.
"""
def get_otp_images():
"""Returns a list of (otp_name, img_target) tuples.
Each tuple corresponds to an OTP image defined in //hw/ip/otp_ctrl/data. The
otp_name is a short, unique suffix of the image target, e.g. "rma". The
img_target is the full path of the OTP image target.
"""
img_targets = [
"//hw/ip/otp_ctrl/data:img_dev",
"//hw/ip/otp_ctrl/data:img_rma",
"//hw/ip/otp_ctrl/data:img_test_unlocked0",
"//hw/ip/otp_ctrl/data:img_prod",
"//hw/ip/otp_ctrl/data:img_exec_disabled",
]
out = []
for img_target in img_targets:
[_, img_target_name] = img_target.rsplit(":")
otp_name = img_target_name.removeprefix("img_")
out.append((
otp_name,
img_target,
))
return out
def _otp_json_impl(ctx):
"""Bazel rule for generating JSON specifications for OTP configurations."""
otp = {}
# Seed to be used for generation of partition randomized values.
# Can be overridden by the OTP image generation tool.
otp["seed"] = "01931961561863975174"
# Assemble all OTP paritions
# The partition and item names must correspond with the OTP memory map.
otp["partitions"] = [
{
"name": "CREATOR_SW_CFG",
"items": {
"CREATOR_SW_CFG_DIGEST": "0x0",
# Use software mod_exp implementation for signature
# verification. See the definition of `hardened_bool_t` in
# sw/device/lib/base/hardened.h.
"CREATOR_SW_CFG_USE_SW_RSA_VERIFY": "0x739",
# Mark the first two keys as valid and remaining as invalid
# since we have currently only two keys. See the definition of
# `hardened_byte_bool_t` in sw/device/lib/base/hardened.h.
"CREATOR_SW_CFG_KEY_IS_VALID": "0x4b4b4b4b4b4ba5a5",
# Enable use of entropy for countermeasures. See the definition
# of `hardened_bool_t` in sw/device/lib/base/hardened.h.
"CREATOR_SW_CFG_RNG_EN": "0x739",
# ROM execution is enabled if this item is set to a non-zero
# value.
"CREATOR_SW_CFG_ROM_EXEC_EN": ctx.attr.creator_sw_cfg_rom_exec_en,
# Value to write to the cpuctrl CSR in `rom_init()`.
# See:
# https://ibex-core.readthedocs.io/en/latest/03_reference/cs_registers.html#cpu-control-register-cpuctrl
"CREATOR_SW_CFG_CPUCTRL": "0x1",
"CREATOR_SW_CFG_JITTER_EN": "0x9",
# Value of the min_security_version_rom_ext field of the
# default boot data.
"CREATOR_SW_CFG_MIN_SEC_VER_ROM_EXT": "0x0",
# Value of the min_security_version_bl0 field of the default
# boot data.
"CREATOR_SW_CFG_MIN_SEC_VER_BL0": "0x0",
# Enable the default boot data in PROD and PROD_END life cycle
# states. See the definition of `hardened_bool_t` in
# sw/device/lib/base/hardened.h.
"CREATOR_SW_CFG_DEFAULT_BOOT_DATA_IN_PROD_EN": "0x739",
},
},
{
"name": "OWNER_SW_CFG",
"items": {
"OWNER_SW_CFG_DIGEST": "0x0",
# Enable bootstrap. See `hardened_bool_t` in
# sw/device/lib/base/hardened.h.
"OWNER_SW_CFG_ROM_BOOTSTRAP_EN": "0x739",
# Set to 0x739 to use the ROM_EXT hash measurement as the key
# manager attestation binding value.
"OWNER_SW_CFG_ROM_KEYMGR_ROM_EXT_MEAS_EN": "0x0",
# Set the enables to kAlertEnableNone.
# See `alert_enable_t` in
# sw/device/silicon_creator/lib/drivers/alert.h
"OWNER_SW_CFG_ROM_ALERT_CLASS_EN": "0xa9a9a9a9",
# Set the esclation policies to kAlertEscalateNone.
# See `alert_escalate_t`
# in sw/device/silicon_creator/lib/drivers/alert.h
"OWNER_SW_CFG_ROM_ALERT_ESCALATION": "0xd1d1d1d1",
# Set the classifiactions to kAlertClassX.
# See `alert_class_t` in
# sw/device/silicon_creator/lib/drivers/alert.h
"OWNER_SW_CFG_ROM_ALERT_CLASSIFICATION": ["0x94949494"] * 80,
# Set the classifiactions to kAlertClassX.
# See `alert_class_t` in
# sw/device/silicon_creator/lib/drivers/alert.h
"OWNER_SW_CFG_ROM_LOCAL_ALERT_CLASSIFICATION": ["0x94949494"] * 16,
# Set the alert accumulation thresholds to 0 per class.
"OWNER_SW_CFG_ROM_ALERT_ACCUM_THRESH": ["0x00000000"] * 4,
# Set the alert timeout cycles to 0 per class.
"OWNER_SW_CFG_ROM_ALERT_TIMEOUT_CYCLES": ["0x00000000"] * 4,
# Set the alert phase cycles to 0,10,10,0xFFFFFFFF for classes
# A and B, and to all zeros for classes C and D.
"OWNER_SW_CFG_ROM_ALERT_PHASE_CYCLES": [
"0x0",
"0xa",
"0xa",
"0xFFFFFFFF",
"0x0",
"0xa",
"0xa",
"0xFFFFFFFF",
"0x0",
"0x0",
"0x0",
"0x0",
"0x0",
"0x0",
"0x0",
"0x0",
],
"OWNER_SW_CFG_ROM_ALERT_DIGEST_RMA": "0x36ed9cb0",
},
},
{
"name": "HW_CFG",
# If set to true, this computes the HW digest value and locks the
# partition.
"lock": True,
"items": {
"DEVICE_ID": "<random>",
# Cryptolib and chip-level tests require access to the CSRNG
# software interfaces.
"EN_CSRNG_SW_APP_READ": True,
# Cryptolib and chip-level tests require access to the
# entropy_src FW data interface.
"EN_ENTROPY_SRC_FW_READ": True,
# Cryptolib and chip-level tests require access to the
# entropy_src FW override interface.
"EN_ENTROPY_SRC_FW_OVER": True,
},
},
{
"name": "SECRET0",
"lock": True,
"items": {
"TEST_UNLOCK_TOKEN": "<random>",
"TEST_EXIT_TOKEN": "<random>",
},
},
{
"name": "SECRET1",
"lock": True,
"items": {
"FLASH_ADDR_KEY_SEED": "<random>",
"FLASH_DATA_KEY_SEED": "<random>",
"SRAM_DATA_KEY_SEED": "<random>",
},
},
{
"name": "SECRET2",
"lock": False,
"items": {
"RMA_TOKEN": "<random>",
"CREATOR_ROOT_KEY_SHARE0": "<random>",
"CREATOR_ROOT_KEY_SHARE1": "<random>",
},
},
{
"name": "LIFE_CYCLE",
"state": ctx.attr.lc_state,
# Can range from 0 to 16.
# Note that a value of 0 is only permissible in RAW state.
"count": ctx.attr.lc_count,
},
]
# For every partition with an "items" dictionary, expand the dictionary of
# key:value pairs into a list of dicts, each of the form
# {
# "name": key,
# "value": value
# }
# This format is expected by the OTP image generation tool
for partition in otp["partitions"]:
if "items" in partition.keys():
items = partition["items"]
partition["items"] = [{"name": k, "value": items[k]} for k in items.keys()]
file = ctx.actions.declare_file("{}.json".format(ctx.attr.name))
ctx.actions.write(file, json.encode_indent(otp))
return DefaultInfo(files = depset([file]))
otp_json = rule(
implementation = _otp_json_impl,
attrs = {
# Valid life cycle states can be found in the life cycle state
# definition file (default: hw/ip/lc_ctrl/data/lc_ctrl_state.hjson)
"lc_state": attr.string(doc = "Life cycle state", default = "RMA"),
"lc_count": attr.int(doc = "Life cycle count", default = 8),
"creator_sw_cfg_rom_exec_en": attr.string(default = "0xffffffff"),
},
)
def _otp_image(ctx):
output = ctx.actions.declare_file(ctx.attr.name + ".24.vmem")
args = ctx.actions.args()
args.add("--quiet")
args.add("--lc-state-def", ctx.file.lc_state_def)
args.add("--mmap-def", ctx.file.mmap_def)
args.add("--img-cfg", ctx.file.src)
args.add("--out", "{}/{}.BITWIDTH.vmem".format(output.dirname, ctx.attr.name))
ctx.actions.run(
outputs = [output],
inputs = [
ctx.file.src,
ctx.file.lc_state_def,
ctx.file.mmap_def,
],
arguments = [args],
executable = ctx.executable._tool,
)
return [DefaultInfo(files = depset([output]), runfiles = ctx.runfiles(files = [output]))]
otp_image = rule(
implementation = _otp_image,
attrs = {
"src": attr.label(allow_single_file = True),
"lc_state_def": attr.label(
allow_single_file = True,
default = "//hw/ip/lc_ctrl/data:lc_ctrl_state.hjson",
doc = "Life-cycle state definition file in Hjson format.",
),
"mmap_def": attr.label(
allow_single_file = True,
default = "//hw/ip/otp_ctrl/data:otp_ctrl_mmap.hjson",
doc = "OTP Controller memory map file in Hjson format.",
),
"_tool": attr.label(
default = "//util/design:gen-otp-img",
executable = True,
cfg = "exec",
),
},
)