| # Copyright lowRISC contributors. |
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| # SPDX-License-Identifier: Apache-2.0 |
| |
| load( |
| "//rules:opentitan_test.bzl", |
| "DEFAULT_TEST_FAILURE_MSG", |
| "cw310_params", |
| "dv_params", |
| "opentitan_functest", |
| "verilator_params", |
| ) |
| load("//rules:const.bzl", "CONST", "error_redact", "hex") |
| load( |
| "//rules:opentitan.bzl", |
| "opentitan_flash_binary", |
| "opentitan_multislot_flash_binary", |
| ) |
| load("//rules:manifest.bzl", "manifest") |
| load("//rules:opentitan_gdb_test.bzl", "opentitan_gdb_fpga_cw310_test") |
| load("//rules:otp.bzl", "otp_image", "otp_json", "otp_partition") |
| load("//rules:rom_e2e.bzl", "maybe_skip_in_ci") |
| load("//rules:splice.bzl", "bitstream_splice") |
| load("@bazel_skylib//lib:shell.bzl", "shell") |
| load("@bazel_skylib//lib:structs.bzl", "structs") |
| |
| package(default_visibility = ["//visibility:public"]) |
| |
| MSG_TEMPLATE_BFV = "{}{}\r\n(?s:.*){}{}\r\n".format( |
| CONST.SHUTDOWN.PREFIX.BFV, |
| "{0}", |
| CONST.SHUTDOWN.PREFIX.BFV, |
| "{0}", |
| ) |
| |
| MSG_TEMPLATE_BFV_LCV = "{}{}\r\n{}{}\r\n(?s:.*){}{}\r\n{}{}\r\n".format( |
| CONST.SHUTDOWN.PREFIX.BFV, |
| "{0}", |
| CONST.SHUTDOWN.PREFIX.LCV, |
| "{1}", |
| CONST.SHUTDOWN.PREFIX.BFV, |
| "{0}", |
| CONST.SHUTDOWN.PREFIX.LCV, |
| "{1}", |
| ) |
| |
| MSG_STARTING_ROM_EXT = "Starting ROM_EXT" |
| |
| MSG_PASS = "PASS!" |
| |
| SLOTS = { |
| "a": "0x0", |
| "b": "0x80000", |
| } |
| |
| [opentitan_flash_binary( |
| name = "empty_test_slot_{}".format(slot), |
| srcs = ["empty_test.c"], |
| devices = [ |
| "fpga_cw310", |
| "sim_dv", |
| "sim_verilator", |
| ], |
| signed = True, |
| deps = [ |
| "//hw/ip/otp_ctrl/data:otp_ctrl_regs", |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| "//sw/device/silicon_creator/lib/drivers:lifecycle", |
| "//sw/device/silicon_creator/lib/drivers:otp", |
| "//sw/device/lib/testing/test_framework:ottf_ld_silicon_creator_slot_{}".format(slot), |
| ], |
| ) for slot in SLOTS] |
| |
| opentitan_functest( |
| name = "rom_e2e_flash_ctrl_init", |
| srcs = ["rom_e2e_flash_ctrl_init_test.c"], |
| signed = True, |
| targets = [ |
| "cw310_rom", |
| ], |
| deps = [ |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| "//sw/device/silicon_creator/lib/drivers:flash_ctrl", |
| "//sw/device/silicon_creator/lib/drivers:otp", |
| ], |
| ) |
| |
| opentitan_functest( |
| name = "rom_e2e_shutdown_exception_c", |
| srcs = ["rom_e2e_shutdown_exception_c_test.c"], |
| cw310 = cw310_params( |
| # Note: This test never prints a failure message so it will fail only |
| # when it times out. |
| exit_failure = "NO_FAILURE_MESSAGE", |
| exit_success = MSG_TEMPLATE_BFV.format(hex(CONST.BFV.INTERRUPT.INSTRUCTION_ACCESS)), |
| ), |
| dv = dv_params( |
| rom = "//sw/device/silicon_creator/rom", |
| ), |
| signed = True, |
| targets = [ |
| "dv", |
| "cw310_rom", |
| "verilator", |
| ], |
| verilator = verilator_params( |
| timeout = "eternal", |
| exit_failure = "NO_FAILURE_MESSAGE", |
| exit_success = MSG_TEMPLATE_BFV.format(hex(CONST.BFV.INTERRUPT.INSTRUCTION_ACCESS)), |
| rom = "//sw/device/silicon_creator/rom", |
| ), |
| deps = [ |
| "//hw/top_earlgrey/sw/autogen:top_earlgrey", |
| "//sw/device/silicon_creator/lib:manifest_def", |
| "//sw/device/silicon_creator/lib/base:static_critical_boot_measurements", |
| "//sw/device/silicon_creator/lib/base:static_critical_epmp_state", |
| "//sw/device/silicon_creator/lib/base:static_critical_sec_mmio", |
| ], |
| ) |
| |
| opentitan_functest( |
| name = "rom_e2e_smoke", |
| cw310 = cw310_params( |
| bitstream = "//hw/bitstream:rom", |
| ), |
| dv = dv_params( |
| rom = "//sw/device/silicon_creator/rom", |
| ), |
| key = "test_key_0", |
| ot_flash_binary = ":empty_test_slot_a", |
| targets = [ |
| "cw310_rom", |
| "verilator", |
| "dv", |
| ], |
| verilator = verilator_params( |
| timeout = "eternal", |
| rom = "//sw/device/silicon_creator/rom", |
| ), |
| ) |
| |
| opentitan_functest( |
| name = "rom_e2e_static_critical", |
| srcs = ["rom_e2e_static_critical_test.c"], |
| dv = dv_params( |
| rom = "//sw/device/silicon_creator/rom", |
| ), |
| signed = True, |
| targets = [ |
| "dv", |
| "cw310_rom", |
| "verilator", |
| ], |
| verilator = verilator_params( |
| timeout = "eternal", |
| rom = "//sw/device/silicon_creator/rom", |
| ), |
| deps = [ |
| "//sw/device/lib/dif:hmac", |
| "//sw/device/lib/testing:hmac_testutils", |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| "//sw/device/silicon_creator/lib/base:sec_mmio", |
| ], |
| ) |
| |
| opentitan_functest( |
| name = "rom_e2e_keymgr_init", |
| srcs = ["rom_e2e_keymgr_init_test.c"], |
| dv = dv_params( |
| rom = "//sw/device/silicon_creator/rom", |
| ), |
| signed = True, |
| targets = [ |
| "cw310_rom", |
| "dv", |
| "verilator", |
| ], |
| verilator = verilator_params( |
| timeout = "eternal", |
| rom = "//sw/device/silicon_creator/rom", |
| ), |
| deps = [ |
| "//sw/device/lib/dif:keymgr", |
| "//sw/device/lib/testing:keymgr_testutils", |
| "//sw/device/lib/testing:otp_ctrl_testutils", |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| ], |
| ) |
| |
| opentitan_functest( |
| name = "rom_e2e_c_init", |
| srcs = ["rom_e2e_c_init_test.c"], |
| cw310 = cw310_params( |
| exit_failure = CONST.SHUTDOWN.PREFIX.BFV, |
| exit_success = MSG_PASS, |
| ), |
| signed = True, |
| targets = [ |
| "cw310_rom", |
| ], |
| deps = [ |
| "//hw/ip/uart/data:uart_regs", |
| "//hw/top_earlgrey/ip/pinmux/data/autogen:pinmux_regs", |
| "//hw/top_earlgrey/sw/autogen:top_earlgrey", |
| "//sw/device/lib/runtime:hart", |
| "//sw/device/lib/runtime:log", |
| "//sw/device/lib/runtime:print", |
| "//sw/device/silicon_creator/lib:manifest_def", |
| "//sw/device/silicon_creator/lib/base:static_critical_boot_measurements", |
| "//sw/device/silicon_creator/lib/base:static_critical_epmp_state", |
| "//sw/device/silicon_creator/lib/base:static_critical_sec_mmio", |
| "//sw/device/silicon_creator/lib/drivers:otp", |
| "//sw/device/silicon_creator/lib/drivers:pinmux", |
| "//sw/device/silicon_creator/lib/drivers:uart", |
| ], |
| ) |
| |
| # Same as `:e2e_bootup_success`, but the Dev OTP image is spliced into the |
| # bitstream before it's sent to the CW310 FPGA. |
| opentitan_functest( |
| name = "e2e_bootup_success_otp_dev", |
| cw310 = cw310_params( |
| bitstream = "//hw/bitstream:rom_otp_dev", |
| # TODO(lowRISC/opentitan#13603): Remove this "manual" tag when the |
| # bitstream target can fetch pre-spliced bitstream from GCP. |
| tags = ["manual"], |
| ), |
| key = "test_key_0", |
| ot_flash_binary = ":empty_test_slot_a", |
| targets = ["cw310_rom"], |
| ) |
| |
| opentitan_functest( |
| name = "e2e_bootstrap_entry", |
| cw310 = cw310_params( |
| test_cmds = [ |
| "--rom-kind=rom", |
| "--bitstream=\"$(location //hw/bitstream:rom)\"", |
| "--bootstrap=\"$(location {flash})\"", |
| ], |
| ), |
| ot_flash_binary = ":empty_test_slot_a", |
| # We don't want the `empty_test` to run, but we _also_ don't want some |
| # leftover flash image from a previous test to run. So, bootstrap an |
| # unsigned image to force a boot failure. |
| signed = False, |
| targets = ["cw310_rom"], |
| test_harness = "//sw/host/tests/rom/e2e_bootstrap_entry", |
| ) |
| |
| opentitan_functest( |
| name = "e2e_bootstrap_disabled", |
| cw310 = cw310_params( |
| bitstream = "//hw/bitstream:rom_otp_bootstrap_disabled", |
| tags = [ |
| "vivado", |
| ], |
| test_cmds = [ |
| "--bitstream=\"$(location {bitstream})\"", |
| ], |
| ), |
| # Since the bitstream disables bootstrap, there is no firmware to |
| # load into the chip. However, opentitan_functest wants to build a |
| # binary target. We'll build an unsigned do-nothing binary. |
| ot_flash_binary = ":empty_test_slot_a", |
| signed = False, |
| targets = ["cw310_rom"], |
| test_harness = "//sw/host/tests/rom/e2e_bootstrap_disabled", |
| ) |
| |
| opentitan_functest( |
| name = "e2e_chip_specific_startup", |
| srcs = ["chip_specific_startup.c"], |
| args = [], |
| cw310 = cw310_params( |
| test_cmds = [ |
| "--rom-kind=rom", |
| "--bitstream=\"$(location //hw/bitstream:rom)\"", |
| "--bootstrap=\"$(location {flash})\"", |
| "--otp-unprogrammed", |
| ], |
| ), |
| signed = True, |
| targets = ["cw310_rom"], |
| test_harness = "//sw/host/tests/rom/e2e_chip_specific_startup", |
| deps = [ |
| "//hw/ip/csrng/data:csrng_regs", |
| "//hw/ip/edn/data:edn_regs", |
| "//hw/ip/entropy_src/data:entropy_src_regs", |
| "//hw/ip/otp_ctrl/data:otp_ctrl_regs", |
| "//hw/top_earlgrey/ip/sensor_ctrl/data:sensor_ctrl_regs", |
| "//hw/top_earlgrey/sw/autogen:top_earlgrey", |
| "//sw/device/lib/base:mmio", |
| "//sw/device/lib/dif:clkmgr", |
| "//sw/device/lib/dif:lc_ctrl", |
| "//sw/device/lib/dif:otp_ctrl", |
| "//sw/device/lib/dif:sram_ctrl", |
| "//sw/device/lib/runtime:log", |
| "//sw/device/lib/testing/json:chip_specific_startup", |
| "//sw/device/lib/testing/json:command", |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| "//sw/device/lib/testing/test_framework:ujson_ottf", |
| "//sw/device/lib/ujson", |
| ], |
| ) |
| |
| opentitan_functest( |
| name = "rom_ext_a_flash_a", |
| cw310 = cw310_params( |
| exit_failure = CONST.SHUTDOWN.PREFIX.BFV, |
| exit_success = MSG_STARTING_ROM_EXT, |
| ), |
| ot_flash_binary = "//sw/device/silicon_creator/rom_ext:rom_ext_slot_a", |
| targets = ["cw310_rom"], |
| ) |
| |
| opentitan_multislot_flash_binary( |
| name = "rom_ext_b_flash_b_image", |
| srcs = { |
| "//sw/device/silicon_creator/rom_ext:rom_ext_slot_b": { |
| "key": "test_key_0", |
| "offset": SLOTS["b"], |
| }, |
| }, |
| ) |
| |
| opentitan_functest( |
| name = "rom_ext_b_flash_b", |
| cw310 = cw310_params( |
| exit_failure = CONST.SHUTDOWN.PREFIX.BFV, |
| exit_success = MSG_STARTING_ROM_EXT, |
| ), |
| key = "multislot", |
| ot_flash_binary = ":rom_ext_b_flash_b_image", |
| targets = ["cw310_rom"], |
| ) |
| |
| opentitan_multislot_flash_binary( |
| name = "rom_ext_a_flash_b_image", |
| srcs = { |
| "//sw/device/silicon_creator/rom_ext:rom_ext_slot_a": { |
| "key": "test_key_0", |
| "offset": SLOTS["b"], |
| }, |
| }, |
| ) |
| |
| opentitan_functest( |
| name = "rom_ext_a_flash_b", |
| cw310 = cw310_params( |
| exit_failure = MSG_STARTING_ROM_EXT, |
| exit_success = MSG_TEMPLATE_BFV.format(hex(CONST.BFV.INTERRUPT.STORE_ACCESS)), |
| ), |
| key = "multislot", |
| ot_flash_binary = ":rom_ext_a_flash_b_image", |
| targets = ["cw310_rom"], |
| ) |
| |
| opentitan_multislot_flash_binary( |
| name = "rom_ext_b_flash_a_image", |
| srcs = { |
| "//sw/device/silicon_creator/rom_ext:rom_ext_slot_b": { |
| "key": "test_key_0", |
| "offset": SLOTS["a"], |
| }, |
| }, |
| ) |
| |
| opentitan_functest( |
| name = "rom_ext_b_flash_a", |
| cw310 = cw310_params( |
| exit_failure = MSG_STARTING_ROM_EXT, |
| exit_success = MSG_TEMPLATE_BFV.format(hex(CONST.BFV.INTERRUPT.STORE_ACCESS)), |
| ), |
| key = "multislot", |
| ot_flash_binary = ":rom_ext_b_flash_a_image", |
| targets = ["cw310_rom"], |
| ) |
| |
| opentitan_functest( |
| name = "rom_ext_v_flash_a", |
| cw310 = cw310_params( |
| exit_failure = CONST.SHUTDOWN.PREFIX.BFV, |
| exit_success = MSG_STARTING_ROM_EXT, |
| ), |
| ot_flash_binary = "//sw/device/silicon_creator/rom_ext:rom_ext_slot_virtual", |
| targets = ["cw310_rom"], |
| ) |
| |
| opentitan_multislot_flash_binary( |
| name = "rom_ext_v_flash_b_image", |
| srcs = { |
| "//sw/device/silicon_creator/rom_ext:rom_ext_slot_virtual": { |
| "key": "test_key_0", |
| "offset": SLOTS["b"], |
| }, |
| }, |
| ) |
| |
| opentitan_functest( |
| name = "rom_ext_v_flash_b", |
| cw310 = cw310_params( |
| exit_failure = CONST.SHUTDOWN.PREFIX.BFV, |
| exit_success = MSG_STARTING_ROM_EXT, |
| ), |
| key = "multislot", |
| ot_flash_binary = ":rom_ext_v_flash_b_image", |
| targets = ["cw310_rom"], |
| ) |
| |
| opentitan_functest( |
| name = "rom_ext_a_flash_a_bad_addr_trans", |
| cw310 = cw310_params( |
| exit_failure = MSG_STARTING_ROM_EXT, |
| exit_success = MSG_TEMPLATE_BFV.format(hex(CONST.BFV.INTERRUPT.ILLEGAL_INSTRUCTION)), |
| ), |
| ot_flash_binary = "//sw/device/silicon_creator/rom_ext:rom_ext_slot_a_bad_address_translation", |
| targets = ["cw310_rom"], |
| ) |
| |
| test_suite( |
| name = "address_translation", |
| tags = ["manual"], |
| tests = [ |
| "rom_ext_a_flash_a", |
| "rom_ext_a_flash_a_bad_addr_trans", |
| "rom_ext_a_flash_b", |
| "rom_ext_b_flash_a", |
| "rom_ext_b_flash_b", |
| "rom_ext_v_flash_a", |
| "rom_ext_v_flash_b", |
| ], |
| ) |
| |
| opentitan_functest( |
| name = "sigverify_key_auth", |
| cw310 = cw310_params( |
| exit_failure = MSG_PASS, |
| exit_success = MSG_TEMPLATE_BFV.format(hex(CONST.BFV.SIGVERIFY.BAD_KEY)), |
| ), |
| key = "unauthorized_0", |
| ot_flash_binary = ":empty_test_slot_a", |
| targets = ["cw310_rom"], |
| ) |
| |
| [otp_image( |
| name = "otp_img_shutdown_output_{}".format(lc_state.lower()), |
| src = "//hw/ip/otp_ctrl/data:otp_json_{}".format(lc_state.lower()), |
| overlays = [ |
| "//hw/ip/otp_ctrl/data:otp_json_creator_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_owner_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_alert_digest_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_hw_cfg", |
| ], |
| ) for lc_state in structs.to_dict(CONST.LCV)] |
| |
| # Splice OTP images into bitstreams |
| [ |
| bitstream_splice( |
| name = "bitstream_shutdown_output_{}".format(lc_state.lower()), |
| src = "//hw/bitstream:rom", |
| data = ":otp_img_shutdown_output_{}".format(lc_state.lower()), |
| meminfo = "//hw/bitstream:otp_mmi", |
| tags = ["vivado"], |
| update_usr_access = True, |
| ) |
| for lc_state in structs.to_dict(CONST.LCV) |
| ] |
| |
| manifest({ |
| "name": "manifest_bad_identifier", |
| "address_translation": hex(CONST.FALSE), |
| "identifier": "0", |
| }) |
| |
| [opentitan_functest( |
| name = "shutdown_output_{}".format(lc_state.lower()), |
| cw310 = cw310_params( |
| bitstream = ":bitstream_shutdown_output_{}".format(lc_state.lower()), |
| exit_failure = MSG_PASS, |
| exit_success = MSG_TEMPLATE_BFV_LCV.format( |
| hex(CONST.BFV.BOOT_POLICY.BAD_IDENTIFIER), |
| hex(lc_state_val), |
| ), |
| otp = ":otp_img_shutdown_output_{}".format(lc_state.lower()), |
| tags = ["vivado"] + maybe_skip_in_ci(lc_state_val), |
| ), |
| dv = dv_params( |
| otp = ":otp_img_shutdown_output_{}".format(lc_state.lower()), |
| rom = "//sw/device/silicon_creator/rom", |
| ), |
| manifest = ":manifest_bad_identifier", |
| ot_flash_binary = ":empty_test_slot_a", |
| signed = False, |
| targets = [ |
| "cw310_rom", |
| "dv", |
| ], |
| ) for lc_state, lc_state_val in structs.to_dict(CONST.LCV).items()] |
| |
| test_suite( |
| name = "shutdown_output", |
| tags = ["manual"], |
| tests = ["shutdown_output_{}".format(lc_state.lower()) for lc_state in structs.to_dict(CONST.LCV)], |
| ) |
| |
| SEC_VERS = [ |
| 0, |
| 1, |
| 2, |
| ] |
| |
| [manifest({ |
| "name": "manifest_sec_ver_{}".format(sec_ver), |
| "address_translation": hex(CONST.FALSE), |
| "identifier": hex(CONST.ROM_EXT), |
| "security_version": hex(sec_ver), |
| }) for sec_ver in SEC_VERS] |
| |
| [opentitan_flash_binary( |
| name = "empty_test_slot_{}_sec_ver_{}".format(slot, sec_ver), |
| srcs = ["empty_test.c"], |
| devices = ["fpga_cw310"], |
| local_defines = [ |
| shell.quote("EMPTY_TEST_MSG=\"slot=%p, security_version=%01d, lc_state=0x%08x\", manifest_def_get(), manifest_def_get()->security_version, lifecycle_raw_state_get()"), |
| ], |
| manifest = ":manifest_sec_ver_{}".format(sec_ver), |
| signed = True, |
| deps = [ |
| "//hw/ip/otp_ctrl/data:otp_ctrl_regs", |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| "//sw/device/silicon_creator/lib/drivers:lifecycle", |
| "//sw/device/silicon_creator/lib/drivers:otp", |
| "//sw/device/lib/testing/test_framework:ottf_ld_silicon_creator_slot_{}".format(slot), |
| ], |
| ) for slot in SLOTS for sec_ver in SEC_VERS] |
| |
| [opentitan_multislot_flash_binary( |
| name = "sec_ver_{}_{}_image".format(sec_ver_a, sec_ver_b), |
| srcs = { |
| ":empty_test_slot_a_sec_ver_{}".format(sec_ver_a): { |
| "key": "test_key_0", |
| "offset": SLOTS["a"], |
| }, |
| ":empty_test_slot_b_sec_ver_{}".format(sec_ver_b): { |
| "key": "test_key_0", |
| "offset": SLOTS["b"], |
| }, |
| }, |
| devices = ["fpga_cw310"], |
| ) for sec_ver_a in SEC_VERS for sec_ver_b in SEC_VERS] |
| |
| BOOT_POLICY_NEWER_CASES = [ |
| { |
| "a": 0, |
| "b": 0, |
| "exit_success": "slot=0x20000000, security_version=0, lc_state=0x{}", |
| }, |
| { |
| "a": 0, |
| "b": 1, |
| "exit_success": "slot=0x20080000, security_version=1, lc_state=0x{}", |
| }, |
| { |
| "a": 1, |
| "b": 0, |
| "exit_success": "slot=0x20000000, security_version=1, lc_state=0x{}", |
| }, |
| { |
| "a": 1, |
| "b": 1, |
| "exit_success": "slot=0x20000000, security_version=1, lc_state=0x{}", |
| }, |
| ] |
| |
| [otp_image( |
| name = "otp_img_boot_policy_newer_{}".format(lc_state.lower()), |
| src = "//hw/ip/otp_ctrl/data:otp_json_{}".format(lc_state.lower()), |
| overlays = [ |
| "//hw/ip/otp_ctrl/data:otp_json_creator_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_owner_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_alert_digest_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_hw_cfg", |
| ], |
| ) for lc_state in structs.to_dict(CONST.LCV)] |
| |
| # Splice OTP images into bitstreams |
| [ |
| bitstream_splice( |
| name = "bitstream_boot_policy_newer_{}".format(lc_state.lower()), |
| src = "//hw/bitstream:rom", |
| data = ":otp_img_boot_policy_newer_{}".format(lc_state.lower()), |
| meminfo = "//hw/bitstream:otp_mmi", |
| tags = ["vivado"], |
| update_usr_access = True, |
| ) |
| for lc_state in structs.to_dict(CONST.LCV) |
| ] |
| |
| [opentitan_functest( |
| name = "boot_policy_newer_{}_a_{}_b_{}".format( |
| lc_state.lower(), |
| t["a"], |
| t["b"], |
| ), |
| cw310 = cw310_params( |
| bitstream = ":bitstream_boot_policy_newer_{}".format(lc_state.lower()), |
| exit_success = t["exit_success"].format(hex(lc_state_val)), |
| tags = ["vivado"] + maybe_skip_in_ci(lc_state_val), |
| ), |
| key = "multislot", |
| ot_flash_binary = ":sec_ver_{}_{}_image".format( |
| t["a"], |
| t["b"], |
| ), |
| targets = ["cw310_rom"], |
| ) for lc_state, lc_state_val in structs.to_dict(CONST.LCV).items() for t in BOOT_POLICY_NEWER_CASES] |
| |
| test_suite( |
| name = "boot_policy_newer", |
| tags = ["manual"], |
| tests = ["boot_policy_newer_{}_a_{}_b_{}".format( |
| lc_state.lower(), |
| t["a"], |
| t["b"], |
| ) for lc_state in structs.to_dict(CONST.LCV) for t in BOOT_POLICY_NEWER_CASES], |
| ) |
| |
| BOOT_POLICY_ROLLBACK_CASES = [ |
| { |
| "a": 0, |
| "b": 0, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.BOOT_POLICY.ROLLBACK)), |
| }, |
| { |
| "a": 0, |
| "b": 1, |
| "exit_success": "slot=0x20080000, security_version=1", |
| }, |
| { |
| "a": 2, |
| "b": 0, |
| "exit_success": "slot=0x20000000, security_version=2", |
| }, |
| { |
| "a": 1, |
| "b": 1, |
| "exit_success": "slot=0x20000000, security_version=1", |
| }, |
| ] |
| |
| otp_json( |
| name = "otp_json_boot_policy_rollback", |
| partitions = [ |
| otp_partition( |
| name = "CREATOR_SW_CFG", |
| items = { |
| "CREATOR_SW_CFG_MIN_SEC_VER_ROM_EXT": "1", |
| }, |
| ), |
| ], |
| ) |
| |
| [otp_image( |
| name = "otp_img_boot_policy_rollback_{}".format(lc_state.lower()), |
| src = "//hw/ip/otp_ctrl/data:otp_json_{}".format(lc_state.lower()), |
| overlays = [ |
| "//hw/ip/otp_ctrl/data:otp_json_creator_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_owner_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_alert_digest_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_hw_cfg", |
| ":otp_json_boot_policy_rollback", |
| ], |
| visibility = ["//visibility:private"], |
| ) for lc_state in structs.to_dict(CONST.LCV)] |
| |
| [bitstream_splice( |
| name = "bitstream_boot_policy_rollback_{}".format( |
| lc_state.lower(), |
| ), |
| src = "//hw/bitstream:rom", |
| data = ":otp_img_boot_policy_rollback_{}".format( |
| lc_state.lower(), |
| ), |
| meminfo = "//hw/bitstream:otp_mmi", |
| tags = ["vivado"], |
| update_usr_access = True, |
| visibility = ["//visibility:private"], |
| ) for lc_state in structs.to_dict(CONST.LCV)] |
| |
| [opentitan_functest( |
| name = "boot_policy_rollback_{}_a_{}_b_{}".format( |
| lc_state.lower(), |
| t["a"], |
| t["b"], |
| ), |
| cw310 = cw310_params( |
| bitstream = "bitstream_boot_policy_rollback_{}".format(lc_state.lower()), |
| exit_success = t["exit_success"], |
| tags = ["vivado"] + maybe_skip_in_ci(lc_state_val), |
| ), |
| key = "multislot", |
| ot_flash_binary = ":sec_ver_{}_{}_image".format( |
| t["a"], |
| t["b"], |
| ), |
| targets = ["cw310_rom"], |
| ) for lc_state, lc_state_val in structs.to_dict(CONST.LCV).items() for t in BOOT_POLICY_ROLLBACK_CASES] |
| |
| test_suite( |
| name = "rom_e2e_boot_policy_rollback", |
| tags = ["manual"], |
| tests = ["boot_policy_rollback_{}_a_{}_b_{}".format( |
| lc_state.lower(), |
| t["a"], |
| t["b"], |
| ) for lc_state in structs.to_dict(CONST.LCV) for t in BOOT_POLICY_ROLLBACK_CASES], |
| ) |
| |
| # Watchdog configuration test cases. |
| # |
| # These test cases verify the ROM correctly configures the watchdog in each life |
| # cycle state. Tests are run for OTP configurations that disable the watchdog |
| # and for OTP configurations that enable the watchdog. |
| |
| # Watchdog bite threshold for the watchdog-enabled cases. This is 2 seconds, |
| # assuming a 200kHz clock. |
| WATCHDOG_BITE_THRESHOLD = "0x61a80" |
| |
| # OTP overlay that enables the watchdog. The bite threshold is 2 seconds, |
| # assuming a 200kHz clock. |
| otp_json( |
| name = "otp_json_watchdog_enable", |
| partitions = [ |
| otp_partition( |
| name = "OWNER_SW_CFG", |
| items = {"OWNER_SW_CFG_ROM_WATCHDOG_BITE_THRESHOLD_CYCLES": WATCHDOG_BITE_THRESHOLD}, |
| ), |
| ], |
| ) |
| |
| # OTP images that enable the watchdog. |
| [otp_image( |
| name = "otp_img_watchdog_enable_{}".format(lc_state.lower()), |
| src = "//hw/ip/otp_ctrl/data:otp_json_{}".format(lc_state.lower()), |
| overlays = [ |
| "//hw/ip/otp_ctrl/data:otp_json_creator_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_owner_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_hw_cfg", |
| ":otp_json_watchdog_enable", |
| ], |
| ) for lc_state in structs.to_dict(CONST.LCV)] |
| |
| # Bitstreams with the watchdog-enable OTP images spliced in. |
| [bitstream_splice( |
| name = "bitstream_watchdog_enable_{}".format(lc_state.lower()), |
| src = "//hw/bitstream:rom", |
| data = ":otp_img_watchdog_enable_{}".format(lc_state.lower()), |
| meminfo = "//hw/bitstream:otp_mmi", |
| tags = ["vivado"] + maybe_skip_in_ci(lc_state_val), |
| update_usr_access = True, |
| ) for lc_state, lc_state_val in structs.to_dict(CONST.LCV).items()] |
| |
| # Creates a binary that confirms the watchdog is enabled and a binary that |
| # confirms the watchdog is disabled. |
| [opentitan_flash_binary( |
| name = "test_watchdog_{}".format(watchdog_config), |
| srcs = ["watchdog_test.c"], |
| devices = [ |
| "fpga_cw310", |
| "sim_verilator", |
| ], |
| local_defines = [ |
| "EXPECT_WATCHDOG_{}".format(watchdog_config.upper()), |
| "WATCHDOG_BITE_THRESHOLD={}".format(WATCHDOG_BITE_THRESHOLD), |
| ], |
| deps = [ |
| "//hw/ip/aon_timer/data:aon_timer_regs", |
| "//hw/top_earlgrey/sw/autogen:top_earlgrey", |
| "//sw/device/lib/base:abs_mmio", |
| "//sw/device/lib/testing/test_framework:ottf_ld_silicon_creator_slot_a", |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| ], |
| ) for watchdog_config in [ |
| "disabled", |
| "enabled", |
| ]] |
| |
| WATCHDOG_TEST_CASES = { |
| "disable": { |
| "DEV": "disabled", |
| "PROD": "disabled", |
| "PROD_END": "disabled", |
| "RMA": "disabled", |
| "TEST_UNLOCKED0": "disabled", |
| }, |
| "enable": { |
| "DEV": "enabled", |
| "PROD": "enabled", |
| "PROD_END": "enabled", |
| "RMA": "disabled", |
| "TEST_UNLOCKED0": "disabled", |
| }, |
| } |
| |
| # Bitstream targets (CW310) and otp images (verilator) for the watchdog config |
| # tests. The format argument should be replaced with the desired life cycle |
| # state. |
| WATCHDOG_BITSTREAM = { |
| "disable": "//hw/bitstream:rom_otp_{}", |
| "enable": ":bitstream_watchdog_enable_{}", |
| } |
| |
| WATCHDOG_OTP = { |
| "disable": "//hw/ip/otp_ctrl/data:img_{}", |
| "enable": ":otp_img_watchdog_enable_{}", |
| } |
| |
| [opentitan_functest( |
| name = "watchdog_{}_{}".format( |
| otp_config, |
| lc_state.lower(), |
| ), |
| cw310 = cw310_params( |
| bitstream = WATCHDOG_BITSTREAM[otp_config].format(lc_state.lower()), |
| tags = ["vivado"] + maybe_skip_in_ci(lc_state_val), |
| ), |
| ot_flash_binary = ":test_watchdog_{}".format(WATCHDOG_TEST_CASES[otp_config][lc_state]), |
| targets = [ |
| "cw310_rom", |
| "verilator", |
| ], |
| verilator = verilator_params( |
| timeout = "eternal", |
| otp = WATCHDOG_OTP[otp_config].format(lc_state.lower()), |
| rom = "//sw/device/silicon_creator/rom:rom", |
| # Test cases that enable the watchdog time out in verilator, cause |
| # unknown. |
| tags = ["broken"] if WATCHDOG_TEST_CASES[otp_config][lc_state] == "enabled" else [], |
| ), |
| ) for otp_config in [ |
| "disable", |
| "enable", |
| ] for lc_state, lc_state_val in structs.to_dict(CONST.LCV).items()] |
| |
| test_suite( |
| name = "rom_e2e_watchdog_reconfig", |
| tags = ["manual"], |
| tests = [ |
| "watchdog_{}_{}".format( |
| otp_config, |
| lc_state.lower(), |
| ) |
| for otp_config in [ |
| "disable", |
| "enable", |
| ] |
| for lc_state in structs.to_dict(CONST.LCV) |
| ], |
| ) |
| |
| SIGVERIFY_MOD_EXP_CASES = [ |
| { |
| "name": "sw", |
| "use_sw_rsa_verify": CONST.TRUE, |
| "exit_success": {lc_state.lower(): "use_sw_rsa_verify=0x00000739" for lc_state in structs.to_dict(CONST.LCV)}, |
| }, |
| { |
| "name": "otbn", |
| "use_sw_rsa_verify": CONST.FALSE, |
| "exit_success": {lc_state.lower(): "use_sw_rsa_verify=0x000001d4" for lc_state in structs.to_dict(CONST.LCV)}, |
| }, |
| { |
| "name": "invalid", |
| "use_sw_rsa_verify": 0, |
| "exit_success": { |
| lc_state.lower(): MSG_TEMPLATE_BFV.format(hex(CONST.BFV.INTERRUPT.ILLEGAL_INSTRUCTION)) if lc_state_val != CONST.LCV.TEST_UNLOCKED0 else "use_sw_rsa_verify=0x00000000" |
| for lc_state, lc_state_val in structs.to_dict(CONST.LCV).items() |
| }, |
| }, |
| ] |
| |
| opentitan_flash_binary( |
| name = "empty_test_sigverify_mod_exp", |
| srcs = ["empty_test.c"], |
| devices = ["fpga_cw310"], |
| local_defines = [ |
| shell.quote("EMPTY_TEST_MSG=\"use_sw_rsa_verify=0x%08x\", otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_USE_SW_RSA_VERIFY_OFFSET)"), |
| ], |
| signed = True, |
| deps = [ |
| "//hw/ip/otp_ctrl/data:otp_ctrl_regs", |
| "//sw/device/lib/testing/test_framework:ottf_ld_silicon_creator_slot_a", |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| "//sw/device/silicon_creator/lib/drivers:lifecycle", |
| "//sw/device/silicon_creator/lib/drivers:otp", |
| ], |
| ) |
| |
| [ |
| otp_json( |
| name = "otp_json_sigverify_mod_exp_{}".format(t["name"]), |
| partitions = [ |
| otp_partition( |
| name = "CREATOR_SW_CFG", |
| items = {"CREATOR_SW_CFG_USE_SW_RSA_VERIFY": "0x{}".format(hex(t["use_sw_rsa_verify"]))}, |
| ), |
| ], |
| ) |
| for t in SIGVERIFY_MOD_EXP_CASES |
| ] |
| |
| [ |
| otp_image( |
| name = "otp_img_sigverify_mod_exp_{}_{}".format( |
| lc_state.lower(), |
| t["name"], |
| ), |
| src = "//hw/ip/otp_ctrl/data:otp_json_{}".format(lc_state.lower()), |
| overlays = [ |
| "//hw/ip/otp_ctrl/data:otp_json_creator_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_owner_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_alert_digest_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_hw_cfg", |
| ":otp_json_sigverify_mod_exp_{}".format(t["name"]), |
| ], |
| visibility = ["//visibility:private"], |
| ) |
| for lc_state in structs.to_dict(CONST.LCV) |
| for t in SIGVERIFY_MOD_EXP_CASES |
| ] |
| |
| [ |
| bitstream_splice( |
| name = "bitstream_sigverify_mod_exp_{}_{}".format( |
| lc_state.lower(), |
| t["name"], |
| ), |
| src = "//hw/bitstream:rom", |
| data = ":otp_img_sigverify_mod_exp_{}_{}".format( |
| lc_state.lower(), |
| t["name"], |
| ), |
| meminfo = "//hw/bitstream:otp_mmi", |
| tags = ["vivado"], |
| update_usr_access = True, |
| visibility = ["//visibility:private"], |
| ) |
| for lc_state in structs.to_dict(CONST.LCV) |
| for t in SIGVERIFY_MOD_EXP_CASES |
| ] |
| |
| [ |
| opentitan_functest( |
| name = "sigverify_mod_exp_{}_{}".format( |
| lc_state.lower(), |
| t["name"], |
| ), |
| cw310 = cw310_params( |
| bitstream = ":bitstream_sigverify_mod_exp_{}_{}".format( |
| lc_state.lower(), |
| t["name"], |
| ), |
| exit_success = t["exit_success"][lc_state.lower()], |
| tags = ["vivado"] + maybe_skip_in_ci(lc_state_val), |
| ), |
| ot_flash_binary = ":empty_test_sigverify_mod_exp", |
| targets = ["cw310_rom"], |
| ) |
| for lc_state, lc_state_val in structs.to_dict(CONST.LCV).items() |
| for t in SIGVERIFY_MOD_EXP_CASES |
| ] |
| |
| test_suite( |
| name = "rom_e2e_sigverify_mod_exp", |
| tags = ["manual"], |
| tests = ["sigverify_mod_exp_{}_{}".format( |
| lc_state.lower(), |
| t["name"], |
| ) for lc_state in structs.to_dict(CONST.LCV) for t in SIGVERIFY_MOD_EXP_CASES], |
| ) |
| |
| BOOT_POLICY_BAD_MANIFEST_CASES = [ |
| { |
| "name": "bad_identifier", |
| "manifest": { |
| "identifier": "0", |
| }, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.BOOT_POLICY.BAD_IDENTIFIER)), |
| }, |
| { |
| "name": "too_small", |
| "manifest": { |
| "identifier": hex(CONST.ROM_EXT), |
| "length": hex(CONST.ROM_EXT_SIZE_MIN - 1), |
| }, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.BOOT_POLICY.BAD_LENGTH)), |
| }, |
| { |
| "name": "too_large", |
| "manifest": { |
| "identifier": hex(CONST.ROM_EXT), |
| "length": hex(CONST.ROM_EXT_SIZE_MAX + 1), |
| }, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.BOOT_POLICY.BAD_LENGTH)), |
| }, |
| { |
| "name": "empty_code", |
| "manifest": { |
| # Note: `length` is filled automatically unless overriden here. |
| "identifier": hex(CONST.ROM_EXT), |
| "code_start": hex(CONST.MANIFEST_SIZE + 12), |
| "code_end": hex(CONST.MANIFEST_SIZE + 12), |
| }, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.MANIFEST.BAD_CODE_REGION)), |
| }, |
| { |
| "name": "code_in_manifest", |
| "manifest": { |
| "identifier": hex(CONST.ROM_EXT), |
| "code_start": hex(CONST.MANIFEST_SIZE - 4), |
| "code_end": hex(CONST.MANIFEST_SIZE + 12), |
| "entry_point": hex(CONST.MANIFEST_SIZE + 8), |
| }, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.MANIFEST.BAD_CODE_REGION)), |
| }, |
| { |
| "name": "code_outside_image", |
| "manifest": { |
| "identifier": hex(CONST.ROM_EXT), |
| "code_start": hex(CONST.ROM_EXT_SIZE_MAX), |
| "code_end": hex(CONST.MANIFEST_SIZE + 12), |
| "entry_point": hex(CONST.MANIFEST_SIZE + 8), |
| }, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.MANIFEST.BAD_CODE_REGION)), |
| }, |
| { |
| "name": "code_start_unaligned", |
| "manifest": { |
| "identifier": hex(CONST.ROM_EXT), |
| "code_start": hex(CONST.MANIFEST_SIZE + 6), |
| "code_end": hex(CONST.MANIFEST_SIZE + 12), |
| "entry_point": hex(CONST.MANIFEST_SIZE + 8), |
| }, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.MANIFEST.BAD_CODE_REGION)), |
| }, |
| { |
| "name": "code_end_unaligned", |
| "manifest": { |
| "identifier": hex(CONST.ROM_EXT), |
| "code_start": hex(CONST.MANIFEST_SIZE + 8), |
| "code_end": hex(CONST.MANIFEST_SIZE + 10), |
| "entry_point": hex(CONST.MANIFEST_SIZE + 8), |
| }, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.MANIFEST.BAD_CODE_REGION)), |
| }, |
| { |
| "name": "entry_before_code_start", |
| "manifest": { |
| "identifier": hex(CONST.ROM_EXT), |
| "code_start": hex(CONST.MANIFEST_SIZE + 8), |
| "code_end": hex(CONST.MANIFEST_SIZE + 12), |
| "entry_point": hex(CONST.MANIFEST_SIZE + 4), |
| }, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.MANIFEST.BAD_ENTRY_POINT)), |
| }, |
| { |
| "name": "entry_at_code_end", |
| "manifest": { |
| "identifier": hex(CONST.ROM_EXT), |
| "code_start": hex(CONST.MANIFEST_SIZE + 8), |
| "code_end": hex(CONST.MANIFEST_SIZE + 12), |
| "entry_point": hex(CONST.MANIFEST_SIZE + 12), |
| }, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.MANIFEST.BAD_ENTRY_POINT)), |
| }, |
| { |
| "name": "entry_unaligned", |
| "manifest": { |
| "identifier": hex(CONST.ROM_EXT), |
| "code_start": hex(CONST.MANIFEST_SIZE + 8), |
| "code_end": hex(CONST.MANIFEST_SIZE + 12), |
| "entry_point": hex(CONST.MANIFEST_SIZE + 10), |
| }, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.MANIFEST.BAD_ENTRY_POINT)), |
| }, |
| { |
| "name": "rollback", |
| "manifest": { |
| "identifier": hex(CONST.ROM_EXT), |
| "code_start": hex(CONST.MANIFEST_SIZE + 8), |
| "code_end": hex(CONST.MANIFEST_SIZE + 12), |
| "entry_point": hex(CONST.MANIFEST_SIZE + 8), |
| "security_version": "0", |
| }, |
| "exit_success": MSG_TEMPLATE_BFV.format(hex(CONST.BFV.BOOT_POLICY.ROLLBACK)), |
| "sec_ver": 1, |
| }, |
| ] |
| |
| [opentitan_flash_binary( |
| name = "boot_policy_bad_manifest_{}_{}_bin".format( |
| t["name"], |
| slot, |
| ), |
| srcs = ["empty_test.c"], |
| devices = [ |
| "fpga_cw310", |
| "sim_dv", |
| "sim_verilator", |
| ], |
| manifest = manifest(dict( |
| t["manifest"], |
| name = "{}_{}".format( |
| t["name"], |
| slot, |
| ), |
| )), |
| signed = True, |
| deps = [ |
| "//hw/ip/otp_ctrl/data:otp_ctrl_regs", |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| "//sw/device/silicon_creator/lib/drivers:lifecycle", |
| "//sw/device/silicon_creator/lib/drivers:otp", |
| "//sw/device/lib/testing/test_framework:ottf_ld_silicon_creator_slot_{}".format(slot), |
| ], |
| ) for t in BOOT_POLICY_BAD_MANIFEST_CASES for slot in SLOTS] |
| |
| [opentitan_multislot_flash_binary( |
| name = "boot_policy_bad_manifest_{}_{}_img".format( |
| t["name"], |
| slot, |
| ), |
| srcs = { |
| "boot_policy_bad_manifest_{}_{}_bin".format( |
| t["name"], |
| slot, |
| ): { |
| "key": "test_key_0", |
| "offset": offset, |
| }, |
| }, |
| devices = [ |
| "fpga_cw310", |
| "sim_dv", |
| "sim_verilator", |
| ], |
| ) for t in BOOT_POLICY_BAD_MANIFEST_CASES for slot, offset in SLOTS.items()] |
| |
| [ |
| otp_json( |
| name = "otp_json_sec_ver_{}".format(sec_ver), |
| partitions = [ |
| otp_partition( |
| name = "CREATOR_SW_CFG", |
| items = { |
| "CREATOR_SW_CFG_MIN_SEC_VER_ROM_EXT": "{}".format(sec_ver), |
| }, |
| ), |
| ], |
| ) |
| for sec_ver in [ |
| 0, |
| 1, |
| ] |
| ] |
| |
| [ |
| otp_image( |
| name = "otp_img_boot_policy_bad_manifest_{}_sec_ver_{}".format( |
| lc_state.lower(), |
| sec_ver, |
| ), |
| src = "//hw/ip/otp_ctrl/data:otp_json_{}".format(lc_state.lower()), |
| overlays = [ |
| "//hw/ip/otp_ctrl/data:otp_json_creator_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_owner_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_alert_digest_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_hw_cfg", |
| ":otp_json_sec_ver_{}".format(sec_ver), |
| ], |
| visibility = ["//visibility:private"], |
| ) |
| for lc_state in structs.to_dict(CONST.LCV) |
| for sec_ver in [ |
| 0, |
| 1, |
| ] |
| ] |
| |
| [ |
| bitstream_splice( |
| name = "bitstream_boot_policy_bad_manifest_{}_sec_ver_{}".format( |
| lc_state.lower(), |
| sec_ver, |
| ), |
| src = "//hw/bitstream:rom", |
| data = ":otp_img_boot_policy_bad_manifest_{}_sec_ver_{}".format( |
| lc_state.lower(), |
| sec_ver, |
| ), |
| meminfo = "//hw/bitstream:otp_mmi", |
| tags = ["vivado"], |
| update_usr_access = True, |
| visibility = ["//visibility:private"], |
| ) |
| for lc_state in structs.to_dict(CONST.LCV) |
| for sec_ver in [ |
| 0, |
| 1, |
| ] |
| ] |
| |
| [ |
| opentitan_functest( |
| name = "boot_policy_bad_manifest_{}_{}_{}".format( |
| lc_state.lower(), |
| t["name"], |
| slot, |
| ), |
| cw310 = cw310_params( |
| bitstream = "bitstream_boot_policy_bad_manifest_{}_sec_ver_{}".format( |
| lc_state.lower(), |
| t.get("sec_ver", 0), |
| ), |
| exit_success = t["exit_success"], |
| tags = ["vivado"] + maybe_skip_in_ci(lc_state_val), |
| ), |
| key = "multislot", |
| ot_flash_binary = "boot_policy_bad_manifest_{}_{}_img".format( |
| t["name"], |
| slot, |
| ), |
| targets = [ |
| "cw310_rom", |
| "verilator", |
| ], |
| verilator = verilator_params( |
| tags = [ |
| # FIXME:#16056 Verilator fails to set up test. |
| "vivado", |
| "broken", |
| ], |
| ), |
| ) |
| for lc_state, lc_state_val in structs.to_dict(CONST.LCV).items() |
| for t in BOOT_POLICY_BAD_MANIFEST_CASES |
| for slot in SLOTS |
| ] |
| |
| test_suite( |
| name = "rom_e2e_boot_policy_bad_manifest", |
| tags = ["manual"], |
| tests = [ |
| "boot_policy_bad_manifest_{}_{}_{}".format( |
| lc_state.lower(), |
| t["name"], |
| slot, |
| ) |
| for lc_state in structs.to_dict(CONST.LCV) |
| for t in BOOT_POLICY_BAD_MANIFEST_CASES |
| for slot in SLOTS |
| ], |
| ) |
| |
| SHUTDOWN_WATCHDOG_BITE_THRESHOLDS = [ |
| 400000, # 2 seconds at 200 kHz |
| 0, # Watchdog disabled |
| ] |
| |
| SHUTDOWN_WATCHDOG_CASES = [ |
| { |
| "lc_state": lc_state, |
| "exit_success": "Returning after 1 seconds", |
| "bite_threshold": bite_threshold, |
| } |
| for lc_state in [ |
| "test_unlocked0", |
| "rma", |
| ] |
| for bite_threshold in SHUTDOWN_WATCHDOG_BITE_THRESHOLDS |
| ] + [ |
| { |
| "lc_state": lc_state, |
| "exit_success": "Returning after 1 seconds" if bite_threshold == 0 else "I00000[^\r\n]*\r\nROM:[0-9a-f]{8}\r\n", |
| "bite_threshold": bite_threshold, |
| } |
| for lc_state in [ |
| "dev", |
| "prod", |
| "prod_end", |
| ] |
| for bite_threshold in SHUTDOWN_WATCHDOG_BITE_THRESHOLDS |
| ] |
| |
| [ |
| otp_json( |
| name = "otp_json_shutdown_watchdog_{}_{}".format( |
| t["lc_state"], |
| t["bite_threshold"], |
| ), |
| partitions = [ |
| otp_partition( |
| name = "OWNER_SW_CFG", |
| items = {"OWNER_SW_CFG_ROM_WATCHDOG_BITE_THRESHOLD_CYCLES": "0x{}".format(hex(t["bite_threshold"]))}, |
| ), |
| ], |
| ) |
| for t in SHUTDOWN_WATCHDOG_CASES |
| ] |
| |
| [ |
| otp_image( |
| name = "otp_img_shutdown_watchdog_{}_{}".format( |
| t["lc_state"], |
| t["bite_threshold"], |
| ), |
| src = "//hw/ip/otp_ctrl/data:otp_json_{}".format(t["lc_state"]), |
| overlays = [ |
| "//hw/ip/otp_ctrl/data:otp_json_creator_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_owner_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_alert_digest_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_hw_cfg", |
| ":otp_json_shutdown_watchdog_{}_{}".format( |
| t["lc_state"], |
| t["bite_threshold"], |
| ), |
| ], |
| ) |
| for t in SHUTDOWN_WATCHDOG_CASES |
| ] |
| |
| [ |
| bitstream_splice( |
| name = "bitstream_shutdown_watchdog_{}_{}".format( |
| t["lc_state"], |
| t["bite_threshold"], |
| ), |
| src = "//hw/bitstream:rom", |
| data = ":otp_img_shutdown_watchdog_{}_{}".format( |
| t["lc_state"], |
| t["bite_threshold"], |
| ), |
| meminfo = "//hw/bitstream:otp_mmi", |
| tags = ["vivado"], |
| update_usr_access = True, |
| visibility = ["//visibility:private"], |
| ) |
| for t in SHUTDOWN_WATCHDOG_CASES |
| ] |
| |
| [ |
| opentitan_functest( |
| name = "shutdown_watchdog_{}_{}".format( |
| t["lc_state"], |
| t["bite_threshold"], |
| ), |
| srcs = ["hang_test.c"], |
| cw310 = cw310_params( |
| bitstream = ":bitstream_shutdown_watchdog_{}_{}".format( |
| t["lc_state"], |
| t["bite_threshold"], |
| ), |
| exit_success = t["exit_success"], |
| tags = ["vivado"] + maybe_skip_in_ci(getattr( |
| CONST.LCV, |
| t["lc_state"].upper(), |
| )), |
| ), |
| local_defines = [ |
| "HANG_SECS=1", |
| ], |
| targets = ["cw310_rom"], |
| deps = [ |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| ], |
| ) |
| for t in SHUTDOWN_WATCHDOG_CASES |
| ] |
| |
| test_suite( |
| name = "rom_e2e_shutdown_watchdog", |
| tags = ["manual"], |
| tests = [ |
| "shutdown_watchdog_{}_{}".format( |
| t["lc_state"], |
| t["bite_threshold"], |
| ) |
| for t in SHUTDOWN_WATCHDOG_CASES |
| ], |
| ) |
| |
| [genrule( |
| name = "empty_test_slot_{}_corrupted_{}_bin_signed_{}".format(slot, device, key), |
| srcs = ["empty_test_slot_{}_{}_bin_signed_{}".format(slot, device, key)], |
| outs = ["empty_test_slot_{}_bad_signature_{}_bin_signed_{}".format(slot, device, key)], |
| cmd_bash = "cat $(SRCS) > $(OUTS) && dd if=/dev/zero of=$(OUTS) bs=4 seek=7 count=1 conv=notrunc status=none".format(slot), |
| ) for slot in SLOTS for device in ["fpga_cw310"] for key in ["test_key_0"]] |
| |
| BOOT_POLICY_VALID_CASES = [ |
| { |
| "desc": "good", |
| "suffix": "", |
| }, |
| { |
| "desc": "bad", |
| "suffix": "_corrupted", |
| }, |
| ] |
| |
| [ |
| opentitan_multislot_flash_binary( |
| name = "boot_policy_valid_img_a_{}_b_{}".format( |
| a["desc"], |
| b["desc"], |
| ), |
| srcs = { |
| ":empty_test_slot_a{}".format(a["suffix"]): { |
| "key": "test_key_0", |
| "offset": SLOTS["a"], |
| }, |
| ":empty_test_slot_b{}".format(b["suffix"]): { |
| "key": "test_key_0", |
| "offset": SLOTS["b"], |
| }, |
| }, |
| devices = ["fpga_cw310"], |
| ) |
| for a in BOOT_POLICY_VALID_CASES |
| for b in BOOT_POLICY_VALID_CASES |
| ] |
| |
| [ |
| otp_image( |
| name = "otp_img_boot_policy_valid_{}".format(lc_state.lower()), |
| src = "//hw/ip/otp_ctrl/data:otp_json_{}".format(lc_state.lower()), |
| overlays = [ |
| "//hw/ip/otp_ctrl/data:otp_json_creator_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_owner_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_alert_digest_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_hw_cfg", |
| ], |
| ) |
| for lc_state in structs.to_dict(CONST.LCV) |
| ] |
| |
| # Splice OTP images into bitstreams |
| [ |
| bitstream_splice( |
| name = "bitstream_boot_policy_valid_{}".format(lc_state.lower()), |
| src = "//hw/bitstream:rom", |
| data = ":otp_img_boot_policy_valid_{}".format(lc_state.lower()), |
| meminfo = "//hw/bitstream:otp_mmi", |
| tags = ["vivado"], |
| update_usr_access = True, |
| ) |
| for lc_state in structs.to_dict(CONST.LCV) |
| ] |
| |
| [ |
| opentitan_functest( |
| name = "boot_policy_valid_{}_a_{}_b_{}".format( |
| lc_state.lower(), |
| a["desc"], |
| b["desc"], |
| ), |
| cw310 = cw310_params( |
| bitstream = "bitstream_boot_policy_valid_{}".format(lc_state.lower()), |
| exit_failure = MSG_PASS if a["desc"] == b["desc"] and a["desc"] == "bad" else DEFAULT_TEST_FAILURE_MSG, |
| exit_success = MSG_TEMPLATE_BFV.format(hex(CONST.BFV.SIGVERIFY.BAD_ENCODED_MSG)) if a["desc"] == b["desc"] and a["desc"] == "bad" else MSG_PASS, |
| tags = ["vivado"] + maybe_skip_in_ci(lc_state_val), |
| ), |
| key = "multislot", |
| ot_flash_binary = ":boot_policy_valid_img_a_{}_b_{}".format( |
| a["desc"], |
| b["desc"], |
| ), |
| targets = ["cw310_rom"], |
| ) |
| for lc_state, lc_state_val in structs.to_dict(CONST.LCV).items() |
| for a in BOOT_POLICY_VALID_CASES |
| for b in BOOT_POLICY_VALID_CASES |
| ] |
| |
| test_suite( |
| name = "rom_e2e_boot_policy_valid", |
| tags = ["manual"], |
| tests = [ |
| "boot_policy_valid_{}_a_{}_b_{}".format( |
| lc_state.lower(), |
| a["desc"], |
| b["desc"], |
| ) |
| for lc_state in structs.to_dict(CONST.LCV) |
| for a in BOOT_POLICY_VALID_CASES |
| for b in BOOT_POLICY_VALID_CASES |
| ], |
| ) |
| |
| # Names of OTP configs shared by tests that require execution to be disabled. |
| OTP_CFGS_EXEC_DISABLED = [ |
| "test_unlocked0", |
| "dev", |
| "rma", |
| ] |
| |
| # Apply an overlay that disables ROM execution on top of the base OTP configs |
| # derived from `OTP_CFGS_EXEC_DISABLED`. |
| [ |
| otp_image( |
| name = "img_{}_exec_disabled".format(otp_name), |
| src = "//hw/ip/otp_ctrl/data:otp_json_" + otp_name, |
| overlays = [ |
| "//hw/ip/otp_ctrl/data:otp_json_creator_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_owner_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_alert_digest_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_hw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_exec_disabled", |
| ], |
| visibility = ["//visibility:private"], |
| ) |
| for otp_name in OTP_CFGS_EXEC_DISABLED |
| ] |
| |
| # Splice each execution-disabled OTP image into the ROM bitstream. |
| [ |
| bitstream_splice( |
| name = "rom_otp_{}_exec_disabled".format(otp_name), |
| src = "//hw/bitstream:rom", |
| data = "img_{}_exec_disabled".format(otp_name), |
| meminfo = "//hw/bitstream:otp_mmi", |
| tags = [ |
| "manual", |
| "vivado", |
| ], |
| update_usr_access = True, |
| visibility = ["//visibility:private"], |
| ) |
| for otp_name in OTP_CFGS_EXEC_DISABLED |
| ] |
| |
| SRAM_JTAG_INJECTION_GDB_SCRIPT = """ |
| target extended-remote :3333 |
| |
| echo :::: Send OpenOCD the 'reset halt' command.\\n |
| monitor reset halt |
| |
| |
| # Mitigate flakiness from the watchdog timer. Prior to connecting |
| # OpenOCD and GDB, the device is executing normally. The ROM has |
| # probably already started up and configured the watchdog timer. This is |
| # a problem; if the timer fires while we're connected, the interrupt |
| # will steal control away from the debugger and cause this test to fail. |
| # Thus, we need to disable the watchdog timer as quickly as possible to |
| # minimize the chances of it firing. |
| # |
| # The proper solution would be to disable ROM execution by provisioning |
| # with an OTP image that has CREATOR_SW_CFG_ROM_EXEC_EN set to zero. |
| # |
| # Initialize and disable the watchdog timer per aon_timer docs [1]. The |
| # hardcoded addresses were computed by adding REG_OFFSET values from |
| # //hw/ip/aon_timer/data:aon_timer_regs to the base address |
| # TOP_EARLGREY_AON_TIMER_AON_BASE_ADDR. |
| # |
| # [1]: https://docs.opentitan.org/hw/ip/aon_timer/doc/#initialization |
| |
| echo :::: Disable the watchdog timer.\\n |
| monitor mdw 0x40470014 |
| monitor mww 0x40470014 0 |
| echo :::: Reset WDOG_COUNT.\\n |
| monitor mdw 0x40470020 |
| monitor mww 0x40470020 0 |
| echo :::: Clear the interrupt (if any) by writing to INTR_STATE.\\n |
| monitor mdw 0x40470024 |
| monitor mww 0x40470024 0 |
| |
| |
| # Before transferring the SRAM program to the device, we must configure |
| # the PMP unit to enable writing to and executing from SRAM. Due to |
| # implementation details of OpenTitan's hardware debug module, we cannot |
| # set pmpcfg* registers to arbitrary values [1]. However, we can safely |
| # modify unused PMP configuration registers. Thankfully, pmp0cfg (the |
| # lowest byte of CSR pmpcfg0) is unused and has the highest priority. |
| # |
| # In more detail, the problem is that our debug module implements the |
| # "Access Register" abstract command by assembling instructions in the |
| # program buffer and then executing the buffer. If one of those |
| # instructions clobbers the PMP configuration register that allows |
| # execution from the program buffer, subsequent instruction fetches will |
| # generate exceptions. |
| # |
| # Debug module concepts like abstract commands and the program buffer |
| # buffer are defined in "RISC-V External Debug Support Version 0.13.2" |
| # [2]. OpenTitan's (vendored-in) implementation lives in |
| # //hw/vendor/pulp_riscv_dbg. |
| # |
| # [1]: https://github.com/lowRISC/opentitan/issues/14978 |
| # [2]: https://riscv.org/wp-content/uploads/2019/03/riscv-debug-release.pdf |
| |
| echo :::: Configure the PMP unit.\\n |
| monitor reg pmpcfg0 |
| # Write "L NAPOT X W R" to pmp{0,1,2,3}cfg in pmpcfg0. Crucially, this |
| # value is no less permissive than whatever the current value is. |
| monitor reg pmpcfg0 0x9f9f9f9f |
| monitor reg pmpaddr0 0xffffffff |
| |
| echo :::: Value of CREATOR_SW_CFG_ROM_EXEC_EN.\\n |
| monitor mdw 0x40131108 |
| |
| echo :::: Load the SRAM program onto the device and check integrity.\\n |
| file sram_program.elf |
| load sram_program.elf |
| compare-sections |
| |
| echo :::: Update registers before calling functions.\\n |
| set $sp = _stack_end |
| set $gp = __global_pointer$ |
| info registers |
| |
| # When testing SRAM execution, we want to be sure the code is running |
| # out of SRAM and not the instruction cache. |
| echo :::: Invalidate the icache.\\n |
| print icache_invalidate() |
| |
| echo :::: Call sram_main().\\n |
| print sram_main() |
| |
| echo :::: Done.\\n |
| """ |
| |
| [ |
| opentitan_gdb_fpga_cw310_test( |
| name = "sram_program_fpga_cw310_test_otp_" + otp_name, |
| timeout = "short", |
| exit_success_pattern = "sram_program\\.c:\\d+\\] PC: 0x100020e0, SRAM: \\[0x10000000, 0x10020000\\)", |
| gdb_script = SRAM_JTAG_INJECTION_GDB_SCRIPT, |
| gdb_script_symlinks = { |
| "//sw/device/examples/sram_program:sram_program_fpga_cw310.elf": "sram_program.elf", |
| }, |
| rom_bitstream = ":rom_otp_{}_exec_disabled".format(otp_name), |
| rom_kind = "Rom", |
| tags = [ |
| "cw310", |
| "exclusive", |
| "vivado", |
| ], |
| ) |
| for otp_name in OTP_CFGS_EXEC_DISABLED |
| ] |
| |
| test_suite( |
| name = "rom_e2e_jtag_inject_tests", |
| tags = [ |
| "cw310", |
| "vivado", |
| ], |
| tests = ["sram_program_fpga_cw310_test_otp_" + otp_name for otp_name in OTP_CFGS_EXEC_DISABLED], |
| ) |
| |
| [ |
| opentitan_gdb_fpga_cw310_test( |
| name = "asm_interrupt_handler_fpga_cw310_test_otp_" + otp_name, |
| timeout = "short", |
| gdb_script = """ |
| target extended-remote :3333 |
| |
| echo :::: Send OpenOCD the 'reset halt' command.\\n |
| monitor reset halt |
| |
| echo :::: Load ROM symbols into GDB.\\n |
| file rom.elf |
| |
| echo :::: Set breakpoint on exception handler.\\n |
| break _asm_exception_handler |
| |
| echo :::: Attempt to trigger an exception.\\n |
| set $pc = 0 |
| continue |
| printf ":::: PC=%p. Expected PC=%p.\\n", $pc, _asm_exception_handler |
| |
| if $pc == _asm_exception_handler |
| echo :::: Test passed!\\n |
| quit 0 |
| else |
| echo :::: Test failed!\\n |
| quit 1 |
| end |
| """, |
| gdb_script_symlinks = { |
| "//sw/device/silicon_creator/rom:rom_fpga_cw310.elf": "rom.elf", |
| }, |
| rom_bitstream = ":rom_otp_{}_exec_disabled".format(otp_name), |
| rom_kind = "Rom", |
| tags = [ |
| "cw310", |
| "exclusive", |
| "vivado", |
| ], |
| ) |
| for otp_name in OTP_CFGS_EXEC_DISABLED |
| ] |
| |
| test_suite( |
| name = "rom_e2e_asm_interrupt_handler", |
| tags = [ |
| "cw310", |
| "vivado", |
| ], |
| tests = ["asm_interrupt_handler_fpga_cw310_test_otp_" + otp_name for otp_name in OTP_CFGS_EXEC_DISABLED], |
| ) |
| |
| # Dict that also includes an invalid redaction value for test purposes. |
| REDACT = structs.to_dict(CONST.SHUTDOWN.REDACT) |
| |
| # Ensure that the watchdog restarts the ROM even when the bite threshold has |
| # been artificially inflated. |
| [ |
| opentitan_gdb_fpga_cw310_test( |
| name = "rom_e2e_asm_watchdog_bark_fpga_cw310_test_otp_" + otp_name, |
| timeout = "short", |
| gdb_script = """ |
| target extended-remote :3333 |
| |
| echo :::: Send OpenOCD the 'reset halt' command.\\n |
| monitor reset halt |
| |
| echo :::: Load ROM symbols into GDB.\\n |
| file rom.elf |
| |
| echo :::: Run until we check whether ROM execution is enabled.\\n |
| break kRomStartBootMaybeHalt |
| continue |
| |
| printf ":::: PC=%p. Expected PC=%p.\\n", $pc, kRomStartBootMaybeHalt |
| if $pc != kRomStartBootMaybeHalt |
| quit 42 |
| end |
| |
| echo :::: Pretend execution is enabled.\\n |
| set $pc = kRomStartBootExecEn |
| |
| break kRomStartStoreT1ToBiteThold |
| continue |
| printf ":::: PC=%p. Expected PC=%p.\\n", $pc, kRomStartStoreT1ToBiteThold |
| if $pc != kRomStartStoreT1ToBiteThold |
| quit 43 |
| end |
| |
| # Set the bite threshold to UINT32_MAX. We want to exercise that the |
| # bark causes control to reach the interrupt handler. |
| set $t1 = 0xffffffff |
| |
| echo :::: Run until right after configuring the watchdog timer.\\n |
| break kRomStartWatchdogEnabled |
| continue |
| |
| printf ":::: PC=%p. Expected PC=%p.\\n", $pc, kRomStartWatchdogEnabled |
| if $pc != kRomStartWatchdogEnabled |
| quit 44 |
| end |
| |
| echo :::: Set breakpoint on NMI handler.\\n |
| delete breakpoints |
| break _asm_exception_handler |
| |
| echo :::: Wait for interrupt.\\n |
| set $pc = kRomStartBootMaybeHalt |
| echo :::: Continue.\\n |
| continue |
| |
| printf ":::: PC=%p. Expected PC=%p.\\n", $pc, _asm_exception_handler |
| if $pc != _asm_exception_handler |
| quit 45 |
| end |
| """, |
| gdb_script_symlinks = { |
| "//sw/device/silicon_creator/rom:rom_fpga_cw310.elf": "rom.elf", |
| }, |
| rom_bitstream = ":rom_otp_{}_exec_disabled".format(otp_name), |
| rom_kind = "Rom", |
| tags = [ |
| "cw310", |
| "exclusive", |
| "vivado", |
| ], |
| ) |
| for otp_name in OTP_CFGS_EXEC_DISABLED |
| ] |
| |
| # Ensure that the watchdog's bite restarts the ROM. |
| [ |
| opentitan_gdb_fpga_cw310_test( |
| name = "rom_e2e_asm_watchdog_bite_fpga_cw310_test_otp_" + otp_name, |
| timeout = "short", |
| gdb_expect_output_sequence = [ |
| ":::: Wait for interrupt.", |
| "Hart 0 unexpectedly reset!", |
| ], |
| gdb_script = """ |
| target extended-remote :3333 |
| |
| echo :::: Send OpenOCD the 'reset halt' command.\\n |
| monitor reset halt |
| |
| echo :::: Load ROM symbols into GDB.\\n |
| file rom.elf |
| |
| echo :::: Run until we check whether ROM execution is enabled.\\n |
| break kRomStartBootMaybeHalt |
| continue |
| |
| printf ":::: PC=%p. Expected PC=%p.\\n", $pc, kRomStartBootMaybeHalt |
| if $pc != kRomStartBootMaybeHalt |
| quit 42 |
| end |
| |
| echo :::: Pretend execution is enabled.\\n |
| set $pc = kRomStartBootExecEn |
| |
| echo :::: Run until right after configuring the watchdog timer.\\n |
| break kRomStartWatchdogEnabled |
| continue |
| |
| printf ":::: PC=%p. Expected PC=%p.\\n", $pc, kRomStartWatchdogEnabled |
| if $pc != kRomStartWatchdogEnabled |
| quit 43 |
| end |
| |
| echo :::: Set breakpoint on NMI handler.\\n |
| delete breakpoints |
| break _asm_exception_handler |
| |
| echo :::: Wait for interrupt.\\n |
| set $pc = kRomStartBootMaybeHalt |
| echo :::: Continue.\\n |
| continue |
| |
| # Not reached. |
| quit 123 |
| """, |
| gdb_script_symlinks = { |
| "//sw/device/silicon_creator/rom:rom_fpga_cw310.elf": "rom.elf", |
| }, |
| rom_bitstream = ":rom_otp_{}_exec_disabled".format(otp_name), |
| rom_kind = "Rom", |
| tags = [ |
| "cw310", |
| "exclusive", |
| "vivado", |
| ], |
| ) |
| for otp_name in OTP_CFGS_EXEC_DISABLED |
| ] |
| |
| test_suite( |
| name = "rom_e2e_asm_watchdog", |
| tags = [ |
| "cw310", |
| "vivado", |
| ], |
| tests = [ |
| "rom_e2e_asm_watchdog_" + type + "_fpga_cw310_test_otp_" + otp_name |
| for otp_name in OTP_CFGS_EXEC_DISABLED |
| for type in ("bite", "bark") |
| ], |
| ) |
| |
| # Shutdown Redact Test |
| |
| REDACT.update({"INVALID": 0x0}) |
| |
| [ |
| otp_json( |
| name = "otp_json_{}_overlay".format(k.lower()), |
| partitions = [ |
| otp_partition( |
| name = "OWNER_SW_CFG", |
| items = { |
| "OWNER_SW_CFG_ROM_ERROR_REPORTING": "0x{}".format(hex(v)), |
| }, |
| ), |
| ], |
| ) |
| for k, v in REDACT.items() |
| ] |
| |
| [ |
| otp_image( |
| name = "img_{}_{}".format( |
| lc_state.lower(), |
| redact.lower(), |
| ), |
| src = "//hw/ip/otp_ctrl/data:otp_json_{}".format(lc_state.lower()), |
| overlays = [ |
| "//hw/ip/otp_ctrl/data:otp_json_creator_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_owner_sw_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_alert_digest_cfg", |
| "//hw/ip/otp_ctrl/data:otp_json_hw_cfg", |
| ":otp_json_{}_overlay".format(redact.lower()), |
| ], |
| visibility = ["//visibility:private"], |
| ) |
| for lc_state in structs.to_dict(CONST.LCV) |
| for redact in REDACT |
| ] |
| |
| [ |
| bitstream_splice( |
| name = "bitstream_{}_{}".format( |
| lc_state.lower(), |
| redact.lower(), |
| ), |
| src = "//hw/bitstream:rom", |
| data = ":img_{}_{}".format( |
| lc_state.lower(), |
| redact.lower(), |
| ), |
| meminfo = "//hw/bitstream:otp_mmi", |
| tags = ["vivado"], |
| update_usr_access = True, |
| visibility = ["//visibility:private"], |
| ) |
| for lc_state in structs.to_dict(CONST.LCV) |
| for redact in REDACT |
| ] |
| |
| [ |
| opentitan_functest( |
| name = "e2e_shutdown_redact_{}_{}".format( |
| lc_state.lower(), |
| redact.lower(), |
| ), |
| srcs = ["empty_test.c"], |
| cw310 = cw310_params( |
| bitstream = "bitstream_{}_{}".format( |
| lc_state.lower(), |
| redact.lower(), |
| ), |
| exit_failure = MSG_PASS, |
| exit_success = MSG_TEMPLATE_BFV.format(hex(error_redact( |
| CONST.BFV.BOOT_POLICY.BAD_IDENTIFIER, |
| lc_state_val, |
| redact_val, |
| ))), |
| tags = ["vivado"] + maybe_skip_in_ci(lc_state_val), |
| ), |
| signed = False, |
| targets = ["cw310_rom"], |
| deps = [ |
| "//hw/ip/otp_ctrl/data:otp_ctrl_regs", |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| "//sw/device/silicon_creator/lib/drivers:lifecycle", |
| "//sw/device/silicon_creator/lib/drivers:otp", |
| ], |
| ) |
| for lc_state, lc_state_val in structs.to_dict(CONST.LCV).items() |
| for redact, redact_val in REDACT.items() |
| ] |
| |
| test_suite( |
| name = "rom_e2e_shutdown_redact", |
| tags = ["manual"], |
| tests = ["e2e_shutdown_redact_{}_{}".format( |
| lc_state.lower(), |
| redact.lower(), |
| ) for lc_state in structs.to_dict(CONST.LCV) for redact in REDACT], |
| ) |
| |
| [opentitan_multislot_flash_binary( |
| name = "boot_policy_valid_img_a_{}_b_{}".format( |
| "empty" if offset == "0x0" else "bad", |
| "empty" if offset != "0x0" else "bad", |
| ), |
| srcs = { |
| ":empty_test_slot_{}_corrupted".format(slot): { |
| "key": "test_key_0", |
| "offset": offset, |
| }, |
| }, |
| devices = ["fpga_cw310"], |
| ) for slot, offset in SLOTS.items()] |
| |
| SIGVERIFY_BAD_CASES = [ |
| { |
| "desc": "bad", |
| "suffix": "_corrupted", |
| }, |
| { |
| "desc": "empty", |
| "suffix": "_empty", |
| }, |
| ] |
| |
| [ |
| opentitan_functest( |
| name = "sigverify_always_a_{}_b_{}".format( |
| a["desc"], |
| b["desc"], |
| ), |
| cw310 = cw310_params( |
| exit_failure = MSG_PASS, |
| exit_success = DEFAULT_TEST_FAILURE_MSG, |
| ), |
| key = "multislot", |
| ot_flash_binary = ":boot_policy_valid_img_a_{}_b_{}".format( |
| a["desc"], |
| b["desc"] if a != b and b != "empty" else "bad", |
| ), |
| targets = ["cw310_rom"], |
| ) |
| for a in SIGVERIFY_BAD_CASES |
| for b in SIGVERIFY_BAD_CASES |
| ] |
| |
| test_suite( |
| name = "sigverify_always", |
| tests = [ |
| "sigverify_always_a_{}_b_{}".format( |
| a["desc"], |
| b["desc"], |
| ) |
| for a in SIGVERIFY_BAD_CASES |
| for b in SIGVERIFY_BAD_CASES |
| ], |
| ) |