Skip to content

Commit c9aae62

Browse files
committed
Add handling to load for files with multiple family IDs
Also adds supported family IDs to models, used to check if family is supported for SRAM loads (and RP2040 flash loads) This fixes picotool load for the universal binaries
1 parent d1a8d35 commit c9aae62

2 files changed

Lines changed: 89 additions & 28 deletions

File tree

main.cpp

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -84,18 +84,6 @@ static __forceinline int __builtin_ctz(unsigned x) {
8484
#define OTP_ROW_COUNT (OTP_PAGE_COUNT * OTP_PAGE_ROWS)
8585
#define OTP_SPECIAL_PAGES 3
8686

87-
// Support for SDK 2.1.0 & SDK 2.1.1 -----
88-
#ifndef CYW43_FIRMWARE_FAMILY_ID
89-
#define CYW43_FIRMWARE_FAMILY_ID 0xe48bff55u
90-
#endif
91-
#ifndef BOOTROM_FAMILY_ID_MIN
92-
#define BOOTROM_FAMILY_ID_MIN RP2040_FAMILY_ID
93-
#endif
94-
#ifndef BOOTROM_FAMILY_ID_MAX
95-
#define BOOTROM_FAMILY_ID_MAX RP2350_ARM_NS_FAMILY_ID
96-
#endif
97-
// ------
98-
9987
using std::string;
10088
using std::vector;
10189
using std::pair;
@@ -4994,7 +4982,31 @@ bool load_guts(picoboot::connection con, iostream_memory_access &file_access) {
49944982
bool load_command::execute(device_map &devices) {
49954983
auto con = get_single_bootsel_device_connection(devices);
49964984
picoboot_memory_access raw_access(con);
4997-
auto tmp_file_access = get_file_memory_access(0);
4985+
uint32_t next_id = 0;
4986+
vector<uint32_t> available_family_ids;
4987+
uint32_t file_family_id = 0;
4988+
uint32_t override_family_id = settings.family_id;
4989+
auto tmp_file_access = get_file_memory_access(0, false, &next_id);
4990+
if (next_id) {
4991+
// UF2 file with multiple family IDs
4992+
settings.family_id = 0;
4993+
next_id = get_family_id(0);
4994+
while (next_id) {
4995+
available_family_ids.push_back(next_id);
4996+
auto tmp_access = get_file_memory_access(0, false, &next_id);
4997+
}
4998+
if (override_family_id) {
4999+
if (std::find(available_family_ids.begin(), available_family_ids.end(), override_family_id) == available_family_ids.end()) {
5000+
fos << "WARNING: Requested family ID " << family_name(override_family_id) << " not found in UF2 file, ";
5001+
fos << "so treating first family ID found in the UF2 file (" << family_name(available_family_ids[0]) << ") as the requested one\n";
5002+
available_family_ids.resize(1);
5003+
} else {
5004+
available_family_ids.resize(1);
5005+
available_family_ids[0] = override_family_id;
5006+
}
5007+
}
5008+
}
5009+
49985010
if (settings.load.partition >= 0) {
49995011
auto partitions = get_partitions(con);
50005012
if (!partitions) {
@@ -5010,28 +5022,52 @@ bool load_command::execute(device_map &devices) {
50105022
settings.offset = start + FLASH_START;
50115023
settings.offset_set = true;
50125024
settings.partition_size = end - start;
5013-
} else if (!settings.load.ignore_pt && !settings.offset_set && tmp_file_access.get_binary_start() == FLASH_START) {
5014-
uint32_t family_id = get_family_id(0);
5015-
settings.family_id = family_id;
5025+
} else if (!settings.load.ignore_pt && !settings.offset_set) {
5026+
if (available_family_ids.size() == 0) {
5027+
uint32_t family_id = get_family_id(0);
5028+
available_family_ids.push_back(family_id);
5029+
}
50165030
uint32_t start;
50175031
uint32_t end;
5018-
if (raw_access.get_model()->supports_partition_table()) {
5019-
if (get_target_partition(con, &start, &end)) {
5020-
settings.offset = start + FLASH_START;
5021-
settings.offset_set = true;
5022-
settings.partition_size = end - start;
5032+
bool accepted = false;
5033+
for (auto family_id : available_family_ids) {
5034+
settings.family_id = override_family_id ? override_family_id : family_id;
5035+
if (raw_access.get_model()->supports_partition_table() && tmp_file_access.get_binary_start() == FLASH_START) {
5036+
if (get_target_partition(con, &start, &end)) {
5037+
settings.offset = start + FLASH_START;
5038+
settings.offset_set = true;
5039+
settings.partition_size = end - start;
5040+
accepted = true;
5041+
file_family_id = family_id;
5042+
break;
5043+
}
50235044
} else {
5024-
// Check if partition table is present, for correct error message
5045+
// Check the family ID is supported by the model (either SRAM, or RP2040)
5046+
if (raw_access.get_model()->supports_family_id(settings.family_id)) {
5047+
if (available_family_ids.size() > 1) {
5048+
fos << "Loading family ID " << family_name(settings.family_id) << "\n";
5049+
}
5050+
accepted = true;
5051+
file_family_id = family_id;
5052+
break;
5053+
}
5054+
}
5055+
}
5056+
if (!accepted) {
5057+
// Check if partition table is present, for correct error message
5058+
if (raw_access.get_model()->supports_partition_table() && tmp_file_access.get_binary_start() == FLASH_START) {
50255059
auto partitions = get_partitions(con);
50265060
if (!partitions) {
5027-
fail(ERROR_NOT_POSSIBLE, "This file cannot be loaded onto a device with no partition table");
5061+
fail(ERROR_NOT_POSSIBLE, "This file cannot be loaded onto an %s device with no partition table", raw_access.get_model()->name().c_str());
50285062
} else {
50295063
fail(ERROR_NOT_POSSIBLE, "This file cannot be loaded into the partition table on the device");
50305064
}
5065+
} else {
5066+
fail(ERROR_NOT_POSSIBLE, "This file cannot be loaded onto an %s device", raw_access.get_model()->name().c_str());
50315067
}
50325068
}
50335069
}
5034-
auto file_access = get_file_memory_access(0);
5070+
auto file_access = get_file_memory_access(0, false, &file_family_id);
50355071
if (settings.offset_set && get_file_type() != filetype::bin && raw_access.get_model()->chip() == rp2040) {
50365072
fail(ERROR_ARGS, "Offset only valid for BIN files");
50375073
}

model/model.h

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ typedef enum {
4545
unknown_revision
4646
} chip_revision_t;
4747

48+
// Support for SDK 2.1.0 & SDK 2.1.1 -----
49+
#ifndef CYW43_FIRMWARE_FAMILY_ID
50+
#define CYW43_FIRMWARE_FAMILY_ID 0xe48bff55u
51+
#endif
52+
#ifndef BOOTROM_FAMILY_ID_MIN
53+
#define BOOTROM_FAMILY_ID_MIN RP2040_FAMILY_ID
54+
#endif
55+
#ifndef BOOTROM_FAMILY_ID_MAX
56+
#define BOOTROM_FAMILY_ID_MAX RP2350_ARM_NS_FAMILY_ID
57+
#endif
58+
// ------
59+
4860
#ifdef __cplusplus
4961

5062
#include <algorithm>
@@ -70,8 +82,8 @@ static std::string chip_name(chip_t chip) {
7082
// looking at the bootrom), however "stock" versions can be created from family IDs for example
7183
class model_info {
7284
public:
73-
model_info(chip_t chip, std::string name, uint32_t rom_end, std::set<picoboot_cmd_id> picoboot_cmds = {}) : _chip(chip), _name(std::move(name)),
74-
_rom_end(rom_end), _picoboot_cmds(std::move(picoboot_cmds)) {}
85+
model_info(chip_t chip, std::string name, uint32_t rom_end, std::set<picoboot_cmd_id> picoboot_cmds = {}, std::set<uint32_t> supported_family_ids = {}) : _chip(chip), _name(std::move(name)),
86+
_rom_end(rom_end), _picoboot_cmds(std::move(picoboot_cmds)), _supported_family_ids(std::move(supported_family_ids)) {}
7587
chip_t chip() const { return _chip; }
7688
chip_revision_t chip_revision() const { return _chip_revision; }
7789
void set_chip_revision(chip_revision_t revision) { _chip_revision = revision; }
@@ -86,6 +98,10 @@ class model_info {
8698
return invalid;
8799
}
88100

101+
virtual bool supports_family_id(uint32_t family_id) const {
102+
return _supported_family_ids.find(family_id) != _supported_family_ids.end();
103+
}
104+
89105
virtual bool supports_picoboot_cmd(picoboot_cmd_id cmd) const {
90106
return _picoboot_cmds.find(cmd) != _picoboot_cmds.end();
91107
}
@@ -128,6 +144,7 @@ class model_info {
128144
chip_revision_t _chip_revision;
129145
uint32_t _rom_end;
130146
std::set<picoboot_cmd_id> _picoboot_cmds;
147+
std::set<uint32_t> _supported_family_ids;
131148
chip_t _chip;
132149
uint32_t _family_id;
133150
};
@@ -142,7 +159,7 @@ class model_unknown : public model_info {
142159

143160
class model_rp : public model_info {
144161
protected:
145-
model_rp(chip_t chip, std::string name, uint32_t rom_end, std::set<picoboot_cmd_id> picoboot_cmds = {}) : model_info(chip, std::move(name), rom_end, std::move(picoboot_cmds)) {}
162+
model_rp(chip_t chip, std::string name, uint32_t rom_end, std::set<picoboot_cmd_id> picoboot_cmds = {}, std::set<uint32_t> supported_family_ids = {}) : model_info(chip, std::move(name), rom_end, std::move(picoboot_cmds), std::move(supported_family_ids)) {}
146163

147164
public:
148165
enum memory_type get_memory_type(uint32_t addr) override {
@@ -171,7 +188,7 @@ class model_rp : public model_info {
171188
class model_rp_generic : public model_rp {
172189
public:
173190
// allow large memory regions for generic model
174-
model_rp_generic() : model_rp(unknown, chip_name(unknown), 0x100, {}) {}
191+
model_rp_generic() : model_rp(unknown, chip_name(unknown), 0x100) {}
175192

176193
uint32_t xip_sram_start() override {
177194
return std::min({XIP_SRAM_START_RP2040, XIP_SRAM_START_RP2350});
@@ -202,6 +219,8 @@ class model_rp2040 : public model_rp {
202219
PC_ENTER_CMD_XIP,
203220
PC_EXEC,
204221
PC_VECTORIZE_FLASH,
222+
}, {
223+
RP2040_FAMILY_ID,
205224
}) {
206225
set_family_id(RP2040_FAMILY_ID);
207226
}
@@ -264,6 +283,12 @@ class model_rp2350 : public model_rp {
264283
PC_GET_INFO,
265284
PC_OTP_READ,
266285
PC_OTP_WRITE,
286+
}, {
287+
ABSOLUTE_FAMILY_ID,
288+
DATA_FAMILY_ID,
289+
RP2350_ARM_S_FAMILY_ID,
290+
RP2350_RISCV_FAMILY_ID,
291+
RP2350_ARM_NS_FAMILY_ID,
267292
}) {}
268293

269294
bool supports_partition_table() override { return true; }

0 commit comments

Comments
 (0)