Bug #605
openSome write paths verify without respecting --no-verify
0%
Description
From #520
If an erase is unaligned, there is a subsequent write to fill in data that should not have been erased. Some write functions implement a verify_range call, but not all functions look to verify the write was persisted (in fact, it only looks like the WRITE_JEDEC{1} verifies writes).
I've only visually instrumented the code, but this looks like it may still be the case.
Any time a write is issued to a chip that uses WRITE_JEDEC
/WRITE_JEDEC1
:
static int jedec_write_page(struct flashctx *flash, const uint8_t *src,
unsigned int start, unsigned int page_size)
{
int tries = 0, failed;
const uint8_t *s = src;
const chipaddr bios = flash->virtual_memory;
chipaddr dst = bios + start;
chipaddr d = dst;
for (; tries < MAX_REFLASH_TRIES; tries++) {
/* Issue JEDEC Start Program command */
start_program_jedec_common(flash);
/* transfer data from source to destination */
for (unsigned int i = 0; i < page_size; i++) {
/* If the data is 0xFF, don't program it */
if (*src != 0xFF)
chip_writeb(flash, *src, dst);
dst++;
src++;
}
toggle_ready_jedec(flash, dst - 1);
dst = d;
src = s;
failed = verify_range(flash, src, start, page_size); // This is not respecting flashctx->flags.verify_after_write
if (!failed)
break;
msg_cerr("retrying.\n");
}
if (failed) {
msg_cerr(" page 0x%" PRIxPTR " failed!\n", (d - bios) / page_size);
}
return failed;
}
static int write_byte_program_jedec_common(const struct flashctx *flash, const uint8_t *src,
chipaddr dst)
{
int tries = 0;
/* If the data is 0xFF, don't program it and don't complain. */
if (*src == 0xFF) {
return 0;
}
for (; tries < MAX_REFLASH_TRIES; tries++) {
const chipaddr bios = flash->virtual_memory;
/* Issue JEDEC Byte Program command */
start_program_jedec_common(flash);
/* transfer data from source to destination */
chip_writeb(flash, *src, dst);
toggle_ready_jedec(flash, bios);
if (chip_readb(flash, dst) == *src) // This is implicitly verifying and causing a retry without respecting flashctx->flags.verify_after_write
break;
}
return (tries >= MAX_REFLASH_TRIES) ? 1 : 0;
}
It looks like writes are verified regardless of whether flashrom was instructed to not verify them. I do not know if these are governed by a JEDEC spec that specifies that retries must be attempted.
I haven't verified other write functions/paths.
This probably isn't super important, but it would keep things consistent
Updated by Anastasia Klimchuk about 20 hours ago
I think you are right, verifying here is needed to implement retries - to make a decision whether more retries is needed.
I also thought, possibly that the people using jedec write are relying on the retry behaviour? Retry count is defined as 16, which is quite a lot. It can be disruptive to cut that off and stop retrying, if someone relies on that.
On a closer look, chips using WRITE_JEDEC/WRITE_JEDEC1 are on non-SPI buses (parallel, fwh) so maybe retries make sense for those specifically - I understand those often needed a special treatment. I also understand that they are less commonly used now - so even if this extra verification happens it doesn't affect the mainstream usage.
I am thinking, maybe this can be left as is.
In any case, checking jedec spec is a good idea, I will do this.
I will also check other write functions.