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 = ®istered_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