From daae8906675491d2b64bd7346f2fb41473243f82 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 19 Jul 2019 22:59:51 +0200 Subject: [PATCH] Bootrom & flasher changes: * use macros for versions * activate UNDERSTANDS_VERSION in bootrom * fix missing break; bug in bootrom * force flash_load to reject images > 256k if bootloader not up to date * move logic from flasher to flash --- CHANGELOG.md | 1 + bootrom/bootrom.c | 5 ++- client/flash.c | 107 +++++++++++++++++++++++++++++++++++++--------- client/flash.h | 3 +- client/flasher.c | 52 ++-------------------- include/pm3_cmd.h | 14 ++++-- 6 files changed, 105 insertions(+), 77 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 001a53a34..b38e12e3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix support for flashing 512K units with old bootrom (@slurdge/@doegox) - Fix 'hf mf sim' - wrong access rights to write key B in trailer (@McEloff) - Add option -i to flasher to query Pm3 for its memory size (@doegox) - Add support for flashing 512K units (@slurdge) diff --git a/bootrom/bootrom.c b/bootrom/bootrom.c index 030074177..1a3dafc12 100644 --- a/bootrom/bootrom.c +++ b/bootrom/bootrom.c @@ -125,8 +125,8 @@ void UsbPacketReceived(uint8_t *packet, int len) { arg0 = DEVICE_INFO_FLAG_BOOTROM_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM | DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH | - DEVICE_INFO_FLAG_UNDERSTANDS_CHIP_INFO; - //to add later: DEVICE_INFO_FLAG_UNDERSTANDS_VERSION + DEVICE_INFO_FLAG_UNDERSTANDS_CHIP_INFO | + DEVICE_INFO_FLAG_UNDERSTANDS_VERSION; if (common_area.flags.osimage_present) arg0 |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT; @@ -146,6 +146,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { arg0 = BL_VERSION_1_0_0; reply_old(CMD_BL_VERSION, arg0, 0, 0, 0, 0); } + break; case CMD_SETUP_WRITE: { /* The temporary write buffer of the embedded flash controller is mapped to the diff --git a/client/flash.c b/client/flash.c index 2c990a80a..316b53066 100644 --- a/client/flash.c +++ b/client/flash.c @@ -17,6 +17,8 @@ #define BLOCK_SIZE 0x200 +#define FLASHER_VERSION BL_VERSION_1_0_0 + static const uint8_t elf_ident[] = { 0x7f, 'E', 'L', 'F', ELFCLASS32, @@ -24,6 +26,42 @@ static const uint8_t elf_ident[] = { EV_CURRENT }; +static int chipid_to_mem_avail(uint32_t iChipID) { + int mem_avail = 0; + switch ((iChipID & 0xF00) >> 8) { + case 0: + mem_avail = 0; + break; + case 1: + mem_avail = 8; + break; + case 2: + mem_avail = 16; + break; + case 3: + mem_avail = 32; + break; + case 5: + mem_avail = 64; + break; + case 7: + mem_avail = 128; + break; + case 9: + mem_avail = 256; + break; + case 10: + mem_avail = 512; + break; + case 12: + mem_avail = 1024; + break; + case 14: + mem_avail = 2048; + } + return mem_avail; +} + // Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent // unaligned segments if needed static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, uint16_t num_phdrs, uint32_t flash_end) { @@ -339,9 +377,19 @@ static int wait_for_ack(PacketResponseNG *ack) { return 0; } +static void flash_suggest_update_bootloader(void) { + PrintAndLogEx(ERR, _RED_("It is recommended that you first update your bootloader alone,")); + PrintAndLogEx(ERR, _RED_("reboot the Proxmark3 then only update the main firmware") "\n"); +} + +static void flash_suggest_update_flasher(void) { + PrintAndLogEx(ERR, _RED_("It is recommended that you first update your flasher")); +} + // Go into flashing mode -int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *chipinfo) { +int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *max_allowed) { uint32_t state; + uint32_t chipinfo = 0; if (enter_bootloader(serial_port_name) < 0) return -1; @@ -353,7 +401,7 @@ int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t SendCommandBL(CMD_CHIP_INFO, 0, 0, 0, NULL, 0); PacketResponseNG resp; WaitForResponse(CMD_CHIP_INFO, &resp); - *chipinfo = resp.oldarg[0]; + chipinfo = resp.oldarg[0]; } int version = BL_VERSION_INVALID; @@ -362,32 +410,51 @@ int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t PacketResponseNG resp; WaitForResponse(CMD_BL_VERSION, &resp); version = resp.oldarg[0]; - if ((version < BL_VERSION_FIRST || version > BL_VERSION_LAST)) { + if ((BL_VERSION_MAJOR(version) < BL_VERSION_FIRST_MAJOR) || (BL_VERSION_MAJOR(version) > BL_VERSION_LAST_MAJOR)) { + // version info seems fishy version = BL_VERSION_INVALID; + PrintAndLogEx(ERR, _RED_("Note: Your bootloader reported an invalid version number")); + flash_suggest_update_bootloader(); + // + } else if (BL_VERSION_MAJOR(version) < BL_VERSION_MAJOR(FLASHER_VERSION)) { + PrintAndLogEx(ERR, _RED_("Note: Your bootloader reported a version older than this flasher")); + flash_suggest_update_bootloader(); + } else if (BL_VERSION_MAJOR(version) > BL_VERSION_MAJOR(FLASHER_VERSION)) { + PrintAndLogEx(ERR, _RED_("Note: Your bootloader is more recent than this flasher")); + flash_suggest_update_flasher(); } } else { PrintAndLogEx(ERR, _RED_("Note: Your bootloader does not understand the new CMD_BL_VERSION command")); - PrintAndLogEx(ERR, _RED_("It is recommended that you update your bootloader") "\n"); - } - - bool allow_512k_writes = false; - if (version == BL_VERSION_INVALID) { - PrintAndLogEx(ERR, _RED_("Note: Your bootloader reported an invalid version number")); - PrintAndLogEx(ERR, _RED_("It is recommended that you update your bootloader") "\n"); - } else if (version >= BL_VERSION_1_0_0) { - allow_512k_writes = true; + flash_suggest_update_bootloader(); } uint32_t flash_end = FLASH_START + AT91C_IFLASH_PAGE_SIZE * AT91C_IFLASH_NB_OF_PAGES / 2; - if ((((*chipinfo & 0xF00) >> 8) > 9) && allow_512k_writes) { - flash_end = FLASH_START + AT91C_IFLASH_PAGE_SIZE * AT91C_IFLASH_NB_OF_PAGES; + *max_allowed = 256; + + int mem_avail = chipid_to_mem_avail(chipinfo); + if (mem_avail != 0) { + PrintAndLogEx(NORMAL, "Available memory on this board: %uK bytes\n", mem_avail); + if (mem_avail > 256) { + if (BL_VERSION_MAJOR(version) < BL_VERSION_MAJOR(BL_VERSION_1_0_0)) { + PrintAndLogEx(ERR, _RED_("Your bootloader does not support writing above 256k")); + flash_suggest_update_bootloader(); + } else { + flash_end = FLASH_START + AT91C_IFLASH_PAGE_SIZE * AT91C_IFLASH_NB_OF_PAGES; + *max_allowed = mem_avail; + } + } + } else { + PrintAndLogEx(NORMAL, "Available memory on this board: "_RED_("UNKNOWN")"\n"); + PrintAndLogEx(ERR, _RED_("Note: Your bootloader does not understand the new CHIP_INFO command")); + flash_suggest_update_bootloader(); + } + + if (enable_bl_writes) { + PrintAndLogEx(INFO, "Permitted flash range: 0x%08x-0x%08x", FLASH_START, flash_end); + } else { + PrintAndLogEx(INFO, "Permitted flash range: 0x%08x-0x%08x", BOOTLOADER_END, flash_end); } - - PrintAndLogEx(INFO, "End of flash: 0x%08x", flash_end); - if (state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) { - // This command is stupid. Why the heck does it care which area we're - // flashing, as long as it's not the bootloader area? The mind boggles. PacketResponseNG resp; if (enable_bl_writes) { @@ -398,7 +465,7 @@ int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t return wait_for_ack(&resp); } else { PrintAndLogEx(ERR, _RED_("Note: Your bootloader does not understand the new START_FLASH command")); - PrintAndLogEx(ERR, _RED_("It is recommended that you update your bootloader") "\n"); + flash_suggest_update_bootloader(); } return 0; } diff --git a/client/flash.h b/client/flash.h index cc0387bf3..4f05029dc 100644 --- a/client/flash.h +++ b/client/flash.h @@ -38,10 +38,9 @@ typedef struct { } flash_file_t; int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_size); -int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *chipid); +int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *max_allowed); int flash_write(flash_file_t *ctx); void flash_free(flash_file_t *ctx); int flash_stop_flashing(void); - #endif diff --git a/client/flasher.c b/client/flasher.c index 25585e7cd..97e3d7a1c 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -41,42 +41,6 @@ static void usage(char *argv0) { #endif } -int chipid_to_mem_avail(uint32_t iChipID) { - int mem_avail = 0; - switch ((iChipID & 0xF00) >> 8) { - case 0: - mem_avail = 0; - break; - case 1: - mem_avail = 8; - break; - case 2: - mem_avail = 16; - break; - case 3: - mem_avail = 32; - break; - case 5: - mem_avail = 64; - break; - case 7: - mem_avail = 128; - break; - case 9: - mem_avail = 256; - break; - case 10: - mem_avail = 512; - break; - case 12: - mem_avail = 1024; - break; - case 14: - mem_avail = 2048; - } - return mem_avail; -} - int main(int argc, char **argv) { int can_write_bl = 0; int num_files = 0; @@ -126,28 +90,18 @@ int main(int argc, char **argv) { return -1; } - uint32_t chipid = 0; - res = flash_start_flashing(can_write_bl, serial_port_name, &chipid); + uint32_t max_allowed = 0; + res = flash_start_flashing(can_write_bl, serial_port_name, &max_allowed); if (res < 0) { ret = -1; goto finish; } - int mem_avail = chipid_to_mem_avail(chipid); - if (mem_avail != 0) { - PrintAndLogEx(NORMAL, "Available memory on this board: %uK bytes\n", mem_avail); - } else { - PrintAndLogEx(NORMAL, "Available memory on this board: "_RED_("UNKNOWN")"\n"); - PrintAndLogEx(ERR, _RED_("Note: Your bootloader does not understand the new CHIP_INFO command")); - PrintAndLogEx(ERR, _RED_("It is recommended that you update your bootloader") "\n"); - mem_avail = 256; //we default to a low value - } - if (info) goto finish; for (int i = 0 ; i < num_files; ++i) { - res = flash_load(&files[i], filenames[i], can_write_bl, mem_avail * ONE_KB); + res = flash_load(&files[i], filenames[i], can_write_bl, max_allowed * ONE_KB); if (res < 0) { ret = -1; goto finish; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 640a3e2bf..39edb2b61 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -540,11 +540,17 @@ typedef struct { /* Set if this device understands the version command */ #define DEVICE_INFO_FLAG_UNDERSTANDS_VERSION (1<<6) -// Different versions here. Each version should increse the number +#define BL_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) +#define BL_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) +#define BL_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) +#define BL_MAKE_VERSION(major, minor, patch) (((major) << 22) | ((minor) << 12) | (patch)) +// Some boundaries to distinguish valid versions from corrupted info +#define BL_VERSION_FIRST_MAJOR 1 +#define BL_VERSION_LAST_MAJOR 99 #define BL_VERSION_INVALID 0 -#define BL_VERSION_1_0_0 1 -#define BL_VERSION_FIRST BL_VERSION_1_0_0 -#define BL_VERSION_LAST BL_VERSION_1_0_0 +// Different versions here. Each version should increase the numbers +#define BL_VERSION_1_0_0 BL_MAKE_VERSION(1, 0, 0) + /* CMD_START_FLASH may have three arguments: start of area to flash, end of area to flash, optional magic.