1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 15:38:11 +00:00
trezor-firmware/storage/flash_common.c
2024-02-20 09:37:28 +01:00

140 lines
4.1 KiB
C

#include "flash_common.h"
#include "flash.h"
secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data);
secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data);
const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size);
static uint32_t flash_subarea_get_size(const flash_subarea_t *subarea) {
uint32_t size = 0;
for (int s = 0; s < subarea->num_sectors; s++) {
size += flash_sector_size(subarea->first_sector + s);
}
return size;
}
static secbool subarea_get_sector_and_offset(const flash_subarea_t *subarea,
uint32_t offset,
uint16_t *sector_out,
uint32_t *offset_out) {
uint32_t tmp_offset = offset;
uint16_t sector = subarea->first_sector;
// in correct subarea
for (int s = 0; s < subarea->num_sectors; s++) {
const uint32_t sector_size = flash_sector_size(sector);
if (tmp_offset < sector_size) {
*sector_out = sector;
*offset_out = tmp_offset;
return sectrue;
}
tmp_offset -= sector_size;
sector++;
}
return secfalse;
}
uint32_t flash_area_get_size(const flash_area_t *area) {
uint32_t size = 0;
for (int i = 0; i < area->num_subareas; i++) {
size += flash_subarea_get_size(&area->subarea[i]);
}
return size;
}
uint16_t flash_total_sectors(const flash_area_t *area) {
uint16_t total = 0;
for (int i = 0; i < area->num_subareas; i++) {
total += area->subarea[i].num_sectors;
}
return total;
}
int32_t flash_get_sector_num(const flash_area_t *area,
uint32_t sector_inner_num) {
uint16_t sector = 0;
uint16_t remaining = sector_inner_num;
for (int i = 0; i < area->num_subareas; i++) {
if (remaining < area->subarea[i].num_sectors) {
sector = area->subarea[i].first_sector + remaining;
return sector;
} else {
remaining -= area->subarea[i].num_sectors;
}
}
return -1;
}
static secbool get_sector_and_offset(const flash_area_t *area, uint32_t offset,
uint16_t *sector_out,
uint32_t *offset_out) {
uint32_t tmp_offset = offset;
for (int i = 0; i < area->num_subareas; i++) {
uint32_t sub_size = flash_subarea_get_size(&area->subarea[i]);
if (tmp_offset >= sub_size) {
tmp_offset -= sub_size;
continue;
}
return subarea_get_sector_and_offset(&area->subarea[i], tmp_offset,
sector_out, offset_out);
}
return secfalse;
}
const void *flash_area_get_address(const flash_area_t *area, uint32_t offset,
uint32_t size) {
uint16_t sector;
uint32_t sector_offset;
if (!get_sector_and_offset(area, offset, &sector, &sector_offset)) {
return NULL;
}
return flash_get_address(sector, sector_offset, size);
}
secbool flash_area_erase(const flash_area_t *area,
void (*progress)(int pos, int len)) {
return flash_area_erase_bulk(area, 1, progress);
}
secbool flash_area_write_byte(const flash_area_t *area, uint32_t offset,
uint8_t data) {
uint16_t sector;
uint32_t sector_offset;
if (get_sector_and_offset(area, offset, &sector, &sector_offset) != sectrue) {
return secfalse;
}
return flash_write_byte(sector, sector_offset, data);
}
secbool flash_area_write_word(const flash_area_t *area, uint32_t offset,
uint32_t data) {
uint16_t sector;
uint32_t sector_offset;
if (get_sector_and_offset(area, offset, &sector, &sector_offset) != sectrue) {
return secfalse;
}
return flash_write_word(sector, sector_offset, data);
}
secbool flash_area_write_block(const flash_area_t *area, uint32_t offset,
const flash_block_t block) {
if (!FLASH_IS_ALIGNED(offset)) {
return secfalse;
}
uint16_t sector;
uint32_t sector_offset;
if (sectrue != get_sector_and_offset(area, offset, &sector, &sector_offset)) {
return secfalse;
}
return flash_write_block(sector, sector_offset, block);
}