@@ -198,6 +198,93 @@ class Uicr(c.LittleEndianStructure):
198
198
]
199
199
200
200
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
+
201
288
def main () -> None :
202
289
parser = argparse .ArgumentParser (
203
290
allow_abbrev = False ,
@@ -255,6 +342,65 @@ def main() -> None:
255
342
type = lambda s : int (s , 0 ),
256
343
help = "Absolute flash address of the UICR region (decimal or 0x-prefixed hex)" ,
257
344
)
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
+ )
258
404
parser .add_argument (
259
405
"--secondary" ,
260
406
action = "store_true" ,
@@ -327,12 +473,43 @@ def main() -> None:
327
473
"--out-secondary-periphconf-hex is used"
328
474
)
329
475
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
+
330
496
init_values = DISABLED_VALUE .to_bytes (4 , "little" ) * (c .sizeof (Uicr ) // 4 )
331
497
uicr = Uicr .from_buffer_copy (init_values )
332
498
333
499
uicr .VERSION .MAJOR = UICR_FORMAT_VERSION_MAJOR
334
500
uicr .VERSION .MINOR = UICR_FORMAT_VERSION_MINOR
335
501
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
+
336
513
# Process periphconf data first and configure UICR completely before creating hex objects
337
514
periphconf_hex = IntelHex ()
338
515
secondary_periphconf_hex = IntelHex ()
0 commit comments