Software APIs
nvm_ctrl.h
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#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_NVM_CTRL_H_
6#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_NVM_CTRL_H_
7
8#include <stdint.h>
9
13#include "sw/device/lib/base/multibits.h"
14#include "sw/device/silicon_creator/lib/error.h"
15
16// Hardware parameter and address constants. Only nvm_ctrl.{h,c} may include
17// these headers directly; all other callers use the NVM_* aliases below.
18//
19// USE_FLASH/USE_RRAM select which backend's constants populate the NVM_*
20// aliases below; set per top by the `nvm_ctrl` build rule.
21#if defined(USE_FLASH)
23#if defined(OPENTITAN_IS_EARLGREY)
25#elif defined(OPENTITAN_IS_ENGLISHBREAKFAST)
27#else
28#error "USE_FLASH set for an unsupported top"
29#endif
30#elif defined(USE_RRAM)
31#include "sw/device/silicon_creator/lib/drivers/rram_ctrl.h"
32
34#if defined(OPENTITAN_IS_EARLGREY)
36#else
37#error "USE_RRAM set for an unsupported top"
38#endif
39#else
40#error "nvm_ctrl.h requires USE_FLASH or USE_RRAM to be defined"
41#endif
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47// ---------------------------------------------------------------------------
48// NVM layout constants
49// ---------------------------------------------------------------------------
50
51#if defined(USE_FLASH)
52/** Byte size of one NVM page. */
53#define NVM_BYTES_PER_PAGE FLASH_CTRL_PARAM_BYTES_PER_PAGE
54/** Byte size of one NVM program/read word. */
55#define NVM_BYTES_PER_WORD FLASH_CTRL_PARAM_BYTES_PER_WORD
56/** Byte size of one NVM bank. */
57#define NVM_BYTES_PER_BANK FLASH_CTRL_PARAM_BYTES_PER_BANK
58/** Number of NVM banks. */
59#define NVM_NUM_BANKS FLASH_CTRL_PARAM_REG_NUM_BANKS
60/** Number of data pages per NVM bank. */
61#define NVM_PAGES_PER_BANK FLASH_CTRL_PARAM_REG_PAGES_PER_BANK
62/** Value that enables code execution from NVM; see `nvm_ctrl_exec_set()`. */
63#define NVM_EXEC_EN FLASH_CTRL_PARAM_EXEC_EN
64#if defined(OPENTITAN_IS_EARLGREY)
65/** Base address of the NVM data partition in the system memory map. */
66#define NVM_DATA_BASE_ADDR TOP_EARLGREY_FLASH_CTRL_MEM_BASE_ADDR
67/** Total byte size of the NVM data partition. */
68#define NVM_DATA_SIZE_BYTES TOP_EARLGREY_FLASH_CTRL_MEM_SIZE_BYTES
69#elif defined(OPENTITAN_IS_ENGLISHBREAKFAST)
70/** Base address of the NVM data partition in the system memory map. */
71#define NVM_DATA_BASE_ADDR TOP_ENGLISHBREAKFAST_FLASH_CTRL_MEM_BASE_ADDR
72/** Total byte size of the NVM data partition. */
73#define NVM_DATA_SIZE_BYTES TOP_ENGLISHBREAKFAST_FLASH_CTRL_MEM_SIZE_BYTES
74#endif
75#elif defined(USE_RRAM)
76/** Byte size of one NVM page. */
77#define NVM_BYTES_PER_PAGE RRAM_CTRL_PARAM_BYTES_PER_PAGE
78/**
79 * Byte size of one NVM program/read word.
80 *
81 * This is a fixed, tech-agnostic value (matching flash's
82 * `FLASH_CTRL_PARAM_BYTES_PER_WORD`), not `RRAM_CTRL_PARAM_BYTES_PER_WORD`
83 * (16): callers like `boot_data.c` use it to size wire-format struct fields
84 * (e.g. `boot_data_t.is_valid`) that must stay identical regardless of NVM
85 * technology. RRAM's actual write granularity (4x this, 16 bytes) is a
86 * separate, driver-internal detail handled by `nvm_ctrl.c`/`rram_ctrl.c`.
87 */
88#define NVM_BYTES_PER_WORD 8
89/**
90 * Number of NVM banks.
91 *
92 * RRAM has no bank-erase concept, so the whole data partition is treated as
93 * a single bank; `NVM_BYTES_PER_BANK`/`NVM_PAGES_PER_BANK` describe the full
94 * data partition. Slot A/B addressing (the only thing that matters for
95 * dual-bank redundancy) is computed from `NVM_DATA_BASE_ADDR`/
96 * `NVM_DATA_SIZE_BYTES` directly and does not depend on this value.
97 */
98#define NVM_NUM_BANKS 1u
99/** Number of data pages per NVM bank. */
100#define NVM_PAGES_PER_BANK RRAM_CTRL_PARAM_NUM_DATA_PAGES
101/** Byte size of one NVM bank. */
102#define NVM_BYTES_PER_BANK (NVM_PAGES_PER_BANK * NVM_BYTES_PER_PAGE)
103/** Value that enables code execution from NVM; see `nvm_ctrl_exec_set()`. */
104#define NVM_EXEC_EN RRAM_CTRL_PARAM_EXEC_EN
105/**
106 * Base address of the NVM data partition in the system memory map.
107 *
108 * This is the CPU-visible, memory-mapped execute-in-place window (used e.g.
109 * to determine the current boot slot from the program counter), distinct
110 * from the 0-based byte offsets `rram_ctrl_data_read`/`_write` operate on.
111 */
112#define NVM_DATA_BASE_ADDR TOP_EARLGREY_RRAM_CTRL_HOST_BASE_ADDR
113/** Total byte size of the NVM data partition. */
114#define NVM_DATA_SIZE_BYTES \
115 (RRAM_CTRL_PARAM_NUM_DATA_PAGES * RRAM_CTRL_PARAM_BYTES_PER_PAGE)
116#endif // USE_FLASH / USE_RRAM
117
118/**
119 * Page/byte count of one firmware slot (A or B).
120 *
121 * There are always exactly two slots, splitting the NVM data partition in
122 * half regardless of technology: two banks of one slot each for flash, or one
123 * bank of two slots for RRAM.
124 */
125#define NVM_PAGES_PER_SLOT ((NVM_NUM_BANKS * NVM_PAGES_PER_BANK) / 2)
126#define NVM_BYTES_PER_SLOT (NVM_PAGES_PER_SLOT * NVM_BYTES_PER_PAGE)
127
128/** Absolute byte offset of Slot A's start within the NVM data partition. */
129#define NVM_SLOT_A_START_BYTES 0
130/** Absolute byte offset of Slot B's start within the NVM data partition. */
131#define NVM_SLOT_B_START_BYTES NVM_BYTES_PER_SLOT
132
133/**
134 * Byte size of the portion of a firmware slot actually usable for generic
135 * firmware: a slot's total size minus its reserved tail.
136 */
137#if defined(USE_RRAM)
138#define NVM_SLOT_USABLE_SIZE_BYTES \
139 (NVM_BYTES_PER_SLOT - kRramCtrlReservedPageCount * NVM_BYTES_PER_PAGE)
140#else
141#define NVM_SLOT_USABLE_SIZE_BYTES NVM_BYTES_PER_SLOT
142#endif // USE_RRAM
143
144/**
145 * Exclusive absolute upper bound, in bytes, of the portion of Slot A/B
146 * actually usable for generic firmware reads/writes/erases.
147 */
148#define NVM_SLOT_A_END_BYTES \
149 (NVM_SLOT_A_START_BYTES + NVM_SLOT_USABLE_SIZE_BYTES)
150#define NVM_SLOT_B_END_BYTES \
151 (NVM_SLOT_B_START_BYTES + NVM_SLOT_USABLE_SIZE_BYTES)
152
153/**
154 * Byte size of one NVM program transaction / SPI `PAGE_PROGRAM` "page".
155 *
156 * This is the SPI `PAGE_PROGRAM` wrap-around unit
157 * `nvm_ctrl_bootstrap_page_program()` uses internally, and the natural
158 * write-transaction size for the underlying NVM technology. It is NOT the same
159 * concept as `NVM_BYTES_PER_PAGE` (the erase granularity) -- the two happen to
160 * coincide for RRAM (both 512), but differ for flash (2048 erase vs. 256
161 * program/SPI-wrap).
162 *
163 * For RRAM, this matches `rram_phy_wr`'s store-buffer size (`BytesPerPage`
164 * in `rram_ctrl.hjson`): a write up to this size commits to the array as a
165 * single physical operation, and a write that straddles two of these units
166 * costs an extra one. For flash, it's simply the SPI NOR industry-standard
167 * `PAGE_PROGRAM` wrap size, with no known equivalent benefit to writing
168 * more than one at a time.
169 */
170#if defined(USE_RRAM)
171#define NVM_PROG_PAGE_SIZE 512
172#else
173#define NVM_PROG_PAGE_SIZE 256
174#endif
175
176/** Value of a word in NVM after erase. */
177#define kNvmErasedWord UINT32_MAX
178
179// ---------------------------------------------------------------------------
180// Access permission and configuration types
181// ---------------------------------------------------------------------------
182
183/**
184 * Access permission settings for an NVM page.
185 *
186 * Fields hold `multi_bit_bool_t` values: `kMultiBitBool4True` enables the
187 * operation; `kMultiBitBool4False` disables it. Raw hardware register values
188 * are passed through without normalisation. Bitfields match the layout of
189 * `flash_ctrl_perms_t`/`rram_ctrl_perms_t` so the struct stays register-sized.
190 */
191typedef struct nvm_page_perms {
192 uint32_t _pad0 : 4;
193 uint32_t read : 4;
194 uint32_t write : 4;
195 uint32_t erase : 4;
196 uint32_t _pad1 : 16;
197} nvm_page_perms_t;
198OT_ASSERT_SIZE(nvm_page_perms_t, 4);
199
200/**
201 * Configuration settings for an NVM page.
202 *
203 * Fields hold `multi_bit_bool_t` values: `kMultiBitBool4True` enables the
204 * feature; `kMultiBitBool4False` disables it. Raw hardware register values
205 * are passed through without normalisation. Bitfields match the layout of
206 * `flash_ctrl_cfg_t`/`rram_ctrl_cfg_t` so the struct stays register-sized.
207 */
208typedef struct nvm_page_cfg {
209 uint32_t _pad0 : 16;
210 uint32_t scrambling : 4;
211 uint32_t ecc : 4;
212 uint32_t he : 4;
213 uint32_t _pad1 : 4;
214} nvm_page_cfg_t;
215OT_ASSERT_SIZE(nvm_page_cfg_t, 4);
216
217/** Read, write, and erase all enabled. */
218extern const nvm_page_perms_t kNvmPagePermsReadWrite;
219/** Read enabled; write and erase disabled. */
220extern const nvm_page_perms_t kNvmPagePermsReadOnly;
221/** All permissions disabled. */
222extern const nvm_page_perms_t kNvmPagePermsNone;
223/** Erase enabled; read and write disabled. */
224extern const nvm_page_perms_t kNvmPagePermsErase;
225
226/** Scrambling and ECC enabled; high-endurance disabled. */
227extern const nvm_page_cfg_t kNvmPageCfgScrambled;
228/** Scrambling disabled; ECC enabled; high-endurance disabled. */
229extern const nvm_page_cfg_t kNvmPageCfgPlain;
230/** Scrambling, ECC, and high-endurance all disabled. */
231extern const nvm_page_cfg_t kNvmPageCfgRaw;
232
233// ---------------------------------------------------------------------------
234// Info page identifiers
235// ---------------------------------------------------------------------------
236
237/**
238 * Named NVM info partition pages.
239 *
240 * Enum values are contiguous: bank 0 pages 0-9 map to values 0-9, bank 1
241 * pages 0-9 map to values 10-19. The mapping to physical hardware addresses
242 * is an internal detail of nvm_ctrl.c.
243 */
244typedef enum nvm_info_page {
245 // Bank 0
246 kNvmInfoPageFactoryId = 0,
247 kNvmInfoPageCreatorSecret = 1,
248 kNvmInfoPageOwnerSecret = 2,
249 kNvmInfoPageWaferAuthSecret = 3,
250 kNvmInfoPageAttestationKeySeeds = 4,
251 kNvmInfoPageOwnerReserved0 = 5,
252 kNvmInfoPageOwnerReserved1 = 6,
253 kNvmInfoPageOwnerReserved2 = 7,
254 kNvmInfoPageOwnerReserved3 = 8,
255 kNvmInfoPageFactoryCerts = 9,
256 // Bank 1
257 kNvmInfoPageBootData0 = 10,
258 kNvmInfoPageBootData1 = 11,
259 kNvmInfoPageOwnerSlot0 = 12,
260 kNvmInfoPageOwnerSlot1 = 13,
261 kNvmInfoPageCreatorReserved0 = 14,
262 kNvmInfoPageOwnerReserved4 = 15,
263 kNvmInfoPageOwnerReserved5 = 16,
264 kNvmInfoPageOwnerReserved6 = 17,
265 kNvmInfoPageOwnerReserved7 = 18,
266 kNvmInfoPageDiceCerts = 19,
267} nvm_info_page_t;
268
269/**
270 * Byte size of `DiceCerts`/`FactoryCerts`/`BootData0`/`BootData1`, the
271 * logical pages whose exact on-NVM capacity a caller needs.
272 */
273#if defined(USE_RRAM)
274enum {
275 kNvmInfoPageDiceCertsSize = kRramCtrlInfoPageDiceCertsSize,
276 kNvmInfoPageFactoryCertsSize = kRramCtrlInfoPageFactoryCertsSize,
277 kNvmInfoPageBootData0Size = kRramCtrlInfoPageBootData0Size,
278 kNvmInfoPageBootData1Size = kRramCtrlInfoPageBootData1Size,
279};
280
281/**
282 * Returns the physical RRAM info page descriptor for a logical page.
283 *
284 * The single source of truth for the logical-to-physical info page mapping
285 * (built from `RRAM_CTRL_INFO_PAGES_DEFINE` in rram_ctrl.h), exported so
286 * that `nvm_testutils.c` -- which talks to rram_ctrl via DIFs rather than
287 * this driver, for host-injected provisioning/test code -- can share it
288 * instead of maintaining a second, independently hand-written table that
289 * can silently drift out of sync (as happened with `FactoryCerts`,
290 * `OwnerSlot0`/`OwnerSlot1`, and `DiceCerts` growing to span multiple
291 * physical pages here without the other table being updated to match).
292 */
293const rram_ctrl_info_page_t *nvm_ctrl_rram_page_info(nvm_info_page_t page);
294#else
295enum {
296 kNvmInfoPageDiceCertsSize = NVM_BYTES_PER_PAGE,
297 kNvmInfoPageFactoryCertsSize = NVM_BYTES_PER_PAGE,
298 kNvmInfoPageBootData0Size = NVM_BYTES_PER_PAGE,
299 kNvmInfoPageBootData1Size = NVM_BYTES_PER_PAGE,
300};
301#endif // USE_RRAM
302
303// ---------------------------------------------------------------------------
304// SEC_MMIO write-increment constants
305// ---------------------------------------------------------------------------
306// Drop-in replacements for kFlashCtrlSecMmio* — identical numeric values.
307// Callers keep their SEC_MMIO_WRITE_INCREMENT() call sites; only the constant
308// name changes during migration.
309//
310// RRAM caveat: `kNvmCtrlSecMmioInfoPermsSet`, `kNvmCtrlSecMmioInfoCfgSet`,
311// `kNvmCtrlSecMmioInfoCfgLock`, `kNvmCtrlSecMmioCertInfoPageCreatorCfg`, and
312// `kNvmCtrlSecMmioCertInfoPageOwnerRestrict` are single constants shared by
313// call sites that each target a caller-chosen `nvm_info_page_t`. For RRAM,
314// `nvm_ctrl_info_perms_set`/`_cfg_set`/`_cfg_lock` are no-ops on an emulated
315// info page (see the TODO on `rram_ctrl_info_page_t`), so any call site
316// targeting an emulated page (e.g. OwnerSlot0/1, DiceCerts, OwnerReserved4-7)
317// performs fewer actual register writes than these constants assume. This is
318// a known, accepted gap for call sites whose target page varies at runtime:
319// making those fully correct would require auditing every call site
320// (ownership.c, owner_block.c, cert/dice_chain.c, manuf/ft_personalize.c,
321// rom_ext.c, ...) to conditionally increment based on the specific page
322// targeted. Call sites with a FIXED, statically-known page set don't have
323// this excuse and must account for emulated pages precisely:
324// `kNvmCtrlSecMmioCreatorInfoPagesLockdown` (fixed inside nvm_ctrl.c) does so
325// below, and `boot_data.c`'s three call sites (always BootData0/BootData1,
326// always emulated on RRAM) do so with their own `#if defined(USE_RRAM)` at
327// each `SEC_MMIO_WRITE_INCREMENT` rather than via this shared constant.
328enum {
329 kNvmCtrlSecMmioCertInfoPageCreatorCfg = 2,
330 kNvmCtrlSecMmioCertInfoPageOwnerRestrict = 2,
331 kNvmCtrlSecMmioCertInfoPagesOwnerRestrict = 5,
332#if defined(USE_RRAM)
333 // 2 writes for each of the 4 pages (of the 7 in kNvmPagesNoOwnerAccess)
334 // that are real (non-emulated) RRAM info pages: FactoryId, CreatorSecret,
335 // OwnerSecret, WaferAuthSecret. The other 3 (BootData0, BootData1,
336 // CreatorReserved0) are emulated and are skipped (see the TODO on
337 // `rram_ctrl_info_page_t`).
338 kNvmCtrlSecMmioCreatorInfoPagesLockdown = 8,
339#else
340 kNvmCtrlSecMmioCreatorInfoPagesLockdown = 14,
341#endif
342 kNvmCtrlSecMmioDataDefaultCfgSet = 1,
343 kNvmCtrlSecMmioDataDefaultPermsSet = 1,
344 kNvmCtrlSecMmioExecSet = 1,
345 kNvmCtrlSecMmioInfoCfgSet = 1,
346 kNvmCtrlSecMmioInfoCfgLock = 1,
347 kNvmCtrlSecMmioInfoPageLockdown = 2,
348 kNvmCtrlSecMmioInfoPermsSet = 1,
349 kNvmCtrlSecMmioBankErasePermsSet = 1,
350#if defined(USE_RRAM)
351 // 1 write from `rram_ctrl_data_default_cfg_set` (via `rram_ctrl_init`) plus
352 // 1 from the `rram_ctrl_data_default_perms_set` call in `nvm_ctrl_init`.
353 kNvmCtrlSecMmioInit = 2,
354#else
355 kNvmCtrlSecMmioInit = 3,
356#endif
357 // 2 writes: MP_REGION_${region} and MP_REGION_CFG_${region}.
358 kNvmCtrlSecMmioDataRegionProtect = 2,
359 kNvmCtrlSecMmioDataRegionProtectLock = 1,
360};
361
362// ---------------------------------------------------------------------------
363// Lifecycle
364// ---------------------------------------------------------------------------
365
366/**
367 * Kicks off initialization of the NVM controller.
368 *
369 * The caller is responsible for calling
370 * `SEC_MMIO_WRITE_INCREMENT(kNvmCtrlSecMmioInit)` when sec_mmio is used.
371 */
372void nvm_ctrl_init(void);
373
374/**
375 * Permanently disables the NVM controller.
376 */
377void nvm_ctrl_disable(void);
378
379// ---------------------------------------------------------------------------
380// Wire-format bridge (ownership layer only)
381// ---------------------------------------------------------------------------
382
383/**
384 * Translate a wire-format (bank, page) pair to a typed info page enum value.
385 *
386 * Intended for use only at the ownership-layer boundary, where page addresses
387 * are read from on-flash owner configuration structs that store raw bank and
388 * page integers. All NVM I/O then proceeds through the enum-based API.
389 *
390 * @param bank Bank index (must be < 2; this is a fixed wire-format constant,
391 * independent of the number of banks the underlying NVM
392 * technology actually has).
393 * @param page Page index within the info partition type 0 (must be < 10).
394 * @param[out] out Translated info page enum value.
395 * @return kErrorOk on success, kErrorNvmCtrlInvalidInfoPage if out of range.
396 */
398rom_error_t nvm_ctrl_info_page_lookup(uint8_t bank, uint8_t page,
399 nvm_info_page_t *out);
400
401// ---------------------------------------------------------------------------
402// Data partition I/O
403// ---------------------------------------------------------------------------
404
406rom_error_t nvm_ctrl_data_read(uint32_t addr, uint32_t word_count, void *data);
407
409rom_error_t nvm_ctrl_data_write(uint32_t addr, uint32_t word_count,
410 const void *data);
411
413rom_error_t nvm_ctrl_data_erase(uint32_t addr);
414
416rom_error_t nvm_ctrl_data_erase_verify(uint32_t addr);
417
418/**
419 * Erases all NVM data banks.
420 *
421 * Enables bank-erase permissions, erases every bank, then re-disables
422 * bank-erase permissions. Bank count and addresses are internal details.
423 */
425rom_error_t nvm_ctrl_chip_erase(void);
426
427/**
428 * Verifies that all NVM data banks have been erased.
429 */
431rom_error_t nvm_ctrl_chip_erase_verify(void);
432
433/**
434 * Programs up to 256 bytes of NVM data starting at `addr`, emulating SPI
435 * PAGE_PROGRAM wrapping semantics for the bootstrap protocol.
436 *
437 * This is not a generic NVM page write: the 256-byte unit here is the SPI
438 * NOR flash PAGE_PROGRAM wrap size, unrelated to `NVM_BYTES_PER_PAGE` (the
439 * erase granularity). If `byte_count` is not a multiple of the NVM word size
440 * it is rounded up to the next word boundary and padding bytes in `data` are
441 * set to 0xff. If `addr` is not 256-byte aligned the write is split so the
442 * first chunk fills up to the 256-byte boundary and the second starts at the
443 * aligned address. Write permissions are managed internally; the caller is
444 * responsible for address range validation.
445 *
446 * @param addr Start address; must be NVM-word aligned.
447 * @param byte_count Number of bytes to write.
448 * @param data Buffer; must be word aligned with room for up to one extra word
449 * of 0xff padding beyond `byte_count`.
450 */
452rom_error_t nvm_ctrl_bootstrap_page_program(uint32_t addr, size_t byte_count,
453 uint8_t *data);
454
455/**
456 * Erases the 4 KiB SPI flash sector containing `addr` in the data partition.
457 *
458 * A 4 KiB sector is not an NVM concept; it's the conventional SPI NOR flash
459 * erase granularity that this function emulates for the bootstrap protocol,
460 * which erases the underlying NVM one sector at a time. Because the NVM page
461 * size is 2 KiB, erasing a 4 KiB sector requires two consecutive page erases.
462 * `addr` is truncated to the nearest 4 KiB boundary before erasing; the
463 * caller is responsible for range validation. Erase permissions are managed
464 * internally.
465 */
467rom_error_t nvm_ctrl_bootstrap_sector_erase(uint32_t addr);
468
469// ---------------------------------------------------------------------------
470// Info page I/O
471// ---------------------------------------------------------------------------
472
474rom_error_t nvm_ctrl_info_read(nvm_info_page_t page, uint32_t offset,
475 uint32_t word_count, void *data);
476
477/**
478 * Read from an info page, returning all-zeros words on a read error.
479 */
481rom_error_t nvm_ctrl_info_read_zeros_on_read_error(nvm_info_page_t page,
482 uint32_t offset,
483 uint32_t word_count,
484 void *data);
485
487rom_error_t nvm_ctrl_info_write(nvm_info_page_t page, uint32_t offset,
488 uint32_t word_count, const void *data);
489
491rom_error_t nvm_ctrl_info_erase(nvm_info_page_t page);
492
493// ---------------------------------------------------------------------------
494// Permissions and configuration
495// ---------------------------------------------------------------------------
496
497/**
498 * Sets default access permissions for the data partition.
499 *
500 * The caller is responsible for calling
501 * `SEC_MMIO_WRITE_INCREMENT(kNvmCtrlSecMmioDataDefaultPermsSet)`.
502 */
503void nvm_ctrl_data_default_perms_set(nvm_page_perms_t perms);
504
505/**
506 * Sets access permissions for a named info page.
507 *
508 * The caller is responsible for calling
509 * `SEC_MMIO_WRITE_INCREMENT(kNvmCtrlSecMmioInfoPermsSet)`.
510 */
511void nvm_ctrl_info_perms_set(nvm_info_page_t page, nvm_page_perms_t perms);
512
513/**
514 * Sets default configuration for the data partition.
515 *
516 * The caller is responsible for calling
517 * `SEC_MMIO_WRITE_INCREMENT(kNvmCtrlSecMmioDataDefaultCfgSet)`.
518 */
519void nvm_ctrl_data_default_cfg_set(nvm_page_cfg_t cfg);
520
521/** Returns the current default configuration for the data partition. */
522nvm_page_cfg_t nvm_ctrl_data_default_cfg_get(void);
523
524/** Returns the boot-data info page configuration read from OTP. */
525nvm_page_cfg_t nvm_ctrl_boot_data_cfg_get(void);
526
527/**
528 * Sets configuration for a named info page.
529 *
530 * The caller is responsible for calling
531 * `SEC_MMIO_WRITE_INCREMENT(kNvmCtrlSecMmioInfoCfgSet)`.
532 */
533void nvm_ctrl_info_cfg_set(nvm_info_page_t page, nvm_page_cfg_t cfg);
534
535/**
536 * Write-locks configuration for a named info page.
537 *
538 * The caller is responsible for calling
539 * `SEC_MMIO_WRITE_INCREMENT(kNvmCtrlSecMmioInfoCfgLock)`.
540 */
541void nvm_ctrl_info_cfg_lock(nvm_info_page_t page);
542
543// ---------------------------------------------------------------------------
544// Data region protection
545// ---------------------------------------------------------------------------
546
547/**
548 * Configure memory protection for a data partition region.
549 *
550 * The caller is responsible for calling
551 * `SEC_MMIO_WRITE_INCREMENT(kNvmCtrlSecMmioDataRegionProtect)` (plus
552 * `kNvmCtrlSecMmioDataRegionProtectLock` when `lock` is true).
553 */
554void nvm_ctrl_data_region_protect(uint32_t region, uint32_t page_offset,
555 uint32_t num_pages, nvm_page_perms_t perms,
556 nvm_page_cfg_t cfg, hardened_bool_t lock);
557
558/**
559 * Set bank erase permissions for both NVM banks.
560 *
561 * The caller is responsible for calling
562 * `SEC_MMIO_WRITE_INCREMENT(kNvmCtrlSecMmioBankErasePermsSet)`.
563 */
564void nvm_ctrl_bank_erase_perms_set(hardened_bool_t enable);
565
566/**
567 * Enable or disable execution from NVM.
568 *
569 * The caller is responsible for calling
570 * `SEC_MMIO_WRITE_INCREMENT(kNvmCtrlSecMmioExecSet)`.
571 *
572 * @param exec_val `NVM_EXEC_EN` enables execution; all other values disable
573 * it.
574 */
575void nvm_ctrl_exec_set(uint32_t exec_val);
576
577// ---------------------------------------------------------------------------
578// Lockdown and certificate page management
579// ---------------------------------------------------------------------------
580
581/** Certificate page configuration: scrambling and ECC enabled. */
582extern const nvm_page_cfg_t kNvmCertInfoPageCfg;
583/** Creator access: read, write, and erase enabled. */
584extern const nvm_page_perms_t kNvmCertInfoPageCreatorAccess;
585/** Owner access: read enabled; write and erase disabled. */
586extern const nvm_page_perms_t kNvmCertInfoPageOwnerAccess;
587
588/**
589 * Disables all access to silicon creator info pages until next reset.
590 *
591 * Must be called in ROM_EXT before handing over execution to the first owner
592 * boot stage.
593 *
594 * The caller is responsible for calling
595 * `SEC_MMIO_WRITE_INCREMENT(kNvmCtrlSecMmioCreatorInfoPagesLockdown)`.
596 */
597void nvm_ctrl_creator_info_pages_lockdown(void);
598
599/**
600 * Configures a certificate info page for full creator access.
601 *
602 * The caller is responsible for calling
603 * `SEC_MMIO_WRITE_INCREMENT(kNvmCtrlSecMmioCertInfoPageCreatorCfg)`.
604 */
605void nvm_ctrl_cert_info_page_creator_cfg(nvm_info_page_t page);
606
607/**
608 * Restricts a certificate info page to read-only for the silicon owner.
609 *
610 * The caller is responsible for calling
611 * `SEC_MMIO_WRITE_INCREMENT(kNvmCtrlSecMmioCertInfoPageOwnerRestrict)`.
612 */
613void nvm_ctrl_cert_info_page_owner_restrict(nvm_info_page_t page);
614
615// clang-format off
616/**
617 * Bitfields for the `access` word of owner NVM region configs.
618 */
619#define OWNER_NVM_CONFIG_READ ((bitfield_field32_t) { .mask = 0xF, .index = 0 })
620#define OWNER_NVM_CONFIG_PROGRAM ((bitfield_field32_t) { .mask = 0xF, .index = 4 })
621#define OWNER_NVM_CONFIG_ERASE ((bitfield_field32_t) { .mask = 0xF, .index = 8 })
622#define OWNER_NVM_CONFIG_PROTECT_WHEN_PRIMARY ((bitfield_field32_t) { .mask = 0xF, .index = 24 })
623#define OWNER_NVM_CONFIG_LOCK ((bitfield_field32_t) { .mask = 0xF, .index = 28 })
624
625/**
626 * Bitfields for the `properties` word of owner NVM region configs.
627 */
628#define OWNER_NVM_CONFIG_SCRAMBLE ((bitfield_field32_t) { .mask = 0xF, .index = 0 })
629#define OWNER_NVM_CONFIG_ECC ((bitfield_field32_t) { .mask = 0xF, .index = 4 })
630#define OWNER_NVM_CONFIG_HIGH_ENDURANCE ((bitfield_field32_t) { .mask = 0xF, .index = 8 })
631// clang-format on
632
633#ifdef __cplusplus
634}
635#endif
636
637#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_NVM_CTRL_H_