1 /** @file
2 * Copyright (c) 2018-2021, Arm Limited or its affiliates. All rights reserved.
3 * SPDX-License-Identifier : Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 **/
17
18 #include "val_framework.h"
19 #include "val_dispatcher.h"
20 #include "val_interfaces.h"
21 #include "val_peripherals.h"
22 #include "val_target.h"
23
24 extern val_api_t val_api;
25 extern psa_api_t psa_api;
26
27 /* gloabls */
28 addr_t g_test_info_addr;
29
30 /**
31 @brief - This function prints PSA_{SUITE}_API_VERSION_MAJOR
32 PSA_{SUITE}_API_VERSION_MINOR details.
33 @param - None
34 @return - None
35 **/
val_print_api_version(void)36 __attribute__((unused)) static void val_print_api_version(void)
37 {
38 #ifdef CRYPTO
39 val_print(PRINT_ALWAYS, " %d.", PSA_CRYPTO_API_VERSION_MAJOR);
40 val_print(PRINT_ALWAYS, "%d", PSA_CRYPTO_API_VERSION_MINOR);
41 #endif
42 #ifdef INTERNAL_TRUSTED_STORAGE
43 val_print(PRINT_ALWAYS, " %d.", PSA_ITS_API_VERSION_MAJOR);
44 val_print(PRINT_ALWAYS, "%d", PSA_ITS_API_VERSION_MINOR);
45 #endif
46 #ifdef PROTECTED_STORAGE
47 val_print(PRINT_ALWAYS, " %d.", PSA_PS_API_VERSION_MAJOR);
48 val_print(PRINT_ALWAYS, "%d", PSA_PS_API_VERSION_MINOR);
49 #endif
50 #ifdef STORAGE
51 val_print(PRINT_ALWAYS, " ITS %d.", PSA_ITS_API_VERSION_MAJOR);
52 val_print(PRINT_ALWAYS, "%d", PSA_ITS_API_VERSION_MINOR);
53 val_print(PRINT_ALWAYS, " and PS %d.", PSA_PS_API_VERSION_MAJOR);
54 val_print(PRINT_ALWAYS, "%d", PSA_PS_API_VERSION_MINOR);
55 #endif
56 #ifdef INITIAL_ATTESTATION
57 val_print(PRINT_ALWAYS, " %d.", PSA_INITIAL_ATTEST_API_VERSION_MAJOR);
58 val_print(PRINT_ALWAYS, "%d", PSA_INITIAL_ATTEST_API_VERSION_MINOR);
59 #endif
60 }
61
62 /**
63 @brief - This function reads the test ELFs from RAM or secondary storage and loads into
64 system memory
65 @param - test_id : Returns the current test ID
66 - test_id_prev : Previous test ID.
67 @return - Error code
68 **/
val_test_load(test_id_t * test_id,test_id_t test_id_prev)69 val_status_t val_test_load(test_id_t *test_id, test_id_t test_id_prev)
70 {
71 int i;
72 val_test_info_t test_list[] = {
73 #include "test_entry_list.inc"
74 {VAL_INVALID_TEST_ID, NULL}
75 };
76
77 for (i = 0; i < (int)(sizeof(test_list)/sizeof(test_list[0])); i++)
78 {
79 if (test_id_prev == VAL_INVALID_TEST_ID)
80 {
81 *test_id = test_list[i].test_id;
82 g_test_info_addr = (addr_t) test_list[i].entry_addr;
83 return VAL_STATUS_SUCCESS;
84 }
85 else if (test_id_prev == test_list[i].test_id)
86 {
87 *test_id = test_list[i+1].test_id;
88 g_test_info_addr = (addr_t) test_list[i+1].entry_addr;
89 return VAL_STATUS_SUCCESS;
90 }
91 else if (test_list[i].test_id == VAL_INVALID_TEST_ID)
92 {
93 val_print(PRINT_DEBUG, "\n\nNo more valid tests found. Exiting.", 0);
94 *test_id = VAL_INVALID_TEST_ID;
95 return VAL_STATUS_SUCCESS;
96 }
97 }
98
99 *test_id = VAL_INVALID_TEST_ID;
100 val_print(PRINT_ERROR, "\n\nError: No more valid tests found. Exiting.", 0);
101 return VAL_STATUS_LOAD_ERROR;
102 }
103
104 /**
105 @brief - This function reads the function pointer addresses for
106 test_entry
107 @param - paddr : Returns the Test function address
108 @return - Returns val_status_t
109 **/
val_get_test_entry_addr(addr_t * paddr)110 val_status_t val_get_test_entry_addr(addr_t *paddr)
111 {
112 *paddr = g_test_info_addr;
113 return VAL_STATUS_SUCCESS;
114 }
115
116 /**
117 @brief - Execute the function pointer which was given to us by the test
118 @param - void
119 **/
val_execute_test_fn(void)120 void val_execute_test_fn(void)
121 {
122 test_fptr_t fn_ptr;
123 addr_t addr;
124
125 val_get_test_entry_addr(&addr);
126 fn_ptr = (test_fptr_t)addr;
127 fn_ptr(&val_api, &psa_api);
128 return;
129 }
130
131 /*
132 @brief - Reads the pre-defined component name against given test_id
133 @param - test_id : Current Test ID
134 @return - Component name
135 */
val_get_comp_name(test_id_t test_id)136 char * val_get_comp_name(test_id_t test_id)
137 {
138 switch (VAL_GET_COMP_NUM(test_id))
139 {
140 case VAL_FF_BASE:
141 return "IPC Suite";
142 case VAL_CRYPTO_BASE:
143 return "Crypto Suite";
144 case VAL_STORAGE_BASE:
145 return "Storage Suite";
146 case VAL_INITIAL_ATTESTATION_BASE:
147 return "Attestation Suite";
148 default:
149 return "Unknown Suite";
150 }
151 }
152
153 /**
154 @brief - This function is responsible for setting up VAL infrastructure.
155 Loads test one by one from combine binary and calls test_entry
156 function of each test image.
157 @return - 0 if success Or error code for the failure.
158 **/
val_dispatcher(test_id_t test_id_prev)159 int32_t val_dispatcher(test_id_t test_id_prev)
160 {
161
162 test_id_t test_id;
163 val_status_t status;
164 boot_t boot;
165 test_count_t test_count;
166 uint32_t test_result;
167
168 do
169 {
170 status = val_get_boot_flag(&boot.state);
171 if (VAL_ERROR(status))
172 {
173 return status;
174 }
175
176 /* Did last run test hang and system re-booted due to watchdog timeout and
177 boot.state was set to BOOT_NOT_EXPECTED ? If yes, set the test status
178 to SIM ERROR and go to next test. */
179 if (boot.state == BOOT_NOT_EXPECTED)
180 {
181 val_set_status(RESULT_PENDING(VAL_STATUS_ERROR));
182 status = val_nvmem_read(VAL_NVMEM_OFFSET(NV_TEST_ID_CURRENT),
183 &test_id, sizeof(test_id_t));
184 if (VAL_ERROR(status))
185 {
186 val_print(PRINT_ERROR, "\n\tNVMEM read error", 0);
187 return status;
188 }
189 }
190 /* Did last run test hang and system reset due to watchdog timeout but
191 boot.state was set to BOOT_EXPECTED_BUT_FAILED ? If yes, set the test status
192 to FAIL and go to next test. This condition will hit when test was expecting
193 re-boot on perticular scenario but it didn't happen and system re-booted due
194 to other reason. */
195 else if (boot.state == BOOT_EXPECTED_BUT_FAILED)
196 {
197 val_set_status(RESULT_FAIL(VAL_STATUS_BOOT_EXPECTED_BUT_FAILED));
198 status = val_nvmem_read(VAL_NVMEM_OFFSET(NV_TEST_ID_CURRENT),
199 &test_id, sizeof(test_id_t));
200 if (VAL_ERROR(status))
201 {
202 val_print(PRINT_ERROR, "\n\tNVMEM read error", 0);
203 return status;
204 }
205 }
206 else
207 {
208 status = val_test_load(&test_id, test_id_prev);
209
210 if (VAL_ERROR(status))
211 {
212 return status;
213 }
214 else if (test_id == VAL_INVALID_TEST_ID)
215 {
216 break;
217 }
218
219 status = val_nvmem_write(VAL_NVMEM_OFFSET(NV_TEST_ID_CURRENT),
220 &test_id, sizeof(test_id_t));
221 if (VAL_ERROR(status))
222 {
223 val_print(PRINT_ERROR, "\n\tNVMEM write error", 0);
224 return status;
225 }
226
227 if (VAL_GET_COMP_NUM(test_id_prev) != VAL_GET_COMP_NUM(test_id))
228 {
229 val_print(PRINT_ALWAYS, "\nRunning.. ", 0);
230 val_print(PRINT_ALWAYS, val_get_comp_name(test_id), 0);
231 // val_print_api_version();
232 #ifdef TESTS_COVERAGE
233 val_print(PRINT_ALWAYS, "\nNOTE : Known failing tests are excluded from this \
234 build. For PSA functional API certification, all tests must be run.\n", 0);
235 #endif
236 val_print(PRINT_ALWAYS, "\n******************************************\n", 0);
237 }
238
239 if (boot.state == BOOT_UNKNOWN)
240 {
241 /* Set boot.state to BOOT_NOT_EXPECTED to catch unexpected test hang */
242 status = val_set_boot_flag(BOOT_NOT_EXPECTED);
243 if (VAL_ERROR(status))
244 {
245 return status;
246 }
247 }
248 val_execute_test_fn();
249 }
250
251 test_result = val_report_status();
252
253 /* Reset boot.state to UNKNOWN before lunching next test */
254 status = val_set_boot_flag(BOOT_UNKNOWN);
255 if (VAL_ERROR(status))
256 {
257 return status;
258 }
259
260 /* Prepare suite summary data structure */
261 status = val_nvmem_read(VAL_NVMEM_OFFSET(NV_TEST_CNT), &test_count, sizeof(test_count_t));
262 if (VAL_ERROR(status))
263 {
264 val_print(PRINT_ERROR, "\n\tNVMEM read error", 0);
265 return status;
266 }
267
268 switch (test_result)
269 {
270 case TEST_PASS:
271 test_count.pass_cnt += 1;
272 break;
273 case TEST_FAIL:
274 test_count.fail_cnt += 1;
275 break;
276 case TEST_SKIP:
277 test_count.skip_cnt += 1;
278 break;
279 case TEST_PENDING:
280 test_count.sim_error_cnt += 1;
281 break;
282 }
283
284 status = val_nvmem_write(VAL_NVMEM_OFFSET(NV_TEST_CNT), &test_count, sizeof(test_count_t));
285 if (VAL_ERROR(status))
286 {
287 val_print(PRINT_ERROR, "\n\tNVMEM write error", 0);
288 return status;
289 }
290
291 test_id_prev = test_id;
292 status = val_nvmem_write(VAL_NVMEM_OFFSET(NV_TEST_ID_PREVIOUS),
293 &test_id, sizeof(test_id_t));
294 if (VAL_ERROR(status))
295 {
296 val_print(PRINT_ERROR, "\n\tNVMEM write error", 0);
297 return status;
298 }
299
300 } while(1);
301
302 status = val_nvmem_read(VAL_NVMEM_OFFSET(NV_TEST_CNT), &test_count, sizeof(test_count_t));
303 if (VAL_ERROR(status))
304 {
305 val_print(PRINT_ERROR, "\n\tNVMEM read error", 0);
306 return status;
307 }
308
309 val_print(PRINT_ALWAYS, "\n************ ", 0);
310 val_print(PRINT_ALWAYS, val_get_comp_name(test_id_prev), 0);
311 val_print(PRINT_ALWAYS, " Report **********\n", 0);
312 val_print(PRINT_ALWAYS, "TOTAL TESTS : %d\n", test_count.pass_cnt + test_count.fail_cnt
313 + test_count.skip_cnt + test_count.sim_error_cnt);
314 val_print(PRINT_ALWAYS, "TOTAL PASSED : %d\n", test_count.pass_cnt);
315 val_print(PRINT_ALWAYS, "TOTAL SIM ERROR : %d\n", test_count.sim_error_cnt);
316 val_print(PRINT_ALWAYS, "TOTAL FAILED : %d\n", test_count.fail_cnt);
317 val_print(PRINT_ALWAYS, "TOTAL SKIPPED : %d\n", test_count.skip_cnt);
318 val_print(PRINT_ALWAYS, "******************************************\n", 0);
319
320 return (test_count.fail_cnt > 0) ? VAL_STATUS_TEST_FAILED : VAL_STATUS_SUCCESS;
321 }
322
323
324
325
326
327
328
329