[dif_sram_ctrl] Add missing implementation
This change adds `dif_sram_ctrl_scramble` implementation and
unittests.
This function constitutes the recommended way of completely scrambling
the SRAM. The function is blocking, the alternative way of
constructing a non-blocking version is described in the description.
`dif_sram_ctrl_scramble_is_busy` has been removed from the header file,
as there is no real need for it, the status can be queried through
`dif_sram_ctrl_get_status`.
`dif_sram_ctrl_wipe` is implemented in #10490 .
Signed-off-by: Silvestrs Timofejevs <silvestrst@lowrisc.org>
diff --git a/sw/device/lib/dif/dif_sram_ctrl.c b/sw/device/lib/dif/dif_sram_ctrl.c
index fa8914f..46a4a7b 100644
--- a/sw/device/lib/dif/dif_sram_ctrl.c
+++ b/sw/device/lib/dif/dif_sram_ctrl.c
@@ -64,6 +64,39 @@
return mmio_region_read32(sram_ctrl->base_addr, SRAM_CTRL_STATUS_REG_OFFSET);
}
+dif_result_t dif_sram_ctrl_scramble(const dif_sram_ctrl_t *sram_ctrl) {
+ if (sram_ctrl == NULL) {
+ return kDifBadArg;
+ }
+
+ if (sram_ctrl_locked_ctrl(sram_ctrl)) {
+ return kDifLocked;
+ }
+
+ // Issue request for new scrambling key.
+ uint32_t reg =
+ bitfield_bit32_write(0, SRAM_CTRL_CTRL_RENEW_SCR_KEY_BIT, true);
+ mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_CTRL_REG_OFFSET, reg);
+
+ // Wait until the scrambling key has been updated.
+ dif_sram_ctrl_status_bitfield_t status;
+ do {
+ status = sram_ctrl_get_status(sram_ctrl);
+ } while ((status & kDifSramCtrlStatusScrKeyValid) == 0);
+
+ // Overwrite memory with pseudo random data.
+ reg = bitfield_bit32_write(0, SRAM_CTRL_CTRL_INIT_BIT, true);
+ mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_CTRL_REG_OFFSET, reg);
+
+ // Wait for memory to be overwritten with pseudo random data.
+ do {
+ status = sram_ctrl_get_status(sram_ctrl);
+ } while ((status & kDifSramCtrlStatusInitDone) == 0);
+
+ // Check for the errors during memory overwriting.
+ return (status & kDifSramCtrlStatusInitErr) == 0 ? kDifOk : kDifError;
+}
+
dif_result_t dif_sram_ctrl_request_new_key(const dif_sram_ctrl_t *sram_ctrl) {
if (sram_ctrl == NULL) {
return kDifBadArg;
diff --git a/sw/device/lib/dif/dif_sram_ctrl.h b/sw/device/lib/dif/dif_sram_ctrl.h
index 8fe221f..9bfdb9f 100644
--- a/sw/device/lib/dif/dif_sram_ctrl.h
+++ b/sw/device/lib/dif/dif_sram_ctrl.h
@@ -94,7 +94,7 @@
} dif_sram_ctrl_lock_t;
/**
- * Performs SRAM scrambling.
+ * Performs blocking SRAM scrambling operation.
*
* This function should only be called when the data is no longer used.
*
@@ -107,13 +107,10 @@
* values or predictable data that could potentially make "unscrambling"
* easier.
*
- * This operation is expected to take a significant amount of CPU cycles. The
- * status can be checked via `dif_sram_ctrl_scramble_is_busy`, which is useful
- * when a non-blocking work flow is desirable. Otherwise any SRAM access will
- * automatically block until this operation has finished.
- *
- * The equivalent effect can be achieved by calling
- * `dif_sram_ctrl_request_new_key`, followed by `dif_sram_ctrl_wipe`.
+ * This operation is expected to take a significant amount of CPU cycles. If
+ * a non-blocking alternative is required, then `dif_sram_ctrl_request_new_key`,
+ * should be used followed by `dif_sram_ctrl_wipe`. The status of these
+ * operations can be found through `dif_sram_ctrl_get_status`.
*
* Note: when dealing with the Main RAM, additional implication is that the
* C runtime can be invalidated by the call to this function, and must be
@@ -126,19 +123,6 @@
dif_result_t dif_sram_ctrl_scramble(const dif_sram_ctrl_t *sram_ctrl);
/**
- * Checks whether SRAM scramble is still progress.
- *
- * Useful when a non-blocking work flow is desirable.
- *
- * @param sram_ctrl A SRAM Controller handle.
- * @param[out] is_busy Out-param for the busy state.
- * @return The result of the operation.
- */
-OT_WARN_UNUSED_RESULT
-dif_result_t dif_sram_ctrl_scramble_is_busy(const dif_sram_ctrl_t *sram_ctrl,
- bool *is_busy);
-
-/**
* Requests a new scrambling key.
*
* This function should only be called when the data is no longer used.
diff --git a/sw/device/lib/dif/dif_sram_ctrl_unittest.cc b/sw/device/lib/dif/dif_sram_ctrl_unittest.cc
index b503d20..34a050d 100644
--- a/sw/device/lib/dif/dif_sram_ctrl_unittest.cc
+++ b/sw/device/lib/dif/dif_sram_ctrl_unittest.cc
@@ -23,6 +23,60 @@
dif_sram_ctrl_t sram_ctrl_ = {.base_addr = dev().region()};
};
+class Scramble : public SramCtrlTest {};
+
+TEST_F(Scramble, NullArgs) {
+ EXPECT_EQ(dif_sram_ctrl_scramble(nullptr), kDifBadArg);
+}
+
+TEST_F(Scramble, Locked) {
+ EXPECT_READ32(SRAM_CTRL_CTRL_REGWEN_REG_OFFSET, 0);
+ EXPECT_EQ(dif_sram_ctrl_scramble(&sram_ctrl_), kDifLocked);
+}
+
+TEST_F(Scramble, Failure) {
+ EXPECT_READ32(SRAM_CTRL_CTRL_REGWEN_REG_OFFSET, 1);
+
+ // Issue request for new scrambling key.
+ EXPECT_WRITE32(SRAM_CTRL_CTRL_REG_OFFSET,
+ {{SRAM_CTRL_CTRL_RENEW_SCR_KEY_BIT, true},
+ {SRAM_CTRL_CTRL_INIT_BIT, false}});
+ EXPECT_READ32(SRAM_CTRL_STATUS_REG_OFFSET, kDifSramCtrlStatusScrKeyValid);
+
+ // Overwrite memory with pseudo random data.
+ EXPECT_WRITE32(SRAM_CTRL_CTRL_REG_OFFSET,
+ {{SRAM_CTRL_CTRL_RENEW_SCR_KEY_BIT, false},
+ {SRAM_CTRL_CTRL_INIT_BIT, true}});
+ EXPECT_READ32(SRAM_CTRL_STATUS_REG_OFFSET,
+ std::numeric_limits<uint32_t>::max());
+
+ EXPECT_EQ(dif_sram_ctrl_scramble(&sram_ctrl_), kDifError);
+}
+
+TEST_F(Scramble, Success) {
+ EXPECT_READ32(SRAM_CTRL_CTRL_REGWEN_REG_OFFSET, 1);
+
+ // Issue request for new scrambling key, and emulate three iteration status
+ // read loop.
+ EXPECT_WRITE32(SRAM_CTRL_CTRL_REG_OFFSET,
+ {{SRAM_CTRL_CTRL_RENEW_SCR_KEY_BIT, true},
+ {SRAM_CTRL_CTRL_INIT_BIT, false}});
+ EXPECT_READ32(SRAM_CTRL_STATUS_REG_OFFSET, 0);
+ EXPECT_READ32(SRAM_CTRL_STATUS_REG_OFFSET, 0);
+ EXPECT_READ32(SRAM_CTRL_STATUS_REG_OFFSET, kDifSramCtrlStatusScrKeyValid);
+
+ // Overwrite memory with pseudo random data, and emulate three iteration
+ // status read loop.
+ EXPECT_WRITE32(SRAM_CTRL_CTRL_REG_OFFSET,
+ {{SRAM_CTRL_CTRL_RENEW_SCR_KEY_BIT, false},
+ {SRAM_CTRL_CTRL_INIT_BIT, true}});
+ EXPECT_READ32(SRAM_CTRL_STATUS_REG_OFFSET, 0);
+ EXPECT_READ32(SRAM_CTRL_STATUS_REG_OFFSET, 0);
+ EXPECT_READ32(SRAM_CTRL_STATUS_REG_OFFSET, kDifSramCtrlStatusInitDone);
+
+ EXPECT_EQ(dif_sram_ctrl_scramble(&sram_ctrl_), kDifOk);
+}
+
class RequestNewKeyTest : public SramCtrlTest {};
TEST_F(RequestNewKeyTest, NullArgs) {