in common/util/util_spi.c [67:164]
static int do_update(const struct device *flash_device, off_t offset, uint8_t *buf, size_t len)
{
int ret = 0;
uint32_t flash_sz = flash_get_flash_size(flash_device);
uint32_t sector_sz = flash_get_write_block_size(flash_device);
uint32_t flash_offset = (uint32_t)offset;
uint32_t remain, op_addr = 0, end_sector_addr;
uint8_t *update_ptr = buf, *op_buf = NULL, *read_back_buf = NULL;
bool update_it = false;
if (flash_sz < flash_offset + len) {
printk("ERROR: update boundary exceeds flash size. (%d, %d, %u)\n", flash_sz,
flash_offset, len);
ret = -EINVAL;
goto end;
}
op_buf = (uint8_t *)malloc(sector_sz);
if (op_buf == NULL) {
printk("heap full %d %d\n", __LINE__, sector_sz);
ret = -EINVAL;
goto end;
}
read_back_buf = (uint8_t *)malloc(sector_sz);
if (read_back_buf == NULL) {
printk("heap full %d %d\n", __LINE__, sector_sz);
ret = -EINVAL;
goto end;
}
/* initial op_addr */
op_addr = (flash_offset / sector_sz) * sector_sz;
/* handle the start part which is not multiple of sector size */
if (flash_offset % sector_sz != 0) {
ret = flash_read(flash_device, op_addr, op_buf, sector_sz);
if (ret != 0)
goto end;
remain = MIN(sector_sz - (flash_offset % sector_sz), len);
memcpy((uint8_t *)op_buf + (flash_offset % sector_sz), update_ptr, remain);
ret = do_erase_write_verify(flash_device, op_addr, op_buf, read_back_buf,
sector_sz);
if (ret != 0)
goto end;
op_addr += sector_sz;
update_ptr += remain;
}
end_sector_addr = (flash_offset + len) / sector_sz * sector_sz;
/* handle body */
for (; op_addr < end_sector_addr;) {
ret = flash_read(flash_device, op_addr, op_buf, sector_sz);
if (ret != 0)
goto end;
if (memcmp(op_buf, update_ptr, sector_sz) != 0)
update_it = true;
if (update_it) {
ret = do_erase_write_verify(flash_device, op_addr, update_ptr,
read_back_buf, sector_sz);
if (ret != 0)
goto end;
}
op_addr += sector_sz;
update_ptr += sector_sz;
}
/* handle remain part */
if (end_sector_addr < flash_offset + len) {
ret = flash_read(flash_device, op_addr, op_buf, sector_sz);
if (ret != 0)
goto end;
remain = flash_offset + len - end_sector_addr;
memcpy((uint8_t *)op_buf, update_ptr, remain);
ret = do_erase_write_verify(flash_device, op_addr, op_buf, read_back_buf,
sector_sz);
if (ret != 0)
goto end;
op_addr += remain;
}
end:
if (op_buf != NULL)
free(op_buf);
if (read_back_buf != NULL)
free(read_back_buf);
return ret;
}