blob: 1bc3b1284f2662e274cddc88e76bcf2c3d6ae6e5 [file] [log] [blame]
jaypit02ea3cd062018-10-05 12:22:38 +05301/** @file
Gowtham Siddarth47223082019-01-17 09:59:50 +05302 * Copyright (c) 2018-2019, Arm Limited or its affiliates. All rights reserved.
jaypit02ea3cd062018-10-05 12:22:38 +05303 * 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_interfaces.h"
20#include "val_dispatcher.h"
21#include "val_peripherals.h"
22#include "pal_interfaces_ns.h"
23#include "val_target.h"
24
25extern val_api_t val_api;
26extern psa_api_t psa_api;
27
28/* globals */
29test_status_buffer_t g_status_buffer;
30
31/**
32 * @brief Connect to given sid
33 @param -sid : RoT service id
34 @param -minor_version : minor_version of RoT service
35 @param -handle - return connection handle
36 * @return val_status_t
37 */
38val_status_t val_ipc_connect(uint32_t sid, uint32_t minor_version, psa_handle_t *handle )
39{
jaypit02ac23b5b2018-11-02 13:10:19 +053040 *handle = pal_ipc_connect(sid, minor_version);
jaypit02ea3cd062018-10-05 12:22:38 +053041
42 if (*handle < 0)
43 {
44 return VAL_STATUS_CONNECTION_FAILED;
45 }
46
47 return VAL_STATUS_SUCCESS;
48}
49
50/**
51 * @brief Call a connected Root of Trust Service.@n
52 * The caller must provide an array of ::psa_invec_t structures as the input payload.
53 *
54 * @param handle Handle for the connection.
55 * @param in_vec Array of psa_invec structures.
56 * @param in_len Number of psa_invec structures in in_vec.
57 * @param out_vec Array of psa_outvec structures for optional Root of Trust Service response.
58 * @param out_len Number of psa_outvec structures in out_vec.
59 * @return val_status_t
60 */
61val_status_t val_ipc_call(psa_handle_t handle, psa_invec *in_vec, size_t in_len,
62 psa_outvec *out_vec, size_t out_len)
63{
64 psa_status_t call_status = PSA_SUCCESS;
65
jaypit02ac23b5b2018-11-02 13:10:19 +053066 call_status = pal_ipc_call(handle, in_vec, in_len, out_vec, out_len);
jaypit02ea3cd062018-10-05 12:22:38 +053067
68 if (call_status != PSA_SUCCESS)
69 {
70 return VAL_STATUS_CALL_FAILED;
71 }
72
73 return VAL_STATUS_SUCCESS;
74}
75
76/**
77 * @brief Close a connection to a Root of Trust Service.
78 * Sends the PSA_IPC_DISCONNECT message to the Root of Trust Service so it can clean up resources.
79 *
80 * @param handle Handle for the connection.
81 * @return void
82 */
83void val_ipc_close(psa_handle_t handle)
84{
jaypit02ac23b5b2018-11-02 13:10:19 +053085 pal_ipc_close(handle);
jaypit02ea3cd062018-10-05 12:22:38 +053086}
87/**
88 @brief - This function executes given list of tests from non-secure sequentially
89 This covers non-secure to secure IPC API scenario
90 @param - test_num : Test_num
91 @param - tests_list : list of tests to be executed
92 @param - server_hs : Initiate a server handshake
93 @return - val_status_t
94**/
95val_status_t val_execute_non_secure_tests(uint32_t test_num, client_test_t *tests_list,
96 bool_t server_hs)
97{
98 val_status_t status = VAL_STATUS_SUCCESS;
99 val_status_t test_status = VAL_STATUS_SUCCESS;
100 boot_t boot;
101 psa_handle_t handle;
102 uint32_t i = 1;
103 test_info_t test_info;
104
105 test_info.test_num = test_num;
106
107 status = val_get_boot_flag(&boot.state);
108 if (VAL_ERROR(status))
109 {
110 val_set_status(RESULT_FAIL(status));
111 return status;
112 }
113
114 if (boot.state == BOOT_NOT_EXPECTED || boot.state == BOOT_EXPECTED_CRYPTO)
115 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530116 val_print(PRINT_TEST,"[Info] Executing tests from non-secure\n", 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530117 while (tests_list[i] != NULL)
118 {
119 if (server_hs == TRUE)
120 {
121 /* Handshake with server tests */
122 test_info.block_num = i;
123 status = val_execute_secure_test_func(&handle, test_info,
124 SERVER_TEST_DISPATCHER_SID);
125 if (VAL_ERROR(status))
126 {
127 val_set_status(RESULT_FAIL(status));
Gowtham Siddarth47223082019-01-17 09:59:50 +0530128 val_print(PRINT_DEBUG,"[Check%d] START\n", i);
jaypit02ea3cd062018-10-05 12:22:38 +0530129 return status;
130 }
131 else
132 {
133 val_print(PRINT_DEBUG,"[Check%d] START\n", i);
134 }
135 }
136
137 /* Execute client tests */
138 test_status = tests_list[i](NONSECURE);
139
140 if (server_hs == TRUE)
141 {
142 /* Retrive Server test status */
143 status = val_get_secure_test_result(&handle);
144 }
145
146 status = test_status ? test_status:status;
Gowtham Siddarth47223082019-01-17 09:59:50 +0530147 if (IS_TEST_SKIP(status))
148 {
149 val_set_status(status);
150 if (server_hs == TRUE)
151 val_print(PRINT_DEBUG, "[Check%d] SKIPPED\n", i);
152 return status;
153 }
154 else if (VAL_ERROR(status))
jaypit02ea3cd062018-10-05 12:22:38 +0530155 {
156 val_set_status(RESULT_FAIL(status));
jaypit02ac23b5b2018-11-02 13:10:19 +0530157 if (server_hs == TRUE)
Gowtham Siddarth47223082019-01-17 09:59:50 +0530158 val_print(PRINT_DEBUG, "[Check%d] FAILED\n", i);
159
jaypit02ea3cd062018-10-05 12:22:38 +0530160 return status;
161 }
162 else
163 {
jaypit02ac23b5b2018-11-02 13:10:19 +0530164 if (server_hs == TRUE)
Gowtham Siddarth47223082019-01-17 09:59:50 +0530165 val_print(PRINT_DEBUG, "[Check%d] PASSED\n", i);
jaypit02ea3cd062018-10-05 12:22:38 +0530166 }
Gowtham Siddarth47223082019-01-17 09:59:50 +0530167
jaypit02ea3cd062018-10-05 12:22:38 +0530168 i++;
169 }
170 }
171 else
172 {
173 /* If we are here means, we are in second run of this test */
174 status = VAL_STATUS_SUCCESS;
175 if (boot.state != BOOT_EXPECTED_S)
176 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530177 val_print(PRINT_DEBUG, "[Check1] PASSED\n", 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530178 }
179 }
180 return status;
181}
182/**
183 @brief - This function is used to switch to client_partition.c
184 where client tests will be executed to cover secure to secure
185 IPC scenario.
186 @param - test_num : Test_num
187 @return - val_status_t
188**/
189val_status_t val_switch_to_secure_client(uint32_t test_num)
190{
191 val_status_t status = VAL_STATUS_SUCCESS;
192 boot_t boot;
193 psa_handle_t handle;
194 test_info_t test_info;
195
196 test_info.test_num = test_num;
197 test_info.block_num = 1;
198
199 status = val_get_boot_flag(&boot.state);
200 if (VAL_ERROR(status))
201 {
202 goto exit;
203 }
204
205 if (boot.state != BOOT_EXPECTED_S)
206 {
207 status = val_set_boot_flag(BOOT_NOT_EXPECTED);
208 if (VAL_ERROR(status))
209 {
210 goto exit;
211 }
212
213 /* switch to secure client */
214 status = val_execute_secure_test_func(&handle, test_info, CLIENT_TEST_DISPATCHER_SID);
215 if (VAL_ERROR(status))
216 {
217 goto exit;
218 }
219
220 /* Retrive secure client test status */
221 status = val_get_secure_test_result(&handle);
Gowtham Siddarth47223082019-01-17 09:59:50 +0530222 if (IS_TEST_SKIP(status))
223 {
224 val_set_status(status);
225 return status;
226 }
jaypit02ea3cd062018-10-05 12:22:38 +0530227 if (VAL_ERROR(status))
228 {
229 goto exit;
230 }
231 return status;
232 }
233 else
234 {
235 /* If we are here means, we are in third run of this test */
Gowtham Siddarth47223082019-01-17 09:59:50 +0530236 val_print(PRINT_DEBUG, "[Check1] PASSED\n", 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530237 return VAL_STATUS_SUCCESS;
238 }
239
240exit:
241 val_set_status(RESULT_FAIL(status));
242 return status;
243}
244
245/**
246 @brief - This function is used to handshake between:
247 - nonsecure client fn to server test fn
248 - secure client fn and server test fn
249 - nonsecure client fn to secure client test fn
250 @param - handle : handle returned while connecting given sid
251 @param - test_info : Test_num and block_num to be executed
252 @param - sid : RoT service to be connected. Partition dispatcher sid
253 @return - val_status_t
254**/
255val_status_t val_execute_secure_test_func(psa_handle_t *handle, test_info_t test_info, uint32_t sid)
256{
257 uint32_t test_data;
258 val_status_t status = VAL_STATUS_SUCCESS;
259 psa_status_t status_of_call = PSA_SUCCESS;
260
jaypit02ac23b5b2018-11-02 13:10:19 +0530261 *handle = pal_ipc_connect(sid, 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530262 if (*handle < 0)
263 {
264 val_print(PRINT_ERROR, "Could not connect SID. Handle=%x\n", *handle);
265 return VAL_STATUS_CONNECTION_FAILED;
266 }
267
268 test_data = ((uint32_t)(test_info.test_num) |((uint32_t)(test_info.block_num) << BLOCK_NUM_POS)
269 | ((uint32_t)(TEST_EXECUTE_FUNC) << ACTION_POS));
270 psa_invec data[1] = {{&test_data, sizeof(test_data)}};
271
jaypit02ac23b5b2018-11-02 13:10:19 +0530272 status_of_call = pal_ipc_call(*handle, data, 1, NULL, 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530273 if (status_of_call != PSA_SUCCESS)
274 {
275 status = VAL_STATUS_CALL_FAILED;
276 val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call);
jaypit02ac23b5b2018-11-02 13:10:19 +0530277 pal_ipc_close(*handle);
jaypit02ea3cd062018-10-05 12:22:38 +0530278 }
Gowtham Siddarth47223082019-01-17 09:59:50 +0530279
jaypit02ea3cd062018-10-05 12:22:38 +0530280 return status;
281}
282
283/**
284 @brief - This function is used to retrive the status of previously connected test function
285 using val_execute_secure_test_func
286 @param - handle : handle of server function. Handle of Partition dispatcher sid
287 @return - The status of test functions
288**/
289val_status_t val_get_secure_test_result(psa_handle_t *handle)
290{
291 uint32_t test_data;
292 val_status_t status = VAL_STATUS_SUCCESS;
293 psa_status_t status_of_call = PSA_SUCCESS;
294
295 test_data = (TEST_RETURN_RESULT << ACTION_POS);
296
297 psa_outvec resp = {&status, sizeof(status)};
298 psa_invec data[1] = {{&test_data, sizeof(test_data)}};
299
jaypit02ac23b5b2018-11-02 13:10:19 +0530300 status_of_call = pal_ipc_call(*handle, data, 1, &resp, 1);
jaypit02ea3cd062018-10-05 12:22:38 +0530301 if (status_of_call != PSA_SUCCESS)
302 {
303 status = VAL_STATUS_CALL_FAILED;
304 val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call);
305 }
306
jaypit02ac23b5b2018-11-02 13:10:19 +0530307 pal_ipc_close(*handle);
jaypit02ea3cd062018-10-05 12:22:38 +0530308 return status;
309}
310
311
312/**
313 @brief - Parses input status for a given test and
314 outputs appropriate information on the console
315 @return - Test state
316**/
317uint32_t val_report_status(void)
318{
319 uint32_t status, state;
320
321 status = val_get_status();
322
323 state = (status >> TEST_STATE_BIT) & TEST_STATE_MASK;
324 status = status & TEST_STATUS_MASK;
325
326 switch (state)
327 {
328 case TEST_START:
329 state = TEST_FAIL;
330 val_print(PRINT_ALWAYS, "TEST RESULT: FAILED (Error Code=0x%x)\n",
331 VAL_STATUS_INIT_FAILED);
332 break;
333
334 case TEST_END:
335 state = TEST_PASS;
336 val_print(PRINT_ALWAYS, "TEST RESULT: PASSED \n", 0);
337 break;
338
339 case TEST_FAIL:
340 val_print(PRINT_ALWAYS, "TEST RESULT: FAILED (Error Code=0x%x) \n", status);
341 break;
342
343 case TEST_SKIP:
Gowtham Siddarth47223082019-01-17 09:59:50 +0530344 state = TEST_SKIP;
jaypit02ea3cd062018-10-05 12:22:38 +0530345 val_print(PRINT_ALWAYS, "TEST RESULT: SKIPPED (Skip Code=0x%x)\n", status);
346 break;
347
348 case TEST_PENDING:
349 val_print(PRINT_ALWAYS, "TEST RESULT: SIM ERROR (Error Code=0x%x)\n", status);
350 break;
351
352 default:
353 state = TEST_FAIL;
354 val_print(PRINT_ALWAYS, "TEST RESULT: FAILED(Error Code=0x%x)\n", VAL_STATUS_INVALID);
355 break;
356
357 }
358
359 val_print(PRINT_ALWAYS, "\n******************************************\n", 0);
360 return state;
361}
362
363/**
364 @brief - Records the state and status of test
365 @return - val_status_t
366**/
367val_status_t val_set_status(uint32_t status)
368{
369 g_status_buffer.state = ((status >> TEST_STATE_BIT) & TEST_STATE_MASK);
370 g_status_buffer.status = (status & TEST_STATUS_MASK);
371
372 return VAL_STATUS_SUCCESS;
373}
374
375/**
376 @brief - Updates the state and status for a given test
377 @return - test status
378**/
379uint32_t val_get_status(void)
380{
381 return ((g_status_buffer.state) << TEST_STATE_BIT) | (g_status_buffer.status);
382}
383
384/*
385 @brief - This function checks if the input status argument is an error.
386 On error, we print the checkpoint value and set the status.
387 @param - checkpoint : Test debug checkpoint
388 - val_status_t : Test status
389 @return - returns the input status back to the program.
390*/
391
392val_status_t val_err_check_set(uint32_t checkpoint, val_status_t status)
393{
394 if (VAL_ERROR(status))
395 {
396 val_print(PRINT_ERROR, "\tCheckpoint %d : ", checkpoint);
397 val_print(PRINT_ERROR, "Error Code=0x%x \n", status);
398 val_set_status(RESULT_FAIL(status));
399 }
400 else
401 {
402 status = val_get_status();
403 if (VAL_ERROR(status))
404 {
405 val_print(PRINT_ERROR, "\tCheckpoint %d : ", checkpoint);
406 val_print(PRINT_ERROR, "Error Code=0x%x \n", status);
407 }
408 else
409 {
410 val_print(PRINT_DEBUG, "\tCheckpoint %d \n", checkpoint);
411 }
412 }
413 return status;
414}
415
416/**
417 @brief This API prints the test number, description and
418 sets the test state to TEST_START on successful execution.
419 @param test_num :unique number identifying this test
420 @param desc :brief description of the test
421 @param test_bitfield :Addition test info such as
422 - test isolation level requirement
423 - Watchdog timeout type
424 @return void
425**/
426
427void val_test_init(uint32_t test_num, char8_t *desc, uint32_t test_bitfield)
428{
429 val_status_t status = VAL_STATUS_SUCCESS;
430 miscellaneous_desc_t *misc_desc;
431
432 /*global init*/
cherat013f028722019-02-18 14:50:37 +0530433 g_status_buffer.state = TEST_FAIL;
jaypit02ea3cd062018-10-05 12:22:38 +0530434 g_status_buffer.status = VAL_STATUS_INVALID;
435
436 val_print(PRINT_ALWAYS, "\nTEST: %d | DESCRIPTION: ", test_num);
437 val_print(PRINT_ALWAYS, desc, 0);
438
439 /* common skip logic */
440 status = val_target_get_config(TARGET_CONFIG_CREATE_ID(GROUP_MISCELLANEOUS,
441 MISCELLANEOUS_DUT, 0),
442 (uint8_t **)&misc_desc,
443 (uint32_t *)sizeof(miscellaneous_desc_t));
444 if (VAL_ERROR(status))
445 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530446 val_print(PRINT_ERROR, "val_target_get_config failed Error=0x%x\n", status);
jaypit02ea3cd062018-10-05 12:22:38 +0530447 return;
448 }
449
450 if (misc_desc->implemented_psa_firmware_isolation_level <
451 GET_TEST_ISOLATION_LEVEL(test_bitfield))
452 {
453 val_set_status(RESULT_SKIP(VAL_STATUS_ISOLATION_LEVEL_NOT_SUPP));
454 val_print(PRINT_ALWAYS, "Skipping test. Required isolation level is not supported\n", 0);
455 return;
456 }
457
458 /* Initialise watchdog */
459 status = val_wd_timer_init(GET_WD_TIMOUT_TYPE(test_bitfield));
460 if (VAL_ERROR(status))
461 {
462 val_print(PRINT_ERROR, "val_wd_timer_init failed Error=0x%x\n", status);
463 return;
464 }
465
466 /* Enable watchdog Timer */
467 status = val_wd_timer_enable();
468 if (VAL_ERROR(status))
469 {
470 val_print(PRINT_ERROR, "val_wd_timer_enable failed Error=0x%x\n", status);
471 return;
472 }
473
474 val_set_status(RESULT_START(VAL_STATUS_SUCCESS));
475 return;
476}
477
478/**
479 @brief This API sets the test state to TEST_END if test is successfuly passed.
480 @param none
481 @return none
482**/
483
484void val_test_exit(void)
485{
Gowtham Siddarth47223082019-01-17 09:59:50 +0530486 val_status_t status;
jaypit02ea3cd062018-10-05 12:22:38 +0530487
Gowtham Siddarth47223082019-01-17 09:59:50 +0530488 val_wd_timer_disable();
489 status = val_get_status();
jaypit02ea3cd062018-10-05 12:22:38 +0530490 /* return if test skipped or failed */
Gowtham Siddarth47223082019-01-17 09:59:50 +0530491 if (IS_TEST_FAIL(status) || IS_TEST_SKIP(status))
jaypit02ea3cd062018-10-05 12:22:38 +0530492 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530493 return;
jaypit02ea3cd062018-10-05 12:22:38 +0530494 }
Gowtham Siddarth47223082019-01-17 09:59:50 +0530495 else
496 {
497 val_set_status(RESULT_END(VAL_STATUS_SUCCESS));
498 }
jaypit02ea3cd062018-10-05 12:22:38 +0530499}
500
501/**
502 @brief - This function returns the test ID of the last test that was run
503 @param - test_id address
504 @return - val_status_t
505**/
506val_status_t val_get_last_run_test_id(test_id_t *test_id)
507{
508 val_status_t status;
509 test_count_t test_count;
510 boot_t boot;
511 int i = 0, intermediate_boot = 0;
512 boot_state_t boot_state[] = {BOOT_NOT_EXPECTED, BOOT_EXPECTED_NS,
513 BOOT_EXPECTED_S, BOOT_EXPECTED_BUT_FAILED,
514 BOOT_EXPECTED_CRYPTO};
515
516 status = val_get_boot_flag(&boot.state);
517 if (VAL_ERROR(status))
518 {
519 return status;
520 }
521
522 for (i = 0; i < (sizeof(boot_state)/sizeof(boot_state[0])); i++)
523 {
524 if (boot.state == boot_state[i])
525 {
526 intermediate_boot = 1;
527 break;
528 }
529 }
530
531 if (!intermediate_boot)
532 {
533 /* First boot. Initiliase necessary data structure */
534 status = val_set_boot_flag(BOOT_UNKNOWN);
535 if (VAL_ERROR(status))
536 {
537 return status;
538 }
539
540 *test_id = VAL_INVALID_TEST_ID;
541 status = val_nvmem_write(VAL_NVMEM_OFFSET(NV_TEST_ID_PREVIOUS),
542 test_id, sizeof(test_id_t));
543 if (VAL_ERROR(status))
544 {
545 val_print(PRINT_ALWAYS, "\n\tNVMEM write error", 0);
546 return status;
547 }
548
549 test_count.pass_cnt = 0;
550 test_count.fail_cnt = 0;
551 test_count.skip_cnt = 0;
552 test_count.sim_error_cnt = 0;
553
554 status = val_nvmem_write(VAL_NVMEM_OFFSET(NV_TEST_CNT),
555 &test_count, sizeof(test_count_t));
556 if (VAL_ERROR(status))
557 {
558 val_print(PRINT_ERROR, "\n\tNVMEM write error", 0);
559 return status;
560 }
561 }
562
563 status = val_nvmem_read(VAL_NVMEM_OFFSET(NV_TEST_ID_PREVIOUS), test_id, sizeof(test_id_t));
564 if (VAL_ERROR(status))
565 {
566 val_print(PRINT_ERROR, "\n\tNVMEM read error", 0);
567 }
568
569 val_print(PRINT_INFO, "In val_get_last_run_test_id, test_id=%x\n", *test_id);
570 return status;
571}
572
573/**
574 @brief - This function sets the given boot.state value to corresponding
575 boot NVMEM location
576 @param - state: boot_state_t
577 @return - val_status_t
578**/
579val_status_t val_set_boot_flag(boot_state_t state)
580{
581 boot_t boot;
582 val_status_t status;
583
584 boot.state = state;
585 status = val_nvmem_write(VAL_NVMEM_OFFSET(NV_BOOT), &boot, sizeof(boot_t));
586 if (VAL_ERROR(status))
587 {
588 val_print(PRINT_ERROR, "val_nvmem_write failed. Error=0x%x\n", status);
589 return status;
590 }
591 return status;
592}
593
594/**
595 @brief - This function returns boot.state value available in boot NVMEM location
596 @param - state address
597 @return - val_status_t
598**/
599val_status_t val_get_boot_flag(boot_state_t *state)
600{
601 boot_t boot;
602 val_status_t status;
603
604 status = val_nvmem_read(VAL_NVMEM_OFFSET(NV_BOOT), &boot, sizeof(boot_t));
605 if (VAL_ERROR(status))
606 {
607 val_print(PRINT_ERROR, "val_nvmem_read failed. Error=0x%x\n", status);
608 return status;
609 }
610 *state = boot.state;
611 return status;
612}