diff --git a/sw/device/silicon_creator/lib/base/sec_mmio.c b/sw/device/silicon_creator/lib/base/sec_mmio.c index 514029fec4c00..d798e782696cf 100644 --- a/sw/device/silicon_creator/lib/base/sec_mmio.c +++ b/sw/device/silicon_creator/lib/base/sec_mmio.c @@ -63,6 +63,17 @@ void sec_mmio_init(sec_mmio_shutdown_handler cb) { sec_mmio_ctx.expected_write_count = 0; for (size_t i = 0; i < ARRAYSIZE(sec_mmio_ctx.addrs); ++i) { sec_mmio_ctx.addrs[i] = UINT32_MAX; + sec_mmio_ctx.values[i] = UINT32_MAX; + } +} + +void sec_mmio_next_stage_init(sec_mmio_shutdown_handler cb) { + sec_mmio_shutdown_cb = cb; + sec_mmio_ctx.check_count = 0; + for (size_t i = sec_mmio_ctx.last_index; i < ARRAYSIZE(sec_mmio_ctx.addrs); + ++i) { + sec_mmio_ctx.addrs[i] = UINT32_MAX; + sec_mmio_ctx.values[i] = UINT32_MAX; } } diff --git a/sw/device/silicon_creator/lib/base/sec_mmio.h b/sw/device/silicon_creator/lib/base/sec_mmio.h index e63f03954276d..666b29a877218 100644 --- a/sw/device/silicon_creator/lib/base/sec_mmio.h +++ b/sw/device/silicon_creator/lib/base/sec_mmio.h @@ -131,6 +131,21 @@ typedef void (*sec_mmio_shutdown_handler)(rom_error_t); */ void sec_mmio_init(sec_mmio_shutdown_handler cb); +/** + * Executes sec_mmio next boot stage initialization. + * + * Registers the `cb` callback handler, and performs the following operations to + * the internal `sec_mmio_ctx_t` context: + * + * - Clear the check count. This allows the caller to reset the + * `sec_mmio_check_counters()` expected count argument. + * - Reset all expected address and values in the expectations table starting at + * the last_index. + * + * @param cb Shutdown module callback handler. + */ +void sec_mmio_next_stage_init(sec_mmio_shutdown_handler cb); + /** * Reads an aligned uint32_t from the MMIO region `addr`. * diff --git a/sw/device/silicon_creator/lib/base/sec_mmio_unittest.cc b/sw/device/silicon_creator/lib/base/sec_mmio_unittest.cc index 031709d5345d5..0655faafd960a 100644 --- a/sw/device/silicon_creator/lib/base/sec_mmio_unittest.cc +++ b/sw/device/silicon_creator/lib/base/sec_mmio_unittest.cc @@ -20,6 +20,7 @@ extern sec_mmio_ctx_t sec_mmio_ctx; namespace sec_mmio_unittest { namespace { using ::testing::Each; +using ::testing::ElementsAreArray; using ::testing::Eq; using ::testing::Test; @@ -46,6 +47,46 @@ TEST_F(SecMmioTest, Initialize) { EXPECT_EQ(ctx_->last_index, 0); EXPECT_EQ(ctx_->write_count, 0); EXPECT_THAT(ctx_->addrs, Each(Eq(UINT32_MAX))); + EXPECT_THAT(ctx_->values, Each(Eq(UINT32_MAX))); +} + +TEST_F(SecMmioTest, NextStageInitialize) { + // Ensure the register file size is greater than zero to ensure checks are + // performed on non-zero sized arrays. + static_assert(kSecMmioRegFileSize > 2); + std::array expected_addrs; + std::array expected_values; + + // Prefill data to simulate a pre-initialization conditions. Use different + // values for `addr` and `values` to ensure the test checks are specific for + // each array. + for (size_t i = 0; i < kSecMmioRegFileSize; ++i) { + ctx_->addrs[i] = i ^ 0xa; + ctx_->values[i] = i ^ 0x5; + expected_addrs[i] = ctx_->addrs[i]; + expected_values[i] = ctx_->values[i]; + } + + ctx_->check_count = 5; + ctx_->expected_write_count = 6; + ctx_->write_count = 6; + + const uint32_t kExpectedWriteCount = kSecMmioRegFileSize / 2; + ctx_->last_index = kExpectedWriteCount; + + for (size_t i = kExpectedWriteCount; i < kSecMmioRegFileSize; ++i) { + expected_addrs[i] = UINT32_MAX; + expected_values[i] = UINT32_MAX; + } + + sec_mmio_next_stage_init(+[](rom_error_t) { std::abort(); }); + + EXPECT_EQ(ctx_->write_count, 6); + EXPECT_EQ(ctx_->expected_write_count, 6); + EXPECT_EQ(ctx_->last_index, kExpectedWriteCount); + EXPECT_EQ(ctx_->check_count, 0); + EXPECT_THAT(ctx_->addrs, ElementsAreArray(expected_addrs)); + EXPECT_THAT(ctx_->values, ElementsAreArray(expected_values)); } TEST_F(SecMmioTest, Read32OrDie) {