5#include "sw/device/silicon_creator/lib/nvm_ctrl.h"
10#include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
15enum { kNvmInfoPagesPerBank = FLASH_CTRL_PARAM_NUM_INFOS0 };
21static const flash_ctrl_info_page_t *
const kPageTable[] = {
22 [kNvmInfoPageFactoryId] = &kFlashCtrlInfoPageFactoryId,
23 [kNvmInfoPageCreatorSecret] = &kFlashCtrlInfoPageCreatorSecret,
24 [kNvmInfoPageOwnerSecret] = &kFlashCtrlInfoPageOwnerSecret,
25 [kNvmInfoPageWaferAuthSecret] = &kFlashCtrlInfoPageWaferAuthSecret,
26 [kNvmInfoPageAttestationKeySeeds] = &kFlashCtrlInfoPageAttestationKeySeeds,
27 [kNvmInfoPageOwnerReserved0] = &kFlashCtrlInfoPageOwnerReserved0,
28 [kNvmInfoPageOwnerReserved1] = &kFlashCtrlInfoPageOwnerReserved1,
29 [kNvmInfoPageOwnerReserved2] = &kFlashCtrlInfoPageOwnerReserved2,
30 [kNvmInfoPageOwnerReserved3] = &kFlashCtrlInfoPageOwnerReserved3,
31 [kNvmInfoPageFactoryCerts] = &kFlashCtrlInfoPageFactoryCerts,
32 [kNvmInfoPageBootData0] = &kFlashCtrlInfoPageBootData0,
33 [kNvmInfoPageBootData1] = &kFlashCtrlInfoPageBootData1,
34 [kNvmInfoPageOwnerSlot0] = &kFlashCtrlInfoPageOwnerSlot0,
35 [kNvmInfoPageOwnerSlot1] = &kFlashCtrlInfoPageOwnerSlot1,
36 [kNvmInfoPageCreatorReserved0] = &kFlashCtrlInfoPageCreatorReserved0,
37 [kNvmInfoPageOwnerReserved4] = &kFlashCtrlInfoPageOwnerReserved4,
38 [kNvmInfoPageOwnerReserved5] = &kFlashCtrlInfoPageOwnerReserved5,
39 [kNvmInfoPageOwnerReserved6] = &kFlashCtrlInfoPageOwnerReserved6,
40 [kNvmInfoPageOwnerReserved7] = &kFlashCtrlInfoPageOwnerReserved7,
41 [kNvmInfoPageDiceCerts] = &kFlashCtrlInfoPageDiceCerts,
45static_assert(
ARRAYSIZE(kPageTable) <= NVM_NUM_BANKS * kNvmInfoPagesPerBank,
46 "More named pages than hardware supports");
52static const flash_ctrl_info_page_t *page_ptr(nvm_info_page_t page) {
53 HARDENED_CHECK_LT((uint32_t)page,
ARRAYSIZE(kPageTable));
54 return kPageTable[(uint32_t)page];
57static flash_ctrl_perms_t perms_to_flash(nvm_page_perms_t p) {
58 return (flash_ctrl_perms_t){
59 .read = (uint32_t)p.read,
60 .write = (uint32_t)p.write,
61 .erase = (uint32_t)p.erase,
65static flash_ctrl_cfg_t cfg_to_flash(nvm_page_cfg_t c) {
66 return (flash_ctrl_cfg_t){
67 .scrambling = (uint32_t)c.scrambling,
68 .ecc = (uint32_t)c.ecc,
73static nvm_page_cfg_t cfg_from_flash(flash_ctrl_cfg_t c) {
74 return (nvm_page_cfg_t){
76 .ecc = (multi_bit_bool_t)c.
ecc,
77 .he = (multi_bit_bool_t)c.
he,
85const nvm_page_perms_t kNvmPagePermsReadWrite = {.read = kMultiBitBool4True,
86 .write = kMultiBitBool4True,
87 .erase = kMultiBitBool4True};
88const nvm_page_perms_t kNvmPagePermsReadOnly = {.read = kMultiBitBool4True,
89 .write = kMultiBitBool4False,
90 .erase = kMultiBitBool4False};
91const nvm_page_perms_t kNvmPagePermsNone = {.read = kMultiBitBool4False,
92 .write = kMultiBitBool4False,
93 .erase = kMultiBitBool4False};
94const nvm_page_perms_t kNvmPagePermsErase = {.read = kMultiBitBool4False,
95 .write = kMultiBitBool4False,
96 .erase = kMultiBitBool4True};
98const nvm_page_cfg_t kNvmPageCfgScrambled = {.scrambling = kMultiBitBool4True,
99 .ecc = kMultiBitBool4True,
100 .he = kMultiBitBool4False};
101const nvm_page_cfg_t kNvmPageCfgPlain = {.scrambling = kMultiBitBool4False,
102 .ecc = kMultiBitBool4True,
103 .he = kMultiBitBool4False};
104const nvm_page_cfg_t kNvmPageCfgRaw = {.scrambling = kMultiBitBool4False,
105 .ecc = kMultiBitBool4False,
106 .he = kMultiBitBool4False};
108const nvm_page_cfg_t kNvmCertInfoPageCfg = {.scrambling = kMultiBitBool4True,
109 .ecc = kMultiBitBool4True,
110 .he = kMultiBitBool4False};
111const nvm_page_perms_t kNvmCertInfoPageCreatorAccess = {
112 .read = kMultiBitBool4True,
113 .write = kMultiBitBool4True,
114 .erase = kMultiBitBool4True};
115const nvm_page_perms_t kNvmCertInfoPageOwnerAccess = {
116 .read = kMultiBitBool4True,
117 .write = kMultiBitBool4False,
118 .erase = kMultiBitBool4False};
124void nvm_ctrl_init(
void) { flash_ctrl_init(); }
125void nvm_ctrl_disable(
void) { flash_ctrl_disable(); }
131rom_error_t nvm_ctrl_info_page_lookup(uint8_t bank, uint8_t page,
132 nvm_info_page_t *out) {
133 if ((uint32_t)bank >= (uint32_t)NVM_NUM_BANKS ||
134 (uint32_t)page >= (uint32_t)kNvmInfoPagesPerBank) {
135 return kErrorNvmCtrlInvalidInfoPage;
137 *out = (nvm_info_page_t)(bank * kNvmInfoPagesPerBank + page);
145rom_error_t nvm_ctrl_data_read(uint32_t addr, uint32_t word_count,
void *data) {
146 return flash_ctrl_data_read(addr, word_count, data);
149rom_error_t nvm_ctrl_data_write(uint32_t addr, uint32_t word_count,
151 return flash_ctrl_data_write(addr, word_count, data);
154rom_error_t nvm_ctrl_data_erase(uint32_t addr) {
155 return flash_ctrl_data_erase(addr, kFlashCtrlEraseTypePage);
158rom_error_t nvm_ctrl_data_erase_verify(uint32_t addr) {
159 return flash_ctrl_data_erase_verify(addr, kFlashCtrlEraseTypePage);
162rom_error_t nvm_ctrl_chip_erase(
void) {
164 rom_error_t err_0 = flash_ctrl_data_erase(0, kFlashCtrlEraseTypeBank);
165 rom_error_t err_1 = flash_ctrl_data_erase(FLASH_CTRL_PARAM_BYTES_PER_BANK,
166 kFlashCtrlEraseTypeBank);
168 HARDENED_RETURN_IF_ERROR(err_0);
172rom_error_t nvm_ctrl_chip_erase_verify(
void) {
173 rom_error_t err_0 = flash_ctrl_data_erase_verify(0, kFlashCtrlEraseTypeBank);
174 rom_error_t err_1 = flash_ctrl_data_erase_verify(
175 FLASH_CTRL_PARAM_BYTES_PER_BANK, kFlashCtrlEraseTypeBank);
176 HARDENED_RETURN_IF_ERROR(err_0);
180rom_error_t nvm_ctrl_page_program(uint32_t addr,
size_t byte_count,
182 static_assert((FLASH_CTRL_PARAM_BYTES_PER_WORD &
183 (FLASH_CTRL_PARAM_BYTES_PER_WORD - 1)) == 0,
184 "Bytes per NVM word must be a power of two.");
186 kWordMask = FLASH_CTRL_PARAM_BYTES_PER_WORD - 1,
188 kProgPageMask = kProgPageSize - 1,
192 size_t word_misalignment = byte_count & kWordMask;
193 if (word_misalignment > 0) {
194 size_t pad = FLASH_CTRL_PARAM_BYTES_PER_WORD - word_misalignment;
195 for (
size_t i = 0; i < pad; ++i) {
196 data[byte_count++] = 0xff;
199 size_t rem_word_count = byte_count /
sizeof(uint32_t);
201 flash_ctrl_data_default_perms_set((flash_ctrl_perms_t){
202 .read = kMultiBitBool4False,
203 .write = kMultiBitBool4True,
204 .erase = kMultiBitBool4False,
209 rom_error_t err_0 = kErrorOk;
210 size_t prog_page_misalignment = addr & kProgPageMask;
211 if (prog_page_misalignment > 0) {
213 (kProgPageSize - prog_page_misalignment) /
sizeof(uint32_t);
214 if (word_count > rem_word_count) {
215 word_count = rem_word_count;
217 err_0 = flash_ctrl_data_write(addr, word_count, data);
218 rem_word_count -= word_count;
219 data += word_count *
sizeof(uint32_t);
220 addr &= ~(uint32_t)kProgPageMask;
222 rom_error_t err_1 = kErrorOk;
223 if (rem_word_count > 0) {
224 err_1 = flash_ctrl_data_write(addr, rem_word_count, data);
226 flash_ctrl_data_default_perms_set((flash_ctrl_perms_t){
227 .read = kMultiBitBool4False,
228 .write = kMultiBitBool4False,
229 .erase = kMultiBitBool4False,
231 HARDENED_RETURN_IF_ERROR(err_0);
235rom_error_t nvm_ctrl_sector_erase(uint32_t addr) {
236 static_assert(FLASH_CTRL_PARAM_BYTES_PER_PAGE == 2048,
237 "Page size must be 2 KiB");
238 enum { kSectorAddrMask = ~UINT32_C(4096) + 1 };
239 addr &= kSectorAddrMask;
240 flash_ctrl_data_default_perms_set((flash_ctrl_perms_t){
241 .read = kMultiBitBool4False,
242 .write = kMultiBitBool4False,
243 .erase = kMultiBitBool4True,
245 rom_error_t err_0 = flash_ctrl_data_erase(addr, kFlashCtrlEraseTypePage);
246 rom_error_t err_1 = flash_ctrl_data_erase(
247 addr + FLASH_CTRL_PARAM_BYTES_PER_PAGE, kFlashCtrlEraseTypePage);
248 flash_ctrl_data_default_perms_set((flash_ctrl_perms_t){
249 .read = kMultiBitBool4False,
250 .write = kMultiBitBool4False,
251 .erase = kMultiBitBool4False,
253 HARDENED_RETURN_IF_ERROR(err_0);
261rom_error_t nvm_ctrl_info_read(nvm_info_page_t page, uint32_t offset,
262 uint32_t word_count,
void *data) {
263 return flash_ctrl_info_read(page_ptr(page), offset, word_count, data);
266rom_error_t nvm_ctrl_info_read_zeros_on_read_error(nvm_info_page_t page,
270 return flash_ctrl_info_read_zeros_on_read_error(page_ptr(page), offset,
274rom_error_t nvm_ctrl_info_write(nvm_info_page_t page, uint32_t offset,
275 uint32_t word_count,
const void *data) {
276 return flash_ctrl_info_write(page_ptr(page), offset, word_count, data);
279rom_error_t nvm_ctrl_info_erase(nvm_info_page_t page) {
280 return flash_ctrl_info_erase(page_ptr(page), kFlashCtrlEraseTypePage);
287void nvm_ctrl_data_default_perms_set(nvm_page_perms_t perms) {
288 flash_ctrl_data_default_perms_set(perms_to_flash(perms));
291void nvm_ctrl_info_perms_set(nvm_info_page_t page, nvm_page_perms_t perms) {
292 flash_ctrl_info_perms_set(page_ptr(page), perms_to_flash(perms));
295void nvm_ctrl_data_default_cfg_set(nvm_page_cfg_t cfg) {
296 flash_ctrl_data_default_cfg_set(cfg_to_flash(cfg));
299nvm_page_cfg_t nvm_ctrl_data_default_cfg_get(
void) {
300 return cfg_from_flash(flash_ctrl_data_default_cfg_get());
303nvm_page_cfg_t nvm_ctrl_boot_data_cfg_get(
void) {
304 return cfg_from_flash(flash_ctrl_boot_data_cfg_get());
307void nvm_ctrl_info_cfg_set(nvm_info_page_t page, nvm_page_cfg_t cfg) {
308 flash_ctrl_info_cfg_set(page_ptr(page), cfg_to_flash(cfg));
311void nvm_ctrl_info_cfg_lock(nvm_info_page_t page) {
312 flash_ctrl_info_cfg_lock(page_ptr(page));
319void nvm_ctrl_data_region_protect(uint32_t region, uint32_t page_offset,
320 uint32_t num_pages, nvm_page_perms_t perms,
322 flash_ctrl_data_region_protect(region, page_offset, num_pages,
323 perms_to_flash(perms), cfg_to_flash(cfg),
328 flash_ctrl_bank_erase_perms_set(enable);
331void nvm_ctrl_exec_set(uint32_t exec_val) { flash_ctrl_exec_set(exec_val); }
337static const nvm_info_page_t kNvmPagesNoOwnerAccess[] = {
338 kNvmInfoPageFactoryId, kNvmInfoPageCreatorSecret,
339 kNvmInfoPageOwnerSecret, kNvmInfoPageWaferAuthSecret,
340 kNvmInfoPageBootData0, kNvmInfoPageBootData1,
341 kNvmInfoPageCreatorReserved0,
345 kNvmPagesNoOwnerAccessCount =
ARRAYSIZE(kNvmPagesNoOwnerAccess),
348void nvm_ctrl_creator_info_pages_lockdown(
void) {
350 2 * kNvmPagesNoOwnerAccessCount);
351 size_t i = 0, r = kNvmPagesNoOwnerAccessCount - 1;
352 for (; launder32(i) < kNvmPagesNoOwnerAccessCount &&
353 launder32(r) < kNvmPagesNoOwnerAccessCount;
355 flash_ctrl_info_page_lockdown(page_ptr(kNvmPagesNoOwnerAccess[i]));
361void nvm_ctrl_cert_info_page_creator_cfg(nvm_info_page_t page) {
363 nvm_ctrl_info_cfg_set(page, kNvmCertInfoPageCfg);
364 nvm_ctrl_info_perms_set(page, kNvmCertInfoPageCreatorAccess);
367void nvm_ctrl_cert_info_page_owner_restrict(nvm_info_page_t page) {
369 nvm_ctrl_info_perms_set(page, kNvmCertInfoPageOwnerAccess);
370 nvm_ctrl_info_cfg_lock(page);