Software APIs
flash_rma_unlocked_test.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 
5 // Note that since rma process takes more than 100ms in dvsim,
6 // the test runs 1.6h (110ms in simtime).
7 
17 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
18 #include "sw/device/lib/testing/pinmux_testutils.h"
19 #include "sw/device/lib/testing/test_framework/check.h"
20 #include "sw/device/lib/testing/test_framework/status.h"
21 
22 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.
23 
24 #define LC_TOKEN_SIZE 16
25 
26 static dif_pinmux_t pinmux;
27 static dif_uart_t uart0;
28 static dif_flash_ctrl_state_t flash_state;
29 static dif_lc_ctrl_t lc;
30 
31 // This is updated by the sv component of the test
32 static volatile const uint8_t kTestPhase = 0;
33 static volatile const uint8_t kSrcLcState = 0;
34 
35 // Closed source short rma support
36 static volatile const uint8_t kShortRma = 0;
37 enum {
38  kFlashInfoPageIdCreatorSecret = 1,
39  kFlashInfoPageIdOwnerSecret = 2,
40  kFlashInfoPageIdIsoPart = 3,
41  kFlashInfoBank = 0,
42  kRegionBaseBank0Page0Index = 0,
43  kRegionBaseBank0Page255Index = 255,
44  kRegionBaseBank1Page0Index = 256,
45  kRegionBaseBank1Page255Index = 511,
46  kFlashBank0Page0DataRegion = 0,
47  kFlashBank0Page255DataRegion = 1,
48  kFlashBank1Page0DataRegion = 2,
49  kFlashBank1Page255DataRegion = 3,
50  kPartitionId = 0,
51  kRegionSize = 1,
52  kDataSize = 16,
53  kPageSize = 2048,
54 };
55 
56 enum {
57  kTestPhaseWriteData = 0,
58  kTestPhaseEnterRMA = 1,
59  kTestPhaseCheckWipe = 2,
60 };
61 
62 static const uint32_t kRandomData[7][kDataSize] = {
63  {0x27af716e, 0xdd493905, 0x4d674f07, 0x1e876023, 0x555477e5, 0x8c079501,
64  0xfa0aed05, 0x1091a5e4, 0xe94119be, 0xe0bed120, 0xb4611217, 0x1fa02d2a,
65  0x5252583f, 0xc2a5083b, 0xc43409c3, 0xdb348c5c},
66  {0x55c88b8c, 0x5cb3c5eb, 0xc942d714, 0x7df99821, 0x151101b2, 0x739749a1,
67  0x82bab3ef, 0xeb96c062, 0x99ac3750, 0xb31bb5e2, 0x83f979fb, 0x2e89575f,
68  0x0ff9081f, 0x81d627e9, 0x8d0bdbfb, 0x69349b84},
69  {0xabd3622b, 0xd5d03fbb, 0x7c3bf1df, 0x697b82fb, 0xa96e5282, 0xf6dda27e,
70  0x9bb834db, 0x207e2f9f, 0xe7249768, 0x24e91f04, 0x0c86716b, 0x38f956fe,
71  0x246ac305, 0xee607b20, 0xb20bb6ef, 0xe95c3687},
72  {0xaf2afb37, 0x646de1b1, 0x092b67d9, 0x1aaaebc3, 0x0dab6bd2, 0x47c83a55,
73  0xbdd1009f, 0xcd9f4c7a, 0xabe6e3a3, 0xb56e9d22, 0xacb955ce, 0x2d05fe1b,
74  0x7e748f0c, 0xc7f4a59d, 0x7cac8713, 0x568ba3c9},
75  {0x95f9fe5a, 0xb5173233, 0x7055dc6e, 0x9ffdbec7, 0x98d5a883, 0xe81e5751,
76  0x62bbd34e, 0x4bd22ca9, 0x58aac56e, 0xf9d87d26, 0xb2e7eba5, 0x6bcb1c4e,
77  0xec7421c7, 0x8c49708a, 0xbf7932b2, 0x353b6a75},
78  {0xf8ff57b9, 0x444ff4a9, 0xf3574d3c, 0xf6682a84, 0x67455a38, 0x9c138df2,
79  0x4054e3e5, 0xde4b1a26, 0x047cc121, 0x42cbd0ae, 0x3eec418f, 0x454323c4,
80  0xf21bee28, 0x28dd24b7, 0x29dd06a6, 0xf83e419f},
81  {0x0eb23677, 0x58c97854, 0x284e1a8f, 0x9b460e99, 0x339b0fe6, 0x80778f39,
82  0x9dbc2981, 0xb4bdc15f, 0x3abbdeb2, 0xab39dd53, 0x96bb2c4a, 0x9b2d1795,
83  0x733bf534, 0xc4914b4b, 0x64487458, 0x9d0fa332}};
84 
85 static void write_info_page_scrambled(uint32_t page_index,
86  const uint32_t *data) {
87  uint32_t address = 0;
88  CHECK_STATUS_OK(flash_ctrl_testutils_info_region_scrambled_setup(
89  &flash_state, page_index, kFlashInfoBank, kPartitionId, &address));
90  CHECK_STATUS_OK(flash_ctrl_testutils_erase_and_write_page(
91  &flash_state, address, kPartitionId, data, kDifFlashCtrlPartitionTypeInfo,
92  kDataSize));
93 }
94 
95 static void write_data_page_scrambled(uint32_t page_index, uint32_t region,
96  const uint32_t *data) {
97  uint32_t address;
98  CHECK_STATUS_OK(flash_ctrl_testutils_data_region_scrambled_setup(
99  &flash_state, page_index, region, kRegionSize, &address));
100  CHECK_STATUS_OK(flash_ctrl_testutils_erase_and_write_page(
101  &flash_state, address, kPartitionId, data, kDifFlashCtrlPartitionTypeData,
102  kDataSize));
103 }
104 
105 static void read_and_check_info_page_scrambled(bool is_equal,
106  uint32_t page_index,
107  const uint32_t *data) {
108  uint32_t readback_data[kDataSize];
109  uint32_t address = 0;
110  CHECK_STATUS_OK(flash_ctrl_testutils_info_region_scrambled_setup(
111  &flash_state, page_index, kFlashInfoBank, kPartitionId, &address));
112 
113  CHECK_STATUS_OK(flash_ctrl_testutils_read(
114  &flash_state, address, kPartitionId, readback_data,
115  kDifFlashCtrlPartitionTypeInfo, kDataSize, 0));
116  if (is_equal) {
117  CHECK_ARRAYS_EQ(readback_data, data, kDataSize);
118  } else {
119  CHECK_ARRAYS_NE(readback_data, data, kDataSize);
120  }
121 }
122 
123 static void read_and_check_data_page_scrambled(bool is_equal,
124  uint32_t page_index,
125  uint32_t region,
126  const uint32_t *data) {
127  uint32_t readback_data[kDataSize];
128  uint32_t address;
129  CHECK_STATUS_OK(flash_ctrl_testutils_data_region_scrambled_setup(
130  &flash_state, page_index, region, kRegionSize, &address));
131 
132  CHECK_STATUS_OK(flash_ctrl_testutils_read(
133  &flash_state, address, kPartitionId, readback_data,
134  kDifFlashCtrlPartitionTypeData, kDataSize, 0));
135  if (is_equal) {
136  CHECK_ARRAYS_EQ(readback_data, data, kDataSize);
137  } else {
138  CHECK_ARRAYS_NE(readback_data, data, kDataSize);
139  }
140 }
141 
142 // Function for the first boot, the flash is written to with known data.
143 // All partitions can be written to when the LC_STATE is Dev and
144 // the OTP secret 2 partition has not been provisioned.
145 static void write_data_test_phase(void) {
146  dif_lc_ctrl_state_t curr_state;
147  CHECK_DIF_OK(dif_lc_ctrl_get_state(&lc, &curr_state));
148  CHECK(curr_state == kSrcLcState);
149 
150  uint32_t write_idx = 0;
151  write_info_page_scrambled(kFlashInfoPageIdCreatorSecret, kRandomData[0]);
152  write_info_page_scrambled(kFlashInfoPageIdOwnerSecret, kRandomData[1]);
153  write_info_page_scrambled(kFlashInfoPageIdIsoPart, kRandomData[2]);
154  write_data_page_scrambled(kRegionBaseBank0Page0Index,
155  kFlashBank0Page0DataRegion, kRandomData[3]);
156  if (kShortRma)
157  write_idx = (kRegionBaseBank0Page0Index + 1);
158  else
159  write_idx = kRegionBaseBank0Page255Index;
160  write_data_page_scrambled(write_idx, kFlashBank0Page255DataRegion,
161  kRandomData[4]);
162  write_data_page_scrambled(kRegionBaseBank1Page0Index,
163  kFlashBank1Page0DataRegion, kRandomData[5]);
164  if (kShortRma)
165  write_idx = (kRegionBaseBank1Page0Index + 1);
166  else
167  write_idx = kRegionBaseBank1Page255Index;
168  write_data_page_scrambled(write_idx, kFlashBank1Page255DataRegion,
169  kRandomData[6]);
170 
171  LOG_INFO("Write data test complete - waiting for TB");
172  // Going into WFI which will be detected by the testbench
173  // and an OTP write and reset can be triggered.
174  test_status_set(kTestStatusInWfi);
176 }
177 
178 // Function for the second boot, the LC_STATE is still Dev but the OTP secret 2
179 // partition has now been provisioned by the testbench. Reading back
180 // from the flash pages that are still accessible as a smoke check.
181 // Creator Secret is not accessible because of OTP secret 2 provisioning.
182 // Isolation Partition cannot be read in LC_STATE of Dev.
183 // All others are accessible.
184 // Once readback is complete we wait for the testbench to issue a
185 // transition into RMA.
186 static void enter_rma_test_phase(void) {
187  dif_lc_ctrl_state_t curr_state;
188  CHECK_DIF_OK(dif_lc_ctrl_get_state(&lc, &curr_state));
189  CHECK(curr_state == kSrcLcState);
190  uint32_t read_idx = 0;
191 
192  read_and_check_info_page_scrambled(true, kFlashInfoPageIdOwnerSecret,
193  kRandomData[1]);
194  read_and_check_data_page_scrambled(true, kRegionBaseBank0Page0Index,
195  kFlashBank0Page0DataRegion,
196  kRandomData[3]);
197  if (kShortRma)
198  read_idx = (kRegionBaseBank0Page0Index + 1);
199  else
200  read_idx = kRegionBaseBank0Page255Index;
201  read_and_check_data_page_scrambled(
202  true, read_idx, kFlashBank0Page255DataRegion, kRandomData[4]);
203  read_and_check_data_page_scrambled(true, kRegionBaseBank1Page0Index,
204  kFlashBank1Page0DataRegion,
205  kRandomData[5]);
206  if (kShortRma)
207  read_idx = (kRegionBaseBank1Page0Index + 1);
208  else
209  read_idx = kRegionBaseBank1Page255Index;
210  read_and_check_data_page_scrambled(
211  true, read_idx, kFlashBank1Page255DataRegion, kRandomData[6]);
212 
213  LOG_INFO("Enter RMA test complete - waiting for TB");
214  // Enter WFI for detection in the testbench.
215  test_status_set(kTestStatusInWfi);
217 }
218 
219 // Function for the third boot, all flash partitions are readable as the
220 // LC_STATE is now RMA. Check that the data read from these partitions does
221 // *not* match the original data and therefore has been successfully wiped.
222 static void check_wipe_test_phase(void) {
223  dif_lc_ctrl_state_t curr_state;
224  CHECK_DIF_OK(dif_lc_ctrl_get_state(&lc, &curr_state));
225  CHECK(curr_state == kDifLcCtrlStateRma);
226  uint32_t read_idx = 0;
227 
228  read_and_check_info_page_scrambled(false, kFlashInfoPageIdCreatorSecret,
229  kRandomData[0]);
230  read_and_check_info_page_scrambled(false, kFlashInfoPageIdOwnerSecret,
231  kRandomData[1]);
232  read_and_check_info_page_scrambled(false, kFlashInfoPageIdIsoPart,
233  kRandomData[2]);
234  read_and_check_data_page_scrambled(false, kRegionBaseBank0Page0Index,
235  kFlashBank0Page0DataRegion,
236  kRandomData[3]);
237  if (kShortRma)
238  read_idx = (kRegionBaseBank0Page0Index + 1);
239  else
240  read_idx = kRegionBaseBank0Page255Index;
241  read_and_check_data_page_scrambled(
242  false, read_idx, kFlashBank0Page255DataRegion, kRandomData[4]);
243  read_and_check_data_page_scrambled(false, kRegionBaseBank1Page0Index,
244  kFlashBank1Page0DataRegion,
245  kRandomData[5]);
246  if (kShortRma)
247  read_idx = (kRegionBaseBank1Page0Index + 1);
248  else
249  read_idx = kRegionBaseBank1Page255Index;
250  read_and_check_data_page_scrambled(
251  false, read_idx, kFlashBank1Page255DataRegion, kRandomData[6]);
252  LOG_INFO("Wipe test complete - done");
253 }
254 
255 bool rom_test_main(void) {
256  // We need to set the test status as "in test" to indicate to the test code
257  // has been reached, even though this test is also in the "boot ROM".
258  test_status_set(kTestStatusInTest);
259  CHECK_DIF_OK(dif_pinmux_init(
261  pinmux_testutils_init(&pinmux);
262 
263  // We need to initialize the UART regardless if we LOG any messages, since
264  // Verilator and FPGA platforms use the UART to communicate the test results.
265  if (kDeviceType != kDeviceSimDV) {
266  CHECK_DIF_OK(dif_uart_init(
268  CHECK(kUartBaudrate <= UINT32_MAX, "kUartBaudrate must fit in uint32_t");
269  CHECK(kClockFreqPeripheralHz <= UINT32_MAX,
270  "kClockFreqPeripheralHz must fit in uint32_t");
271  CHECK_DIF_OK(dif_uart_configure(
272  &uart0, (dif_uart_config_t){
273  .baudrate = (uint32_t)kUartBaudrate,
274  .clk_freq_hz = (uint32_t)kClockFreqPeripheralHz,
275  .parity_enable = kDifToggleDisabled,
276  .parity = kDifUartParityEven,
277  .tx_enable = kDifToggleEnabled,
278  .rx_enable = kDifToggleEnabled,
279  }));
280  base_uart_stdout(&uart0);
281  }
282 
283  // Start of the test specific code.
284  CHECK_DIF_OK(dif_flash_ctrl_init_state(
285  &flash_state,
287  CHECK_DIF_OK(dif_lc_ctrl_init(
289 
290  dif_otp_ctrl_t otp;
291  CHECK_DIF_OK(dif_otp_ctrl_init(
293 
294  dif_otp_ctrl_config_t otp_config = {
295  .check_timeout = 100000,
296  .integrity_period_mask = 0x0,
297  .consistency_period_mask = 0x0,
298  };
299  CHECK_DIF_OK(dif_otp_ctrl_configure(&otp, otp_config));
300 
301  LOG_INFO("Test phase %d", kTestPhase);
302  switch (kTestPhase) {
303  case kTestPhaseWriteData:
304  write_data_test_phase();
305  break;
306  case kTestPhaseEnterRMA:
307  enter_rma_test_phase();
308  break;
309  case kTestPhaseCheckWipe:
310  check_wipe_test_phase();
311  return true;
312  default:
313  LOG_FATAL("Unexpected Test Phase");
314  break;
315  }
316 
317  return false;
318 }