1 /*
2  * Copyright (c) 2023 Google Inc
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/drivers/flash.h>
10 #include <zephyr/drivers/flash/stm32_flash_api_extensions.h>
11 #include <zephyr/devicetree.h>
12 #include <zephyr/storage/flash_map.h>
13 
14 #define TEST_AREA	 storage_partition
15 #define TEST_AREA_OFFSET FIXED_PARTITION_OFFSET(TEST_AREA)
16 #define TEST_AREA_SIZE	 FIXED_PARTITION_SIZE(TEST_AREA)
17 #define TEST_AREA_MAX	 (TEST_AREA_OFFSET + TEST_AREA_SIZE)
18 #define TEST_AREA_DEVICE FIXED_PARTITION_DEVICE(TEST_AREA)
19 #define TEST_AREA_DEVICE_REG DT_REG_ADDR(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(TEST_AREA)))
20 
21 #define EXPECTED_SIZE 512
22 
23 static const struct device *const flash_dev = TEST_AREA_DEVICE;
24 
25 #if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
26 static const struct flash_parameters *flash_params;
27 static uint64_t sector_mask;
28 static uint8_t __aligned(4) expected[EXPECTED_SIZE];
29 
sector_mask_from_offset(const struct device * dev,off_t offset,size_t size,uint64_t * mask)30 static int sector_mask_from_offset(const struct device *dev, off_t offset,
31 				   size_t size, uint64_t *mask)
32 {
33 	struct flash_pages_info start_page, end_page;
34 
35 	if (flash_get_page_info_by_offs(dev, offset, &start_page) ||
36 	    flash_get_page_info_by_offs(dev, offset + size - 1, &end_page)) {
37 		return -EINVAL;
38 	}
39 
40 	*mask = ((1UL << (end_page.index + 1)) - 1) &
41 		~((1UL << start_page.index) - 1);
42 
43 	return 0;
44 }
45 #endif
46 
flash_stm32_setup(void)47 static void *flash_stm32_setup(void)
48 {
49 #if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
50 	struct flash_stm32_ex_op_sector_wp_out wp_status;
51 	struct flash_stm32_ex_op_sector_wp_in wp_request;
52 	uint8_t buf[EXPECTED_SIZE];
53 	bool is_buf_clear = true;
54 	int rc;
55 #endif
56 
57 	/* Check if tested region fits in flash. */
58 	zassert_true((TEST_AREA_OFFSET + EXPECTED_SIZE) < TEST_AREA_MAX,
59 		     "Test area exceeds flash size");
60 
61 	zassert_true(device_is_ready(flash_dev));
62 
63 #if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
64 	flash_params = flash_get_parameters(flash_dev);
65 
66 	rc = sector_mask_from_offset(flash_dev, TEST_AREA_OFFSET, EXPECTED_SIZE,
67 				     &sector_mask);
68 	zassert_equal(rc, 0, "Cannot get sector mask");
69 
70 	TC_PRINT("Sector mask for offset 0x%x size 0x%x is 0x%llx\n",
71 	       TEST_AREA_OFFSET, EXPECTED_SIZE, sector_mask);
72 
73 	/* Check if region is not write protected. */
74 	rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_SECTOR_WP,
75 			 (uintptr_t)NULL, &wp_status);
76 	zassert_equal(rc, 0, "Cannot get write protect status");
77 
78 	TC_PRINT("Protected sectors: 0x%llx\n", wp_status.protected_mask);
79 
80 	/* Remove protection if needed. */
81 	if (wp_status.protected_mask & sector_mask) {
82 		TC_PRINT("Removing write protection\n");
83 		wp_request.disable_mask = sector_mask;
84 		wp_request.enable_mask = 0;
85 
86 		rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_SECTOR_WP,
87 				 (uintptr_t)&wp_request, NULL);
88 		zassert_equal(rc, 0, "Cannot remove write protection");
89 	}
90 
91 	/* Check if test region is not empty. */
92 	rc = flash_read(flash_dev, TEST_AREA_OFFSET, buf, EXPECTED_SIZE);
93 	zassert_equal(rc, 0, "Cannot read flash");
94 
95 	/* Check if flash is cleared. */
96 	for (off_t i = 0; i < EXPECTED_SIZE; i++) {
97 		if (buf[i] != flash_params->erase_value) {
98 			is_buf_clear = false;
99 			break;
100 		}
101 	}
102 
103 	if (!is_buf_clear) {
104 		TC_PRINT("Test area is not empty. Clear it before continuing.\n");
105 		rc = flash_erase(flash_dev, TEST_AREA_OFFSET, EXPECTED_SIZE);
106 		zassert_equal(rc, 0, "Flash memory not properly erased");
107 	}
108 
109 	/* Fill test buffer with some pattern. */
110 	for (int i = 0; i < EXPECTED_SIZE; i++) {
111 		expected[i] = i;
112 	}
113 #endif
114 
115 	return NULL;
116 }
117 
118 #if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
ZTEST(flash_stm32,test_stm32_write_protection)119 ZTEST(flash_stm32, test_stm32_write_protection)
120 {
121 	struct flash_stm32_ex_op_sector_wp_in wp_request;
122 	uint8_t buf[EXPECTED_SIZE];
123 	int rc;
124 
125 	TC_PRINT("Enabling write protection...");
126 	wp_request.disable_mask = 0;
127 	wp_request.enable_mask = sector_mask;
128 
129 	rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_SECTOR_WP,
130 			 (uintptr_t)&wp_request, NULL);
131 	zassert_equal(rc, 0, "Cannot enable write protection");
132 	TC_PRINT("Done\n");
133 
134 	rc = flash_write(flash_dev, TEST_AREA_OFFSET, expected, EXPECTED_SIZE);
135 	zassert_not_equal(rc, 0, "Write suceeded");
136 	TC_PRINT("Write failed as expected, error %d\n", rc);
137 
138 	rc = flash_read(flash_dev, TEST_AREA_OFFSET, buf, EXPECTED_SIZE);
139 	zassert_equal(rc, 0, "Cannot read flash");
140 
141 	for (off_t i = 0; i < EXPECTED_SIZE; i++) {
142 		zassert_true(buf[i] == flash_params->erase_value,
143 			     "Buffer is not empty after write with protected "
144 			     "sectors");
145 	}
146 
147 	TC_PRINT("Disabling write protection...");
148 	wp_request.disable_mask = sector_mask;
149 	wp_request.enable_mask = 0;
150 
151 	rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_SECTOR_WP,
152 			 (uintptr_t)&wp_request, NULL);
153 	zassert_equal(rc, 0, "Cannot disable write protection");
154 	TC_PRINT("Done\n");
155 
156 	rc = flash_write(flash_dev, TEST_AREA_OFFSET, expected, EXPECTED_SIZE);
157 	zassert_equal(rc, 0, "Write failed");
158 	TC_PRINT("Write suceeded\n");
159 
160 	rc = flash_read(flash_dev, TEST_AREA_OFFSET, buf, EXPECTED_SIZE);
161 	zassert_equal(rc, 0, "Cannot read flash");
162 
163 	zassert_equal(memcmp(buf, expected, EXPECTED_SIZE), 0,
164 		      "Read data doesn't match expected data");
165 }
166 #endif
167 
168 #if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
ZTEST(flash_stm32,test_stm32_readout_protection_disabled)169 ZTEST(flash_stm32, test_stm32_readout_protection_disabled)
170 {
171 	struct flash_stm32_ex_op_rdp rdp_status;
172 	int rc;
173 
174 	rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_RDP, (uintptr_t)NULL,
175 			 &rdp_status);
176 	zassert_equal(rc, 0, "Failed to get RDP status");
177 	zassert_false(rdp_status.enable, "RDP is enabled");
178 	zassert_false(rdp_status.permanent, "RDP is enabled permanently");
179 
180 	TC_PRINT("RDP is disabled\n");
181 }
182 #endif
183 
184 #ifdef CONFIG_FLASH_STM32_BLOCK_REGISTERS
185 
186 #if defined(CONFIG_FLASH_STM32_WRITE_PROTECT) || defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
187 #error Block Register tests unable to run other tests, because of locked registers.
188 #endif
189 
190 int flash_stm32_option_bytes_lock(const struct device *dev, bool enable);
191 
flash_opt_locked(void)192 static bool flash_opt_locked(void)
193 {
194 	FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
195 
196 	return regs->OPTCR & FLASH_OPTCR_OPTLOCK;
197 }
198 
flash_cr_unlock(void)199 static void flash_cr_unlock(void)
200 {
201 	FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
202 
203 	regs->KEYR = FLASH_KEY1;
204 	regs->KEYR = FLASH_KEY2;
205 }
206 
flash_cr_locked(void)207 static bool flash_cr_locked(void)
208 {
209 	FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
210 
211 	return regs->CR & FLASH_CR_LOCK;
212 }
213 
ZTEST(flash_stm32,test_stm32_block_registers)214 ZTEST(flash_stm32, test_stm32_block_registers)
215 {
216 	/* Test OPT lock. */
217 	TC_PRINT("Unlocking OPT\n");
218 	flash_stm32_option_bytes_lock(flash_dev, false);
219 	zassert_false(flash_opt_locked(), "Unable to unlock OPT");
220 
221 	TC_PRINT("Blocking OPT\n");
222 	flash_ex_op(flash_dev, FLASH_STM32_EX_OP_BLOCK_OPTION_REG, (uintptr_t)NULL, NULL);
223 
224 	zassert_true(flash_opt_locked(), "Blocking OPT didn't lock OPT");
225 	TC_PRINT("Try to unlock blocked OPT\n");
226 	__set_FAULTMASK(1);
227 	flash_stm32_option_bytes_lock(flash_dev, false);
228 	/* Clear Bus Fault pending bit */
229 	SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
230 	__set_FAULTMASK(0);
231 	zassert_true(flash_opt_locked(), "OPT unlocked after being blocked");
232 
233 	/* Test CR lock. */
234 	zassert_true(flash_cr_locked(), "CR should be locked by default");
235 	TC_PRINT("Unlocking CR\n");
236 	flash_cr_unlock();
237 	zassert_false(flash_cr_locked(), "Unable to unlock CR");
238 	TC_PRINT("Blocking CR\n");
239 	flash_ex_op(flash_dev, FLASH_STM32_EX_OP_BLOCK_CONTROL_REG, (uintptr_t)NULL, NULL);
240 	zassert_true(flash_cr_locked(), "Blocking CR didn't lock CR");
241 	__set_FAULTMASK(1);
242 	TC_PRINT("Try to unlock blocked CR\n");
243 	flash_cr_unlock();
244 	/* Clear Bus Fault pending bit */
245 	SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
246 	__set_FAULTMASK(0);
247 	zassert_true(flash_cr_locked(), "CR unlocked after being blocked");
248 }
249 #endif
250 
251 ZTEST_SUITE(flash_stm32, NULL, flash_stm32_setup, NULL, NULL, NULL);
252