Software APIs
flash_ctrl.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 #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
6 
7 #include <assert.h>
8 
9 #include "dt/dt_flash_ctrl.h"
15 #include "sw/device/lib/base/multibits.h"
17 #include "sw/device/silicon_creator/lib/drivers/otp.h"
18 #include "sw/device/silicon_creator/lib/error.h"
19 
20 #include "flash_ctrl_regs.h"
21 #include "otp_ctrl_regs.h"
22 
23 static const dt_flash_ctrl_t kFlashCtrlDt = kDtFlashCtrl;
24 
25 // Values of `flash_ctrl_partition_t` constants must be distinct from each
26 // other, and `kFlashCtrlRegionInfo* >> 1` should give the correct
27 // CONTROL.INFO_SEL value.
28 static_assert(kFlashCtrlPartitionData == 0,
29  "Incorrect enum value for kFlashCtrlRegionData");
30 static_assert(kFlashCtrlPartitionInfo0 >> 1 == 0,
31  "Incorrect enum value for kFlashCtrlRegionInfo0");
32 static_assert(kFlashCtrlPartitionInfo1 >> 1 == 1,
33  "Incorrect enum value for kFlashCtrlRegionInfo1");
34 static_assert(kFlashCtrlPartitionInfo2 >> 1 == 2,
35  "Incorrect enum value for kFlashCtrlRegionInfo2");
36 
37 /**
38  * Base address of the flash_ctrl registers.
39  */
40 static inline uint32_t flash_ctrl_core_base(void) {
41  return dt_flash_ctrl_primary_reg_block(kFlashCtrlDt);
42 }
43 
44 /**
45  * Flash transaction parameters.
46  */
47 typedef struct transaction_params {
48  /**
49  * Start address of a flash transaction.
50  *
51  * Must be the full byte address. For read and write operations flash
52  * controller will truncate to the closest 32-bit word aligned address. For
53  * page erases, the controller will truncate to the closest lower page aligned
54  * address. For bank erases, the controller will truncate to the closest lower
55  * bank aligned address.
56  */
57  uint32_t addr;
58  /**
59  * Operation type.
60  *
61  * Must be set to one of FLASH_CTRL_CONTROL_OP_VALUE_*.
62  */
63  uint32_t op_type;
64  /**
65  * Whether to erase a bank or a single page.
66  *
67  * Only applies to erase operations.
68  */
69  flash_ctrl_erase_type_t erase_type;
70  /**
71  * Partition to operate on.
72  */
73  flash_ctrl_partition_t partition;
74  /**
75  * Number of 32-bit words.
76  *
77  * Only applies to read and write operations.
78  */
79  uint32_t word_count;
81 
82 /**
83  * Starts a flash transaction.
84  *
85  * @param params Transaction parameters, see `transaction_params_t`.
86  * @return The result of the operation.
87  */
88 static void transaction_start(transaction_params_t params) {
89  // Set the address.
90  abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_ADDR_REG_OFFSET,
91  params.addr);
92  // Configure flash_ctrl and start the transaction.
93  const bool is_info =
94  bitfield_bit32_read(params.partition, FLASH_CTRL_PARTITION_BIT_IS_INFO);
95  const uint32_t info_type = bitfield_field32_read(
96  params.partition, FLASH_CTRL_PARTITION_FIELD_INFO_TYPE);
97  bool bank_erase = true;
98  switch (launder32(params.erase_type)) {
99  case kFlashCtrlEraseTypeBank:
100  HARDENED_CHECK_EQ(params.erase_type, kFlashCtrlEraseTypeBank);
101  bank_erase = true;
102  break;
103  case kFlashCtrlEraseTypePage:
104  HARDENED_CHECK_EQ(params.erase_type, kFlashCtrlEraseTypePage);
105  bank_erase = false;
106  break;
107  default:
108  HARDENED_TRAP();
109  }
110  uint32_t reg = bitfield_bit32_write(0, FLASH_CTRL_CONTROL_START_BIT, true);
111  reg =
112  bitfield_field32_write(reg, FLASH_CTRL_CONTROL_OP_FIELD, params.op_type);
113  reg =
114  bitfield_bit32_write(reg, FLASH_CTRL_CONTROL_PARTITION_SEL_BIT, is_info);
115  reg =
116  bitfield_field32_write(reg, FLASH_CTRL_CONTROL_INFO_SEL_FIELD, info_type);
117  reg = bitfield_bit32_write(reg, FLASH_CTRL_CONTROL_ERASE_SEL_BIT, bank_erase);
118  reg = bitfield_field32_write(reg, FLASH_CTRL_CONTROL_NUM_FIELD,
119  params.word_count - 1);
120  abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_CONTROL_REG_OFFSET, reg);
121 }
122 
123 /**
124  * Copies `word_count` words from the read FIFO to the given buffer.
125  *
126  * Large reads may create back pressure.
127  *
128  * @param word_count Number of words to read from the FIFO.
129  * @param[out] data Output buffer.
130  */
131 static void fifo_read(size_t word_count, void *data) {
132  size_t i = 0, r = word_count - 1;
133  for (; launder32(i) < word_count && launder32(r) < word_count; ++i, --r) {
134  write_32(
135  abs_mmio_read32(flash_ctrl_core_base() + FLASH_CTRL_RD_FIFO_REG_OFFSET),
136  data);
137  data = (char *)data + sizeof(uint32_t);
138  }
139  HARDENED_CHECK_EQ(i, word_count);
140  HARDENED_CHECK_EQ(r, SIZE_MAX);
141 }
142 
143 /**
144  * Copies `word_count` words from the given buffer to the program FIFO.
145  *
146  * Large writes may create back pressure.
147  *
148  * @param word_count Number of words to write to the FIFO.
149  * @param data Input buffer.
150  */
151 static void fifo_write(size_t word_count, const void *data) {
152  size_t i = 0, r = word_count - 1;
153  for (; launder32(i) < word_count && launder32(r) < word_count; ++i, --r) {
154  abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_PROG_FIFO_REG_OFFSET,
155  read_32(data));
156  data = (const char *)data + sizeof(uint32_t);
157  }
158  HARDENED_CHECK_EQ(i, word_count);
159  HARDENED_CHECK_EQ(r, SIZE_MAX);
160 }
161 
162 /**
163  * Blocks until the current flash transaction is complete.
164  *
165  * @param error Error code to return in case of a flash controller error.
166  * @return The result of the operation.
167  */
169 static rom_error_t wait_for_done(rom_error_t error) {
170  uint32_t op_status;
171  do {
172  op_status = abs_mmio_read32(flash_ctrl_core_base() +
173  FLASH_CTRL_OP_STATUS_REG_OFFSET);
174  } while (!bitfield_bit32_read(op_status, FLASH_CTRL_OP_STATUS_DONE_BIT));
175  abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_OP_STATUS_REG_OFFSET,
176  0u);
177 
178  if (bitfield_bit32_read(op_status, FLASH_CTRL_OP_STATUS_ERR_BIT)) {
179  return error;
180  }
181  return kErrorOk;
182 }
183 
184 /**
185  * Writes data to the given partition.
186  *
187  * @param addr Full byte address to write to.
188  * @param partition The partition to write to.
189  * @param word_count Number of bus words to write.
190  * @param data Data to write.
191  * @param error Error code to return in case of a flash controller error.
192  * @return Result of the operation.
193  */
195 static rom_error_t write(uint32_t addr, flash_ctrl_partition_t partition,
196  uint32_t word_count, const void *data,
197  rom_error_t error) {
198  enum {
199  kWindowWordCount = FLASH_CTRL_PARAM_REG_BUS_PGM_RES_BYTES / sizeof(uint32_t)
200  };
201 
202  // Find the number of words that can be written in the first window.
203  uint32_t window_word_count =
204  kWindowWordCount - ((addr / sizeof(uint32_t)) % kWindowWordCount);
205  while (word_count > 0) {
206  // Program operations can't cross window boundaries.
207  window_word_count =
208  word_count < window_word_count ? word_count : window_word_count;
209 
210  transaction_start((transaction_params_t){
211  .addr = addr,
212  .op_type = FLASH_CTRL_CONTROL_OP_VALUE_PROG,
213  .partition = partition,
214  .word_count = window_word_count,
215  // Does not apply to program transactions.
216  .erase_type = kFlashCtrlEraseTypePage,
217  });
218 
219  fifo_write(window_word_count, data);
220  RETURN_IF_ERROR(wait_for_done(error));
221 
222  addr += window_word_count * sizeof(uint32_t);
223  data = (const char *)data + window_word_count * sizeof(uint32_t);
224  word_count -= window_word_count;
225  window_word_count = kWindowWordCount;
226  }
227 
228  return kErrorOk;
229 }
230 
231 /**
232  * Disables all access to a page until next reset.
233  *
234  * It's the responsibility of the caller to call `SEC_MMIO_WRITE_INCREMENT()`
235  * with the correct value.
236  *
237  * @param info_page An info page.
238  */
239 static void page_lockdown(const flash_ctrl_info_page_t *info_page) {
240  sec_mmio_write32(flash_ctrl_core_base() + info_page->cfg_offset, 0);
241  sec_mmio_write32(flash_ctrl_core_base() + info_page->cfg_wen_offset, 0);
242 }
243 
244 void flash_ctrl_init(void) {
246  kFlashCtrlSecMmioInit,
247  kFlashCtrlSecMmioDataDefaultCfgSet + 2 * kFlashCtrlSecMmioInfoCfgSet);
248 
249  // Set `HW_INFO_CFG_OVERRIDE` register if needed. This must be done before
250  // initializing the flash_ctrl.
251  uint32_t reg_val = FLASH_CTRL_HW_INFO_CFG_OVERRIDE_REG_RESVAL;
252  uint32_t otp_val = otp_read32(
253  OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_HW_INFO_CFG_OVERRIDE_OFFSET);
254  multi_bit_bool_t scramble_dis = bitfield_field32_read(
255  otp_val, FLASH_CTRL_OTP_FIELD_HW_INFO_CFG_OVERRIDE_SCRAMBLE_DIS);
256  if (scramble_dis == kMultiBitBool4True) {
257  reg_val = bitfield_field32_write(
258  reg_val, FLASH_CTRL_HW_INFO_CFG_OVERRIDE_SCRAMBLE_DIS_FIELD,
259  scramble_dis);
260  }
261  multi_bit_bool_t ecc_dis = bitfield_field32_read(
262  otp_val, FLASH_CTRL_OTP_FIELD_HW_INFO_CFG_OVERRIDE_ECC_DIS);
263  if (ecc_dis == kMultiBitBool4True) {
264  reg_val = bitfield_field32_write(
265  reg_val, FLASH_CTRL_HW_INFO_CFG_OVERRIDE_ECC_DIS_FIELD, ecc_dis);
266  }
267  if (reg_val != FLASH_CTRL_HW_INFO_CFG_OVERRIDE_REG_RESVAL) {
269  flash_ctrl_core_base() + FLASH_CTRL_HW_INFO_CFG_OVERRIDE_REG_OFFSET,
270  reg_val);
271  }
272 
273  // Initialize the flash controller.
274  abs_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_INIT_REG_OFFSET,
275  bitfield_bit32_write(0, FLASH_CTRL_INIT_VAL_BIT, true));
276  // Configure default scrambling, ECC, and HE settings for the data partition.
277  otp_val =
278  otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_DATA_DEFAULT_CFG_OFFSET);
279  flash_ctrl_cfg_t data_default_cfg = {
280  .scrambling =
281  bitfield_field32_read(otp_val, FLASH_CTRL_OTP_FIELD_SCRAMBLING),
282  .ecc = bitfield_field32_read(otp_val, FLASH_CTRL_OTP_FIELD_ECC),
283  .he = bitfield_field32_read(otp_val, FLASH_CTRL_OTP_FIELD_HE),
284  };
285  flash_ctrl_data_default_cfg_set(data_default_cfg);
286  // Configure scrambling, ECC, and HE for `boot_data` pages.
287  otp_val =
288  otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_INFO_BOOT_DATA_CFG_OFFSET);
289  flash_ctrl_cfg_t boot_data_cfg = {
290  .scrambling =
291  bitfield_field32_read(otp_val, FLASH_CTRL_OTP_FIELD_SCRAMBLING),
292  .ecc = bitfield_field32_read(otp_val, FLASH_CTRL_OTP_FIELD_ECC),
293  .he = bitfield_field32_read(otp_val, FLASH_CTRL_OTP_FIELD_HE),
294  };
295  flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageBootData0, boot_data_cfg);
296  flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageBootData1, boot_data_cfg);
297 }
298 
299 void flash_ctrl_status_get(flash_ctrl_status_t *status) {
300  // Read flash controller status.
301  uint32_t fc_status =
302  abs_mmio_read32(flash_ctrl_core_base() + FLASH_CTRL_STATUS_REG_OFFSET);
303 
304  // Extract flash controller status bits.
305  status->rd_full =
306  bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_RD_FULL_BIT);
307  status->rd_empty =
308  bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_RD_EMPTY_BIT);
309  status->prog_full =
310  bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_PROG_FULL_BIT);
311  status->prog_empty =
312  bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_PROG_EMPTY_BIT);
313  status->init_wip =
314  bitfield_bit32_read(fc_status, FLASH_CTRL_STATUS_INIT_WIP_BIT);
315 }
316 
317 void flash_ctrl_error_code_get(flash_ctrl_error_code_t *error_code) {
318  // Read flash error code.
319  uint32_t code =
320  abs_mmio_read32(flash_ctrl_core_base() + FLASH_CTRL_ERR_CODE_REG_OFFSET);
321 
322  // Extract flash controller error code bits.
323  error_code->macro_err =
324  bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_MACRO_ERR_BIT);
325  error_code->update_err =
326  bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_UPDATE_ERR_BIT);
327  error_code->prog_type_err =
328  bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_PROG_TYPE_ERR_BIT);
329  error_code->prog_win_err =
330  bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_PROG_WIN_ERR_BIT);
331  error_code->prog_err =
332  bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_PROG_ERR_BIT);
333  error_code->rd_err =
334  bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_RD_ERR_BIT);
335  error_code->mp_err =
336  bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_MP_ERR_BIT);
337  error_code->op_err =
338  bitfield_bit32_read(code, FLASH_CTRL_ERR_CODE_OP_ERR_BIT);
339 }
340 
341 rom_error_t flash_ctrl_data_read(uint32_t addr, uint32_t word_count,
342  void *data) {
343  transaction_start((transaction_params_t){
344  .addr = addr,
345  .op_type = FLASH_CTRL_CONTROL_OP_VALUE_READ,
346  .partition = kFlashCtrlPartitionData,
347  .word_count = word_count,
348  // Does not apply to read transactions.
349  .erase_type = kFlashCtrlEraseTypePage,
350  });
351  fifo_read(word_count, data);
352  return wait_for_done(kErrorFlashCtrlDataRead);
353 }
354 
355 rom_error_t flash_ctrl_info_read(const flash_ctrl_info_page_t *info_page,
356  uint32_t offset, uint32_t word_count,
357  void *data) {
358  transaction_start((transaction_params_t){
359  .addr = info_page->base_addr + offset,
360  .op_type = FLASH_CTRL_CONTROL_OP_VALUE_READ,
361  .partition = kFlashCtrlPartitionInfo0,
362  .word_count = word_count,
363  // Does not apply to read transactions.
364  .erase_type = kFlashCtrlEraseTypePage,
365  });
366  fifo_read(word_count, data);
367  return wait_for_done(kErrorFlashCtrlInfoRead);
368 }
369 
370 rom_error_t flash_ctrl_info_read_zeros_on_read_error(
371  const flash_ctrl_info_page_t *info_page, uint32_t offset,
372  uint32_t word_count, void *data) {
373  rom_error_t err = flash_ctrl_info_read(info_page, offset, word_count, data);
374  if (err != kErrorOk) {
375  flash_ctrl_error_code_t flash_ctrl_err_code;
376  flash_ctrl_error_code_get(&flash_ctrl_err_code);
377  if (flash_ctrl_err_code.rd_err) {
378  // If we encountered a read error, return all 0s.
379  memset(data, 0, word_count * sizeof(uint32_t));
380  return kErrorOk;
381  }
382  }
383  return err;
384 }
385 
386 void flash_ctrl_info_lock(const flash_ctrl_info_page_t *info_page) {
387  abs_mmio_write32(flash_ctrl_core_base() + info_page->cfg_wen_offset, 0);
388 }
389 
390 rom_error_t flash_ctrl_data_write(uint32_t addr, uint32_t word_count,
391  const void *data) {
392  return write(addr, kFlashCtrlPartitionData, word_count, data,
393  kErrorFlashCtrlDataWrite);
394 }
395 
396 rom_error_t flash_ctrl_info_write(const flash_ctrl_info_page_t *info_page,
397  uint32_t offset, uint32_t word_count,
398  const void *data) {
399  const uint32_t addr = info_page->base_addr + offset;
400  return write(addr, kFlashCtrlPartitionInfo0, word_count, data,
401  kErrorFlashCtrlInfoWrite);
402 }
403 
404 rom_error_t flash_ctrl_data_erase(uint32_t addr,
405  flash_ctrl_erase_type_t erase_type) {
406  transaction_start((transaction_params_t){
407  .addr = addr,
408  .op_type = FLASH_CTRL_CONTROL_OP_VALUE_ERASE,
409  .erase_type = erase_type,
410  .partition = kFlashCtrlPartitionData,
411  // Does not apply to erase transactions.
412  .word_count = 1,
413  });
414  return wait_for_done(kErrorFlashCtrlDataErase);
415 }
416 
417 rom_error_t flash_ctrl_data_erase_verify(uint32_t addr,
418  flash_ctrl_erase_type_t erase_type) {
419  static_assert(__builtin_popcount(FLASH_CTRL_PARAM_BYTES_PER_BANK) == 1,
420  "Bytes per bank must be a power of two.");
421  static_assert(__builtin_popcount(FLASH_CTRL_PARAM_BYTES_PER_PAGE) == 1,
422  "Bytes per page must be a power of two.");
423 
424  size_t byte_count = 0;
425  rom_error_t error = kErrorFlashCtrlDataEraseVerify;
426  switch (launder32(erase_type)) {
427  case kFlashCtrlEraseTypeBank:
428  HARDENED_CHECK_EQ(erase_type, kFlashCtrlEraseTypeBank);
429  byte_count = FLASH_CTRL_PARAM_BYTES_PER_BANK;
430  error = kErrorOk ^ (byte_count - 1);
431  break;
432  case kFlashCtrlEraseTypePage:
433  HARDENED_CHECK_EQ(erase_type, kFlashCtrlEraseTypePage);
434  byte_count = FLASH_CTRL_PARAM_BYTES_PER_PAGE;
435  error = kErrorOk ^ (byte_count - 1);
436  break;
437  default:
438  HARDENED_TRAP();
439  byte_count = 0U;
440  break;
441  }
442 
443  // Truncate to the closest lower bank/page aligned address.
444  addr &= ~byte_count + 1;
445  uint32_t mask = kFlashCtrlErasedWord;
446  size_t i = 0, r = byte_count - 1;
447  uint32_t mem_base =
448  dt_flash_ctrl_reg_block(kFlashCtrlDt, kDtFlashCtrlRegBlockMem);
449  for (; launder32(i) < byte_count && launder32(r) < byte_count;
450  i += sizeof(uint32_t), r -= sizeof(uint32_t)) {
451  uint32_t word = abs_mmio_read32(mem_base + addr + i);
452  mask &= word;
453  error &= word;
454  }
455  HARDENED_CHECK_EQ(i, byte_count);
456  HARDENED_CHECK_EQ(r, SIZE_MAX);
457 
458  if (launder32(mask) == kFlashCtrlErasedWord) {
459  HARDENED_CHECK_EQ(mask, kFlashCtrlErasedWord);
460  return error ^ (byte_count - 1);
461  }
462 
463  return kErrorFlashCtrlDataEraseVerify;
464 }
465 
466 rom_error_t flash_ctrl_info_erase(const flash_ctrl_info_page_t *info_page,
467  flash_ctrl_erase_type_t erase_type) {
468  transaction_start((transaction_params_t){
469  .addr = info_page->base_addr,
470  .op_type = FLASH_CTRL_CONTROL_OP_VALUE_ERASE,
471  .erase_type = erase_type,
472  .partition = kFlashCtrlPartitionInfo0,
473  // Does not apply to erase transactions.
474  .word_count = 1,
475  });
476  return wait_for_done(kErrorFlashCtrlInfoErase);
477 }
478 
479 void flash_ctrl_exec_set(uint32_t exec_val) {
480  SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioExecSet, 1);
481  sec_mmio_write32(flash_ctrl_core_base() + FLASH_CTRL_EXEC_REG_OFFSET,
482  exec_val);
483 }
484 
485 void flash_ctrl_data_default_perms_set(flash_ctrl_perms_t perms) {
486  SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioDataDefaultPermsSet, 1);
487 
488  // Read first to preserve ECC, scrambling, and high endurance bits.
489  uint32_t reg = sec_mmio_read32(flash_ctrl_core_base() +
490  FLASH_CTRL_DEFAULT_REGION_REG_OFFSET);
491  reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_RD_EN_FIELD,
492  perms.read);
493  reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_PROG_EN_FIELD,
494  perms.write);
495  reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_ERASE_EN_FIELD,
496  perms.erase);
498  flash_ctrl_core_base() + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET, reg);
499 }
500 
501 void flash_ctrl_info_perms_set(const flash_ctrl_info_page_t *info_page,
502  flash_ctrl_perms_t perms) {
503  SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioInfoPermsSet, 1);
504 
505  // Read first to preserve ECC, scrambling, and high endurance bits.
506  uint32_t reg =
507  sec_mmio_read32(flash_ctrl_core_base() + info_page->cfg_offset);
509  reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_EN_0_FIELD, kMultiBitBool4True);
511  reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_RD_EN_0_FIELD, perms.read);
513  reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_PROG_EN_0_FIELD, perms.write);
515  reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_ERASE_EN_0_FIELD, perms.erase);
516  sec_mmio_write32(flash_ctrl_core_base() + info_page->cfg_offset, reg);
517 }
518 
519 void flash_ctrl_data_default_cfg_set(flash_ctrl_cfg_t cfg) {
520  SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioDataDefaultCfgSet, 1);
521 
522  // Read first to preserve permission bits.
523  uint32_t reg = sec_mmio_read32(flash_ctrl_core_base() +
524  FLASH_CTRL_DEFAULT_REGION_REG_OFFSET);
525  reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_SCRAMBLE_EN_FIELD,
526  cfg.scrambling);
527  reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_ECC_EN_FIELD,
528  cfg.ecc);
529  reg = bitfield_field32_write(reg, FLASH_CTRL_DEFAULT_REGION_HE_EN_FIELD,
530  cfg.he);
532  flash_ctrl_core_base() + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET, reg);
533 }
534 
535 flash_ctrl_cfg_t flash_ctrl_data_default_cfg_get(void) {
536  const uint32_t default_region = sec_mmio_read32(
537  flash_ctrl_core_base() + FLASH_CTRL_DEFAULT_REGION_REG_OFFSET);
538  return (flash_ctrl_cfg_t){
539  .scrambling = bitfield_field32_read(
540  default_region, FLASH_CTRL_DEFAULT_REGION_SCRAMBLE_EN_FIELD),
541  .ecc = bitfield_field32_read(default_region,
542  FLASH_CTRL_DEFAULT_REGION_ECC_EN_FIELD),
543  .he = bitfield_field32_read(default_region,
544  FLASH_CTRL_DEFAULT_REGION_HE_EN_FIELD),
545  };
546 }
547 
548 // This X macro helps to generate code that operates on each of the flash_ctrl
549 // memory protection regions.
550 #define FLASH_CTRL_MP_REGIONS(X) \
551  X(0) \
552  X(1) \
553  X(2) \
554  X(3) \
555  X(4) \
556  X(5) \
557  X(6) \
558  X(7)
559 
560 // Defines the bounds of the given memory protection region by setting the
561 // MP_REGION_${region} register.
562 static void flash_ctrl_mp_region_write(flash_ctrl_region_index_t region,
563  uint32_t page_offset,
564  uint32_t num_pages) {
565 #define FLASH_CTRL_MP_REGION_WRITE_(region_macro_arg) \
566  case ((region_macro_arg)): { \
567  HARDENED_CHECK_EQ(region, (region_macro_arg)); \
568  uint32_t mp_region = FLASH_CTRL_MP_REGION_##region_macro_arg##_REG_RESVAL; \
569  /* Write the region's base address into the bitfield. */ \
570  mp_region = bitfield_field32_write( \
571  mp_region, \
572  FLASH_CTRL_MP_REGION_##region_macro_arg##_BASE_##region_macro_arg##_FIELD, \
573  page_offset); \
574  /* Write the region's size in pages into the bitfield. */ \
575  mp_region = bitfield_field32_write( \
576  mp_region, \
577  FLASH_CTRL_MP_REGION_##region_macro_arg##_SIZE_##region_macro_arg##_FIELD, \
578  num_pages); \
579  /* Write the bitfield to the MP_REGION_${region} register. */ \
580  sec_mmio_write32(flash_ctrl_core_base() + \
581  FLASH_CTRL_MP_REGION_##region_macro_arg##_REG_OFFSET, \
582  mp_region); \
583  return; \
584  }
585 
586  switch (launder32(region)) {
587  FLASH_CTRL_MP_REGIONS(FLASH_CTRL_MP_REGION_WRITE_)
588  default:
589  OT_UNREACHABLE();
590  }
591 
592 #undef FLASH_CTRL_MP_REGION_WRITE_
593 }
594 
595 // Resets the given region's memory protection config by resetting the
596 // MP_REGION_CFG_${region} register, which implicitly disables the region.
597 static void flash_ctrl_mp_region_cfg_reset(flash_ctrl_region_index_t region) {
598 #define FLASH_CTRL_MP_REGION_CFG_RESET_(region_macro_arg) \
599  case ((region_macro_arg)): { \
600  HARDENED_CHECK_EQ(region, (region_macro_arg)); \
601  static_assert( \
602  (FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_RESVAL & \
603  FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_EN_##region_macro_arg##_MASK) == \
604  kMultiBitBool4False, \
605  "FLASH_CTRL_MP_REGION_CFG_" #region_macro_arg \
606  "'s reset value should disable the region"); \
607  /* Reset the MP_REGION_CFG_${region} register. */ \
608  sec_mmio_write32( \
609  flash_ctrl_core_base() + \
610  FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_OFFSET, \
611  FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_RESVAL); \
612  return; \
613  }
614 
615  switch (launder32(region)) {
616  FLASH_CTRL_MP_REGIONS(FLASH_CTRL_MP_REGION_CFG_RESET_)
617  default:
618  OT_UNREACHABLE();
619  }
620 
621 #undef FLASH_CTRL_MP_CFG_RESET_
622 }
623 
624 // Configures permissions for the given MP region by setting the appropriate
625 // MP_REGION_CFG register.
626 static void flash_ctrl_mp_region_cfg_write(flash_ctrl_region_index_t region,
627  flash_ctrl_cfg_t cfg,
628  flash_ctrl_perms_t perms,
629  multi_bit_bool_t en,
630  hardened_bool_t lock) {
631 #define FLASH_CTRL_MP_REGION_CFG_WRITE_(region_macro_arg) \
632  case ((region_macro_arg)): { \
633  HARDENED_CHECK_EQ(region, (region_macro_arg)); \
634  uint32_t mp_region_cfg = \
635  FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_RESVAL; \
636  mp_region_cfg = bitfield_field32_write( \
637  mp_region_cfg, \
638  FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_HE_EN_##region_macro_arg##_FIELD, \
639  cfg.he); \
640  mp_region_cfg = bitfield_field32_write( \
641  mp_region_cfg, \
642  FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_ECC_EN_##region_macro_arg##_FIELD, \
643  cfg.ecc); \
644  mp_region_cfg = bitfield_field32_write( \
645  mp_region_cfg, \
646  FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_SCRAMBLE_EN_##region_macro_arg##_FIELD, \
647  cfg.scrambling); \
648  mp_region_cfg = bitfield_field32_write( \
649  mp_region_cfg, \
650  FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_ERASE_EN_##region_macro_arg##_FIELD, \
651  perms.erase); \
652  mp_region_cfg = bitfield_field32_write( \
653  mp_region_cfg, \
654  FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_PROG_EN_##region_macro_arg##_FIELD, \
655  perms.write); \
656  mp_region_cfg = bitfield_field32_write( \
657  mp_region_cfg, \
658  FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_RD_EN_##region_macro_arg##_FIELD, \
659  perms.read); \
660  mp_region_cfg = bitfield_field32_write( \
661  mp_region_cfg, \
662  FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_EN_##region_macro_arg##_FIELD, \
663  en); \
664  sec_mmio_write32( \
665  flash_ctrl_core_base() + \
666  FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_OFFSET, \
667  mp_region_cfg); \
668  if (lock != kHardenedBoolFalse) { \
669  sec_mmio_write32( \
670  flash_ctrl_core_base() + \
671  FLASH_CTRL_REGION_CFG_REGWEN_##region_macro_arg##_REG_OFFSET, \
672  0); \
673  } \
674  return; \
675  }
676 
677  switch (launder32(region)) {
678  FLASH_CTRL_MP_REGIONS(FLASH_CTRL_MP_REGION_CFG_WRITE_)
679  default:
680  OT_UNREACHABLE();
681  }
682 
683 #undef FLASH_CTRL_MP_REGION_CFG_WRITE_
684 }
685 
686 void flash_ctrl_data_region_protect(flash_ctrl_region_index_t region,
687  uint32_t page_offset, uint32_t num_pages,
688  flash_ctrl_perms_t perms,
689  flash_ctrl_cfg_t cfg,
690  hardened_bool_t lock) {
691  // Reset the region's configuration via the MP_REGION_CFG_${region} register.
692  // This temporarily disables memory protection for the region.
693  flash_ctrl_mp_region_cfg_reset(region);
694 
695  // Set the region's bounds in the MP_REGION_${region} register.
696  flash_ctrl_mp_region_write(region, page_offset, num_pages);
697 
698  // Write the new value of MP_REGION_CFG_${region}.
699  flash_ctrl_mp_region_cfg_write(region, cfg, perms,
700  /*en=*/kMultiBitBool4True, lock);
701 }
702 
703 void flash_ctrl_info_cfg_set(const flash_ctrl_info_page_t *info_page,
704  flash_ctrl_cfg_t cfg) {
705  SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioInfoCfgSet, 1);
706 
707  // Read first to preserve permission bits.
708  uint32_t reg =
709  sec_mmio_read32(flash_ctrl_core_base() + info_page->cfg_offset);
711  reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_EN_0_FIELD, kMultiBitBool4True);
713  reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_SCRAMBLE_EN_0_FIELD,
714  cfg.scrambling);
716  reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_ECC_EN_0_FIELD, cfg.ecc);
718  reg, FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_HE_EN_0_FIELD, cfg.he);
719  sec_mmio_write32(flash_ctrl_core_base() + info_page->cfg_offset, reg);
720 }
721 
722 void flash_ctrl_info_cfg_lock(const flash_ctrl_info_page_t *info_page) {
723  sec_mmio_write32(flash_ctrl_core_base() + info_page->cfg_wen_offset, 0);
724 }
725 
726 void flash_ctrl_bank_erase_perms_set(hardened_bool_t enable) {
727  uint32_t reg = 0;
728  switch (launder32(enable)) {
729  case kHardenedBoolTrue:
731  reg = bitfield_bit32_write(
732  0, FLASH_CTRL_MP_BANK_CFG_SHADOWED_ERASE_EN_0_BIT, true);
733  reg = bitfield_bit32_write(
734  reg, FLASH_CTRL_MP_BANK_CFG_SHADOWED_ERASE_EN_1_BIT, true);
735  break;
736  case kHardenedBoolFalse:
738  reg = 0U;
739  break;
740  default:
741  HARDENED_TRAP();
742  reg = 0U;
743  break;
744  }
746  flash_ctrl_core_base() + FLASH_CTRL_MP_BANK_CFG_SHADOWED_REG_OFFSET, reg);
747 }
748 
749 /**
750  * Information pages that should be locked by ROM_EXT before handing over
751  * execution to the first owner boot stage. See
752  * `flash_ctrl_creator_info_pages_lockdown()`.
753  */
754 static const flash_ctrl_info_page_t *kInfoPagesNoOwnerAccess[] = {
755  // Bank 0
756  &kFlashCtrlInfoPageFactoryId,
757  &kFlashCtrlInfoPageCreatorSecret,
758  &kFlashCtrlInfoPageOwnerSecret,
759  &kFlashCtrlInfoPageWaferAuthSecret,
760  // Bank 1
761  &kFlashCtrlInfoPageBootData0,
762  &kFlashCtrlInfoPageBootData1,
763 };
764 
765 enum {
766  kInfoPagesNoOwnerAccessCount = ARRAYSIZE(kInfoPagesNoOwnerAccess),
767 };
768 
769 void flash_ctrl_creator_info_pages_lockdown(void) {
770  SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioCreatorInfoPagesLockdown,
771  2 * kInfoPagesNoOwnerAccessCount);
772  size_t i = 0, r = kInfoPagesNoOwnerAccessCount - 1;
773  for (; launder32(i) < kInfoPagesNoOwnerAccessCount &&
774  launder32(r) < kInfoPagesNoOwnerAccessCount;
775  ++i, --r) {
776  page_lockdown(kInfoPagesNoOwnerAccess[i]);
777  }
778  HARDENED_CHECK_EQ(i, kInfoPagesNoOwnerAccessCount);
779  HARDENED_CHECK_EQ(r, SIZE_MAX);
780 }
781 
782 const flash_ctrl_cfg_t kCertificateInfoPageCfg = {
783  .scrambling = kMultiBitBool4True,
784  .ecc = kMultiBitBool4True,
785  .he = kMultiBitBool4False,
786 };
787 const flash_ctrl_perms_t kCertificateInfoPageCreatorAccess = {
788  .read = kMultiBitBool4True,
789  .write = kMultiBitBool4True,
790  .erase = kMultiBitBool4True,
791 };
792 const flash_ctrl_perms_t kCertificateInfoPageOwnerAccess = {
793  .read = kMultiBitBool4True,
794  .write = kMultiBitBool4False,
795  .erase = kMultiBitBool4False,
796 };
797 
798 void flash_ctrl_cert_info_page_creator_cfg(
799  const flash_ctrl_info_page_t *info_page) {
800  SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioCertInfoPageCreatorCfg, 2);
801  flash_ctrl_info_cfg_set(info_page, kCertificateInfoPageCfg);
802  flash_ctrl_info_perms_set(info_page, kCertificateInfoPageCreatorAccess);
803 }
804 
805 void flash_ctrl_cert_info_page_owner_restrict(
806  const flash_ctrl_info_page_t *info_page) {
807  SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioCertInfoPageOwnerRestrict,
808  1);
809  flash_ctrl_info_perms_set(info_page, kCertificateInfoPageOwnerAccess);
810 }