diff --git a/MODULE.bazel b/MODULE.bazel index c369b5438..8e29f8c3d 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -133,10 +133,8 @@ override_repo( bazel_dep(name = "opentitan_devbundle") archive_override( module_name = "opentitan_devbundle", - integrity = "sha256-67i+jjvFg9Pd1CXudHpWZ6Gw5lRJvRg4EQm6rDfmang=", - # TODO(cfrantz): We should get this from github.com/lowRISC/opentitan/releases/... - # Update after creating the next official build upstream. - url = "https://storage.googleapis.com/artifacts.opentitan.org/dev_bundle/devbundle-20260714.tar.xz", + integrity = "sha256-7QQkw0JW8R0aYfkjg2IcVT6/mpLYSC0Ab2jEvPEGiq8=", + url = "https://github.com/lowRISC/opentitan/releases/download/devbundle-2026-08-21-1/devbundle.tar.xz", ) bazel_dep(name = "lowrisc_opentitan") diff --git a/target/earlgrey/env/environments.bzl b/target/earlgrey/env/environments.bzl index 6df1c21fb..7b95d4b8f 100644 --- a/target/earlgrey/env/environments.bzl +++ b/target/earlgrey/env/environments.bzl @@ -48,6 +48,12 @@ def _fpga_prepare(ctx, env, firmware_bin, tools): outputs = [boot_image_file], inputs = [env.rom_ext, firmware_bin], executable = tools.opentitantool, + # Workaround: When HOME is unset, opentitantool invokes getpwuid_r() to locate its + # default config directory, which dynamically dlopens host NSS libraries. In static glibc + # binaries, this causes a SIGSEGV if the static glibc version differs from the host glibc. + # Setting HOME prevents the NSS lookup. + # TODO(antchen): remove this workaround once upstream opentitantool handles missing HOME or fixes static NSS lookup. + env = {"HOME": "/tmp"}, arguments = [ "image", "assemble", diff --git a/target/earlgrey/firmware/transport/BUILD.bazel b/target/earlgrey/firmware/transport/BUILD.bazel index c89487a3f..234fb5c44 100644 --- a/target/earlgrey/firmware/transport/BUILD.bazel +++ b/target/earlgrey/firmware/transport/BUILD.bazel @@ -11,6 +11,7 @@ load("@rules_rust//rust:defs.bzl", "rust_binary") load("//target/earlgrey:defs.bzl", "TARGET_COMPATIBLE_WITH") load("//target/earlgrey/signing/keys:defs.bzl", "FPGA_ECDSA_KEY", "SILICON_ECDSA_KEY") load("//target/earlgrey/tooling:opentitan_runner.bzl", "opentitan_test") +load("//target/earlgrey/tooling:system_config.bzl", "system_config_variant") package(default_visibility = ["//visibility:public"]) @@ -252,6 +253,68 @@ rust_binary( ], ) +# +# 88 KiB ROM_EXT / 88 KiB offset variant +# +system_config_variant( + name = "system_config_88k", + base = ":system_config", + flash_start_address = "0xA0016000", +) + +target_linker_script( + name = "linker_script_88k", + system_config = ":system_config_88k", + tags = ["kernel"], + template = "//target/earlgrey:linker_script_template", +) + +target_codegen( + name = "codegen_88k", + arch = "@pigweed//pw_kernel/arch/riscv:arch_riscv", + crate_name = "codegen", + system_config = ":system_config_88k", +) + +rust_binary( + name = "target_88k", + srcs = [ + "target.rs", + ], + edition = "2024", + tags = ["kernel"], + target_compatible_with = TARGET_COMPATIBLE_WITH, + deps = [ + ":codegen_88k", + ":linker_script_88k", + "//target/earlgrey:entry", + "@pigweed//pw_kernel/arch/riscv:arch_riscv", + "@pigweed//pw_kernel/kernel", + "@pigweed//pw_kernel/subsys/console:console_backend", + "@pigweed//pw_kernel/target:target_common", + "@pigweed//pw_log/rust:pw_log", + ], +) + +system_image( + name = "transport_firmware_88k", + apps = [ + ":transport", + ], + kernel = ":target_88k", + platform = "//target/earlgrey", + system_config = ":system_config_88k", + tags = ["kernel"], + visibility = ["//visibility:public"], +) + +rust_binary_no_panics_test( + name = "no_panics_88k", + apps = ["transport"], + binary = ":transport_firmware_88k", + tags = ["no_panics"], +) + opentitan_test( name = "transport_hyper310_test", ecdsa_key = FPGA_ECDSA_KEY, diff --git a/target/earlgrey/firmware/transport/tests/dfu/BUILD.bazel b/target/earlgrey/firmware/transport/tests/dfu/BUILD.bazel index 211fe7d72..f7f6e8113 100644 --- a/target/earlgrey/firmware/transport/tests/dfu/BUILD.bazel +++ b/target/earlgrey/firmware/transport/tests/dfu/BUILD.bazel @@ -41,6 +41,13 @@ sign_bin( ecdsa_key = FPGA_ECDSA_KEY, ) +sign_bin( + name = "transport_firmware_signed_88k", + basename = "transport_firmware_signed_88k", + bin = "//target/earlgrey/firmware/transport:transport_firmware_88k", + ecdsa_key = FPGA_ECDSA_KEY, +) + opentitan_rust_binary( name = "host_usb_dfu_owner_transfer", srcs = ["host_usb_dfu_owner_transfer.rs"], @@ -69,120 +76,52 @@ manifest( address_translation = "0x739", ) -opentitan_test( - name = "dfu_owner_transfer_hyper310_test", - timeout = "eternal", - clear_bitstream = True, - ecdsa_key = FPGA_ECDSA_KEY, - environment = "//target/earlgrey/env:hyper310", - interface = "hyper310", - tags = [ - "hardware", - "hyper310", - ], - target = "//target/earlgrey/tests/eeprom_programmer:eeprom_programmer_firmware", - target_data = [ - ":bootinfo_signed_transfer", - ":bootinfo_signed_simple", - ":transport_firmware_signed", - "@opentitan_devbundle//:rom_ext/rom_ext_usbdfu_anyversion_fpga_cw310.prod_key_0.signed.bin", - ], - test_cmd = " ".join([ - "--logging=info", - "--expect-reboot", - "--expect-app", - "--expect-owner-transfer", - "--rom-ext=$(rootpath @opentitan_devbundle//:rom_ext/rom_ext_usbdfu_anyversion_fpga_cw310.prod_key_0.signed.bin)", - "--firmware=$(rootpath :bootinfo_signed_transfer)", - "--transport-firmware=$(rootpath :transport_firmware_signed)", - ]), - test_harness = ":host_usb_dfu_owner_transfer", -) - -opentitan_test( - name = "dfu_owner_transfer_hyper340_test", - timeout = "eternal", - clear_bitstream = True, - ecdsa_key = FPGA_ECDSA_KEY, - environment = "//target/earlgrey/env:hyper340", - interface = "hyper340", - tags = [ - "hardware", - "hyper340", - ], - target = "//target/earlgrey/tests/eeprom_programmer:eeprom_programmer_firmware", - target_data = [ - ":bootinfo_signed_transfer", - ":bootinfo_signed_simple", - ":transport_firmware_signed", - "@opentitan_devbundle//:rom_ext/rom_ext_usbdfu_anyversion_fpga_cw340.prod_key_0.signed.bin", - ], - test_cmd = " ".join([ - "--logging=info", - "--expect-reboot", - "--expect-app", - "--expect-owner-transfer", - "--rom-ext=$(rootpath @opentitan_devbundle//:rom_ext/rom_ext_usbdfu_anyversion_fpga_cw340.prod_key_0.signed.bin)", - "--firmware=$(rootpath :bootinfo_signed_transfer)", - "--transport-firmware=$(rootpath :transport_firmware_signed)", - ]), - test_harness = ":host_usb_dfu_owner_transfer", -) - -opentitan_test( - name = "dfu_firmware_update_hyper310_test", - timeout = "eternal", - clear_bitstream = True, - ecdsa_key = FPGA_ECDSA_KEY, - environment = "//target/earlgrey/env:hyper310", - interface = "hyper310", - tags = [ - "hardware", - "hyper310", - ], - target = "//target/earlgrey/tests/eeprom_programmer:eeprom_programmer_firmware", - target_data = [ - ":bootinfo_signed_transfer", - ":bootinfo_signed_simple", - ":transport_firmware_signed", - "@opentitan_devbundle//:rom_ext/rom_ext_usbdfu_anyversion_fpga_cw310.prod_key_0.signed.bin", - ], - test_cmd = " ".join([ - "--logging=info", - "--expect-reboot", - "--expect-app", - "--rom-ext=$(rootpath @opentitan_devbundle//:rom_ext/rom_ext_usbdfu_anyversion_fpga_cw310.prod_key_0.signed.bin)", - "--firmware=$(rootpath :bootinfo_signed_simple)", - "--transport-firmware=$(rootpath :transport_firmware_signed)", - ]), - test_harness = ":host_usb_dfu_owner_transfer", -) - -opentitan_test( - name = "dfu_firmware_update_hyper340_test", - timeout = "eternal", - clear_bitstream = True, - ecdsa_key = FPGA_ECDSA_KEY, - environment = "//target/earlgrey/env:hyper340", - interface = "hyper340", - tags = [ - "hardware", - "hyper340", - ], - target = "//target/earlgrey/tests/eeprom_programmer:eeprom_programmer_firmware", - target_data = [ - ":bootinfo_signed_transfer", - ":bootinfo_signed_simple", - ":transport_firmware_signed", - "@opentitan_devbundle//:rom_ext/rom_ext_usbdfu_anyversion_fpga_cw340.prod_key_0.signed.bin", - ], - test_cmd = " ".join([ - "--logging=info", - "--expect-reboot", - "--expect-app", - "--rom-ext=$(rootpath @opentitan_devbundle//:rom_ext/rom_ext_usbdfu_anyversion_fpga_cw340.prod_key_0.signed.bin)", - "--firmware=$(rootpath :bootinfo_signed_simple)", - "--transport-firmware=$(rootpath :transport_firmware_signed)", - ]), - test_harness = ":host_usb_dfu_owner_transfer", -) +[ + opentitan_test( + name = "dfu_{test_name}{fw_suffix}_{env_name}_test".format( + env_name = env_name, + fw_suffix = fw_suffix, + test_name = test_name, + ), + timeout = "eternal", + clear_bitstream = True, + ecdsa_key = FPGA_ECDSA_KEY, + environment = "//target/earlgrey/env:" + env_name, + interface = env_name, + tags = [ + "hardware", + env_name, + ], + target = "//target/earlgrey/tests/eeprom_programmer:eeprom_programmer_firmware", + target_data = [ + ":bootinfo_signed_transfer", + ":bootinfo_signed_simple", + transport_fw_target, + rom_ext_bin, + ], + test_cmd = " ".join([ + "--logging=info", + "--expect-reboot", + "--expect-app", + ] + ([ + "--expect-owner-transfer", + ] if expect_owner_transfer else []) + [ + "--rom-ext=$(rootpath {})".format(rom_ext_bin), + "--firmware=$(rootpath {})".format(fw_binary), + "--transport-firmware=$(rootpath {})".format(transport_fw_target), + ]), + test_harness = ":host_usb_dfu_owner_transfer", + ) + for fw_suffix, transport_fw_target in [ + ("", ":transport_firmware_signed"), + ("_88k", ":transport_firmware_signed_88k"), + ] + for env_name, rom_ext_bin in [ + ("hyper310", "@opentitan_devbundle//:rom_ext/rom_ext_usbdfu_anyversion_fpga_cw310.prod_key_0.signed.bin"), + ("hyper340", "@opentitan_devbundle//:rom_ext/rom_ext_usbdfu_anyversion_fpga_cw340.prod_key_0.signed.bin"), + ] + for test_name, fw_binary, expect_owner_transfer in [ + ("owner_transfer", ":bootinfo_signed_transfer", True), + ("firmware_update", ":bootinfo_signed_simple", False), + ] +] diff --git a/target/earlgrey/firmware/transport/tests/updatemgr/BUILD.bazel b/target/earlgrey/firmware/transport/tests/updatemgr/BUILD.bazel index e1d677d6b..978a8903d 100644 --- a/target/earlgrey/firmware/transport/tests/updatemgr/BUILD.bazel +++ b/target/earlgrey/firmware/transport/tests/updatemgr/BUILD.bazel @@ -15,6 +15,13 @@ sign_bin( ecdsa_key = FPGA_ECDSA_KEY, ) +sign_bin( + name = "transport_firmware_signed_88k", + basename = "transport_firmware_signed_88k", + bin = "//target/earlgrey/firmware/transport:transport_firmware_88k", + ecdsa_key = FPGA_ECDSA_KEY, +) + opentitan_rust_binary( name = "host_eeprom_owner_transfer", srcs = ["host_eeprom_owner_transfer.rs"], @@ -35,9 +42,10 @@ opentitan_rust_binary( [ opentitan_test( - name = "updatemgr_eeprom_{test_name}_slot_{rom_ext_slot}{fw_slot}_{env_name}_test".format( + name = "updatemgr_eeprom_{test_name}{fw_suffix}_slot_{rom_ext_slot}{fw_slot}_{env_name}_test".format( env_name = env_name, fw_slot = fw_slot, + fw_suffix = fw_suffix, rom_ext_slot = rom_ext_slot, test_name = test_name + ("_standalone_app" if is_standalone else ""), ), @@ -52,7 +60,7 @@ opentitan_rust_binary( ], target = "//target/earlgrey/tests/eeprom_programmer:eeprom_programmer_firmware", target_data = [ - ":transport_firmware_signed", + transport_fw_target, fw_binary, rom_ext_bin, ], @@ -67,11 +75,15 @@ opentitan_rust_binary( "--new-rom-ext=$(rootpath {})".format(rom_ext_bin), ] if not is_standalone else []) + [ "--new-firmware=$(rootpath {})".format(fw_binary), - "--transport-firmware=$(rootpath :transport_firmware_signed)", + "--transport-firmware=$(rootpath {})".format(transport_fw_target), "--transport-firmware-slot={}".format(fw_slot), ]), test_harness = ":host_eeprom_owner_transfer", ) + for fw_suffix, transport_fw_target in [ + ("", ":transport_firmware_signed"), + ("_88k", ":transport_firmware_signed_88k"), + ] for env_name, rom_ext_bin in [ ("hyper310", "@opentitan_devbundle//:rom_ext/rom_ext_usbdfu_anyversion_fpga_cw310.prod_key_0.signed.bin"), ("hyper340", "@opentitan_devbundle//:rom_ext/rom_ext_usbdfu_anyversion_fpga_cw340.prod_key_0.signed.bin"), diff --git a/target/earlgrey/target.ld.jinja b/target/earlgrey/target.ld.jinja index 7ea409c4e..6bc4edd8a 100644 --- a/target/earlgrey/target.ld.jinja +++ b/target/earlgrey/target.ld.jinja @@ -27,11 +27,16 @@ MEMORY * expects to execute at flash SlotA address 0x20000000 (no remapping), and * it configures the remap window for 0xA000000 (which is what the real * ROM_EXT would do). - */ + /* OpenTitan Ibex flash remap window base (0xA0000000) and slot capacity (512 KiB = 0x80000) */ + {% set FLASH_REMAP_BASE = 0xA0000000 %} + {% set FLASH_SLOT_SIZE = 0x80000 %} + {% set rom_ext_len = kernel.flash_start_address - FLASH_REMAP_BASE %} + {% set flash_len = FLASH_SLOT_SIZE - rom_ext_len %} + /* ROM_EXT */ - ROM_EXT(rx) : ORIGIN = 0xA0000000, LENGTH = 0x10000 + ROM_EXT(rx) : ORIGIN = 0xA0000000, LENGTH = {{ rom_ext_len | hex }} /* Internal Flash */ - FLASH(rx) : ORIGIN = 0xA0010000, LENGTH = 0x70000 + FLASH(rx) : ORIGIN = {{ kernel.flash_start_address | hex }}, LENGTH = {{ flash_len | hex }} /* Internal SRAM */ RAM(rw) : ORIGIN = 0x10000000, LENGTH = 0x20000 diff --git a/target/earlgrey/tooling/BUILD.bazel b/target/earlgrey/tooling/BUILD.bazel index b69f442bf..091abf5c6 100644 --- a/target/earlgrey/tooling/BUILD.bazel +++ b/target/earlgrey/tooling/BUILD.bazel @@ -104,3 +104,10 @@ py_binary( requirement("hjson"), ], ) + +py_binary( + name = "system_config_override", + srcs = ["system_config_override.py"], + main = "system_config_override.py", + visibility = ["//visibility:public"], +) diff --git a/target/earlgrey/tooling/system_config.bzl b/target/earlgrey/tooling/system_config.bzl new file mode 100644 index 000000000..187201c85 --- /dev/null +++ b/target/earlgrey/tooling/system_config.bzl @@ -0,0 +1,44 @@ +# Licensed under the Apache-2.0 license +# SPDX-License-Identifier: Apache-2.0 + +"""Rule to generate a modified system.json5 configuration variant.""" + +def _system_config_variant_impl(ctx): + out = ctx.actions.declare_file(ctx.attr.name + ".json5") + args = [ + "--input", + ctx.file.base.path, + "--output", + out.path, + ] + if ctx.attr.flash_start_address: + args.extend(["--flash-start-address", ctx.attr.flash_start_address]) + + ctx.actions.run( + inputs = [ctx.file.base], + outputs = [out], + executable = ctx.executable._tool, + arguments = args, + mnemonic = "SystemConfigVariant", + ) + return [DefaultInfo(files = depset([out]))] + +system_config_variant = rule( + implementation = _system_config_variant_impl, + attrs = { + "base": attr.label( + doc = "Base system.json5 file", + allow_single_file = True, + mandatory = True, + ), + "flash_start_address": attr.string( + doc = "Override for kernel.flash_start_address (e.g. '0xA0016000')", + ), + "_tool": attr.label( + executable = True, + cfg = "exec", + default = "//target/earlgrey/tooling:system_config_override", + ), + }, + doc = "Generates a modified system.json5 configuration variant", +) diff --git a/target/earlgrey/tooling/system_config_override.py b/target/earlgrey/tooling/system_config_override.py new file mode 100644 index 000000000..6bd64500d --- /dev/null +++ b/target/earlgrey/tooling/system_config_override.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +# Licensed under the Apache-2.0 license +# SPDX-License-Identifier: Apache-2.0 + +"""Tool to generate a system.json5 configuration variant with overridden properties.""" + +import argparse +import re +import sys + + +def main(): + parser = argparse.ArgumentParser(description="Override system.json5 properties") + parser.add_argument("--input", required=True, help="Input system.json5 file") + parser.add_argument("--output", required=True, help="Output system.json5 file") + parser.add_argument( + "--flash-start-address", + help="Override kernel.flash_start_address (e.g. 0xA0016000)", + ) + args = parser.parse_args() + + with open(args.input, "r", encoding="utf-8") as f: + content = f.read() + + if args.flash_start_address: + content, count = re.subn( + r"(flash_start_address\s*:\s*)(0x[0-9a-fA-F]+|\d+)", + r"\g<1>" + args.flash_start_address, + content, + count=1, + ) + if count == 0: + sys.exit(f"Error: flash_start_address not found in {args.input}") + + with open(args.output, "w", encoding="utf-8") as f: + f.write(content) + + +if __name__ == "__main__": + main()