@@ -42,7 +42,7 @@ usage(int status) {
4242 " dlm-auth <state> <key> Authenticated DLM transition (ssd/nsecsd/rma_req)\n"
4343 " Key format: file:<path> or hex:<32_hex_chars>\n"
4444 " boundary Show secure/non-secure boundary settings\n"
45- " boundary-set Set TrustZone boundaries (requires --cfs1/--cfs2/--dfs/--srs1/--srs2 )\n"
45+ " boundary-set Set TrustZone boundaries (--file <rpd> or explicit options )\n"
4646 " param Show device parameter (initialization command)\n"
4747 " param-set <enable|disable> Enable/disable initialization command\n"
4848 " init Initialize device (factory reset to SSD state)\n"
@@ -71,6 +71,7 @@ usage(int status) {
7171 " --dfs <KB> Data flash secure region size\n"
7272 " --srs1 <KB> SRAM secure region size without NSC\n"
7373 " --srs2 <KB> SRAM secure region size (total)\n"
74+ " --file <rpd> Load boundary settings from .rpd file\n"
7475 " -h, --help Show this help message\n"
7576 " -V, --version Show version\n"
7677 "\n"
@@ -287,6 +288,82 @@ parse_auth_key(const char *str, uint8_t *key) {
287288 }
288289}
289290
291+ /*
292+ * Parse .rpd (Renesas Partition Data) file for TrustZone boundary settings
293+ * Format: key=value lines where values are hex (with 0x prefix) in bytes
294+ * Keys: FLASH_S_SIZE, FLASH_C_SIZE, RAM_S_SIZE, RAM_C_SIZE, DATA_FLASH_S_SIZE
295+ * Converts bytes to KB for boundary settings
296+ * Returns: 0 on success, -1 on error
297+ */
298+ static int
299+ parse_rpd_file (const char * filename , ra_boundary_t * bnd ) {
300+ FILE * f = fopen (filename , "r" );
301+ if (!f ) {
302+ warn ("failed to open boundary file: %s" , filename );
303+ return -1 ;
304+ }
305+
306+ char line [256 ];
307+ bool found_cfs1 = false, found_cfs2 = false, found_dfs = false;
308+ bool found_srs1 = false, found_srs2 = false;
309+
310+ while (fgets (line , sizeof (line ), f )) {
311+ char * eq = strchr (line , '=' );
312+ if (!eq )
313+ continue ;
314+
315+ * eq = '\0' ;
316+ const char * key = line ;
317+ const char * val = eq + 1 ;
318+
319+ /* Skip 0x prefix if present */
320+ if (val [0 ] == '0' && (val [1 ] == 'x' || val [1 ] == 'X' ))
321+ val += 2 ;
322+
323+ char * endptr ;
324+ unsigned long bytes = strtoul (val , & endptr , 16 );
325+
326+ /* Convert bytes to KB */
327+ uint16_t kb = (uint16_t )(bytes / 1024 );
328+
329+ if (strcmp (key , "FLASH_S_SIZE" ) == 0 ) {
330+ bnd -> cfs1 = kb ;
331+ found_cfs1 = true;
332+ } else if (strcmp (key , "FLASH_C_SIZE" ) == 0 ) {
333+ bnd -> cfs2 = kb ;
334+ found_cfs2 = true;
335+ } else if (strcmp (key , "RAM_S_SIZE" ) == 0 ) {
336+ bnd -> srs1 = kb ;
337+ found_srs1 = true;
338+ } else if (strcmp (key , "RAM_C_SIZE" ) == 0 ) {
339+ bnd -> srs2 = kb ;
340+ found_srs2 = true;
341+ } else if (strcmp (key , "DATA_FLASH_S_SIZE" ) == 0 ) {
342+ bnd -> dfs = kb ;
343+ found_dfs = true;
344+ }
345+ }
346+
347+ fclose (f );
348+
349+ if (!found_cfs1 || !found_cfs2 || !found_dfs || !found_srs1 || !found_srs2 ) {
350+ warnx ("incomplete .rpd file: missing required fields" );
351+ if (!found_cfs1 )
352+ warnx (" missing FLASH_S_SIZE (CFS1)" );
353+ if (!found_cfs2 )
354+ warnx (" missing FLASH_C_SIZE (CFS2)" );
355+ if (!found_dfs )
356+ warnx (" missing DATA_FLASH_S_SIZE (DFS)" );
357+ if (!found_srs1 )
358+ warnx (" missing RAM_S_SIZE (SRS1)" );
359+ if (!found_srs2 )
360+ warnx (" missing RAM_C_SIZE (SRS2)" );
361+ return -1 ;
362+ }
363+
364+ return 0 ;
365+ }
366+
290367/*
291368 * Parse key type from string: accepts numeric (1,2,3) or keywords
292369 * Keywords: secdbg, nonsecdbg, rma (case-insensitive)
@@ -318,28 +395,30 @@ parse_key_type(const char *str) {
318395#define OPT_SRS1 259
319396#define OPT_SRS2 260
320397#define OPT_AREA 261
398+ #define OPT_BOUNDARY_FILE 262
321399
322400static const struct option longopts [] = {
323- { "port" , required_argument , NULL , 'p' },
324- { "address" , required_argument , NULL , 'a' },
325- { "size" , required_argument , NULL , 's' },
326- { "baudrate" , required_argument , NULL , 'b' },
327- { "id" , required_argument , NULL , 'i' },
328- { "erase-all" , no_argument , NULL , 'e' },
329- { "verify" , no_argument , NULL , 'v' },
330- { "input-format" , required_argument , NULL , 'f' },
331- { "output-format" , required_argument , NULL , 'F' },
332- { "uart" , no_argument , NULL , 'u' },
333- { "quiet" , no_argument , NULL , 'q' },
334- { "cfs1" , required_argument , NULL , OPT_CFS1 },
335- { "cfs2" , required_argument , NULL , OPT_CFS2 },
336- { "dfs" , required_argument , NULL , OPT_DFS },
337- { "srs1" , required_argument , NULL , OPT_SRS1 },
338- { "srs2" , required_argument , NULL , OPT_SRS2 },
339- { "area" , required_argument , NULL , OPT_AREA },
340- { "help" , no_argument , NULL , 'h' },
341- { "version" , no_argument , NULL , 'V' },
342- { NULL , 0 , NULL , 0 }
401+ { "port" , required_argument , NULL , 'p' },
402+ { "address" , required_argument , NULL , 'a' },
403+ { "size" , required_argument , NULL , 's' },
404+ { "baudrate" , required_argument , NULL , 'b' },
405+ { "id" , required_argument , NULL , 'i' },
406+ { "erase-all" , no_argument , NULL , 'e' },
407+ { "verify" , no_argument , NULL , 'v' },
408+ { "input-format" , required_argument , NULL , 'f' },
409+ { "output-format" , required_argument , NULL , 'F' },
410+ { "uart" , no_argument , NULL , 'u' },
411+ { "quiet" , no_argument , NULL , 'q' },
412+ { "cfs1" , required_argument , NULL , OPT_CFS1 },
413+ { "cfs2" , required_argument , NULL , OPT_CFS2 },
414+ { "dfs" , required_argument , NULL , OPT_DFS },
415+ { "srs1" , required_argument , NULL , OPT_SRS1 },
416+ { "srs2" , required_argument , NULL , OPT_SRS2 },
417+ { "area" , required_argument , NULL , OPT_AREA },
418+ { "file" , required_argument , NULL , OPT_BOUNDARY_FILE },
419+ { "help" , no_argument , NULL , 'h' },
420+ { "version" , no_argument , NULL , 'V' },
421+ { NULL , 0 , NULL , 0 }
343422};
344423
345424int
@@ -365,6 +444,7 @@ main(int argc, char *argv[]) {
365444 ra_boundary_t bnd = { 0 };
366445 bool bnd_cfs1_set = false, bnd_cfs2_set = false, bnd_dfs_set = false;
367446 bool bnd_srs1_set = false, bnd_srs2_set = false;
447+ const char * boundary_file = NULL ;
368448 int8_t area_koa = -1 ; /* -1 = not set, 0/1/2 = code/data/config */
369449 write_entry_t write_entries [MAX_WRITE_FILES ];
370450 int write_count = 0 ;
@@ -459,6 +539,9 @@ main(int argc, char *argv[]) {
459539 area_koa = (int8_t )val ;
460540 }
461541 break ;
542+ case OPT_BOUNDARY_FILE :
543+ boundary_file = optarg ;
544+ break ;
462545 case 'h' :
463546 usage (EXIT_SUCCESS );
464547 break ;
@@ -566,8 +649,23 @@ main(int argc, char *argv[]) {
566649 cmd = CMD_BOUNDARY ;
567650 } else if (strcmp (command , "boundary-set" ) == 0 ) {
568651 cmd = CMD_BOUNDARY_SET ;
569- if (!bnd_cfs1_set || !bnd_cfs2_set || !bnd_dfs_set || !bnd_srs1_set || !bnd_srs2_set )
570- errx (EXIT_FAILURE , "boundary-set requires all options: --cfs1 --cfs2 --dfs --srs1 --srs2" );
652+ if (boundary_file ) {
653+ /* Parse .rpd file */
654+ if (parse_rpd_file (boundary_file , & bnd ) < 0 )
655+ exit (EXIT_FAILURE );
656+ printf ("Loaded boundary settings from %s:\n"
657+ " CFS1: %u KB, CFS2: %u KB, DFS: %u KB\n"
658+ " SRS1: %u KB, SRS2: %u KB\n" ,
659+ boundary_file ,
660+ bnd .cfs1 ,
661+ bnd .cfs2 ,
662+ bnd .dfs ,
663+ bnd .srs1 ,
664+ bnd .srs2 );
665+ } else if (!bnd_cfs1_set || !bnd_cfs2_set || !bnd_dfs_set || !bnd_srs1_set || !bnd_srs2_set ) {
666+ errx (EXIT_FAILURE ,
667+ "boundary-set requires --file <rpd> or all options: --cfs1 --cfs2 --dfs --srs1 --srs2" );
668+ }
571669 } else if (strcmp (command , "param" ) == 0 ) {
572670 cmd = CMD_PARAM ;
573671 } else if (strcmp (command , "param-set" ) == 0 ) {
0 commit comments