mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-27 15:12:36 +02:00

This patch is doing few things: 1) Makes chip definitions static global so that they can be reused between test functions. 2) Promotes existing mock chip from 8KiB to 8MiB and eraseblocks are expanded accordingly. Old value of 8KiB was very small and it was confusing. Mock chip looks more realistic now. 3) Uses KiB and MiB macros from flash.h for mock chip definition 4) Renames CHIP_TOTAL_SIZE to MOCK_CHIP_SIZE to avoid confusion (there is also a W25Q128.V chip in the tests) 5) Makes chip definitions const so that every test can work on a fresh copy on the stack. BUG=b:181803212 TEST=builds and ninja test Change-Id: Ia9b5fc71e30610684e68e9aca9fb1970da8f840a Signed-off-by: Anastasia Klimchuk <aklm@chromium.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/57437 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Nico Huber <nico.h@gmx.de>
259 lines
7.0 KiB
C
259 lines
7.0 KiB
C
/*
|
|
* This file is part of the flashrom project.
|
|
*
|
|
* Copyright 2021 Google LLC
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; version 2 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <include/test.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "chipdrivers.h"
|
|
#include "flash.h"
|
|
#include "programmer.h"
|
|
|
|
#define MOCK_CHIP_SIZE (8*MiB)
|
|
|
|
static struct {
|
|
unsigned int unlock_calls; /* how many times unlock function was called */
|
|
uint8_t buf[MOCK_CHIP_SIZE]; /* buffer of total size of chip, to emulate a chip */
|
|
} g_chip_state = {
|
|
.unlock_calls = 0,
|
|
.buf = { 0 },
|
|
};
|
|
|
|
int read_chip(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
|
|
{
|
|
printf("Read chip called with start=0x%x, len=0x%x\n", start, len);
|
|
if (!g_chip_state.unlock_calls) {
|
|
printf("Error while reading chip: unlock was not called.\n");
|
|
return 1;
|
|
}
|
|
|
|
assert_in_range(start + len, 0, MOCK_CHIP_SIZE);
|
|
|
|
memcpy(buf, &g_chip_state.buf[start], len);
|
|
return 0;
|
|
}
|
|
|
|
int write_chip(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
|
|
{
|
|
printf("Write chip called with start=0x%x, len=0x%x\n", start, len);
|
|
if (!g_chip_state.unlock_calls) {
|
|
printf("Error while writing chip: unlock was not called.\n");
|
|
return 1;
|
|
}
|
|
|
|
assert_in_range(start + len, 0, MOCK_CHIP_SIZE);
|
|
|
|
memcpy(&g_chip_state.buf[start], buf, len);
|
|
return 0;
|
|
}
|
|
|
|
int unlock_chip(struct flashctx *flash)
|
|
{
|
|
printf("Unlock chip called\n");
|
|
g_chip_state.unlock_calls++;
|
|
|
|
if (g_chip_state.unlock_calls > 1) {
|
|
printf("Error: Unlock called twice\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int block_erase_chip(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen)
|
|
{
|
|
printf("Block erase called with blockaddr=0x%x, blocklen=0x%x\n", blockaddr, blocklen);
|
|
if (!g_chip_state.unlock_calls) {
|
|
printf("Error while erasing chip: unlock was not called.\n");
|
|
return 1;
|
|
}
|
|
|
|
assert_in_range(blockaddr + blocklen, 0, MOCK_CHIP_SIZE);
|
|
|
|
memset(&g_chip_state.buf[blockaddr], 0xff, blocklen);
|
|
return 0;
|
|
}
|
|
|
|
static void setup_chip(struct flashrom_flashctx *flash, struct flashrom_layout **layout,
|
|
struct flashchip *chip, const char *programmer_param)
|
|
{
|
|
flash->chip = chip;
|
|
|
|
g_chip_state.unlock_calls = 0;
|
|
|
|
printf("Creating layout with one included region... ");
|
|
assert_int_equal(0, flashrom_layout_new(layout));
|
|
/* One region which covers total size of chip. */
|
|
assert_int_equal(0, flashrom_layout_add_region(*layout, 0, chip->total_size * KiB - 1, "region"));
|
|
assert_int_equal(0, flashrom_layout_include_region(*layout, "region"));
|
|
|
|
flashrom_layout_set(flash, *layout);
|
|
printf("done\n");
|
|
|
|
/*
|
|
* We need some programmer (any), and dummy is a very good one,
|
|
* because it doesn't need any mocking. So no extra complexity
|
|
* from a programmer side, and test can focus on working with the chip.
|
|
*/
|
|
printf("Dummyflasher initialising with param=\"%s\"... ", programmer_param);
|
|
assert_int_equal(0, programmer_init(&programmer_dummy, programmer_param));
|
|
/* Assignment below normally happens while probing, but this test is not probing. */
|
|
flash->mst = ®istered_masters[0];
|
|
printf("done\n");
|
|
}
|
|
|
|
static void teardown(struct flashrom_layout **layout)
|
|
{
|
|
printf("Dummyflasher shutdown... ");
|
|
assert_int_equal(0, programmer_shutdown());
|
|
printf("done\n");
|
|
|
|
printf("Releasing layout... ");
|
|
flashrom_layout_release(*layout);
|
|
printf("done\n");
|
|
}
|
|
|
|
static const struct flashchip chip_8MiB = {
|
|
.vendor = "aklm",
|
|
.total_size = MOCK_CHIP_SIZE / KiB,
|
|
.tested = TEST_OK_PREW,
|
|
.read = read_chip,
|
|
.write = write_chip,
|
|
.unlock = unlock_chip,
|
|
.block_erasers =
|
|
{{
|
|
/* All blocks within total size of the chip. */
|
|
.eraseblocks = { {2 * MiB, 4} },
|
|
.block_erase = block_erase_chip,
|
|
}},
|
|
};
|
|
|
|
/* Setup the struct for W25Q128.V, all values come from flashchips.c */
|
|
static const struct flashchip chip_W25Q128_V = {
|
|
.vendor = "aklm&dummyflasher",
|
|
.total_size = 16 * 1024,
|
|
.tested = TEST_OK_PREW,
|
|
.read = spi_chip_read,
|
|
.write = spi_chip_write_256,
|
|
.unlock = spi_disable_blockprotect,
|
|
.block_erasers =
|
|
{
|
|
{
|
|
.eraseblocks = { {4 * 1024, 4096} },
|
|
.block_erase = spi_block_erase_20,
|
|
}, {
|
|
.eraseblocks = { {32 * 1024, 512} },
|
|
.block_erase = spi_block_erase_52,
|
|
}, {
|
|
.eraseblocks = { {64 * 1024, 256} },
|
|
.block_erase = spi_block_erase_d8,
|
|
}, {
|
|
.eraseblocks = { {16 * 1024 * 1024, 1} },
|
|
.block_erase = spi_block_erase_60,
|
|
}, {
|
|
.eraseblocks = { {16 * 1024 * 1024, 1} },
|
|
.block_erase = spi_block_erase_c7,
|
|
}
|
|
},
|
|
};
|
|
|
|
void erase_chip_test_success(void **state)
|
|
{
|
|
(void) state; /* unused */
|
|
|
|
struct flashrom_flashctx flash = { 0 };
|
|
struct flashrom_layout *layout;
|
|
struct flashchip mock_chip = chip_8MiB;
|
|
const char *param = ""; /* Default values for all params. */
|
|
|
|
setup_chip(&flash, &layout, &mock_chip, param);
|
|
|
|
printf("Erase chip operation started.\n");
|
|
assert_int_equal(0, do_erase(&flash));
|
|
printf("Erase chip operation done.\n");
|
|
|
|
teardown(&layout);
|
|
}
|
|
|
|
void erase_chip_with_dummyflasher_test_success(void **state)
|
|
{
|
|
(void) state; /* unused */
|
|
|
|
struct flashrom_flashctx flash = { 0 };
|
|
struct flashrom_layout *layout;
|
|
struct flashchip mock_chip = chip_W25Q128_V;
|
|
/*
|
|
* Dummyflasher is capable to emulate W25Q128.V, so we ask it to do this.
|
|
* Nothing to mock, dummy is taking care of this already.
|
|
*/
|
|
char *param_dup = strdup("bus=spi,emulate=W25Q128FV");
|
|
|
|
setup_chip(&flash, &layout, &mock_chip, param_dup);
|
|
|
|
printf("Erase chip operation started.\n");
|
|
assert_int_equal(0, do_erase(&flash));
|
|
printf("Erase chip operation done.\n");
|
|
|
|
teardown(&layout);
|
|
|
|
free(param_dup);
|
|
}
|
|
|
|
void read_chip_test_success(void **state)
|
|
{
|
|
(void) state; /* unused */
|
|
|
|
struct flashrom_flashctx flash = { 0 };
|
|
struct flashrom_layout *layout;
|
|
struct flashchip mock_chip = chip_8MiB;
|
|
const char *param = ""; /* Default values for all params. */
|
|
|
|
setup_chip(&flash, &layout, &mock_chip, param);
|
|
|
|
const char *const filename = "read_chip.test";
|
|
|
|
printf("Read chip operation started.\n");
|
|
assert_int_equal(0, do_read(&flash, filename));
|
|
printf("Read chip operation done.\n");
|
|
|
|
teardown(&layout);
|
|
}
|
|
|
|
void read_chip_with_dummyflasher_test_success(void **state)
|
|
{
|
|
(void) state; /* unused */
|
|
|
|
struct flashrom_flashctx flash = { 0 };
|
|
struct flashrom_layout *layout;
|
|
struct flashchip mock_chip = chip_W25Q128_V;
|
|
/*
|
|
* Dummyflasher is capable to emulate W25Q128.V, so we ask it to do this.
|
|
* Nothing to mock, dummy is taking care of this already.
|
|
*/
|
|
char *param_dup = strdup("bus=spi,emulate=W25Q128FV");
|
|
|
|
setup_chip(&flash, &layout, &mock_chip, param_dup);
|
|
|
|
const char *const filename = "read_chip.test";
|
|
|
|
printf("Read chip operation started.\n");
|
|
assert_int_equal(0, do_read(&flash, filename));
|
|
printf("Read chip operation done.\n");
|
|
|
|
teardown(&layout);
|
|
|
|
free(param_dup);
|
|
}
|