Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sw/silicon_creator] Add structured kChipInfo to ROM #18100

Merged
merged 3 commits into from
May 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 31 additions & 12 deletions rules/autogen.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -65,35 +65,34 @@ autogen_hjson_header = rule(
},
)

def _chip_info(ctx):
header = ctx.actions.declare_file("chip_info.h")
def _chip_info_src(ctx):
out_source = ctx.actions.declare_file("chip_info.c")
ctx.actions.run(
outputs = [header],
outputs = [
out_source,
],
inputs = [
ctx.file.version,
ctx.executable._tool,
],
arguments = [
"-o",
header.dirname,
out_source.dirname,
"--ot_version_file",
ctx.file.version.path,
],
executable = ctx.executable._tool,
)

return [
CcInfo(compilation_context = cc_common.create_compilation_context(
includes = depset([header.dirname]),
headers = depset([header]),
)),
DefaultInfo(files = depset([header])),
DefaultInfo(files = depset([out_source])),
]

autogen_chip_info = rule(
implementation = _chip_info,
autogen_chip_info_src = rule(
implementation = _chip_info_src,
attrs = {
"version": attr.label(
default = "//util:ot_version_file",
default = "//util:scm_revision_file",
allow_single_file = True,
),
"_tool": attr.label(
Expand All @@ -104,6 +103,26 @@ autogen_chip_info = rule(
},
)

def autogen_chip_info(name):
"""Generates a cc_library named `name` that defines chip info."""

# Generate a C source file that defines the chip info struct. This is an
# implementation detail and should not be depended on externally.
chip_info_src_target = name + "_gen_src"
autogen_chip_info_src(name = chip_info_src_target)

# Package up the generated source file with its corresponding header file
# and dependencies. Any target that wants access to the chip info should
# depend on this.
native.cc_library(
name = name,
srcs = [chip_info_src_target],
hdrs = ["//sw/device/silicon_creator/lib:chip_info.h"],
deps = [
"//sw/device/lib/base:macros",
],
)

def _cryptotest_hjson_external(ctx):
"""
Implementation of the Bazel rule for parsing externally-sourced test vectors.
Expand Down
4 changes: 2 additions & 2 deletions sw/device/lib/arch/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,11 @@ extern const uint32_t kUartNCOValue;
* Helper macro to calculate the time it takes to transmit the entire UART TX
* FIFO in CPU cycles.
*
* This macro assumes 10 bits per byte (no parity bits) and a 32 byte deep TX
* This macro assumes 10 bits per byte (no parity bits) and a 128 byte deep TX
* FIFO.
*/
#define CALCULATE_UART_TX_FIFO_CPU_CYCLES(baud_rate_, cpu_freq_) \
((cpu_freq_)*10 * 32 / (baud_rate_))
((cpu_freq_)*10 * 128 / (baud_rate_))

/**
* The time it takes to transmit the entire UART TX fifo in CPU cycles.
Expand Down
7 changes: 1 addition & 6 deletions sw/device/lib/testing/test_rom/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@
load("//rules:opentitan.bzl", "OPENTITAN_CPU", "opentitan_rom_binary")
load("//rules:opentitan_test.bzl", "opentitan_functest")
load("//rules:exclude_files.bzl", "exclude_files")
load("//rules:autogen.bzl", "autogen_chip_info")
load("//rules:linker.bzl", "ld_library")
load("@rules_pkg//pkg:mappings.bzl", "pkg_files")

package(default_visibility = ["//visibility:public"])

autogen_chip_info(
name = "chip_info",
)

ld_library(
name = "linker_script",
script = "test_rom.ld",
Expand Down Expand Up @@ -120,7 +115,6 @@ cc_library(
],
target_compatible_with = [OPENTITAN_CPU],
deps = [
":chip_info",
":target_test_rom_lib",
":test_rom_manifest",
"//hw/ip/csrng/data:csrng_regs",
Expand Down Expand Up @@ -153,6 +147,7 @@ cc_library(
"//sw/device/lib/testing:pinmux_testutils",
"//sw/device/lib/testing/test_framework:check",
"//sw/device/lib/testing/test_framework:status",
"//sw/device/silicon_creator/lib:chip_info",
"//sw/device/silicon_creator/lib/base:sec_mmio",
"//sw/device/silicon_creator/lib/base:static_critical_boot_measurements",
"//sw/device/silicon_creator/lib/base:static_critical_epmp_state",
Expand Down
4 changes: 2 additions & 2 deletions sw/device/lib/testing/test_rom/test_rom.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
#include "sw/device/lib/testing/pinmux_testutils.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/status.h"
#include "sw/device/lib/testing/test_rom/chip_info.h" // Generated.
#include "sw/device/silicon_creator/lib/base/sec_mmio.h"
#include "sw/device/silicon_creator/lib/chip_info.h"
#include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
#include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
#include "sw/device/silicon_creator/lib/manifest.h"
Expand Down Expand Up @@ -152,7 +152,7 @@ bool rom_test_main(void) {
}

// Print the chip version information
LOG_INFO("%s", chip_info);
LOG_INFO("kChipInfo: scm_revision=%x", kChipInfo.scm_revision);

// Skip sram_init for test_rom
dif_rstmgr_reset_info_bitfield_t reset_reasons;
Expand Down
4 changes: 4 additions & 0 deletions sw/device/silicon_creator/lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# SPDX-License-Identifier: Apache-2.0

load("//rules:opentitan.bzl", "OPENTITAN_CPU")
load("//rules:autogen.bzl", "autogen_chip_info")
load("//rules:opentitan_test.bzl", "cw310_params", "opentitan_functest", "verilator_params")
load("//rules:cross_platform.bzl", "dual_cc_device_library_of", "dual_cc_library", "dual_inputs")

Expand Down Expand Up @@ -272,6 +273,8 @@ filegroup(
],
)

autogen_chip_info(name = "chip_info")
dmcardle marked this conversation as resolved.
Show resolved Hide resolved

dual_cc_library(
name = "shutdown",
srcs = dual_inputs(
Expand All @@ -289,6 +292,7 @@ dual_cc_library(
"@googletest//:gtest",
],
shared = [
":chip_info",
":error",
":epmp_defs",
"//sw/device/lib/base:hardened",
Expand Down
27 changes: 27 additions & 0 deletions sw/device/silicon_creator/lib/chip_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_CHIP_INFO_H_
#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_CHIP_INFO_H_

#include <stdint.h>

#include "sw/device/lib/base/macros.h"

typedef struct chip_info {
cfrantz marked this conversation as resolved.
Show resolved Hide resolved
// A truncated commit hash from the open-source OpenTitan repo that can be
// used to reproduce the ROM binary.
uint64_t scm_revision;
} chip_info_t;

// This struct contains information about the ROM's provenance, and critically,
// it can be manually decoded from a hexdump. The linker script should place
// this at the top of the ROM.
extern const chip_info_t kChipInfo __attribute__((section(".chip_info")));

// Track the size of `kChipInfo` so we can compute how much space is left in the
// `.chip_info` section. If it becomes too large, linking will fail.
OT_ASSERT_SIZE(chip_info_t, 8);

#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_CHIP_INFO_H_
10 changes: 8 additions & 2 deletions sw/device/silicon_creator/lib/shutdown.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "sw/device/lib/base/memory.h"
#include "sw/device/lib/base/multibits.h"
#include "sw/device/lib/base/stdasm.h"
#include "sw/device/silicon_creator/lib/chip_info.h"
#include "sw/device/silicon_creator/lib/drivers/alert.h"
#include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
#include "sw/device/silicon_creator/lib/drivers/otp.h"
Expand Down Expand Up @@ -325,7 +326,7 @@ enum {
/**
* UART TX FIFO size.
*/
kUartFifoSize = 32,
kUartFifoSize = 128,
};

/**
Expand Down Expand Up @@ -379,14 +380,19 @@ SHUTDOWN_FUNC(NO_MODIFIERS, shutdown_report_error(rom_error_t reason)) {
uart_ctrl_reg = bitfield_bit32_write(uart_ctrl_reg, UART_CTRL_TX_BIT, true);
abs_mmio_write32(kUartBase + UART_CTRL_REG_OFFSET, uart_ctrl_reg);

// Extract the commit hash from the `chip_info` at the top of ROM.
uint64_t chip_info_version = kChipInfo.scm_revision;
uint32_t chip_info_version_truncated = chip_info_version >> 32;

// Print the error message and the raw life cycle state as reported by the
// hardware.
shutdown_print(kShutdownLogPrefixBootFault, redacted_error);
shutdown_print(kShutdownLogPrefixLifecycle, raw_state);
shutdown_print(kShutdownLogPrefixVersion, chip_info_version_truncated);

#ifdef OT_PLATFORM_RV32
// Wait until UART TX is complete.
static_assert(2 * kErrorMsgLen <= kUartFifoSize,
static_assert(3 * kErrorMsgLen <= kUartFifoSize,
"Total message length must be less than TX FIFO size.");
CSR_WRITE(CSR_REG_MCYCLE, 0);
uint32_t mcycle;
Expand Down
1 change: 1 addition & 0 deletions sw/device/silicon_creator/lib/shutdown.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ typedef enum shutdown_error_redact {
typedef enum shutdown_log_prefix {
kShutdownLogPrefixBootFault = LOG_PREFIX_('B', 'F', 'V'),
kShutdownLogPrefixLifecycle = LOG_PREFIX_('L', 'C', 'V'),
kShutdownLogPrefixVersion = LOG_PREFIX_('V', 'E', 'R'),
} shutdown_log_prefix_t;

/**
Expand Down
7 changes: 7 additions & 0 deletions util/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ genrule(
stamp = 1, # this provides volatile-status.txt
)

genrule(
name = "scm_revision_file",
outs = ["scm_revision.txt"],
cmd = """awk '/BUILD_SCM_REVISION/ { print $$2 }' bazel-out/volatile-status.txt > $@""",
stamp = 1, # this provides volatile-status.txt
)

py_binary(
name = "otbn_build",
srcs = ["otbn_build.py"],
Expand Down
49 changes: 28 additions & 21 deletions util/rom_chip_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,39 @@
"""

import argparse
import hashlib
import logging as log
import sys
from datetime import datetime
from pathlib import Path

header_template = r"""

def generate_chip_info_c_source(scm_revision: int) -> str:
"""Return the contents of a C source file that defines `kChipInfo`.

Args:
scm_revision: SHA1 sum identifying the current SCM revision.
"""

SHA1_DIGEST_SIZE_BITS = hashlib.sha1().digest_size * 8
assert scm_revision.bit_length() <= SHA1_DIGEST_SIZE_BITS

# Truncate the SCM revision to the top N bits.
SCM_REVISION_SIZE_BITS = 64
shift_amount = SHA1_DIGEST_SIZE_BITS - SCM_REVISION_SIZE_BITS
scm_revision >>= shift_amount

return f"""
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// --------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! ---------//

#ifndef _F_CHIPINFO_H__
#define _F_CHIPINFO_H__

static const char chip_info[128] __attribute__((section(".chip_info"))) =
"Version: {%version%}, Build Date: {%build_date%}";

#endif // _F_CHIPINFO_H__
#include "sw/device/silicon_creator/lib/chip_info.h"

const chip_info_t kChipInfo __attribute__((section(".chip_info"))) = {{
.scm_revision = (uint64_t){scm_revision:#0x},
}};
"""


Expand Down Expand Up @@ -57,24 +70,18 @@ def main():
log.error(
"Missing ot_version, provide --ot_version or --ot_version_file.")
raise SystemExit(sys.exc_info()[1])
version = int(version, base=16)
log.info("Version: %x" % (version, ))

outdir = Path(args.outdir)

outdir.mkdir(parents=True, exist_ok=True)
out_path = outdir / "chip_info.h"

now = datetime.now()
wall_time = now.strftime("%Y-%m-%d %H:%M:%S")

log.info("Version: %s" % (version, ))
log.info("Build Date: %s" % (wall_time, ))
source_out_path = outdir / "chip_info.c"

output = header_template
output = output.replace('{%version%}', version, 1)
output = output.replace('{%build_date%}', wall_time, 1)
output = generate_chip_info_c_source(version)

with out_path.open(mode='w', encoding='UTF-8') as fout:
fout.write(output + "\n")
with source_out_path.open(mode='w', encoding='UTF-8') as fout:
fout.write(output)


if __name__ == "__main__":
Expand Down