| # 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", |
| "DEFAULT_TEST_SUCCESS_MSG", |
| "cw310_params", |
| "dv_params", |
| "opentitan_functest", |
| "verilator_params", |
| ) |
| load( |
| "//rules:opentitan.bzl", |
| "opentitan_flash_binary", |
| "opentitan_multislot_flash_binary", |
| ) |
| load( |
| "//rules:manifest.bzl", |
| "CONST", |
| "manifest", |
| ) |
| load("//rules:opentitan_gdb_test.bzl", "opentitan_gdb_fpga_cw310_test") |
| load("//rules:otp.bzl", "otp_image", "otp_json", "otp_partition") |
| load("//rules:splice.bzl", "bitstream_splice") |
| |
| package(default_visibility = ["//visibility:public"]) |
| |
| MSG_BOOT_FAULT = "BFV:" |
| |
| _BFV_TEMPLATE = "{}{}(?s:.*){}{}".format(MSG_BOOT_FAULT, "{0}", MSG_BOOT_FAULT, "{0}") |
| |
| MSG_STARTING_ROM_EXT = "Starting ROM_EXT" |
| |
| MSG_INSTRUCTION_ACCESS_FAULT = _BFV_TEMPLATE.format("01495202") |
| |
| MSG_ILLEGAL_INSTRUCTION_FAULT = _BFV_TEMPLATE.format("02495202") |
| |
| MSG_STORE_ACCESS_FAULT = _BFV_TEMPLATE.format("07495202") |
| |
| MSG_PASS = "PASS!" |
| |
| MSG_SIGVERIFY_BAD_ENCODED_MSG = _BFV_TEMPLATE.format("01535603") |
| |
| MSG_SIGVERIFY_BAD_KEY = _BFV_TEMPLATE.format("02535603") |
| |
| MSG_BOOT_POLICY_BAD_IDENTIFIER = _BFV_TEMPLATE.format("0142500d") |
| |
| MSG_BOOT_POLICY_BAD_LENGTH = _BFV_TEMPLATE.format("0242500d") |
| |
| MSG_BOOT_POLICY_ROLLBACK = _BFV_TEMPLATE.format("0342500d") |
| |
| MSG_MANIFEST_BAD_ENTRY_POINT = _BFV_TEMPLATE.format("014d410d") |
| |
| MSG_MANIFEST_BAD_CODE_REGION = _BFV_TEMPLATE.format("024d410d") |
| |
| 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 = [ |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| "@//sw/device/lib/testing/test_framework:ottf_ld_silicon_creator_slot_{}".format(slot), |
| ], |
| ) for slot in SLOTS] |
| |
| 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_INSTRUCTION_ACCESS_FAULT, |
| ), |
| 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_INSTRUCTION_ACCESS_FAULT, |
| 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 = "e2e_keymgr_init", |
| srcs = ["rom_e2e_keymgr_init_test.c"], |
| signed = True, |
| targets = [ |
| "cw310_rom", |
| "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", |
| ], |
| ) |
| |
| # 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_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})\"", |
| ], |
| ), |
| signed = True, |
| targets = ["cw310_rom"], |
| test_harness = "//sw/host/tests/rom/e2e_chip_specific_startup", |
| deps = [ |
| "//hw/top_earlgrey/sw/autogen:top_earlgrey", |
| "//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 = MSG_BOOT_FAULT, |
| 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 = MSG_BOOT_FAULT, |
| 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_STORE_ACCESS_FAULT, |
| ), |
| 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_STORE_ACCESS_FAULT, |
| ), |
| 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 = MSG_BOOT_FAULT, |
| 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 = MSG_BOOT_FAULT, |
| 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_ILLEGAL_INSTRUCTION_FAULT, |
| ), |
| ot_flash_binary = "//sw/device/silicon_creator/rom_ext:rom_ext_slot_a_bad_address_translation", |
| targets = ["cw310_rom"], |
| ) |
| |
| test_suite( |
| name = "address_translation", |
| 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_SIGVERIFY_BAD_KEY, |
| ), |
| key = "unauthorized_0", |
| ot_flash_binary = ":empty_test_slot_a", |
| targets = ["cw310_rom"], |
| ) |
| |
| MSG_SHUTDOWN = { |
| "test": "BFV:0142500d\r\nLCV:02108421\r\n", |
| "dev": "BFV:0142500d\r\nLCV:21084210\r\n", |
| "prod": "BFV:0142500d\r\nLCV:2318c631\r\n", |
| "prod_end": "BFV:0142500d\r\nLCV:25294a52\r\n", |
| "rma": "BFV:0142500d\r\nLCV:2739ce73\r\n", |
| } |
| |
| LC_STATES = ["rma"] |
| |
| manifest({ |
| "name": "manifest_bad_identifier", |
| "address_translation": CONST.FALSE, |
| "identifier": 0, |
| }) |
| |
| # TODO(#14270): Add remaining lifecycle states. |
| [opentitan_functest( |
| name = "shutdown_output_{}".format(lc_state), |
| cw310 = cw310_params( |
| bitstream = "@//hw/bitstream:rom", |
| exit_failure = MSG_PASS, |
| exit_success = MSG_SHUTDOWN[lc_state], |
| ), |
| manifest = ":manifest_bad_identifier", |
| ot_flash_binary = ":empty_test_slot_a", |
| signed = False, |
| targets = ["cw310_rom"], |
| ) for lc_state in LC_STATES] |
| |
| test_suite( |
| name = "shutdown_output", |
| tests = ["shutdown_output_{}".format(lc_state) for lc_state in LC_STATES], |
| ) |
| |
| SEC_VERS = [ |
| 0, |
| 1, |
| 2, |
| ] |
| |
| [manifest({ |
| "name": "manifest_sec_ver_{}".format(sec_ver), |
| "address_translation": CONST.FALSE, |
| "identifier": CONST.ROM_EXT, |
| "security_version": 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 = [ |
| 'EMPTY_TEST_MSG=\\"slot=%p,\\ security_version=%01d\\",manifest_def_get(),manifest_def_get()->security_version', |
| ], |
| manifest = ":manifest_sec_ver_{}".format(sec_ver), |
| signed = True, |
| deps = [ |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| "@//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", |
| }, |
| { |
| "a": 0, |
| "b": 1, |
| "exit_success": "slot=0x20080000, security_version=1", |
| }, |
| { |
| "a": 1, |
| "b": 0, |
| "exit_success": "slot=0x20000000, security_version=1", |
| }, |
| { |
| "a": 1, |
| "b": 1, |
| "exit_success": "slot=0x20000000, security_version=1", |
| }, |
| ] |
| |
| [opentitan_functest( |
| name = "boot_policy_newer_a_{}_b_{}".format( |
| t["a"], |
| t["b"], |
| ), |
| cw310 = cw310_params( |
| exit_success = t["exit_success"], |
| ), |
| key = "multislot", |
| ot_flash_binary = ":sec_ver_{}_{}_image".format( |
| t["a"], |
| t["b"], |
| ), |
| targets = ["cw310_rom"], |
| ) for t in BOOT_POLICY_NEWER_CASES] |
| |
| test_suite( |
| name = "boot_policy_newer", |
| tests = ["boot_policy_newer_a_{}_b_{}".format( |
| t["a"], |
| t["b"], |
| ) for t in BOOT_POLICY_NEWER_CASES], |
| ) |
| |
| BOOT_POLICY_ROLLBACK_CASES = [ |
| # TODO(#14473): Enable after OTP splicing is ready. |
| # { |
| # "a": 0, |
| # "b": 0, |
| # "exit_success": MSG_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", |
| }, |
| ] |
| |
| [opentitan_functest( |
| name = "boot_policy_rollback_a_{}_b_{}".format( |
| t["a"], |
| t["b"], |
| ), |
| cw310 = cw310_params( |
| exit_success = t["exit_success"], |
| ), |
| key = "multislot", |
| ot_flash_binary = ":sec_ver_{}_{}_image".format( |
| t["a"], |
| t["b"], |
| ), |
| targets = ["cw310_rom"], |
| ) for t in BOOT_POLICY_ROLLBACK_CASES] |
| |
| test_suite( |
| name = "boot_policy_rollback", |
| tests = ["boot_policy_rollback_a_{}_b_{}".format( |
| t["a"], |
| t["b"], |
| ) for t in BOOT_POLICY_ROLLBACK_CASES], |
| ) |
| |
| SIGVERIFY_MOD_EXP_CASES = [ |
| { |
| "name": "sw", |
| "use_sw_rsa_verify": CONST.TRUE, |
| "exit_success": MSG_PASS, |
| }, |
| # TODO(#14481): Enable after OTP splicing is ready. |
| # TODO: Consider using a custom binary that prints the OTP item. |
| # { |
| # "name": "otbn", |
| # "use_sw_rsa_verify": CONST.FALSE, |
| # "exit_success": MSG_PASS, |
| # }, |
| # { |
| # "name": "invalid", |
| # "use_sw_rsa_verify": 0, |
| # "exit_success": MSG_ILLEGAL_INSTRUCTION_FAULT, |
| # }, |
| ] |
| |
| [opentitan_functest( |
| name = "sigverify_mod_exp_{}".format(t["name"]), |
| cw310 = cw310_params( |
| exit_success = t["exit_success"], |
| ), |
| ot_flash_binary = ":empty_test_slot_a", |
| targets = ["cw310_rom"], |
| ) for t in SIGVERIFY_MOD_EXP_CASES] |
| |
| test_suite( |
| name = "sigverify_mod_exp", |
| tests = ["sigverify_mod_exp_{}".format(t["name"]) for t in SIGVERIFY_MOD_EXP_CASES], |
| ) |
| |
| BOOT_POLICY_BAD_MANIFEST_CASES = [ |
| { |
| "name": "bad_identifier", |
| "manifest": { |
| "identifier": 0, |
| }, |
| "exit_success": MSG_BOOT_POLICY_BAD_IDENTIFIER, |
| }, |
| { |
| "name": "too_small", |
| "manifest": { |
| "identifier": CONST.ROM_EXT, |
| "length": CONST.ROM_EXT_SIZE_MIN - 1, |
| }, |
| "exit_success": MSG_BOOT_POLICY_BAD_LENGTH, |
| }, |
| { |
| "name": "too_large", |
| "manifest": { |
| "identifier": CONST.ROM_EXT, |
| "length": CONST.ROM_EXT_SIZE_MAX + 1, |
| }, |
| "exit_success": MSG_BOOT_POLICY_BAD_LENGTH, |
| }, |
| { |
| "name": "empty_code", |
| "manifest": { |
| # Note: `length` is filled automatically unless overriden here. |
| "identifier": CONST.ROM_EXT, |
| "code_start": CONST.MANIFEST_SIZE + 12, |
| "code_end": CONST.MANIFEST_SIZE + 12, |
| }, |
| "exit_success": MSG_MANIFEST_BAD_CODE_REGION, |
| }, |
| { |
| "name": "code_in_manifest", |
| "manifest": { |
| "identifier": CONST.ROM_EXT, |
| "code_start": CONST.MANIFEST_SIZE - 4, |
| "code_end": CONST.MANIFEST_SIZE + 12, |
| "entry_point": CONST.MANIFEST_SIZE + 8, |
| }, |
| "exit_success": MSG_MANIFEST_BAD_CODE_REGION, |
| }, |
| { |
| "name": "code_outside_image", |
| "manifest": { |
| "identifier": CONST.ROM_EXT, |
| "code_start": CONST.ROM_EXT_SIZE_MAX, |
| "code_end": CONST.MANIFEST_SIZE + 12, |
| "entry_point": CONST.MANIFEST_SIZE + 8, |
| }, |
| "exit_success": MSG_MANIFEST_BAD_CODE_REGION, |
| }, |
| { |
| "name": "code_start_unaligned", |
| "manifest": { |
| "identifier": CONST.ROM_EXT, |
| "code_start": CONST.MANIFEST_SIZE + 6, |
| "code_end": CONST.MANIFEST_SIZE + 12, |
| "entry_point": CONST.MANIFEST_SIZE + 8, |
| }, |
| "exit_success": MSG_MANIFEST_BAD_CODE_REGION, |
| }, |
| { |
| "name": "code_end_unaligned", |
| "manifest": { |
| "identifier": CONST.ROM_EXT, |
| "code_start": CONST.MANIFEST_SIZE + 8, |
| "code_end": CONST.MANIFEST_SIZE + 10, |
| "entry_point": CONST.MANIFEST_SIZE + 8, |
| }, |
| "exit_success": MSG_MANIFEST_BAD_CODE_REGION, |
| }, |
| { |
| "name": "entry_before_code_start", |
| "manifest": { |
| "identifier": CONST.ROM_EXT, |
| "code_start": CONST.MANIFEST_SIZE + 8, |
| "code_end": CONST.MANIFEST_SIZE + 12, |
| "entry_point": CONST.MANIFEST_SIZE + 4, |
| }, |
| "exit_success": MSG_MANIFEST_BAD_ENTRY_POINT, |
| }, |
| { |
| "name": "entry_at_code_end", |
| "manifest": { |
| "identifier": CONST.ROM_EXT, |
| "code_start": CONST.MANIFEST_SIZE + 8, |
| "code_end": CONST.MANIFEST_SIZE + 12, |
| "entry_point": CONST.MANIFEST_SIZE + 12, |
| }, |
| "exit_success": MSG_MANIFEST_BAD_ENTRY_POINT, |
| }, |
| { |
| "name": "entry_unaligned", |
| "manifest": { |
| "identifier": CONST.ROM_EXT, |
| "code_start": CONST.MANIFEST_SIZE + 8, |
| "code_end": CONST.MANIFEST_SIZE + 12, |
| "entry_point": CONST.MANIFEST_SIZE + 10, |
| }, |
| "exit_success": MSG_MANIFEST_BAD_ENTRY_POINT, |
| }, |
| # TODO(#14473): Enable after splicing the OTP with default boot_data |
| # enabled in PROD and CREATOR_SW_CFG_MIN_SEC_VER_ROM_EXT set to 1. |
| # { |
| # "name": "rollback", |
| # "manifest": { |
| # "identifier": CONST.ROM_EXT, |
| # "code_start": CONST.MANIFEST_SIZE + 8, |
| # "code_end": CONST.MANIFEST_SIZE + 12, |
| # "entry_point": CONST.MANIFEST_SIZE + 8, |
| # "security_version": 0, |
| # }, |
| # "exit_success": MSG_BOOT_POLICY_ROLLBACK, |
| # }, |
| ] |
| |
| [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 = [ |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| "@//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()] |
| |
| [opentitan_functest( |
| name = "boot_policy_bad_manifest_{}_{}".format( |
| t["name"], |
| slot, |
| ), |
| cw310 = cw310_params( |
| exit_success = t["exit_success"], |
| ), |
| key = "multislot", |
| ot_flash_binary = "boot_policy_bad_manifest_{}_{}_img".format( |
| t["name"], |
| slot, |
| ), |
| targets = [ |
| "cw310_rom", |
| "dv", |
| "verilator", |
| ], |
| ) for t in BOOT_POLICY_BAD_MANIFEST_CASES for slot in SLOTS] |
| |
| test_suite( |
| name = "boot_policy_bad_manifest", |
| tests = ["boot_policy_bad_manifest_{}_{}".format( |
| t["name"], |
| slot, |
| ) for t in BOOT_POLICY_BAD_MANIFEST_CASES for slot in SLOTS], |
| ) |
| |
| opentitan_functest( |
| name = "shutdown_watchdog", |
| srcs = ["hang_test.c"], |
| cw310 = cw310_params( |
| exit_success = "Returning after 5 seconds", |
| ), |
| local_defines = [ |
| "HANG_SECS=5", |
| ], |
| targets = ["cw310_rom"], |
| deps = [ |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| ], |
| ) |
| |
| [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 |
| ] |
| |
| [ |
| opentitan_functest( |
| name = "boot_policy_valid_a_{}_b_{}".format( |
| a["desc"], |
| b["desc"], |
| ), |
| cw310 = cw310_params( |
| exit_failure = MSG_PASS if a["desc"] == b["desc"] and a["desc"] == "bad" else DEFAULT_TEST_FAILURE_MSG, |
| exit_success = MSG_SIGVERIFY_BAD_ENCODED_MSG if a["desc"] == b["desc"] and a["desc"] == "bad" else MSG_PASS, |
| ), |
| key = "multislot", |
| ot_flash_binary = ":boot_policy_valid_img_a_{}_b_{}".format( |
| a["desc"], |
| b["desc"], |
| ), |
| targets = ["cw310_rom"], |
| ) |
| for a in BOOT_POLICY_VALID_CASES |
| for b in BOOT_POLICY_VALID_CASES |
| ] |
| |
| test_suite( |
| name = "boot_policy_valid", |
| tests = [ |
| "boot_policy_valid_a_{}_b_{}".format( |
| a["desc"], |
| b["desc"], |
| ) |
| 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_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", |
| "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", |
| "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], |
| ) |
| |
| # Shutdown Redact Test |
| |
| # Generate special OTP images |
| # For DEV, PROD, and PROD_END, cycle through ROM_ERROR_REPORTING OTP item |
| |
| LC_STATES = [ |
| "test_unlocked0", |
| "rma", |
| "dev", |
| "prod", |
| "prod_end", |
| ] |
| |
| # The LC states in which redaction is enabled. In all other states, there |
| # should be no redaction. |
| REDACTION_LC_STATES = [ |
| "dev", |
| "prod", |
| "prod_end", |
| ] |
| |
| ERROR_REDACT_VALUES = { |
| "none": "0xe2290aa5", |
| "error": "0x3367d3d4", |
| "module": "0x1e791123", |
| "all": "0x48eb4bd9", |
| } |
| |
| BFV_VALS = { |
| "none": "0142500d", |
| "error": "0042500d", |
| "module": "0000000d", |
| "all": "ffffffff", |
| } |
| |
| overlays = [ |
| ( |
| er_val, |
| otp_json( |
| name = "otp_json_{}_overlay".format(er_val), |
| partitions = [ |
| otp_partition( |
| name = "OWNER_SW_CFG", |
| items = {"OWNER_SW_CFG_ROM_ERROR_REPORTING": ERROR_REDACT_VALUES[er_val]}, |
| ), |
| ], |
| ), |
| ) |
| for er_val in ERROR_REDACT_VALUES.keys() |
| ] |
| |
| otp_imgs = [ |
| otp_image( |
| name = "img_{}_{}".format(lc_state, er_val), |
| src = "//hw/ip/otp_ctrl/data:otp_json_{}".format(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_hw_cfg", |
| ":otp_json_{}_overlay".format(er_val), |
| ], |
| visibility = ["//visibility:private"], |
| ) |
| for lc_state in LC_STATES |
| for er_val in ERROR_REDACT_VALUES.keys() |
| ] |
| |
| # Splice OTP images into bitstreams |
| [ |
| bitstream_splice( |
| name = "bitstream_{}_{}".format(lc_state, er_val), |
| src = "//hw/bitstream:rom", |
| data = ":img_{}_{}".format(lc_state, er_val), |
| meminfo = "//hw/bitstream:otp_mmi", |
| tags = [ |
| "manual", |
| "vivado", |
| ], |
| update_usr_access = True, |
| visibility = ["//visibility:private"], |
| ) |
| for lc_state in LC_STATES |
| for er_val in ERROR_REDACT_VALUES.keys() |
| ] |
| |
| # Assemble the test cases: |
| # (lc_state, er_val, bitstream_target, expected BFV) |
| test_cases = [ |
| ( |
| lc_state, |
| er_val, |
| ":bitstream_{}_{}".format(lc_state, er_val), |
| BFV_VALS[er_val if lc_state in REDACTION_LC_STATES else "none"], |
| ) |
| for lc_state in LC_STATES |
| for er_val in ERROR_REDACT_VALUES.keys() |
| ] |
| |
| [opentitan_functest( |
| name = "e2e_shutdown_redact_{}_{}".format(lc, er), |
| srcs = ["empty_test.c"], |
| cw310 = cw310_params( |
| bitstream = bitstream_target, |
| exit_failure = MSG_PASS, |
| exit_success = MSG_BOOT_FAULT + bfv_val, |
| tags = ["vivado"], |
| ), |
| signed = False, |
| targets = ["cw310_rom"], |
| deps = [ |
| "//sw/device/lib/testing/test_framework:ottf_main", |
| ], |
| ) for lc, er, bitstream_target, bfv_val in test_cases] |
| |
| test_suite( |
| name = "rom_e2e_shutdown_error_redact", |
| tags = ["vivado"], |
| tests = ["e2e_shutdown_redact_{}_{}".format(lc, er) for lc, er, _, _ in test_cases], |
| ) |