Skip to content

Commit 1908a06

Browse files
committed
soc: nordic: uicr: Add support for SECURESTORAGE
Add UICR.SECURESTORAGE configuration based on device tree partitions. Validates partition layout and populates size fields in 1KB units. Handles missing partitions gracefully. Signed-off-by: Sebastian Bøe <[email protected]>
1 parent f23b12d commit 1908a06

File tree

4 files changed

+242
-10
lines changed

4 files changed

+242
-10
lines changed

scripts/ci/check_compliance.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,7 @@ def check_no_undef_outside_kconfig(self, kconf):
12661266
"GEN_UICR_GENERATE_PERIPHCONF", # Used in specialized build tool, not part of main Kconfig
12671267
"GEN_UICR_SECONDARY", # Used in specialized build tool, not part of main Kconfig
12681268
"GEN_UICR_SECONDARY_GENERATE_PERIPHCONF", # Used in specialized build tool, not part of main Kconfig
1269+
"GEN_UICR_SECURESTORAGE", # Used in specialized build tool, not part of main Kconfig
12691270
"HEAP_MEM_POOL_ADD_SIZE_", # Used as an option matching prefix
12701271
"HUGETLBFS", # Linux, in boards/xtensa/intel_adsp_cavs25/doc
12711272
"IAR_BUFFERED_WRITE",

soc/nordic/common/uicr/gen_uicr.py

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,98 @@ class Uicr(c.LittleEndianStructure):
198198
]
199199

200200

201+
def validate_secure_storage_partitions(
202+
secure_storage_address: int,
203+
cpuapp_crypto_address: int,
204+
cpuapp_crypto_size: int,
205+
cpurad_crypto_address: int,
206+
cpurad_crypto_size: int,
207+
cpuapp_its_address: int,
208+
cpuapp_its_size: int,
209+
cpurad_its_address: int,
210+
cpurad_its_size: int,
211+
) -> None:
212+
"""
213+
Validate that secure storage partitions are laid out correctly.
214+
215+
Args:
216+
secure_storage_address: Absolute address of secure storage partition
217+
cpuapp_crypto_address: Absolute address of cpuapp_crypto_partition
218+
cpuapp_crypto_size: Size of cpuapp_crypto_partition
219+
cpurad_crypto_address: Absolute address of cpurad_crypto_partition
220+
cpurad_crypto_size: Size of cpurad_crypto_partition
221+
cpuapp_its_address: Absolute address of cpuapp_its_partition
222+
cpuapp_its_size: Size of cpuapp_its_partition
223+
cpurad_its_address: Absolute address of cpurad_its_partition
224+
cpurad_its_size: Size of cpurad_its_partition
225+
226+
Raises:
227+
ScriptError: If validation fails
228+
"""
229+
# Expected order: cpuapp_crypto_partition, cpurad_crypto_partition,
230+
# cpuapp_its_partition, cpurad_its_partition
231+
partitions = [
232+
(cpuapp_crypto_address, cpuapp_crypto_size, "cpuapp_crypto_partition"),
233+
(cpurad_crypto_address, cpurad_crypto_size, "cpurad_crypto_partition"),
234+
(cpuapp_its_address, cpuapp_its_size, "cpuapp_its_partition"),
235+
(cpurad_its_address, cpurad_its_size, "cpurad_its_partition"),
236+
]
237+
238+
# Filter out zero-sized partitions (missing partitions)
239+
present_partitions = []
240+
for i, (addr, size, name) in enumerate(partitions):
241+
if size > 0:
242+
present_partitions.append((i, addr, size, name))
243+
244+
if not present_partitions:
245+
# No partitions present - this is valid
246+
return
247+
248+
# Check that the first present partition starts at the secure storage address
249+
_, first_addr, _, first_name = present_partitions[0]
250+
if first_addr != secure_storage_address:
251+
raise ScriptError(
252+
f"First partition {first_name} starts at {first_addr}, but must start at "
253+
f"secure storage address {secure_storage_address}"
254+
)
255+
256+
# Check that all present partitions have sizes that are multiples of 1KB
257+
for _, _, size, name in present_partitions:
258+
if size % 1024 != 0:
259+
raise ScriptError(
260+
f"Partition {name} has size {size} bytes, but must be a multiple of "
261+
f"1024 bytes (1KB)"
262+
)
263+
264+
# Check that partitions are in correct order and don't overlap
265+
for i in range(len(present_partitions) - 1):
266+
_, curr_addr, curr_size, curr_name = present_partitions[i]
267+
_, next_addr, _________, next_name = present_partitions[i + 1]
268+
269+
# Check order - partitions should be in ascending address order
270+
if curr_addr >= next_addr:
271+
raise ScriptError(
272+
f"Partition {curr_name} (starts at {curr_addr}) must come before "
273+
f"{next_name} (starts at {next_addr})"
274+
)
275+
276+
# Check for overlap
277+
curr_end = curr_addr + curr_size
278+
if curr_end > next_addr:
279+
raise ScriptError(
280+
f"Partition {curr_name} (ends at {curr_end}) overlaps with "
281+
f"{next_name} (starts at {next_addr})"
282+
)
283+
284+
# Check for gaps (should be no gaps between consecutive partitions)
285+
if curr_end < next_addr:
286+
gap = next_addr - curr_end
287+
raise ScriptError(
288+
f"Gap of {gap} bytes between {curr_name} (ends at {curr_end}) and "
289+
f"{next_name} (starts at {next_addr})"
290+
)
291+
292+
201293
def main() -> None:
202294
parser = argparse.ArgumentParser(
203295
allow_abbrev=False,
@@ -255,6 +347,65 @@ def main() -> None:
255347
type=lambda s: int(s, 0),
256348
help="Absolute flash address of the UICR region (decimal or 0x-prefixed hex)",
257349
)
350+
parser.add_argument(
351+
"--securestorage",
352+
action="store_true",
353+
help="Enable secure storage support in UICR",
354+
)
355+
parser.add_argument(
356+
"--securestorage-address",
357+
default=None,
358+
type=lambda s: int(s, 0),
359+
help="Absolute flash address of the secure storage partition (decimal or 0x-prefixed hex)",
360+
)
361+
parser.add_argument(
362+
"--cpuapp-crypto-address",
363+
default=0,
364+
type=lambda s: int(s, 0),
365+
help="Absolute flash address of cpuapp_crypto_partition (decimal or 0x-prefixed hex)",
366+
)
367+
parser.add_argument(
368+
"--cpuapp-crypto-size",
369+
default=0,
370+
type=lambda s: int(s, 0),
371+
help="Size in bytes of cpuapp_crypto_partition (decimal or 0x-prefixed hex)",
372+
)
373+
parser.add_argument(
374+
"--cpurad-crypto-address",
375+
default=0,
376+
type=lambda s: int(s, 0),
377+
help="Absolute flash address of cpurad_crypto_partition (decimal or 0x-prefixed hex)",
378+
)
379+
parser.add_argument(
380+
"--cpurad-crypto-size",
381+
default=0,
382+
type=lambda s: int(s, 0),
383+
help="Size in bytes of cpurad_crypto_partition (decimal or 0x-prefixed hex)",
384+
)
385+
parser.add_argument(
386+
"--cpuapp-its-address",
387+
default=0,
388+
type=lambda s: int(s, 0),
389+
help="Absolute flash address of cpuapp_its_partition (decimal or 0x-prefixed hex)",
390+
)
391+
parser.add_argument(
392+
"--cpuapp-its-size",
393+
default=0,
394+
type=lambda s: int(s, 0),
395+
help="Size in bytes of cpuapp_its_partition (decimal or 0x-prefixed hex)",
396+
)
397+
parser.add_argument(
398+
"--cpurad-its-address",
399+
default=0,
400+
type=lambda s: int(s, 0),
401+
help="Absolute flash address of cpurad_its_partition (decimal or 0x-prefixed hex)",
402+
)
403+
parser.add_argument(
404+
"--cpurad-its-size",
405+
default=0,
406+
type=lambda s: int(s, 0),
407+
help="Size in bytes of cpurad_its_partition (decimal or 0x-prefixed hex)",
408+
)
258409
parser.add_argument(
259410
"--secondary",
260411
action="store_true",
@@ -327,12 +478,43 @@ def main() -> None:
327478
"--out-secondary-periphconf-hex is used"
328479
)
329480

481+
# Validate secure storage argument dependencies
482+
if args.securestorage:
483+
if args.securestorage_address is None:
484+
raise ScriptError(
485+
"--securestorage-address is required when --securestorage is used"
486+
)
487+
488+
# Validate partition layout
489+
validate_secure_storage_partitions(
490+
args.securestorage_address,
491+
args.cpuapp_crypto_address,
492+
args.cpuapp_crypto_size,
493+
args.cpurad_crypto_address,
494+
args.cpurad_crypto_size,
495+
args.cpuapp_its_address,
496+
args.cpuapp_its_size,
497+
args.cpurad_its_address,
498+
args.cpurad_its_size,
499+
)
500+
330501
init_values = DISABLED_VALUE.to_bytes(4, "little") * (c.sizeof(Uicr) // 4)
331502
uicr = Uicr.from_buffer_copy(init_values)
332503

333504
uicr.VERSION.MAJOR = UICR_FORMAT_VERSION_MAJOR
334505
uicr.VERSION.MINOR = UICR_FORMAT_VERSION_MINOR
335506

507+
# Handle secure storage configuration
508+
if args.securestorage:
509+
uicr.SECURESTORAGE.ENABLE = ENABLED_VALUE
510+
uicr.SECURESTORAGE.ADDRESS = args.securestorage_address
511+
512+
# Set partition sizes in 1KB units
513+
uicr.SECURESTORAGE.CRYPTO.APPLICATIONSIZE1KB = args.cpuapp_crypto_size // 1024
514+
uicr.SECURESTORAGE.CRYPTO.RADIOCORESIZE1KB = args.cpurad_crypto_size // 1024
515+
uicr.SECURESTORAGE.ITS.APPLICATIONSIZE1KB = args.cpuapp_its_size // 1024
516+
uicr.SECURESTORAGE.ITS.RADIOCORESIZE1KB = args.cpurad_its_size // 1024
517+
336518
# Process periphconf data first and configure UICR completely before creating hex objects
337519
periphconf_hex = IntelHex()
338520
secondary_periphconf_hex = IntelHex()

soc/nordic/common/uicr/gen_uicr/CMakeLists.txt

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,22 @@ endfunction()
3232

3333
# Function to compute partition absolute address and size from devicetree
3434
function(compute_partition_address_and_size partition_nodelabel output_address_var output_size_var)
35-
dt_nodelabel(partition_path NODELABEL ${partition_nodelabel} REQUIRED)
36-
dt_reg_addr(partition_offset PATH ${partition_path} REQUIRED)
37-
dt_reg_size(partition_size PATH ${partition_path} REQUIRED)
38-
39-
# Calculate absolute partition address
40-
math(EXPR partition_address "${CONFIG_FLASH_BASE_ADDRESS} + ${partition_offset}" OUTPUT_FORMAT HEXADECIMAL)
41-
42-
# Set output variables in parent scope
43-
set(${output_address_var} ${partition_address} PARENT_SCOPE)
44-
set(${output_size_var} ${partition_size} PARENT_SCOPE)
35+
dt_nodelabel(partition_path NODELABEL ${partition_nodelabel} QUIET)
36+
if(partition_path)
37+
dt_reg_addr(partition_offset PATH ${partition_path} REQUIRED)
38+
dt_reg_size(partition_size PATH ${partition_path} REQUIRED)
39+
40+
# Calculate absolute partition address
41+
math(EXPR partition_address "${CONFIG_FLASH_BASE_ADDRESS} + ${partition_offset}" OUTPUT_FORMAT HEXADECIMAL)
42+
43+
# Set output variables in parent scope
44+
set(${output_address_var} ${partition_address} PARENT_SCOPE)
45+
set(${output_size_var} ${partition_size} PARENT_SCOPE)
46+
else()
47+
# Partition not found - set to zero
48+
set(${output_address_var} 0 PARENT_SCOPE)
49+
set(${output_size_var} 0 PARENT_SCOPE)
50+
endif()
4551
endfunction()
4652

4753
# Use CMAKE_VERBOSE_MAKEFILE to silence an unused-variable warning.
@@ -60,6 +66,31 @@ set(secondary_periphconf_hex_file ${APPLICATION_BINARY_DIR}/zephyr/secondary_per
6066
dt_nodelabel(uicr_path NODELABEL "uicr" REQUIRED)
6167
dt_reg_addr(UICR_ADDRESS PATH ${uicr_path} REQUIRED)
6268

69+
# Handle secure storage configuration
70+
set(securestorage_args)
71+
if(CONFIG_GEN_UICR_SECURESTORAGE)
72+
list(APPEND securestorage_args --securestorage)
73+
74+
# Extract secure storage partition information
75+
compute_partition_address_and_size("secure_storage_partition" SECURE_STORAGE_ADDRESS SECURE_STORAGE_SIZE)
76+
list(APPEND securestorage_args --securestorage-address ${SECURE_STORAGE_ADDRESS})
77+
78+
# Extract individual partition information for validation
79+
compute_partition_address_and_size("cpuapp_crypto_partition" CPUAPP_CRYPTO_ADDRESS CPUAPP_CRYPTO_SIZE)
80+
compute_partition_address_and_size("cpurad_crypto_partition" CPURAD_CRYPTO_ADDRESS CPURAD_CRYPTO_SIZE)
81+
compute_partition_address_and_size("cpuapp_its_partition" CPUAPP_ITS_ADDRESS CPUAPP_ITS_SIZE)
82+
compute_partition_address_and_size("cpurad_its_partition" CPURAD_ITS_ADDRESS CPURAD_ITS_SIZE)
83+
84+
list(APPEND securestorage_args --cpuapp-crypto-address ${CPUAPP_CRYPTO_ADDRESS})
85+
list(APPEND securestorage_args --cpuapp-crypto-size ${CPUAPP_CRYPTO_SIZE})
86+
list(APPEND securestorage_args --cpurad-crypto-address ${CPURAD_CRYPTO_ADDRESS})
87+
list(APPEND securestorage_args --cpurad-crypto-size ${CPURAD_CRYPTO_SIZE})
88+
list(APPEND securestorage_args --cpuapp-its-address ${CPUAPP_ITS_ADDRESS})
89+
list(APPEND securestorage_args --cpuapp-its-size ${CPUAPP_ITS_SIZE})
90+
list(APPEND securestorage_args --cpurad-its-address ${CPURAD_ITS_ADDRESS})
91+
list(APPEND securestorage_args --cpurad-its-size ${CPURAD_ITS_SIZE})
92+
endif(CONFIG_GEN_UICR_SECURESTORAGE)
93+
6394
if(CONFIG_GEN_UICR_GENERATE_PERIPHCONF)
6495
# gen_uicr.py parses all zephyr.elf files. To find these files (which
6596
# have not been built yet) we scan sibling build directories for
@@ -134,6 +165,7 @@ add_custom_command(
134165
--out-merged-hex ${merged_hex_file}
135166
--out-uicr-hex ${uicr_hex_file}
136167
${periphconf_args}
168+
${securestorage_args}
137169
${secondary_args}
138170
DEPENDS ${periphconf_elfs} ${secondary_periphconf_elfs}
139171
WORKING_DIRECTORY ${APPLICATION_BINARY_DIR}

soc/nordic/common/uicr/gen_uicr/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,23 @@ config GEN_UICR_SECONDARY_GENERATE_PERIPHCONF
2121
When enabled, the UICR generator will populate the
2222
secondary_periphconf_partition partition.
2323

24+
config GEN_UICR_SECURESTORAGE
25+
bool "Enable UICR.SECURESTORAGE"
26+
default y
27+
depends on $(dt_nodelabel_enabled,secure_storage_partition)
28+
help
29+
When enabled, the UICR generator will configure the
30+
secure storage region based on device tree partitions.
31+
32+
The following device tree partitions are used in order:
33+
- cpuapp_crypto_partition: Application processor crypto storage
34+
- cpurad_crypto_partition: Radio core crypto storage
35+
- cpuapp_its_partition: Application processor internal trusted storage
36+
- cpurad_its_partition: Radio core internal trusted storage
37+
38+
All partitions must be multiples of 1KB and laid out contiguously
39+
without gaps. Missing partitions are handled gracefully with zero size.
40+
2441
endmenu
2542

2643
source "Kconfig.zephyr"

0 commit comments

Comments
 (0)