From 7bf3255a6cd6f901a8cc01306c5dd4794ed974cc Mon Sep 17 00:00:00 2001 From: slurdge Date: Thu, 18 Jul 2019 21:18:52 +0200 Subject: [PATCH] Flasher support for 512K flash A better way would be to cut the connecting function and flashing function and to move the whole mem computation to flash.c Working flasher --- CHANGELOG.md | 1 + bootrom/bootrom.c | 29 ++++++++++++++++++----------- client/flash.c | 35 ++++++++++++++++++----------------- client/flash.h | 2 +- client/flasher.c | 20 ++++++++++++++------ 5 files changed, 52 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bedc1dc04..cfa26a2b3 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] + - Add support for flashing 512K units (@slurdge) - Add a simple python tool to check the elf sizes (@slurdge) - Change: new keys for Vigik badges in default_keys.dict (@luminouw) - Add 'hw standalone' to jump to standalone mode from command line or script (@doegox) diff --git a/bootrom/bootrom.c b/bootrom/bootrom.c index 4e92bc95b..bda7de2c6 100644 --- a/bootrom/bootrom.c +++ b/bootrom/bootrom.c @@ -153,28 +153,35 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_FINISH_WRITE: { uint32_t *flash_mem = (uint32_t *)(&_flash_start); for (int j = 0; j < 2; j++) { - for (i = 0 + (64 * j); i < 64 + (64 * j); i++) { - flash_mem[i] = c->d.asDwords[i]; - } - uint32_t flash_address = arg0 + (0x100 * j); - + AT91PS_EFC efc_bank = AT91C_BASE_EFC0; + int offset = 0; + uint32_t page_n = (flash_address - ((uint32_t)flash_mem)) / AT91C_IFLASH_PAGE_SIZE; + if (page_n >= AT91C_IFLASH_NB_OF_PAGES / 2) { + page_n -= AT91C_IFLASH_NB_OF_PAGES / 2; + efc_bank = AT91C_BASE_EFC1; + // We need to offset the writes or it will not fill the correct bank write buffer. + offset = (AT91C_IFLASH_NB_OF_PAGES / 2) * AT91C_IFLASH_PAGE_SIZE / sizeof(uint32_t); + } + for (i = 0 + (64 * j); i < 64 + (64 * j); i++) { + flash_mem[offset+i] = c->d.asDwords[i]; + } + /* Check that the address that we are supposed to write to is within our allowed region */ if (((flash_address + AT91C_IFLASH_PAGE_SIZE - 1) >= end_addr) || (flash_address < start_addr)) { /* Disallow write */ dont_ack = 1; reply_old(CMD_NACK, 0, 0, 0, 0, 0); } else { - uint32_t page_n = (flash_address - ((uint32_t)flash_mem)) / AT91C_IFLASH_PAGE_SIZE; - /* Translate address to flash page and do flash, update here for the 512k part */ - AT91C_BASE_EFC0->EFC_FCR = MC_FLASH_COMMAND_KEY | - MC_FLASH_COMMAND_PAGEN(page_n) | - AT91C_MC_FCMD_START_PROG; + + efc_bank->EFC_FCR = MC_FLASH_COMMAND_KEY | + MC_FLASH_COMMAND_PAGEN(page_n) | + AT91C_MC_FCMD_START_PROG; } // Wait until flashing of page finishes uint32_t sr; - while (!((sr = AT91C_BASE_EFC0->EFC_FSR) & AT91C_MC_FRDY)); + while (!((sr = efc_bank->EFC_FSR) & AT91C_MC_FRDY)); if (sr & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) { dont_ack = 1; reply_old(CMD_NACK, sr, 0, 0, 0, 0); diff --git a/client/flash.c b/client/flash.c index e41b47fb0..a29d8d7b0 100644 --- a/client/flash.c +++ b/client/flash.c @@ -12,13 +12,6 @@ #define FLASH_START 0x100000 -#ifdef HAS_512_FLASH -# define FLASH_SIZE (512*1024) -#else -# define FLASH_SIZE (256*1024) -#endif - -#define FLASH_END (FLASH_START + FLASH_SIZE) #define BOOTLOADER_SIZE 0x2000 #define BOOTLOADER_END (FLASH_START + BOOTLOADER_SIZE) @@ -33,7 +26,7 @@ static const uint8_t elf_ident[] = { // 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) { +static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, uint16_t num_phdrs, uint32_t flash_end) { Elf32_Phdr *phdr = phdrs; flash_seg_t *seg; uint32_t last_end = 0; @@ -77,11 +70,11 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, PrintAndLogEx(ERR, "Error: PHDRs not sorted or overlap"); return -1; } - if (paddr < FLASH_START || (paddr + filesz) > FLASH_END) { + if (paddr < FLASH_START || (paddr + filesz) > flash_end) { PrintAndLogEx(ERR, "Error: PHDR is not contained in Flash"); return -1; } - if (vaddr >= FLASH_START && vaddr < FLASH_END && (flags & PF_W)) { + if (vaddr >= FLASH_START && vaddr < flash_end && (flags & PF_W)) { PrintAndLogEx(ERR, "Error: Flash VMA segment is writable"); return -1; } @@ -153,7 +146,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, } // Sanity check segments and check for bootloader writes -static int check_segs(flash_file_t *ctx, int can_write_bl) { +static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_end) { for (int i = 0; i < ctx->num_segs; i++) { flash_seg_t *seg = &ctx->segments[i]; @@ -165,7 +158,7 @@ static int check_segs(flash_file_t *ctx, int can_write_bl) { PrintAndLogEx(ERR, "Error: Segment is outside of flash bounds"); return -1; } - if (seg->start + seg->length > FLASH_END) { + if (seg->start + seg->length > flash_end) { PrintAndLogEx(ERR, "Error: Segment is outside of flash bounds"); return -1; } @@ -182,11 +175,12 @@ static int check_segs(flash_file_t *ctx, int can_write_bl) { } // Load an ELF file and prepare it for flashing -int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) { +int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_size) { FILE *fd; Elf32_Ehdr ehdr; Elf32_Phdr *phdrs = NULL; uint16_t num_phdrs; + uint32_t flash_end = FLASH_START + flash_size; int res; fd = fopen(name, "rb"); @@ -239,10 +233,10 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) { goto fail; } - res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs); + res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs, flash_end); if (res < 0) goto fail; - res = check_segs(ctx, can_write_bl); + res = check_segs(ctx, can_write_bl, flash_end); if (res < 0) goto fail; @@ -362,15 +356,22 @@ int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *chipinfo = resp.oldarg[0]; } + uint32_t flash_end = FLASH_START + AT91C_IFLASH_PAGE_SIZE * AT91C_IFLASH_NB_OF_PAGES / 2; + if (((*chipinfo & 0xF00) >> 8) > 9) { + flash_end = FLASH_START + AT91C_IFLASH_PAGE_SIZE * AT91C_IFLASH_NB_OF_PAGES; + } + + PrintAndLogEx(INFO, "End of flahs: 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) { - SendCommandBL(CMD_START_FLASH, FLASH_START, FLASH_END, START_FLASH_MAGIC, NULL, 0); + SendCommandBL(CMD_START_FLASH, FLASH_START, flash_end, START_FLASH_MAGIC, NULL, 0); } else { - SendCommandBL(CMD_START_FLASH, BOOTLOADER_END, FLASH_END, 0, NULL, 0); + SendCommandBL(CMD_START_FLASH, BOOTLOADER_END, flash_end, 0, NULL, 0); } return wait_for_ack(&resp); } else { diff --git a/client/flash.h b/client/flash.h index 7140de673..cc0387bf3 100644 --- a/client/flash.h +++ b/client/flash.h @@ -37,7 +37,7 @@ typedef struct { flash_seg_t *segments; } flash_file_t; -int flash_load(flash_file_t *ctx, const char *name, int can_write_bl); +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_write(flash_file_t *ctx); void flash_free(flash_file_t *ctx); diff --git a/client/flasher.c b/client/flasher.c index 94e2ef6ba..8b6a87bf8 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -21,6 +21,7 @@ #include "ui.h" #define MAX_FILES 4 +#define ONE_KB 1024 static void usage(char *argv0) { PrintAndLogEx(NORMAL, "Usage: %s [-b] image.elf [image.elf...]\n", argv0); @@ -76,6 +77,7 @@ int main(int argc, char **argv) { int num_files = 0; int res; flash_file_t files[MAX_FILES]; + char * filenames[MAX_FILES]; memset(files, 0, sizeof(files)); @@ -102,11 +104,7 @@ int main(int argc, char **argv) { return -1; } } else { - res = flash_load(&files[num_files], argv[i], can_write_bl); - if (res < 0) - return -1; - - PrintAndLogEx(NORMAL, ""); + filenames[num_files] = argv[i]; num_files++; } } @@ -132,9 +130,19 @@ int main(int argc, char **argv) { 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 } + + for (int i = 0 ; i < num_files; ++i){ + res = flash_load(&files[i], filenames[i], can_write_bl, mem_avail*ONE_KB); + if (res < 0) + return -1; + + PrintAndLogEx(NORMAL, ""); + } + PrintAndLogEx(SUCCESS, "\n" _BLUE_("Flashing...")); -// TODO check if enough space on Pm3 mem to write the given files + for (int i = 0; i < num_files; i++) { res = flash_write(&files[i]); if (res < 0)