diff --git a/.github/workflows/build_test.yaml b/.github/workflows/build_test.yaml index 6ed630d8b145..0c23be068b17 100644 --- a/.github/workflows/build_test.yaml +++ b/.github/workflows/build_test.yaml @@ -76,10 +76,26 @@ jobs: sudo apt-get install -y clang-format-18 - name: Check out QEMU uses: actions/checkout@v4 - - name: Check execution + - name: Check C code format run: | scripts/opentitan/ot-format.sh --ci -i + lint-python: + runs-on: ubuntu-latest + steps: + - name: Install tools + run: | + sudo apt-get update && + sudo apt-get install -y python3-pip + # ubuntu "latest" is too old to require --break-system-packages ... + pip3 install pylint + - name: Check out QEMU + uses: actions/checkout@v4 + - name: Lint Python code + run: | + pylint --rcfile scripts/opentitan/.pylintrc -d 'duplicate-code' -d 'fixme' \ + scripts/opentitan/*.py python/qemu/jtag python/qemu/ot + lint-clang: runs-on: ubuntu-latest needs: build-clang diff --git a/docs/opentitan/jtagmbx.md b/docs/opentitan/jtagmbx.md index 782cb099e280..128adccf878a 100644 --- a/docs/opentitan/jtagmbx.md +++ b/docs/opentitan/jtagmbx.md @@ -36,7 +36,7 @@ instantiated and listens for incoming connection on TCP port 3335. OpenTitan implementation provides JTAG/DTM/DMI/Mailbox stack available as Python modules: -* jtag/tap module is available from `scripts/jtag` directory +* jtag/tap module is available from `python/qemu/jtag` directory * dtm/dmi and jtag mailbox modules are available from `scripts/opentitan` directory Python snippet to create a communication channel with the VM JTAG mailbox: diff --git a/docs/opentitan/lc_ctrl_dmi.md b/docs/opentitan/lc_ctrl_dmi.md index c55e9b44e508..df3d93e264c0 100644 --- a/docs/opentitan/lc_ctrl_dmi.md +++ b/docs/opentitan/lc_ctrl_dmi.md @@ -33,7 +33,7 @@ instantiated and listens for incoming connection on TCP port 3335. OpenTitan implementation provides JTAG/DTM/DMI/Mailbox stack available as Python modules: -* jtag/tap module is available from `scripts/jtag` directory +* jtag/tap module is available from `python/qemu/jtag` directory * dtm/dmi and jtag mailbox modules are available from `scripts/opentitan` directory Python snippet to create a communication channel with the VM JTAG mailbox: diff --git a/docs/opentitan/pymod.md b/docs/opentitan/pymod.md index 9c59066a6a3d..0b43de8ff639 100644 --- a/docs/opentitan/pymod.md +++ b/docs/opentitan/pymod.md @@ -4,8 +4,8 @@ The communication ports of the OpenTitan machines exposed through CharDev device to access the devices from the local host (or also from a remote host when the CharDev is created using a TCP socket). -* `scripts/jtag`: JTAG / TAP controller client, using the _Remote BitBang Protocol_ -* `scripts/opentitan/ot`: OpenTitan tools +* `python/qemu/jtag`: JTAG / TAP controller client, using the _Remote BitBang Protocol_ +* `python/qemu/ot`: OpenTitan tools * `dtm`: Debug Transport Module support, * `dm`: RISC-V Debug Module support, * `lc_ctrl`: [Life Cycle controller](lc_ctrl_dmi.md) over JTAG/DMI support, diff --git a/docs/opentitan/pyot.md b/docs/opentitan/pyot.md index a8f06c746be1..8bb81adb05a6 100644 --- a/docs/opentitan/pyot.md +++ b/docs/opentitan/pyot.md @@ -7,7 +7,7 @@ ````text usage: pyot.py [-h] [-D DELAY] [-i ICOUNT] [-L LOG_FILE] [-M VARIANT] [-N LOG] [-m MACHINE] [-Q OPTS] [-q QEMU] [-P VCP] [-p DEVICE] - [-t TRACE] [-S FIRST_SOC] [-s] [-U] [-b file] [-c JSON] [-e] + [-t TRACE] [-S FIRST_SOC] [-s] [-U] [-b file] [-c HJSON] [-e] [-f RAW] [-g file] [-K] [-l file] [-O RAW] [-o VMEM] [-r ELF] [-w CSV] [-x file] [-X] [-F TEST] [-k SECONDS] [-z] [-R] [-T FACTOR] [-Z] [-v] [-V] [-d] [--quiet] [--log-time] @@ -48,8 +48,8 @@ Virtual machine: Files: -b file, --boot file bootloader 0 file - -c JSON, --config JSON - path to configuration file + -c HJSON, --config HJSON + path to HJSON configuration file -e, --embedded-flash generate an embedded flash image file -f RAW, --flash RAW SPI flash image file -g file, --otcfg file @@ -92,8 +92,8 @@ Extras: This tool may be used in two ways, which can be combined: * From the command line, it is possible to run a QEMU test session for one application. -* Using a JSON configuration file, it is possible to run several QEMU test sessions for each - specified test in the configuration file. This mode is enabled when a JSON config file is +* Using a HJSON configuration file, it is possible to run several QEMU test sessions for each + specified test in the configuration file. This mode is enabled when a HJSON config file is specified. ### Virtual machine @@ -136,8 +136,8 @@ This tool may be used in two ways, which can be combined: * `-b` / ` --boot` specify a bootloader 0 file that can be added to the flash image file when a ROM extension file is specified with the `-x` option. This option is mutually exclusive with the `-f` option. -* `-c` / `--config` specify a (H)JSON configuration file, see the - [Configuration](#Configurationfile) section for details. +* `-c` / `--config` specify a HJSON configuration file, see the [Configuration](#Configurationfile) + section for details. * `-e` / `embedded-flash` generate an embedded flash image file, default is to provide ROM and application files as device options * `-f` / `--flash` specify a RAW image file that stores the embedded Flash content, which can be @@ -191,85 +191,8 @@ This tool may be used in two ways, which can be combined: ## Configuration file -### Legacy JSON syntax - -Sample config for running OpenTitan tests: -````json -{ - "aliases": { - "BASEDIR": "${OT_DIR}/bazel-out/k8-fastbuild/bin" - }, - - "testdir": "${BASEDIR}/sw", - - "default": { - "rom": "${BASEDIR}/sw/device/lib/testing/test_rom/test_rom_fpga_cw310.elf", - "otp": "${BASEDIR}/hw/ip/otp_ctrl/data/img_rma.24.vmem", - "timeout": 3, - "icount": 6 - }, - - "include" : [ - "**/*.fake_rsa_test_key_0.signed.bin" - ], - - "exclude" : [ - "alert_handler_*", - "ast_clk_out_*", - "clkmgr_off_*", - "i2c_*", - "manuf_cp_*", - "sensor_ctrl_*", - "spi_device_*", - "spi_passthru_*", - "usbdev_*" - ], - - "suffixes": [ - "_prog_fpga_cw310" - ], - - "tests": { - "aes_idle_test": { - "opts": ["-global", "ot-aes.fast-mode=false"] - }, - "alert_handler_lpg_reset_toggle_test" : { - "timeout": 10 - }, - "boot_data_functest": { - "icount": 1 - }, - "otbn_rsa_test": { - "timeout": 5 - }, - "mod_exp_otbn_functest_hardcoded": { - "icount": 0 - }, - "ecdsa_p256_functest": { - "timeout": 5 - }, - "ecdh_p256_functest": { - "timeout": 5 - }, - "entropy_src_csrng_test": { - "icount": "" - }, - "csrng_edn_concurrency_test": { - "timeout": 15 - }, - "csrng_smoketest": { - "timeout": 5 - } - } -} -```` - -### HJSON syntax - -HJSON is a more user-friendly syntax that JSON. If the `hjson` module is available on the platform, -this script uses it as a replacement for the system JSON module, hence supporting the improved -syntax for configuration. It is encouraged to install the dependency-less HJSON module using a -command such as `pip3 install hjson`. +This script accepts HJSON configuration file to define how to run a test session. +To install the dependency-less HJSON module, use a command such as `pip3 install hjson`. Sample config for running OpenTitan tests: ````hjson @@ -596,12 +519,12 @@ The script returns the error code of the most occurring error, or success (0) ## Examples -* The most typical usage requires a JSON configuration file and produces an output CSV file. `-vv`, +* The most typical usage requires a HJSON configuration file and produces an output CSV file. `-vv`, that is the information log level, should be enough to track execution without getting too many log messages. ````sh - ./scripts/opentitan/pyot.py -vv -c pyot.json -w pyot.csv + ./scripts/opentitan/pyot.py -vv -c pyot.hjson -w pyot.csv ```` Note that results can be live-tracked from another terminal using a command like the following: diff --git a/hw/jtag/tap_ctrl_rbb.c b/hw/jtag/tap_ctrl_rbb.c index 04c8a6eb90a7..2cd1d72c1e8c 100644 --- a/hw/jtag/tap_ctrl_rbb.c +++ b/hw/jtag/tap_ctrl_rbb.c @@ -29,35 +29,22 @@ */ #include "qemu/osdep.h" -#include "qemu/ctype.h" -#include "qemu/cutils.h" #include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/module.h" -#include "qemu/sockets.h" #include "qapi/error.h" #include "qom/object.h" #include "chardev/char-fe.h" #include "chardev/char.h" -#include "exec/gdbstub.h" -#include "exec/hwaddr.h" -#include "hw/boards.h" -#include "hw/cpu/cluster.h" #include "hw/jtag/tap_ctrl.h" #include "hw/jtag/tap_ctrl_rbb.h" #include "hw/qdev-properties-system.h" #include "hw/qdev-properties.h" #include "hw/resettable.h" -#include "monitor/monitor.h" -#include "semihosting/semihost.h" -#include "sysemu/hw_accel.h" -#include "sysemu/replay.h" #include "sysemu/runstate.h" #include "trace.h" -/* clang-format off */ - typedef enum { TEST_LOGIC_RESET, RUN_TEST_IDLE, @@ -78,10 +65,6 @@ typedef enum { _TAP_STATE_COUNT } TAPState; -#define TAP_CTRL_BYPASS_INST 0 - -/* clang-format on */ - typedef TapDataHandler *tap_ctrl_data_reg_extender_t(uint64_t value); typedef struct TapCtrlRbbState { @@ -135,6 +118,8 @@ typedef struct _TAPProcess { #define DEFAULT_JTAG_BITBANG_PORT "3335" #define MAX_PACKET_LENGTH 4096u +#define TAP_CTRL_BYPASS_INST 0u + /* * TAP controller state machine state/event matrix * @@ -173,13 +158,13 @@ static const char TAPFSM_NAMES[_TAP_STATE_COUNT][18U] = { static void tap_ctrl_rbb_idcode_capture(TapDataHandler *tdh); /* Common TAP instructions */ -static const TapDataHandler tap_ctrl_rbb_bypass = { +static const TapDataHandler TAP_CTRL_RBB_BYPASS = { .name = "bypass", .length = 1, .value = 0, }; -static const TapDataHandler tap_ctrl_rbb_idcode = { +static const TapDataHandler TAP_CTRL_RBB_IDCODE = { .name = "idcode", .length = 32, .capture = &tap_ctrl_rbb_idcode_capture, @@ -669,10 +654,10 @@ static void tap_ctrl_rbb_realize(DeviceState *dev, Error **errp) size_t irslots = 1u << tap->ir_length; tap_ctrl_rbb_register_handler(tap, TAP_CTRL_BYPASS_INST, - &tap_ctrl_rbb_bypass, true); - tap_ctrl_rbb_register_handler(tap, tap->idcode_inst, &tap_ctrl_rbb_idcode, + &TAP_CTRL_RBB_BYPASS, true); + tap_ctrl_rbb_register_handler(tap, tap->idcode_inst, &TAP_CTRL_RBB_IDCODE, true); - tap_ctrl_rbb_register_handler(tap, irslots - 1u, &tap_ctrl_rbb_bypass, + tap_ctrl_rbb_register_handler(tap, irslots - 1u, &TAP_CTRL_RBB_BYPASS, true); /* special case for ID code: opaque store the constant idcode value */ TapDataHandler *tdh = tap_ctrl_rbb_get_data_handler(tap, tap->idcode_inst); diff --git a/hw/opentitan/ot_alert.c b/hw/opentitan/ot_alert.c index b1a64a833a47..16d2c419f6fd 100644 --- a/hw/opentitan/ot_alert.c +++ b/hw/opentitan/ot_alert.c @@ -757,9 +757,9 @@ static void ot_alert_signal_tx(void *opaque, int n, int level) trace_ot_alert_signal_class(s->ot_id, alert, ACLASS(nclass), class_en); - if (class_en) { - DVAL(s->regs.intr->state) |= 1u << nclass; + DVAL(s->regs.intr->state) |= 1u << nclass; + if (class_en) { /* saturate (no roll over) */ if (DVAL(aclass->accum_cnt) < CLASS_ACCUM_CNT_MASK) { DVAL(aclass->accum_cnt) += 1u; diff --git a/hw/opentitan/ot_dm_tl.c b/hw/opentitan/ot_dm_tl.c index 1b831792782b..2c6511052816 100644 --- a/hw/opentitan/ot_dm_tl.c +++ b/hw/opentitan/ot_dm_tl.c @@ -53,6 +53,7 @@ struct OtDMTLState { uint64_t tl_base; uint32_t dmi_addr; unsigned dmi_size; + bool enable; uint8_t role; }; @@ -136,6 +137,7 @@ static Property ot_dm_tl_properties[] = { DEFINE_PROP_UINT64("tl_addr", OtDMTLState, tl_base, 0), DEFINE_PROP_LINK("tl_dev", OtDMTLState, tl_dev, TYPE_SYS_BUS_DEVICE, SysBusDevice *), + DEFINE_PROP_BOOL("enable", OtDMTLState, enable, true), DEFINE_PROP_UINT8("role", OtDMTLState, role, UINT8_MAX), DEFINE_PROP_END_OF_LIST(), }; @@ -148,9 +150,10 @@ static void ot_dm_tl_reset(DeviceState *dev) g_assert(dmtl->dmi_size); if (!dmtl->dtm_ok) { + RISCVDTMClass *dtmc = RISCV_DTM_GET_CLASS(OBJECT(dmtl->dtm)); dmtl->dtm_ok = - riscv_dtm_register_dm(DEVICE(dmtl->dtm), RISCV_DEBUG_DEVICE(dev), - dmtl->dmi_addr, dmtl->dmi_size); + (*dtmc->register_dm)(DEVICE(dmtl->dtm), RISCV_DEBUG_DEVICE(dev), + dmtl->dmi_addr, dmtl->dmi_size, dmtl->enable); } if (dmtl->dtm_ok) { diff --git a/hw/opentitan/ot_lc_ctrl.c b/hw/opentitan/ot_lc_ctrl.c index 1d3fa0507dae..900597cda305 100644 --- a/hw/opentitan/ot_lc_ctrl.c +++ b/hw/opentitan/ot_lc_ctrl.c @@ -44,7 +44,6 @@ #include "hw/riscv/ibex_common.h" #include "hw/riscv/ibex_irq.h" #include "hw/sysbus.h" -#include "ot_lc_defs.h" #include "tomcrypt.h" #include "trace.h" #include "trace/trace-hw_opentitan.h" @@ -185,14 +184,66 @@ static const char *REG_NAMES[REGS_COUNT] = { }; #undef REG_NAME_ENTRY +#define NUM_LC_STATE (LC_STATE_VALID_COUNT) +#define NUM_LC_TRANSITION_COUNT 25u +#define NUM_OWNERSHIP 8u +#define NUM_SOCDBG 3u + +#define LC_TRANSITION_COUNT_WORDS 24u +#define LC_STATE_WORDS 20u +#define OWNERSHIP_WORDS 8u +#define SOCDBG_WORDS 2u + +#define LC_TRANSITION_COUNT_BYTES \ + ((LC_TRANSITION_COUNT_WORDS) / sizeof(uint16_t)) +#define LC_STATE_BYTES ((LC_STATE_WORDS) / sizeof(uint16_t)) +#define OWNERSHIP_SIZE ((OWNERSHIP_WORDS) / sizeof(uint16_t)) +#define SOCDBG_SIZE ((SOCDBG_WORDS) / sizeof(uint16_t)) + +#define LC_STATE_BIT_WIDTH 5u #define LC_ENCODE_STATE(_x_) \ - (((_x_) << 0u) | ((_x_) << 5u) | ((_x_) << 10u) | ((_x_) << 15u) | \ - ((_x_) << 20u) | ((_x_) << 25u)) + (((_x_) << (LC_STATE_BIT_WIDTH * 0)) | \ + ((_x_) << (LC_STATE_BIT_WIDTH * 1u)) | \ + ((_x_) << (LC_STATE_BIT_WIDTH * 2u)) | \ + ((_x_) << (LC_STATE_BIT_WIDTH * 3u)) | \ + ((_x_) << (LC_STATE_BIT_WIDTH * 4u)) | \ + ((_x_) << (LC_STATE_BIT_WIDTH * 5u))) +#define LC_STATE_BITS(_elc_) ((_elc_) & ((1u << LC_STATE_BIT_WIDTH) - 1u)) #define LC_ID_STATE_BLANK 0 #define LC_ID_STATE_PERSONALIZED 0x55555555u #define LC_ID_STATE_INVALID 0xaaaaaaaau +/* Share lifecycle state definitions */ +typedef enum { + LC_STATE_RAW, + LC_STATE_TESTUNLOCKED0, + LC_STATE_TESTLOCKED0, + LC_STATE_TESTUNLOCKED1, + LC_STATE_TESTLOCKED1, + LC_STATE_TESTUNLOCKED2, + LC_STATE_TESTLOCKED2, + LC_STATE_TESTUNLOCKED3, + LC_STATE_TESTLOCKED3, + LC_STATE_TESTUNLOCKED4, + LC_STATE_TESTLOCKED4, + LC_STATE_TESTUNLOCKED5, + LC_STATE_TESTLOCKED5, + LC_STATE_TESTUNLOCKED6, + LC_STATE_TESTLOCKED6, + LC_STATE_TESTUNLOCKED7, + LC_STATE_DEV, + LC_STATE_PROD, + LC_STATE_PRODEND, + LC_STATE_RMA, + LC_STATE_SCRAP, + LC_STATE_VALID_COUNT, + LC_STATE_POST_TRANSITION = LC_STATE_VALID_COUNT, + LC_STATE_ESCALATE, + LC_STATE_INVALID, + LC_STATE_TOTAL_COUNT +} OtLcState; + typedef enum { LC_ENC_STATE_RAW = LC_ENCODE_STATE(LC_STATE_RAW), LC_ENC_STATE_TESTUNLOCKED0 = LC_ENCODE_STATE(LC_STATE_TESTUNLOCKED0), @@ -220,6 +271,11 @@ typedef enum { LC_ENC_STATE_INVALID = LC_ENCODE_STATE(LC_STATE_INVALID), } OtLcEncodedState; +typedef uint16_t OtLcCtrlStateValue[LC_STATE_WORDS]; +typedef uint16_t OtLcCtrlTransitionCountValue[LC_TRANSITION_COUNT_WORDS]; +typedef uint16_t OtLcCtrlOwnershipValue[OWNERSHIP_WORDS]; +typedef uint16_t OtLcCtrlSocDbgValue[SOCDBG_WORDS]; + typedef enum { LC_IF_NONE, LC_IF_SW, /* CPU requester */ @@ -271,6 +327,47 @@ typedef enum { LC_DIV_PROD, } OtLcCtrlKeyMgrDiv; +/* Ownership states */ +typedef enum { + OWNERSHIP_ST_RAW, + OWNERSHIP_ST_LOCKED0, + OWNERSHIP_ST_RELEASED0, + OWNERSHIP_ST_LOCKED1, + OWNERSHIP_ST_RELEASED1, + OWNERSHIP_ST_LOCKED2, + OWNERSHIP_ST_RELEASED2, + OWNERSHIP_ST_LOCKED_3, + OWNERSHIP_ST_SCRAPPED, + OWNERSHIP_ST_COUNT, +} OtLcCtrlOwnershipState; + +/* SocDbg states */ +typedef enum { + SOCDBG_ST_RAW, + SOCDBG_ST_PRE_PROD, + SOCDBG_ST_PROD, + SOCDBG_ST_COUNT, +} OtLcCtrlDbgState; + +typedef enum { + LC_CTRL_TRANS_LC_STATE, + LC_CTRL_TRANS_LC_TCOUNT, + LC_CTRL_TRANS_OWNERSHIP, + LC_CTRL_TRANS_SOCDBG, + LC_CTRL_TRANS_COUNT +} OtLcCtrlTransition; + +enum OtLcCtrlTState { + LC_CTRL_TSTATE_FIRST, /* initial value */ + LC_CTRL_TSTATE_LAST, /* terminal value */ + LC_CTRL_TSTATE_COUNT, +}; + +typedef struct { + /* string of hexadecimal encoded bytes */ + char *state[LC_CTRL_TSTATE_COUNT]; +} OtLcCtrlTransitionConfig; + struct OtLcCtrlState { SysBusDevice parent_obj; @@ -285,13 +382,17 @@ struct OtLcCtrlState { uint32_t *regs; /* slots in xregs are not used in regs */ uint32_t xregs[EXCLUSIVE_SLOTS_COUNT][EXCLUSIVE_REGS_COUNT]; OtLcState lc_state; - OtLcCtrlKeyMgrDiv km_div; uint32_t lc_tcount; + OtLcCtrlKeyMgrDiv km_div; OtOTPTokenValue hash_token; OtLcCtrlIf owner; OtLcCtrlFsmState state; OtLcCtrlFsmKmacState kmac_state; - OtOTPTokenValue hashed_tokens[LC_TK_COUNT]; + OtLcCtrlStateValue *lc_states; + OtLcCtrlTransitionCountValue *lc_transitions; + OtLcCtrlOwnershipValue *ownerships; + OtLcCtrlSocDbgValue *socdbgs; + OtOTPTokenValue *hashed_tokens; uint32_t hashed_token_bm; struct { uint32_t value; @@ -307,6 +408,7 @@ struct OtLcCtrlState { OtOTPState *otp_ctrl; OtKMACState *kmac; char *raw_unlock_token_xstr; + OtLcCtrlTransitionConfig trans_cfg[LC_CTRL_TRANS_COUNT]; uint16_t silicon_creator_id; uint16_t product_id; uint8_t revision_id; @@ -314,6 +416,12 @@ struct OtLcCtrlState { bool volatile_raw_unlock; }; +typedef struct { + unsigned word_count; /* sequence size (count of 16-bit words) */ + unsigned step_count; /* how many different steps/stages, incl. raw/blank */ + const char *name; /* helper name */ +} OtLcCtrlTransitionDesc; + static_assert(sizeof(OtOTPTokenValue) == LC_TOKEN_WIDTH, "Unexpected LC TOLEN WIDTH"); @@ -402,6 +510,35 @@ static const char *LC_BROADCAST_NAMES[] = { LC_NAME_ENTRY(OT_LC_ISO_PART_SW_WR_EN), LC_NAME_ENTRY(OT_LC_SEED_HW_RD_EN), }; + +static const char *TSTATE_NAMES[LC_CTRL_TSTATE_COUNT] = { + [LC_CTRL_TSTATE_FIRST] = "first", + [LC_CTRL_TSTATE_LAST] = "last", +}; + +static const OtLcCtrlTransitionDesc TRANSITION_DESC[LC_CTRL_TRANS_COUNT] = { + [LC_CTRL_TRANS_LC_STATE] = { + .word_count = LC_STATE_WORDS, + .step_count = NUM_LC_STATE, + .name = "lc_state", + }, + [LC_CTRL_TRANS_LC_TCOUNT] = { + .word_count = LC_TRANSITION_COUNT_WORDS, + .step_count = NUM_LC_TRANSITION_COUNT, + .name = "lc_tcount", + }, + [LC_CTRL_TRANS_OWNERSHIP] = { + .word_count = OWNERSHIP_WORDS, + .step_count = NUM_OWNERSHIP, + .name = "ownership", + }, + [LC_CTRL_TRANS_SOCDBG] = { + .word_count = SOCDBG_WORDS, + .step_count = NUM_SOCDBG, + .name = "socdbg", + }, +}; + /* clang-format on */ #undef LC_NAME_ENTRY @@ -431,6 +568,116 @@ static const char *LC_BROADCAST_NAMES[] = { LC_BROADCAST_NAMES[(_bit_)] : \ "?") +#define TSTATE_NAME(_st_) \ + (((unsigned)(_st_)) < ARRAY_SIZE(TSTATE_NAMES) ? TSTATE_NAMES[(_st_)] : "?") + +#define LC_STATE_A (1u << 6u) +#define LC_STATE_B (1u << 7u) + +#define ZRO 0 +#undef A +#undef B +#define A(_n_) ((LC_STATE_A) | (_n_)) +#define B(_n_) ((LC_STATE_B) | (_n_)) + +/* clang-format off */ +static const uint8_t +LC_STATES_TPL[NUM_LC_STATE][LC_STATE_WORDS] = { + [LC_STATE_RAW] = { + ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, + ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, + }, + [LC_STATE_TESTUNLOCKED0] = { + B(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), + A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTLOCKED0] = { + B(0), B(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), + A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTUNLOCKED1] = { + B(0), B(1), B(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), + A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTLOCKED1] = { + B(0), B(1), B(2), B(3), A(4), A(5), A(6), A(7), A(8), A(9), + A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTUNLOCKED2] = { + B(0), B(1), B(2), B(3), B(4), A(5), A(6), A(7), A(8), A(9), + A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTLOCKED2] = { + B(0), B(1), B(2), B(3), B(4), B(5), A(6), A(7), A(8), A(9), + A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTUNLOCKED3] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), A(7), A(8), A(9), + A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTLOCKED3] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), A(8), A(9), + A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTUNLOCKED4] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), A(9), + A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTLOCKED4] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), + A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTUNLOCKED5] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), + B(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTLOCKED5] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), + B(10), B(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTUNLOCKED6] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), + B(10), B(11), B(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTLOCKED6] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), + B(10), B(11), B(12), B(13), A(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_TESTUNLOCKED7] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), + B(10), B(11), B(12), B(13), B(14), A(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_DEV] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), + B(10), B(11), B(12), B(13), B(14), B(15), A(16), A(17), A(18), A(19), + }, + [LC_STATE_PROD] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), + B(10), B(11), B(12), B(13), B(14), A(15), B(16), A(17), A(18), A(19), + }, + [LC_STATE_PRODEND] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), + B(10), B(11), B(12), B(13), B(14), A(15), A(16), B(17), A(18), A(19), + }, + [LC_STATE_RMA] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), + B(10), B(11), B(12), B(13), B(14), B(15), B(16), A(17), B(18), B(19), + }, + [LC_STATE_SCRAP] = { + B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), + B(10), B(11), B(12), B(13), B(14), B(15), B(16), B(17), B(18), B(19), + }, +}; +/* clang-format on */ + +#define LC_STATE_A_WORD(_x_) ((bool)((_x_) & LC_STATE_A)) +#define LC_STATE_B_WORD(_x_) ((bool)((_x_) & LC_STATE_B)) +#define LC_STATE_ZERO_WORD(_x_) ((_x_) == 0u) +#define LC_STATE_WORD(_x_) ((_x_) & ~(LC_STATE_A | LC_STATE_B)) +#undef ZRO +#undef A +#undef B + #ifdef OT_LC_CTRL_DEBUG #define TRACE_LC_CTRL(msg, ...) \ qemu_log("%s: " msg "\n", __func__, ##__VA_ARGS__); @@ -874,12 +1121,13 @@ static uint32_t ot_lc_ctrl_load_lc_info(OtLcCtrlState *s) { OtOTPStateClass *oc = OBJECT_GET_CLASS(OtOTPStateClass, s->otp_ctrl, TYPE_OT_OTP); - uint32_t enc_state; + OtLcCtrlStateValue lc_state; + OtLcCtrlTransitionCountValue lc_tcount; uint8_t lc_valid; uint8_t secret_valid; const OtOTPTokens *tokens = NULL; - oc->get_lc_info(s->otp_ctrl, &enc_state, &s->lc_tcount, &lc_valid, - &secret_valid, &tokens); + oc->get_lc_info(s->otp_ctrl, lc_tcount, lc_state, &lc_valid, &secret_valid, + &tokens); switch (secret_valid) { case OT_MULTIBITBOOL_LC4_FALSE: @@ -896,6 +1144,27 @@ static uint32_t ot_lc_ctrl_load_lc_info(OtLcCtrlState *s) break; } + uint32_t enc_lcstate = LC_ENCODE_STATE(LC_STATE_INVALID); + s->lc_tcount = NUM_LC_TRANSITION_COUNT; + + for (unsigned ix = 0; ix < NUM_LC_TRANSITION_COUNT; ix++) { + if (!memcmp(lc_tcount, s->lc_transitions[ix], + sizeof(OtLcCtrlTransitionCountValue))) { + s->lc_tcount = ix; + break; + } + } + + for (unsigned ix = 0; ix < LC_STATE_VALID_COUNT; ix++) { + if (!memcmp(lc_state, s->lc_states[ix], sizeof(OtLcCtrlStateValue))) { + enc_lcstate = LC_ENCODE_STATE(ix); + break; + } + } + + trace_ot_lc_ctrl_initial_lifecycle(s->ot_id, s->lc_tcount, enc_lcstate, + LC_STATE_BITS(enc_lcstate)); + g_assert(tokens); uint32_t valid_bm = tokens->valid_bm; @@ -917,7 +1186,7 @@ static uint32_t ot_lc_ctrl_load_lc_info(OtLcCtrlState *s) s->hashed_tokens[ltix].lo); } - return lc_valid == OT_MULTIBITBOOL_LC4_TRUE ? enc_state : UINT32_MAX; + return lc_valid == OT_MULTIBITBOOL_LC4_TRUE ? enc_lcstate : UINT32_MAX; } static void ot_lc_ctrl_load_otp_hw_cfg(OtLcCtrlState *s) @@ -969,7 +1238,8 @@ static void ot_lc_ctrl_handle_otp_ack(void *opaque, bool ack) } } -static void ot_lc_ctrl_program_otp(OtLcCtrlState *s, OtLcState lc_state) +static void ot_lc_ctrl_program_otp(OtLcCtrlState *s, unsigned lc_tcount, + OtLcState lc_state) { OtOTPStateClass *oc = OBJECT_GET_CLASS(OtOTPStateClass, s->otp_ctrl, TYPE_OT_OTP); @@ -983,9 +1253,12 @@ static void ot_lc_ctrl_program_otp(OtLcCtrlState *s, OtLcState lc_state) return; } - uint32_t enc_state = LC_ENCODE_STATE(lc_state); + unsigned stix = MIN((unsigned)lc_state, NUM_LC_STATE); + unsigned tcix = MIN(lc_tcount, NUM_LC_TRANSITION_COUNT); + const uint16_t *transition_val = s->lc_transitions[tcix]; + const uint16_t *state_val = s->lc_states[stix]; - if (!oc->program_req(s->otp_ctrl, enc_state, s->lc_tcount, + if (!oc->program_req(s->otp_ctrl, transition_val, state_val, &ot_lc_ctrl_handle_otp_ack, s)) { trace_ot_lc_ctrl_error(s->ot_id, "OTP program request rejected"); s->regs[R_STATUS] |= R_STATUS_STATE_ERROR_MASK; @@ -1088,7 +1361,7 @@ static void ot_lc_ctrl_start_transition(OtLcCtrlState *s) LC_FSM_CHANGE_STATE(s, ST_CNT_PROG); - ot_lc_ctrl_program_otp(s, s->lc_state); + ot_lc_ctrl_program_otp(s, s->lc_tcount, s->lc_state); } static void ot_lc_ctrl_resume_transition(OtLcCtrlState *s) @@ -1133,7 +1406,7 @@ static void ot_lc_ctrl_resume_transition(OtLcCtrlState *s) LC_FSM_CHANGE_STATE(s, ST_TRANS_PROG); - ot_lc_ctrl_program_otp(s, target_state); + ot_lc_ctrl_program_otp(s, s->lc_tcount, target_state); } } @@ -1617,11 +1890,153 @@ static void ot_lc_ctrl_dmi_regs_write(void *opaque, hwaddr addr, uint64_t val64, ot_lc_ctrl_regs_write(s, addr, (uint32_t)val64, LC_IF_DMI); } +static void ot_lc_ctrl_load_transitions(OtLcCtrlState *s, + OtLcCtrlTransition trans, + uint16_t **first, uint16_t **last) +{ + g_assert(trans >= 0 && trans < LC_CTRL_TRANS_COUNT); + + const OtLcCtrlTransitionDesc *tdesc = &TRANSITION_DESC[trans]; + size_t len; + + Error *err = NULL; + uint16_t *state[LC_CTRL_TSTATE_COUNT] = { NULL, NULL }; + + for (unsigned ix = 0; ix < LC_CTRL_TSTATE_COUNT; ix++) { + state[ix] = g_new0(uint16_t, tdesc->word_count); + + if (!s->trans_cfg[trans].state[ix]) { + trace_ot_lc_ctrl_transition_missing(s->ot_id, tdesc->name, + TSTATE_NAME(ix)); + /* non-fatal, state has been cleared out */ + continue; + } + + len = strlen(s->trans_cfg[trans].state[ix]); + /* each byte is encoding with two ASCII nibbles */ + if (len != tdesc->word_count * sizeof(uint16_t) * 2u) { + qemu_log("%s %s %s %zu %zu\n", __func__, tdesc->name, + TSTATE_NAME(ix), len, + tdesc->word_count * sizeof(uint16_t)); + error_setg(&err, "%s: %s invalid %s %s length\n", __func__, + s->ot_id, tdesc->name, TSTATE_NAME(ix)); + break; + } + + if (ot_common_parse_hexa_str((uint8_t *)state[ix], + s->trans_cfg[trans].state[ix], + tdesc->word_count * sizeof(uint16_t), + false, true)) { + error_setg(&err, "%s: %s unable to parse %s %s\n", __func__, + s->ot_id, tdesc->name, TSTATE_NAME(ix)); + break; + } + } + + if (!err) { + /* + * if the configuration is missing, it is not a fatal error. Use an + * blank sequence, so that emulation works as if the config was not + * valid + */ + g_assert(state[LC_CTRL_TSTATE_FIRST] && state[LC_CTRL_TSTATE_LAST]); + *first = state[LC_CTRL_TSTATE_FIRST]; + *last = state[LC_CTRL_TSTATE_LAST]; + return; + } + + for (unsigned ix = 0; ix < LC_CTRL_TSTATE_COUNT; ix++) { + g_free(state[ix]); + } + + /* equivalent to error_fatal usage */ + error_report_err(err); + exit(1); +} + +static void ot_lc_ctrl_configure_lc_states(OtLcCtrlState *s) +{ + uint16_t *first; + uint16_t *last; + + ot_lc_ctrl_load_transitions(s, LC_CTRL_TRANS_LC_STATE, &first, &last); + + for (unsigned lcix = 0; lcix < NUM_LC_STATE; lcix++) { + uint16_t *lcval = &s->lc_states[lcix][0]; + const uint8_t *tpl = LC_STATES_TPL[lcix]; + for (unsigned pos = 0; pos < LC_STATE_WORDS; pos++) { + unsigned slot = LC_STATE_WORD(tpl[pos]); + g_assert(slot < LC_STATE_WORDS); + if (LC_STATE_A_WORD(tpl[pos])) { + lcval[pos] = first[slot]; + } else if (LC_STATE_B_WORD(tpl[pos])) { + lcval[pos] = last[slot]; + } else if (LC_STATE_ZERO_WORD(tpl[pos])) { + lcval[pos] = 0u; + } else { + g_assert_not_reached(); + } + } + } + + g_free(last); + g_free(first); +} + +static void ot_lc_ctrl_configure_transitions( + OtLcCtrlState *s, OtLcCtrlTransition trans, uint16_t *table) +{ + const OtLcCtrlTransitionDesc *tdesc = &TRANSITION_DESC[trans]; + + uint16_t *first; + uint16_t *last; + ot_lc_ctrl_load_transitions(s, trans, &first, &last); + + uint16_t *lcval = table; + memset(lcval, 0, tdesc->word_count * sizeof(uint16_t)); /* RAW stage */ + lcval += tdesc->word_count; + for (unsigned tix = 1; tix < tdesc->step_count; + tix++, lcval += tdesc->word_count) { + memcpy(&lcval[0], &last[0], tix * sizeof(uint16_t)); + memcpy(&lcval[tix], &first[tix], + (tdesc->step_count - tix) * sizeof(uint16_t)); + } + + g_free(last); + g_free(first); +} + static Property ot_lc_ctrl_properties[] = { DEFINE_PROP_STRING("ot_id", OtLcCtrlState, ot_id), DEFINE_PROP_LINK("otp_ctrl", OtLcCtrlState, otp_ctrl, TYPE_OT_OTP, OtOTPState *), DEFINE_PROP_LINK("kmac", OtLcCtrlState, kmac, TYPE_OT_KMAC, OtKMACState *), + DEFINE_PROP_STRING("raw_unlock_token", OtLcCtrlState, + raw_unlock_token_xstr), + DEFINE_PROP_STRING("lc_state_first", OtLcCtrlState, + trans_cfg[LC_CTRL_TRANS_LC_STATE] + .state[LC_CTRL_TSTATE_FIRST]), + DEFINE_PROP_STRING("lc_state_last", OtLcCtrlState, + trans_cfg[LC_CTRL_TRANS_LC_STATE] + .state[LC_CTRL_TSTATE_LAST]), + DEFINE_PROP_STRING("lc_trscnt_first", OtLcCtrlState, + trans_cfg[LC_CTRL_TRANS_LC_TCOUNT] + .state[LC_CTRL_TSTATE_FIRST]), + DEFINE_PROP_STRING("lc_trscnt_last", OtLcCtrlState, + trans_cfg[LC_CTRL_TRANS_LC_TCOUNT] + .state[LC_CTRL_TSTATE_LAST]), + DEFINE_PROP_STRING("ownership_first", OtLcCtrlState, + trans_cfg[LC_CTRL_TRANS_OWNERSHIP] + .state[LC_CTRL_TSTATE_FIRST]), + DEFINE_PROP_STRING("ownership_last", OtLcCtrlState, + trans_cfg[LC_CTRL_TRANS_OWNERSHIP] + .state[LC_CTRL_TSTATE_LAST]), + DEFINE_PROP_STRING("socdbg_first", OtLcCtrlState, + trans_cfg[LC_CTRL_TRANS_SOCDBG] + .state[LC_CTRL_TSTATE_FIRST]), + DEFINE_PROP_STRING("socdbg_last", OtLcCtrlState, + trans_cfg[LC_CTRL_TRANS_SOCDBG] + .state[LC_CTRL_TSTATE_LAST]), DEFINE_PROP_UINT16("silicon_creator_id", OtLcCtrlState, silicon_creator_id, 0), DEFINE_PROP_UINT16("product_id", OtLcCtrlState, product_id, 0), @@ -1629,8 +2044,6 @@ static Property ot_lc_ctrl_properties[] = { DEFINE_PROP_BOOL("volatile_raw_unlock", OtLcCtrlState, volatile_raw_unlock, true), DEFINE_PROP_UINT8("kmac-app", OtLcCtrlState, kmac_app, UINT8_MAX), - DEFINE_PROP_STRING("raw_unlock_token", OtLcCtrlState, - raw_unlock_token_xstr), DEFINE_PROP_END_OF_LIST(), }; @@ -1734,6 +2147,13 @@ static void ot_lc_ctrl_realize(DeviceState *dev, Error **errp) g_strdup(object_get_canonical_path_component(OBJECT(s)->parent)); } + ot_lc_ctrl_configure_lc_states(s); + ot_lc_ctrl_configure_transitions(s, LC_CTRL_TRANS_LC_TCOUNT, + (uint16_t *)s->lc_transitions); + ot_lc_ctrl_configure_transitions(s, LC_CTRL_TRANS_OWNERSHIP, + (uint16_t *)s->ownerships); + ot_lc_ctrl_configure_transitions(s, LC_CTRL_TRANS_SOCDBG, + (uint16_t *)s->socdbgs); ot_lc_ctrl_compute_predefined_tokens(s, &error_fatal); } @@ -1750,6 +2170,12 @@ static void ot_lc_ctrl_init(Object *obj) sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->dmi_mmio); s->regs = g_new0(uint32_t, REGS_COUNT); + s->lc_states = g_new0(OtLcCtrlStateValue, NUM_LC_STATE); + s->lc_transitions = + g_new0(OtLcCtrlTransitionCountValue, NUM_LC_TRANSITION_COUNT); + s->ownerships = g_new0(OtLcCtrlOwnershipValue, NUM_OWNERSHIP); + s->socdbgs = g_new0(OtLcCtrlSocDbgValue, NUM_SOCDBG); + s->hashed_tokens = g_new0(OtOTPTokenValue, LC_TK_COUNT); for (unsigned ix = 0; ix < ARRAY_SIZE(s->alerts); ix++) { ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); diff --git a/hw/opentitan/ot_lc_defs.h b/hw/opentitan/ot_lc_defs.h deleted file mode 100644 index 95e7742f557b..000000000000 --- a/hw/opentitan/ot_lc_defs.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * QEMU OpenTitan LifeCycle definitions - * - * Copyright (c) 2023-2024 Rivos, Inc. - * - * Author(s): - * Emmanuel Blot - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef HW_OPENTITAN_OT_LC_DEFS_H -#define HW_OPENTITAN_OT_LC_DEFS_H - -/* Share lifecycle state definitions */ -typedef enum { - LC_STATE_RAW, - LC_STATE_TESTUNLOCKED0, - LC_STATE_TESTLOCKED0, - LC_STATE_TESTUNLOCKED1, - LC_STATE_TESTLOCKED1, - LC_STATE_TESTUNLOCKED2, - LC_STATE_TESTLOCKED2, - LC_STATE_TESTUNLOCKED3, - LC_STATE_TESTLOCKED3, - LC_STATE_TESTUNLOCKED4, - LC_STATE_TESTLOCKED4, - LC_STATE_TESTUNLOCKED5, - LC_STATE_TESTLOCKED5, - LC_STATE_TESTUNLOCKED6, - LC_STATE_TESTLOCKED6, - LC_STATE_TESTUNLOCKED7, - LC_STATE_DEV, - LC_STATE_PROD, - LC_STATE_PRODEND, - LC_STATE_RMA, - LC_STATE_SCRAP, - LC_STATE_VALID_COUNT, - LC_STATE_POST_TRANSITION = LC_STATE_VALID_COUNT, - LC_STATE_ESCALATE, - LC_STATE_INVALID, - LC_STATE_TOTAL_COUNT -} OtLcState; - -#endif /* HW_OPENTITAN_OT_LC_DEFS_H */ diff --git a/hw/opentitan/ot_otp_dj.c b/hw/opentitan/ot_otp_dj.c index 8c0c73127aa1..512970c25924 100644 --- a/hw/opentitan/ot_otp_dj.c +++ b/hw/opentitan/ot_otp_dj.c @@ -48,7 +48,6 @@ #include "hw/riscv/ibex_common.h" #include "hw/riscv/ibex_irq.h" #include "hw/sysbus.h" -#include "ot_lc_defs.h" #include "sysemu/block-backend.h" #include "trace.h" @@ -527,7 +526,6 @@ REG32(LC_STATE, 16344u) #define SECRET2_CREATOR_ROOT_KEY_SHARE1_SIZE 32u #define SECRET2_CREATOR_SEED_SIZE 32u #define SECRET3_OWNER_SEED_SIZE 32u -#define LC_TRANSITION_COUNT 25u #define LC_TRANSITION_CNT_SIZE 48u #define LC_STATE_SIZE 40u @@ -578,10 +576,6 @@ REG32(LC_STATE, 16344u) #define OTP_ENTROPY_BUF_COUNT \ (OTP_ENTROPY_PRESENT_WORDS + OTP_ENTROPY_NONCE_WORDS) -#define LC_STATE_SLOT_COUNT (LC_STATE_SIZE / sizeof(uint16_t)) -#define LC_STATE_TRANSITION_SLOT_COUNT \ - ((LC_TRANSITION_CNT_SIZE) / sizeof(uint16_t)) - typedef enum { OTP_PART_VENDOR_TEST, OTP_PART_CREATOR_SW_CFG, @@ -747,10 +741,6 @@ typedef struct { QEMUBH *prog_bh; /* OTP prog trigger */ OtOTPLCIState state; OtOTPError error; - struct { - uint32_t state; - unsigned tcount; - } lc; ot_otp_program_ack_fn ack_fn; void *ack_data; uint16_t data[OTP_PART_LIFE_CYCLE_SIZE / sizeof(uint16_t)]; @@ -790,9 +780,6 @@ typedef struct { uint8_t nonce[SRAM_NONCE_BYTES]; } OtOTPScrmblKeyInit; -typedef uint16_t OtOTPStateValue[LC_STATE_SLOT_COUNT]; -typedef uint16_t OtOTPTransitionValue[LC_STATE_TRANSITION_SLOT_COUNT]; - struct OtOTPDjState { OtOTPState parent_obj; @@ -825,8 +812,6 @@ struct OtOTPDjState { OtOTPStorage *otp; OtOTPHWCfg *hw_cfg; OtOTPTokens *tokens; - OtOTPStateValue *lc_states; /* LC_STATE_VALID_COUNT array */ - OtOTPTransitionValue *lc_transitions; /*LC_TRANSITION_COUNT array */ char *ot_id; BlockBackend *blk; /* OTP host backend */ @@ -837,10 +822,6 @@ struct OtOTPDjState { char *digest_iv_xstr; char *sram_const_xstr; char *sram_iv_xstr; - char *lc_state_first_xstr; - char *lc_state_last_xstr; - char *lc_trscnt_first_xstr; - char *lc_trscnt_last_xstr; uint8_t edn_ep; }; @@ -994,6 +975,9 @@ static const char *PART_NAMES[] = { OTP_NAME_ENTRY(OTP_PART_SECRET2), OTP_NAME_ENTRY(OTP_PART_SECRET3), OTP_NAME_ENTRY(OTP_PART_LIFE_CYCLE), + /* fake partitions */ + OTP_NAME_ENTRY(OTP_ENTRY_DAI), + OTP_NAME_ENTRY(OTP_ENTRY_KDI), }; static const char *ERR_CODE_NAMES[] = { @@ -1006,6 +990,7 @@ static const char *ERR_CODE_NAMES[] = { OTP_NAME_ENTRY(OTP_CHECK_FAIL_ERROR), OTP_NAME_ENTRY(OTP_FSM_STATE_ERROR), }; + /* clang-format on */ #undef OTP_NAME_ENTRY @@ -1037,113 +1022,6 @@ static const char *ERR_CODE_NAMES[] = { ERR_CODE_NAMES[(_err_)] : \ "?") -#define LC_STATE_A (1u << 6u) -#define LC_STATE_B (1u << 7u) - -#define ZRO 0 -#undef A -#undef B -#define A(_n_) ((LC_STATE_A) | (_n_)) -#define B(_n_) ((LC_STATE_B) | (_n_)) - -/* clang-format off */ -static const uint8_t -LC_STATES_TPL[LC_STATE_VALID_COUNT][LC_STATE_SLOT_COUNT] = { - [LC_STATE_RAW] = { - ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, - ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, ZRO, - }, - [LC_STATE_TESTUNLOCKED0] = { - B(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), - A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTLOCKED0] = { - B(0), B(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), - A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTUNLOCKED1] = { - B(0), B(1), B(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), - A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTLOCKED1] = { - B(0), B(1), B(2), B(3), A(4), A(5), A(6), A(7), A(8), A(9), - A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTUNLOCKED2] = { - B(0), B(1), B(2), B(3), B(4), A(5), A(6), A(7), A(8), A(9), - A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTLOCKED2] = { - B(0), B(1), B(2), B(3), B(4), B(5), A(6), A(7), A(8), A(9), - A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTUNLOCKED3] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), A(7), A(8), A(9), - A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTLOCKED3] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), A(8), A(9), - A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTUNLOCKED4] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), A(9), - A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTLOCKED4] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), - A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTUNLOCKED5] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), - B(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTLOCKED5] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), - B(10), B(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTUNLOCKED6] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), - B(10), B(11), B(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTLOCKED6] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), - B(10), B(11), B(12), B(13), A(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_TESTUNLOCKED7] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), - B(10), B(11), B(12), B(13), B(14), A(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_DEV] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), - B(10), B(11), B(12), B(13), B(14), B(15), A(16), A(17), A(18), A(19), - }, - [LC_STATE_PROD] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), - B(10), B(11), B(12), B(13), B(14), A(15), B(16), A(17), A(18), A(19), - }, - [LC_STATE_PRODEND] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), - B(10), B(11), B(12), B(13), B(14), A(15), A(16), B(17), A(18), A(19), - }, - [LC_STATE_RMA] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), - B(10), B(11), B(12), B(13), B(14), B(15), B(16), A(17), B(18), B(19), - }, - [LC_STATE_SCRAP] = { - B(0), B(1), B(2), B(3), B(4), B(5), B(6), B(7), B(8), B(9), - B(10), B(11), B(12), B(13), B(14), B(15), B(16), B(17), B(18), B(19), - }, -}; -/* clang-format on */ - -#define LC_STATE_A_SLOT(_x_) ((bool)((_x_) & LC_STATE_A)) -#define LC_STATE_B_SLOT(_x_) ((bool)((_x_) & LC_STATE_B)) -#define LC_STATE_ZERO_SLOT(_x_) ((_x_) == 0u) -#define LC_STATE_SLOT(_x_) ((_x_) & ~(LC_STATE_A | LC_STATE_B)) -#undef ZRO -#undef A -#undef B - static void ot_otp_dj_dai_set_error(OtOTPDjState *s, OtOTPError err); static void @@ -1164,17 +1042,6 @@ ot_otp_dj_lci_change_state_line(OtOTPDjState *s, OtOTPLCIState state, int line); ((unsigned)(OtOTPPartDescs[(_pix_)].size - \ sizeof(uint32_t) * NUM_DIGEST_WORDS)) -#define LC_TRANSITION_COUNT_MAX 24u -#define LC_STATE_BIT_WIDTH 5u -#define LC_ENCODE_STATE(_x_) \ - (((_x_) << (LC_STATE_BIT_WIDTH * 0)) | \ - ((_x_) << (LC_STATE_BIT_WIDTH * 1u)) | \ - ((_x_) << (LC_STATE_BIT_WIDTH * 2u)) | \ - ((_x_) << (LC_STATE_BIT_WIDTH * 3u)) | \ - ((_x_) << (LC_STATE_BIT_WIDTH * 4u)) | \ - ((_x_) << (LC_STATE_BIT_WIDTH * 5u))) -#define LC_STATE_BITS(_elc_) ((_elc_) & ((1u << LC_STATE_BIT_WIDTH) - 1u)) - #ifdef OT_OTP_DEBUG #define TRACE_OTP(msg, ...) qemu_log("%s: " msg "\n", __func__, ##__VA_ARGS__); #else @@ -2064,6 +1931,8 @@ static void ot_otp_dj_dai_read(OtOTPDjState *s) return; } + s->dai->partition = partition; + if (!ot_otp_dj_is_buffered(partition)) { /* fake slow access to OTP cell */ timer_mod(s->dai->delay, @@ -2252,6 +2121,8 @@ static void ot_otp_dj_dai_write(OtOTPDjState *s) } } + s->dai->partition = partition; + if (is_wide || is_digest) { if (ot_otp_dj_dai_write_u64(s, address)) { return; @@ -2429,6 +2300,7 @@ static void ot_otp_dj_dai_complete(void *opaque) switch (s->dai->state) { case OTP_DAI_READ_WAIT: + g_assert(s->dai->partition >= 0); trace_ot_otp_dai_read(s->ot_id, PART_NAME(s->dai->partition), s->dai->partition, s->regs[R_DIRECT_ACCESS_RDATA_1], @@ -2437,6 +2309,7 @@ static void ot_otp_dj_dai_complete(void *opaque) DAI_CHANGE_STATE(s, OTP_DAI_IDLE); break; case OTP_DAI_WRITE_WAIT: + g_assert(s->dai->partition >= 0); s->regs[R_INTR_STATE] |= INTR_OTP_OPERATION_DONE_MASK; s->dai->partition = -1; DAI_CHANGE_STATE(s, OTP_DAI_IDLE); @@ -3166,37 +3039,6 @@ static MemTxResult ot_otp_dj_swcfg_read_with_attrs( return MEMTX_OK; } -static void ot_otp_dj_decode_lc_partition(OtOTPDjState *s) -{ - OtOTPStorage *otp = s->otp; - OtOTPLCIController *lci = s->lci; - const OtOTPPartDesc *lcdesc = &OtOTPPartDescs[OTP_PART_LIFE_CYCLE]; - - g_assert(lcdesc->offset == A_LC_TRANSITION_CNT); - - lci->lc.state = LC_ENCODE_STATE(LC_STATE_INVALID); - lci->lc.tcount = LC_TRANSITION_COUNT_MAX + 1u; - - for (unsigned ix = 0; ix < LC_TRANSITION_COUNT; ix++) { - if (!memcmp(&otp->data[R_LC_TRANSITION_CNT], s->lc_transitions[ix], - sizeof(OtOTPTransitionValue))) { - lci->lc.tcount = ix; - break; - } - } - - for (unsigned ix = 0; ix < LC_STATE_VALID_COUNT; ix++) { - if (!memcmp(&otp->data[R_LC_STATE], s->lc_states[ix], - sizeof(OtOTPStateValue))) { - lci->lc.state = LC_ENCODE_STATE(ix); - break; - } - } - - trace_ot_otp_initial_lifecycle(s->ot_id, lci->lc.tcount, lci->lc.state, - LC_STATE_BITS(lci->lc.state)); -} - static void ot_otp_dj_load_hw_cfg(OtOTPDjState *s) { OtOTPStorage *otp = s->otp; @@ -3206,8 +3048,8 @@ static void ot_otp_dj_load_hw_cfg(OtOTPDjState *s) sizeof(*hw_cfg->device_id)); memcpy(hw_cfg->manuf_state, &otp->data[R_HW_CFG0_MANUF_STATE], sizeof(*hw_cfg->manuf_state)); - - hw_cfg->soc_dbg_state = otp->data[R_HW_CFG1_SOC_DBG_STATE]; + memcpy(&hw_cfg->soc_dbg_state[0], &otp->data[R_HW_CFG1_SOC_DBG_STATE], + sizeof(uint32_t)); hw_cfg->en_sram_ifetch = (uint8_t)otp->data[R_HW_CFG1_EN_SRAM_IFETCH]; } @@ -3256,18 +3098,21 @@ static void ot_otp_dj_load_tokens(OtOTPDjState *s) } static void ot_otp_dj_get_lc_info( - const OtOTPState *s, uint32_t *lc_state, unsigned *tcount, + const OtOTPState *s, uint16_t *lc_tcount, uint16_t *lc_state, uint8_t *lc_valid, uint8_t *secret_valid, const OtOTPTokens **tokens) { const OtOTPDjState *ds = OT_OTP_DJ(s); - const OtOTPLCIController *lci = ds->lci; + const OtOTPStorage *otp = ds->otp; - if (lc_state) { - *lc_state = lci->lc.state; + if (lc_tcount) { + memcpy(lc_tcount, &otp->data[R_LC_TRANSITION_CNT], + LC_TRANSITION_CNT_SIZE); } - if (tcount) { - *tcount = lci->lc.tcount; + + if (lc_state) { + memcpy(lc_state, &otp->data[R_LC_STATE], LC_STATE_SIZE); } + if (lc_valid) { *lc_valid = !(ds->partctrls[OTP_PART_SECRET0].failed || ds->partctrls[OTP_PART_SECRET2].failed || @@ -3281,11 +3126,6 @@ static void ot_otp_dj_get_lc_info( OT_MULTIBITBOOL_LC4_TRUE : OT_MULTIBITBOOL_LC4_FALSE; } - trace_ot_otp_lc_info(ds->ot_id, LC_STATE_BITS(lci->lc.state), - lci->lc.tcount, - !ds->partctrls[OTP_PART_SECRET0].failed, - !ds->partctrls[OTP_PART_SECRET2].failed, - !ds->partctrls[OTP_PART_LIFE_CYCLE].failed); if (tokens) { *tokens = ds->tokens; } @@ -3453,40 +3293,9 @@ static void ot_otp_dj_get_otp_key(OtOTPState *s, OtOTPKeyType type, } } -static void ot_otp_dj_create_lc_data(OtOTPDjState *s, OtOTPLCIController *lci, - uint32_t lc_state, unsigned tcount) -{ - if (tcount >= LC_TRANSITION_COUNT) { - error_setg(&error_fatal, "%s: Invalid tcount: 0x%08x", __func__, - lc_state); - /* linter does not know error_setg never returns */ - return; - } - - unsigned lcix = LC_STATE_BITS(lc_state); - if (LC_ENCODE_STATE(lcix) != lc_state || lcix >= LC_STATE_VALID_COUNT) { - error_setg(&error_fatal, "%s: Invalid lc_state: 0x%08x", __func__, - lc_state); - /* linter does not know error_setg never returns */ - return; - } - - unsigned hpos = 0; - memcpy(&lci->data[hpos], s->lc_transitions[tcount], - sizeof(OtOTPTransitionValue)); - hpos += sizeof(OtOTPTransitionValue) / sizeof(uint16_t); - memcpy(&lci->data[hpos], s->lc_states[lcix], sizeof(OtOTPStateValue)); - hpos += sizeof(OtOTPStateValue) / sizeof(uint16_t); - g_assert(hpos == - OtOTPPartDescs[OTP_PART_LIFE_CYCLE].size / sizeof(uint16_t)); - - /* current position in LC buffer to write to backend */ - lci->hpos = 0; -} - -static bool ot_otp_dj_program_req(OtOTPState *s, uint32_t lc_state, - unsigned tcount, ot_otp_program_ack_fn ack, - void *opaque) +static bool ot_otp_dj_program_req(OtOTPState *s, const uint16_t *lc_tcount, + const uint16_t *lc_state, + ot_otp_program_ack_fn ack, void *opaque) { OtOTPDjState *ds = OT_OTP_DJ(s); OtOTPLCIController *lci = ds->lci; @@ -3512,7 +3321,16 @@ static bool ot_otp_dj_program_req(OtOTPState *s, uint32_t lc_state, lci->ack_data = opaque; if (lci->state == OTP_LCI_IDLE) { - ot_otp_dj_create_lc_data(ds, lci, lc_state, tcount); + unsigned hpos = 0; + memcpy(&lci->data[hpos], lc_tcount, LC_TRANSITION_CNT_SIZE); + hpos += LC_TRANSITION_CNT_SIZE / sizeof(uint16_t); + memcpy(&lci->data[hpos], lc_state, LC_STATE_SIZE); + hpos += LC_STATE_SIZE / sizeof(uint16_t); + g_assert(hpos == + OtOTPPartDescs[OTP_PART_LIFE_CYCLE].size / sizeof(uint16_t)); + + /* current position in LC buffer to write to backend */ + lci->hpos = 0; } /* @@ -3684,7 +3502,6 @@ static void ot_otp_dj_pwr_otp_bh(void *opaque) trace_ot_otp_pwr_otp_req(s->ot_id, "initialize"); ot_otp_dj_initialize_partitions(s); - ot_otp_dj_decode_lc_partition(s); ot_otp_dj_load_hw_cfg(s); ot_otp_dj_load_tokens(s); @@ -3697,7 +3514,7 @@ static void ot_otp_dj_pwr_otp_bh(void *opaque) ibex_irq_set(&s->pwc_otp_rsp, 0); } -static void ot_otp_dj_configure_scrmbl_key(OtOTPDjState *s, Error **errp) +static void ot_otp_dj_configure_scrmbl_key(OtOTPDjState *s) { if (!s->scrmbl_key_xstr) { trace_ot_otp_configure_missing(s->ot_id, "scrmbl_key"); @@ -3706,7 +3523,7 @@ static void ot_otp_dj_configure_scrmbl_key(OtOTPDjState *s, Error **errp) size_t len = strlen(s->scrmbl_key_xstr); if (len != (size_t)(SRAM_KEY_BYTES + SRAM_NONCE_BYTES) * 2u) { - error_setg(errp, "%s: %s invalid scrmbl_key length\n", __func__, + error_setg(&error_fatal, "%s: %s invalid scrmbl_key length\n", __func__, s->ot_id); return; } @@ -3714,21 +3531,21 @@ static void ot_otp_dj_configure_scrmbl_key(OtOTPDjState *s, Error **errp) if (ot_common_parse_hexa_str(s->scrmbl_key_init->key, &s->scrmbl_key_xstr[0], SRAM_KEY_BYTES, false, false)) { - error_setg(errp, "%s: %s unable to parse scrmbl_key\n", __func__, - s->ot_id); + error_setg(&error_fatal, "%s: %s unable to parse scrmbl_key\n", + __func__, s->ot_id); return; } if (ot_common_parse_hexa_str(s->scrmbl_key_init->nonce, &s->scrmbl_key_xstr[SRAM_KEY_BYTES * 2u], SRAM_NONCE_BYTES, false, true)) { - error_setg(errp, "%s: %s unable to parse scrmbl_key\n", __func__, - s->ot_id); + error_setg(&error_fatal, "%s: %s unable to parse scrmbl_key\n", + __func__, s->ot_id); return; } } -static void ot_otp_dj_configure_digest(OtOTPDjState *s, Error **errp) +static void ot_otp_dj_configure_digest(OtOTPDjState *s) { memset(s->digest_const, 0, sizeof(s->digest_const)); s->digest_iv = 0ull; @@ -3747,15 +3564,15 @@ static void ot_otp_dj_configure_digest(OtOTPDjState *s, Error **errp) len = strlen(s->digest_const_xstr); if (len != sizeof(s->digest_const) * 2u) { - error_setg(errp, "%s: %s invalid digest_const length\n", __func__, - s->ot_id); + error_setg(&error_fatal, "%s: %s invalid digest_const length\n", + __func__, s->ot_id); return; } if (ot_common_parse_hexa_str(s->digest_const, s->digest_const_xstr, sizeof(s->digest_const), true, true)) { - error_setg(errp, "%s: %s unable to parse digest_const\n", __func__, - s->ot_id); + error_setg(&error_fatal, "%s: %s unable to parse digest_const\n", + __func__, s->ot_id); return; } @@ -3763,14 +3580,14 @@ static void ot_otp_dj_configure_digest(OtOTPDjState *s, Error **errp) len = strlen(s->digest_iv_xstr); if (len != sizeof(digest_iv) * 2u) { - error_setg(errp, "%s: %s invalid digest_iv length\n", __func__, + error_setg(&error_fatal, "%s: %s invalid digest_iv length\n", __func__, s->ot_id); return; } if (ot_common_parse_hexa_str(digest_iv, s->digest_iv_xstr, sizeof(digest_iv), true, true)) { - error_setg(errp, "%s: %s unable to parse digest_iv\n", __func__, + error_setg(&error_fatal, "%s: %s unable to parse digest_iv\n", __func__, s->ot_id); return; } @@ -3778,7 +3595,7 @@ static void ot_otp_dj_configure_digest(OtOTPDjState *s, Error **errp) s->digest_iv = ldq_le_p(digest_iv); } -static void ot_otp_dj_configure_sram(OtOTPDjState *s, Error **errp) +static void ot_otp_dj_configure_sram(OtOTPDjState *s) { memset(s->sram_const, 0, sizeof(s->sram_const)); s->sram_iv = 0ull; @@ -3797,15 +3614,15 @@ static void ot_otp_dj_configure_sram(OtOTPDjState *s, Error **errp) len = strlen(s->sram_const_xstr); if (len != sizeof(s->sram_const) * 2u) { - error_setg(errp, "%s: %s invalid sram_const length\n", __func__, + error_setg(&error_fatal, "%s: %s invalid sram_const length\n", __func__, s->ot_id); return; } if (ot_common_parse_hexa_str(s->sram_const, s->sram_const_xstr, sizeof(s->sram_const), true, true)) { - error_setg(errp, "%s: %s unable to parse sram_const\n", __func__, - s->ot_id); + error_setg(&error_fatal, "%s: %s unable to parse sram_const\n", + __func__, s->ot_id); return; } @@ -3813,13 +3630,14 @@ static void ot_otp_dj_configure_sram(OtOTPDjState *s, Error **errp) len = strlen(s->sram_iv_xstr); if (len != sizeof(sram_iv) * 2u) { - error_setg(errp, "%s: %s invalid sram_iv length\n", __func__, s->ot_id); + error_setg(&error_fatal, "%s: %s invalid sram_iv length\n", __func__, + s->ot_id); return; } if (ot_common_parse_hexa_str(sram_iv, s->sram_iv_xstr, sizeof(sram_iv), true, true)) { - error_setg(errp, "%s: %s unable to parse sram_iv\n", __func__, + error_setg(&error_fatal, "%s: %s unable to parse sram_iv\n", __func__, s->ot_id); return; } @@ -3827,143 +3645,7 @@ static void ot_otp_dj_configure_sram(OtOTPDjState *s, Error **errp) s->sram_iv = ldq_le_p(sram_iv); } -static void ot_otp_dj_configure_lc_states(OtOTPDjState *s, Error **errp) -{ - if (!s->lc_state_first_xstr) { - trace_ot_otp_configure_missing(s->ot_id, "lc_state_first_xstr"); - return; - } - - if (!s->lc_state_last_xstr) { - trace_ot_otp_configure_missing(s->ot_id, "lc_state_last_xstr"); - return; - } - - size_t len; - - len = strlen(s->lc_state_first_xstr); - if (len != sizeof(OtOTPStateValue) * 2u) { - error_setg(errp, "%s: %s invalid lc_state_first length\n", __func__, - s->ot_id); - return; - } - - len = strlen(s->lc_state_last_xstr); - if (len != sizeof(OtOTPStateValue) * 2u) { - error_setg(errp, "%s: %s invalid lc_state_last length\n", __func__, - s->ot_id); - return; - } - - uint16_t first[sizeof(OtOTPStateValue) / sizeof(uint16_t)]; - uint16_t last[sizeof(OtOTPStateValue) / sizeof(uint16_t)]; - - if (ot_common_parse_hexa_str((uint8_t *)first, s->lc_state_first_xstr, - sizeof(first), false, true)) { - error_setg(errp, "%s: %s unable to parse lc_state_first\n", __func__, - s->ot_id); - return; - } - - if (ot_common_parse_hexa_str((uint8_t *)last, s->lc_state_last_xstr, - sizeof(last), false, true)) { - error_setg(errp, "%s: %s unable to parse lc_state_first\n", __func__, - s->ot_id); - return; - } - - for (unsigned lcix = 0; lcix < LC_STATE_VALID_COUNT; lcix++) { - uint16_t *lcval = &s->lc_states[lcix][0]; - const uint8_t *tpl = LC_STATES_TPL[lcix]; - for (unsigned pos = 0; pos < LC_STATE_SLOT_COUNT; pos++) { - unsigned slot = LC_STATE_SLOT(tpl[pos]); - g_assert(slot < LC_STATE_SLOT_COUNT); - if (LC_STATE_A_SLOT(tpl[pos])) { - lcval[pos] = first[slot]; - } else if (LC_STATE_B_SLOT(tpl[pos])) { - lcval[pos] = last[slot]; - } else if (LC_STATE_ZERO_SLOT(tpl[pos])) { - lcval[pos] = 0u; - } else { - g_assert_not_reached(); - } - } - } - -#ifdef OT_OTP_DEBUG - qemu_log("%s: %s\n", __func__, s->ot_id); - for (unsigned lcix = 0; lcix < LC_STATE_VALID_COUNT; lcix++) { - qemu_log("%s\n", - ot_otp_hexdump(s->lc_states[lcix], sizeof(OtOTPStateValue))); - } -#endif /* OT_OTP_DEBUG */ -} - -static void ot_otp_dj_configure_lc_transitions(OtOTPDjState *s, Error **errp) -{ - if (!s->lc_trscnt_first_xstr) { - trace_ot_otp_configure_missing(s->ot_id, "lc_trscnt_first_xstr"); - return; - } - - if (!s->lc_trscnt_last_xstr) { - trace_ot_otp_configure_missing(s->ot_id, "lc_trscnt_last_xstr"); - return; - } - - size_t len; - - len = strlen(s->lc_trscnt_first_xstr); - if (len != LC_TRANSITION_CNT_SIZE * 2u) { - error_setg(errp, "%s: %s invalid lc_trscnt_first length\n", __func__, - s->ot_id); - return; - } - - len = strlen(s->lc_trscnt_last_xstr); - if (len != LC_TRANSITION_CNT_SIZE * 2u) { - error_setg(errp, "%s: %s invalid lc_trscnt_last length\n", __func__, - s->ot_id); - return; - } - - uint16_t first[LC_TRANSITION_CNT_SIZE / sizeof(uint16_t)]; - uint16_t last[LC_TRANSITION_CNT_SIZE / sizeof(uint16_t)]; - - if (ot_common_parse_hexa_str((uint8_t *)first, s->lc_trscnt_first_xstr, - sizeof(first), false, true)) { - error_setg(errp, "%s: %s unable to parse lc_trscnt_first\n", __func__, - s->ot_id); - return; - } - - if (ot_common_parse_hexa_str((uint8_t *)last, s->lc_trscnt_last_xstr, - sizeof(last), false, true)) { - error_setg(errp, "%s: %s unable to parse lc_trscnt_last\n", __func__, - s->ot_id); - return; - } - - unsigned tix = 0; - - memset(s->lc_transitions[tix++], 0, sizeof(OtOTPTransitionValue)); - for (; tix < LC_TRANSITION_COUNT; tix++) { - uint16_t *lcval = s->lc_transitions[tix]; - memcpy(&lcval[0], &last[0], tix * sizeof(uint16_t)); - memcpy(&lcval[tix], &first[tix], - sizeof(OtOTPTransitionValue) - tix * sizeof(uint16_t)); - } - -#ifdef OT_OTP_DEBUG - qemu_log("%s: NEW %s\n", __func__, s->ot_id); - for (unsigned tix = 0; tix < LC_TRANSITION_COUNT; tix++) { - qemu_log("%s\n", ot_otp_hexdump(s->lc_transitions[tix], - LC_TRANSITION_CNT_SIZE)); - } -#endif /* OT_OTP_DEBUG */ -} - -static void ot_otp_dj_load(OtOTPDjState *s, Error **errp) +static void ot_otp_dj_load(OtOTPDjState *s) { /* * HEADER_FORMAT @@ -4031,25 +3713,26 @@ static void ot_otp_dj_load(OtOTPDjState *s, Error **errp) if (s->blk) { bool write = blk_supports_write_perm(s->blk); uint64_t perm = BLK_PERM_CONSISTENT_READ | (write ? BLK_PERM_WRITE : 0); - if (blk_set_perm(s->blk, perm, perm, errp)) { + if (blk_set_perm(s->blk, perm, perm, &error_fatal)) { warn_report("%s: OTP backend is R/O", __func__); write = false; } int rc = blk_pread(s->blk, 0, (int64_t)otp_size, otp->storage, 0); if (rc < 0) { - error_setg(errp, "failed to read the initial OTP content: %d", rc); + error_setg(&error_fatal, + "failed to read the initial OTP content: %d", rc); return; } const struct otp_header *otp_hdr = (const struct otp_header *)base; if (memcmp(otp_hdr->magic, "vOTP", sizeof(otp_hdr->magic)) != 0) { - error_setg(errp, "OTP file is not a valid OTP backend"); + error_setg(&error_fatal, "OTP file is not a valid OTP backend"); return; } if (otp_hdr->version != 1u && otp_hdr->version != 2u) { - error_setg(errp, "OTP file version %u is not supported", + error_setg(&error_fatal, "OTP file version %u is not supported", otp_hdr->version); return; } @@ -4105,10 +3788,6 @@ static Property ot_otp_dj_properties[] = { DEFINE_PROP_STRING("digest_iv", OtOTPDjState, digest_iv_xstr), DEFINE_PROP_STRING("sram_const", OtOTPDjState, sram_const_xstr), DEFINE_PROP_STRING("sram_iv", OtOTPDjState, sram_iv_xstr), - DEFINE_PROP_STRING("lc_state_first", OtOTPDjState, lc_state_first_xstr), - DEFINE_PROP_STRING("lc_state_last", OtOTPDjState, lc_state_last_xstr), - DEFINE_PROP_STRING("lc_trscnt_first", OtOTPDjState, lc_trscnt_first_xstr), - DEFINE_PROP_STRING("lc_trscnt_last", OtOTPDjState, lc_trscnt_last_xstr), DEFINE_PROP_END_OF_LIST(), }; @@ -4204,12 +3883,10 @@ static void ot_otp_dj_realize(DeviceState *dev, Error **errp) g_strdup(object_get_canonical_path_component(OBJECT(s)->parent)); } - ot_otp_dj_configure_scrmbl_key(s, &error_fatal); - ot_otp_dj_configure_digest(s, &error_fatal); - ot_otp_dj_configure_sram(s, &error_fatal); - ot_otp_dj_configure_lc_states(s, &error_fatal); - ot_otp_dj_configure_lc_transitions(s, &error_fatal); - ot_otp_dj_load(s, &error_fatal); + ot_otp_dj_configure_scrmbl_key(s); + ot_otp_dj_configure_digest(s); + ot_otp_dj_configure_sram(s); + ot_otp_dj_load(s); } static void ot_otp_dj_init(Object *obj) @@ -4261,8 +3938,6 @@ static void ot_otp_dj_init(Object *obj) s->keygen = g_new0(OtOTPKeyGen, 1u); s->otp = g_new0(OtOTPStorage, 1u); s->scrmbl_key_init = g_new0(OtOTPScrmblKeyInit, 1u); - s->lc_states = g_new0(OtOTPStateValue, LC_STATE_VALID_COUNT); - s->lc_transitions = g_new0(OtOTPTransitionValue, LC_TRANSITION_COUNT); for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { if (!OtOTPPartDescs[ix].buffered) { diff --git a/hw/opentitan/ot_otp_eg.c b/hw/opentitan/ot_otp_eg.c index b52c836156b0..c255bbcb5dce 100644 --- a/hw/opentitan/ot_otp_eg.c +++ b/hw/opentitan/ot_otp_eg.c @@ -46,6 +46,7 @@ #include "trace.h" #define NUM_ALERTS 5u +#define NUM_IRQS 2u /* clang-format off */ /* Core registers */ @@ -369,11 +370,7 @@ struct OtOTPEgState { MemoryRegion swcfg; } sub; } mmio; - struct { - uint32_t state; - unsigned tcount; - } lc; - IbexIRQ irqs[2u]; + IbexIRQ irqs[NUM_IRQS]; IbexIRQ alerts[NUM_ALERTS]; QEMUTimer *dai_delay; /**< Simulate delayed access completion */ @@ -403,8 +400,6 @@ static const OtOTPTokens OT_OTP_EG_TOKENS; #define OT_OTP_EG_PARTS /* NOLINTNEXTLINE */ #include "ot_otp_eg_parts.c" -/* NOLINTNEXTLINE */ -#include "ot_otp_eg_lcvalues.c" #define LC_TRANSITION_COUNT_MAX 24u #define LC_STATE_BIT_WIDTH 5u @@ -1005,28 +1000,6 @@ static void ot_otp_eg_swcfg_write(void *opaque, hwaddr addr, uint64_t value, addr, ot_otp_eg_swcfg_reg_name(reg)); } -static void ot_otp_eg_decode_lc_partition(OtOTPEgState *s) -{ - OtOTPStorage *otp = &s->otp; - s->lc.state = LC_ENCODE_STATE(LC_STATE_INVALID); - s->lc.tcount = LC_TRANSITION_COUNT_MAX + 1u; - for (unsigned ix = 0; ix < ARRAY_SIZE(lc_states); ix++) { - if (!memcmp(&otp->data[R_LC_STATE], lc_states[ix], LC_STATE_SIZE)) { - s->lc.state = LC_ENCODE_STATE(ix); - break; - } - } - for (unsigned ix = 0; ix < ARRAY_SIZE(lc_transition_cnts); ix++) { - if (!memcmp(&otp->data[R_LC_TRANSITION_CNT], lc_transition_cnts[ix], - LC_TRANSITION_CNT_SIZE)) { - s->lc.tcount = ix; - break; - } - } - trace_ot_otp_initial_lifecycle(s->ot_id, s->lc.tcount, s->lc.state, - LC_STATE_BITS(s->lc.state)); -} - static void ot_otp_eg_load_hw_cfg(OtOTPEgState *s) { OtOTPStorage *otp = &s->otp; @@ -1038,7 +1011,7 @@ static void ot_otp_eg_load_hw_cfg(OtOTPEgState *s) memcpy(hw_cfg->manuf_state, &otp->data[R_MANUF_STATE], sizeof(*hw_cfg->manuf_state)); uint32_t cfg = otp->data[R_HW_CFG_ENABLE]; - hw_cfg->soc_dbg_state = 0; + memset(hw_cfg->soc_dbg_state, 0, sizeof(hw_cfg->soc_dbg_state)); hw_cfg->en_sram_ifetch = (uint8_t)FIELD_EX32(cfg, HW_CFG_ENABLE, EN_SRAM_IFETCH); @@ -1051,24 +1024,27 @@ static void ot_otp_eg_load_hw_cfg(OtOTPEgState *s) } static void ot_otp_eg_ctrl_get_lc_info( - const OtOTPState *s, uint32_t *lc_state, unsigned *tcount, + const OtOTPState *s, uint16_t *lc_tcount, uint16_t *lc_state, uint8_t *lc_valid, uint8_t *secret_valid, const OtOTPTokens **tokens) { - OtOTPEgState *ds = OT_OTP_EG(s); + OtOTPEgState *es = OT_OTP_EG(s); + const OtOTPStorage *otp = &es->otp; - if (lc_state) { - *lc_state = ds->lc.state; + if (lc_tcount) { + memcpy(lc_tcount, &otp->data[R_LC_TRANSITION_CNT], + LC_TRANSITION_CNT_SIZE); } - if (tcount) { - *tcount = ds->lc.tcount; + if (lc_state) { + memcpy(lc_state, &otp->data[R_LC_STATE], LC_STATE_SIZE); } if (lc_valid) { /* dummy implementation, should check status of secret0, secret2 & LC */ *lc_valid = OT_MULTIBITBOOL_LC4_TRUE; } if (secret_valid) { + /* dummy implementation */ *secret_valid = - ot_otp_eg_swcfg_get_part_digest(ds, OTP_PART_SECRET2) != 0 ? + ot_otp_eg_swcfg_get_part_digest(es, OTP_PART_SECRET2) != 0 ? OT_MULTIBITBOOL_LC4_TRUE : OT_MULTIBITBOOL_LC4_FALSE; } @@ -1208,7 +1184,6 @@ static void ot_otp_eg_load(OtOTPEgState *s, Error **errp) otp->data_size = data_size; otp->ecc_size = ecc_size; - ot_otp_eg_decode_lc_partition(s); ot_otp_eg_load_hw_cfg(s); } diff --git a/hw/opentitan/ot_otp_eg_lcvalues.c b/hw/opentitan/ot_otp_eg_lcvalues.c deleted file mode 100644 index 53c3e5957629..000000000000 --- a/hw/opentitan/ot_otp_eg_lcvalues.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * QEMU OpenTitan EarlGrey One Time Programmable (OTP) life cycle values - * - * Copyright (c) 2023-2024 Rivos, Inc. - * - * Author(s): - * Emmanuel Blot - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "ot_lc_defs.h" - -/* Section auto-generated with otptool.py script */ - -/* clang-format off */ -/* NOLINTBEGIN */ -static const char lc_states[21u][40u] = { - [LC_STATE_RAW] = { - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u - }, - [LC_STATE_TESTUNLOCKED0] = { - 0xf2u, 0x9fu, 0x2eu, 0xb0u, 0x11u, 0xe2u, 0x90u, 0xc9u, 0x21u, 0x0fu, - 0xb1u, 0xd4u, 0x30u, 0x2bu, 0x32u, 0x3du, 0xb0u, 0xe8u, 0x1du, 0xf4u, - 0xa5u, 0x99u, 0x85u, 0xe4u, 0x77u, 0x49u, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTLOCKED0] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x11u, 0xe2u, 0x90u, 0xc9u, 0x21u, 0x0fu, - 0xb1u, 0xd4u, 0x30u, 0x2bu, 0x32u, 0x3du, 0xb0u, 0xe8u, 0x1du, 0xf4u, - 0xa5u, 0x99u, 0x85u, 0xe4u, 0x77u, 0x49u, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTUNLOCKED1] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0x90u, 0xc9u, 0x21u, 0x0fu, - 0xb1u, 0xd4u, 0x30u, 0x2bu, 0x32u, 0x3du, 0xb0u, 0xe8u, 0x1du, 0xf4u, - 0xa5u, 0x99u, 0x85u, 0xe4u, 0x77u, 0x49u, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTLOCKED1] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0x21u, 0x0fu, - 0xb1u, 0xd4u, 0x30u, 0x2bu, 0x32u, 0x3du, 0xb0u, 0xe8u, 0x1du, 0xf4u, - 0xa5u, 0x99u, 0x85u, 0xe4u, 0x77u, 0x49u, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTUNLOCKED2] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xb1u, 0xd4u, 0x30u, 0x2bu, 0x32u, 0x3du, 0xb0u, 0xe8u, 0x1du, 0xf4u, - 0xa5u, 0x99u, 0x85u, 0xe4u, 0x77u, 0x49u, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTLOCKED2] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x30u, 0x2bu, 0x32u, 0x3du, 0xb0u, 0xe8u, 0x1du, 0xf4u, - 0xa5u, 0x99u, 0x85u, 0xe4u, 0x77u, 0x49u, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTUNLOCKED3] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0x32u, 0x3du, 0xb0u, 0xe8u, 0x1du, 0xf4u, - 0xa5u, 0x99u, 0x85u, 0xe4u, 0x77u, 0x49u, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTLOCKED3] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xb0u, 0xe8u, 0x1du, 0xf4u, - 0xa5u, 0x99u, 0x85u, 0xe4u, 0x77u, 0x49u, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTUNLOCKED4] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xbau, 0xeeu, 0x1du, 0xf4u, - 0xa5u, 0x99u, 0x85u, 0xe4u, 0x77u, 0x49u, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTLOCKED4] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xbau, 0xeeu, 0xffu, 0xf4u, - 0xa5u, 0x99u, 0x85u, 0xe4u, 0x77u, 0x49u, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTUNLOCKED5] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xbau, 0xeeu, 0xffu, 0xf4u, - 0xa5u, 0xffu, 0x85u, 0xe4u, 0x77u, 0x49u, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTLOCKED5] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xbau, 0xeeu, 0xffu, 0xf4u, - 0xa5u, 0xffu, 0xefu, 0xe4u, 0x77u, 0x49u, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTUNLOCKED6] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xbau, 0xeeu, 0xffu, 0xf4u, - 0xa5u, 0xffu, 0xefu, 0xe4u, 0xffu, 0x4fu, 0x73u, 0x2cu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTLOCKED6] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xbau, 0xeeu, 0xffu, 0xf4u, - 0xa5u, 0xffu, 0xefu, 0xe4u, 0xffu, 0x4fu, 0x7fu, 0xbeu, 0x6cu, 0x91u, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_TESTUNLOCKED7] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xbau, 0xeeu, 0xffu, 0xf4u, - 0xa5u, 0xffu, 0xefu, 0xe4u, 0xffu, 0x4fu, 0x7fu, 0xbeu, 0xedu, 0x9du, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_DEV] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xbau, 0xeeu, 0xffu, 0xf4u, - 0xa5u, 0xffu, 0xefu, 0xe4u, 0xffu, 0x4fu, 0x7fu, 0xbeu, 0xedu, 0x9du, - 0xdfu, 0xf2u, 0x15u, 0xa6u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_PROD] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xbau, 0xeeu, 0xffu, 0xf4u, - 0xa5u, 0xffu, 0xefu, 0xe4u, 0xffu, 0x4fu, 0x7fu, 0xbeu, 0xedu, 0x9du, - 0x0du, 0x30u, 0x9du, 0xb7u, 0x2eu, 0x61u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_PRODEND] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xbau, 0xeeu, 0xffu, 0xf4u, - 0xa5u, 0xffu, 0xefu, 0xe4u, 0xffu, 0x4fu, 0x7fu, 0xbeu, 0xedu, 0x9du, - 0x0du, 0x30u, 0x15u, 0xa6u, 0x7eu, 0xe5u, 0xb0u, 0xc3u, 0x83u, 0xc1u - }, - [LC_STATE_RMA] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xbau, 0xeeu, 0xffu, 0xf4u, - 0xa5u, 0xffu, 0xefu, 0xe4u, 0xffu, 0x4fu, 0x7fu, 0xbeu, 0xedu, 0x9du, - 0xdfu, 0xf2u, 0x9du, 0xb7u, 0x2eu, 0x61u, 0xb7u, 0xd3u, 0xd7u, 0xe5u - }, - [LC_STATE_SCRAP] = { - 0xf2u, 0x9fu, 0x3fu, 0xb4u, 0x1fu, 0xe3u, 0xd2u, 0xfdu, 0xa7u, 0xafu, - 0xffu, 0xd6u, 0x76u, 0xabu, 0xb3u, 0xffu, 0xbau, 0xeeu, 0xffu, 0xf4u, - 0xa5u, 0xffu, 0xefu, 0xe4u, 0xffu, 0x4fu, 0x7fu, 0xbeu, 0xedu, 0x9du, - 0xdfu, 0xf2u, 0x9du, 0xb7u, 0x7eu, 0xe5u, 0xb7u, 0xd3u, 0xd7u, 0xe5u - }, -}; - -static const char lc_transition_cnts[25u][48u] = { - [0u] = { - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u - }, - [1u] = { - 0x3cu, 0xfcu, 0x83u, 0x21u, 0xc4u, 0xf8u, 0x18u, 0xacu, 0x4du, 0x53u, - 0xd2u, 0x44u, 0xa4u, 0xc4u, 0x63u, 0x1eu, 0x90u, 0x65u, 0x64u, 0x23u, - 0x00u, 0x4bu, 0x81u, 0xbau, 0xaau, 0x5bu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [2u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xc4u, 0xf8u, 0x18u, 0xacu, 0x4du, 0x53u, - 0xd2u, 0x44u, 0xa4u, 0xc4u, 0x63u, 0x1eu, 0x90u, 0x65u, 0x64u, 0x23u, - 0x00u, 0x4bu, 0x81u, 0xbau, 0xaau, 0x5bu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [3u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x18u, 0xacu, 0x4du, 0x53u, - 0xd2u, 0x44u, 0xa4u, 0xc4u, 0x63u, 0x1eu, 0x90u, 0x65u, 0x64u, 0x23u, - 0x00u, 0x4bu, 0x81u, 0xbau, 0xaau, 0x5bu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [4u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x4du, 0x53u, - 0xd2u, 0x44u, 0xa4u, 0xc4u, 0x63u, 0x1eu, 0x90u, 0x65u, 0x64u, 0x23u, - 0x00u, 0x4bu, 0x81u, 0xbau, 0xaau, 0x5bu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [5u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xd2u, 0x44u, 0xa4u, 0xc4u, 0x63u, 0x1eu, 0x90u, 0x65u, 0x64u, 0x23u, - 0x00u, 0x4bu, 0x81u, 0xbau, 0xaau, 0x5bu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [6u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xa4u, 0xc4u, 0x63u, 0x1eu, 0x90u, 0x65u, 0x64u, 0x23u, - 0x00u, 0x4bu, 0x81u, 0xbau, 0xaau, 0x5bu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [7u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x63u, 0x1eu, 0x90u, 0x65u, 0x64u, 0x23u, - 0x00u, 0x4bu, 0x81u, 0xbau, 0xaau, 0x5bu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [8u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0x90u, 0x65u, 0x64u, 0x23u, - 0x00u, 0x4bu, 0x81u, 0xbau, 0xaau, 0x5bu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [9u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x64u, 0x23u, - 0x00u, 0x4bu, 0x81u, 0xbau, 0xaau, 0x5bu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [10u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x00u, 0x4bu, 0x81u, 0xbau, 0xaau, 0x5bu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [11u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0x81u, 0xbau, 0xaau, 0x5bu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [12u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xaau, 0x5bu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [13u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xbfu, 0x5fu, 0x69u, 0x2cu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [14u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xbfu, 0x5fu, 0xe9u, 0x6eu, 0x13u, 0xf2u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [15u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xbfu, 0x5fu, 0xe9u, 0x6eu, 0x77u, 0xf3u, - 0xf2u, 0x1du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [16u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xbfu, 0x5fu, 0xe9u, 0x6eu, 0x77u, 0xf3u, - 0xf3u, 0x5du, 0x60u, 0x9bu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [17u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xbfu, 0x5fu, 0xe9u, 0x6eu, 0x77u, 0xf3u, - 0xf3u, 0x5du, 0x6fu, 0x9fu, 0x68u, 0x5eu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [18u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xbfu, 0x5fu, 0xe9u, 0x6eu, 0x77u, 0xf3u, - 0xf3u, 0x5du, 0x6fu, 0x9fu, 0x68u, 0xffu, 0xc4u, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [19u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xbfu, 0x5fu, 0xe9u, 0x6eu, 0x77u, 0xf3u, - 0xf3u, 0x5du, 0x6fu, 0x9fu, 0x68u, 0xffu, 0xdeu, 0x5du, 0x05u, 0x04u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [20u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xbfu, 0x5fu, 0xe9u, 0x6eu, 0x77u, 0xf3u, - 0xf3u, 0x5du, 0x6fu, 0x9fu, 0x68u, 0xffu, 0xdeu, 0x5du, 0x55u, 0x64u, - 0x28u, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [21u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xbfu, 0x5fu, 0xe9u, 0x6eu, 0x77u, 0xf3u, - 0xf3u, 0x5du, 0x6fu, 0x9fu, 0x68u, 0xffu, 0xdeu, 0x5du, 0x55u, 0x64u, - 0xbeu, 0x76u, 0xe8u, 0x62u, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [22u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xbfu, 0x5fu, 0xe9u, 0x6eu, 0x77u, 0xf3u, - 0xf3u, 0x5du, 0x6fu, 0x9fu, 0x68u, 0xffu, 0xdeu, 0x5du, 0x55u, 0x64u, - 0xbeu, 0x76u, 0xfdu, 0x6bu, 0x8au, 0x8bu, 0x0du, 0xd0u - }, - [23u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xbfu, 0x5fu, 0xe9u, 0x6eu, 0x77u, 0xf3u, - 0xf3u, 0x5du, 0x6fu, 0x9fu, 0x68u, 0xffu, 0xdeu, 0x5du, 0x55u, 0x64u, - 0xbeu, 0x76u, 0xfdu, 0x6bu, 0xfbu, 0x8fu, 0x0du, 0xd0u - }, - [24u] = { - 0x3cu, 0xfcu, 0xfbu, 0x23u, 0xeeu, 0xf9u, 0x9fu, 0xadu, 0x6fu, 0x7fu, - 0xfbu, 0x44u, 0xe6u, 0xceu, 0x7bu, 0x5eu, 0xd4u, 0x77u, 0x67u, 0xe7u, - 0x53u, 0xcbu, 0xabu, 0xfeu, 0xbfu, 0x5fu, 0xe9u, 0x6eu, 0x77u, 0xf3u, - 0xf3u, 0x5du, 0x6fu, 0x9fu, 0x68u, 0xffu, 0xdeu, 0x5du, 0x55u, 0x64u, - 0xbeu, 0x76u, 0xfdu, 0x6bu, 0xfbu, 0x8fu, 0xcdu, 0xfbu - }, -}; -/* NOLINTEND */ -/* clang-format on */ - -/* End of auto-generated section */ diff --git a/hw/opentitan/trace-events b/hw/opentitan/trace-events index 3b6c25c59e98..2ceb5516e21d 100644 --- a/hw/opentitan/trace-events +++ b/hw/opentitan/trace-events @@ -254,6 +254,7 @@ ot_lc_ctrl_error(const char * id, const char *msg) "%s: %s" ot_lc_ctrl_escalate(const char * id, const char *fsm, const char *lc) "%s: %s: %s" ot_lc_ctrl_escalate_rx(const char * id, unsigned line, bool level) "%s: %u: %u" ot_lc_ctrl_info(const char * id, const char *msg) "%s: %s" +ot_lc_ctrl_initial_lifecycle(const char * id, unsigned tcount, uint32_t lc_state, unsigned stix) "%s: transcount %u, lifecyle 0x%x [%u]" ot_lc_ctrl_initialize(const char * id, const char *cst, int cstix, unsigned tcount, const char *state, int six) "%s: %s (%d), tcount %u, state %s (%u)" ot_lc_ctrl_io_read_out(const char * id, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "%s: addr=0x%02x (%s), val=0x%x, pc=0x%x" ot_lc_ctrl_io_read_out_repeat(const char * id, uint32_t addr, const char * regname, unsigned count, uint32_t val) "%s: addr=0x%02x (%s) repeated %u times, val=0x%x" @@ -265,6 +266,7 @@ ot_lc_ctrl_reset(const char * id) "%s: " ot_lc_ctrl_start_transition(const char * id, const char *sr, const char *kind, const char *cst, int cstix, const char *tst, int tstix, unsigned tcount) "%s: %s start %s transit from %s (%d) to %s (%d) at tcount %u" ot_lc_ctrl_token_missing(const char * id, const char *token) "%s: %s" ot_lc_ctrl_transit_request(const char * id, const char *sr, const char *cst, int cstix, const char *tst, int tstix, const char *tk, int tkix) "%s: %s req. transit from %s (%d) to %s (%d) with token %s (%d)" +ot_lc_ctrl_transition_missing(const char *id, const char *cfg, const char *st) "%s: %s_%s" ot_lc_ctrl_update_broadcast(const char * id, const char *st, const char *bcast, bool olvl, bool nlvl) "%s: %s: %s %u -> %u" # ot_mbx.c @@ -310,7 +312,6 @@ ot_otp_ecc_mismatch(const char * id, unsigned address, uint32_t secc, uint32_t l ot_otp_ecc_parity_error(const char * id, uint32_t d_i, uint32_t ecc) "%s: 0x%04x, ECC 0x%02x" ot_otp_ecc_recovered_error(const char * id, uint32_t d_i, uint32_t d_o) "%s: 0x%04x -> 0x%04x" ot_otp_ecc_unrecoverable_error(const char * id, uint32_t d_i) "%s: 0x%04x" -ot_otp_initial_lifecycle(const char * id, unsigned tcount, uint32_t lc_state, unsigned stix) "%s: transcount %u, lifecyle 0x%x [%u]" ot_otp_initialize(const char * id) "%s" ot_otp_integrity_report(const char * id, const char* part, unsigned pix, const char *msg) "%s: partition %s (#%u) %s" ot_otp_io_reg_read_out(const char * id, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "%s: addr=0x%02x (%s), val=0x%x, pc=0x%x" @@ -318,7 +319,6 @@ ot_otp_io_reg_write(const char * id, uint32_t addr, const char * regname, uint32 ot_otp_io_swcfg_read_out(const char * id, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "%s: addr=0x%02x (%s), val=0x%x, pc=0x%x" ot_otp_keygen_entropy(const char * id, unsigned slot, bool resched) "%s: %u slots, resched: %u" ot_otp_lc_broadcast(const char * id, unsigned sig, bool level) "%s: bcast %u, level %u" -ot_otp_lc_info(const char * id, unsigned st, unsigned tc, bool secret0, bool secret2, bool lc) "%s: st:%u tc:%u s0:%u s1:%u lc:%u" ot_otp_lci_change_state(const char * id, int line, const char *old, int nold, const char *new, int nnew) "%s: @ %d [%s:%d] -> [%s:%d]" ot_otp_lci_write(const char * id, unsigned pos, uint16_t cval, uint16_t nval) "%s: @ %u 0x%04x -> 0x%04x" ot_otp_lci_write_ecc(const char * id, unsigned pos, uint8_t cval, uint8_t nval) "%s: @ %u 0x%02x -> 0x%02x" diff --git a/hw/riscv/dm.c b/hw/riscv/dm.c index 2accc7483c05..56230bba99cf 100644 --- a/hw/riscv/dm.c +++ b/hw/riscv/dm.c @@ -319,6 +319,7 @@ typedef struct RISCVDMConfig { uint16_t resume_offset; bool sysbus_access; bool abstractauto; + bool enable; } RISCVDMConfig; /** Debug Module */ @@ -681,6 +682,13 @@ static uint32_t riscv_dm_read_value(RISCVDebugDeviceState *dev) return value; } +static void riscv_dm_set_next_dm(RISCVDebugDeviceState *dev, uint32_t addr) +{ + RISCVDMState *dm = RISCV_DM(dev); + + dm->regs[A_NEXTDM] = addr; +} + /* -------------------------------------------------------------------------- */ /* DM implementation */ /* -------------------------------------------------------------------------- */ @@ -2554,6 +2562,7 @@ static Property riscv_dm_properties[] = { DEFINE_PROP_UINT64("mta_dm", RISCVDMState, cfg.mta_dm, RISCVDM_DEFAULT_MTA), DEFINE_PROP_UINT64("mta_sba", RISCVDMState, cfg.mta_sba, RISCVDM_DEFAULT_MTA), + DEFINE_PROP_BOOL("enable", RISCVDMState, cfg.enable, true), DEFINE_PROP_END_OF_LIST(), }; @@ -2562,8 +2571,10 @@ static void riscv_dm_reset(DeviceState *dev) RISCVDMState *dm = RISCV_DM(dev); g_assert(dm->dtm != NULL); - dm->dtm_ok = riscv_dtm_register_dm(DEVICE(dm->dtm), RISCV_DEBUG_DEVICE(dev), - dm->cfg.dmi_addr, DM_REG_COUNT); + RISCVDTMClass *dtmc = RISCV_DTM_GET_CLASS(OBJECT(dm->dtm)); + dm->dtm_ok = + (*dtmc->register_dm)(DEVICE(dm->dtm), RISCV_DEBUG_DEVICE(dev), + dm->cfg.dmi_addr, DM_REG_COUNT, dm->cfg.enable); for (unsigned ix = 0; ix < DM_REG_COUNT; ix++) { if (ix != A_NEXTDM) { @@ -2626,6 +2637,7 @@ static void riscv_dm_class_init(ObjectClass *klass, void *data) dmc->write_rq = &riscv_dm_write_rq; dmc->read_rq = &riscv_dm_read_rq; dmc->read_value = &riscv_dm_read_value; + dmc->set_next_dm = &riscv_dm_set_next_dm; /* * unfortunately, MemTxtAttrs is a bitfield and there is no built-time way diff --git a/hw/riscv/dtm.c b/hw/riscv/dtm.c index cf9a4e417d18..b52d74f9e4eb 100644 --- a/hw/riscv/dtm.c +++ b/hw/riscv/dtm.c @@ -50,10 +50,6 @@ #include "sysemu/runstate.h" #include "trace.h" -/* - * Register definitions - */ - /* clang-format off */ /* Debug Module Interface and Control */ @@ -69,6 +65,8 @@ REG64(DMI, 0x11u) FIELD(DMI, DATA, 2u, 32u) FIELD(DMI, ADDRESS, 34u, 64u-34u) /* real width is a runtime property */ +/* clang-format on */ + #define xtrace_riscv_dtm_error(_msg_) \ trace_riscv_dtm_error(__func__, __LINE__, _msg_) #define xtrace_riscv_dtm_info(_msg_, _val_) \ @@ -91,8 +89,10 @@ typedef struct RISCVDebugModule { QLIST_ENTRY(RISCVDebugModule) entry; RISCVDebugDeviceState *dev; RISCVDebugDeviceClass *dc; + char *path; uint32_t base; uint32_t size; + bool enabled; } RISCVDebugModule; /** Debug Module Interface */ @@ -111,26 +111,19 @@ struct RISCVDTMState { unsigned abits; /* address bit count */ }; -/* - * Forward declarations - */ - static void riscv_dtm_reset(DeviceState *dev); -static RISCVDebugModule* riscv_dtm_get_dm(RISCVDTMState *s, uint32_t addr); +static RISCVDebugModule *riscv_dtm_get_dm(RISCVDTMState *s, uint32_t addr); static void riscv_dtm_sort_dms(RISCVDTMState *s); +static void riscv_dtm_activate_dms(RISCVDTMState *s); static void riscv_dtm_tap_dtmcs_capture(TapDataHandler *tdh); static void riscv_dtm_tap_dtmcs_update(TapDataHandler *tdh); static void riscv_dtm_tap_dmi_capture(TapDataHandler *tdh); static void riscv_dtm_tap_dmi_update(TapDataHandler *tdh); -/* - * Constants - */ - -#define RISCV_DEBUG_DMI_VERSION 1u /* RISC-V Debug spec 0.13.x & 1.0 */ -#define RISCVDMI_DTMCS_IR 0x10u -#define RISCVDMI_DMI_IR 0x11u +#define RISCV_DEBUG_DMI_VERSION 1u /* RISC-V Debug spec 0.13.x & 1.0 */ +#define RISCVDMI_DTMCS_IR 0x10u +#define RISCVDMI_DMI_IR 0x11u static const TapDataHandler RISCVDMI_DTMCS = { .name = "dtmcs", @@ -177,11 +170,12 @@ static const char *RISCVDMI_RUNSTATE_NAMES[] = { "?") /* -------------------------------------------------------------------------- */ -/* Public API */ +/* DTM API */ /* -------------------------------------------------------------------------- */ -bool riscv_dtm_register_dm(DeviceState *dev, RISCVDebugDeviceState *dbgdev, - hwaddr base_addr, hwaddr size) +static bool riscv_dtm_register_dm(DeviceState *dev, + RISCVDebugDeviceState *dbgdev, + hwaddr base_addr, hwaddr size, bool enable) { RISCVDTMState *s = RISCV_DTM(dev); @@ -230,18 +224,48 @@ bool riscv_dtm_register_dm(DeviceState *dev, RISCVDebugDeviceState *dbgdev, dm->dc = RISCV_DEBUG_DEVICE_GET_CLASS(OBJECT(dbgdev)); dm->base = base_addr; dm->size = size; + dm->enabled = enable; + dm->path = + g_strdup_printf("%s/%s", + object_get_canonical_path_component( + OBJECT(dbgdev)->parent), + object_get_canonical_path_component(OBJECT(dbgdev))); QLIST_INSERT_HEAD(&s->dms, dm, entry); s->last_dm = dm; - trace_riscv_dtm_register_dm(count, base_addr, base_addr + size - 1u, - tap_ok); + trace_riscv_dtm_register_dm(dm->path, count, base_addr, + base_addr + size - 1u, enable, tap_ok); riscv_dtm_sort_dms(s); + riscv_dtm_activate_dms(s); return tap_ok; } +static void riscv_dtm_enable_dm(DeviceState *dev, RISCVDebugDeviceState *dbgdev, + bool enable) +{ + RISCVDTMState *s = RISCV_DTM(dev); + + RISCVDebugModule *node; + bool update = false; + QLIST_FOREACH(node, &s->dms, entry) { + if (node->dev == dbgdev) { + update = node->enabled != enable; + node->enabled = enable; + trace_riscv_dtm_enable_dm(object_get_canonical_path_component( + OBJECT(dbgdev)), + enable, update); + break; + } + } + + if (update) { + riscv_dtm_activate_dms(s); + } +} + /* -------------------------------------------------------------------------- */ /* DTMCS/DMI implementation */ /* -------------------------------------------------------------------------- */ @@ -454,6 +478,40 @@ static void riscv_dtm_sort_dms(RISCVDTMState *s) g_free(dma); } +static void riscv_dtm_update_next_dm(RISCVDebugModule *dm, + const RISCVDebugModule *next_dm) +{ + if (dm->dc->set_next_dm) { + uint32_t next_addr = next_dm ? next_dm->base : 0u; + trace_riscv_dtm_set_next_dm(dm->path, dm->base, + next_dm ? next_dm->path : "end", next_addr); + (*dm->dc->set_next_dm)(dm->dev, next_addr); + } +} + +static void riscv_dtm_activate_dms(RISCVDTMState *s) +{ + RISCVDebugModule *dm; + RISCVDebugModule *prev_dm = NULL; + QLIST_FOREACH(dm, &s->dms, entry) { + /* + * devices that do not implement set_next_dm are not part of the next_dm + * chain and therefore ignored + */ + if (dm->enabled && dm->dc->set_next_dm) { + /* do not bother updating a disabled DM */ + if (prev_dm && prev_dm->enabled) { + riscv_dtm_update_next_dm(prev_dm, dm); + } + prev_dm = dm; + } + } + + if (prev_dm) { + riscv_dtm_update_next_dm(prev_dm, NULL); + } +} + static Property riscv_dtm_properties[] = { DEFINE_PROP_UINT32("abits", RISCVDTMState, abits, 0x7u), DEFINE_PROP_LINK("tap_ctrl", RISCVDTMState, tap_ctrl, TYPE_DEVICE, @@ -499,6 +557,10 @@ static void riscv_dtm_class_init(ObjectClass *klass, void *data) dc->realize = &riscv_dtm_realize; device_class_set_props(dc, riscv_dtm_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); + + RISCVDTMClass *dmc = RISCV_DTM_CLASS(klass); + dmc->register_dm = &riscv_dtm_register_dm; + dmc->enable_dm = &riscv_dtm_enable_dm; } static const TypeInfo riscv_dtm_info = { @@ -507,6 +569,7 @@ static const TypeInfo riscv_dtm_info = { .instance_size = sizeof(RISCVDTMState), .instance_init = &riscv_dtm_init, .class_init = &riscv_dtm_class_init, + .class_size = sizeof(RISCVDTMClass), }; static void riscv_dtm_register_types(void) diff --git a/hw/riscv/ibex_common.c b/hw/riscv/ibex_common.c index b2eefbe84df4..df4bc9caa6cb 100644 --- a/hw/riscv/ibex_common.c +++ b/hw/riscv/ibex_common.c @@ -41,6 +41,7 @@ #include "hw/riscv/ibex_common.h" #include "monitor/monitor.h" #include "sysemu/runstate.h" +#include "trace.h" static void rust_demangle_fn(const char *st_name, int st_info, uint64_t st_value, uint64_t st_size); @@ -63,7 +64,10 @@ DeviceState **ibex_create_devices(const IbexDeviceDef *defs, unsigned count, DeviceState *parent) { DeviceState **devices = g_new0(DeviceState *, count); - unsigned unimp_count = 0; + GHashTable *chtable = + g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); + const char *pname = object_get_typename(OBJECT(parent)); + for (unsigned idx = 0; idx < count; idx++) { const IbexDeviceDef *def = &defs[idx]; if (!def->type) { @@ -72,21 +76,35 @@ DeviceState **ibex_create_devices(const IbexDeviceDef *defs, unsigned count, } devices[idx] = qdev_new(def->type); - char *name; + const char *tname; if (!strcmp(def->type, TYPE_UNIMPLEMENTED_DEVICE)) { - if (def->name) { - name = g_strdup_printf("%s[%u]", def->name, def->instance); + tname = def->name ? def->name : TYPE_UNIMPLEMENTED_DEVICE; + } else { + tname = def->type; + } + + char *name; + if (!IBEX_HAS_INSTANCE_NUM(def)) { + gpointer sibling = g_hash_table_lookup(chtable, (gpointer)tname); + unsigned *chcount; + if (!sibling) { + chcount = g_new(unsigned, 1u); + *chcount = 0; + g_hash_table_insert(chtable, (gpointer)tname, + (gpointer)chcount); } else { - name = g_strdup_printf(TYPE_UNIMPLEMENTED_DEVICE "[%u]", - unimp_count); + chcount = (unsigned *)sibling; + *chcount = (*chcount) + 1u; } - unimp_count += 1u; + name = g_strdup_printf("%s.%u", tname, *chcount); } else { - name = g_strdup_printf("%s[%u]", def->type, def->instance); + name = g_strdup_printf("%s[%u]", tname, IBEX_GET_INSTANCE_NUM(def)); } + trace_ibex_create_device(pname, name); object_property_add_child(OBJECT(parent), name, OBJECT(devices[idx])); g_free(name); } + g_hash_table_destroy(chtable); return devices; } @@ -279,7 +297,14 @@ void ibex_map_devices_ext_mask_offset( g_assert(def->type); g_assert(def->memmap); - char *name = g_strdup_printf("%s[%u]", def->type, def->instance); + if (!IBEX_HAS_INSTANCE_NUM(def)) { + error_setg(&error_fatal, "Device %s @ %u instance is not known", + def->type, ix); + return; + } + + char *name = + g_strdup_printf("%s[%u]", def->type, IBEX_GET_INSTANCE_NUM(def)); Object *child; child = object_property_get_link(OBJECT(dev), name, &error_fatal); SysBusDevice *sdev; diff --git a/hw/riscv/ot_darjeeling.c b/hw/riscv/ot_darjeeling.c index af5f5c607d4f..d2e630953395 100644 --- a/hw/riscv/ot_darjeeling.c +++ b/hw/riscv/ot_darjeeling.c @@ -114,8 +114,8 @@ enum OtDjSocDevice { OT_DJ_SOC_DEV_AST, OT_DJ_SOC_DEV_CLKMGR, OT_DJ_SOC_DEV_CSRNG, - OT_DJ_SOC_DEV_DM_TL_LC_CTRL, - OT_DJ_SOC_DEV_DM_TL_MBX, + OT_DJ_SOC_DEV_DM_MBX, + OT_DJ_SOC_DEV_DM_LC_CTRL, OT_DJ_SOC_DEV_DM, OT_DJ_SOC_DEV_DMA, OT_DJ_SOC_DEV_DTM, @@ -287,12 +287,11 @@ enum OtDjPinmuxMioOut { #define OT_DJ_CTN_RAM_SIZE (2u << 20u) /* DEBUG address space */ -#define OT_DJ_DEBUG_RV_DM_ADDR 0x0u -#define OT_DJ_DEBUG_MBX_JTAG_ADDR 0x2200u -#define OT_DJ_DEBUG_SOCDBG_CTRL_ADDR 0x2300u -#define OT_DJ_DEBUG_LC_CTRL_ADDR 0x3000u -#define OT_DJ_DEBUG_LC_CTRL_SIZE 0x400u -#define OT_DJ_DBG_XBAR_SIZE 0x4000u +#define OT_DJ_DEBUG_RV_DM_ADDR 0x0u +#define OT_DJ_DEBUG_MBX_JTAG_ADDR 0x2200u +#define OT_DJ_DEBUG_LC_CTRL_ADDR 0x3000u +#define OT_DJ_DEBUG_LC_CTRL_SIZE 0x400u +#define OT_DJ_DBG_XBAR_SIZE 0x4000u #define OT_DJ_PERIPHERAL_CLK_HZ 250000000u /* 250 MHz */ #define OT_DJ_AON_CLK_HZ 62500000u /* 62.5 MHz */ @@ -408,7 +407,7 @@ static const uint32_t ot_dj_pmp_addrs[] = { OT_DJ_SOC_SIGNAL(_rsp_##_RSP, 0, _tgt_, _rsp_##_RSP, 0) #define OT_DJ_SOC_DEV_MBX(_ix_, _addr_, _asname_, _irq_, _alert_) \ - .type = TYPE_OT_MBX, .instance = (_ix_), \ + .type = TYPE_OT_MBX, .instance = IBEX_MAKE_INSTANCE_NUM(_ix_), \ .memmap = MEMMAPENTRIES({ .base = (_addr_) }), \ .gpio = IBEXGPIOCONNDEFS(OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, (_irq_)), \ OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, (_irq_) + 1u), \ @@ -420,7 +419,7 @@ static const uint32_t ot_dj_pmp_addrs[] = { #define OT_DJ_SOC_DEV_MBX_DUAL(_ix_, _addr_, _asname_, _irq_, _alert_, \ _xaddr_) \ - .type = TYPE_OT_MBX, .instance = (_ix_), \ + .type = TYPE_OT_MBX, .instance = IBEX_MAKE_INSTANCE_NUM(_ix_), \ .memmap = MEMMAPENTRIES({ .base = (_addr_) }, { .base = (_xaddr_) }), \ .gpio = IBEXGPIOCONNDEFS(OT_DJ_SOC_GPIO_SYSBUS_IRQ(0, PLIC, (_irq_)), \ OT_DJ_SOC_GPIO_SYSBUS_IRQ(1, PLIC, (_irq_) + 1u), \ @@ -541,31 +540,29 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { IBEX_DEV_BOOL_PROP("abstractauto", true) ), }, - [OT_DJ_SOC_DEV_DM_TL_LC_CTRL] = { + [OT_DJ_SOC_DEV_DM_MBX] = { .type = TYPE_OT_DM_TL, - .instance = 0, .link = IBEXDEVICELINKDEFS( OT_DJ_SOC_DEVLINK("dtm", DTM), - OT_DJ_SOC_DEVLINK("tl_dev", LC_CTRL) + OT_DJ_SOC_DEVLINK("tl_dev", MBX_JTAG) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("dmi_addr", OT_DJ_DEBUG_LC_CTRL_DMI_ADDR), - IBEX_DEV_UINT_PROP("dmi_size", OT_DJ_DEBUG_LC_CTRL_DMI_SIZE), - IBEX_DEV_UINT_PROP("tl_addr", OT_DJ_DEBUG_LC_CTRL_ADDR), + IBEX_DEV_UINT_PROP("dmi_addr", OT_DJ_DEBUG_MBX_JTAG_DMI_ADDR), + IBEX_DEV_UINT_PROP("dmi_size", OT_DJ_DEBUG_MBX_JTAG_DMI_SIZE), + IBEX_DEV_UINT_PROP("tl_addr", OT_DJ_DEBUG_MBX_JTAG_ADDR), IBEX_DEV_STRING_PROP("tl_as_name", "ot-dbg") ) }, - [OT_DJ_SOC_DEV_DM_TL_MBX] = { + [OT_DJ_SOC_DEV_DM_LC_CTRL] = { .type = TYPE_OT_DM_TL, - .instance = 1, .link = IBEXDEVICELINKDEFS( OT_DJ_SOC_DEVLINK("dtm", DTM), - OT_DJ_SOC_DEVLINK("tl_dev", MBX_JTAG) + OT_DJ_SOC_DEVLINK("tl_dev", LC_CTRL) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("dmi_addr", OT_DJ_DEBUG_MBX_JTAG_DMI_ADDR), - IBEX_DEV_UINT_PROP("dmi_size", OT_DJ_DEBUG_MBX_JTAG_DMI_SIZE), - IBEX_DEV_UINT_PROP("tl_addr", OT_DJ_DEBUG_MBX_JTAG_ADDR), + IBEX_DEV_UINT_PROP("dmi_addr", OT_DJ_DEBUG_LC_CTRL_DMI_ADDR), + IBEX_DEV_UINT_PROP("dmi_size", OT_DJ_DEBUG_LC_CTRL_DMI_SIZE), + IBEX_DEV_UINT_PROP("tl_addr", OT_DJ_DEBUG_LC_CTRL_ADDR), IBEX_DEV_STRING_PROP("tl_as_name", "ot-dbg") ) }, @@ -670,7 +667,6 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { }, [OT_DJ_SOC_DEV_EDN0] = { .type = TYPE_OT_EDN, - .instance = 0, .memmap = MEMMAPENTRIES( { .base = 0x21170000u } ), @@ -689,7 +685,6 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { }, [OT_DJ_SOC_DEV_EDN1] = { .type = TYPE_OT_EDN, - .instance = 1, .memmap = MEMMAPENTRIES( { .base = 0x21180000u } ), @@ -708,7 +703,6 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { }, [OT_DJ_SOC_DEV_SRAM_MAIN] = { .type = TYPE_OT_SRAM_CTRL, - .instance = 0, .memmap = MEMMAPENTRIES( { .base = 0x211c0000u }, { 0x10000000u } @@ -726,7 +720,6 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { }, [OT_DJ_SOC_DEV_SRAM_MBX] = { .type = TYPE_OT_SRAM_CTRL, - .instance = 1, .memmap = MEMMAPENTRIES( { .base = 0x211d0000u }, { 0x11000000u } @@ -744,7 +737,6 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { }, [OT_DJ_SOC_DEV_ROM0] = { .type = TYPE_OT_ROM_CTRL, - .instance = 0, .memmap = MEMMAPENTRIES( { .base = 0x211e0000u }, { 0x00008000u } @@ -769,7 +761,6 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { }, [OT_DJ_SOC_DEV_ROM1] = { .type = TYPE_OT_ROM_CTRL, - .instance = 1, .memmap = MEMMAPENTRIES( { .base = 0x211e1000u }, { 0x00020000u } @@ -1021,7 +1012,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { [OT_DJ_SOC_DEV_UART0] = { .type = TYPE_OT_UART, .cfg = &ot_dj_soc_uart_configure, - .instance = 0, + .instance = IBEX_MAKE_INSTANCE_NUM(0), .memmap = MEMMAPENTRIES( { .base = 0x30010000u } ), @@ -1052,7 +1043,6 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { }, [OT_DJ_SOC_DEV_I2C0] = { .type = TYPE_OT_I2C_DJ, - .instance = 0, .memmap = MEMMAPENTRIES( { .base = 0x30080000u } ), @@ -1124,19 +1114,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { IBEX_DEV_STRING_PROP("sram_const", "63b9485a3856c417cf7a50a9a91ef7f7"), IBEX_DEV_STRING_PROP("sram_iv", - "bee3958332f2939b"), - IBEX_DEV_STRING_PROP("lc_state_first", - "ee75b407d2314d2ef84185ac8c990f536071632c" - "086d4c924070be92d2948d6228b2711e9b2d8c4d"), - IBEX_DEV_STRING_PROP("lc_state_last", - "ee75fe0ffe7b6f3ffc5f9ffd9ff96fdb7f736f6c" - "9e6fdcd35277fef2d3bdcd6ffbb2f59fdf3fbedd"), - IBEX_DEV_STRING_PROP("lc_trscnt_first", - "dfb6c45a241f85ce9f42229e8627462fdb02c6701242f14b" - "41891180045c09c26c52744267c04aa055921b9461bb07da"), - IBEX_DEV_STRING_PROP("lc_trscnt_last", - "dfb6f4fabf1fefcebf5ba2ffc677c6afdbabcefeb672f36b" - "4fbdb3988dfe1be67e7e77ca77c76af7ddde3b9e7fbfe7de") + "bee3958332f2939b") ), }, [OT_DJ_SOC_DEV_OTP_BACKEND] = { @@ -1191,7 +1169,19 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { IBEX_DEV_BOOL_PROP("volatile_raw_unlock", true), IBEX_DEV_UINT_PROP("kmac-app", 1u), IBEX_DEV_STRING_PROP("raw_unlock_token", - "ea2b3f32cbe77554e43c8ea7ebf197c2") + "ea2b3f32cbe77554e43c8ea7ebf197c2"), + IBEX_DEV_STRING_PROP("lc_state_first", + "ee75b407d2314d2ef84185ac8c990f536071632c" + "086d4c924070be92d2948d6228b2711e9b2d8c4d"), + IBEX_DEV_STRING_PROP("lc_state_last", + "ee75fe0ffe7b6f3ffc5f9ffd9ff96fdb7f736f6c" + "9e6fdcd35277fef2d3bdcd6ffbb2f59fdf3fbedd"), + IBEX_DEV_STRING_PROP("lc_trscnt_first", + "dfb6c45a241f85ce9f42229e8627462fdb02c6701242f14b" + "41891180045c09c26c52744267c04aa055921b9461bb07da"), + IBEX_DEV_STRING_PROP("lc_trscnt_last", + "dfb6f4fabf1fefcebf5ba2ffc677c6afdbabcefeb672f36b" + "4fbdb3988dfe1be67e7e77ca77c76af7ddde3b9e7fbfe7de") ) }, [OT_DJ_SOC_DEV_ALERT_HANDLER] = { @@ -1222,7 +1212,6 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { }, [OT_DJ_SOC_DEV_SPI_HOST0] = { .type = TYPE_OT_SPI_HOST, - .instance = 0, .memmap = MEMMAPENTRIES( { .base = 0x30300000u } ), @@ -1368,7 +1357,6 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { }, [OT_DJ_SOC_DEV_SRAM_RET] = { .type = TYPE_OT_SRAM_CTRL, - .instance = 2, .memmap = MEMMAPENTRIES( { .base = 0x30500000u }, { .base = 0x30600000u } @@ -1387,14 +1375,12 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { /* IRQ splitters */ [OT_DJ_SOC_SPLITTER_LC_HW_DEBUG] = { .type = TYPE_SPLIT_IRQ, - .instance = 0, .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("num-lines", 1u) // to be changed ) }, [OT_DJ_SOC_SPLITTER_LC_ESCALATE] = { .type = TYPE_SPLIT_IRQ, - .instance = 1, .gpio = IBEXGPIOCONNDEFS( OT_DJ_SOC_S2D(0, OTP_CTRL, OT_LC_BROADCAST, OT_OTP_LC_ESCALATE_EN) @@ -1539,7 +1525,7 @@ static void ot_dj_soc_uart_configure(DeviceState *dev, const IbexDeviceDef *def, { (void)def; (void)parent; - qdev_prop_set_chr(dev, "chardev", serial_hd(def->instance)); + qdev_prop_set_chr(dev, "chardev", serial_hd(IBEX_GET_INSTANCE_NUM(def))); } /* ------------------------------------------------------------------------ */ @@ -1573,8 +1559,8 @@ static void ot_dj_soc_reset_hold(Object *obj, ResetType type) resettable_reset(dmi, type); // TODO: not sure where Reset is plugged here... - resettable_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_DM_TL_LC_CTRL]), type); - resettable_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_DM_TL_MBX]), type); + resettable_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_DM_LC_CTRL]), type); + resettable_reset(OBJECT(s->devices[OT_DJ_SOC_DEV_DM_MBX]), type); Object *dm = OBJECT(s->devices[OT_DJ_SOC_DEV_DM]); resettable_reset(dm, type); diff --git a/hw/riscv/ot_earlgrey.c b/hw/riscv/ot_earlgrey.c index ba0d7a08aa83..287f5c1604fd 100644 --- a/hw/riscv/ot_earlgrey.c +++ b/hw/riscv/ot_earlgrey.c @@ -327,7 +327,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { [OT_EG_SOC_DEV_UART0] = { .type = TYPE_OT_UART, .cfg = &ot_eg_soc_uart_configure, - .instance = 0, + .instance = IBEX_MAKE_INSTANCE_NUM(0), .memmap = MEMMAPENTRIES( { .base = 0x40000000u } ), @@ -348,7 +348,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { [OT_EG_SOC_DEV_UART1] = { .type = TYPE_OT_UART, .cfg = &ot_eg_soc_uart_configure, - .instance = 1, + .instance = IBEX_MAKE_INSTANCE_NUM(1), .memmap = MEMMAPENTRIES( { .base = 0x40010000u } ), @@ -369,7 +369,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { [OT_EG_SOC_DEV_UART2] = { .type = TYPE_OT_UART, .cfg = &ot_eg_soc_uart_configure, - .instance = 2, + .instance = IBEX_MAKE_INSTANCE_NUM(2), .memmap = MEMMAPENTRIES( { .base = 0x40020000u } ), @@ -390,7 +390,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { [OT_EG_SOC_DEV_UART3] = { .type = TYPE_OT_UART, .cfg = &ot_eg_soc_uart_configure, - .instance = 3, + .instance = IBEX_MAKE_INSTANCE_NUM(3), .memmap = MEMMAPENTRIES( { .base = 0x40030000u } ), @@ -476,7 +476,6 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-i2c", .cfg = &ibex_unimp_configure, - .instance = 0, .memmap = MEMMAPENTRIES( { .base = 0x40080000u } ), @@ -488,7 +487,6 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-i2c", .cfg = &ibex_unimp_configure, - .instance = 1, .memmap = MEMMAPENTRIES( { .base = 0x40090000u } ), @@ -500,7 +498,6 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { .type = TYPE_UNIMPLEMENTED_DEVICE, .name = "ot-i2c", .cfg = &ibex_unimp_configure, - .instance = 2, .memmap = MEMMAPENTRIES( { .base = 0x400a0000u } ), @@ -608,7 +605,6 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { }, [OT_EG_SOC_DEV_SPI_HOST0] = { .type = TYPE_OT_SPI_HOST, - .instance = 0, .memmap = MEMMAPENTRIES( { .base = 0x40300000u } ), @@ -622,7 +618,6 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { }, [OT_EG_SOC_DEV_SPI_HOST1] = { .type = TYPE_OT_SPI_HOST, - .instance = 1, .memmap = MEMMAPENTRIES( { .base = 0x40310000u } ), @@ -753,7 +748,6 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { }, [OT_EG_SOC_DEV_SRAM_RET_CTRL] = { .type = TYPE_OT_SRAM_CTRL, - .instance = 0, .memmap = MEMMAPENTRIES( { .base = 0x40500000u }, { .base = 0x40600000u } @@ -891,7 +885,6 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { }, [OT_EG_SOC_DEV_EDN0] = { .type = TYPE_OT_EDN, - .instance = 0, .memmap = MEMMAPENTRIES( { .base = 0x41170000u } ), @@ -908,7 +901,6 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { }, [OT_EG_SOC_DEV_EDN1] = { .type = TYPE_OT_EDN, - .instance = 1, .memmap = MEMMAPENTRIES( { .base = 0x41180000u } ), @@ -925,7 +917,6 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { }, [OT_EG_SOC_DEV_SRAM_MAIN_CTRL] = { .type = TYPE_OT_SRAM_CTRL, - .instance = 1, .memmap = MEMMAPENTRIES( { .base = 0x411c0000u }, { .base = 0x10000000u } @@ -1167,7 +1158,7 @@ static void ot_eg_soc_uart_configure(DeviceState *dev, const IbexDeviceDef *def, { (void)def; (void)parent; - qdev_prop_set_chr(dev, "chardev", serial_hd(def->instance)); + qdev_prop_set_chr(dev, "chardev", serial_hd(IBEX_GET_INSTANCE_NUM(def))); } /* ------------------------------------------------------------------------ */ diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events index 7290751b9a91..d9447549818f 100644 --- a/hw/riscv/trace-events +++ b/hw/riscv/trace-events @@ -1,6 +1,7 @@ # See documentation at docs/devel/tracing.rst -# Debug Module +# dm.c + riscv_dm_aarsize_error(const char *soc, unsigned aarsize) "%s: aarsize %u not supported" riscv_dm_absdata(const char *soc, const char *op, unsigned woffset, unsigned wcount, uint64_t value, uint32_t res) "%s: %s: @ %u[%u] = 0x%08" PRIx64 ": res %u" riscv_dm_abstract_cmd(const char *soc, uint32_t addr, uint32_t inst) "%s: [%x]: %08x" @@ -27,9 +28,16 @@ riscv_dm_sysbus_data_read(const char *soc, uint64_t address, unsigned size, uint riscv_dm_sysbus_data_write(const char *soc, uint64_t address, unsigned size, uint64_t val64, unsigned res) "%s: 0x%08" PRIx64 "[+%u] -> %08" PRIx64 ": res %u" riscv_dm_unavailable(const char *soc, bool unavail) "%s: %u" -# Debug Transport Module +# dtm.c + riscv_dtm_dtmcs_reset(void) "" +riscv_dtm_enable_dm(const char *cls, bool enable, bool update) "%s: en:%u upd:%u" riscv_dtm_error(const char *func, int line, const char *msg) "%s:%d %s" riscv_dtm_info(const char *func, int line, const char *msg, uint32_t val) "%s:%d %s 0x%08x" -riscv_dtm_register_dm(unsigned count, uint64_t first, uint64_t last, bool ok) "#%u 0x%" PRIx64 "..0x%" PRIx64 ": %u" +riscv_dtm_register_dm(const char *cls, unsigned count, uint64_t first, uint64_t last, bool enabled, bool ok) "%s: #%u 0x%" PRIx64 "..0x%" PRIx64 ": enabled:%u tap:%u" +riscv_dtm_set_next_dm(const char *fromcls, uint32_t fromaddr, const char *tocls, uint32_t toaddr) "%s @ 0x%x next_dm %s @ 0x%x" riscv_dtm_vm_state_change(const char *name, unsigned state) "VM state: %s[%u]" + +# ibex_common.c + +ibex_create_device(const char *pname, const char *name) "%s.%s" diff --git a/include/hw/opentitan/ot_lc_ctrl.h b/include/hw/opentitan/ot_lc_ctrl.h index bc8b522f77a4..33446d3ef0e0 100644 --- a/include/hw/opentitan/ot_lc_ctrl.h +++ b/include/hw/opentitan/ot_lc_ctrl.h @@ -41,7 +41,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(OtLcCtrlState, OT_LC_CTRL) /* Life cycle broadcast signals */ typedef enum { OT_LC_RAW_TEST_RMA, /* SoC debug control */ - OT_LC_DFT_EN, /* pervasive, useless for current QEMU devices */ + OT_LC_DFT_EN, /* device for test */ OT_LC_NVM_DEBUG_EN, /* for embed. flash, not used in DJ */ OT_LC_HW_DEBUG_EN, /* unfortunately highly pervasive */ OT_LC_CPU_EN, /* ibex core */ diff --git a/include/hw/opentitan/ot_otp.h b/include/hw/opentitan/ot_otp.h index 792ed8966415..b837d4a1ab1f 100644 --- a/include/hw/opentitan/ot_otp.h +++ b/include/hw/opentitan/ot_otp.h @@ -58,7 +58,7 @@ typedef enum { typedef struct { uint32_t device_id[8u]; uint32_t manuf_state[8u]; - uint32_t soc_dbg_state; /* meaningless for Earlgrey platforms */ + uint16_t soc_dbg_state[2u]; /* may be meaningless, dep. on the platform */ /* the following value is stored as OT_MULTIBITBOOL8 */ uint8_t en_sram_ifetch; } OtOTPHWCfg; @@ -119,15 +119,16 @@ struct OtOTPStateClass { * Provide OTP lifecycle information. * * @s the OTP device - * @lc_state if not NULL, updated with the 5-bit encoded LifeCycle state - * @tcount if not NULL, updated with the LifeCycle transition count - * @lc_valid if not NULL, update with the LC valid state - * @secret_valid if not NULL, update with the LC secret_valid info + * @lc_tcount if not NULL, updated with the raw LifeCycle transition count + * buffer. + * @lc_state if not NULL, updated with the raw LifeCycle state buffer. + * @lc_valid if not NULL, update with the LC valid state (scalar) + * @secret_valid if not NULL, update with the LC secret_valid info (scalar) * * @note: lc_valid and secret_valid use OT_MULTIBITBOOL_LC4 encoding */ - void (*get_lc_info)(const OtOTPState *s, uint32_t *lc_state, - unsigned *tcount, uint8_t *lc_valid, + void (*get_lc_info)(const OtOTPState *s, uint16_t *lc_state, + uint16_t *lc_tcount, uint8_t *lc_valid, uint8_t *secret_valid, const OtOTPTokens **tokens); /* @@ -163,14 +164,15 @@ struct OtOTPStateClass { * is accepted. * * @s the OTP device - * @lc_state the LifeCycle 5-bit state - * @tcount the LifeCycle transition count + * @lc_tcount the raw LifeCycle transition count buffer + * @lc_state the raw LifeCycle state buffer * @ack the callback to asynchronously invoke on OTP completion/error * @opaque opaque data to forward to the ot_otp_program_ack_fn function * @return @c true if request is accepted, @c false is rejected. */ - bool (*program_req)(OtOTPState *s, uint32_t lc_state, unsigned tcount, - ot_otp_program_ack_fn ack, void *opaque); + bool (*program_req)(OtOTPState *s, const uint16_t *lc_tcount, + const uint16_t *lc_state, ot_otp_program_ack_fn ack, + void *opaque); }; #endif /* HW_OPENTITAN_OT_OTP_H */ diff --git a/include/hw/riscv/debug.h b/include/hw/riscv/debug.h index d14904d81770..67925c2bd87c 100644 --- a/include/hw/riscv/debug.h +++ b/include/hw/riscv/debug.h @@ -1,7 +1,7 @@ /* * QEMU RISC-V Debug * - * Copyright (c) 2023 Rivos, Inc. + * Copyright (c) 2023-2024 Rivos, Inc. * Author(s): * Emmanuel Blot * @@ -63,6 +63,11 @@ struct RISCVDebugDeviceClass { * Read back value. */ uint32_t (*read_value)(RISCVDebugDeviceState *dev); + + /* + * Set next DM address + */ + void (*set_next_dm)(RISCVDebugDeviceState *dev, uint32_t addr); }; struct RISCVDebugDeviceState { diff --git a/include/hw/riscv/dtm.h b/include/hw/riscv/dtm.h index a14a423c1f64..154b4d3e6a6d 100644 --- a/include/hw/riscv/dtm.h +++ b/include/hw/riscv/dtm.h @@ -32,20 +32,33 @@ #include "hw/riscv/debug.h" #define TYPE_RISCV_DTM "riscv.dtm" -OBJECT_DECLARE_SIMPLE_TYPE(RISCVDTMState, RISCV_DTM) +OBJECT_DECLARE_TYPE(RISCVDTMState, RISCVDTMClass, RISCV_DTM) -/** - * Register a debug module on the Debug Transport Module. - * It is valid to register the same module multiple time, as long as base_addr - * and size are not modified. - * - * @dev the DTM instance - * @dmif the DM to register - * @base_addr the address of the first DM register - * @size the count of DM registers - * @return @c true if DTM is enabled, @c false otherwise - */ -bool riscv_dtm_register_dm(DeviceState *dev, RISCVDebugDeviceState *dmif, - hwaddr base_addr, hwaddr size); +struct RISCVDTMClass { + DeviceClass parent_class; + + /* + * Register a debug module on the Debug Transport Module. + * It is valid to register the same module multiple time, as long as + * base_addr and size are not modified. + * + * @dev the DTM instance + * @dmif the DM to register + * @base_addr the address of the first DM register + * @size the count of DM registers + * @enable whether the DM should be immediately enabled or not + * @return @c true if DTM is enabled, @c false otherwise + */ + bool (*register_dm)(DeviceState *dev, RISCVDebugDeviceState *dbgdev, + hwaddr base_addr, hwaddr size, bool enable); + + /* + * Change the activation state of an already registered Debug Module. + * When disabled, the Debug Module can no longer be accessed from the DTM, + * and is removed from the "next_dm" chain. + */ + void (*enable_dm)(DeviceState *dev, RISCVDebugDeviceState *dbgdev, + bool enable); +}; #endif /* HW_RISCV_DTM_H */ diff --git a/include/hw/riscv/ibex_common.h b/include/hw/riscv/ibex_common.h index 8ffd1c94dc75..e07077e43ecc 100644 --- a/include/hw/riscv/ibex_common.h +++ b/include/hw/riscv/ibex_common.h @@ -80,59 +80,59 @@ typedef struct IbexDeviceDef IbexDeviceDef; typedef void (*ibex_dev_cfg_fn)(DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent); -/** +/* * Structure defining a GPIO connection (in particular, IRQs) from the current * device to a target device */ typedef struct { - /** Source GPIO */ + /* Source GPIO */ struct { - /** Name of source GPIO array or NULL for unnamed */ + /* Name of source GPIO array or NULL for unnamed */ const char *name; - /** Index of source output GPIO */ + /* Index of source output GPIO */ int num; } out; - /** Target GPIO */ + /* Target GPIO */ struct { - /** Target device index */ + /* Target device index */ int index; - /** Name of target input GPIO array or NULL for unnamed */ + /* Name of target input GPIO array or NULL for unnamed */ const char *name; - /** Index of target input GPIO */ + /* Index of target input GPIO */ int num; } in; } IbexGpioConnDef; -/** +/* * Structure defining the export of a device GPIO connection to the parent level */ typedef struct { - /** Device GPIO */ + /* Device GPIO */ struct { - /** Name of device GPIO array or NULL for unnamed */ + /* Name of device GPIO array or NULL for unnamed */ const char *name; - /** Index of device GPIO */ + /* Index of device GPIO */ int num; } device; - /** Parent GPIO */ + /* Parent GPIO */ struct { - /** Name of parent GPIO array or NULL for unnamed */ + /* Name of parent GPIO array or NULL for unnamed */ const char *name; - /** Index of parent GPIO */ + /* Index of parent GPIO */ int num; } parent; } IbexGpioExportDef; typedef struct { - /** Name of the property to assign the linked device to */ + /* Name of the property to assign the linked device to */ const char *propname; - /** Linked device index */ + /* Linked device index */ int index; } IbexDeviceLinkDef; -/** Type of device property */ +/* Type of device property */ typedef enum { IBEX_PROP_TYPE_BOOL, IBEX_PROP_TYPE_INT, @@ -141,11 +141,11 @@ typedef enum { } IbexPropertyType; typedef struct { - /** Name of the property */ + /* Name of the property */ const char *propname; - /** Type of property */ + /* Type of property */ IbexPropertyType type; - /** Value */ + /* Value */ union { bool b; int64_t i; @@ -168,35 +168,49 @@ typedef struct IbexMemMapEntry { #define IBEX_MEM_MAP_ENTRY_FLAG(_f_) (1u << (IBEX_MEM_MAP_ENTRY_FLAG_##_f_)) +#define IBEX_INSTANCE_FLAG (1u << 31u) +#define IBEX_MAKE_INSTANCE_NUM(_ix_) (IBEX_INSTANCE_FLAG | (_ix_)) +#define IBEX_HAS_INSTANCE_NUM(_def_) \ + ((bool)(((_def_)->instance & IBEX_INSTANCE_FLAG))) +#define IBEX_GET_INSTANCE_NUM(_def_) \ + (IBEX_HAS_INSTANCE_NUM(_def_) ? \ + ((_def_)->instance & ~IBEX_INSTANCE_FLAG) : \ + UINT32_MAX) + /* Device definition */ struct IbexDeviceDef { - /** Registered type of the device */ + /* Registered type of the device */ const char *type; - /** Optional name, may be NULL */ + /* Optional name, may be NULL */ const char *name; - /** Instance number, default to 0 */ - int instance; - /** Optional configuration function */ + /* + * Instance number, default to auto-numbering, using a monotonic incremental + * value following the declaration order. Use IBEX_MAKE_INSTANCE_NUM macro + * to specify a unique instance of the type, when an instance needs to be + * explictly referenced by its instance number. + */ + unsigned instance; + /* Optional configuration function */ ibex_dev_cfg_fn cfg; - /** Array of memory map */ + /* Array of memory map */ const IbexMemMapEntry *memmap; - /** Array of GPIO connections */ + /* Array of GPIO connections */ const IbexGpioConnDef *gpio; - /** Array of linked devices */ + /* Array of linked devices */ const IbexDeviceLinkDef *link; - /** Array of properties */ + /* Array of properties */ const IbexDevicePropDef *prop; - /** Array of GPIO export */ + /* Array of GPIO export */ const IbexGpioExportDef *gpio_export; }; /* Additional device mapping for external buses */ typedef struct { - /** Registered type of the device */ + /* Registered type of the device */ const char *type; - /** Instance number, default to 0 */ + /* Instance number, default to 0 */ int instance; - /** Array of memory map */ + /* Array of memory map */ const IbexMemMapEntry *memmap; } IbexDeviceMapDef; @@ -246,7 +260,7 @@ typedef struct { #define IBEX_MEMMAP_IGNORE(_mmap_) \ ((bool)((_mmap_)->flags & IBEX_MEM_MAP_ENTRY_FLAG(SKIP))) -/** +/* * Create memory map entries, each arg is MemMapEntry definition */ #define MEMMAPENTRIES(...) \ @@ -255,7 +269,7 @@ typedef struct { __VA_ARGS__, IBEX_MEMMAP_LAST \ } -/** +/* * Create GPIO connection entries, each arg is IbexGpioConnDef definition */ #define IBEXGPIOCONNDEFS(...) \ @@ -267,7 +281,7 @@ typedef struct { } \ } -/** +/* * Create device link entries, each arg is IbexDeviceLinkDef definition */ #define IBEXDEVICELINKDEFS(...) \ @@ -279,7 +293,7 @@ typedef struct { } \ } -/** +/* * Create device property entries, each arg is IbexDevicePropDef definition */ #define IBEXDEVICEPROPDEFS(...) \ @@ -291,7 +305,7 @@ typedef struct { } \ } -/** +/* * Create device additional map entries, each arg is IbexDeviceMapDef definition */ #define IBEXDEVICEMAPDEFS(...) \ @@ -303,7 +317,7 @@ typedef struct { } \ } -/** +/* * Create device gpio export property entries, each arg is IbexGpioExportDef * definition */ @@ -316,7 +330,7 @@ typedef struct { } \ } -/** +/* * Create a IbexGpioConnDef to connect two unnamed GPIOs */ #define IBEX_GPIO(_irq_, _in_idx_, _num_) \ @@ -330,7 +344,7 @@ typedef struct { } \ } -/** +/* * Create a IbexGpioConnDef to connect a SysBus IRQ to an unnamed GPIO */ #define IBEX_GPIO_SYSBUS_IRQ(_irq_, _in_idx_, _num_) \ @@ -345,7 +359,7 @@ typedef struct { } \ } -/** +/* * Create a IbexLinkDeviceDef to link one device to another */ #define IBEX_DEVLINK(_pname_, _idx_) \ @@ -354,7 +368,7 @@ typedef struct { .index = (_idx_), \ } -/** +/* * Create a IbexGpioExportDef to export a GPIO */ #define IBEX_EXPORT_GPIO(_dname_, _dnum_, _pname_, _pnum_) \ @@ -369,13 +383,13 @@ typedef struct { }, \ } -/** +/* * Create a IbexGpioExportDef to export a SysBus IRQ */ #define IBEX_EXPORT_SYSBUS_IRQ(_dnum_, _pname_, _pnum_) \ IBEX_EXPORT_GPIO(NULL, _dnum_, _pname_, _pnum_) -/** +/* * Create a boolean device property */ #define IBEX_DEV_BOOL_PROP(_pname_, _b_) \ @@ -385,7 +399,7 @@ typedef struct { .b = (_b_), \ } -/** +/* * Create a signed integer device property */ #define IBEX_DEV_INT_PROP(_pname_, _i_) \ @@ -395,7 +409,7 @@ typedef struct { .i = (_i_), \ } -/** +/* * Create an unsigned integer device property */ #define IBEX_DEV_UINT_PROP(_pname_, _u_) \ @@ -405,7 +419,7 @@ typedef struct { .u = (_u_), \ } -/** +/* * Create a string device property */ #define IBEX_DEV_STRING_PROP(_pname_, _s_) \ @@ -462,7 +476,7 @@ void ibex_connect_soc_devices(DeviceState **soc_devices, DeviceState **devices, const IbexDeviceDef *defs, unsigned count); DeviceState *ibex_get_child_device(DeviceState *s, const char *typename, unsigned instance); -/** +/* * Utility function to configure unimplemented device. * The Ibex device definition should have one defined memory entry, and an * optional name. @@ -474,7 +488,7 @@ void ibex_unimp_configure(DeviceState *dev, const IbexDeviceDef *def, /* CPU */ /* ------------------------------------------------------------------------ */ -/** +/* * Load an ELF application into a CPU address space. * * @cpu the CPU to load the application for; maybe NULL in which case the @@ -487,7 +501,7 @@ void ibex_unimp_configure(DeviceState *dev, const IbexDeviceDef *def, */ uint32_t ibex_load_kernel(CPUState *cpu); -/** +/* * Helper for device debugging: report the current guest PC, if any. * * If a HW access is performed from another device but the CPU, reported PC @@ -495,7 +509,7 @@ uint32_t ibex_load_kernel(CPUState *cpu); */ uint32_t ibex_get_current_pc(void); -/** +/* * Helper for device debugging: report the current guest CPU index, if any. * * If a HW access is performed from another device but the CPU, reported CPU @@ -538,7 +552,7 @@ enum { RV_GPR_T6 = (1u << 31u), }; -/** +/* * Log current vCPU registers. * * @regbm is a bitmap of registers to be dumped [x1..t6], pc replace x0 @@ -549,7 +563,7 @@ void ibex_log_vcpu_registers(uint64_t regbm); /* CharDev utilities */ /* ------------------------------------------------------------------------ */ -/** +/* * Find a char device by its id, e.g. "-chardev type,id=,...`" * * @chrid the id of the char device diff --git a/scripts/jtag/.flake8 b/python/qemu/jtag/.flake8 similarity index 100% rename from scripts/jtag/.flake8 rename to python/qemu/jtag/.flake8 diff --git a/scripts/jtag/.pylintrc b/python/qemu/jtag/.pylintrc similarity index 91% rename from scripts/jtag/.pylintrc rename to python/qemu/jtag/.pylintrc index 4ee3afd2c601..7ee6e793e253 100644 --- a/scripts/jtag/.pylintrc +++ b/python/qemu/jtag/.pylintrc @@ -4,6 +4,7 @@ disable= too-few-public-methods, too-many-arguments, too-many-branches, + too-many-function-args, too-many-instance-attributes, too-many-lines, too-many-locals, diff --git a/scripts/jtag/__init__.py b/python/qemu/jtag/__init__.py similarity index 100% rename from scripts/jtag/__init__.py rename to python/qemu/jtag/__init__.py diff --git a/scripts/jtag/bitbang.py b/python/qemu/jtag/bitbang.py similarity index 100% rename from scripts/jtag/bitbang.py rename to python/qemu/jtag/bitbang.py diff --git a/scripts/jtag/bits.py b/python/qemu/jtag/bits.py similarity index 100% rename from scripts/jtag/bits.py rename to python/qemu/jtag/bits.py diff --git a/scripts/jtag/jtag.py b/python/qemu/jtag/jtag.py similarity index 100% rename from scripts/jtag/jtag.py rename to python/qemu/jtag/jtag.py diff --git a/python/qemu/ot/.flake8 b/python/qemu/ot/.flake8 new file mode 100644 index 000000000000..15fc7e33eb08 --- /dev/null +++ b/python/qemu/ot/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 80 diff --git a/python/qemu/ot/.pylintrc b/python/qemu/ot/.pylintrc new file mode 100644 index 000000000000..5c450101b3e8 --- /dev/null +++ b/python/qemu/ot/.pylintrc @@ -0,0 +1,15 @@ +[MESSAGES CONTROL] + +disable= + import-error, + too-few-public-methods, + too-many-arguments, + too-many-branches, + too-many-function-args, + too-many-instance-attributes, + too-many-lines, + too-many-locals, + too-many-nested-blocks, + too-many-public-methods, + too-many-statements, + unspecified-encoding diff --git a/scripts/opentitan/ot/__init__.py b/python/qemu/ot/__init__.py similarity index 100% rename from scripts/opentitan/ot/__init__.py rename to python/qemu/ot/__init__.py diff --git a/scripts/opentitan/ot/bitfield.py b/python/qemu/ot/bitfield.py similarity index 100% rename from scripts/opentitan/ot/bitfield.py rename to python/qemu/ot/bitfield.py diff --git a/scripts/opentitan/ot/devproxy.py b/python/qemu/ot/devproxy.py similarity index 99% rename from scripts/opentitan/ot/devproxy.py rename to python/qemu/ot/devproxy.py index 92526c125f3d..37b6fa675602 100644 --- a/scripts/opentitan/ot/devproxy.py +++ b/python/qemu/ot/devproxy.py @@ -1696,6 +1696,7 @@ def _notify(self) -> None: if not dispatcher: self._log.error('Unsupported notification: %s', handler) continue + # pylint: disable=not-callable dispatcher(payload) else: if not self._request_handler: diff --git a/scripts/opentitan/ot/dm/__init__.py b/python/qemu/ot/dm/__init__.py similarity index 100% rename from scripts/opentitan/ot/dm/__init__.py rename to python/qemu/ot/dm/__init__.py diff --git a/scripts/opentitan/ot/dm/dm.py b/python/qemu/ot/dm/dm.py similarity index 100% rename from scripts/opentitan/ot/dm/dm.py rename to python/qemu/ot/dm/dm.py diff --git a/scripts/opentitan/ot/dm/otp.py b/python/qemu/ot/dm/otp.py similarity index 100% rename from scripts/opentitan/ot/dm/otp.py rename to python/qemu/ot/dm/otp.py diff --git a/scripts/opentitan/ot/dm/regs.py b/python/qemu/ot/dm/regs.py similarity index 100% rename from scripts/opentitan/ot/dm/regs.py rename to python/qemu/ot/dm/regs.py diff --git a/scripts/opentitan/ot/dtm/__init__.py b/python/qemu/ot/dtm/__init__.py similarity index 100% rename from scripts/opentitan/ot/dtm/__init__.py rename to python/qemu/ot/dtm/__init__.py diff --git a/scripts/opentitan/ot/dtm/dtm.py b/python/qemu/ot/dtm/dtm.py similarity index 98% rename from scripts/opentitan/ot/dtm/dtm.py rename to python/qemu/ot/dtm/dtm.py index 9dc038f3460a..d6d1fcc14652 100644 --- a/scripts/opentitan/ot/dtm/dtm.py +++ b/python/qemu/ot/dtm/dtm.py @@ -11,9 +11,8 @@ from sys import modules from typing import Optional -# pylint: disable=import-error -from jtag.bits import BitSequence # noqa: E402 -from jtag.jtag import JtagEngine # noqa: E402 +from jtag.bits import BitSequence +from jtag.jtag import JtagEngine class DMIError(RuntimeError): diff --git a/scripts/opentitan/ot/lc_ctrl/__init__.py b/python/qemu/ot/lc_ctrl/__init__.py similarity index 100% rename from scripts/opentitan/ot/lc_ctrl/__init__.py rename to python/qemu/ot/lc_ctrl/__init__.py diff --git a/scripts/opentitan/ot/lc_ctrl/lcdmi.py b/python/qemu/ot/lc_ctrl/lcdmi.py similarity index 100% rename from scripts/opentitan/ot/lc_ctrl/lcdmi.py rename to python/qemu/ot/lc_ctrl/lcdmi.py diff --git a/scripts/opentitan/ot/mailbox/__init__.py b/python/qemu/ot/mailbox/__init__.py similarity index 100% rename from scripts/opentitan/ot/mailbox/__init__.py rename to python/qemu/ot/mailbox/__init__.py diff --git a/scripts/opentitan/ot/mailbox/doe.py b/python/qemu/ot/mailbox/doe.py similarity index 100% rename from scripts/opentitan/ot/mailbox/doe.py rename to python/qemu/ot/mailbox/doe.py diff --git a/scripts/opentitan/ot/mailbox/jtag.py b/python/qemu/ot/mailbox/jtag.py similarity index 94% rename from scripts/opentitan/ot/mailbox/jtag.py rename to python/qemu/ot/mailbox/jtag.py index 38812f4c7f0b..8c09827c4285 100644 --- a/scripts/opentitan/ot/mailbox/jtag.py +++ b/python/qemu/ot/mailbox/jtag.py @@ -8,10 +8,6 @@ from logging import getLogger -# see scripts/jtag -# pylint: disable=import-error -# pylint: disable=unused-import -from jtag.jtag import JtagError # noqa: F401 from .sysmbox import SysMbox from ..dtm import DebugTransportModule diff --git a/scripts/opentitan/ot/mailbox/sysmbox.py b/python/qemu/ot/mailbox/sysmbox.py similarity index 100% rename from scripts/opentitan/ot/mailbox/sysmbox.py rename to python/qemu/ot/mailbox/sysmbox.py diff --git a/scripts/opentitan/ot/otp/__init__.py b/python/qemu/ot/otp/__init__.py similarity index 100% rename from scripts/opentitan/ot/otp/__init__.py rename to python/qemu/ot/otp/__init__.py diff --git a/scripts/opentitan/ot/otp/const.py b/python/qemu/ot/otp/const.py similarity index 83% rename from scripts/opentitan/ot/otp/const.py rename to python/qemu/ot/otp/const.py index 705ef81f63ab..6982e657335e 100644 --- a/scripts/opentitan/ot/otp/const.py +++ b/python/qemu/ot/otp/const.py @@ -7,8 +7,8 @@ """ from logging import getLogger -from re import finditer from typing import TextIO +import re from ot.util.misc import camel_to_snake_case @@ -28,19 +28,19 @@ def load(self, svp: TextIO): :param svp: System Verilog stream with OTP definitions. """ svdata = svp.read() - for smo in finditer(r"\stypedef\s+enum\s+logic\s+\[[^]]+\]\s" - r"{((?:\s+\w+,?)+)\s*}\s(\w+)_sel_e;", svdata): + for smo in re.finditer(r"\stypedef\s+enum\s+logic\s+\[[^]]+\]\s" + r"{((?:\s+\w+,?)+)\s*}\s(\w+)_sel_e;", svdata): values, name = smo.groups() if name in self._consts: raise ValueError(f'Multiple definitions of enumeration {name}') enums = self._enums[name] = {} - for emo in finditer(r"\s+(\w+),?", values): + for emo in re.finditer(r"\s+(\w+),?", values): vname = camel_to_snake_case(emo.group(1)) enums[vname] = len(enums) - for amo in finditer(r"\s+parameter\s+(\w+)_array_t\s+(\w+)\s+=\s+" - r"{(\s+(?:(?:64|128)'h[0-9A-F]+,?\s+)+)};", - svdata): + for amo in re.finditer(r"\s+parameter\s+(\w+)_array_t\s+(\w+)\s+=\s+" + r"{(\s+(?:(?:64|128)'h[0-9A-F]+,?\s+)+)};", + svdata): _type, name, values = amo.groups() sc_name = camel_to_snake_case(name) sc_parts = sc_name.split('_') @@ -52,7 +52,7 @@ def load(self, svp: TextIO): if name in self._consts: raise ValueError(f'Multiple definitions of constant {name}') consts = self._consts[name] = [] - for cmo in finditer(r"(64|128)'h([0-9A-F]+),?", values): + for cmo in re.finditer(r"(64|128)'h([0-9A-F]+),?", values): consts.append(cmo.group(2).lower()) # RTL order in array is reversed consts.reverse() diff --git a/scripts/opentitan/ot/otp/descriptor.py b/python/qemu/ot/otp/descriptor.py similarity index 100% rename from scripts/opentitan/ot/otp/descriptor.py rename to python/qemu/ot/otp/descriptor.py diff --git a/scripts/opentitan/ot/otp/image.py b/python/qemu/ot/otp/image.py similarity index 99% rename from scripts/opentitan/ot/otp/image.py rename to python/qemu/ot/otp/image.py index e1c1340d7685..227e46c01785 100644 --- a/scripts/opentitan/ot/otp/image.py +++ b/python/qemu/ot/otp/image.py @@ -10,9 +10,9 @@ from configparser import ConfigParser, NoOptionError from io import BytesIO from logging import getLogger -from re import match as re_match, sub as re_sub from struct import calcsize as scalc, pack as spack, unpack as sunpack from typing import Any, BinaryIO, Optional, Sequence, TextIO, Union +import re from .map import OtpMap from .partition import OtpPartition, OtpLifecycleExtension @@ -142,18 +142,18 @@ def load_vmem(self, vfp: TextIO, vmem_kind: Optional[str] = None, raise ValueError(f"Unknown VMEM file kind '{vmem_kind}'") for lno, line in enumerate(vfp, start=1): if vkind is None: - kmo = re_match(self.RE_VMEMDESC, line) + kmo = re.match(self.RE_VMEMDESC, line) if kmo: vkind = kmo.group(1) row_count = int(kmo.group(2)) bits = int(kmo.group(3)) byte_count = bits // 8 continue - line = re_sub(r'//.*', '', line) + line = re.sub(r'//.*', '', line) line = line.strip() if not line: continue - lmo = re_match(self.RE_VMEMLOC, line) + lmo = re.match(self.RE_VMEMLOC, line) if not lmo: self._log.error('Unexpected line @ %d: %s', lno, line) continue diff --git a/scripts/opentitan/ot/otp/lifecycle.py b/python/qemu/ot/otp/lifecycle.py similarity index 88% rename from scripts/opentitan/ot/otp/lifecycle.py rename to python/qemu/ot/otp/lifecycle.py index dd0ffd85ff42..c9ccba25c376 100644 --- a/scripts/opentitan/ot/otp/lifecycle.py +++ b/python/qemu/ot/otp/lifecycle.py @@ -10,9 +10,9 @@ from io import StringIO from logging import getLogger from os.path import basename -from re import finditer, match, sub from textwrap import fill from typing import TextIO +import re from ot.util.misc import camel_to_snake_case, group @@ -31,7 +31,7 @@ class OtpLifecycle: def __init__(self): self._log = getLogger('otp.lc') - self._sequences: dict[str, list[str]] = {} + self._sequences: dict[str, dict[str, list[str]]] = {} self._tables: dict[str, dict[str, str]] = {} self._tokens: dict[str, str] = {} @@ -41,17 +41,19 @@ def load(self, svp: TextIO): :param svp: System Verilog stream with OTP definitions. """ ab_re = (r"\s*parameter\s+logic\s+\[\d+:\d+\]\s+" - r"([ABCD]\d+|ZRO)\s+=\s+\d+'(b(?:[01]+)|h(?:[0-9a-fA-F]+));") - tbl_re = r"\s*Lc(St|Cnt)(\w+)\s+=\s+\{([^\}]+)\}\s*,?" + r"([ABCDEFGH]\d+|ZRO)\s+=\s+" + r"\d+'(b(?:[01]+)|h(?:[0-9a-fA-F]+));") + tbl_re = (r"\s*(LcSt|LcCnt|OwnershipSt|SocDbgSt)(\w+)\s+=" + r"\s+\{([^\}]+)\}\s*,?") codes: dict[str, int] = {} - sequences: dict[str, list[str]] = {} + sequences: dict[str, dict[str, list[str]]] = {} svp = StringIO(svp.read()) for line in svp: cmt = line.find('//') if cmt >= 0: line = line[:cmt] line = line.strip() - abmo = match(ab_re, line) + abmo = re.match(ab_re, line) if not sequences and abmo: name = abmo.group(1) sval = abmo.group(2) @@ -62,7 +64,7 @@ def load(self, svp: TextIO): continue codes[name] = val continue - smo = match(tbl_re, line) + smo = re.match(tbl_re, line) if smo: kind = smo.group(1).lower() name = smo.group(2) @@ -77,7 +79,7 @@ def load(self, svp: TextIO): continue self._sequences = sequences svp.seek(0) - for tmo in finditer(r"\s+parameter\s+lc_token_t\s+(\w+)\s+=" + for tmo in re.finditer(r"\s+parameter\s+lc_token_t\s+(\w+)\s+=" r"\s+\{\s+128'h([0-9A-F]+)\s+\};", svp.getvalue()): token, value = tmo.group(1), tmo.group(2) @@ -85,8 +87,10 @@ def load(self, svp: TextIO): raise ValueError(f'Multiple definitions of token {token}') self._tokens[token] = value.lower() for kind, seqs in sequences.items(): - mkind, conv = {'st': ('LC_STATE', str), - 'cnt': ('LC_TRANSITION_CNT', int)}[kind] + mkind, conv = {'lcst': ('LC_STATE', str), + 'lccnt': ('LC_TRANSITION_CNT', int), + 'ownershipst': ('OWNERSHIP', str), + 'socdbgst': ('SOCDBG', str)}[kind] self._tables[mkind] = {} for ref, seq in seqs.items(): seq = ''.join((f'{x:04x}'for x in map(codes.get, seq))) @@ -146,7 +150,7 @@ def _save_template(self, cfp: TextIO) -> None: for stname, stwords in states.items(): print(f' [LC_STATE_{stname.upper()}] = {{', file=cfp) for wgrp in group(stwords, len(stwords)//2): - items = (sub(r'(\d+)', r'(\1)', wg) for wg in wgrp) + items = (re.sub(r'(\d+)', r'(\1)', wg) for wg in wgrp) stws = ' '.join(f'{w:<6s}' for w in (f'{i},' for i in items)) print(f' {stws.rstrip()}', file=cfp) print(' },', file=cfp) @@ -155,7 +159,7 @@ def _save_template(self, cfp: TextIO) -> None: def get_configuration(self, name: str) -> dict[str, str]: """Provide a dictionary of configurable elements for QEMU.""" - return self._tables.get(name, {}) + return dict(self._tables.get(name, {})) def get_tokens(self, hashed: bool, zero: bool) -> dict[str, str]: """Return a dictionary of parsed tokens.""" diff --git a/scripts/opentitan/ot/otp/map.py b/python/qemu/ot/otp/map.py similarity index 100% rename from scripts/opentitan/ot/otp/map.py rename to python/qemu/ot/otp/map.py diff --git a/scripts/opentitan/ot/otp/partition.py b/python/qemu/ot/otp/partition.py similarity index 95% rename from scripts/opentitan/ot/otp/partition.py rename to python/qemu/ot/otp/partition.py index eef57f817f42..59b02be34c8a 100644 --- a/scripts/opentitan/ot/otp/partition.py +++ b/python/qemu/ot/otp/partition.py @@ -6,7 +6,7 @@ :author: Emmanuel Blot """ -from binascii import hexlify +from binascii import hexlify, unhexlify, Error as hexerror from io import BytesIO from logging import getLogger from typing import BinaryIO, Optional, TextIO @@ -207,7 +207,12 @@ class OtpLifecycleExtension(OtpLifecycle, OtpPartitionDecoder): """ def decode(self, category: str, seq: str) -> Optional[str | int]: - return self._tables.get(category, {}).get(seq, None) + try: + iseq = hexlify(bytes(reversed(unhexlify(seq)))).decode() + except (ValueError, TypeError, hexerror) as exc: + self._log.error('Unable to parse LC data: %s', str(exc)) + return None + return self._tables.get(category, {}).get(iseq, None) # imported here to avoid Python circular dependency issue diff --git a/scripts/opentitan/ot/spi/__init__.py b/python/qemu/ot/spi/__init__.py similarity index 100% rename from scripts/opentitan/ot/spi/__init__.py rename to python/qemu/ot/spi/__init__.py diff --git a/scripts/opentitan/ot/spi/spi_device.py b/python/qemu/ot/spi/spi_device.py similarity index 100% rename from scripts/opentitan/ot/spi/spi_device.py rename to python/qemu/ot/spi/spi_device.py diff --git a/scripts/opentitan/ot/util/__init__.py b/python/qemu/ot/util/__init__.py similarity index 100% rename from scripts/opentitan/ot/util/__init__.py rename to python/qemu/ot/util/__init__.py diff --git a/scripts/opentitan/ot/util/elf.py b/python/qemu/ot/util/elf.py similarity index 98% rename from scripts/opentitan/ot/util/elf.py rename to python/qemu/ot/util/elf.py index 4ac38d77c05e..1a67484188ff 100644 --- a/scripts/opentitan/ot/util/elf.py +++ b/python/qemu/ot/util/elf.py @@ -9,8 +9,8 @@ from io import BytesIO from logging import getLogger from os.path import basename -from re import compile as re_compile from typing import BinaryIO, Iterator, NamedTuple, Optional +import re try: _ELF_ERROR = None @@ -52,7 +52,7 @@ class ElfBlob: RUST_ERROR = _RUST_ERROR """Report whether Rust tools have been loaded.""" - RUST_TRAIL_CRE = re_compile(r'::h[0-9a-f]{16}$') + RUST_TRAIL_CRE = re.compile(r'::h[0-9a-f]{16}$') """Regex to get rid of Rust trailing symbol string.""" def __init__(self): diff --git a/scripts/opentitan/ot/util/log.py b/python/qemu/ot/util/log.py similarity index 100% rename from scripts/opentitan/ot/util/log.py rename to python/qemu/ot/util/log.py diff --git a/scripts/opentitan/ot/util/mbb.py b/python/qemu/ot/util/mbb.py similarity index 100% rename from scripts/opentitan/ot/util/mbb.py rename to python/qemu/ot/util/mbb.py diff --git a/scripts/opentitan/ot/util/misc.py b/python/qemu/ot/util/misc.py similarity index 98% rename from scripts/opentitan/ot/util/misc.py rename to python/qemu/ot/util/misc.py index 8a1d7af5b425..43a0464eee66 100644 --- a/scripts/opentitan/ot/util/misc.py +++ b/python/qemu/ot/util/misc.py @@ -7,9 +7,9 @@ """ from io import BytesIO -from re import sub from sys import stdout from typing import Any, Iterable, Optional, TextIO +import re try: # only available from Python 3.12+ @@ -109,4 +109,4 @@ def round_up(value: int, rnd: int) -> int: def camel_to_snake_case(camel: str) -> str: """Convert CamelString string into snake_case lower string.""" pattern = r'(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])' - return sub(pattern, '_', camel).lower() + return re.sub(pattern, '_', camel).lower() diff --git a/scripts/opentitan/.flake8 b/scripts/opentitan/.flake8 index 15fc7e33eb08..fbd6e07a1d5c 100644 --- a/scripts/opentitan/.flake8 +++ b/scripts/opentitan/.flake8 @@ -1,2 +1,3 @@ [flake8] max-line-length = 80 +extend-ignore = E402 diff --git a/scripts/opentitan/.pylintrc b/scripts/opentitan/.pylintrc index 7ee6e793e253..4c02f0f674aa 100644 --- a/scripts/opentitan/.pylintrc +++ b/scripts/opentitan/.pylintrc @@ -1,6 +1,8 @@ [MESSAGES CONTROL] disable= + unknown-option-value, + import-error, too-few-public-methods, too-many-arguments, too-many-branches, @@ -9,6 +11,9 @@ disable= too-many-lines, too-many-locals, too-many-nested-blocks, + too-many-positional-arguments, too-many-public-methods, too-many-statements, - unspecified-encoding + unspecified-encoding, + wrong-import-order, + wrong-import-position diff --git a/scripts/opentitan/cfggen.py b/scripts/opentitan/cfggen.py index 8c9935dec963..1de696c207d0 100755 --- a/scripts/opentitan/cfggen.py +++ b/scripts/opentitan/cfggen.py @@ -11,22 +11,29 @@ from argparse import ArgumentParser from configparser import ConfigParser from logging import getLogger -from os.path import isdir, isfile, join as joinpath, normpath -from re import match, search -from sys import exit as sysexit, modules, stderr, stdout +from os.path import dirname, isdir, isfile, join as joinpath, normpath from traceback import format_exc from typing import Optional +import re +import sys + +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) try: _HJSON_ERROR = None from hjson import load as hjload except ImportError as hjson_exc: _HJSON_ERROR = str(hjson_exc) + def hjload(*_, **__): # noqa: E301 + """dummy func if HJSON module is not available""" + return {} -from ot.util.log import configure_loggers -from ot.util.misc import camel_to_snake_case from ot.otp.const import OtpConstants from ot.otp.lifecycle import OtpLifecycle +from ot.util.log import configure_loggers +from ot.util.misc import camel_to_snake_case OtParamRegex = str @@ -40,12 +47,15 @@ def __init__(self): self._log = getLogger('cfggen.cfg') self._lc_states: tuple[str, str] = ('', '') self._lc_transitions: tuple[str, str] = ('', '') + self._socdbg: tuple[str, str] = ('', '') + self._ownership: tuple[str, str] = ('', '') self._roms: dict[Optional[int], dict[str, str]] = {} self._otp: dict[str, str] = {} self._lc: dict[str, str] = {} def load_top_config(self, toppath: str) -> None: """Load data from HJSON top configuration file.""" + assert not _HJSON_ERROR with open(toppath, 'rt') as tfp: cfg = hjload(tfp) for module in cfg.get('module') or []: @@ -80,10 +90,27 @@ def load_lifecycle(self, lcpath: str) -> None: del trans[raw] otrans = list(trans) self._lc_transitions = otrans[0], otrans[-1] - self._log.info('Transitions first : %d, last %d', + self._log.info('Transitions first: %d, last %d', int(trans[self._lc_transitions[0]]), int(trans[self._lc_transitions[1]])) self._lc.update(lcext.get_tokens(False, False)) + socdbg = lcext.get_configuration('SOCDBG') + if socdbg: + for raw in {s for s in socdbg if int(s, 16) == 0}: + del socdbg[raw] + osoc = list(socdbg) + self._socdbg = osoc[0], osoc[-1] + self._log.info("Socdbg first: '%s', last '%s'", + socdbg[self._socdbg[0]], socdbg[self._socdbg[1]]) + ownership = lcext.get_configuration('OWNERSHIP') + if ownership: + for raw in {s for s in ownership if int(s, 16) == 0}: + del ownership[raw] + osoc = list(ownership) + self._ownership = osoc[0], osoc[-1] + self._log.info("Socdbg first: '%s', last '%s'", + ownership[self._ownership[0]], + ownership[self._ownership[1]]) def load_otp_constants(self, otppath: str) -> None: """Load OTP data from RTL file.""" @@ -93,37 +120,38 @@ def load_otp_constants(self, otppath: str) -> None: self._otp.update(otpconst.get_digest_pair('cnsty_digest', 'digest')) self._otp.update(otpconst.get_digest_pair('sram_data_key', 'sram')) - def save(self, socid: Optional[str] = None, count: Optional[int] = 1, - outpath: Optional[str] = None) \ + def save(self, socid: Optional[str], count: Optional[int], + outpath: Optional[str]) \ -> None: """Save QEMU configuration file using a INI-like file format, compatible with the `-readconfig` option of QEMU. """ cfg = ConfigParser() - self._generate_roms(cfg, socid, count) + self._generate_roms(cfg, socid, count or 1) self._generate_otp(cfg, socid) self._generate_life_cycle(cfg, socid) if outpath: with open(outpath, 'wt') as ofp: cfg.write(ofp) else: - cfg.write(stdout) + cfg.write(sys.stdout) @classmethod def add_pair(cls, data: dict[str, str], kname: str, value: str) -> None: """Helper to create key, value pair entries.""" - data[f' {kname}'] = f'"{value}"' + if value: + data[f' {kname}'] = f'"{value}"' def _load_top_values(self, module: dict, odict: dict, multi: bool, - *regexes: list[OtParamRegex]) -> None: + *regexes: tuple[OtParamRegex, ...]) -> None: modname = module.get('name') if not modname: return for params in module.get('param_list', []): if not isinstance(params, dict): continue - for regex in regexes: # TODO: camelcase to lower snake case - pmo = match(regex, params['name']) + for regex in regexes: + pmo = re.match(regex, params['name']) if not pmo: continue value = params.get('default') @@ -133,7 +161,7 @@ def _load_top_values(self, module: dict, odict: dict, multi: bool, value = value[2:] kname = camel_to_snake_case(pmo.group(1)) if multi: - imo = search(r'(\d+)$', modname) + imo = re.search(r'(\d+)$', modname) idx = int(imo.group(1)) if imo else 'None' if idx not in odict: odict[idx] = {} @@ -166,10 +194,6 @@ def _generate_otp(self, cfg: ConfigParser, socid: Optional[str] = None) \ nameargs.append(socid) otpname = '.'.join(nameargs) otpdata = {} - self.add_pair(otpdata, 'lc_state_first', self._lc_states[0]) - self.add_pair(otpdata, 'lc_state_last', self._lc_states[-1]) - self.add_pair(otpdata, 'lc_trscnt_first', self._lc_transitions[0]) - self.add_pair(otpdata, 'lc_trscnt_last', self._lc_transitions[-1]) for kname, val in self._otp.items(): self.add_pair(otpdata, kname, val) otpdata = dict(sorted(otpdata.items())) @@ -182,8 +206,17 @@ def _generate_life_cycle(self, cfg: ConfigParser, nameargs.append(socid) lcname = '.'.join(nameargs) lcdata = {} + self.add_pair(lcdata, 'lc_state_first', self._lc_states[0]) + self.add_pair(lcdata, 'lc_state_last', self._lc_states[1]) + self.add_pair(lcdata, 'lc_trscnt_first', self._lc_transitions[0]) + self.add_pair(lcdata, 'lc_trscnt_last', self._lc_transitions[1]) + self.add_pair(lcdata, 'ownership_first', self._ownership[0]) + self.add_pair(lcdata, 'ownership_last', self._ownership[1]) + self.add_pair(lcdata, 'socdbg_first', self._socdbg[0]) + self.add_pair(lcdata, 'socdbg_last', self._socdbg[1]) for kname, value in self._lc.items(): self.add_pair(lcdata, kname, value) + lcdata = dict(sorted(lcdata.items())) cfg[f'ot_device "{lcname}"'] = lcdata @@ -192,7 +225,7 @@ def main(): debug = True default_top = 'darjeeling' try: - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}.') files = argparser.add_argument_group(title='Files') files.add_argument('opentitan', nargs=1, metavar='TOPDIR', @@ -224,7 +257,7 @@ def main(): configure_loggers(args.verbose, 'cfggen', 'otp') if _HJSON_ERROR: - argparser.error('Missing HSJON module: {_HJSON_ERROR}') + argparser.error('Missing HJSON module: {_HJSON_ERROR}') topdir = args.opentitan[0] if not isdir(topdir): @@ -260,12 +293,12 @@ def main(): cfg.save(args.socid, args.count, args.out) except (IOError, ValueError, ImportError) as exc: - print(f'\nError: {exc}', file=stderr) + print(f'\nError: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: - sysexit(2) + sys.exit(2) if __name__ == '__main__': diff --git a/scripts/opentitan/checkregs.py b/scripts/opentitan/checkregs.py index e076c28a3695..81a48e85220a 100755 --- a/scripts/opentitan/checkregs.py +++ b/scripts/opentitan/checkregs.py @@ -11,10 +11,10 @@ from os import pardir, walk from os.path import (basename, dirname, join as joinpath, normpath, relpath, splitext) -from re import compile as re_compile, sub as re_sub -from sys import exit as sysexit, modules, stderr from traceback import format_exc from typing import NamedTuple, Optional, TextIO +import re +import sys class ValueLocation(NamedTuple): @@ -58,7 +58,7 @@ def _parse_defs(self, hfp: TextIO) -> RegisterDefs: # the following RE matches two kinds of definition: # #define __REG_OFFSET # #define _PARAM__OFFSET - reg_cre = re_compile(rf'^#define {rre}(?PPARAM_)?' + reg_cre = re.compile(rf'^#define {rre}(?PPARAM_)?' r'(?P[A-Z][\w]+?)(?(param)|_REG)_OFFSET\s+' r'(?P(?:0x)?[A-Fa-f0-9]+)(?:\s|$)') for lno, line in enumerate(hfp, start=1): @@ -80,7 +80,7 @@ def _parse_defs(self, hfp: TextIO) -> RegisterDefs: def find_qemu_impl(self, filename: str, basedir: str, nomap: bool) \ -> Optional[str]: filename = basename(filename) - radix = re_sub(r'_regs$', '', splitext(filename)[0]) + radix = re.sub(r'_regs$', '', splitext(filename)[0]) if not nomap: radix = self.DEFMAP.get(radix, radix) impl_name = f'ot_{radix}.c' @@ -99,7 +99,7 @@ def parse_ot_qemu(self, filename: str) -> RegisterDefs: def _parse_ot_qemu(self, qfp: TextIO) -> RegisterDefs: defs = {} - regfield_cre = re_compile(r'^\s*REG32\(([A-Z][\w]+),\s+' + regfield_cre = re.compile(r'^\s*REG32\(([A-Z][\w]+),\s+' r'((?:0x)?[A-Fa-f0-9]+)u?\)(?:\s|$)') for lno, line in enumerate(qfp, start=1): line = line.strip() @@ -208,7 +208,7 @@ def main(): debug = False qemu_default_dir = dirname(dirname(dirname(normpath(__file__)))) try: - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}.') argparser.add_argument('regs', nargs='+', metavar='file', help='register header file') @@ -238,7 +238,7 @@ def main(): loglevel = min(ERROR, loglevel) formatter = Formatter('%(levelname)8s %(name)-10s %(message)s') log = getLogger('ot') - logh = StreamHandler(stderr) + logh = StreamHandler(sys.stderr) logh.setFormatter(formatter) log.setLevel(loglevel) log.addHandler(logh) @@ -265,18 +265,18 @@ def main(): mismatch_count += mm_count if mismatch_count: - print(f'{mismatch_count} differences', file=stderr) - sysexit(1) - print('No differences', file=stderr) + print(f'{mismatch_count} differences', file=sys.stderr) + sys.exit(1) + print('No differences', file=sys.stderr) # pylint: disable=broad-except except Exception as exc: - print(f'\nError: {exc}', file=stderr) + print(f'\nError: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: - sysexit(2) + sys.exit(2) if __name__ == '__main__': diff --git a/scripts/opentitan/clang-format.d/opentitan.lst b/scripts/opentitan/clang-format.d/opentitan.lst index d68d1aee1cba..d8c2d3124b39 100644 --- a/scripts/opentitan/clang-format.d/opentitan.lst +++ b/scripts/opentitan/clang-format.d/opentitan.lst @@ -4,6 +4,7 @@ hw/opentitan/*.c hw/opentitan/*.h hw/riscv/debug.c hw/riscv/dm*.c +hw/riscv/dtm*.c hw/riscv/ibex*.c hw/riscv/ot_*.c include/hw/jtag/*.h @@ -11,6 +12,7 @@ include/hw/misc/pulp_rv_dm.h include/hw/opentitan/*.h include/hw/riscv/debug.h include/hw/riscv/dm*.h +include/hw/riscv/dtm*.h include/hw/riscv/ibex*.h include/hw/riscv/ot_*.h target/riscv/ibex*.c diff --git a/scripts/opentitan/dtm.py b/scripts/opentitan/dtm.py index 7308c396306f..8cc5aa16216c 100755 --- a/scripts/opentitan/dtm.py +++ b/scripts/opentitan/dtm.py @@ -11,28 +11,25 @@ from argparse import ArgumentParser, Namespace, FileType from io import BytesIO from os import linesep -from os.path import dirname, normpath +from os.path import dirname, join as joinpath, normpath from socket import create_connection, socket, AF_UNIX, SOCK_STREAM from traceback import format_exc from typing import Optional import sys -# pylint: disable=wrong-import-position -# pylint: disable=wrong-import-order -# pylint: disable=import-error +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) -# JTAG module is available from the scripts/ directory -sys.path.append(normpath(dirname(dirname(sys.argv[0])))) - -from ot.util.elf import ElfBlob # noqa: E402 -from ot.util.log import configure_loggers # noqa: E402 -from ot.util.misc import HexInt, dump_buffer # noqa: E402 -from ot.dtm import DebugTransportModule # noqa: E402 -from ot.dm import DebugModule # noqa: E402 -from jtag.bits import BitSequence # noqa: E402 -from jtag.bitbang import JtagBitbangController # noqa: E402 -from jtag.jtag import JtagEngine # noqa: E402 +from jtag.bitbang import JtagBitbangController +from jtag.bits import BitSequence +from jtag.jtag import JtagEngine +from ot.dm import DebugModule +from ot.dtm import DebugTransportModule +from ot.util.elf import ElfBlob +from ot.util.log import configure_loggers +from ot.util.misc import HexInt, dump_buffer DEFAULT_IR_LENGTH = 5 """Default TAP Instruction Register length.""" @@ -125,7 +122,8 @@ def main(): else: raise ValueError(f"Invalid socket type {socket_type}") else: - sock = create_connection((default_host, default_port), timeout=0.5) + sock = create_connection((default_host, default_port), + timeout=0.5) except Exception as exc: raise RuntimeError(f'Cannot connect to {args.socket}: ' f'{exc}') from exc diff --git a/scripts/opentitan/flashgen.py b/scripts/opentitan/flashgen.py index f2ca1d6805b1..9ee607e19a45 100755 --- a/scripts/opentitan/flashgen.py +++ b/scripts/opentitan/flashgen.py @@ -14,12 +14,17 @@ from itertools import repeat from logging import getLogger from os import SEEK_END, SEEK_SET, rename, stat -from os.path import abspath, basename, exists, isfile -from re import sub as re_sub +from os.path import (abspath, basename, dirname, exists, isfile, + join as joinpath, normpath) from struct import calcsize as scalc, pack as spack, unpack as sunpack -from sys import exit as sysexit, modules, stderr, version_info from traceback import format_exc from typing import Any, BinaryIO, NamedTuple, Optional +import re +import sys + +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) from ot.util.elf import ElfBlob from ot.util.log import configure_loggers @@ -159,9 +164,6 @@ def __init__(self, bl_offset: Optional[int] = None, hfmt = ''.join(self.HEADER_FORMAT.values()) header_size = scalc(hfmt) assert header_size == 32 - # dict in Python 3.7+ are kept ordered - if version_info[:2] < (3, 7): - raise RuntimeError('Unsupported Python version') self._header_size = header_size bhfmt = ''.join(self.BOOT_HEADER_FORMAT.values()) self._boot_header_size = scalc(bhfmt) @@ -488,7 +490,7 @@ def _build_boot_header(self, counter) -> bytes: def _get_elf_filename(self, filename: str) -> str: pathname = abspath(filename) - radix = re_sub(r'.[a-z_]+_0.signed.bin$', '', pathname) + radix = re.sub(r'.[a-z_]+_0.signed.bin$', '', pathname) elfname = f'{radix}.elf' if not exists(elfname): self._log.warning('No ELF debug info found') @@ -602,7 +604,7 @@ def main(): debug = True banks = list(range(FlashGen.NUM_BANKS)) try: - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}.') img = argparser.add_argument_group(title='Image') img.add_argument('flash', nargs=1, metavar='flash', @@ -682,17 +684,17 @@ def main(): finally: gen.close() if backup_filename: - print('Restoring previous file after error', file=stderr) + print('Restoring previous file after error', file=sys.stderr) rename(backup_filename, flash_pathname) # pylint: disable=broad-except except Exception as exc: - print(f'\nError: {exc}', file=stderr) + print(f'\nError: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: - sysexit(2) + sys.exit(2) if __name__ == '__main__': diff --git a/scripts/opentitan/gdbreplay.py b/scripts/opentitan/gdbreplay.py index 8c420926639c..cacd801c6ec0 100755 --- a/scripts/opentitan/gdbreplay.py +++ b/scripts/opentitan/gdbreplay.py @@ -13,13 +13,17 @@ from logging import getLogger from os import linesep from os.path import dirname, isfile, join as joinpath, normpath -from re import compile as re_compile from socket import (SOL_SOCKET, SO_REUSEADDR, SHUT_RDWR, socket, timeout as LegacyTimeoutError) from string import ascii_uppercase -from sys import exit as sysexit, modules, stderr from traceback import format_exc from typing import BinaryIO, Optional, TextIO +import re +import sys + +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) from ot.util.elf import ElfBlob from ot.util.log import configure_loggers @@ -280,7 +284,7 @@ class QEMUGDBReplay: """Maximum packet size.""" # Trace 0: 0x280003d00 [00000000/00008c9a/00101003/ff020000] _boot_start - TCRE = re_compile(r'^Trace\s(\d+):\s0x[0-9a-f]+\s\[[0-9a-f]+/([0-9a-f]+)' + TCRE = re.compile(r'^Trace\s(\d+):\s0x[0-9a-f]+\s\[[0-9a-f]+/([0-9a-f]+)' r'/[0-9a-f]+/[0-9a-f]+\](?:\s([&,<>\s\w:]+))?\s*$') """Regex to parse QEMU execution trace from a QEMU log file.""" @@ -444,6 +448,7 @@ def _handle_request(self, req: bytearray): else: self._send('') return + # pylint: disable=not-callable resp = handler(bytes(req[clen:])) if resp is not None: self._send(resp) @@ -522,6 +527,7 @@ def _do_q(self, payload: bytes): handler = getattr(self, f'_do_query_{parts[0].decode().lower()}', None) if not handler: return '' + # pylint: disable=not-callable return handler(bytes(parts[1]) if len(parts) > 1 else b'') def _do_m(self, payload: bytes) -> str: @@ -648,7 +654,7 @@ def main(): qemu_path = None try: args: Optional[Namespace] = None - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}.') argparser.add_argument('-t', '--trace', metavar='LOG', type=FileType('rt'), @@ -697,15 +703,15 @@ def main(): gdbr.serve(args.gdb) - sysexit(0) + sys.exit(0) # pylint: disable=broad-except except Exception as exc: - print(f'{linesep}Error: {exc}', file=stderr) + print(f'{linesep}Error: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: - sysexit(2) + sys.exit(2) if __name__ == '__main__': diff --git a/scripts/opentitan/gpiodev.py b/scripts/opentitan/gpiodev.py index 35803d27a562..3b02d140c2ad 100755 --- a/scripts/opentitan/gpiodev.py +++ b/scripts/opentitan/gpiodev.py @@ -10,12 +10,17 @@ from argparse import ArgumentParser, FileType from logging import getLogger -from re import match as re_match +from os.path import dirname, join as joinpath, normpath from socket import create_server, socket, SHUT_RDWR -from sys import exit as sysexit, modules, stderr from traceback import format_exc from time import sleep from typing import Optional, TextIO +import re +import sys + +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) from ot.util.log import configure_loggers from ot.util.misc import HexInt @@ -40,7 +45,7 @@ def load(self, lfp: TextIO) -> None: error = 0 for lno, line in enumerate(lfp, start=1): line = line.strip() - cmo = re_match(chk_re, line) + cmo = re.match(chk_re, line) if not cmo: self._log.error('Unknown check line @ %d: %s', lno, line) error += 1 @@ -214,6 +219,7 @@ def _inject(self, line: str, it_cmd: Optional[GpioChecker.Iterator]) -> \ return None self._log.info('Execute %s: 0x%08x', command, word) self._record.append((cmd, word)) + # pylint: disable=not-callable out = handler(word) if it_cmd: try: @@ -268,7 +274,7 @@ def main(): """ debug = False try: - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}.') argparser.add_argument('-p', '--port', type=int, default=8007, help='remote host TCP port (defaults to 8007)') @@ -305,15 +311,15 @@ def main(): exec_ok = gpio.run(args.port, args.single, args.quit_on_error, args.end) if args.record: gpio.save(args.record) - sysexit(int(not exec_ok)) + sys.exit(int(not exec_ok)) except (IOError, ValueError, ImportError) as exc: - print(f'\nError: {exc}', file=stderr) + print(f'\nError: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: - sysexit(2) + sys.exit(2) if __name__ == '__main__': diff --git a/scripts/opentitan/loghelp.py b/scripts/opentitan/loghelp.py index 40011d9f846c..404a6ce8778f 100755 --- a/scripts/opentitan/loghelp.py +++ b/scripts/opentitan/loghelp.py @@ -10,17 +10,21 @@ from argparse import ArgumentParser, FileType from logging import getLogger -from os.path import basename, splitext -from re import compile as re_compile, sub as re_sub -from sys import exit as sysexit, modules, stderr +from os.path import basename, dirname, splitext, join as joinpath, normpath from traceback import format_exc from typing import TextIO +import re +import sys + +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) from ot.util.log import configure_loggers # pylint: disable=missing-function-docstring -REG_CRE = re_compile(r'^#define ([A-Z][\w]+)_REG_(OFFSET|RESVAL)\s+' +REG_CRE = re.compile(r'^#define ([A-Z][\w]+)_REG_(OFFSET|RESVAL)\s+' r'((?:0x)?[A-Fa-f0-9]+)(?:\s|$)') RegisterDefs = dict[str, tuple[int, int]] @@ -40,7 +44,7 @@ def parse_defs(hfp: TextIO) -> RegisterDefs: sregname = rmo.group(1) sregkind = rmo.group(2) sregaddr = rmo.group(3) - regname = re_sub(radix_re, '', sregname) + regname = re.sub(radix_re, '', sregname) regval = int(sregaddr, 16 if sregaddr.startswith('0x') else 10) if sregkind == 'OFFSET': defs[regname] = (regval, 0) @@ -86,7 +90,7 @@ def main(): """Main routine""" debug = False try: - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}.') argparser.add_argument('log', nargs=1, metavar='file', type=FileType('rt'), @@ -111,12 +115,12 @@ def main(): # pylint: disable=broad-except except Exception as exc: - print(f'\nError: {exc}', file=stderr) + print(f'\nError: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: - sysexit(2) + sys.exit(2) if __name__ == '__main__': diff --git a/scripts/opentitan/mbbdef.py b/scripts/opentitan/mbbdef.py index 366ec94baaa3..398a21a3e75c 100755 --- a/scripts/opentitan/mbbdef.py +++ b/scripts/opentitan/mbbdef.py @@ -11,11 +11,15 @@ from argparse import ArgumentParser from logging import getLogger from os import walk -from os.path import basename, dirname, join as joinpath, splitext +from os.path import basename, dirname, join as joinpath, normpath, splitext from pprint import pprint -from sys import exit as sysexit, modules, stderr from traceback import format_exc from typing import Iterator, TextIO +import sys + +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) from ot.util.log import configure_loggers @@ -113,7 +117,7 @@ def main(): """Main routine""" debug = False try: - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}.') argparser.add_argument('ot', nargs='+', metavar='dir', help='HJSON top-level directory') @@ -132,12 +136,12 @@ def main(): # pylint: disable=broad-except except Exception as exc: - print(f'\nError: {exc}', file=stderr) + print(f'\nError: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: - sysexit(2) + sys.exit(2) if __name__ == '__main__': diff --git a/scripts/opentitan/otpdm.py b/scripts/opentitan/otpdm.py index 2b7c73bee8b7..1703f63ad780 100755 --- a/scripts/opentitan/otpdm.py +++ b/scripts/opentitan/otpdm.py @@ -18,21 +18,19 @@ from typing import Optional import sys -# pylint: disable=wrong-import-position -# pylint: disable=wrong-import-order -# pylint: disable=import-error - -# JTAG module is available from the scripts/ directory -sys.path.append(joinpath(normpath(dirname(dirname(sys.argv[0]))))) - -from ot.util.log import configure_loggers # noqa: E402 -from ot.util.misc import HexInt, dump_buffer # noqa: E402 -from ot.dtm import DebugTransportModule # noqa: E402 -from ot.dm import DebugModule # noqa: E402 -from ot.dm.otp import OTPController # noqa: E402 -from ot.otp import OtpMap # noqa: E402 -from jtag.bitbang import JtagBitbangController # noqa: E402 -from jtag.jtag import JtagEngine # noqa: E402 +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) + +from jtag.bitbang import JtagBitbangController +from jtag.jtag import JtagEngine + +from ot.dm import DebugModule +from ot.dm.otp import OTPController +from ot.dtm import DebugTransportModule +from ot.otp import OtpMap +from ot.util.log import configure_loggers +from ot.util.misc import HexInt, dump_buffer DEFAULT_IR_LENGTH = 5 diff --git a/scripts/opentitan/otptool.py b/scripts/opentitan/otptool.py index 8903b1ba4d05..58174484db42 100755 --- a/scripts/opentitan/otptool.py +++ b/scripts/opentitan/otptool.py @@ -9,20 +9,19 @@ """ from argparse import ArgumentParser, FileType -from os.path import basename -from sys import argv, exit as sysexit, modules, stderr, stdout, version_info +from os.path import basename, dirname, join as joinpath, normpath from traceback import format_exc from typing import Optional +import sys +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) + +from ot.otp import (OtpImage, OtpLifecycleExtension, OtpMap, + OTPPartitionDesc, OTPRegisterDef) from ot.util.log import configure_loggers from ot.util.misc import HexInt -from ot.otp import (OtpImage, OtpLifecycleExtension, OtpMap, OTPPartitionDesc, - OTPRegisterDef) - - -# requirement: Python 3.7+: dict entries are kept in creation order -if version_info[:2] < (3, 7): - raise RuntimeError('Unsupported Python version') def main(): @@ -30,7 +29,7 @@ def main(): debug = True genfmts = 'LCVAL LCTPL PARTS REGS'.split() try: - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}.') files = argparser.add_argument_group(title='Files') files.add_argument('-j', '--otp-map', type=FileType('rt'), @@ -150,17 +149,18 @@ def main(): elif args.generate in ('LCVAL', 'LCTPL'): argparser.error('Cannot generate LC array w/o a lifecycle file') - output = stdout if not args.output else args.output + output = sys.stdout if not args.output else args.output if not args.generate: pass elif args.generate == 'PARTS': partdesc = OTPPartitionDesc(otpmap) - partdesc.save(basename(args.otp_map.name), basename(argv[0]), + partdesc.save(basename(args.otp_map.name), basename(sys.argv[0]), output) elif args.generate == 'REGS': regdef = OTPRegisterDef(otpmap) - regdef.save(basename(args.otp_map.name), basename(argv[0]), output) + regdef.save(basename(args.otp_map.name), basename(sys.argv[0]), + output) elif args.generate == 'LCVAL': lcext.save(output, True) elif args.generate == 'LCTPL': @@ -206,7 +206,7 @@ def main(): if lcext: otp.load_lifecycle(lcext) if args.show: - otp.decode(not args.no_decode, args.wide, stdout) + otp.decode(not args.no_decode, args.wide, sys.stdout) if args.digest: if not otp.has_present_constants: if args.raw and otp.version == 1: @@ -230,12 +230,12 @@ def main(): otp.save_raw(rfp) except (IOError, ValueError, ImportError) as exc: - print(f'\nError: {exc}', file=stderr) + print(f'\nError: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: - sysexit(2) + sys.exit(2) if __name__ == '__main__': diff --git a/scripts/opentitan/pyot.py b/scripts/opentitan/pyot.py index c4a507cb95ee..53f6e0ae8c53 100755 --- a/scripts/opentitan/pyot.py +++ b/scripts/opentitan/pyot.py @@ -15,11 +15,13 @@ from fnmatch import fnmatchcase from glob import glob try: - # try to use HJSON if available + _HJSON_ERROR = None from hjson import load as jload -except ImportError: - # fallback on legacy JSON syntax otherwise - from json import load as jload +except ImportError as hjson_exc: + _HJSON_ERROR = str(hjson_exc) + def hjload(*_, **__): # noqa: E301 + """dummy func if HJSON module is not available""" + return {} from os import close, curdir, environ, getcwd, linesep, pardir, sep, unlink from os.path import (abspath, basename, dirname, exists, isabs, isdir, isfile, join as joinpath, normpath, relpath) @@ -27,7 +29,6 @@ from shutil import rmtree from socket import socket, timeout as LegacyTimeoutError from subprocess import Popen, PIPE, TimeoutExpired -from sys import argv, exit as sysexit, modules, stderr from threading import Event, Thread from tempfile import mkdtemp, mkstemp from time import time as now @@ -36,6 +37,16 @@ import logging import re +import sys + +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) +print(__file__, sys.path[-1]) + +# pylint: disable=wrong-import-position +# pylint: disable=wrong-import-order +# pylint: disable=import-error from ot.util.log import ColorLogFormatter, configure_loggers from ot.util.misc import EasyDict @@ -312,7 +323,7 @@ def trig_match(bline): except OSError as exc: log.error('Cannot setup QEMU VCP connection %s: %s', vcpid, exc) - print(format_exc(chain=False), file=stderr) + print(format_exc(chain=False), file=sys.stderr) raise # removal from dictionary cannot be done while iterating it for vcpid in connected: @@ -591,6 +602,9 @@ def replace(smo: re.Match) -> str: name = smo.group(1) val = self._env[name] if name in self._env \ else environ.get(name, '') + if not val: + getLogger('pyot.file').warning("Unknown placeholder '%s'", + name) return val svalue = str(value) nvalue = re.sub(r'\$\{(\w+)\}', replace, svalue) @@ -1225,7 +1239,7 @@ def run(self, debug: bool, allow_no_test: bool) -> int: except Exception as exc: self._log.critical('%s', str(exc)) if debug: - print(format_exc(chain=False), file=stderr) + print(format_exc(chain=False), file=sys.stderr) tret = 99 xtime = 0.0 err = str(exc) @@ -1706,9 +1720,10 @@ def main(): if not isfile(qemu_path): qemu_path = None tmp_result: Optional[str] = None + result_file: Optional[str] = None try: args: Optional[Namespace] = None - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}.') qvm = argparser.add_argument_group(title='Virtual machine') rel_qemu_path = relpath(qemu_path) if qemu_path else '?' @@ -1749,9 +1764,9 @@ def main(): files = argparser.add_argument_group(title='Files') files.add_argument('-b', '--boot', metavar='file', help='bootloader 0 file') - files.add_argument('-c', '--config', metavar='JSON', + files.add_argument('-c', '--config', metavar='HJSON', type=FileType('rt', encoding='utf-8'), - help='path to configuration file') + help='path to HJSON configuration file') files.add_argument('-e', '--embedded-flash', action='store_true', help='generate an embedded flash image file') files.add_argument('-f', '--flash', metavar='RAW', @@ -1811,20 +1826,26 @@ def main(): try: # all arguments after `--` are forwarded to QEMU - pos = argv.index('--') - sargv = argv[1:pos] - opts = argv[pos+1:] + pos = sys.argv.index('--') + sargv = sys.argv[1:pos] + opts = sys.argv[pos+1:] except ValueError: - sargv = argv[1:] + sargv = sys.argv[1:] opts = [] cli_opts = list(opts) args = argparser.parse_args(sargv) if args.debug is not None: debug = args.debug - if args.summary and not args.result: - tmpfd, tmp_result = mkstemp(suffix='.csv') - close(tmpfd) - args.result = tmp_result + + if _HJSON_ERROR: + argparser.error('Missing HJSON module: {_HJSON_ERROR}') + + if args.summary: + if not args.result: + tmpfd, tmp_result = mkstemp(suffix='.csv') + close(tmpfd) + args.result = tmp_result + result_file = args.result log = configure_loggers(args.verbose, 'pyot', args.vcp_verbose or 0, @@ -1864,6 +1885,7 @@ def main(): continue optname = f'--{arg}' if len(arg) > 1 else f'-{arg}' if isinstance(val, list): + val = QEMUExecuter.flatten(v.split() for v in val) for valit in val: jargs.append(f'{optname}={qfm.interpolate(valit)}') else: @@ -1908,29 +1930,33 @@ def main(): if args.list: for tst in qexc.enumerate_tests(): print(tst) - sysexit(0) + sys.exit(0) try: qexc.build() except ValueError as exc: if debug: - print(format_exc(chain=False), file=stderr) + print(format_exc(chain=False), file=sys.stderr) argparser.error(str(exc)) ret = qexc.run(debug, args.zero) - if args.summary: - rfmt = ResultFormatter() - rfmt.load(args.result) - rfmt.show(True) log.debug('End of execution with code %d', ret or 0) - sysexit(ret) + sys.exit(ret) # pylint: disable=broad-except except Exception as exc: - print(f'{linesep}Error: {exc}', file=stderr) + print(f'{linesep}Error: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: - sysexit(2) + sys.exit(2) finally: + if result_file: + rfmt = ResultFormatter() + try: + rfmt.load(result_file) + rfmt.show(True) + # pylint: disable=broad-except + except Exception as exc: + print(f'Cannot generate result file: {exc}', file=sys.stderr) if tmp_result and isfile(tmp_result): unlink(tmp_result) diff --git a/scripts/opentitan/spidevflash.py b/scripts/opentitan/spidevflash.py index 81190803a8b8..36c9324c2606 100755 --- a/scripts/opentitan/spidevflash.py +++ b/scripts/opentitan/spidevflash.py @@ -11,9 +11,14 @@ from argparse import ArgumentParser, FileType from logging import getLogger from os import linesep -from sys import exit as sysexit, modules, stderr +from os.path import dirname, join as joinpath, normpath from time import sleep, time as now from traceback import format_exc +import sys + +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) from ot.spi import SpiDevice from ot.util.log import configure_loggers @@ -83,7 +88,7 @@ def main(): """Main routine""" debug = True try: - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}.') argparser.add_argument('-f', '--file', type=FileType('rb'), required=True, @@ -114,15 +119,15 @@ def main(): flasher.program(data, args.address) flasher.disconnect() - sysexit(0) + sys.exit(0) # pylint: disable=broad-except except Exception as exc: - print(f'{linesep}Error: {exc}', file=stderr) + print(f'{linesep}Error: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: - sysexit(2) + sys.exit(2) if __name__ == '__main__': diff --git a/scripts/opentitan/swexit.py b/scripts/opentitan/swexit.py index de49aa87d3b7..953a6e724593 100755 --- a/scripts/opentitan/swexit.py +++ b/scripts/opentitan/swexit.py @@ -10,13 +10,12 @@ from argparse import ArgumentParser, FileType from struct import pack as spack -from sys import exit as sysexit, modules, stderr, stdout from traceback import format_exc from typing import Union +import sys # pylint: disable=missing-function-docstring - BASE_ADDRESS = { 'earlgrey': 0x411f0000, 'darjeeling': 0x211f0000, @@ -26,7 +25,7 @@ LUI_MASK = (1 << 12) - 1 -def to_int(value: Union[int,str]) -> int: +def to_int(value: Union[int, str]) -> int: if isinstance(value, int): return value return int(value.strip(), value.startswith('0x') and 16 or 10) @@ -55,12 +54,14 @@ def ibexdemo_code(addr: int) -> bytes: def main(): debug = False try: - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}') argparser.add_argument('-a', '--address', type=to_int, - help='Base address for swexit device (default: depends on SoC)') + help='Base address for swexit device ' + '(default: depends on SoC)') argparser.add_argument('-b', '--base', type=to_int, default=0x80, - help='Offset for the first instruction (default: 0x80)') + help='Offset for the first instruction ' + '(default: 0x80)') argparser.add_argument('-t', '--soc', choices=list(BASE_ADDRESS), help='SoC type', required=True) argparser.add_argument('-o', '--output', type=FileType('wb'), @@ -75,19 +76,19 @@ def main(): bincode = ibexdemo_code(addr) else: bincode = opentitan_code(addr) - out = args.output or stdout.buffer + out = args.output or sys.stdout.buffer padding = bytes(args.base) out.write(padding) out.write(bincode) # pylint: disable=broad-except except Exception as exc: - print(f'\nError: {exc}', file=stderr) + print(f'\nError: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: - sysexit(2) + sys.exit(2) if __name__ == '__main__': diff --git a/scripts/opentitan/tap.py b/scripts/opentitan/tap.py index d0f64c2d16f9..85f044ec3720 100755 --- a/scripts/opentitan/tap.py +++ b/scripts/opentitan/tap.py @@ -11,10 +11,15 @@ from argparse import ArgumentParser from enum import IntEnum from logging import getLogger +from os.path import dirname, join as joinpath, normpath from socket import create_server, socket, SHUT_RDWR -from sys import exit as sysexit, modules, stderr from traceback import format_exc from typing import Optional +import sys + +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) from ot.util.log import configure_loggers @@ -313,6 +318,7 @@ def _inject(self, req: bytes) -> Optional[bool]: if handler is None: self._log.warning('Unimplemented handler for %s', command) return None + # pylint: disable=not-callable return handler(*args) def _inject_quit(self): @@ -486,6 +492,7 @@ def update(self): f' {data:08x}' if write else '') handler = getattr(self, f'_{regname}_{opname}', None) if handler: + # pylint: disable=not-callable handler(data) def _dmcontrol_write(self, value: int): @@ -616,7 +623,7 @@ def main(): """ debug = False try: - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}.') argparser.add_argument('-p', '--port', type=int, default=3335, help='remote host TCP port (defaults to 3335)') @@ -634,15 +641,15 @@ def main(): ext = TAPExtension(args.abits) tap = BitBangController(ext) tap.run(args.port) - sysexit(0) + sys.exit(0) except (IOError, ValueError, ImportError) as exc: - print(f'\nError: {exc}', file=stderr) + print(f'\nError: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: - sysexit(2) + sys.exit(2) if __name__ == '__main__': diff --git a/scripts/opentitan/uartmux.py b/scripts/opentitan/uartmux.py index 42e8ba911996..8a19922b1747 100755 --- a/scripts/opentitan/uartmux.py +++ b/scripts/opentitan/uartmux.py @@ -11,11 +11,16 @@ from argparse import ArgumentParser from collections import deque from logging import getLogger +from os.path import dirname, join as joinpath, normpath from socketserver import StreamRequestHandler, ThreadingTCPServer -from sys import exit as sysexit, modules, stderr, stdout from threading import Event, Lock, Thread from traceback import format_exc from typing import Optional, TextIO +import sys + +QEMU_PYPATH = joinpath(dirname(dirname(dirname(normpath(__file__)))), + 'python', 'qemu') +sys.path.append(QEMU_PYPATH) from ot.util.log import configure_loggers @@ -67,7 +72,7 @@ def handle(self): self.server.push(self._id, line) except Exception as exc: if self.server.debug: - print(format_exc(chain=False), file=stderr) + print(format_exc(chain=False), file=sys.stderr) else: self._log.critical('Error: %s', str(exc)) self.server.resume = False @@ -206,7 +211,7 @@ def main(): default_channel_count = 3 mux = None try: - desc = modules[__name__].__doc__.split('.', 1)[0].strip() + desc = sys.modules[__name__].__doc__.split('.', 1)[0].strip() argparser = ArgumentParser(description=f'{desc}.') argparser.add_argument('name', nargs='*', help='assign name to input connection') @@ -231,21 +236,22 @@ def main(): configure_loggers(args.verbose, 'mux') ThreadingTCPServer.allow_reuse_address = True - mux = UartMuxer((args.iface, args.port), stdout, debug, args.separator) + mux = UartMuxer((args.iface, args.port), sys.stdout, debug, + args.separator) channel = args.channel if channel is None: channel = len(args.name) if args.name else default_channel_count mux.run(channel, args.name) except (IOError, ValueError, ImportError) as exc: - print(f'\nError: {exc}', file=stderr) + print(f'\nError: {exc}', file=sys.stderr) if debug: - print(format_exc(chain=False), file=stderr) - sysexit(1) + print(format_exc(chain=False), file=sys.stderr) + sys.exit(1) except KeyboardInterrupt: if mux: mux.resume = False - sysexit(2) + sys.exit(2) if __name__ == '__main__':