Software APIs
inject_scramble_seed.c
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 
13 #include "sw/device/lib/runtime/irq.h"
15 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
16 #include "sw/device/lib/testing/otp_ctrl_testutils.h"
17 #include "sw/device/lib/testing/rand_testutils.h"
18 #include "sw/device/lib/testing/test_framework/check.h"
20 #include "sw/device/lib/testing/test_framework/status.h"
21 
22 #include "flash_ctrl_regs.h"
24 #include "otp_ctrl_regs.h"
25 
26 static dif_rstmgr_t rstmgr;
27 static dif_otp_ctrl_t otp_ctrl;
28 static dif_flash_ctrl_state_t flash_ctrl;
29 
30 enum {
31  kFlashWordSize = FLASH_CTRL_PARAM_BYTES_PER_WORD,
32  kFlashPageSize = FLASH_CTRL_PARAM_BYTES_PER_PAGE,
33  kFlashStartAddr = TOP_EARLGREY_FLASH_CTRL_MEM_BASE_ADDR,
34  kFlashMpRegions = FLASH_CTRL_PARAM_NUM_REGIONS
35 };
36 
37 OTTF_DEFINE_TEST_CONFIG();
38 
39 // Expected data for the scramble seed, directly backdoor loaded by the
40 // test environment. The data has to be backdoor loaded because the
41 // life cycle state used in this test does not permit the isolated
42 // partition to be written.
43 OT_SET_BSS_SECTION(".non_volatile_scratch", uint32_t kIsoPartExpData[16];)
44 
45 static void check_iso_data(dif_flash_ctrl_state_t *flash_ctrl) {
46  // Disable scramble on expected data page
47  uint32_t exp_data_addr = (uint32_t)&kIsoPartExpData;
48  uint32_t base_page = (exp_data_addr - kFlashStartAddr) / kFlashPageSize;
50  .rd_en = kMultiBitBool4True,
51  .prog_en = kMultiBitBool4False,
52  .erase_en = kMultiBitBool4False,
53  .scramble_en = kMultiBitBool4False,
54  .ecc_en = kMultiBitBool4False,
55  .high_endurance_en = kMultiBitBool4False};
56  uint32_t addr = 0;
57  CHECK_STATUS_OK(flash_ctrl_testutils_data_region_setup_properties(
58  flash_ctrl, base_page, /*data_region=*/kFlashMpRegions - 1,
59  /*region_size=*/1, exp_page, &addr));
60 
61  // Double check that the region address covers the area we care about.
62  CHECK((exp_data_addr >= (addr + kFlashStartAddr)) &&
63  (exp_data_addr < (addr + kFlashPageSize + kFlashStartAddr)));
64 
65  // Enable access to isolated page.
67  .rd_en = kMultiBitBool4True,
68  .prog_en = kMultiBitBool4False,
69  .erase_en = kMultiBitBool4False,
70  .scramble_en = kMultiBitBool4False,
71  .ecc_en = kMultiBitBool4False,
72  .high_endurance_en = kMultiBitBool4False};
73 
74  CHECK_STATUS_OK(flash_ctrl_testutils_info_region_setup_properties(
75  flash_ctrl, /*page_id=*/3,
76  /*bank=*/0, /*partition_id=*/0, iso_page, &addr));
77 
78  uint32_t read_data[16];
79  CHECK_STATUS_OK(flash_ctrl_testutils_read(
80  flash_ctrl, addr, /*partition_id=*/0, read_data,
81  kDifFlashCtrlPartitionTypeInfo, ARRAYSIZE(read_data), 0));
82 
83  CHECK_ARRAYS_EQ(kIsoPartExpData, read_data, ARRAYSIZE(read_data),
84  "Isolated info page data mismatch.");
85 };
86 
87 bool test_main(void) {
88  CHECK_DIF_OK(dif_rstmgr_init(
90 
91  CHECK_DIF_OK(dif_otp_ctrl_init(
93 
94  CHECK_DIF_OK(dif_flash_ctrl_init_state(
95  &flash_ctrl,
97 
98  bool secret1_locked = false;
100  &otp_ctrl, kDifOtpCtrlPartitionSecret1, &secret1_locked));
101 
102  if (!secret1_locked) {
103  LOG_INFO("Powered up for the first time, program and lock otp");
104 
105  // Check Isolated partition data is correct prior to enabling scrambling.
106  check_iso_data(&flash_ctrl);
107 
108  // Populate the scramble seeds in otp.
109  rand_testutils_reseed();
110 
111  // The secret partition must be 64b aligned...for some reason.
112  // Figure out that part later.
113  enum {
114  kFlashAddrKeyOffset = OTP_CTRL_PARAM_FLASH_ADDR_KEY_SEED_OFFSET -
115  OTP_CTRL_PARAM_SECRET1_OFFSET,
116  kFlashDataKeyOffset = OTP_CTRL_PARAM_FLASH_DATA_KEY_SEED_OFFSET -
117  OTP_CTRL_PARAM_SECRET1_OFFSET,
118  kSramDataKeyOffset = OTP_CTRL_PARAM_SRAM_DATA_KEY_SEED_OFFSET -
119  OTP_CTRL_PARAM_SECRET1_OFFSET
120  };
121 
122  for (uint32_t i = 0; i < OTP_CTRL_PARAM_FLASH_ADDR_KEY_SEED_SIZE;
123  i += kFlashWordSize) {
124  uint64_t val =
125  (uint64_t)rand_testutils_gen32() << 32 | rand_testutils_gen32();
126 
127  CHECK_DIF_OK(dif_otp_ctrl_dai_program64(&otp_ctrl,
129  kFlashAddrKeyOffset + i, val));
130  CHECK_STATUS_OK(otp_ctrl_testutils_wait_for_dai(&otp_ctrl));
131  };
132 
133  for (uint32_t i = 0; i < OTP_CTRL_PARAM_FLASH_DATA_KEY_SEED_SIZE;
134  i += kFlashWordSize) {
135  uint64_t val =
136  (uint64_t)rand_testutils_gen32() << 32 | rand_testutils_gen32();
137 
138  CHECK_DIF_OK(dif_otp_ctrl_dai_program64(&otp_ctrl,
140  kFlashDataKeyOffset + i, val));
141  CHECK_STATUS_OK(otp_ctrl_testutils_wait_for_dai(&otp_ctrl));
142  };
143 
144  for (uint32_t i = 0; i < OTP_CTRL_PARAM_SRAM_DATA_KEY_SEED_SIZE;
145  i += kFlashWordSize) {
146  uint64_t val =
147  (uint64_t)rand_testutils_gen32() << 32 | rand_testutils_gen32();
148 
149  CHECK_DIF_OK(dif_otp_ctrl_dai_program64(
150  &otp_ctrl, kDifOtpCtrlPartitionSecret1, kSramDataKeyOffset + i, val));
151  CHECK_STATUS_OK(otp_ctrl_testutils_wait_for_dai(&otp_ctrl));
152  };
153 
154  // Lock the secret1 partition.
155  CHECK_STATUS_OK(otp_ctrl_testutils_lock_partition(
156  &otp_ctrl, kDifOtpCtrlPartitionSecret1, 0));
157 
158  // Inform rom to setup scramble next round.
159  uint32_t otp_val = 0;
160  otp_val = bitfield_field32_write(
161  otp_val, FLASH_CTRL_DEFAULT_REGION_SCRAMBLE_EN_FIELD,
162  kMultiBitBool4True);
163  CHECK_DIF_OK(dif_otp_ctrl_dai_program32(
165  (OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_DATA_DEFAULT_CFG_OFFSET -
166  OTP_CTRL_PARAM_CREATOR_SW_CFG_OFFSET),
167  otp_val));
168  CHECK_STATUS_OK(otp_ctrl_testutils_wait_for_dai(&otp_ctrl));
169 
170  // Check to see if there are any otp_ctrl errors.
172  CHECK_DIF_OK(dif_otp_ctrl_get_status(&otp_ctrl, &status));
173 
174  // There should not have been any errors.
175  // The only bit that should be asserted is the IDLE bit.
176  LOG_INFO("otp_ctrl status: 0x%x", status.codes);
177  CHECK(status.codes == 1 << OTP_CTRL_STATUS_DAI_IDLE_BIT);
178 
179  // Reset the device.
180  LOG_INFO("Completed first phase, wait for reset");
181  CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
183  return false;
184  } else if (secret1_locked) {
185  // Check Isolated partition data is correct after scramble enabled.
186  check_iso_data(&flash_ctrl);
187  LOG_INFO("Hello World");
188  return true;
189  }
190  return false;
191 }