mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-26 22:52:34 +02:00
Fix FEATURE_NO_ERASE chips and add test for them
New check was added to `check_block_eraser` in commit 0f389aea9e630c3b21547a5dd8dbe572a8502853 but it was not handling FEATURE_NO_ERASE chips. This patch fixes processing such chips and adds test to run write and verify with dummyflasher for FEATURE_NO_ERASE chips. Ticket: https://ticket.coreboot.org/issues/553 Change-Id: I582fe00da0715e9b5e92fcc9d15d5a90a2615117 Signed-off-by: Anastasia Klimchuk <aklm@flashrom.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/84203 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Peter Marheine <pmarheine@chromium.org>
This commit is contained in:
parent
d71e88ecfb
commit
b6b0eba310
15
flashrom.c
15
flashrom.c
@ -484,14 +484,15 @@ int check_block_eraser(const struct flashctx *flash, int k, int log)
|
|||||||
|
|
||||||
if (flash->mst->buses_supported & BUS_SPI) {
|
if (flash->mst->buses_supported & BUS_SPI) {
|
||||||
const uint8_t *opcode = spi_get_opcode_from_erasefn(eraser.block_erase);
|
const uint8_t *opcode = spi_get_opcode_from_erasefn(eraser.block_erase);
|
||||||
for (int i = 0; opcode[i]; i++) {
|
if (opcode)
|
||||||
if (!spi_probe_opcode(flash, opcode[i])) {
|
for (int i = 0; opcode[i]; i++) {
|
||||||
if (log)
|
if (!spi_probe_opcode(flash, opcode[i])) {
|
||||||
msg_cdbg("block erase function and layout found "
|
if (log)
|
||||||
"but SPI master doesn't support the function. ");
|
msg_cdbg("block erase function and layout found "
|
||||||
return 1;
|
"but SPI master doesn't support the function. ");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// TODO: Once erase functions are annotated with allowed buses, check that as well.
|
// TODO: Once erase functions are annotated with allowed buses, check that as well.
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -148,6 +148,14 @@ enum write_granularity {
|
|||||||
* other flash chips, such as the ENE KB9012 internal flash, work the opposite way.
|
* other flash chips, such as the ENE KB9012 internal flash, work the opposite way.
|
||||||
*/
|
*/
|
||||||
#define FEATURE_ERASED_ZERO (1 << 18)
|
#define FEATURE_ERASED_ZERO (1 << 18)
|
||||||
|
/*
|
||||||
|
* Feature indicates that the chip does not require erase before writing:
|
||||||
|
* write operations can set any bit to any value without first doing an erase,
|
||||||
|
* but bulk erase operations may still be supported.
|
||||||
|
*
|
||||||
|
* EEPROMs usually behave this way (compare to Flash, which requires erase),
|
||||||
|
* for example the ST M95M02.
|
||||||
|
*/
|
||||||
#define FEATURE_NO_ERASE (1 << 19)
|
#define FEATURE_NO_ERASE (1 << 19)
|
||||||
|
|
||||||
#define FEATURE_WRSR_EXT2 (1 << 20)
|
#define FEATURE_WRSR_EXT2 (1 << 20)
|
||||||
|
62
tests/chip.c
62
tests/chip.c
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <include/test.h>
|
#include <include/test.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
@ -132,6 +133,25 @@ static const struct flashchip chip_8MiB = {
|
|||||||
}},
|
}},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Chip expected to be processed with dummyflasher, so using real op functions. */
|
||||||
|
static const struct flashchip chip_no_erase = {
|
||||||
|
.vendor = "aklm&dummyflasher",
|
||||||
|
.total_size = 16 * 1024,
|
||||||
|
.tested = TEST_OK_PREW,
|
||||||
|
.read = SPI_CHIP_READ,
|
||||||
|
.write = SPI_CHIP_WRITE256,
|
||||||
|
.page_size = 256,
|
||||||
|
.feature_bits = FEATURE_NO_ERASE | FEATURE_ERASED_ZERO,
|
||||||
|
.block_erasers =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.eraseblocks = { {16 * 1024 * 1024, 1} },
|
||||||
|
/* Special erase fn for chips without erase capability. */
|
||||||
|
.block_erase = SPI_BLOCK_ERASE_EMULATION,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/* Setup the struct for W25Q128.V, all values come from flashchips.c */
|
/* Setup the struct for W25Q128.V, all values come from flashchips.c */
|
||||||
static const struct flashchip chip_W25Q128_V = {
|
static const struct flashchip chip_W25Q128_V = {
|
||||||
.vendor = "aklm&dummyflasher",
|
.vendor = "aklm&dummyflasher",
|
||||||
@ -384,6 +404,48 @@ void write_chip_with_dummyflasher_test_success(void **state)
|
|||||||
free(newcontents);
|
free(newcontents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_chip_feature_no_erase(void **state)
|
||||||
|
{
|
||||||
|
(void) state; /* unused */
|
||||||
|
|
||||||
|
static struct io_mock_fallback_open_state data = {
|
||||||
|
.noc = 0,
|
||||||
|
.paths = { NULL },
|
||||||
|
};
|
||||||
|
const struct io_mock chip_io = {
|
||||||
|
.fallback_open_state = &data,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flashrom_flashctx flashctx = { 0 };
|
||||||
|
struct flashrom_layout *layout;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tricking the dummyflasher by asking to emulate W25Q128FV but giving to it
|
||||||
|
* mock chip with FEATURE_NO_ERASE.
|
||||||
|
* As long as chip size is the same, this is fine.
|
||||||
|
*/
|
||||||
|
struct flashchip mock_chip = chip_no_erase;
|
||||||
|
const char *param_dup = "bus=spi,emulate=W25Q128FV";
|
||||||
|
|
||||||
|
setup_chip(&flashctx, &layout, &mock_chip, param_dup, &chip_io);
|
||||||
|
|
||||||
|
/* See comment in write_chip_test_success */
|
||||||
|
const char *const filename = "-";
|
||||||
|
unsigned long size = mock_chip.total_size * 1024;
|
||||||
|
uint8_t *const newcontents = malloc(size);
|
||||||
|
assert_non_null(newcontents);
|
||||||
|
|
||||||
|
printf("Write chip operation started.\n");
|
||||||
|
assert_int_equal(0, read_buf_from_file(newcontents, size, filename));
|
||||||
|
assert_int_equal(0, flashrom_image_write(&flashctx, newcontents, size, NULL));
|
||||||
|
assert_int_equal(0, flashrom_image_verify(&flashctx, newcontents, size));
|
||||||
|
printf("Write chip operation done.\n");
|
||||||
|
|
||||||
|
teardown(&layout);
|
||||||
|
|
||||||
|
free(newcontents);
|
||||||
|
}
|
||||||
|
|
||||||
void write_nonaligned_region_with_dummyflasher_test_success(void **state)
|
void write_nonaligned_region_with_dummyflasher_test_success(void **state)
|
||||||
{
|
{
|
||||||
(void) state; /* unused */
|
(void) state; /* unused */
|
||||||
|
@ -498,6 +498,7 @@ int main(int argc, char *argv[])
|
|||||||
cmocka_unit_test(read_chip_with_dummyflasher_test_success),
|
cmocka_unit_test(read_chip_with_dummyflasher_test_success),
|
||||||
cmocka_unit_test(write_chip_test_success),
|
cmocka_unit_test(write_chip_test_success),
|
||||||
cmocka_unit_test(write_chip_with_dummyflasher_test_success),
|
cmocka_unit_test(write_chip_with_dummyflasher_test_success),
|
||||||
|
cmocka_unit_test(write_chip_feature_no_erase),
|
||||||
cmocka_unit_test(write_nonaligned_region_with_dummyflasher_test_success),
|
cmocka_unit_test(write_nonaligned_region_with_dummyflasher_test_success),
|
||||||
cmocka_unit_test(verify_chip_test_success),
|
cmocka_unit_test(verify_chip_test_success),
|
||||||
cmocka_unit_test(verify_chip_with_dummyflasher_test_success),
|
cmocka_unit_test(verify_chip_with_dummyflasher_test_success),
|
||||||
|
@ -86,6 +86,7 @@ void read_chip_test_success(void **state);
|
|||||||
void read_chip_with_dummyflasher_test_success(void **state);
|
void read_chip_with_dummyflasher_test_success(void **state);
|
||||||
void write_chip_test_success(void **state);
|
void write_chip_test_success(void **state);
|
||||||
void write_chip_with_dummyflasher_test_success(void **state);
|
void write_chip_with_dummyflasher_test_success(void **state);
|
||||||
|
void write_chip_feature_no_erase(void **state);
|
||||||
void write_nonaligned_region_with_dummyflasher_test_success(void **state);
|
void write_nonaligned_region_with_dummyflasher_test_success(void **state);
|
||||||
void verify_chip_test_success(void **state);
|
void verify_chip_test_success(void **state);
|
||||||
void verify_chip_with_dummyflasher_test_success(void **state);
|
void verify_chip_with_dummyflasher_test_success(void **state);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user