Skip to content

Commit 64cdd50

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 b690bdd commit 64cdd50

File tree

3 files changed

+234
-10
lines changed

3 files changed

+234
-10
lines changed

soc/nordic/common/uicr/gen_uicr.py

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,93 @@ 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_idx, first_addr, first_size, 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 secure storage address {secure_storage_address}"
253+
)
254+
255+
# Check that all present partitions have sizes that are multiples of 1KB
256+
for i, addr, size, name in present_partitions:
257+
if size % 1024 != 0:
258+
raise ScriptError(
259+
f"Partition {name} has size {size} bytes, but must be a multiple of 1024 bytes (1KB)"
260+
)
261+
262+
# Check that partitions are in correct order and don't overlap
263+
for i in range(len(present_partitions) - 1):
264+
curr_idx, curr_addr, curr_size, curr_name = present_partitions[i]
265+
next_idx, next_addr, next_size, next_name = present_partitions[i + 1]
266+
267+
# Check order - partitions should be in ascending address order
268+
if curr_addr >= next_addr:
269+
raise ScriptError(
270+
f"Partition {curr_name} (starts at {curr_addr}) must come before {next_name} (starts at {next_addr})"
271+
)
272+
273+
# Check for overlap
274+
curr_end = curr_addr + curr_size
275+
if curr_end > next_addr:
276+
raise ScriptError(
277+
f"Partition {curr_name} (ends at {curr_end}) overlaps with {next_name} (starts at {next_addr})"
278+
)
279+
280+
# Check for gaps (should be no gaps between consecutive partitions)
281+
if curr_end < next_addr:
282+
gap = next_addr - curr_end
283+
raise ScriptError(
284+
f"Gap of {gap} bytes between {curr_name} (ends at {curr_end}) and {next_name} (starts at {next_addr})"
285+
)
286+
287+
201288
def main() -> None:
202289
parser = argparse.ArgumentParser(
203290
allow_abbrev=False,
@@ -255,6 +342,65 @@ def main() -> None:
255342
type=lambda s: int(s, 0),
256343
help="Absolute flash address of the UICR region (decimal or 0x-prefixed hex)",
257344
)
345+
parser.add_argument(
346+
"--securestorage",
347+
action="store_true",
348+
help="Enable secure storage support in UICR",
349+
)
350+
parser.add_argument(
351+
"--securestorage-address",
352+
default=None,
353+
type=lambda s: int(s, 0),
354+
help="Absolute flash address of the secure storage partition (decimal or 0x-prefixed hex)",
355+
)
356+
parser.add_argument(
357+
"--cpuapp-crypto-address",
358+
default=0,
359+
type=lambda s: int(s, 0),
360+
help="Absolute flash address of cpuapp_crypto_partition (decimal or 0x-prefixed hex)",
361+
)
362+
parser.add_argument(
363+
"--cpuapp-crypto-size",
364+
default=0,
365+
type=lambda s: int(s, 0),
366+
help="Size in bytes of cpuapp_crypto_partition (decimal or 0x-prefixed hex)",
367+
)
368+
parser.add_argument(
369+
"--cpurad-crypto-address",
370+
default=0,
371+
type=lambda s: int(s, 0),
372+
help="Absolute flash address of cpurad_crypto_partition (decimal or 0x-prefixed hex)",
373+
)
374+
parser.add_argument(
375+
"--cpurad-crypto-size",
376+
default=0,
377+
type=lambda s: int(s, 0),
378+
help="Size in bytes of cpurad_crypto_partition (decimal or 0x-prefixed hex)",
379+
)
380+
parser.add_argument(
381+
"--cpuapp-its-address",
382+
default=0,
383+
type=lambda s: int(s, 0),
384+
help="Absolute flash address of cpuapp_its_partition (decimal or 0x-prefixed hex)",
385+
)
386+
parser.add_argument(
387+
"--cpuapp-its-size",
388+
default=0,
389+
type=lambda s: int(s, 0),
390+
help="Size in bytes of cpuapp_its_partition (decimal or 0x-prefixed hex)",
391+
)
392+
parser.add_argument(
393+
"--cpurad-its-address",
394+
default=0,
395+
type=lambda s: int(s, 0),
396+
help="Absolute flash address of cpurad_its_partition (decimal or 0x-prefixed hex)",
397+
)
398+
parser.add_argument(
399+
"--cpurad-its-size",
400+
default=0,
401+
type=lambda s: int(s, 0),
402+
help="Size in bytes of cpurad_its_partition (decimal or 0x-prefixed hex)",
403+
)
258404
parser.add_argument(
259405
"--secondary",
260406
action="store_true",
@@ -327,12 +473,43 @@ def main() -> None:
327473
"--out-secondary-periphconf-hex is used"
328474
)
329475

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

333499
uicr.VERSION.MAJOR = UICR_FORMAT_VERSION_MAJOR
334500
uicr.VERSION.MINOR = UICR_FORMAT_VERSION_MINOR
335501

502+
# Handle secure storage configuration
503+
if args.securestorage:
504+
uicr.SECURESTORAGE.ENABLE = ENABLED_VALUE
505+
uicr.SECURESTORAGE.ADDRESS = args.securestorage_address
506+
507+
# Set partition sizes in 1KB units
508+
uicr.SECURESTORAGE.CRYPTO.APPLICATIONSIZE1KB = args.cpuapp_crypto_size // 1024
509+
uicr.SECURESTORAGE.CRYPTO.RADIOCORESIZE1KB = args.cpurad_crypto_size // 1024
510+
uicr.SECURESTORAGE.ITS.APPLICATIONSIZE1KB = args.cpuapp_its_size // 1024
511+
uicr.SECURESTORAGE.ITS.RADIOCORESIZE1KB = args.cpurad_its_size // 1024
512+
336513
# Process periphconf data first and configure UICR completely before creating hex objects
337514
periphconf_hex = IntelHex()
338515
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: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ 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+
help
27+
When enabled, the UICR generator will configure the
28+
secure storage region based on device tree partitions.
29+
30+
The following device tree partitions are used in order:
31+
- cpuapp_crypto_partition: Application processor crypto storage
32+
- cpurad_crypto_partition: Radio core crypto storage
33+
- cpuapp_its_partition: Application processor internal trusted storage
34+
- cpurad_its_partition: Radio core internal trusted storage
35+
36+
All partitions must be multiples of 1KB and laid out contiguously
37+
without gaps. Missing partitions are handled gracefully with zero size.
38+
2439
endmenu
2540

2641
source "Kconfig.zephyr"

0 commit comments

Comments
 (0)