Skip to content

Commit 889469c

Browse files
committed
add -n option to load to avoid overwriting existing program
1 parent 62873e1 commit 889469c

File tree

1 file changed

+46
-9
lines changed

1 file changed

+46
-9
lines changed

main.cpp

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ struct range {
140140
to = other.clamp(to);
141141
}
142142

143+
bool intersects(const range& other) const {
144+
return !(other.from >= to || other.to < from);
145+
}
146+
143147
};
144148

145149
// ranges should not overlap
@@ -248,6 +252,8 @@ struct _settings {
248252
struct {
249253
bool verify = false;
250254
bool execute = false;
255+
bool no_overwrite = false;
256+
bool no_overwrite_force = false;
251257
} load;
252258

253259
struct {
@@ -363,6 +369,8 @@ struct load_command : public cmd {
363369
group get_cli() override {
364370
return (
365371
(
372+
option('n', "--no-overwrite").set(settings.load.no_overwrite) % "When writing flash data, do not overwrite an existing program in flash. If picotool cannot determine the size/presence of the program in flash, the command fails" +
373+
option('N', "--no-overwrite-unsafe").set(settings.load.no_overwrite_force) % "When writing flash data, do not overwrite an existing program in flash. If picotool cannot determine the size/presence of the program in flash, the load continues anyway" +
366374
option('v', "--verify").set(settings.load.verify) % "Verify the data was written correctly" +
367375
option('x', "--execute").set(settings.load.execute) % "Attempt to execute the downloaded file as a program after the load"
368376
).min(0).doc_non_optional(true) % "Post load actions" +
@@ -934,6 +942,12 @@ string read_string(memory_access &access, uint32_t addr) {
934942
}
935943

936944
struct bi_visitor_base {
945+
void visit(memory_access& access, const binary_info_header& hdr) {
946+
for (const auto &a : hdr.bi_addr) {
947+
visit(access, a);
948+
}
949+
}
950+
937951
void visit(memory_access& access, uint32_t addr) {
938952
binary_info_core_t bi;
939953
access.read_raw(addr, bi);
@@ -1332,9 +1346,7 @@ void info_guts(memory_access &raw_access) {
13321346
named_feature_groups[std::make_pair(group_tag, group_id)] = std::make_pair(label, flags);
13331347
});
13341348

1335-
for (const auto &a : hdr.bi_addr) {
1336-
visitor.visit(access, a);
1337-
}
1349+
visitor.visit(access, hdr);
13381350

13391351
visitor = bi_visitor{};
13401352
visitor.id_and_int([&](int tag, uint32_t id, uint32_t value) {
@@ -1380,9 +1392,7 @@ void info_guts(memory_access &raw_access) {
13801392
}
13811393
});
13821394

1383-
for (const auto &a : hdr.bi_addr) {
1384-
visitor.visit(access, a);
1385-
}
1395+
visitor.visit(access, hdr);
13861396

13871397
if (settings.info.show_basic || settings.info.all) {
13881398
select_group(program_info);
@@ -1603,9 +1613,7 @@ void save_command::execute(device_map &devices) {
16031613
return;
16041614
if (id == BINARY_INFO_ID_RP_BINARY_END) binary_end = value;
16051615
});
1606-
for (const auto &a : hdr.bi_addr) {
1607-
visitor.visit(access, a);
1608-
}
1616+
visitor.visit(access, hdr);
16091617
}
16101618
if (binary_end == 0) {
16111619
fail(ERROR_NOT_POSSIBLE,
@@ -1719,6 +1727,25 @@ void load_command::execute(device_map &devices) {
17191727
auto file_access = get_file_memory_access();
17201728
auto con = get_single_usb_boot_device(devices);
17211729
picoboot_memory_access raw_access(con);
1730+
range flash_binary_range(FLASH_START, FLASH_END);
1731+
bool flash_binary_end_unknown = true;
1732+
if (settings.load.no_overwrite_force) settings.load.no_overwrite = true;
1733+
if (settings.load.no_overwrite) {
1734+
binary_info_header hdr;
1735+
if (find_binary_info(raw_access, hdr)) {
1736+
auto access = remapped_memory_access(raw_access, hdr.reverse_copy_mapping);
1737+
auto visitor = bi_visitor{};
1738+
visitor.id_and_int([&](int tag, uint32_t id, uint32_t value) {
1739+
if (tag != BINARY_INFO_TAG_RASPBERRY_PI)
1740+
return;
1741+
if (id == BINARY_INFO_ID_RP_BINARY_END) {
1742+
flash_binary_range.to = value;
1743+
flash_binary_end_unknown = false;
1744+
}
1745+
});
1746+
visitor.visit(access, hdr);
1747+
}
1748+
}
17221749
auto ranges = get_colaesced_ranges(file_access);
17231750
for (auto mem_range : ranges) {
17241751
enum memory_type t1 = get_memory_type(mem_range.from);
@@ -1727,6 +1754,16 @@ void load_command::execute(device_map &devices) {
17271754
fail(ERROR_FORMAT, "File to load contained an invalid memory range 0x%08x-0x%08x", mem_range.from,
17281755
mem_range.to);
17291756
}
1757+
if (settings.load.no_overwrite && mem_range.intersects(flash_binary_range)) {
1758+
if (flash_binary_end_unknown) {
1759+
if (!settings.load.no_overwrite_force) {
1760+
fail(ERROR_NOT_POSSIBLE, "-n option specified, but the size/presence of an existing flash binary could not be detected; aborting. Consider using the -N option");
1761+
}
1762+
} else {
1763+
fail(ERROR_NOT_POSSIBLE, "-n option specified, and the loaded data range clashes with the existing flash binary range %08x->%08x",
1764+
flash_binary_range.from, flash_binary_range.to);
1765+
}
1766+
}
17301767
}
17311768
for (auto mem_range : ranges) {
17321769
enum memory_type type = get_memory_type(mem_range.from);

0 commit comments

Comments
 (0)