Add permission handling to OTP dump Prints XXs for any rows with permissions failures Also, add `--pages` option to index by page & row (eg 63:56) rather than hex (eg 0ff8)
diff --git a/main.cpp b/main.cpp index 823c010..cd77e03 100644 --- a/main.cpp +++ b/main.cpp
@@ -80,6 +80,7 @@ #define OTP_PAGE_COUNT 64 #define OTP_PAGE_ROWS 64 #define OTP_ROW_COUNT (OTP_PAGE_COUNT * OTP_PAGE_ROWS) +#define OTP_SPECIAL_PAGES 3 using std::string; using std::vector; @@ -439,6 +440,7 @@ std::vector<std::string> selectors; uint32_t row = 0; std::vector<std::string> extra_files; + bool dump_pages = false; } otp; struct { @@ -1029,7 +1031,8 @@ return ( ( option('r', "--raw").set(settings.otp.raw) % "Get raw 24 bit values" + - option('e', "--ecc").set(settings.otp.ecc) % "Use error correction" + option('e', "--ecc").set(settings.otp.ecc) % "Use error correction" + + option('p', "--pages").set(settings.otp.dump_pages) % "Index by page number & row number" ).min(0).doc_non_optional(true) % "Row/field options" + ( device_selection % "Target device selection" @@ -5688,7 +5691,7 @@ if (m.reg_row / OTP_PAGE_ROWS != last_page) { // todo pre-check page lock struct picoboot_otp_cmd otp_cmd; - if (m.reg_row / OTP_PAGE_ROWS >= 62) { + if (m.reg_row / OTP_PAGE_ROWS >= OTP_PAGE_COUNT - OTP_SPECIAL_PAGES) { // Read individual rows for lock words otp_cmd.wRow = m.reg_row; otp_cmd.wRowCount = 1; @@ -5842,20 +5845,59 @@ auto con = get_single_rp2350_bootsel_device_connection(devices, false); // todo pre-check page lock struct picoboot_otp_cmd otp_cmd; - otp_cmd.wRow = 0; - otp_cmd.wRowCount = OTP_ROW_COUNT; otp_cmd.bEcc = settings.otp.ecc && !settings.otp.raw; vector<uint8_t> raw_buffer; - raw_buffer.resize(otp_cmd.wRowCount * (otp_cmd.bEcc ? 2 : 4)); + uint8_t row_size = otp_cmd.bEcc ? 2 : 4; + raw_buffer.resize(OTP_ROW_COUNT * row_size); picoboot_memory_access raw_access(con); - con.otp_read(&otp_cmd, raw_buffer.data(), raw_buffer.size()); + std::map<int, string> page_errors; + std::map<int, string> row_errors; + + // Read most pages by page, as permissions are per page + otp_cmd.wRowCount = OTP_PAGE_ROWS; + for (int i=0; i < OTP_PAGE_COUNT - OTP_SPECIAL_PAGES; i++) { + otp_cmd.wRow = i * OTP_PAGE_ROWS; + try { + con.otp_read(&otp_cmd, raw_buffer.data() + i*(raw_buffer.size() / OTP_PAGE_COUNT), raw_buffer.size() / OTP_PAGE_COUNT); + } catch (picoboot::command_failure& e) { + if (e.get_code() == PICOBOOT_NOT_PERMITTED) { + page_errors[i] = e.what(); + } else { + throw e; + } + } + } + + // Read special pages by row, as permissions are special + otp_cmd.wRowCount = 1; + for (int i=(OTP_PAGE_COUNT - OTP_SPECIAL_PAGES) * OTP_PAGE_ROWS; i < OTP_PAGE_COUNT * OTP_PAGE_ROWS; i++) { + otp_cmd.wRow = i; + try { + con.otp_read(&otp_cmd, raw_buffer.data() + i * row_size, row_size); + } catch (picoboot::command_failure& e) { + if (e.get_code() == PICOBOOT_NOT_PERMITTED) { + row_errors[i] = e.what(); + } else { + throw e; + } + } + } + fos.first_column(0); char buf[256]; for(int i=0;i<OTP_ROW_COUNT;i+=8) { - snprintf(buf, sizeof(buf), "%04x: ", i); - fos << buf; + if (settings.otp.dump_pages) { + snprintf(buf, sizeof(buf), "%02d:%02d: ", i / OTP_PAGE_ROWS, i % OTP_PAGE_ROWS); + fos << buf; + } else { + snprintf(buf, sizeof(buf), "%04x: ", i); + fos << buf; + } + for (int j = i; j < i + 8; j++) { - if (otp_cmd.bEcc) { + if (row_errors.find(j) != row_errors.end() || page_errors.find(j / OTP_PAGE_ROWS) != page_errors.end()) { + snprintf(buf, sizeof(buf), "%s, ", otp_cmd.bEcc ? "XXXX" : "XXXXXXXX"); + } else if (otp_cmd.bEcc) { snprintf(buf, sizeof(buf), "%04x, ", ((uint16_t *) raw_buffer.data())[j]); } else { snprintf(buf, sizeof(buf), "%08x, ", ((uint32_t *) raw_buffer.data())[j]);