Skip to content

Commit 91173cb

Browse files
committed
Allow piecemeal reads during block searches
For unsigned/unhashed binaries, this offers a large performance boost, by only reading the metadata blocks and not reading the whole binary. For signed/hashed binaries there is no difference, as the whole binary must be read for verification anyway.
1 parent 88ca001 commit 91173cb

File tree

3 files changed

+47
-30
lines changed

3 files changed

+47
-30
lines changed

bintool/bintool.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,14 @@ std::unique_ptr<block> get_last_block(std::vector<uint8_t> &bin, uint32_t storag
319319
uint32_t next_block_addr = first_block->physical_addr + first_block->next_block_rel;
320320
std::unique_ptr<block> new_first_block;
321321
uint32_t read_size = PICOBIN_MAX_BLOCK_SIZE;
322+
uint32_t current_bin_start = storage_addr;
322323
while (true) {
323-
auto offset = next_block_addr - storage_addr;
324-
if (offset + read_size > bin.size() && more_cb != nullptr) {
325-
more_cb(bin, offset + read_size);
324+
if (next_block_addr + read_size > current_bin_start + bin.size() && more_cb != nullptr) {
325+
DEBUG_LOG("Reading into bin %08x+%x\n", next_block_addr, read_size);
326+
more_cb(bin, next_block_addr, read_size);
327+
current_bin_start = next_block_addr;
326328
}
329+
auto offset = next_block_addr - current_bin_start;
327330
std::vector<uint32_t> words = lsb_bytes_to_words(bin.begin() + offset, bin.end());
328331
if (words.front() != PICOBIN_BLOCK_MARKER_START) {
329332
fail(ERROR_UNKNOWN, "Block loop is not valid - no block found at %08x\n", (int)(next_block_addr));
@@ -362,12 +365,15 @@ std::vector<std::unique_ptr<block>> get_all_blocks(std::vector<uint8_t> &bin, ui
362365
uint32_t next_block_addr = first_block->physical_addr + first_block->next_block_rel;
363366
std::vector<std::unique_ptr<block>> all_blocks;
364367
uint32_t read_size = PICOBIN_MAX_BLOCK_SIZE;
368+
uint32_t current_bin_start = storage_addr;
365369
while (true) {
366370
std::unique_ptr<block> new_first_block;
367-
auto offset = next_block_addr - storage_addr;
368-
if (offset + read_size > bin.size() && more_cb != nullptr) {
369-
more_cb(bin, offset + read_size);
371+
if (next_block_addr + read_size > current_bin_start + bin.size() && more_cb != nullptr) {
372+
DEBUG_LOG("Reading into bin %08x+%x\n", next_block_addr, read_size);
373+
more_cb(bin, next_block_addr, read_size);
374+
current_bin_start = next_block_addr;
370375
}
376+
auto offset = next_block_addr - current_bin_start;
371377
std::vector<uint32_t> words = lsb_bytes_to_words(bin.begin() + offset, bin.end());
372378
words.erase(words.begin());
373379
DEBUG_LOG("Checking block at %x\n", next_block_addr);
@@ -698,7 +704,7 @@ std::vector<uint8_t> get_lm_hash_data(elf_file *elf, block *new_block, bool clea
698704
}
699705

700706

701-
std::vector<uint8_t> get_lm_hash_data(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, bool clear_sram = false) {
707+
std::vector<uint8_t> get_lm_hash_data(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, get_more_bin_cb more_cb, bool clear_sram = false) {
702708
std::vector<uint8_t> to_hash;
703709
std::shared_ptr<load_map_item> load_map = new_block->get_item<load_map_item>();
704710
if (load_map == nullptr) {
@@ -729,6 +735,7 @@ std::vector<uint8_t> get_lm_hash_data(std::vector<uint8_t> bin, uint32_t storage
729735
} else {
730736
DEBUG_LOG("Already has load map, so hashing that\n");
731737
// todo hash existing load map
738+
uint32_t current_bin_start = storage_addr;
732739
for(const auto &entry : load_map->entries) {
733740
if (entry.storage_address == 0) {
734741
std::copy(
@@ -737,7 +744,15 @@ std::vector<uint8_t> get_lm_hash_data(std::vector<uint8_t> bin, uint32_t storage
737744
std::back_inserter(to_hash));
738745
DEBUG_LOG("CLEAR %08x + %08x\n", (int)entry.runtime_address, (int)entry.size);
739746
} else {
740-
uint32_t rel_addr = entry.storage_address - storage_addr;
747+
if (entry.storage_address + entry.size > current_bin_start + bin.size()) {
748+
if (more_cb == nullptr) {
749+
fail(ERROR_NOT_POSSIBLE, "BIN does not contain data for load_map entry %08x->%08x", entry.storage_address, entry.storage_address + entry.size);
750+
}
751+
DEBUG_LOG("Reading into bin %08x+%x\n", entry.storage_address, entry.size);
752+
more_cb(bin, entry.storage_address, entry.size);
753+
current_bin_start = entry.storage_address;
754+
}
755+
uint32_t rel_addr = entry.storage_address - current_bin_start;
741756
std::copy(
742757
bin.begin() + rel_addr,
743758
bin.begin() + rel_addr + entry.size,
@@ -787,10 +802,10 @@ int hash_andor_sign(elf_file *elf, block *new_block, const public_t public_key,
787802

788803

789804
std::vector<uint8_t> hash_andor_sign(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const public_t public_key, const private_t private_key, bool hash_value, bool sign, bool clear_sram) {
790-
std::vector<uint8_t> to_hash = get_lm_hash_data(bin, storage_addr, runtime_addr, new_block, clear_sram);
805+
std::vector<uint8_t> to_hash = get_lm_hash_data(bin, storage_addr, runtime_addr, new_block, nullptr, clear_sram);
806+
807+
hash_andor_sign_block(new_block, public_key, private_key, hash_value, sign, to_hash);
791808

792-
hash_andor_sign_block(new_block, public_key, private_key, hash_value, sign, bin);
793-
794809
auto tmp = new_block->to_words();
795810
std::vector<uint8_t> data = words_to_lsb_bytes(tmp.begin(), tmp.end());
796811

@@ -800,15 +815,15 @@ std::vector<uint8_t> hash_andor_sign(std::vector<uint8_t> bin, uint32_t storage_
800815
}
801816

802817

803-
void verify_block(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *block, verified_t &hash_verified, verified_t &sig_verified) {
818+
void verify_block(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *block, verified_t &hash_verified, verified_t &sig_verified, get_more_bin_cb more_cb) {
804819
std::shared_ptr<load_map_item> load_map = block->get_item<load_map_item>();
805820
std::shared_ptr<hash_def_item> hash_def = block->get_item<hash_def_item>();
806821
hash_verified = none;
807822
sig_verified = none;
808823
if (load_map == nullptr || hash_def == nullptr) {
809824
return;
810825
}
811-
std::vector<uint8_t> to_hash = get_lm_hash_data(bin, storage_addr, runtime_addr, block, false);
826+
std::vector<uint8_t> to_hash = get_lm_hash_data(bin, storage_addr, runtime_addr, block, more_cb, false);
812827

813828
// auto it = std::find(block->items.begin(), block->items.end(), hash_def);
814829
// assert (it != block->items.end());

bintool/bintool.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block);
2929
#endif
3030

3131
// Bins
32-
typedef std::function<void(std::vector<uint8_t> &bin, uint32_t size)> get_more_bin_cb;
32+
typedef std::function<void(std::vector<uint8_t> &bin, uint32_t offset, uint32_t size)> get_more_bin_cb;
3333
std::unique_ptr<block> find_first_block(std::vector<uint8_t> bin, uint32_t storage_addr);
3434
std::unique_ptr<block> get_last_block(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, get_more_bin_cb more_cb = nullptr);
3535
std::vector<std::unique_ptr<block>> get_all_blocks(std::vector<uint8_t> &bin, uint32_t storage_addr, std::unique_ptr<block> &first_block, get_more_bin_cb more_cb = nullptr);
@@ -38,5 +38,5 @@ uint32_t calc_checksum(std::vector<uint8_t> bin);
3838
#if HAS_MBEDTLS
3939
std::vector<uint8_t> hash_andor_sign(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const public_t public_key, const private_t private_key, bool hash_value, bool sign, bool clear_sram = false);
4040
std::vector<uint8_t> encrypt(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *new_block, const private_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign);
41-
void verify_block(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *block, verified_t &hash_verified, verified_t &sig_verified);
41+
void verify_block(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runtime_addr, block *block, verified_t &hash_verified, verified_t &sig_verified, get_more_bin_cb more_cb = nullptr);
4242
#endif

main.cpp

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2897,9 +2897,9 @@ std::unique_ptr<block> find_best_block(memory_access &raw_access, vector<uint8_t
28972897
std::unique_ptr<block> best_block = find_first_block(bin, raw_access.get_binary_start());
28982898
if (best_block) {
28992899
// verify stuff
2900-
get_more_bin_cb more_cb = [&raw_access](std::vector<uint8_t> &bin, uint32_t new_size) {
2901-
DEBUG_LOG("Now reading from %x size %x\n", raw_access.get_binary_start(), new_size);
2902-
bin = raw_access.read_vector<uint8_t>(raw_access.get_binary_start(), new_size, true);
2900+
get_more_bin_cb more_cb = [&raw_access](std::vector<uint8_t> &bin, uint32_t offset, uint32_t size) {
2901+
DEBUG_LOG("Now reading from %x size %x\n", offset, size);
2902+
bin = raw_access.read_vector<uint8_t>(offset, size, true);
29032903
};
29042904
auto all_blocks = get_all_blocks(bin, raw_access.get_binary_start(), best_block, more_cb);
29052905

@@ -2961,9 +2961,9 @@ std::unique_ptr<block> find_last_block(memory_access &raw_access, vector<uint8_t
29612961
std::unique_ptr<block> first_block = find_first_block(bin, raw_access.get_binary_start());
29622962
if (first_block) {
29632963
// verify stuff
2964-
get_more_bin_cb more_cb = [&raw_access](std::vector<uint8_t> &bin, uint32_t new_size) {
2965-
DEBUG_LOG("Now reading from %x size %x\n", raw_access.get_binary_start(), new_size);
2966-
bin = raw_access.read_vector<uint8_t>(raw_access.get_binary_start(), new_size, true);
2964+
get_more_bin_cb more_cb = [&raw_access](std::vector<uint8_t> &bin, uint32_t offset, uint32_t size) {
2965+
DEBUG_LOG("Now reading from %x size %x\n", offset, size);
2966+
bin = raw_access.read_vector<uint8_t>(offset, size, true);
29672967
};
29682968
auto last_block = get_last_block(bin, raw_access.get_binary_start(), first_block, more_cb);
29692969
return last_block;
@@ -3027,6 +3027,11 @@ void info_guts(memory_access &raw_access, void *con) {
30273027
#endif
30283028
// Use flash caching
30293029
settings.use_flash_cache = true;
3030+
// Callback to pass to bintool, to get more bin data
3031+
get_more_bin_cb more_cb = [&raw_access](std::vector<uint8_t> &bin, uint32_t offset, uint32_t size) {
3032+
DEBUG_LOG("Now reading from %x size %x\n", offset, size);
3033+
bin = raw_access.read_vector<uint8_t>(offset, size, true);
3034+
};
30303035
try {
30313036
struct group {
30323037
explicit group(string name, bool enabled = true, int min_tab = 0) : name(std::move(name)), enabled(enabled), min_tab(min_tab) {}
@@ -3058,11 +3063,12 @@ void info_guts(memory_access &raw_access, void *con) {
30583063
infos[current_group].emplace_back(std::make_pair(name, value));
30593064
}
30603065
};
3061-
auto info_metadata = [&](std::vector<uint8_t> bin, block *current_block, bool verbose_metadata = false) {
3066+
auto info_metadata = [&](block *current_block, bool verbose_metadata = false) {
30623067
verified_t hash_verified = none;
30633068
verified_t sig_verified = none;
30643069
#if HAS_MBEDTLS
3065-
verify_block(bin, raw_access.get_binary_start(), raw_access.get_binary_start(), current_block, hash_verified, sig_verified);
3070+
// Pass empty bin, which will be populated by more_cb if there is a signature/hash_value
3071+
verify_block({}, raw_access.get_binary_start(), raw_access.get_binary_start(), current_block, hash_verified, sig_verified, more_cb);
30663072
#endif
30673073

30683074
// Addresses
@@ -3442,18 +3448,14 @@ void info_guts(memory_access &raw_access, void *con) {
34423448
std::unique_ptr<block> first_block = find_first_block(bin, raw_access.get_binary_start());
34433449
if (first_block) {
34443450
// verify stuff
3445-
get_more_bin_cb more_cb = [&raw_access](std::vector<uint8_t> &bin, uint32_t new_size) {
3446-
DEBUG_LOG("Now reading from %x size %x\n", raw_access.get_binary_start(), new_size);
3447-
bin = raw_access.read_vector<uint8_t>(raw_access.get_binary_start(), new_size, true);
3448-
};
34493451
auto all_blocks = get_all_blocks(bin, raw_access.get_binary_start(), first_block, more_cb);
34503452

34513453
int block_i = 0;
34523454
select_group(metadata_info[block_i++], true);
3453-
info_metadata(bin, first_block.get(), true);
3455+
info_metadata(first_block.get(), true);
34543456
for (auto &block : all_blocks) {
34553457
select_group(metadata_info[block_i++], true);
3456-
info_metadata(bin, block.get(), true);
3458+
info_metadata(block.get(), true);
34573459
}
34583460
} else {
34593461
// This displays that there are no metadata blocks
@@ -3463,7 +3465,7 @@ void info_guts(memory_access &raw_access, void *con) {
34633465
std::unique_ptr<block> best_block = find_best_block(raw_access, bin);
34643466
if (best_block && (settings.info.show_basic || settings.info.all)) {
34653467
select_group(program_info);
3466-
info_metadata(bin, best_block.get());
3468+
info_metadata(best_block.get());
34673469
} else if (!best_block && has_binary_info && get_model(raw_access) == rp2350) {
34683470
fos << "WARNING: Binary on RP2350 device does not contain a block loop - this binary will not boot\n";
34693471
}

0 commit comments

Comments
 (0)