@@ -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"
@@ -6108,7 +6111,7 @@ bool otp_get_command::execute(device_map &devices) {
61086111 if (m.reg_row / OTP_PAGE_ROWS != last_page) {
61096112 // todo pre-check page lock
61106113 struct picoboot_otp_cmd otp_cmd;
6111- if (m.reg_row / OTP_PAGE_ROWS >= 62 ) {
6114+ if (m.reg_row / OTP_PAGE_ROWS >= OTP_PAGE_COUNT - OTP_SPECIAL_PAGES ) {
61126115 // Read individual rows for lock words
61136116 otp_cmd.wRow = m.reg_row ;
61146117 otp_cmd.wRowCount = 1 ;
@@ -6262,20 +6265,59 @@ bool otp_dump_command::execute(device_map &devices) {
62626265 auto con = get_single_rp2350_bootsel_device_connection (devices, false );
62636266 // todo pre-check page lock
62646267 struct picoboot_otp_cmd otp_cmd;
6265- otp_cmd.wRow = 0 ;
6266- otp_cmd.wRowCount = OTP_ROW_COUNT;
62676268 otp_cmd.bEcc = settings.otp .ecc && !settings.otp .raw ;
62686269 vector<uint8_t > raw_buffer;
6269- raw_buffer.resize (otp_cmd.wRowCount * (otp_cmd.bEcc ? 2 : 4 ));
6270+ uint8_t row_size = otp_cmd.bEcc ? 2 : 4 ;
6271+ raw_buffer.resize (OTP_ROW_COUNT * row_size);
62706272 picoboot_memory_access raw_access (con);
6271- con.otp_read (&otp_cmd, raw_buffer.data (), raw_buffer.size ());
6273+ std::map<int , string> page_errors;
6274+ std::map<int , string> row_errors;
6275+
6276+ // Read most pages by page, as permissions are per page
6277+ otp_cmd.wRowCount = OTP_PAGE_ROWS;
6278+ for (int i=0 ; i < OTP_PAGE_COUNT - OTP_SPECIAL_PAGES; i++) {
6279+ otp_cmd.wRow = i * OTP_PAGE_ROWS;
6280+ try {
6281+ con.otp_read (&otp_cmd, raw_buffer.data () + i*(raw_buffer.size () / OTP_PAGE_COUNT), raw_buffer.size () / OTP_PAGE_COUNT);
6282+ } catch (picoboot::command_failure& e) {
6283+ if (e.get_code () == PICOBOOT_NOT_PERMITTED) {
6284+ page_errors[i] = e.what ();
6285+ } else {
6286+ throw e;
6287+ }
6288+ }
6289+ }
6290+
6291+ // Read special pages by row, as permissions are special
6292+ otp_cmd.wRowCount = 1 ;
6293+ for (int i=(OTP_PAGE_COUNT - OTP_SPECIAL_PAGES) * OTP_PAGE_ROWS; i < OTP_PAGE_COUNT * OTP_PAGE_ROWS; i++) {
6294+ otp_cmd.wRow = i;
6295+ try {
6296+ con.otp_read (&otp_cmd, raw_buffer.data () + i * row_size, row_size);
6297+ } catch (picoboot::command_failure& e) {
6298+ if (e.get_code () == PICOBOOT_NOT_PERMITTED) {
6299+ row_errors[i] = e.what ();
6300+ } else {
6301+ throw e;
6302+ }
6303+ }
6304+ }
6305+
62726306 fos.first_column (0 );
62736307 char buf[256 ];
62746308 for (int i=0 ;i<OTP_ROW_COUNT;i+=8 ) {
6275- snprintf (buf, sizeof (buf), " %04x: " , i);
6276- fos << buf;
6309+ if (settings.otp .dump_pages ) {
6310+ snprintf (buf, sizeof (buf), " %02d:%02d: " , i / OTP_PAGE_ROWS, i % OTP_PAGE_ROWS);
6311+ fos << buf;
6312+ } else {
6313+ snprintf (buf, sizeof (buf), " %04x: " , i);
6314+ fos << buf;
6315+ }
6316+
62776317 for (int j = i; j < i + 8 ; j++) {
6278- if (otp_cmd.bEcc ) {
6318+ if (row_errors.find (j) != row_errors.end () || page_errors.find (j / OTP_PAGE_ROWS) != page_errors.end ()) {
6319+ snprintf (buf, sizeof (buf), " %s, " , otp_cmd.bEcc ? " XXXX" : " XXXXXXXX" );
6320+ } else if (otp_cmd.bEcc ) {
62796321 snprintf (buf, sizeof (buf), " %04x, " , ((uint16_t *) raw_buffer.data ())[j]);
62806322 } else {
62816323 snprintf (buf, sizeof (buf), " %08x, " , ((uint32_t *) raw_buffer.data ())[j]);
0 commit comments