@@ -82,6 +82,7 @@ static __forceinline int __builtin_ctz(unsigned x) {
8282#define OTP_PAGE_COUNT 64
8383#define OTP_PAGE_ROWS 64
8484#define OTP_ROW_COUNT (OTP_PAGE_COUNT * OTP_PAGE_ROWS)
85+ #define OTP_SPECIAL_PAGES 3
8586
8687using std::string;
8788using std::vector;
@@ -476,6 +477,7 @@ struct _settings {
476477 std::vector<std::string> selectors;
477478 uint32_t row = 0 ;
478479 std::vector<std::string> extra_files;
480+ bool dump_pages = false ;
479481 } otp;
480482
481483 struct {
@@ -1098,7 +1100,8 @@ struct otp_dump_command : public cmd {
10981100 return (
10991101 (
11001102 option (' r' , " --raw" ).set (settings.otp .raw ) % " Get raw 24 bit values" +
1101- option (' e' , " --ecc" ).set (settings.otp .ecc ) % " Use error correction"
1103+ option (' e' , " --ecc" ).set (settings.otp .ecc ) % " Use error correction" +
1104+ option (' p' , " --pages" ).set (settings.otp .dump_pages ) % " Index by page number & row number"
11021105 ).min (0 ).doc_non_optional (true ) % " Row/field options" +
11031106 (
11041107 device_selection % " Target device selection"
@@ -6100,7 +6103,7 @@ bool otp_get_command::execute(device_map &devices) {
61006103 if (m.reg_row / OTP_PAGE_ROWS != last_page) {
61016104 // todo pre-check page lock
61026105 struct picoboot_otp_cmd otp_cmd;
6103- if (m.reg_row / OTP_PAGE_ROWS >= 62 ) {
6106+ if (m.reg_row / OTP_PAGE_ROWS >= OTP_PAGE_COUNT - OTP_SPECIAL_PAGES ) {
61046107 // Read individual rows for lock words
61056108 otp_cmd.wRow = m.reg_row ;
61066109 otp_cmd.wRowCount = 1 ;
@@ -6254,20 +6257,59 @@ bool otp_dump_command::execute(device_map &devices) {
62546257 auto con = get_single_rp2350_bootsel_device_connection (devices, false );
62556258 // todo pre-check page lock
62566259 struct picoboot_otp_cmd otp_cmd;
6257- otp_cmd.wRow = 0 ;
6258- otp_cmd.wRowCount = OTP_ROW_COUNT;
62596260 otp_cmd.bEcc = settings.otp .ecc && !settings.otp .raw ;
62606261 vector<uint8_t > raw_buffer;
6261- raw_buffer.resize (otp_cmd.wRowCount * (otp_cmd.bEcc ? 2 : 4 ));
6262+ uint8_t row_size = otp_cmd.bEcc ? 2 : 4 ;
6263+ raw_buffer.resize (OTP_ROW_COUNT * row_size);
62626264 picoboot_memory_access raw_access (con);
6263- con.otp_read (&otp_cmd, raw_buffer.data (), raw_buffer.size ());
6265+ std::map<int , string> page_errors;
6266+ std::map<int , string> row_errors;
6267+
6268+ // Read most pages by page, as permissions are per page
6269+ otp_cmd.wRowCount = OTP_PAGE_ROWS;
6270+ for (int i=0 ; i < OTP_PAGE_COUNT - OTP_SPECIAL_PAGES; i++) {
6271+ otp_cmd.wRow = i * OTP_PAGE_ROWS;
6272+ try {
6273+ con.otp_read (&otp_cmd, raw_buffer.data () + i*(raw_buffer.size () / OTP_PAGE_COUNT), raw_buffer.size () / OTP_PAGE_COUNT);
6274+ } catch (picoboot::command_failure& e) {
6275+ if (e.get_code () == PICOBOOT_NOT_PERMITTED) {
6276+ page_errors[i] = e.what ();
6277+ } else {
6278+ throw e;
6279+ }
6280+ }
6281+ }
6282+
6283+ // Read special pages by row, as permissions are special
6284+ otp_cmd.wRowCount = 1 ;
6285+ for (int i=(OTP_PAGE_COUNT - OTP_SPECIAL_PAGES) * OTP_PAGE_ROWS; i < OTP_PAGE_COUNT * OTP_PAGE_ROWS; i++) {
6286+ otp_cmd.wRow = i;
6287+ try {
6288+ con.otp_read (&otp_cmd, raw_buffer.data () + i * row_size, row_size);
6289+ } catch (picoboot::command_failure& e) {
6290+ if (e.get_code () == PICOBOOT_NOT_PERMITTED) {
6291+ row_errors[i] = e.what ();
6292+ } else {
6293+ throw e;
6294+ }
6295+ }
6296+ }
6297+
62646298 fos.first_column (0 );
62656299 char buf[256 ];
62666300 for (int i=0 ;i<OTP_ROW_COUNT;i+=8 ) {
6267- snprintf (buf, sizeof (buf), " %04x: " , i);
6268- fos << buf;
6301+ if (settings.otp .dump_pages ) {
6302+ snprintf (buf, sizeof (buf), " %02d:%02d: " , i / OTP_PAGE_ROWS, i % OTP_PAGE_ROWS);
6303+ fos << buf;
6304+ } else {
6305+ snprintf (buf, sizeof (buf), " %04x: " , i);
6306+ fos << buf;
6307+ }
6308+
62696309 for (int j = i; j < i + 8 ; j++) {
6270- if (otp_cmd.bEcc ) {
6310+ if (row_errors.find (j) != row_errors.end () || page_errors.find (j / OTP_PAGE_ROWS) != page_errors.end ()) {
6311+ snprintf (buf, sizeof (buf), " %s, " , otp_cmd.bEcc ? " XXXX" : " XXXXXXXX" );
6312+ } else if (otp_cmd.bEcc ) {
62716313 snprintf (buf, sizeof (buf), " %04x, " , ((uint16_t *) raw_buffer.data ())[j]);
62726314 } else {
62736315 snprintf (buf, sizeof (buf), " %08x, " , ((uint32_t *) raw_buffer.data ())[j]);
0 commit comments