xref: /aosp_15_r20/external/flashrom/tests/chip.c (revision 0d6140be3aa665ecc836e8907834fcd3e3b018fc)
1 /*
2  * This file is part of the flashrom project.
3  *
4  * Copyright 2021 Google LLC
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * This file contains tests for operations on flash chip.
16  *
17  * Two flash chip test variants are used:
18  *
19  * 1) Mock chip state backed by `g_chip_state`.
20  * Example of test: erase_chip_test_success.
21  *
22  * 2) Mock chip operations backed by `dummyflasher` emulation.
23  * Dummyflasher controls chip state and emulates read/write/erase.
24  * `g_chip_state` is NOT used for this type of tests.
25  * Example of test: erase_chip_with_dummyflasher_test_success.
26  */
27 
28 #include <include/test.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 #include "tests.h"
34 #include "chipdrivers.h"
35 #include "flash.h"
36 #include "io_mock.h"
37 #include "libflashrom.h"
38 #include "programmer.h"
39 
40 #define MOCK_CHIP_SIZE (8*MiB)
41 #define MOCK_CHIP_CONTENT 0xCC /* 0x00 is a zeroed heap and 0xFF is an erased chip. */
42 
43 static struct {
44 	uint8_t buf[MOCK_CHIP_SIZE]; /* buffer of total size of chip, to emulate a chip */
45 } g_chip_state = {
46 	.buf = { 0 },
47 };
48 
read_chip(struct flashctx * flash,uint8_t * buf,unsigned int start,unsigned int len)49 static int read_chip(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
50 {
51 	printf("Read chip called with start=0x%x, len=0x%x\n", start, len);
52 
53 	assert_in_range(start + len, 0, MOCK_CHIP_SIZE);
54 
55 	memcpy(buf, &g_chip_state.buf[start], len);
56 	return 0;
57 }
58 
write_chip(struct flashctx * flash,const uint8_t * buf,unsigned int start,unsigned int len)59 static int write_chip(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
60 {
61 	printf("Write chip called with start=0x%x, len=0x%x\n", start, len);
62 
63 	assert_in_range(start + len, 0, MOCK_CHIP_SIZE);
64 
65 	memcpy(&g_chip_state.buf[start], buf, len);
66 	return 0;
67 }
68 
block_erase_chip(struct flashctx * flash,unsigned int blockaddr,unsigned int blocklen)69 static int block_erase_chip(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen)
70 {
71 	printf("Block erase called with blockaddr=0x%x, blocklen=0x%x\n", blockaddr, blocklen);
72 
73 	assert_in_range(blockaddr + blocklen, 0, MOCK_CHIP_SIZE);
74 
75 	memset(&g_chip_state.buf[blockaddr], 0xff, blocklen);
76 	return 0;
77 }
78 
setup_chip(struct flashrom_flashctx * flashctx,struct flashrom_layout ** layout,struct flashchip * chip,const char * programmer_param,const struct io_mock * io)79 static void setup_chip(struct flashrom_flashctx *flashctx, struct flashrom_layout **layout,
80 		struct flashchip *chip, const char *programmer_param, const struct io_mock *io)
81 {
82 	io_mock_register(io);
83 
84 	flashctx->chip = chip;
85 
86 	memset(g_chip_state.buf, MOCK_CHIP_CONTENT, sizeof(g_chip_state.buf));
87 
88 	printf("Creating layout with one included region... ");
89 	assert_int_equal(0, flashrom_layout_new(layout));
90 	/* One region which covers total size of chip. */
91 	assert_int_equal(0, flashrom_layout_add_region(*layout, 0, chip->total_size * KiB - 1, "region"));
92 	assert_int_equal(0, flashrom_layout_include_region(*layout, "region"));
93 
94 	flashrom_layout_set(flashctx, *layout);
95 	printf("done\n");
96 
97 	/*
98 	 * We need some programmer (any), and dummy is a very good one,
99 	 * because it doesn't need any mocking. So no extra complexity
100 	 * from a programmer side, and test can focus on working with the chip.
101 	 */
102 	printf("Dummyflasher initialising with param=\"%s\"... ", programmer_param);
103 	assert_int_equal(0, programmer_init(&programmer_dummy, programmer_param));
104 	/* Assignment below normally happens while probing, but this test is not probing. */
105 	flashctx->mst = &registered_masters[0];
106 	printf("done\n");
107 }
108 
teardown(struct flashrom_layout ** layout)109 static void teardown(struct flashrom_layout **layout)
110 {
111 	printf("Dummyflasher shutdown... ");
112 	assert_int_equal(0, programmer_shutdown());
113 	printf("done\n");
114 
115 	printf("Releasing layout... ");
116 	flashrom_layout_release(*layout);
117 	printf("done\n");
118 
119 	io_mock_register(NULL);
120 }
121 
122 extern write_func_t *g_test_write_injector;
123 extern read_func_t *g_test_read_injector;
124 extern erasefunc_t *g_test_erase_injector;
125 
126 static const struct flashchip chip_8MiB = {
127 	.vendor		= "aklm",
128 	.total_size	= MOCK_CHIP_SIZE / KiB,
129 	.tested		= TEST_OK_PREW,
130 	.read		= TEST_READ_INJECTOR,
131 	.write		= TEST_WRITE_INJECTOR,
132 	.block_erasers	=
133 	{{
134 		 /* All blocks within total size of the chip. */
135 		.eraseblocks = { {2 * MiB, 4} },
136 		.block_erase = TEST_ERASE_INJECTOR,
137 	 }},
138 };
139 
140 /* Chip expected to be processed with dummyflasher, so using real op functions. */
141 static const struct flashchip chip_no_erase = {
142 	.vendor		= "aklm&dummyflasher",
143 	.total_size	= 16 * 1024,
144 	.tested		= TEST_OK_PREW,
145 	.read		= SPI_CHIP_READ,
146 	.write		= SPI_CHIP_WRITE256,
147 	.page_size	= 256,
148 	.feature_bits   = FEATURE_NO_ERASE | FEATURE_ERASED_ZERO,
149 	.block_erasers  =
150 	{
151 		{
152 			.eraseblocks = { {16 * 1024 * 1024, 1} },
153 			/* Special erase fn for chips without erase capability. */
154 			.block_erase = SPI_BLOCK_ERASE_EMULATION,
155 		}
156 	},
157 };
158 
159 /* Setup the struct for W25Q128.V, all values come from flashchips.c */
160 static const struct flashchip chip_W25Q128_V = {
161 	.vendor		= "aklm&dummyflasher",
162 	.total_size	= 16 * 1024,
163 	.tested		= TEST_OK_PREW,
164 	.read		= SPI_CHIP_READ,
165 	.write		= SPI_CHIP_WRITE256,
166 	.page_size	= 256,
167 	.block_erasers  =
168 	{
169 		{
170 			.eraseblocks = { {4 * 1024, 4096} },
171 			.block_erase = SPI_BLOCK_ERASE_20,
172 		}, {
173 			.eraseblocks = { {32 * 1024, 512} },
174 			.block_erase = SPI_BLOCK_ERASE_52,
175 		}, {
176 			.eraseblocks = { {64 * 1024, 256} },
177 			.block_erase = SPI_BLOCK_ERASE_D8,
178 		}, {
179 			.eraseblocks = { {16 * 1024 * 1024, 1} },
180 			.block_erase = SPI_BLOCK_ERASE_60,
181 		}, {
182 			.eraseblocks = { {16 * 1024 * 1024, 1} },
183 			.block_erase = SPI_BLOCK_ERASE_C7,
184 		}
185 	},
186 };
187 
erase_chip_test_success(void ** state)188 void erase_chip_test_success(void **state)
189 {
190 	(void) state; /* unused */
191 
192 	static struct io_mock_fallback_open_state data = {
193 		.noc	= 0,
194 		.paths	= { SUSPEND_ANNOUNCED_FILE, NULL },
195 	};
196 	const struct io_mock chip_io = {
197 		.fallback_open_state = &data,
198 	};
199 
200 	g_test_write_injector = write_chip;
201 	g_test_read_injector = read_chip;
202 	g_test_erase_injector = block_erase_chip;
203 	struct flashrom_flashctx flashctx = { 0 };
204 	struct flashrom_layout *layout;
205 	struct flashchip mock_chip = chip_8MiB;
206 	const char *param = ""; /* Default values for all params. */
207 
208 	setup_chip(&flashctx, &layout, &mock_chip, param, &chip_io);
209 
210 	printf("Erase chip operation started.\n");
211 	assert_int_equal(0, flashrom_flash_erase(&flashctx));
212 	printf("Erase chip operation done.\n");
213 
214 	teardown(&layout);
215 }
216 
erase_chip_with_dummyflasher_test_success(void ** state)217 void erase_chip_with_dummyflasher_test_success(void **state)
218 {
219 	(void) state; /* unused */
220 
221 	static struct io_mock_fallback_open_state data = {
222 		.noc	= 0,
223 		.paths	= { NULL },
224 	};
225 	const struct io_mock chip_io = {
226 		.fallback_open_state = &data,
227 	};
228 
229 	struct flashrom_flashctx flashctx = { 0 };
230 	struct flashrom_layout *layout;
231 	struct flashchip mock_chip = chip_W25Q128_V;
232 	/*
233 	 * Dummyflasher is capable to emulate W25Q128.V, so we ask it to do this.
234 	 * Nothing to mock, dummy is taking care of this already.
235 	 */
236 	const char *param_dup = "bus=spi,emulate=W25Q128FV";
237 
238 	setup_chip(&flashctx, &layout, &mock_chip, param_dup, &chip_io);
239 
240 	printf("Erase chip operation started.\n");
241 	assert_int_equal(0, flashrom_flash_erase(&flashctx));
242 	printf("Erase chip operation done.\n");
243 
244 	teardown(&layout);
245 }
246 
read_chip_test_success(void ** state)247 void read_chip_test_success(void **state)
248 {
249 	(void) state; /* unused */
250 
251 	static struct io_mock_fallback_open_state data = {
252 		.noc	= 0,
253 		.paths	= { NULL },
254 	};
255 	const struct io_mock chip_io = {
256 		.fallback_open_state = &data,
257 	};
258 
259 	g_test_write_injector = write_chip;
260 	g_test_read_injector = read_chip;
261 	g_test_erase_injector = block_erase_chip;
262 	struct flashrom_flashctx flashctx = { 0 };
263 	struct flashrom_layout *layout;
264 	struct flashchip mock_chip = chip_8MiB;
265 	const char *param = ""; /* Default values for all params. */
266 
267 	setup_chip(&flashctx, &layout, &mock_chip, param, &chip_io);
268 
269 	const char *const filename = "read_chip.test";
270 	unsigned long size = mock_chip.total_size * 1024;
271 	unsigned char *buf = calloc(size, sizeof(unsigned char));
272 	assert_non_null(buf);
273 
274 	printf("Read chip operation started.\n");
275 	assert_int_equal(0, flashrom_image_read(&flashctx, buf, size));
276 	assert_int_equal(0, write_buf_to_file(buf, size, filename));
277 	printf("Read chip operation done.\n");
278 
279 	teardown(&layout);
280 
281 	free(buf);
282 }
283 
read_chip_with_dummyflasher_test_success(void ** state)284 void read_chip_with_dummyflasher_test_success(void **state)
285 {
286 	(void) state; /* unused */
287 
288 	static struct io_mock_fallback_open_state data = {
289 		.noc	= 0,
290 		.paths	= { NULL },
291 	};
292 	const struct io_mock chip_io = {
293 		.fallback_open_state = &data,
294 	};
295 
296 	struct flashrom_flashctx flashctx = { 0 };
297 	struct flashrom_layout *layout;
298 	struct flashchip mock_chip = chip_W25Q128_V;
299 	/*
300 	 * Dummyflasher is capable to emulate W25Q128.V, so we ask it to do this.
301 	 * Nothing to mock, dummy is taking care of this already.
302 	 */
303 	const char *param_dup = "bus=spi,emulate=W25Q128FV";
304 
305 	setup_chip(&flashctx, &layout, &mock_chip, param_dup, &chip_io);
306 
307 	const char *const filename = "read_chip.test";
308 	unsigned long size = mock_chip.total_size * 1024;
309 	unsigned char *buf = calloc(size, sizeof(unsigned char));
310 	assert_non_null(buf);
311 
312 	printf("Read chip operation started.\n");
313 	assert_int_equal(0, flashrom_image_read(&flashctx, buf, size));
314 	assert_int_equal(0, write_buf_to_file(buf, size, filename));
315 	printf("Read chip operation done.\n");
316 
317 	teardown(&layout);
318 
319 	free(buf);
320 }
321 
write_chip_test_success(void ** state)322 void write_chip_test_success(void **state)
323 {
324 	(void) state; /* unused */
325 
326 	static struct io_mock_fallback_open_state data = {
327 		.noc	= 0,
328 		.paths	= { NULL },
329 	};
330 	const struct io_mock chip_io = {
331 		.fallback_open_state = &data,
332 	};
333 
334 	g_test_write_injector = write_chip;
335 	g_test_read_injector = read_chip;
336 	g_test_erase_injector = block_erase_chip;
337 	struct flashrom_flashctx flashctx = { 0 };
338 	struct flashrom_layout *layout;
339 	struct flashchip mock_chip = chip_8MiB;
340 	const char *param = ""; /* Default values for all params. */
341 
342 	setup_chip(&flashctx, &layout, &mock_chip, param, &chip_io);
343 
344 	/*
345 	 * Providing filename "-" means content is taken from standard input.
346 	 * This doesn't change much because all file operations are mocked.
347 	 * However filename "-" makes a difference for
348 	 * flashrom.c#read_buf_from_file and allows to avoid mocking
349 	 * image_stat.st_size.
350 	 *
351 	 * Now this does mean test covers successful path only, but this test
352 	 * is designed to cover only successful write operation anyway.
353 	 *
354 	 * To cover error path of image_stat.st_size != flash size, filename
355 	 * needs to be provided and image_stat.st_size needs to be mocked.
356 	 */
357 	const char *const filename = "-";
358 	unsigned long size = mock_chip.total_size * 1024;
359 	uint8_t *const newcontents = malloc(size);
360 	assert_non_null(newcontents);
361 
362 	printf("Write chip operation started.\n");
363 	assert_int_equal(0, read_buf_from_file(newcontents, size, filename));
364 	assert_int_equal(0, flashrom_image_write(&flashctx, newcontents, size, NULL));
365 	printf("Write chip operation done.\n");
366 
367 	teardown(&layout);
368 
369 	free(newcontents);
370 }
371 
write_chip_with_dummyflasher_test_success(void ** state)372 void write_chip_with_dummyflasher_test_success(void **state)
373 {
374 	(void) state; /* unused */
375 
376 	static struct io_mock_fallback_open_state data = {
377 		.noc	= 0,
378 		.paths	= { NULL },
379 	};
380 	const struct io_mock chip_io = {
381 		.fallback_open_state = &data,
382 	};
383 
384 	struct flashrom_flashctx flashctx = { 0 };
385 	struct flashrom_layout *layout;
386 	struct flashchip mock_chip = chip_W25Q128_V;
387 	/*
388 	 * Dummyflasher is capable to emulate W25Q128.V, so we ask it to do this.
389 	 * Nothing to mock, dummy is taking care of this already.
390 	 */
391 	const char *param_dup = "bus=spi,emulate=W25Q128FV";
392 
393 	setup_chip(&flashctx, &layout, &mock_chip, param_dup, &chip_io);
394 
395 	/* See comment in write_chip_test_success */
396 	const char *const filename = "-";
397 	unsigned long size = mock_chip.total_size * 1024;
398 	uint8_t *const newcontents = malloc(size);
399 	assert_non_null(newcontents);
400 
401 	printf("Write chip operation started.\n");
402 	assert_int_equal(0, read_buf_from_file(newcontents, size, filename));
403 	assert_int_equal(0, flashrom_image_write(&flashctx, newcontents, size, NULL));
404 	printf("Write chip operation done.\n");
405 
406 	teardown(&layout);
407 
408 	free(newcontents);
409 }
410 
write_chip_feature_no_erase(void ** state)411 void write_chip_feature_no_erase(void **state)
412 {
413 	(void) state; /* unused */
414 
415 	static struct io_mock_fallback_open_state data = {
416 		.noc	= 0,
417 		.paths	= { NULL },
418 	};
419 	const struct io_mock chip_io = {
420 		.fallback_open_state = &data,
421 	};
422 
423 	struct flashrom_flashctx flashctx = { 0 };
424 	struct flashrom_layout *layout;
425 
426 	/*
427 	 * Tricking the dummyflasher by asking to emulate W25Q128FV but giving to it
428 	 * mock chip with FEATURE_NO_ERASE.
429 	 * As long as chip size is the same, this is fine.
430 	 */
431 	struct flashchip mock_chip = chip_no_erase;
432 	const char *param_dup = "bus=spi,emulate=W25Q128FV";
433 
434 	setup_chip(&flashctx, &layout, &mock_chip, param_dup, &chip_io);
435 
436 	/* See comment in write_chip_test_success */
437 	const char *const filename = "-";
438 	unsigned long size = mock_chip.total_size * 1024;
439 	uint8_t *const newcontents = malloc(size);
440 	assert_non_null(newcontents);
441 
442 	printf("Write chip operation started.\n");
443 	assert_int_equal(0, read_buf_from_file(newcontents, size, filename));
444 	assert_int_equal(0, flashrom_image_write(&flashctx, newcontents, size, NULL));
445 	assert_int_equal(0, flashrom_image_verify(&flashctx, newcontents, size));
446 	printf("Write chip operation done.\n");
447 
448 	teardown(&layout);
449 
450 	free(newcontents);
451 }
452 
write_nonaligned_region_with_dummyflasher_test_success(void ** state)453 void write_nonaligned_region_with_dummyflasher_test_success(void **state)
454 {
455 	(void) state; /* unused */
456 
457 	static struct io_mock_fallback_open_state data = {
458 		.noc	= 0,
459 		.paths	= { NULL },
460 	};
461 	const struct io_mock chip_io = {
462 		.fallback_open_state = &data,
463 	};
464 
465 	struct flashrom_flashctx flashctx = { 0 };
466 	struct flashrom_layout *layout;
467 	struct flashchip mock_chip = chip_W25Q128_V;
468 	const uint32_t mock_chip_size = mock_chip.total_size * KiB;
469 	/*
470 	 * Dummyflasher is capable to emulate W25Q128.V, so we ask it to do this.
471 	 * Nothing to mock, dummy is taking care of this already.
472 	 */
473 	const char *param_dup = "bus=spi,emulate=W25Q128FV";
474 
475 	/* FIXME: MOCK_CHIP_CONTENT is buggy within setup_chip, it should also
476 	 * not be either 0x00 or 0xFF as those are specific values related to
477 	 * either a erased chip or zero'ed heap thus ambigous.
478 	 */
479 #define MOCK_CHIP_SUBREGION_CONTENTS 0xCC
480 	/**
481 	 * Step 0 - Prepare newcontents as contiguous sample data bytes as follows:
482 	 * {MOCK_CHIP_SUBREGION_CONTENTS, [..]}.
483 	 */
484 	uint8_t *newcontents = calloc(1, mock_chip_size);
485 	assert_non_null(newcontents);
486 	memset(newcontents, MOCK_CHIP_SUBREGION_CONTENTS, mock_chip_size);
487 
488 	setup_chip(&flashctx, &layout, &mock_chip, param_dup, &chip_io);
489 	/* Expect to verify only the non-aligned write operation within the region. */
490 	flashrom_flag_set(&flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE, true);
491 	flashrom_flag_set(&flashctx, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, false);
492 
493 	/**
494 	 * Prepare mock chip content and release setup_chip() layout for our
495 	 * custom ones.
496 	 */
497 	assert_int_equal(0, flashrom_image_write(&flashctx, newcontents, mock_chip_size, NULL));
498 	flashrom_layout_release(layout);
499 
500 	/**
501 	 * Create region smaller than erase granularity of chip.
502 	 */
503 	printf("Creating custom region layout... ");
504 	assert_int_equal(0, flashrom_layout_new(&layout));
505 	printf("Adding and including region0... ");
506 	assert_int_equal(0, flashrom_layout_add_region(layout, 0, (1 * KiB), "region0"));
507 	assert_int_equal(0, flashrom_layout_include_region(layout, "region0"));
508 	flashrom_layout_set(&flashctx, layout);
509 	printf("Subregion layout configuration done.\n");
510 
511 	/**
512 	 * Step 1 - Modify newcontents as non-contiguous sample data bytes as follows:
513 	 * 0xAA 0xAA {MOCK_CHIP_SUBREGION_CONTENTS}, [..]}.
514 	 */
515 	printf("Subregion chip write op..\n");
516 	memset(newcontents, 0xAA, 2);
517 	assert_int_equal(0, flashrom_image_write(&flashctx, newcontents, mock_chip_size, NULL));
518 	printf("Subregion chip write op done.\n");
519 
520 	/**
521 	 * FIXME: A 'NULL' layout should indicate a default layout however this
522 	 * causes a crash for a unknown reason. For now prepare a new default
523 	 * layout of the entire chip. flashrom_layout_set(&flashctx, NULL); // use default layout.
524 	 */
525 	flashrom_layout_release(layout);
526 	assert_int_equal(0, flashrom_layout_new(&layout));
527 	assert_int_equal(0, flashrom_layout_add_region(layout, 0, mock_chip_size - 1, "entire"));
528 	assert_int_equal(0, flashrom_layout_include_region(layout, "entire"));
529 	flashrom_layout_set(&flashctx, layout);
530 
531 	/**
532 	 * Expect a verification pass that the previous content within the region, however
533 	 * outside the region write length, is untouched.
534 	 */
535 	printf("Entire chip verify op..\n");
536 	assert_int_equal(0, flashrom_image_verify(&flashctx, newcontents, mock_chip_size));
537 	printf("Entire chip verify op done.\n");
538 
539 	teardown(&layout);
540 	free(newcontents);
541 }
542 
verify_chip_fread(void * state,void * buf,size_t size,size_t len,FILE * fp)543 static size_t verify_chip_fread(void *state, void *buf, size_t size, size_t len, FILE *fp)
544 {
545 	/*
546 	 * Verify operation compares contents of the file vs contents on the chip.
547 	 * To emulate successful verification we emulate file contents to be the
548 	 * same as what is on the chip.
549 	 */
550 	memset(buf, MOCK_CHIP_CONTENT, len);
551 	return len;
552 }
553 
verify_chip_test_success(void ** state)554 void verify_chip_test_success(void **state)
555 {
556 	(void) state; /* unused */
557 
558 	static struct io_mock_fallback_open_state data = {
559 		.noc	= 0,
560 		.paths	= { NULL },
561 	};
562 	const struct io_mock verify_chip_io = {
563 		.iom_fread = verify_chip_fread,
564 		.fallback_open_state = &data,
565 	};
566 
567 	g_test_write_injector = write_chip;
568 	g_test_read_injector = read_chip;
569 	g_test_erase_injector = block_erase_chip;
570 	struct flashrom_flashctx flashctx = { 0 };
571 	struct flashrom_layout *layout;
572 	struct flashchip mock_chip = chip_8MiB;
573 	const char *param = ""; /* Default values for all params. */
574 
575 	setup_chip(&flashctx, &layout, &mock_chip, param, &verify_chip_io);
576 
577 	/* See comment in write_chip_test_success */
578 	const char *const filename = "-";
579 	unsigned long size = mock_chip.total_size * 1024;
580 	uint8_t *const newcontents = malloc(size);
581 	assert_non_null(newcontents);
582 
583 	printf("Verify chip operation started.\n");
584 	assert_int_equal(0, read_buf_from_file(newcontents, size, filename));
585 	assert_int_equal(0, flashrom_image_verify(&flashctx, newcontents, size));
586 	printf("Verify chip operation done.\n");
587 
588 	teardown(&layout);
589 
590 	free(newcontents);
591 }
592 
verify_chip_with_dummyflasher_test_success(void ** state)593 void verify_chip_with_dummyflasher_test_success(void **state)
594 {
595 	(void) state; /* unused */
596 
597 	static struct io_mock_fallback_open_state data = {
598 		.noc	= 0,
599 		.paths	= { NULL },
600 	};
601 	const struct io_mock verify_chip_io = {
602 		.iom_fread = verify_chip_fread,
603 		.fallback_open_state = &data,
604 	};
605 
606 	struct flashrom_flashctx flashctx = { 0 };
607 	struct flashrom_layout *layout;
608 	struct flashchip mock_chip = chip_W25Q128_V;
609 	/*
610 	 * Dummyflasher is capable to emulate W25Q128.V, so we ask it to do this.
611 	 * Nothing to mock, dummy is taking care of this already.
612 	 */
613 	const char *param_dup = "bus=spi,emulate=W25Q128FV";
614 
615 	setup_chip(&flashctx, &layout, &mock_chip, param_dup, &verify_chip_io);
616 
617 	/* See comment in write_chip_test_success */
618 	const char *const filename = "-";
619 	unsigned long size = mock_chip.total_size * 1024;
620 	uint8_t *const newcontents = malloc(size);
621 	assert_non_null(newcontents);
622 
623 	/*
624 	 * Dummyflasher controls chip state and fully emulates reads and writes,
625 	 * so to set up initial chip state we need to write on chip. Write
626 	 * operation takes content from file and writes on chip. File content is
627 	 * emulated in verify_chip_fread mock.
628 	 */
629 
630 	printf("Write chip operation started.\n");
631 	assert_int_equal(0, read_buf_from_file(newcontents, size, filename));
632 	assert_int_equal(0, flashrom_image_write(&flashctx, newcontents, size, NULL));
633 	printf("Write chip operation done.\n");
634 
635 	printf("Verify chip operation started.\n");
636 	assert_int_equal(0, flashrom_image_verify(&flashctx, newcontents, size));
637 	printf("Verify chip operation done.\n");
638 
639 	teardown(&layout);
640 
641 	free(newcontents);
642 }
643