Software APIs
flash_ctrl_unittest.cc
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
6 
7 #include <array>
8 
9 #include "absl/strings/str_cat.h"
10 #include "gtest/gtest.h"
11 #include "sw/device/lib/base/mock_abs_mmio.h"
12 #include "sw/device/lib/base/mock_mmio_test_utils.h"
13 #include "sw/device/lib/base/multibits.h"
14 #include "sw/device/silicon_creator/lib/base/mock_sec_mmio.h"
15 #include "sw/device/silicon_creator/lib/drivers/mock_otp.h"
16 #include "sw/device/silicon_creator/lib/error.h"
17 #include "sw/device/silicon_creator/testing/rom_test.h"
18 
19 #include "flash_ctrl_regs.h"
21 #include "otp_ctrl_regs.h"
22 
23 namespace flash_ctrl_unittest {
24 namespace {
25 using ::testing::Each;
26 using ::testing::Return;
27 using ::testing::SizeIs;
28 
29 /**
30  * A struct that holds bank, page, and config register information for an
31  * information page.
32  */
33 struct InfoPage {
34  uint32_t bank;
35  uint32_t page;
36  uint32_t cfg_offset;
37  uint32_t cfg_wen_offset;
38 };
39 
40 /**
41  * Returns a map from `flash_ctrl_info_page_t` to `InfoPage` to be used in
42  * tests.
43  */
44 const std::map<const flash_ctrl_info_page_t *, InfoPage> &InfoPages() {
45 #define INFO_PAGE_MAP_INIT(name_, bank_, page_) \
46  { \
47  &name_, \
48  { \
49  bank_, \
50  page_, \
51  FLASH_CTRL_BANK##bank_##_INFO0_PAGE_CFG_##page_##_REG_OFFSET, \
52  FLASH_CTRL_BANK##bank_##_INFO0_REGWEN_##page_##_REG_OFFSET, \
53  }, \
54  },
55 
56  static const std::map<const flash_ctrl_info_page_t *, InfoPage> *const
57  kInfoPages = new std::map<const flash_ctrl_info_page_t *, InfoPage>{
58  FLASH_CTRL_INFO_PAGES_DEFINE(INFO_PAGE_MAP_INIT)};
59  return *kInfoPages;
60 }
61 
63  protected:
65  rom_test::MockAbsMmio mmio_;
66  rom_test::MockSecMmio sec_mmio_;
67  rom_test::MockOtp otp_;
68 };
69 
70 class InfoPagesTest : public FlashCtrlTest {};
71 TEST_F(InfoPagesTest, NumberOfPages) { EXPECT_THAT(InfoPages(), SizeIs(20)); }
72 
73 TEST_F(InfoPagesTest, PagesPerBank) {
74  std::array<uint32_t, 2> pages_per_bank = {0, 0};
75  for (const auto &it : InfoPages()) {
76  const uint32_t bank = it.second.bank;
77  EXPECT_LE(bank, 1);
78  ++pages_per_bank[bank];
79  }
80 
81  EXPECT_THAT(pages_per_bank, Each(10));
82 }
83 
84 TEST_F(InfoPagesTest, PageIndices) {
85  for (const auto &it : InfoPages()) {
86  const uint32_t page = it.second.page;
87  EXPECT_LE(page, 9);
88  }
89 }
90 
91 struct InitCase {
92  /**
93  * Configuration settings to be read from OTP.
94  */
96  /**
97  * Expected value to be written to the info config register.
98  */
99  uint32_t info_write_val;
100  /**
101  * Expected value to be written to the data config register.
102  */
103  uint32_t data_write_val;
104 };
105 
106 class InitTest : public FlashCtrlTest,
107  public testing::WithParamInterface<InitCase> {};
108 
109 uint32_t CfgToOtp(flash_ctrl_cfg_t cfg) {
110  uint32_t val = bitfield_field32_write(0, FLASH_CTRL_OTP_FIELD_SCRAMBLING,
111  cfg.scrambling);
112  val = bitfield_field32_write(val, FLASH_CTRL_OTP_FIELD_ECC, cfg.ecc);
113  val = bitfield_field32_write(val, FLASH_CTRL_OTP_FIELD_HE, cfg.he);
114  return val;
115 }
116 
117 TEST_P(InitTest, Initialize) {
118  EXPECT_CALL(
119  otp_,
120  read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_HW_INFO_CFG_OVERRIDE_OFFSET))
121  .WillOnce(Return(0));
122 
123  EXPECT_ABS_WRITE32(base_ + FLASH_CTRL_INIT_REG_OFFSET,
124  {{FLASH_CTRL_INIT_VAL_BIT, true}});
125 
126  EXPECT_CALL(
127  otp_, read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_DATA_DEFAULT_CFG_OFFSET))
128  .WillOnce(Return(CfgToOtp(GetParam().cfg)));
129  EXPECT_SEC_READ32(base_ + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET,
130  FLASH_CTRL_DEFAULT_REGION_REG_RESVAL);
131  EXPECT_SEC_WRITE32(base_ + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET,
132  GetParam().data_write_val);
133 
134  EXPECT_CALL(
135  otp_,
136  read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_INFO_BOOT_DATA_CFG_OFFSET))
137  .WillOnce(Return(CfgToOtp(GetParam().cfg)));
138  auto info_page = InfoPages().at(&kFlashCtrlInfoPageBootData0);
139  EXPECT_SEC_READ32(base_ + info_page.cfg_offset,
140  FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_REG_RESVAL);
141  EXPECT_SEC_WRITE32(base_ + info_page.cfg_offset, GetParam().info_write_val);
142 
143  info_page = InfoPages().at(&kFlashCtrlInfoPageBootData1);
144  EXPECT_SEC_READ32(base_ + info_page.cfg_offset,
145  FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_REG_RESVAL);
146  EXPECT_SEC_WRITE32(base_ + info_page.cfg_offset, GetParam().info_write_val);
147 
148  flash_ctrl_init();
149 }
150 
151 INSTANTIATE_TEST_SUITE_P(AllCases, InitTest,
152  testing::Values(
153  // Scrambling.
154  InitCase{
155  .cfg = {.scrambling = kMultiBitBool4True,
156  .ecc = kMultiBitBool4False,
157  .he = kMultiBitBool4False},
158  .info_write_val = 0x9969996,
159  .data_write_val = 0x996999,
160  },
161  // ECC.
162  InitCase{
163  .cfg = {.scrambling = kMultiBitBool4False,
164  .ecc = kMultiBitBool4True,
165  .he = kMultiBitBool4False},
166  .info_write_val = 0x9699996,
167  .data_write_val = 0x969999,
168  },
169  // High endurance.
170  InitCase{
171  .cfg = {.scrambling = kMultiBitBool4False,
172  .ecc = kMultiBitBool4False,
173  .he = kMultiBitBool4True},
174  .info_write_val = 0x6999996,
175  .data_write_val = 0x699999,
176  },
177  // Scrambling and ECC.
178  InitCase{
179  .cfg = {.scrambling = kMultiBitBool4True,
180  .ecc = kMultiBitBool4True,
181  .he = kMultiBitBool4False},
182  .info_write_val = 0x9669996,
183  .data_write_val = 0x966999,
184  }));
185 
186 class StatusCheckTest : public FlashCtrlTest {};
187 
188 TEST_F(StatusCheckTest, DefaultStatus) {
189  EXPECT_ABS_READ32(base_ + FLASH_CTRL_STATUS_REG_OFFSET,
190  {
191  {FLASH_CTRL_STATUS_RD_FULL_BIT, false},
192  {FLASH_CTRL_STATUS_RD_EMPTY_BIT, false},
193  {FLASH_CTRL_STATUS_INIT_WIP_BIT, false},
194  });
195 
197  flash_ctrl_status_get(&status);
198 
199  EXPECT_EQ(status.init_wip, false);
200  EXPECT_EQ(status.rd_empty, false);
201  EXPECT_EQ(status.rd_full, false);
202 }
203 
204 TEST_F(StatusCheckTest, AllSetStatus) {
205  EXPECT_ABS_READ32(base_ + FLASH_CTRL_STATUS_REG_OFFSET,
206  {
207  {FLASH_CTRL_STATUS_RD_FULL_BIT, true},
208  {FLASH_CTRL_STATUS_RD_EMPTY_BIT, true},
209  {FLASH_CTRL_STATUS_INIT_WIP_BIT, true},
210  });
211 
213  flash_ctrl_status_get(&status);
214 
215  EXPECT_EQ(status.init_wip, true);
216  EXPECT_EQ(status.rd_empty, true);
217  EXPECT_EQ(status.rd_full, true);
218 }
219 
221 
222 TEST_F(ErrorCodeCheckTest, DefaultErrorCodes) {
223  EXPECT_ABS_READ32(base_ + FLASH_CTRL_ERR_CODE_REG_OFFSET,
224  {
225  {FLASH_CTRL_ERR_CODE_MACRO_ERR_BIT, false},
226  {FLASH_CTRL_ERR_CODE_UPDATE_ERR_BIT, false},
227  {FLASH_CTRL_ERR_CODE_PROG_TYPE_ERR_BIT, false},
228  {FLASH_CTRL_ERR_CODE_PROG_WIN_ERR_BIT, false},
229  {FLASH_CTRL_ERR_CODE_PROG_ERR_BIT, false},
230  {FLASH_CTRL_ERR_CODE_RD_ERR_BIT, false},
231  {FLASH_CTRL_ERR_CODE_MP_ERR_BIT, false},
232  {FLASH_CTRL_ERR_CODE_OP_ERR_BIT, false},
233  });
234 
235  flash_ctrl_error_code_t error_code;
236  flash_ctrl_error_code_get(&error_code);
237 
238  EXPECT_EQ(error_code.macro_err, false);
239  EXPECT_EQ(error_code.update_err, false);
240  EXPECT_EQ(error_code.prog_type_err, false);
241  EXPECT_EQ(error_code.prog_win_err, false);
242  EXPECT_EQ(error_code.prog_err, false);
243  EXPECT_EQ(error_code.rd_err, false);
244  EXPECT_EQ(error_code.mp_err, false);
245  EXPECT_EQ(error_code.op_err, false);
246 }
247 
248 TEST_F(ErrorCodeCheckTest, AllSetErrorCodes) {
249  EXPECT_ABS_READ32(base_ + FLASH_CTRL_ERR_CODE_REG_OFFSET,
250  {
251  {FLASH_CTRL_ERR_CODE_MACRO_ERR_BIT, true},
252  {FLASH_CTRL_ERR_CODE_UPDATE_ERR_BIT, true},
253  {FLASH_CTRL_ERR_CODE_PROG_TYPE_ERR_BIT, true},
254  {FLASH_CTRL_ERR_CODE_PROG_WIN_ERR_BIT, true},
255  {FLASH_CTRL_ERR_CODE_PROG_ERR_BIT, true},
256  {FLASH_CTRL_ERR_CODE_RD_ERR_BIT, true},
257  {FLASH_CTRL_ERR_CODE_MP_ERR_BIT, true},
258  {FLASH_CTRL_ERR_CODE_OP_ERR_BIT, true},
259  });
260 
261  flash_ctrl_error_code_t error_code;
262  flash_ctrl_error_code_get(&error_code);
263 
264  EXPECT_EQ(error_code.macro_err, true);
265  EXPECT_EQ(error_code.update_err, true);
266  EXPECT_EQ(error_code.prog_type_err, true);
267  EXPECT_EQ(error_code.prog_win_err, true);
268  EXPECT_EQ(error_code.prog_err, true);
269  EXPECT_EQ(error_code.rd_err, true);
270  EXPECT_EQ(error_code.mp_err, true);
271  EXPECT_EQ(error_code.op_err, true);
272 }
273 
274 class TransferTest : public FlashCtrlTest {
275  protected:
276  const std::vector<uint32_t> words_ = {0x12345678, 0x90ABCDEF, 0x0F1E2D3C,
277  0x4B5A6978};
278  void ExpectWaitForDone(bool done, bool error) {
279  EXPECT_ABS_READ32(base_ + FLASH_CTRL_OP_STATUS_REG_OFFSET,
280  {{FLASH_CTRL_OP_STATUS_DONE_BIT, done},
281  {FLASH_CTRL_OP_STATUS_ERR_BIT, error}});
282  if (done) {
283  EXPECT_ABS_WRITE32(base_ + FLASH_CTRL_OP_STATUS_REG_OFFSET, 0u);
284  }
285  }
286 
287  void ExpectTransferStart(uint8_t part_sel, uint8_t info_sel,
288  uint8_t erase_sel, uint32_t op, uint32_t addr,
289  uint32_t word_count) {
290  EXPECT_ABS_WRITE32(base_ + FLASH_CTRL_ADDR_REG_OFFSET, addr);
291  EXPECT_ABS_WRITE32(base_ + FLASH_CTRL_CONTROL_REG_OFFSET,
292  {
293  {FLASH_CTRL_CONTROL_OP_OFFSET, op},
294  {FLASH_CTRL_CONTROL_PARTITION_SEL_BIT, part_sel},
295  {FLASH_CTRL_CONTROL_INFO_SEL_OFFSET, info_sel},
296  {FLASH_CTRL_CONTROL_ERASE_SEL_BIT, erase_sel},
297  {FLASH_CTRL_CONTROL_NUM_OFFSET, word_count - 1},
298  {FLASH_CTRL_CONTROL_START_BIT, 1},
299  });
300  }
301 
302  void ExpectReadData(const std::vector<uint32_t> &data) {
303  for (auto val : data) {
304  EXPECT_ABS_READ32(base_ + FLASH_CTRL_RD_FIFO_REG_OFFSET, val);
305  }
306  }
307 
308  void ExpectProgData(const std::vector<uint32_t> &data) {
309  for (auto val : data) {
310  EXPECT_ABS_WRITE32(base_ + FLASH_CTRL_PROG_FIFO_REG_OFFSET, val);
311  }
312  }
313 };
314 
315 TEST_F(TransferTest, ReadDataOk) {
316  ExpectTransferStart(0, 0, 0, FLASH_CTRL_CONTROL_OP_VALUE_READ, 0x01234567,
317  words_.size());
318  ExpectReadData(words_);
319  ExpectWaitForDone(true, false);
320  std::vector<uint32_t> words_out(words_.size());
321  EXPECT_EQ(flash_ctrl_data_read(0x01234567, words_.size(), &words_out.front()),
322  kErrorOk);
323  EXPECT_EQ(words_out, words_);
324 }
325 
326 TEST_F(TransferTest, ReadInfoOk) {
327  // Address of the `kFlashCtrlInfoPageOwnerSlot0` page, see `info_page_addr`.
328  const uint32_t addr =
329  1 * FLASH_CTRL_PARAM_BYTES_PER_BANK + 2 * FLASH_CTRL_PARAM_BYTES_PER_PAGE;
330  ExpectTransferStart(1, 0, 0, FLASH_CTRL_CONTROL_OP_VALUE_READ,
331  addr + 0x01234567, words_.size());
332  ExpectReadData(words_);
333  ExpectWaitForDone(true, false);
334  std::vector<uint32_t> words_out(words_.size());
335  EXPECT_EQ(flash_ctrl_info_read(&kFlashCtrlInfoPageOwnerSlot0, 0x01234567,
336  words_.size(), &words_out.front()),
337  kErrorOk);
338  EXPECT_EQ(words_out, words_);
339 }
340 
341 TEST_F(TransferTest, ProgDataOk) {
342  ExpectTransferStart(0, 0, 0, FLASH_CTRL_CONTROL_OP_VALUE_PROG, 0x01234567,
343  words_.size());
344  ExpectProgData(words_);
345  ExpectWaitForDone(true, false);
346  EXPECT_EQ(flash_ctrl_data_write(0x01234567, words_.size(), &words_.front()),
347  kErrorOk);
348 }
349 
350 TEST_F(TransferTest, ProgInfoOk) {
351  // Address of the `kFlashCtrlInfoPageOwnerSlot0` page, see `info_page_addr`.
352  const uint32_t addr =
353  1 * FLASH_CTRL_PARAM_BYTES_PER_BANK + 2 * FLASH_CTRL_PARAM_BYTES_PER_PAGE;
354  ExpectTransferStart(1, 0, 0, FLASH_CTRL_CONTROL_OP_VALUE_PROG,
355  addr + 0x01234567, words_.size());
356  ExpectProgData(words_);
357  ExpectWaitForDone(true, false);
358  EXPECT_EQ(flash_ctrl_info_write(&kFlashCtrlInfoPageOwnerSlot0, 0x01234567,
359  words_.size(), &words_.front()),
360  kErrorOk);
361 }
362 
363 TEST_F(TransferTest, EraseDataPageOk) {
364  ExpectTransferStart(0, 0, 0, FLASH_CTRL_CONTROL_OP_VALUE_ERASE, 0x01234567,
365  1);
366  ExpectWaitForDone(true, false);
367  EXPECT_EQ(flash_ctrl_data_erase(0x01234567, kFlashCtrlEraseTypePage),
368  kErrorOk);
369 }
370 
371 TEST_F(TransferTest, EraseInfoPageOk) {
372  // Address of the `kFlashCtrlInfoPageOwnerSlot0` page, see `info_page_addr`.
373  const uint32_t addr =
374  1 * FLASH_CTRL_PARAM_BYTES_PER_BANK + 2 * FLASH_CTRL_PARAM_BYTES_PER_PAGE;
375  ExpectTransferStart(1, 0, 0, FLASH_CTRL_CONTROL_OP_VALUE_ERASE, addr, 1);
376  ExpectWaitForDone(true, false);
377  EXPECT_EQ(flash_ctrl_info_erase(&kFlashCtrlInfoPageOwnerSlot0,
378  kFlashCtrlEraseTypePage),
379  kErrorOk);
380 }
381 
382 TEST_F(TransferTest, ProgAcrossWindows) {
383  static const uint32_t kWinSize = FLASH_CTRL_PARAM_REG_BUS_PGM_RES_BYTES;
384  static const uint32_t kManyWordsSize = 2 * kWinSize / sizeof(uint32_t);
385 
386  std::array<uint32_t, kManyWordsSize> many_words;
387  for (uint32_t i = 0; i < many_words.size(); ++i) {
388  many_words[i] = i;
389  }
390 
391  auto iter = many_words.begin();
392  size_t half_step = kWinSize / sizeof(uint32_t) / 2;
393 
394  // Program address range [0x20, 0x40)
395  ExpectTransferStart(0, 0, 0, FLASH_CTRL_CONTROL_OP_VALUE_PROG, kWinSize / 2,
396  half_step);
397  ExpectProgData(std::vector<uint32_t>(iter, iter + half_step));
398  ExpectWaitForDone(true, false);
399  iter += half_step;
400 
401  // Program address range [0x40, 0x80)
402  ExpectTransferStart(0, 0, 0, FLASH_CTRL_CONTROL_OP_VALUE_PROG, kWinSize,
403  2 * half_step);
404  ExpectProgData(std::vector<uint32_t>(iter, iter + 2 * half_step));
405  ExpectWaitForDone(true, false);
406  iter += 2 * half_step;
407 
408  // Programm address range [0x80, 0xA0)
409  ExpectTransferStart(0, 0, 0, FLASH_CTRL_CONTROL_OP_VALUE_PROG, 2 * kWinSize,
410  half_step);
411  ExpectProgData(std::vector<uint32_t>(iter, iter + half_step));
412  ExpectWaitForDone(true, false);
413 
414  EXPECT_EQ(iter + half_step, many_words.end());
415 
416  EXPECT_EQ(flash_ctrl_data_write(kWinSize / 2, many_words.size(),
417  &many_words.front()),
418  kErrorOk);
419 }
420 
421 TEST_F(TransferTest, TransferInternalError) {
422  ExpectTransferStart(0, 0, 0, FLASH_CTRL_CONTROL_OP_VALUE_READ, 0x01234567,
423  words_.size());
424  ExpectReadData(words_);
425  ExpectWaitForDone(true, true);
426  std::vector<uint32_t> words_out(words_.size());
427  EXPECT_EQ(flash_ctrl_data_read(0x01234567, words_.size(), &words_out.front()),
428  kErrorFlashCtrlDataRead);
429 }
430 
431 class ExecTest : public FlashCtrlTest {};
432 
433 TEST_F(ExecTest, Set) {
434  EXPECT_SEC_WRITE32(base_ + FLASH_CTRL_EXEC_REG_OFFSET, UINT32_MAX);
435  flash_ctrl_exec_set(UINT32_MAX);
436 }
437 
438 struct PermsSetCase {
439  /**
440  * Access permissions to set.
441  */
443  /**
444  * Expected value to be read from the info config register.
445  */
446  uint32_t info_read_val;
447  /**
448  * Expected value to be written to the info config register.
449  */
450  uint32_t info_write_val;
451  /**
452  * Expected value to be read from the data config register.
453  */
454  uint32_t data_read_val;
455  /**
456  * Expected value to be written to the data config register.
457  */
458  uint32_t data_write_val;
459 };
460 
462  public testing::WithParamInterface<PermsSetCase> {
463 };
464 
465 TEST_P(FlashCtrlPermsSetTest, InfoPermsSet) {
466  for (const auto &it : InfoPages()) {
467  EXPECT_SEC_READ32(base_ + it.second.cfg_offset, GetParam().info_read_val);
468  EXPECT_SEC_WRITE32(base_ + it.second.cfg_offset, GetParam().info_write_val);
469 
470  flash_ctrl_info_perms_set(it.first, GetParam().perms);
471  }
472 }
473 
474 TEST_P(FlashCtrlPermsSetTest, DataDefaultPermsSet) {
475  EXPECT_SEC_READ32(base_ + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET,
476  GetParam().data_read_val);
477  EXPECT_SEC_WRITE32(base_ + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET,
478  GetParam().data_write_val);
479 
480  flash_ctrl_data_default_perms_set(GetParam().perms);
481 }
482 
483 INSTANTIATE_TEST_SUITE_P(AllCases, FlashCtrlPermsSetTest,
484  testing::Values(
485  // Read.
486  PermsSetCase{
487  .perms = {.read = kMultiBitBool4True,
488  .write = kMultiBitBool4False,
489  .erase = kMultiBitBool4False},
490  .info_read_val = 0x9999999,
491  .info_write_val = 0x9999966,
492  .data_read_val = 0x999999,
493  .data_write_val = 0x999996,
494  },
495  PermsSetCase{
496  .perms = {.read = kMultiBitBool4True,
497  .write = kMultiBitBool4False,
498  .erase = kMultiBitBool4False},
499  .info_read_val = 0x6666666,
500  .info_write_val = 0x6669966,
501  .data_read_val = 0x666666,
502  .data_write_val = 0x666996,
503  },
504  // Write.
505  PermsSetCase{
506  .perms = {.read = kMultiBitBool4False,
507  .write = kMultiBitBool4True,
508  .erase = kMultiBitBool4False},
509  .info_read_val = 0x9999999,
510  .info_write_val = 0x9999696,
511  .data_read_val = 0x999999,
512  .data_write_val = 0x999969,
513  },
514  PermsSetCase{
515  .perms = {.read = kMultiBitBool4False,
516  .write = kMultiBitBool4True,
517  .erase = kMultiBitBool4False},
518  .info_read_val = 0x6666666,
519  .info_write_val = 0x6669696,
520  .data_read_val = 0x666666,
521  .data_write_val = 0x666969,
522  },
523  // Erase.
524  PermsSetCase{
525  .perms = {.read = kMultiBitBool4False,
526  .write = kMultiBitBool4False,
527  .erase = kMultiBitBool4True},
528  .info_read_val = 0x9999999,
529  .info_write_val = 0x9996996,
530  .data_read_val = 0x999999,
531  .data_write_val = 0x999699,
532  },
533  PermsSetCase{
534  .perms = {.read = kMultiBitBool4False,
535  .write = kMultiBitBool4False,
536  .erase = kMultiBitBool4True},
537  .info_read_val = 0x6666666,
538  .info_write_val = 0x6666996,
539  .data_read_val = 0x666666,
540  .data_write_val = 0x666699,
541  },
542  // Write and erase.
543  PermsSetCase{
544  .perms = {.read = kMultiBitBool4False,
545  .write = kMultiBitBool4True,
546  .erase = kMultiBitBool4True},
547  .info_read_val = 0x9999999,
548  .info_write_val = 0x9996696,
549  .data_read_val = 0x999999,
550  .data_write_val = 0x999669},
551  PermsSetCase{
552  .perms = {.read = kMultiBitBool4False,
553  .write = kMultiBitBool4True,
554  .erase = kMultiBitBool4True},
555  .info_read_val = 0x6666666,
556  .info_write_val = 0x6666696,
557  .data_read_val = 0x666666,
558  .data_write_val = 0x666669,
559  }));
560 
561 struct CfgSetCase {
562  /**
563  * Configuration settings to set.
564  */
566  /**
567  * Expected value to be read from the info config register.
568  */
569  uint32_t info_read_val;
570  /**
571  * Expected value to be written to the info config register.
572  */
573  uint32_t info_write_val;
574  /**
575  * Expected value to be read from the data config register.
576  */
577  uint32_t data_read_val;
578  /**
579  * Expected value to be written to the data config register.
580  */
581  uint32_t data_write_val;
582 };
583 
585  public testing::WithParamInterface<CfgSetCase> {};
586 
587 TEST_P(FlashCtrlCfgSetTest, InfoCfgSet) {
588  for (const auto &it : InfoPages()) {
589  EXPECT_SEC_READ32(base_ + it.second.cfg_offset, GetParam().info_read_val);
590  EXPECT_SEC_WRITE32(base_ + it.second.cfg_offset, GetParam().info_write_val);
591 
592  flash_ctrl_info_cfg_set(it.first, GetParam().cfg);
593  }
594 }
595 
596 TEST_P(FlashCtrlCfgSetTest, DataDefaultCfgSet) {
597  EXPECT_SEC_READ32(base_ + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET,
598  GetParam().data_read_val);
599  EXPECT_SEC_WRITE32(base_ + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET,
600  GetParam().data_write_val);
601 
602  flash_ctrl_data_default_cfg_set(GetParam().cfg);
603 }
604 
605 INSTANTIATE_TEST_SUITE_P(AllCases, FlashCtrlCfgSetTest,
606  testing::Values(
607  // Scrambling.
608  CfgSetCase{
609  .cfg = {.scrambling = kMultiBitBool4True,
610  .ecc = kMultiBitBool4False,
611  .he = kMultiBitBool4False},
612  .info_read_val = 0x9999999,
613  .info_write_val = 0x9969996,
614  .data_read_val = 0x999999,
615  .data_write_val = 0x996999,
616  },
617  CfgSetCase{
618  .cfg = {.scrambling = kMultiBitBool4True,
619  .ecc = kMultiBitBool4False,
620  .he = kMultiBitBool4False},
621  .info_read_val = 0x6666666,
622  .info_write_val = 0x9966666,
623  .data_read_val = 0x666666,
624  .data_write_val = 0x996666,
625  },
626  // ECC.
627  CfgSetCase{
628  .cfg = {.scrambling = kMultiBitBool4False,
629  .ecc = kMultiBitBool4True,
630  .he = kMultiBitBool4False},
631  .info_read_val = 0x9999999,
632  .info_write_val = 0x9699996,
633  .data_read_val = 0x999999,
634  .data_write_val = 0x969999,
635  },
636  CfgSetCase{
637  .cfg = {.scrambling = kMultiBitBool4False,
638  .ecc = kMultiBitBool4True,
639  .he = kMultiBitBool4False},
640  .info_read_val = 0x6666666,
641  .info_write_val = 0x9696666,
642  .data_read_val = 0x666666,
643  .data_write_val = 0x969666,
644  },
645  // High endurance.
646  CfgSetCase{
647  .cfg = {.scrambling = kMultiBitBool4False,
648  .ecc = kMultiBitBool4False,
649  .he = kMultiBitBool4True},
650  .info_read_val = 0x9999999,
651  .info_write_val = 0x6999996,
652  .data_read_val = 0x999999,
653  .data_write_val = 0x699999,
654  },
655  CfgSetCase{
656  .cfg = {.scrambling = kMultiBitBool4False,
657  .ecc = kMultiBitBool4False,
658  .he = kMultiBitBool4True},
659  .info_read_val = 0x6666666,
660  .info_write_val = 0x6996666,
661  .data_read_val = 0x666666,
662  .data_write_val = 0x699666,
663  },
664  // Scrambling and ECC.
665  CfgSetCase{
666  .cfg = {.scrambling = kMultiBitBool4True,
667  .ecc = kMultiBitBool4True,
668  .he = kMultiBitBool4False},
669  .info_read_val = 0x9999999,
670  .info_write_val = 0x9669996,
671  .data_read_val = 0x999999,
672  .data_write_val = 0x966999,
673  },
674  CfgSetCase{
675  .cfg = {.scrambling = kMultiBitBool4True,
676  .ecc = kMultiBitBool4True,
677  .he = kMultiBitBool4False},
678  .info_read_val = 0x6666666,
679  .info_write_val = 0x9666666,
680  .data_read_val = 0x666666,
681  .data_write_val = 0x966666,
682  }));
683 
684 TEST_F(FlashCtrlTest, CreatorInfoLockdown) {
685  std::array<const flash_ctrl_info_page_t *, 6> no_owner_access = {
686  &kFlashCtrlInfoPageFactoryId, &kFlashCtrlInfoPageCreatorSecret,
687  &kFlashCtrlInfoPageOwnerSecret, &kFlashCtrlInfoPageWaferAuthSecret,
688  &kFlashCtrlInfoPageBootData0, &kFlashCtrlInfoPageBootData1,
689  };
690  for (auto page : no_owner_access) {
691  auto info_page = InfoPages().at(page);
692  EXPECT_SEC_WRITE32(base_ + info_page.cfg_offset, 0);
693  EXPECT_SEC_WRITE32(base_ + info_page.cfg_wen_offset, 0);
694  }
695 
696  flash_ctrl_creator_info_pages_lockdown();
697 }
698 
699 TEST_F(FlashCtrlTest, BankErasePermsSet) {
700  EXPECT_SEC_WRITE32_SHADOWED(
701  base_ + FLASH_CTRL_MP_BANK_CFG_SHADOWED_REG_OFFSET,
702  {
703  {FLASH_CTRL_MP_BANK_CFG_SHADOWED_ERASE_EN_0_BIT, 1},
704  {FLASH_CTRL_MP_BANK_CFG_SHADOWED_ERASE_EN_1_BIT, 1},
705  });
706  flash_ctrl_bank_erase_perms_set(kHardenedBoolTrue);
707 
708  EXPECT_SEC_WRITE32_SHADOWED(
709  base_ + FLASH_CTRL_MP_BANK_CFG_SHADOWED_REG_OFFSET, 0);
710  flash_ctrl_bank_erase_perms_set(kHardenedBoolFalse);
711 }
712 
713 TEST_F(FlashCtrlTest, CertInfoCreatorCfg) {
714  std::array<const flash_ctrl_info_page_t *, 2> cert_pages = {
715  &kFlashCtrlInfoPageAttestationKeySeeds,
716  &kFlashCtrlInfoPageDiceCerts,
717  };
718  for (auto page : cert_pages) {
719  auto info_page = InfoPages().at(page);
720  EXPECT_SEC_READ32(base_ + info_page.cfg_offset,
721  FLASH_CTRL_BANK1_INFO0_PAGE_CFG_0_REG_RESVAL);
722  EXPECT_SEC_WRITE32(base_ + info_page.cfg_offset, 0x9669996);
723  EXPECT_SEC_READ32(base_ + info_page.cfg_offset, 0x9669996);
724  EXPECT_SEC_WRITE32(base_ + info_page.cfg_offset, 0x9666666);
725  }
726 
727  flash_ctrl_cert_info_page_creator_cfg(&kFlashCtrlInfoPageAttestationKeySeeds);
728  flash_ctrl_cert_info_page_creator_cfg(&kFlashCtrlInfoPageDiceCerts);
729 }
730 
731 TEST_F(FlashCtrlTest, CertInfoOwnerRestrict) {
732  std::array<const flash_ctrl_info_page_t *, 2> cert_pages = {
733  &kFlashCtrlInfoPageAttestationKeySeeds,
734  &kFlashCtrlInfoPageDiceCerts,
735  };
736  for (auto page : cert_pages) {
737  auto info_page = InfoPages().at(page);
738  EXPECT_SEC_READ32(base_ + info_page.cfg_offset, 0x9666666);
739  EXPECT_SEC_WRITE32(base_ + info_page.cfg_offset, 0x9669966);
740  }
741 
742  flash_ctrl_cert_info_page_owner_restrict(
743  &kFlashCtrlInfoPageAttestationKeySeeds);
744  flash_ctrl_cert_info_page_owner_restrict(&kFlashCtrlInfoPageDiceCerts);
745 }
746 
748  /**
749  * Address.
750  */
751  uint32_t addr;
752  /**
753  * Truncated address aligned to closest lower page/bank.
754  */
755  uint32_t aligned_addr;
756  /**
757  * Erase type.
758  */
759  flash_ctrl_erase_type_t erase_type;
760  /**
761  * Value of the last word read from flash (for testing failure cases).
762  */
763  uint32_t last_word_val;
764  /**
765  * Expected return value.
766  */
767  rom_error_t error;
768 };
769 
771  public testing::WithParamInterface<EraseVerifyCase> {};
772 
773 TEST_P(EraseVerifyTest, DataEraseVerify) {
774  size_t byte_count;
775  switch (GetParam().erase_type) {
776  case kFlashCtrlEraseTypeBank:
777  byte_count = FLASH_CTRL_PARAM_BYTES_PER_BANK;
778  break;
779  case kFlashCtrlEraseTypePage:
780  byte_count = FLASH_CTRL_PARAM_BYTES_PER_PAGE;
781  break;
782  default:
783  FAIL();
784  }
785 
786  size_t i = 0;
787  for (; i < byte_count - sizeof(uint32_t); i += sizeof(uint32_t)) {
788  EXPECT_ABS_READ32(
789  TOP_EARLGREY_FLASH_CTRL_MEM_BASE_ADDR + GetParam().aligned_addr + i,
790  kFlashCtrlErasedWord);
791  }
792  EXPECT_ABS_READ32(
793  TOP_EARLGREY_FLASH_CTRL_MEM_BASE_ADDR + GetParam().aligned_addr + i,
794  GetParam().last_word_val);
795 
796  EXPECT_EQ(
797  flash_ctrl_data_erase_verify(GetParam().addr, GetParam().erase_type),
798  GetParam().error);
799 }
800 
801 INSTANTIATE_TEST_SUITE_P(
802  AllCases, EraseVerifyTest,
803  testing::Values(
804  // Verify first page.
805  EraseVerifyCase{
806  .addr = 0,
807  .aligned_addr = 0,
808  .erase_type = kFlashCtrlEraseTypePage,
809  .last_word_val = kFlashCtrlErasedWord,
810  .error = kErrorOk,
811  },
812  // Verify 10th page, unaligned address.
813  EraseVerifyCase{
814  .addr = 10 * FLASH_CTRL_PARAM_BYTES_PER_PAGE + 128,
815  .aligned_addr = 10 * FLASH_CTRL_PARAM_BYTES_PER_PAGE,
816  .erase_type = kFlashCtrlEraseTypePage,
817  .last_word_val = kFlashCtrlErasedWord,
818  .error = kErrorOk,
819  },
820  // Fail to verify 10th page, unaligned address.
821  EraseVerifyCase{
822  .addr = 10 * FLASH_CTRL_PARAM_BYTES_PER_PAGE + 128,
823  .aligned_addr = 10 * FLASH_CTRL_PARAM_BYTES_PER_PAGE,
824  .erase_type = kFlashCtrlEraseTypePage,
825  .last_word_val = 0xfffffff0,
826  .error = kErrorFlashCtrlDataEraseVerify,
827  } // Note: No cases for bank erases since the test times out due to
828  // large number of expectations.
829  ));
830 
832  : public testing::TestWithParam<
833  std::tuple<size_t, size_t, size_t, bool, bool, bool>> {
834  public:
835  /// Return a human-readable suffix for an instance of this parameterized test.
836  ///
837  /// @param info The tuple of values that defines the instance of the test.
838  /// @return A human-readable string that is appended to the test name.
839  static std::string HumanReadableTestNameSuffix(
840  const testing::TestParamInfo<ParamType> info) {
841  return absl::StrCat("RegionIndex", std::get<0>(info.param), //
842  "_PageOffset", std::get<1>(info.param), //
843  "_NumPages", std::get<2>(info.param), //
844  "_Read", std::get<3>(info.param), //
845  "_Write", std::get<4>(info.param), //
846  "_Erase", std::get<5>(info.param));
847  }
848 
849  protected:
850  size_t GetParamRegion() const { return std::get<0>(GetParam()); }
851  size_t GetParamPageOffset() const { return std::get<1>(GetParam()); }
852  size_t GetParamNumPages() const { return std::get<2>(GetParam()); }
853  bool GetParamRead() const { return std::get<3>(GetParam()); }
854  bool GetParamWrite() const { return std::get<4>(GetParam()); }
855  bool GetParamErase() const { return std::get<5>(GetParam()); }
856 
857  static constexpr multi_bit_bool_t BoolToMultiBitBool4(bool value) {
858  return value ? kMultiBitBool4True : kMultiBitBool4False;
859  }
860 
861  static constexpr uint32_t ConcatMultiBitBool4(
862  std::initializer_list<bool> values) {
863  uint32_t acc = 0;
864  for (bool value : values) {
865  acc = (acc << 4) | BoolToMultiBitBool4(value);
866  }
867  return acc;
868  }
869 
870  static constexpr size_t kNumMemoryProtectionRegions = 8;
871  static constexpr size_t
872  kFlashCtrlMpRegionRegOffset[kNumMemoryProtectionRegions]{
873  FLASH_CTRL_MP_REGION_0_REG_OFFSET, FLASH_CTRL_MP_REGION_1_REG_OFFSET,
874  FLASH_CTRL_MP_REGION_2_REG_OFFSET, FLASH_CTRL_MP_REGION_3_REG_OFFSET,
875  FLASH_CTRL_MP_REGION_4_REG_OFFSET, FLASH_CTRL_MP_REGION_5_REG_OFFSET,
876  FLASH_CTRL_MP_REGION_6_REG_OFFSET, FLASH_CTRL_MP_REGION_7_REG_OFFSET,
877  };
878  static constexpr size_t
879  kFlashCtrlMpRegionCfgRegOffset[kNumMemoryProtectionRegions]{
880  FLASH_CTRL_MP_REGION_CFG_0_REG_OFFSET,
881  FLASH_CTRL_MP_REGION_CFG_1_REG_OFFSET,
882  FLASH_CTRL_MP_REGION_CFG_2_REG_OFFSET,
883  FLASH_CTRL_MP_REGION_CFG_3_REG_OFFSET,
884  FLASH_CTRL_MP_REGION_CFG_4_REG_OFFSET,
885  FLASH_CTRL_MP_REGION_CFG_5_REG_OFFSET,
886  FLASH_CTRL_MP_REGION_CFG_6_REG_OFFSET,
887  FLASH_CTRL_MP_REGION_CFG_7_REG_OFFSET,
888  };
889  static constexpr size_t
890  kFlashCtrlMpRegionCfgRegResval[kNumMemoryProtectionRegions]{
891  FLASH_CTRL_MP_REGION_CFG_0_REG_RESVAL,
892  FLASH_CTRL_MP_REGION_CFG_1_REG_RESVAL,
893  FLASH_CTRL_MP_REGION_CFG_2_REG_RESVAL,
894  FLASH_CTRL_MP_REGION_CFG_3_REG_RESVAL,
895  FLASH_CTRL_MP_REGION_CFG_4_REG_RESVAL,
896  FLASH_CTRL_MP_REGION_CFG_5_REG_RESVAL,
897  FLASH_CTRL_MP_REGION_CFG_6_REG_RESVAL,
898  FLASH_CTRL_MP_REGION_CFG_7_REG_RESVAL,
899  };
900 
901  static constexpr uint32_t kBase = TOP_EARLGREY_FLASH_CTRL_CORE_BASE_ADDR;
902 
903  rom_test::MockAbsMmio mmio_;
904  rom_test::MockSecMmio sec_mmio_;
905  rom_test::MockOtp otp_;
906 
907  testing::InSequence seq_;
908 };
909 
910 constexpr size_t DataRegionProtectTestSuite::kFlashCtrlMpRegionRegOffset[];
911 constexpr size_t DataRegionProtectTestSuite::kFlashCtrlMpRegionCfgRegOffset[];
912 constexpr size_t DataRegionProtectTestSuite::kFlashCtrlMpRegionCfgRegResval[];
913 
914 INSTANTIATE_TEST_SUITE_P(
915  DataRegionProtectTestInstance, DataRegionProtectTestSuite,
916  testing::Combine(testing::Values(0, 1, 2, 3, 4, 5, 6, 7), // Region index
917  testing::Values(0, 1, 2, 42, 256), // Page offset
918  testing::Values(0, 1, 64, 256), // Number of pages
919  testing::Bool(), // Read
920  testing::Bool(), // Write
921  testing::Bool() // Erase
922  ),
923  DataRegionProtectTestSuite::HumanReadableTestNameSuffix);
924 
925 TEST_P(DataRegionProtectTestSuite, ProtectRegionReadWriteEraseEnabled) {
926  // Choose arbitrary values for the fields of `flash_ctrl_cfg_t`.
927  constexpr bool kFlashScrambling = true;
928  constexpr bool kFlashEcc = false;
929  constexpr bool kFlashHe = true;
930 
931  // Expect that flash_ctrl_data_region_protect() will reset the
932  // MP_REGION_CFG_${i} register.
933  EXPECT_CALL(sec_mmio_,
934  Write32(kBase + kFlashCtrlMpRegionCfgRegOffset[GetParamRegion()],
935  kFlashCtrlMpRegionCfgRegResval[GetParamRegion()]));
936 
937  // Expect that flash_ctrl_data_region_protect() will encode the region's
938  // bounds in the MP_REGION_${i} register.
939  EXPECT_CALL(sec_mmio_,
940  Write32(kBase + kFlashCtrlMpRegionRegOffset[GetParamRegion()],
941  (GetParamNumPages() << 9) | GetParamPageOffset()));
942 
943  // Configure permissions for the region. All fields should be true except
944  // for SCRAMBLE_EN. In particular, note that ERASE_EN is enabled for the
945  // region.
946  constexpr bool kRegionEnabled = true;
947  EXPECT_CALL(sec_mmio_,
948  Write32(kBase + kFlashCtrlMpRegionCfgRegOffset[GetParamRegion()],
949  ConcatMultiBitBool4({
950  kFlashHe,
951  kFlashEcc,
952  kFlashScrambling,
953  GetParamErase(),
954  GetParamWrite(),
955  GetParamRead(),
956  kRegionEnabled,
957  })));
958 
959  flash_ctrl_data_region_protect(
960  GetParamRegion(), GetParamPageOffset(), GetParamNumPages(),
962  .read = BoolToMultiBitBool4(GetParamRead()),
963  .write = BoolToMultiBitBool4(GetParamWrite()),
964  .erase = BoolToMultiBitBool4(GetParamErase()),
965  },
967  .scrambling = BoolToMultiBitBool4(kFlashScrambling),
968  .ecc = BoolToMultiBitBool4(kFlashEcc),
969  .he = BoolToMultiBitBool4(kFlashHe),
970  },
972 }
973 
974 } // namespace
975 } // namespace flash_ctrl_unittest