blob: 4f75690979a088152d8a8b6553ebf17f94b25042 [file] [log] [blame]
Jakub Czapiga2b8d7212021-04-22 20:14:02 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <crc_byte.h>
4#include <spd_bin.h>
5#include <spd_cache.h>
6#include <stdlib.h>
7#include <string.h>
8#include <tests/test.h>
9#include <tests/lib/spd_cache_data.h>
10
11struct region_device flash_rdev_rw;
12static char *flash_buffer = NULL;
13static size_t flash_buffer_size = 0;
14
15static int setup_spd_cache(void **state)
16{
17 flash_buffer_size = SC_SPD_TOTAL_LEN + SC_CRC_LEN;
18 flash_buffer = malloc(flash_buffer_size);
19
20 if (flash_buffer == NULL) {
21 flash_buffer_size = 0;
22 return -1;
23 }
24
25 rdev_chain_mem_rw(&flash_rdev_rw, flash_buffer, flash_buffer_size);
26 return 0;
27}
28
29static int setup_spd_cache_test(void **state)
30{
31 memset(flash_buffer, 0xff, flash_buffer_size);
32 return 0;
33}
34
35static int teardown_spd_cache(void **state)
36{
37 rdev_chain_mem_rw(&flash_rdev_rw, NULL, 0);
38 free(flash_buffer);
39 flash_buffer = NULL;
40 flash_buffer_size = 0;
41 return 0;
42}
43
44
Patrick Georgice55ca22021-06-09 18:37:42 +020045int fmap_locate_area_as_rdev(const char *name, struct region_device *area)
Jakub Czapiga2b8d7212021-04-22 20:14:02 +020046{
47 return rdev_chain(area, &flash_rdev_rw, 0, flash_buffer_size);
48}
49
50/* This test verifies if load_spd_cache() correctly loads spd_cache pointer and size
Patrick Georgice55ca22021-06-09 18:37:42 +020051 from provided region_device. Memory region device is returned by our
52 fmap_locate_area_as_rdev() override. */
Jakub Czapiga2b8d7212021-04-22 20:14:02 +020053static void test_load_spd_cache(void **state)
54{
55 uint8_t *spd_cache;
56 size_t spd_cache_sz;
57
58 assert_int_equal(CB_SUCCESS, load_spd_cache(&spd_cache, &spd_cache_sz));
59 assert_ptr_equal(flash_buffer, spd_cache);
60 assert_int_equal(SC_SPD_TOTAL_LEN + SC_CRC_LEN, spd_cache_sz);
61}
62
63static void calc_spd_cache_crc(uint8_t *spd_cache)
64{
65 *(uint16_t *)(spd_cache + SC_CRC_OFFSET) =
66 CRC(spd_cache, SC_SPD_TOTAL_LEN, crc16_byte);
67}
68
69__attribute__((unused))
70static void fill_spd_cache_ddr3(uint8_t *spd_cache, size_t spd_cache_sz)
71{
72 assert_true(spd_cache_sz >= (spd_data_ddr3_1_sz + sizeof(uint16_t)));
73
74 memcpy(spd_cache, spd_data_ddr3_1, spd_data_ddr3_1_sz);
75 memset(spd_cache + spd_data_ddr3_1_sz, 0, spd_cache_sz - spd_data_ddr3_1_sz);
76 calc_spd_cache_crc(spd_cache);
77}
78
79__attribute__((unused))
80static void fill_spd_cache_ddr4(uint8_t *spd_cache, size_t spd_cache_sz)
81{
82 assert_true(spd_cache_sz >=
83 (spd_data_ddr4_1_sz + spd_data_ddr4_2_sz + sizeof(uint16_t)));
84
85 memcpy(spd_cache, spd_data_ddr4_1, spd_data_ddr4_1_sz);
86 memcpy(spd_cache + spd_data_ddr4_1_sz, spd_data_ddr4_2, spd_data_ddr4_2_sz);
87 memset(spd_cache + spd_data_ddr4_1_sz + spd_data_ddr4_2_sz, 0,
88 spd_cache_sz - (spd_data_ddr4_1_sz + spd_data_ddr4_2_sz));
89 calc_spd_cache_crc(spd_cache);
90}
91
92static void test_spd_fill_from_cache(void **state)
93{
94 struct spd_block blk;
95 uint8_t *spd_cache;
96 size_t spd_cache_sz;
97 assert_int_equal(CB_SUCCESS, load_spd_cache(&spd_cache, &spd_cache_sz));
98
99 /* Empty spd cache */
100 assert_int_equal(CB_ERR, spd_fill_from_cache(spd_cache, &blk));
101
102#if __TEST_SPD_CACHE_DDR == 3
103 fill_spd_cache_ddr3(spd_cache, spd_cache_sz);
104#elif __TEST_SPD_CACHE_DDR == 4
105 fill_spd_cache_ddr4(spd_cache, spd_cache_sz);
106#endif
107 assert_int_equal(CB_SUCCESS, spd_fill_from_cache(spd_cache, &blk));
108}
109
110
111static void test_spd_cache_is_valid(void **state)
112{
113 uint8_t *spd_cache;
114 size_t spd_cache_sz;
115 assert_int_equal(CB_SUCCESS, load_spd_cache(&spd_cache, &spd_cache_sz));
116
117 /* Empty, incorrect SPD */
118 assert_false(spd_cache_is_valid(spd_cache, spd_cache_sz));
119
120#if __TEST_SPD_CACHE_DDR == 3
121 fill_spd_cache_ddr3(spd_cache, spd_cache_sz);
122#elif __TEST_SPD_CACHE_DDR == 4
123 fill_spd_cache_ddr4(spd_cache, spd_cache_sz);
124#endif
125 assert_true(spd_cache_is_valid(spd_cache, spd_cache_sz));
126}
127
128
129/* Used for setting `sn` parameter value */
130static u32 get_spd_sn_ret_sn[SC_SPD_NUMS] = { 0 };
131static size_t get_spd_sn_ret_sn_idx = 0;
132/* Implementation for testing purposes. */
133enum cb_err get_spd_sn(u8 addr, u32 *sn)
134{
135 *sn = get_spd_sn_ret_sn[get_spd_sn_ret_sn_idx];
136 get_spd_sn_ret_sn_idx = (get_spd_sn_ret_sn_idx + 1) % ARRAY_SIZE(get_spd_sn_ret_sn);
137
138 return mock_type(enum cb_err);
139}
140
141static void get_sn_from_spd_cache(uint8_t *spd_cache, u32 arr[])
142{
143 for (int i = 0; i < SC_SPD_NUMS; ++i)
144 arr[i] = *(u32 *)(spd_cache + SC_SPD_OFFSET(i) + DDR4_SPD_SN_OFF);
145}
146
147/* check_if_dimm_changed() has is used only with DDR4, so there tests are not used for DDR3 */
148__attribute__((unused))
149static void test_check_if_dimm_changed_not_changed(void **state)
150{
151 uint8_t *spd_cache;
152 size_t spd_cache_sz;
Jakub Czapigad5433af2021-05-17 10:53:22 +0200153 struct spd_block blk = { .addr_map = {0}, .spd_array = {0}, .len = 0 };
Jakub Czapiga2b8d7212021-04-22 20:14:02 +0200154
155 assert_int_equal(CB_SUCCESS, load_spd_cache(&spd_cache, &spd_cache_sz));
156 fill_spd_cache_ddr4(spd_cache, spd_cache_sz);
157 assert_int_equal(CB_SUCCESS, spd_fill_from_cache(spd_cache, &blk));
158
159 get_sn_from_spd_cache(spd_cache, get_spd_sn_ret_sn);
160 get_spd_sn_ret_sn_idx = 0;
161 will_return_count(get_spd_sn, CB_SUCCESS, SC_SPD_NUMS);
162 assert_false(check_if_dimm_changed(spd_cache, &blk));
163}
164
165__attribute__((unused))
166static void test_check_if_dimm_changed_sn_error(void **state)
167{
168 uint8_t *spd_cache;
169 size_t spd_cache_sz;
Jakub Czapigad5433af2021-05-17 10:53:22 +0200170 struct spd_block blk = { .addr_map = {0}, .spd_array = {0}, .len = 0 };
Jakub Czapiga2b8d7212021-04-22 20:14:02 +0200171
172 assert_int_equal(CB_SUCCESS, load_spd_cache(&spd_cache, &spd_cache_sz));
173 fill_spd_cache_ddr4(spd_cache, spd_cache_sz);
174 assert_int_equal(CB_SUCCESS, spd_fill_from_cache(spd_cache, &blk));
175
176 /* Simulate error */
177 will_return_count(get_spd_sn, CB_ERR, 1);
178 assert_true(check_if_dimm_changed(spd_cache, &blk));
179}
180
181__attribute__((unused))
182static void test_check_if_dimm_changed_sodimm_lost(void **state)
183{
184 uint8_t *spd_cache;
185 size_t spd_cache_sz;
Jakub Czapigad5433af2021-05-17 10:53:22 +0200186 struct spd_block blk = { .addr_map = {0}, .spd_array = {0}, .len = 0 };
Jakub Czapiga2b8d7212021-04-22 20:14:02 +0200187
188 assert_int_equal(CB_SUCCESS, load_spd_cache(&spd_cache, &spd_cache_sz));
189 fill_spd_cache_ddr4(spd_cache, spd_cache_sz);
190 assert_int_equal(CB_SUCCESS, spd_fill_from_cache(spd_cache, &blk));
191 get_sn_from_spd_cache(spd_cache, get_spd_sn_ret_sn);
192 memset(spd_cache + spd_data_ddr4_1_sz, 0xff, spd_data_ddr4_2_sz);
193
194 get_spd_sn_ret_sn_idx = 0;
195 will_return_always(get_spd_sn, CB_SUCCESS);
196 assert_true(check_if_dimm_changed(spd_cache, &blk));
197}
198
199__attribute__((unused))
200static void test_check_if_dimm_changed_new_sodimm(void **state)
201{
202 uint8_t *spd_cache;
203 size_t spd_cache_sz;
Jakub Czapigad5433af2021-05-17 10:53:22 +0200204 struct spd_block blk = { .addr_map = {0}, .spd_array = {0}, .len = 0 };
Jakub Czapiga2b8d7212021-04-22 20:14:02 +0200205
206 assert_int_equal(CB_SUCCESS, load_spd_cache(&spd_cache, &spd_cache_sz));
207 fill_spd_cache_ddr4(spd_cache, spd_cache_sz);
208 assert_int_equal(CB_SUCCESS, spd_fill_from_cache(spd_cache, &blk));
209 get_sn_from_spd_cache(spd_cache, get_spd_sn_ret_sn);
210 memcpy(spd_cache + spd_data_ddr4_1_sz + spd_data_ddr4_2_sz,
211 spd_data_ddr4_2, spd_data_ddr4_2_sz);
212
213 get_spd_sn_ret_sn_idx = 0;
214 will_return_always(get_spd_sn, CB_SUCCESS);
215 assert_true(check_if_dimm_changed(spd_cache, &blk));
216}
217
218__attribute__((unused))
219static void test_check_if_dimm_changed_sn_changed(void **state)
220{
221 uint8_t *spd_cache;
222 size_t spd_cache_sz;
Jakub Czapigad5433af2021-05-17 10:53:22 +0200223 struct spd_block blk = { .addr_map = {0}, .spd_array = {0}, .len = 0 };
Jakub Czapiga2b8d7212021-04-22 20:14:02 +0200224
225 assert_int_equal(CB_SUCCESS, load_spd_cache(&spd_cache, &spd_cache_sz));
226 fill_spd_cache_ddr4(spd_cache, spd_cache_sz);
227 assert_int_equal(CB_SUCCESS, spd_fill_from_cache(spd_cache, &blk));
228 get_sn_from_spd_cache(spd_cache, get_spd_sn_ret_sn);
229 *(u32 *)(spd_cache + SC_SPD_OFFSET(0) + DDR4_SPD_SN_OFF) = 0x43211234;
230
231 get_spd_sn_ret_sn_idx = 0;
232 will_return_always(get_spd_sn, CB_SUCCESS);
233 assert_true(check_if_dimm_changed(spd_cache, &blk));
234}
235
236int main(void)
237{
238 const struct CMUnitTest tests[] = {
239 cmocka_unit_test_setup(test_load_spd_cache, setup_spd_cache_test),
240 cmocka_unit_test_setup(test_spd_fill_from_cache, setup_spd_cache_test),
241 cmocka_unit_test_setup(test_spd_cache_is_valid, setup_spd_cache_test),
242#if __TEST_SPD_CACHE_DDR == 4
243 cmocka_unit_test_setup(test_check_if_dimm_changed_not_changed,
244 setup_spd_cache_test),
245 cmocka_unit_test_setup(test_check_if_dimm_changed_sn_error,
246 setup_spd_cache_test),
247 cmocka_unit_test_setup(test_check_if_dimm_changed_sodimm_lost,
248 setup_spd_cache_test),
249 cmocka_unit_test_setup(test_check_if_dimm_changed_new_sodimm,
250 setup_spd_cache_test),
251 cmocka_unit_test_setup(test_check_if_dimm_changed_sn_changed,
252 setup_spd_cache_test),
253#endif
254 };
255
Jakub Czapiga7c6081e2021-08-25 16:27:35 +0200256 return cb_run_group_tests(tests, setup_spd_cache, teardown_spd_cache);
Jakub Czapiga2b8d7212021-04-22 20:14:02 +0200257}