elf2uf2: determine entry address selected by Boot ROM (Plan B)

This commit is contained in:
Peter Lawrence 2021-02-19 11:16:30 -06:00 committed by Graham Sanderson
parent 07e3387458
commit eae2006f79

View File

@ -46,8 +46,7 @@ static int fail_write_error() {
struct address_range { struct address_range {
enum type { enum type {
CONTENTS_ENTRY, // may have contents *and* allows an entry address CONTENTS, // may have contents
CONTENTS_NO_ENTRY, // may have contents but does NOT allow an entry address
NO_CONTENTS, // must be uninitialized NO_CONTENTS, // must be uninitialized
IGNORE // will be ignored IGNORE // will be ignored
}; };
@ -68,13 +67,13 @@ typedef std::vector<address_range> address_ranges;
#define XIP_SRAM_END 0x15004000u #define XIP_SRAM_END 0x15004000u
const address_ranges rp2040_address_ranges_flash { const address_ranges rp2040_address_ranges_flash {
address_range(FLASH_START, FLASH_END, address_range::type::CONTENTS_NO_ENTRY), address_range(FLASH_START, FLASH_END, address_range::type::CONTENTS),
address_range(MAIN_RAM_START, MAIN_RAM_END, address_range::type::NO_CONTENTS) address_range(MAIN_RAM_START, MAIN_RAM_END, address_range::type::NO_CONTENTS)
}; };
const address_ranges rp2040_address_ranges_ram { const address_ranges rp2040_address_ranges_ram {
address_range(MAIN_RAM_START, MAIN_RAM_END, address_range::type::CONTENTS_ENTRY), address_range(MAIN_RAM_START, MAIN_RAM_END, address_range::type::CONTENTS),
address_range(XIP_SRAM_START, XIP_SRAM_END, address_range::type::CONTENTS_NO_ENTRY), address_range(XIP_SRAM_START, XIP_SRAM_END, address_range::type::CONTENTS),
address_range(0x00000000u, 0x00004000u, address_range::type::IGNORE) // for now we ignore the bootrom if present address_range(0x00000000u, 0x00004000u, address_range::type::IGNORE) // for now we ignore the bootrom if present
}; };
@ -154,7 +153,7 @@ int read_and_check_elf32_ph_entries(FILE *in, const elf32_header &eh, const addr
rc = check_address_range(valid_ranges, entry.paddr, entry.vaddr, mapped_size, false, ar); rc = check_address_range(valid_ranges, entry.paddr, entry.vaddr, mapped_size, false, ar);
if (rc) return rc; if (rc) return rc;
// we don't download uninitialized, generally it is BSS and should be zero-ed by crt0.S, or it may be COPY areas which are undefined // we don't download uninitialized, generally it is BSS and should be zero-ed by crt0.S, or it may be COPY areas which are undefined
if ( (ar.type != address_range::type::CONTENTS_ENTRY) && (ar.type != address_range::type::CONTENTS_NO_ENTRY) ) { if (ar.type != address_range::type::CONTENTS) {
if (verbose) printf(" ignored\n"); if (verbose) printf(" ignored\n");
continue; continue;
} }
@ -219,16 +218,7 @@ static bool is_address_valid(const address_ranges& valid_ranges, uint32_t addr)
static bool is_address_initialized(const address_ranges& valid_ranges, uint32_t addr) { static bool is_address_initialized(const address_ranges& valid_ranges, uint32_t addr) {
for(const auto& range : valid_ranges) { for(const auto& range : valid_ranges) {
if (range.from <= addr && range.to > addr) { if (range.from <= addr && range.to > addr) {
return (address_range::type::CONTENTS_ENTRY == range.type) || (address_range::type::CONTENTS_NO_ENTRY == range.type); return address_range::type::CONTENTS == range.type;
}
}
return false;
}
static bool is_address_entry_capable(const address_ranges& valid_ranges, uint32_t addr) {
for(const auto& range : valid_ranges) {
if (range.from <= addr && range.to > addr) {
return (address_range::type::CONTENTS_ENTRY == range.type);
} }
} }
return false; return false;
@ -265,14 +255,19 @@ int elf2uf2(FILE *in, FILE *out) {
} }
uint page_num = 0; uint page_num = 0;
if (ram_style) { if (ram_style) {
// the Boot ROM cherry-picks the lowest MAIN_RAM address as the entry point; determine what that will be uint32_t expected_ep_main_ram = 0xFFFFFFFF;
uint32_t expected_ep = 0xFFFFFFFF; uint32_t expected_ep_xip_sram = 0xFFFFFFFF;
for(auto& page_entry : pages) { for(auto& page_entry : pages) {
if (is_address_entry_capable(valid_ranges, page_entry.first) && (page_entry.first < expected_ep)) { if ( ((page_entry.first >= MAIN_RAM_START) && (page_entry.first < (MAIN_RAM_START + MAIN_RAM_END))) && (page_entry.first < expected_ep_main_ram) ) {
expected_ep = page_entry.first | 0x1; expected_ep_main_ram = page_entry.first | 0x1;
} else if ( ((page_entry.first >= XIP_SRAM_START) && (page_entry.first < (XIP_SRAM_START + XIP_SRAM_END))) && (page_entry.first < expected_ep_xip_sram) ) {
expected_ep_xip_sram = pages.begin()->first | 0x1;
} }
} }
if (eh.entry != expected_ep) { uint32_t expected_ep = (0xFFFFFFFF != expected_ep_main_ram) ? expected_ep_main_ram : expected_ep_xip_sram;
if (eh.entry == expected_ep_xip_sram) {
return fail(ERROR_INCOMPATIBLE, "B0/B1 Boot RAM errata prevents entry into XIP_SRAM\n");
} else if (eh.entry != expected_ep) {
return fail(ERROR_INCOMPATIBLE, "A RAM binary should have an entry point at the beginning: %08x (not %08x)\n", expected_ep, eh.entry); return fail(ERROR_INCOMPATIBLE, "A RAM binary should have an entry point at the beginning: %08x (not %08x)\n", expected_ep, eh.entry);
} }
static_assert(0 == (MAIN_RAM_START & (PAGE_SIZE - 1)), ""); static_assert(0 == (MAIN_RAM_START & (PAGE_SIZE - 1)), "");