mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-03-03 11:36:34 +08:00
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:
parent
68aa9d631d
commit
daae890667
6 changed files with 105 additions and 77 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
107
client/flash.c
107
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue