/* write a new configuration item to config space in flash memory. * data will be 4-byte aligned when writing, but original length information * will be retained. * * @return 0 if successful, -2 when no space for storing data is available, * -1 when there is not enough space for the requested length */ int config_write(const uint32_t type, const uint32_t length, const void* data) { uint32_t *dst = (uint32_t*) config_find_item(CONFIG_UNSET); if(dst == NULL) return -2; if(dst + length + 3 >= (uint32_t*)(CONFIG_ADDRESS + CONFIG_SIZE)) return -1; flash_unlock(); /* write header information */ flash_program_word((uint32_t)(dst++), type); flash_program_word((uint32_t)(dst++), length); /* word-wise reading/writing */ uint32_t p = 0; for(; p + 3 < length; p+=sizeof(uint32_t)) { uint32_t v = *((uint32_t*)(data+p)); flash_program_word((uint32_t)(dst++), v); } /* read remainder of partial last word */ if(p < length) { uint32_t v = ((uint8_t*)data)[p++]; if(p < length) v = v | (((uint8_t*)data)[p++] << 8); if(p < length) v = v | (((uint8_t*)data)[p++] << 16); flash_program_word((uint32_t)(dst++), v); } flash_lock(); return 0; }
void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len) { for(int i = 0; i < len; i += 4) flash_program_word(baseaddr + i, *(u32*)(buf+i), FLASH_PROGRAM_X32); }
void storage_commit(void) { int i; uint32_t *w; // backup meta memcpy(meta_backup, (void *)FLASH_META_START, FLASH_META_LEN); flash_clear_status_flags(); flash_unlock(); // erase storage for (i = FLASH_META_SECTOR_FIRST; i <= FLASH_META_SECTOR_LAST; i++) { flash_erase_sector(i, FLASH_CR_PROGRAM_X32); } // modify storage memcpy(meta_backup + FLASH_META_DESC_LEN, "stor", 4); memcpy(meta_backup + FLASH_META_DESC_LEN + 4, storage_uuid, sizeof(storage_uuid)); memcpy(meta_backup + FLASH_META_DESC_LEN + 4 + sizeof(storage_uuid), &storage, sizeof(Storage)); // copy it back for (i = 0; i < FLASH_META_LEN / 4; i++) { w = (uint32_t *)(meta_backup + i * 4); flash_program_word(FLASH_META_START + i * 4, *w); } flash_lock(); // flash operation failed if (FLASH_SR & (FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR | FLASH_SR_WRPERR)) { layoutDialog(DIALOG_ICON_ERROR, NULL, NULL, NULL, "Storage failure", "detected.", NULL, "Please unplug", "the device.", NULL); for (;;) { } } }
void check_bootloader(void) { #if MEMORY_PROTECT uint8_t hash[32]; int r = memory_bootloader_hash(hash); if (!known_bootloader(r, hash)) { layoutDialog(&bmp_icon_error, NULL, NULL, NULL, _("Unknown bootloader"), _("detected."), NULL, _("Unplug your TREZOR"), _("contact our support."), NULL); shutdown(); } if (is_mode_unprivileged()) { return; } if (r == 32 && 0 == memcmp(hash, bl_hash, 32)) { // all OK -> done return; } // ENABLE THIS AT YOUR OWN RISK // ATTEMPTING TO OVERWRITE BOOTLOADER WITH UNSIGNED FIRMWARE MAY BRICK // YOUR DEVICE. layoutDialog(&bmp_icon_warning, NULL, NULL, NULL, _("Updating bootloader"), NULL, NULL, _("DO NOT UNPLUG"), _("YOUR TREZOR!"), NULL); // unlock sectors memory_write_unlock(); for (int tries = 0; tries < 10; tries++) { // replace bootloader flash_unlock(); for (int i = FLASH_BOOT_SECTOR_FIRST; i <= FLASH_BOOT_SECTOR_LAST; i++) { flash_erase_sector(i, FLASH_CR_PROGRAM_X32); } for (int i = 0; i < FLASH_BOOT_LEN / 4; i++) { const uint32_t *w = (const uint32_t *)(bl_data + i * 4); flash_program_word(FLASH_BOOT_START + i * 4, *w); } flash_lock(); // check whether the write was OK r = memory_bootloader_hash(hash); if (r == 32 && 0 == memcmp(hash, bl_hash, 32)) { // OK -> show info and halt layoutDialog(&bmp_icon_info, NULL, NULL, NULL, _("Update finished"), _("successfully."), NULL, _("Please reconnect"), _("the device."), NULL); shutdown(); return; } } // show info and halt layoutDialog(&bmp_icon_error, NULL, NULL, NULL, _("Bootloader update"), _("broken."), NULL, _("Unplug your TREZOR"), _("contact our support."), NULL); shutdown(); #endif }
void platform_save_config() { volatile unsigned *src, *dest; int n_sectors, conf_bytes; flash_unlock(); /* configrom is sectors 1 through 3, each 16k, * compute how many we need to erase */ conf_bytes = ((char*)&_econfigdata - (char*)&_sconfigdata); n_sectors = (conf_bytes + 16385) / 16386; flash_erase_sector(n_sectors, 2); for (dest = &_configdata_loadaddr, src = &_sconfigdata; src < &_econfigdata; src++, dest++) { flash_program_word((uint32_t)dest, *src); } flash_lock(); }
static u32 flash_program_data(u32 start_address, u8 *input_data, u16 num_elements) { u16 iter; u32 current_address = start_address; u32 page_address = start_address; u32 flash_status = 0; /*check if start_address is in proper range*/ if((start_address - FLASH_BASE) >= (FLASH_PAGE_SIZE * (FLASH_PAGE_NUM_MAX+1))) return 1; /*calculate current page address*/ if(start_address % FLASH_PAGE_SIZE) page_address -= (start_address % FLASH_PAGE_SIZE); flash_unlock(); /*Erasing page*/ flash_erase_page(page_address); flash_status = flash_get_status_flags(); if(flash_status != FLASH_SR_EOP) return flash_status; /*programming flash memory*/ for(iter=0; iter<num_elements; iter += 4) { /*programming word data*/ flash_program_word(current_address+iter, *((u32*)(input_data + iter))); flash_status = flash_get_status_flags(); if(flash_status != FLASH_SR_EOP) return flash_status; /*verify if correct data is programmed*/ if(*((u32*)(current_address+iter)) != *((u32*)(input_data + iter))) return FLASH_WRONG_DATA_WRITTEN; } return 0; }
void flash_func_write_word(uint32_t address, uint32_t word) { flash_program_word(address + APP_LOAD_ADDRESS, word); }
void flash_func_write_word(uint32_t address, uint32_t word) { flash_program_word(address + APP_LOAD_ADDRESS, word, FLASH_PROGRAM_X32); }