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
This commit is contained in:
Philippe Teuwen 2019-07-19 22:59:51 +02:00
parent 68aa9d631d
commit daae890667
6 changed files with 105 additions and 77 deletions

View file

@ -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)

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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.