xref: /aosp_15_r20/external/flashrom/tests/chip_wp.c (revision 0d6140be3aa665ecc836e8907834fcd3e3b018fc)
1*0d6140beSAndroid Build Coastguard Worker /*
2*0d6140beSAndroid Build Coastguard Worker  * This file is part of the flashrom project.
3*0d6140beSAndroid Build Coastguard Worker  *
4*0d6140beSAndroid Build Coastguard Worker  * Copyright (C) 2021 3mdeb Embedded Systems Consulting
5*0d6140beSAndroid Build Coastguard Worker  *
6*0d6140beSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify
7*0d6140beSAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License as published by
8*0d6140beSAndroid Build Coastguard Worker  * the Free Software Foundation; either version 2 of the License, or
9*0d6140beSAndroid Build Coastguard Worker  * (at your option) any later version.
10*0d6140beSAndroid Build Coastguard Worker  *
11*0d6140beSAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
12*0d6140beSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*0d6140beSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*0d6140beSAndroid Build Coastguard Worker  * GNU General Public License for more details.
15*0d6140beSAndroid Build Coastguard Worker  */
16*0d6140beSAndroid Build Coastguard Worker 
17*0d6140beSAndroid Build Coastguard Worker #include <include/test.h>
18*0d6140beSAndroid Build Coastguard Worker #include <stdio.h>
19*0d6140beSAndroid Build Coastguard Worker #include <string.h>
20*0d6140beSAndroid Build Coastguard Worker 
21*0d6140beSAndroid Build Coastguard Worker #include "chipdrivers.h"
22*0d6140beSAndroid Build Coastguard Worker #include "flash.h"
23*0d6140beSAndroid Build Coastguard Worker #include "libflashrom.h"
24*0d6140beSAndroid Build Coastguard Worker #include "programmer.h"
25*0d6140beSAndroid Build Coastguard Worker #include "tests.h"
26*0d6140beSAndroid Build Coastguard Worker 
unittest_print_cb(enum flashrom_log_level level,const char * fmt,va_list ap)27*0d6140beSAndroid Build Coastguard Worker static int unittest_print_cb(enum flashrom_log_level level, const char *fmt, va_list ap)
28*0d6140beSAndroid Build Coastguard Worker {
29*0d6140beSAndroid Build Coastguard Worker 	if (level > FLASHROM_MSG_INFO) return 0;
30*0d6140beSAndroid Build Coastguard Worker 	return vfprintf(stderr, fmt, ap);
31*0d6140beSAndroid Build Coastguard Worker }
32*0d6140beSAndroid Build Coastguard Worker 
33*0d6140beSAndroid Build Coastguard Worker /*
34*0d6140beSAndroid Build Coastguard Worker  * Tests in this file do not use any mocking, because using write-protect
35*0d6140beSAndroid Build Coastguard Worker  * emulation in dummyflasher programmer is sufficient
36*0d6140beSAndroid Build Coastguard Worker  */
37*0d6140beSAndroid Build Coastguard Worker 
38*0d6140beSAndroid Build Coastguard Worker #define LAYOUT_TAIL_REGION_START 0x1000
39*0d6140beSAndroid Build Coastguard Worker 
setup_chip(struct flashrom_flashctx * flash,struct flashrom_layout ** layout,struct flashchip * chip,const char * programmer_param)40*0d6140beSAndroid Build Coastguard Worker static void setup_chip(struct flashrom_flashctx *flash, struct flashrom_layout **layout,
41*0d6140beSAndroid Build Coastguard Worker 		       struct flashchip *chip, const char *programmer_param)
42*0d6140beSAndroid Build Coastguard Worker {
43*0d6140beSAndroid Build Coastguard Worker 	flash->chip = chip;
44*0d6140beSAndroid Build Coastguard Worker 
45*0d6140beSAndroid Build Coastguard Worker 	if (layout) {
46*0d6140beSAndroid Build Coastguard Worker 		const size_t tail_start = LAYOUT_TAIL_REGION_START;
47*0d6140beSAndroid Build Coastguard Worker 		const size_t tail_len = chip->total_size * KiB - 1;
48*0d6140beSAndroid Build Coastguard Worker 
49*0d6140beSAndroid Build Coastguard Worker 		assert_int_equal(0, flashrom_layout_new(layout));
50*0d6140beSAndroid Build Coastguard Worker 		assert_int_equal(0, flashrom_layout_add_region(*layout, 0, tail_start - 1, "head"));
51*0d6140beSAndroid Build Coastguard Worker 		assert_int_equal(0, flashrom_layout_add_region(*layout, tail_start, tail_len, "tail"));
52*0d6140beSAndroid Build Coastguard Worker 
53*0d6140beSAndroid Build Coastguard Worker 		flashrom_layout_set(flash, *layout);
54*0d6140beSAndroid Build Coastguard Worker 	}
55*0d6140beSAndroid Build Coastguard Worker 
56*0d6140beSAndroid Build Coastguard Worker 	flashrom_set_log_callback((flashrom_log_callback *)&unittest_print_cb);
57*0d6140beSAndroid Build Coastguard Worker 
58*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, programmer_init(&programmer_dummy, programmer_param));
59*0d6140beSAndroid Build Coastguard Worker 	/* Assignment below normally happens while probing, but this test is not probing. */
60*0d6140beSAndroid Build Coastguard Worker 	flash->mst = &registered_masters[0];
61*0d6140beSAndroid Build Coastguard Worker }
62*0d6140beSAndroid Build Coastguard Worker 
teardown(struct flashrom_layout ** layout)63*0d6140beSAndroid Build Coastguard Worker static void teardown(struct flashrom_layout **layout)
64*0d6140beSAndroid Build Coastguard Worker {
65*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, programmer_shutdown());
66*0d6140beSAndroid Build Coastguard Worker 	if (layout)
67*0d6140beSAndroid Build Coastguard Worker 		flashrom_layout_release(*layout);
68*0d6140beSAndroid Build Coastguard Worker }
69*0d6140beSAndroid Build Coastguard Worker 
70*0d6140beSAndroid Build Coastguard Worker /* Setup the struct for W25Q128.V, all values come from flashchips.c */
71*0d6140beSAndroid Build Coastguard Worker static const struct flashchip chip_W25Q128_V = {
72*0d6140beSAndroid Build Coastguard Worker 	.vendor		= "aklm&dummyflasher",
73*0d6140beSAndroid Build Coastguard Worker 	.total_size	= 16 * 1024,
74*0d6140beSAndroid Build Coastguard Worker 	.page_size	= 1024,
75*0d6140beSAndroid Build Coastguard Worker 	.tested		= TEST_OK_PREW,
76*0d6140beSAndroid Build Coastguard Worker 	.read		= SPI_CHIP_READ,
77*0d6140beSAndroid Build Coastguard Worker 	.write		= SPI_CHIP_WRITE256,
78*0d6140beSAndroid Build Coastguard Worker 	.unlock         = SPI_DISABLE_BLOCKPROTECT,
79*0d6140beSAndroid Build Coastguard Worker 	.feature_bits	= FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2 | FEATURE_WRSR2 | FEATURE_WRSR3,
80*0d6140beSAndroid Build Coastguard Worker 	.block_erasers  =
81*0d6140beSAndroid Build Coastguard Worker 	{
82*0d6140beSAndroid Build Coastguard Worker 		{
83*0d6140beSAndroid Build Coastguard Worker 			.eraseblocks = { {4 * 1024, 4096} },
84*0d6140beSAndroid Build Coastguard Worker 			.block_erase = SPI_BLOCK_ERASE_20,
85*0d6140beSAndroid Build Coastguard Worker 		}, {
86*0d6140beSAndroid Build Coastguard Worker 			.eraseblocks = { {32 * 1024, 512} },
87*0d6140beSAndroid Build Coastguard Worker 			.block_erase = SPI_BLOCK_ERASE_52,
88*0d6140beSAndroid Build Coastguard Worker 		}, {
89*0d6140beSAndroid Build Coastguard Worker 			.eraseblocks = { {64 * 1024, 256} },
90*0d6140beSAndroid Build Coastguard Worker 			.block_erase = SPI_BLOCK_ERASE_D8,
91*0d6140beSAndroid Build Coastguard Worker 		}, {
92*0d6140beSAndroid Build Coastguard Worker 			.eraseblocks = { {16 * 1024 * 1024, 1} },
93*0d6140beSAndroid Build Coastguard Worker 			.block_erase = SPI_BLOCK_ERASE_60,
94*0d6140beSAndroid Build Coastguard Worker 		}, {
95*0d6140beSAndroid Build Coastguard Worker 			.eraseblocks = { {16 * 1024 * 1024, 1} },
96*0d6140beSAndroid Build Coastguard Worker 			.block_erase = SPI_BLOCK_ERASE_C7,
97*0d6140beSAndroid Build Coastguard Worker 		}
98*0d6140beSAndroid Build Coastguard Worker 	},
99*0d6140beSAndroid Build Coastguard Worker 	.reg_bits	=
100*0d6140beSAndroid Build Coastguard Worker 	{
101*0d6140beSAndroid Build Coastguard Worker 		.srp    = {STATUS1, 7, RW},
102*0d6140beSAndroid Build Coastguard Worker 		.srl    = {STATUS2, 0, RW},
103*0d6140beSAndroid Build Coastguard Worker 		.bp     = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}},
104*0d6140beSAndroid Build Coastguard Worker 		.tb     = {STATUS1, 5, RW},
105*0d6140beSAndroid Build Coastguard Worker 		.sec    = {STATUS1, 6, RW},
106*0d6140beSAndroid Build Coastguard Worker 		.cmp    = {STATUS2, 6, RW},
107*0d6140beSAndroid Build Coastguard Worker 		.wps    = {STATUS3, 2, RW},
108*0d6140beSAndroid Build Coastguard Worker 	},
109*0d6140beSAndroid Build Coastguard Worker 	.decode_range	= DECODE_RANGE_SPI25,
110*0d6140beSAndroid Build Coastguard Worker };
111*0d6140beSAndroid Build Coastguard Worker 
112*0d6140beSAndroid Build Coastguard Worker /* Trying to set an unsupported WP range fails */
invalid_wp_range_dummyflasher_test_success(void ** state)113*0d6140beSAndroid Build Coastguard Worker void invalid_wp_range_dummyflasher_test_success(void **state)
114*0d6140beSAndroid Build Coastguard Worker {
115*0d6140beSAndroid Build Coastguard Worker 	(void) state; /* unused */
116*0d6140beSAndroid Build Coastguard Worker 
117*0d6140beSAndroid Build Coastguard Worker 	const char *param_dup = "bus=spi,emulate=W25Q128FV,hwwp=no";
118*0d6140beSAndroid Build Coastguard Worker 
119*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_flashctx flash = { 0 };
120*0d6140beSAndroid Build Coastguard Worker 	struct flashchip mock_chip = chip_W25Q128_V;
121*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_wp_cfg *wp_cfg;
122*0d6140beSAndroid Build Coastguard Worker 
123*0d6140beSAndroid Build Coastguard Worker 	setup_chip(&flash, NULL, &mock_chip, param_dup);
124*0d6140beSAndroid Build Coastguard Worker 
125*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_cfg_new(&wp_cfg));
126*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_set_mode(wp_cfg, FLASHROM_WP_MODE_HARDWARE);
127*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_set_range(wp_cfg, 0x1000, 0x1000);
128*0d6140beSAndroid Build Coastguard Worker 
129*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(FLASHROM_WP_ERR_RANGE_UNSUPPORTED, flashrom_wp_write_cfg(&flash, wp_cfg));
130*0d6140beSAndroid Build Coastguard Worker 
131*0d6140beSAndroid Build Coastguard Worker 	teardown(NULL);
132*0d6140beSAndroid Build Coastguard Worker 
133*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_cfg_release(wp_cfg);
134*0d6140beSAndroid Build Coastguard Worker }
135*0d6140beSAndroid Build Coastguard Worker 
136*0d6140beSAndroid Build Coastguard Worker /* Enabling hardware WP with a valid range succeeds */
set_wp_range_dummyflasher_test_success(void ** state)137*0d6140beSAndroid Build Coastguard Worker void set_wp_range_dummyflasher_test_success(void **state)
138*0d6140beSAndroid Build Coastguard Worker {
139*0d6140beSAndroid Build Coastguard Worker 	(void) state; /* unused */
140*0d6140beSAndroid Build Coastguard Worker 
141*0d6140beSAndroid Build Coastguard Worker 	const char *param_dup = "bus=spi,emulate=W25Q128FV,hwwp=no";
142*0d6140beSAndroid Build Coastguard Worker 
143*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_flashctx flash = { 0 };
144*0d6140beSAndroid Build Coastguard Worker 	struct flashchip mock_chip = chip_W25Q128_V;
145*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_wp_cfg *wp_cfg;
146*0d6140beSAndroid Build Coastguard Worker 
147*0d6140beSAndroid Build Coastguard Worker 	size_t start;
148*0d6140beSAndroid Build Coastguard Worker 	size_t len;
149*0d6140beSAndroid Build Coastguard Worker 
150*0d6140beSAndroid Build Coastguard Worker 	setup_chip(&flash, NULL, &mock_chip, param_dup);
151*0d6140beSAndroid Build Coastguard Worker 
152*0d6140beSAndroid Build Coastguard Worker 	/* Use last 4 KiB for a range. */
153*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_cfg_new(&wp_cfg));
154*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_set_mode(wp_cfg, FLASHROM_WP_MODE_HARDWARE);
155*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_set_range(wp_cfg, mock_chip.total_size * KiB - 4 * KiB, 4 * KiB);
156*0d6140beSAndroid Build Coastguard Worker 
157*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_write_cfg(&flash, wp_cfg));
158*0d6140beSAndroid Build Coastguard Worker 
159*0d6140beSAndroid Build Coastguard Worker 	/* Check that range was set correctly. */
160*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_read_cfg(wp_cfg, &flash));
161*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_get_range(&start, &len, wp_cfg);
162*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(16 * MiB - 4 * KiB, start);
163*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(4 * KiB, len);
164*0d6140beSAndroid Build Coastguard Worker 
165*0d6140beSAndroid Build Coastguard Worker 	teardown(NULL);
166*0d6140beSAndroid Build Coastguard Worker 
167*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_cfg_release(wp_cfg);
168*0d6140beSAndroid Build Coastguard Worker }
169*0d6140beSAndroid Build Coastguard Worker 
170*0d6140beSAndroid Build Coastguard Worker /* Enable hardware WP and verify that it can not be unset */
switch_wp_mode_dummyflasher_test_success(void ** state)171*0d6140beSAndroid Build Coastguard Worker void switch_wp_mode_dummyflasher_test_success(void **state)
172*0d6140beSAndroid Build Coastguard Worker {
173*0d6140beSAndroid Build Coastguard Worker 	(void) state; /* unused */
174*0d6140beSAndroid Build Coastguard Worker 
175*0d6140beSAndroid Build Coastguard Worker 	const char *param_dup = "bus=spi,emulate=W25Q128FV,hwwp=yes";
176*0d6140beSAndroid Build Coastguard Worker 
177*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_flashctx flash = { 0 };
178*0d6140beSAndroid Build Coastguard Worker 	struct flashchip mock_chip = chip_W25Q128_V;
179*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_wp_cfg *wp_cfg;
180*0d6140beSAndroid Build Coastguard Worker 
181*0d6140beSAndroid Build Coastguard Worker 	setup_chip(&flash, NULL, &mock_chip, param_dup);
182*0d6140beSAndroid Build Coastguard Worker 
183*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_cfg_new(&wp_cfg));
184*0d6140beSAndroid Build Coastguard Worker 
185*0d6140beSAndroid Build Coastguard Worker 	/* Check initial mode. */
186*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_read_cfg(wp_cfg, &flash));
187*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(FLASHROM_WP_MODE_DISABLED, flashrom_wp_get_mode(wp_cfg));
188*0d6140beSAndroid Build Coastguard Worker 
189*0d6140beSAndroid Build Coastguard Worker 	/* Enable hardware protection, which can't be unset because simulated
190*0d6140beSAndroid Build Coastguard Worker 	   HW WP pin is in active state. */
191*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_set_mode(wp_cfg, FLASHROM_WP_MODE_HARDWARE);
192*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_write_cfg(&flash, wp_cfg));
193*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_read_cfg(wp_cfg, &flash));
194*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(FLASHROM_WP_MODE_HARDWARE, flashrom_wp_get_mode(wp_cfg));
195*0d6140beSAndroid Build Coastguard Worker 
196*0d6140beSAndroid Build Coastguard Worker 	/* Check that write-protection mode can't be unset. */
197*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_set_mode(wp_cfg, FLASHROM_WP_MODE_DISABLED);
198*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(FLASHROM_WP_ERR_VERIFY_FAILED, flashrom_wp_write_cfg(&flash, wp_cfg));
199*0d6140beSAndroid Build Coastguard Worker 
200*0d6140beSAndroid Build Coastguard Worker 	/* Final mode should be "hardware". */
201*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_read_cfg(wp_cfg, &flash));
202*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(FLASHROM_WP_MODE_HARDWARE, flashrom_wp_get_mode(wp_cfg));
203*0d6140beSAndroid Build Coastguard Worker 
204*0d6140beSAndroid Build Coastguard Worker 	teardown(NULL);
205*0d6140beSAndroid Build Coastguard Worker 
206*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_cfg_release(wp_cfg);
207*0d6140beSAndroid Build Coastguard Worker }
208*0d6140beSAndroid Build Coastguard Worker 
209*0d6140beSAndroid Build Coastguard Worker /* WP state is decoded correctly from status registers */
wp_init_from_status_dummyflasher_test_success(void ** state)210*0d6140beSAndroid Build Coastguard Worker void wp_init_from_status_dummyflasher_test_success(void **state)
211*0d6140beSAndroid Build Coastguard Worker {
212*0d6140beSAndroid Build Coastguard Worker 	(void) state; /* unused */
213*0d6140beSAndroid Build Coastguard Worker 
214*0d6140beSAndroid Build Coastguard Worker 	/*
215*0d6140beSAndroid Build Coastguard Worker 	 * CMP  (S14) = 1 (range complement)
216*0d6140beSAndroid Build Coastguard Worker 	 * SRP1 (S8)  = 1
217*0d6140beSAndroid Build Coastguard Worker 	 * SRP0 (S7)  = 1 (`SRP1 == 1 && SRP0 == 1` is permanent mode)
218*0d6140beSAndroid Build Coastguard Worker 	 * SEC  (S6)  = 1 (base unit is a 4 KiB sector)
219*0d6140beSAndroid Build Coastguard Worker 	 * TB   (S5)  = 1 (bottom up range)
220*0d6140beSAndroid Build Coastguard Worker 	 * BP2  (S4)  = 0
221*0d6140beSAndroid Build Coastguard Worker 	 * BP1  (S3)  = 1
222*0d6140beSAndroid Build Coastguard Worker 	 * BP0  (S2)  = 1 (bp: BP2-0 == 0b011 == 3)
223*0d6140beSAndroid Build Coastguard Worker 	 *
224*0d6140beSAndroid Build Coastguard Worker 	 * Range coefficient is `2 ** (bp - 1)`, which is 4 in this case.
225*0d6140beSAndroid Build Coastguard Worker 	 * Multiplaying that by base unit gives 16 KiB protected region at the
226*0d6140beSAndroid Build Coastguard Worker 	 * bottom (start of the chip), which is then complemented.
227*0d6140beSAndroid Build Coastguard Worker 	 */
228*0d6140beSAndroid Build Coastguard Worker 	const char *param_dup = "bus=spi,emulate=W25Q128FV,spi_status=0x41ec";
229*0d6140beSAndroid Build Coastguard Worker 
230*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_flashctx flash = { 0 };
231*0d6140beSAndroid Build Coastguard Worker 	struct flashchip mock_chip = chip_W25Q128_V;
232*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_wp_cfg *wp_cfg;
233*0d6140beSAndroid Build Coastguard Worker 
234*0d6140beSAndroid Build Coastguard Worker 	size_t start;
235*0d6140beSAndroid Build Coastguard Worker 	size_t len;
236*0d6140beSAndroid Build Coastguard Worker 
237*0d6140beSAndroid Build Coastguard Worker 	setup_chip(&flash, NULL, &mock_chip, param_dup);
238*0d6140beSAndroid Build Coastguard Worker 
239*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_cfg_new(&wp_cfg));
240*0d6140beSAndroid Build Coastguard Worker 
241*0d6140beSAndroid Build Coastguard Worker 	/* Verify that WP mode reflects SPI status */
242*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_read_cfg(wp_cfg, &flash));
243*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(FLASHROM_WP_MODE_PERMANENT, flashrom_wp_get_mode(wp_cfg));
244*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_get_range(&start, &len, wp_cfg);
245*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0x004000, start);
246*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0xffc000, len);
247*0d6140beSAndroid Build Coastguard Worker 
248*0d6140beSAndroid Build Coastguard Worker 	teardown(NULL);
249*0d6140beSAndroid Build Coastguard Worker 
250*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_cfg_release(wp_cfg);
251*0d6140beSAndroid Build Coastguard Worker }
252*0d6140beSAndroid Build Coastguard Worker 
253*0d6140beSAndroid Build Coastguard Worker /* Enabled WP makes full chip erasure fail */
full_chip_erase_with_wp_dummyflasher_test_success(void ** state)254*0d6140beSAndroid Build Coastguard Worker void full_chip_erase_with_wp_dummyflasher_test_success(void **state)
255*0d6140beSAndroid Build Coastguard Worker {
256*0d6140beSAndroid Build Coastguard Worker 	(void) state; /* unused */
257*0d6140beSAndroid Build Coastguard Worker 
258*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_flashctx flash = { 0 };
259*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_layout *layout;
260*0d6140beSAndroid Build Coastguard Worker 	struct flashchip mock_chip = chip_W25Q128_V;
261*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_wp_cfg *wp_cfg;
262*0d6140beSAndroid Build Coastguard Worker 
263*0d6140beSAndroid Build Coastguard Worker 	const char *param_dup = "bus=spi,emulate=W25Q128FV,hwwp=yes";
264*0d6140beSAndroid Build Coastguard Worker 
265*0d6140beSAndroid Build Coastguard Worker 	setup_chip(&flash, &layout, &mock_chip, param_dup);
266*0d6140beSAndroid Build Coastguard Worker 	/* Layout regions are created by setup_chip(). */
267*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_layout_include_region(layout, "head"));
268*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_layout_include_region(layout, "tail"));
269*0d6140beSAndroid Build Coastguard Worker 
270*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_cfg_new(&wp_cfg));
271*0d6140beSAndroid Build Coastguard Worker 
272*0d6140beSAndroid Build Coastguard Worker 	/* Write protection takes effect only after changing SRP values, so at
273*0d6140beSAndroid Build Coastguard Worker 	   this stage WP is not enabled and erase completes successfully. */
274*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_flash_erase(&flash));
275*0d6140beSAndroid Build Coastguard Worker 
276*0d6140beSAndroid Build Coastguard Worker 	/* Write non-erased value to entire chip so that erase operations cannot
277*0d6140beSAndroid Build Coastguard Worker 	 * be optimized away. */
278*0d6140beSAndroid Build Coastguard Worker 	unsigned long size = flashrom_flash_getsize(&flash);
279*0d6140beSAndroid Build Coastguard Worker 	uint8_t *const contents = malloc(size);
280*0d6140beSAndroid Build Coastguard Worker 	assert_non_null(contents);
281*0d6140beSAndroid Build Coastguard Worker 	memset(contents, UNERASED_VALUE(&flash), size);
282*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_image_write(&flash, contents, size, NULL));
283*0d6140beSAndroid Build Coastguard Worker 	free(contents);
284*0d6140beSAndroid Build Coastguard Worker 
285*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_read_cfg(wp_cfg, &flash));
286*0d6140beSAndroid Build Coastguard Worker 
287*0d6140beSAndroid Build Coastguard Worker 	/* Hardware-protect first 4 KiB. */
288*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_set_range(wp_cfg, 0, 4 * KiB);
289*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_set_mode(wp_cfg, FLASHROM_WP_MODE_HARDWARE);
290*0d6140beSAndroid Build Coastguard Worker 
291*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_write_cfg(&flash, wp_cfg));
292*0d6140beSAndroid Build Coastguard Worker 
293*0d6140beSAndroid Build Coastguard Worker 	/* Try erasing the chip again. Now that WP is active, the first 4 KiB is
294*0d6140beSAndroid Build Coastguard Worker 	   protected and we're trying to erase the whole chip, erase should
295*0d6140beSAndroid Build Coastguard Worker 	   fail. */
296*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(1, flashrom_flash_erase(&flash));
297*0d6140beSAndroid Build Coastguard Worker 
298*0d6140beSAndroid Build Coastguard Worker 	teardown(&layout);
299*0d6140beSAndroid Build Coastguard Worker 
300*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_cfg_release(wp_cfg);
301*0d6140beSAndroid Build Coastguard Worker }
302*0d6140beSAndroid Build Coastguard Worker 
303*0d6140beSAndroid Build Coastguard Worker /* Enabled WP does not block erasing unprotected parts of the chip */
partial_chip_erase_with_wp_dummyflasher_test_success(void ** state)304*0d6140beSAndroid Build Coastguard Worker void partial_chip_erase_with_wp_dummyflasher_test_success(void **state)
305*0d6140beSAndroid Build Coastguard Worker {
306*0d6140beSAndroid Build Coastguard Worker 	(void) state; /* unused */
307*0d6140beSAndroid Build Coastguard Worker 
308*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_flashctx flash = { 0 };
309*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_layout *layout;
310*0d6140beSAndroid Build Coastguard Worker 	struct flashchip mock_chip = chip_W25Q128_V;
311*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_wp_cfg *wp_cfg;
312*0d6140beSAndroid Build Coastguard Worker 
313*0d6140beSAndroid Build Coastguard Worker 	const char *param_dup = "bus=spi,emulate=W25Q128FV,hwwp=yes";
314*0d6140beSAndroid Build Coastguard Worker 
315*0d6140beSAndroid Build Coastguard Worker 	setup_chip(&flash, &layout, &mock_chip, param_dup);
316*0d6140beSAndroid Build Coastguard Worker 	/* Layout region is created by setup_chip(). */
317*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_layout_include_region(layout, "tail"));
318*0d6140beSAndroid Build Coastguard Worker 
319*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_cfg_new(&wp_cfg));
320*0d6140beSAndroid Build Coastguard Worker 
321*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_read_cfg(wp_cfg, &flash));
322*0d6140beSAndroid Build Coastguard Worker 
323*0d6140beSAndroid Build Coastguard Worker 	/* Hardware-protect head region. */
324*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_set_mode(wp_cfg, FLASHROM_WP_MODE_HARDWARE);
325*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_set_range(wp_cfg, 0, LAYOUT_TAIL_REGION_START);
326*0d6140beSAndroid Build Coastguard Worker 
327*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_write_cfg(&flash, wp_cfg));
328*0d6140beSAndroid Build Coastguard Worker 
329*0d6140beSAndroid Build Coastguard Worker 	/* First 4 KiB is the only protected part of the chip and the region
330*0d6140beSAndroid Build Coastguard Worker 	   we included covers only unprotected part, so erase operation should
331*0d6140beSAndroid Build Coastguard Worker 	   succeed. */
332*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_flash_erase(&flash));
333*0d6140beSAndroid Build Coastguard Worker 
334*0d6140beSAndroid Build Coastguard Worker 	teardown(&layout);
335*0d6140beSAndroid Build Coastguard Worker 
336*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_cfg_release(wp_cfg);
337*0d6140beSAndroid Build Coastguard Worker }
338*0d6140beSAndroid Build Coastguard Worker 
339*0d6140beSAndroid Build Coastguard Worker /* Chip register values & masks are calculated correctly by WP */
wp_get_register_values_and_masks(void ** state)340*0d6140beSAndroid Build Coastguard Worker void wp_get_register_values_and_masks(void **state)
341*0d6140beSAndroid Build Coastguard Worker {
342*0d6140beSAndroid Build Coastguard Worker 	(void) state; /* unused */
343*0d6140beSAndroid Build Coastguard Worker 
344*0d6140beSAndroid Build Coastguard Worker 	/*
345*0d6140beSAndroid Build Coastguard Worker 	 * Test with range: start = 0x004000, lengh = 0xffc000
346*0d6140beSAndroid Build Coastguard Worker 	 *
347*0d6140beSAndroid Build Coastguard Worker 	 * WP should use these bit values:
348*0d6140beSAndroid Build Coastguard Worker 	 * WPS  (S17) = 0 (write protect scheme)
349*0d6140beSAndroid Build Coastguard Worker 	 * CMP  (S14) = 1 (range complement)
350*0d6140beSAndroid Build Coastguard Worker 	 * SRP1 (S8)  = 0
351*0d6140beSAndroid Build Coastguard Worker 	 * SRP0 (S7)  = 1 (`SRP1 == 1 && SRP0 == 1` is permanent mode)
352*0d6140beSAndroid Build Coastguard Worker 	 * SEC  (S6)  = 1 (base unit is a 4 KiB sector)
353*0d6140beSAndroid Build Coastguard Worker 	 * TB   (S5)  = 1 (bottom up range)
354*0d6140beSAndroid Build Coastguard Worker 	 * BP2  (S4)  = 0
355*0d6140beSAndroid Build Coastguard Worker 	 * BP1  (S3)  = 1
356*0d6140beSAndroid Build Coastguard Worker 	 * BP0  (S2)  = 1 (bp: BP2-0 == 0b011 == 3)
357*0d6140beSAndroid Build Coastguard Worker 	 *
358*0d6140beSAndroid Build Coastguard Worker 	 * Register values:
359*0d6140beSAndroid Build Coastguard Worker 	 * SR1 = 0b11101100 = 0xec
360*0d6140beSAndroid Build Coastguard Worker 	 * SR2 = 0b01000000 = 0x40
361*0d6140beSAndroid Build Coastguard Worker 	 * SR3 = 0b00000000 = 0x00
362*0d6140beSAndroid Build Coastguard Worker 	 *
363*0d6140beSAndroid Build Coastguard Worker 	 * Masks for WP bits in registers:
364*0d6140beSAndroid Build Coastguard Worker 	 * SR1: 0b11111100 = 0xfc
365*0d6140beSAndroid Build Coastguard Worker 	 * SR2: 0b01000000 = 0x41
366*0d6140beSAndroid Build Coastguard Worker 	 * SR3: 0b00000100 = 0x04
367*0d6140beSAndroid Build Coastguard Worker 	 *
368*0d6140beSAndroid Build Coastguard Worker 	 * All WP bits are RW so write masks should be the same as the bit masks.
369*0d6140beSAndroid Build Coastguard Worker 	 *
370*0d6140beSAndroid Build Coastguard Worker 	 */
371*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_flashctx flash = { 0 };
372*0d6140beSAndroid Build Coastguard Worker 	struct flashchip mock_chip = chip_W25Q128_V;
373*0d6140beSAndroid Build Coastguard Worker 	struct flashrom_wp_cfg *wp_cfg;
374*0d6140beSAndroid Build Coastguard Worker 
375*0d6140beSAndroid Build Coastguard Worker 	uint8_t reg_values[MAX_REGISTERS];
376*0d6140beSAndroid Build Coastguard Worker 	uint8_t bit_masks[MAX_REGISTERS];
377*0d6140beSAndroid Build Coastguard Worker 	uint8_t write_masks[MAX_REGISTERS];
378*0d6140beSAndroid Build Coastguard Worker 
379*0d6140beSAndroid Build Coastguard Worker 	setup_chip(&flash, NULL, &mock_chip, "bus=spi,emulate=W25Q128FV");
380*0d6140beSAndroid Build Coastguard Worker 
381*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, flashrom_wp_cfg_new(&wp_cfg));
382*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_set_mode(wp_cfg, FLASHROM_WP_MODE_HARDWARE);
383*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_set_range(wp_cfg, 0x004000, 0xffc000);
384*0d6140beSAndroid Build Coastguard Worker 
385*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0, wp_cfg_to_reg_values(reg_values, bit_masks, write_masks, &flash, wp_cfg));
386*0d6140beSAndroid Build Coastguard Worker 
387*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0xec, reg_values[STATUS1]);
388*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0x40, reg_values[STATUS2]);
389*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0x00, reg_values[STATUS3]);
390*0d6140beSAndroid Build Coastguard Worker 
391*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0xfc, bit_masks[STATUS1]);
392*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0x41, bit_masks[STATUS2]);
393*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0x04, bit_masks[STATUS3]);
394*0d6140beSAndroid Build Coastguard Worker 
395*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0xfc, write_masks[STATUS1]);
396*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0x41, write_masks[STATUS2]);
397*0d6140beSAndroid Build Coastguard Worker 	assert_int_equal(0x04, write_masks[STATUS3]);
398*0d6140beSAndroid Build Coastguard Worker 
399*0d6140beSAndroid Build Coastguard Worker 	teardown(NULL);
400*0d6140beSAndroid Build Coastguard Worker 
401*0d6140beSAndroid Build Coastguard Worker 	flashrom_wp_cfg_release(wp_cfg);
402*0d6140beSAndroid Build Coastguard Worker }
403