# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

load("//rules:const.bzl", "CONST", "hex")

_SEL_DEVICE_ID = 1
_SEL_MANUF_STATE_CREATOR = (1 << 8)
_SEL_MANUF_STATE_OWNER = (1 << 9)
_SEL_LIFE_CYCLE_STATE = (1 << 10)

def _manifest_impl(ctx):
    mf = {}

    # All the easy parameters are simple assignments
    if ctx.attr.signature:
        mf["signature"] = ctx.attr.signature
    if ctx.attr.modulus:
        mf["modulus"] = ctx.attr.modulus
    if ctx.attr.identifier:
        mf["identifier"] = ctx.attr.identifier
    if ctx.attr.length:
        mf["length"] = ctx.attr.length
    if ctx.attr.version_major:
        mf["version_major"] = ctx.attr.version_major
    if ctx.attr.version_minor:
        mf["version_minor"] = ctx.attr.version_minor
    if ctx.attr.security_version:
        mf["security_version"] = ctx.attr.security_version
    if ctx.attr.timestamp:
        mf["timestamp"] = ctx.attr.timestamp
    if ctx.attr.max_key_version:
        mf["max_key_version"] = ctx.attr.max_key_version
    if ctx.attr.code_start:
        mf["code_start"] = ctx.attr.code_start
    if ctx.attr.code_end:
        mf["code_end"] = ctx.attr.code_end
    if ctx.attr.entry_point:
        mf["entry_point"] = ctx.attr.entry_point

    # Address Translation is a bool, but encoded as an int so we can have
    # a special value mean "unset" and so we can set to non-standard values
    # for testing.
    if ctx.attr.address_translation:
        mf["address_translation"] = ctx.attr.address_translation

    # The binding_value, if provided, must be exactly 8 words.
    if ctx.attr.binding_value:
        if len(ctx.attr.binding_value) != 8:
            fail("The binding_value must be exactly 8 words.")
        mf["binding_value"] = [v for v in ctx.attr.binding_value]

    # The selector_bits are set based on the values of the usage_constraints.
    uc = {}
    selector_bits = 0
    device_id = list(ctx.attr.device_id)
    if len(device_id) > 8:
        fail("The device_id must be 8 words or fewer.")

    # Extend the device_id to 8 words, then set the selector_bits for each
    # non-default word.
    if len(device_id) < 8:
        device_id.extend([hex(CONST.DEFAULT_USAGE_CONSTRAINTS)] * (8 - len(device_id)))
    for i, d in enumerate(device_id):
        if d != hex(CONST.DEFAULT_USAGE_CONSTRAINTS):
            selector_bits |= _SEL_DEVICE_ID << i
        device_id[i] = d
    uc["device_id"] = device_id

    # Set the selector bits for the remaining non-default values.
    if ctx.attr.manuf_state_creator:
        uc["manuf_state_creator"] = ctx.attr.manuf_state_creator
        selector_bits |= _SEL_MANUF_STATE_CREATOR
    else:
        uc["manuf_state_creator"] = hex(CONST.DEFAULT_USAGE_CONSTRAINTS)

    if ctx.attr.manuf_state_owner:
        uc["manuf_state_owner"] = ctx.attr.manuf_state_owner
        selector_bits |= _SEL_MANUF_STATE_OWNER
    else:
        uc["manuf_state_owner"] = hex(CONST.DEFAULT_USAGE_CONSTRAINTS)

    if ctx.attr.life_cycle_state:
        uc["life_cycle_state"] = ctx.attr.life_cycle_state
        selector_bits |= _SEL_LIFE_CYCLE_STATE
    else:
        uc["life_cycle_state"] = hex(CONST.DEFAULT_USAGE_CONSTRAINTS)

    # If the user supplied selector_bits, check if they make sense.
    if ctx.attr.selector_bits:
        # If they don't match, fail unless explicitly permitted to set a
        # bad value.
        if int(ctx.attr.selector_bits, base = 16) != selector_bits and ctx.attr.selector_mismatch_is_failure:
            fail("User provided selector_bits ({}) don't match computed selector_bits ({})".format(ctx.attr.selector_bits, selector_bits))
        uc["selector_bits"] = ctx.attr.selector_bits
    else:
        uc["selector_bits"] = selector_bits

    mf["usage_constraints"] = uc

    file = ctx.actions.declare_file("{}.json".format(ctx.attr.name))
    ctx.actions.write(file, json.encode_indent(mf))
    return DefaultInfo(
        files = depset([file]),
        data_runfiles = ctx.runfiles(files = [file]),
    )

_manifest = rule(
    implementation = _manifest_impl,
    # Manifest attrs are supplied as strings due to Bazel limiting int types to 32-bit signed integers
    attrs = {
        "signature": attr.string(doc = "Image signature as a 0x-prefixed hex-encoded string"),
        "modulus": attr.string(doc = "Signing key modulus as a 0x-prefixed hex-encoded string"),
        "selector_bits": attr.string(doc = "Usage constraint selector bits as a 0x-prefixed hex-encoded string"),
        "selector_mismatch_is_failure": attr.bool(default = True, doc = "A mismatch in computed selector bits is a failure"),
        "device_id": attr.string_list(doc = "Usage constraint device ID as a 0x-prefixed hex-encoded string"),
        "manuf_state_creator": attr.string(doc = "Usage constraint for silicon creator manufacturing status as a 0x-prefixed hex-encoded string"),
        "manuf_state_owner": attr.string(doc = "Usage constraint for silicon owner manufacturing status as a 0x-prefixed hex-encoded string"),
        "life_cycle_state": attr.string(doc = "Usage constraint for life cycle status as a 0x-prefixed hex-encoded string"),
        "address_translation": attr.string(doc = "Whether this image uses address translation as a 0x-prefixed hex-encoded string"),
        "identifier": attr.string(doc = "Manifest identifier as a 0x-prefixed hex-encoded string"),
        "length": attr.string(doc = "Length of this image as a 0x-prefixed hex-encoded string"),
        "version_major": attr.string(doc = "Image major version as a 0x-prefixed hex-encoded string"),
        "version_minor": attr.string(doc = "Image minor version as a 0x-prefixed hex-encoded string"),
        "security_version": attr.string(doc = "Security version for anti-rollback protection as a 0x-prefixed hex-encoded string"),
        "timestamp": attr.string(doc = "Unix timestamp of the image as a 0x-prefixed hex-encoded string"),
        "binding_value": attr.string_list(doc = "Binding value used by key manager to derive secrets as a 0x-prefixed hex-encoded string"),
        "max_key_version": attr.string(doc = "Maximum allowed version for keys generated at the next boot stage as a 0x-prefixed hex-encoded string"),
        "code_start": attr.string(doc = "Start offset of the executable region in the image as a 0x-prefixed hex-encoded string"),
        "code_end": attr.string(doc = "End offset of the executable region in the image as a 0x-prefixed hex-encoded string"),
        "entry_point": attr.string(doc = "Offset of the first instruction in the image as a 0x-prefixed hex-encoded string"),
    },
)

def manifest(d):
    _manifest(**d)
    return d["name"]
