blob: df36402d4ed3251e01b5a4938f0766e0610b5994 [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/* Note- This file contains the functions and variables definition which are common to
jaypit02ac23b5b2018-11-02 13:10:19 +053019 all partitions defined by test suite. These functions and variables are declared with static
jaypit02ea3cd062018-10-05 12:22:38 +053020 keyword because some fully isolated system may not allow to share code and data segment
21 between partitions and static will help each partition to have its own copy of code and data.
22 Moreover it can prevents symbol names conflict if these functions are separately compiled and
23 linked with each of partitions in fully isolated environment.
24*/
25
26#ifndef _VAL_COMMON_SP_APIS_H_
27#define _VAL_COMMON_SP_APIS_H_
28
Gowtham Siddarth47223082019-01-17 09:59:50 +053029#include "val.h"
30#include "val_target.c"
jaypit02ea3cd062018-10-05 12:22:38 +053031#include "val_service_defs.h"
32
jaypit02ac23b5b2018-11-02 13:10:19 +053033/* "psa_manifest/<manifestfilename>.h" Manifest definitions. Only accessible to Secure Partition.
jaypit02ea3cd062018-10-05 12:22:38 +053034 * The file name is based on the name of the Secure Partitions manifest file.
35 * The name must not collide with other header files.
36 * Compliance tests expect the below manifest output files implementation from build tool.
37 */
jaypit02ac23b5b2018-11-02 13:10:19 +053038#include "psa_manifest/client_partition_psa.h"
39#include "psa_manifest/server_partition_psa.h"
jaypit02ea3cd062018-10-05 12:22:38 +053040
41__UNUSED STATIC_DECLARE val_status_t val_print
42 (print_verbosity_t verbosity, char *string, uint32_t data);
43__UNUSED STATIC_DECLARE val_status_t val_ipc_connect
44 (uint32_t sid, uint32_t minor_version, psa_handle_t *handle );
45__UNUSED STATIC_DECLARE val_status_t val_ipc_call
46 (psa_handle_t handle, psa_invec *in_vec, size_t in_len,
47 psa_outvec *out_vec, size_t out_len);
48__UNUSED STATIC_DECLARE void val_ipc_close
49 (psa_handle_t handle);
50__UNUSED STATIC_DECLARE val_status_t val_process_connect_request(psa_signal_t sig, psa_msg_t *msg);
51__UNUSED STATIC_DECLARE val_status_t val_process_call_request(psa_signal_t sig, psa_msg_t *msg);
52__UNUSED STATIC_DECLARE val_status_t val_process_disconnect_request
53 (psa_signal_t sig, psa_msg_t *msg);
54__UNUSED STATIC_DECLARE val_status_t val_execute_secure_tests
55 (uint32_t test_num, client_test_t *tests_list);
56__UNUSED STATIC_DECLARE val_status_t val_execute_secure_test_func
57 (psa_handle_t *handle, test_info_t test_info, uint32_t sid);
58__UNUSED STATIC_DECLARE val_status_t val_get_secure_test_result(psa_handle_t *handle);
59__UNUSED STATIC_DECLARE val_status_t val_err_check_set(uint32_t checkpoint, val_status_t status);
60__UNUSED STATIC_DECLARE val_status_t val_nvmem_write(uint32_t offset, void *buffer, int size);
61__UNUSED STATIC_DECLARE val_status_t val_set_boot_flag(boot_state_t state);
62
63__UNUSED static val_api_t val_api = {
64 .print = val_print,
65 .err_check_set = val_err_check_set,
66 .execute_secure_test_func = val_execute_secure_test_func,
67 .get_secure_test_result = val_get_secure_test_result,
68 .ipc_connect = val_ipc_connect,
69 .ipc_call = val_ipc_call,
70 .ipc_close = val_ipc_close,
71 .set_boot_flag = val_set_boot_flag,
jaypit02ac23b5b2018-11-02 13:10:19 +053072 .target_get_config = val_target_get_config,
jaypit02ea3cd062018-10-05 12:22:38 +053073};
74
75__UNUSED static psa_api_t psa_api = {
76 .framework_version = psa_framework_version,
77 .version = psa_version,
78 .connect = psa_connect,
79 .call = psa_call,
80 .close = psa_close,
81};
82
83/**
84 @brief - Print module. This is client interface API of secure partition
85 val_print_sf API for spe world
86 @param - verbosity: Print verbosity level
87 - string : Input string
88 - data : Value for format specifier
89 @return - val_status_t
90**/
91STATIC_DECLARE val_status_t val_print(print_verbosity_t verbosity, char *string, uint32_t data)
92{
93 int string_len = 0;
94 char *p = string;
95 psa_handle_t print_handle = 0;
96 psa_status_t status_of_call = PSA_SUCCESS;
97 val_status_t status = VAL_STATUS_SUCCESS;
jaypit02ac23b5b2018-11-02 13:10:19 +053098 uart_fn_type_t uart_fn = UART_PRINT;
99
100 if (verbosity < VERBOSE)
101 {
102 return VAL_STATUS_SUCCESS;
103 }
jaypit02ea3cd062018-10-05 12:22:38 +0530104
105 while (*p != '\0')
106 {
107 string_len++;
108 p++;
109 }
110
jaypit02ac23b5b2018-11-02 13:10:19 +0530111 psa_invec data1[3] = {{&uart_fn, sizeof(uart_fn)}, {string, string_len+1}, {&data, 4}};
jaypit02ea3cd062018-10-05 12:22:38 +0530112 print_handle = psa_connect(DRIVER_UART_SID, 0);
113
114 if (print_handle < 0)
115 {
116 return VAL_STATUS_CONNECTION_FAILED;
117 }
118 else
119 {
120 status_of_call = psa_call(print_handle, data1, 3, NULL, 0);
121 if (status_of_call != PSA_SUCCESS)
122 {
123 status = VAL_STATUS_CALL_FAILED;
124 }
125 }
126 psa_close(print_handle);
127 return status;
128}
129
130/**
131 * @brief Connect to given sid
132 @param -sid : RoT service id
133 @param -minor_version : minor_version of RoT service
134 @param -handle - return connection handle
135 * @return val_status_t
136 */
137STATIC_DECLARE val_status_t val_ipc_connect(uint32_t sid, uint32_t minor_version,
138 psa_handle_t *handle )
139{
140 *handle = psa_connect(sid, minor_version);
141
142 if (*handle < 0)
143 {
144 return(VAL_STATUS_CONNECTION_FAILED);
145 }
146
147 return VAL_STATUS_SUCCESS;
148}
149
150/**
151 * @brief Call a connected Root of Trust Service.@n
152 * The caller must provide an array of ::psa_invec_t structures as the input payload.
153 * @param handle: Handle for the connection.
154 * @param in_vec: Array of psa_invec structures.
155 * @param in_len: Number of psa_invec structures in in_vec.
156 * @param out_vec: Array of psa_outvec structures for optional Root of Trust Service response.
157 * @param out_len: Number of psa_outvec structures in out_vec.
158 * @return val_status_t
159 */
160STATIC_DECLARE val_status_t val_ipc_call(psa_handle_t handle, psa_invec *in_vec, size_t in_len,
161 psa_outvec *out_vec, size_t out_len)
162{
163 psa_status_t call_status = PSA_SUCCESS;
164
165 call_status = psa_call(handle, in_vec, in_len, out_vec, out_len);
166
167 if (call_status != PSA_SUCCESS)
168 {
169 return(VAL_STATUS_CALL_FAILED);
170 }
171
172 return VAL_STATUS_SUCCESS;
173}
174
175/**
176 * @brief Close a connection to a Root of Trust Service.
177 * Sends the PSA_IPC_DISCONNECT message to the Root of Trust Service so
178 it can clean up resources.
179 * @param handle: Handle for the connection.
180 * @return void
181 */
182STATIC_DECLARE void val_ipc_close(psa_handle_t handle)
183{
184 psa_close(handle);
185}
186
187/**
188 * @brief Proccess a generic connect message to given rot signal.
189 @param -sig : signal to be processed
190 @param -msg : return msg info of given signal
191 * @return val_status_t.
192 */
193STATIC_DECLARE val_status_t val_process_connect_request(psa_signal_t sig, psa_msg_t *msg)
194{
195 val_status_t res = VAL_STATUS_ERROR;
196 psa_signal_t signals;
197
198wait1:
jaypit02ac23b5b2018-11-02 13:10:19 +0530199 signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
jaypit02ea3cd062018-10-05 12:22:38 +0530200 if (signals & sig)
201 {
202 if (psa_get(sig, msg) != PSA_SUCCESS)
203 {
204 goto wait1;
205 }
206
207 if ((msg->type != PSA_IPC_CONNECT) || (msg->handle <= 0))
208 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530209 val_print(PRINT_ERROR, "\tpsa_get failed for PSA_IPC_CONNECT\n", 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530210 res = VAL_STATUS_ERROR;
211 }
212 else
213 {
214 res = VAL_STATUS_SUCCESS;
215 }
216 }
217 else
218 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530219 val_print(PRINT_ERROR, "\tpsa_wait returned with invalid signal value = 0x%x\n", signals);
jaypit02ea3cd062018-10-05 12:22:38 +0530220 res = VAL_STATUS_ERROR;
221 }
222 return res;
223}
224
225/**
226 * @brief Proccess a generic call message to given rot signal.
227 @param -sig : signal to be processed
228 @param -msg : return msg info of given signal
229 * @return val_status_t
230 */
231STATIC_DECLARE val_status_t val_process_call_request(psa_signal_t sig, psa_msg_t *msg)
232{
233 val_status_t res = VAL_STATUS_ERROR;
234 psa_signal_t signals;
235
236wait2:
jaypit02ac23b5b2018-11-02 13:10:19 +0530237 signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
jaypit02ea3cd062018-10-05 12:22:38 +0530238 if (signals & sig)
239 {
240 if (psa_get(sig, msg) != PSA_SUCCESS)
241 {
242 goto wait2;
243 }
244
245 if ((msg->type != PSA_IPC_CALL) || (msg->handle <= 0))
246 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530247 val_print(PRINT_ERROR, "\tpsa_get failed for PSA_IPC_CALL\n", 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530248 res = VAL_STATUS_ERROR;
249 }
250 else
251 {
252 res = VAL_STATUS_SUCCESS;
253 }
254 }
255 else
256 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530257 val_print(PRINT_ERROR, "\tpsa_wait returned with invalid signal value = 0x%x\n", signals);
jaypit02ea3cd062018-10-05 12:22:38 +0530258 res = VAL_STATUS_ERROR;
259 }
260 return res;
261}
262
263/**
264 * @brief Proccess a generic disconnect message to given rot signal.
265 @param -sig : signal to be processed
266 @param -msg : return msg info of given signal
267 * @return val_status_t
268 */
269STATIC_DECLARE val_status_t val_process_disconnect_request(psa_signal_t sig, psa_msg_t *msg)
270{
271 val_status_t res = VAL_STATUS_ERROR;
272 psa_signal_t signals;
273
274wait3:
jaypit02ac23b5b2018-11-02 13:10:19 +0530275 signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
jaypit02ea3cd062018-10-05 12:22:38 +0530276 if (signals & sig)
277 {
278 if (psa_get(sig, msg) != PSA_SUCCESS)
279 {
280 goto wait3;
281 }
282
283 if ((msg->type != PSA_IPC_DISCONNECT) || (msg->handle <= 0))
284 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530285 val_print(PRINT_ERROR, "\tpsa_get failed for PSA_IPC_DISCONNECT\n", 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530286 res = VAL_STATUS_ERROR;
287 }
288 else
289 {
290 res = VAL_STATUS_SUCCESS;
291 }
292 }
293 else
294 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530295 val_print(PRINT_ERROR, "\tpsa_wait returned with invalid signal value = 0x%x\n", signals);
jaypit02ea3cd062018-10-05 12:22:38 +0530296 res = VAL_STATUS_ERROR;
297 }
298 return res;
299}
300
301/**
302 @brief - This function executes given list of tests from secure sequentially
303 This covers secure to secure IPC API scenario
304 @param - test_num : Test_num
305 @param - tests_list : list of tests to be executed
306 @return - val_status_t
307**/
308STATIC_DECLARE val_status_t val_execute_secure_tests(uint32_t test_num, client_test_t *tests_list)
309{
310 val_status_t status = VAL_STATUS_SUCCESS;
311 val_status_t test_status = VAL_STATUS_SUCCESS;
312 psa_handle_t handle;
313 int i = 1;
314 test_info_t test_info;
315
316 test_info.test_num = test_num;
Gowtham Siddarth47223082019-01-17 09:59:50 +0530317 val_print(PRINT_TEST, "[Info] Executing tests from secure\n", 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530318
319 while (tests_list[i] != NULL)
320 {
321
322 /* Handshake with server tests */
323 test_info.block_num = i;
324 status = val_execute_secure_test_func(&handle, test_info, SERVER_TEST_DISPATCHER_SID);
325 if (VAL_ERROR(status))
326 {
327 val_print(PRINT_ERROR,"[Check%d] START\n", i);
328 return status;
329 }
330 else
331 {
332 val_print(PRINT_DEBUG,"[Check%d] START\n", i);
333 }
334
335 /* Execute client tests */
336 test_status = tests_list[i](SECURE);
337
338 /* Retrive Server test status */
339 status = val_get_secure_test_result(&handle);
340
341 status = test_status ? test_status:status;
Gowtham Siddarth47223082019-01-17 09:59:50 +0530342 if (IS_TEST_SKIP(status))
343 {
344 val_print(PRINT_DEBUG, "[Check%d] SKIPPED\n", i);
345 return status;
346 }
jaypit02ea3cd062018-10-05 12:22:38 +0530347 if (VAL_ERROR(status))
348 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530349 val_print(PRINT_DEBUG,"[Check%d] FAILED\n", i);
jaypit02ea3cd062018-10-05 12:22:38 +0530350 return status;
351 }
352 else
353 {
354 val_print(PRINT_DEBUG,"[Check%d] PASSED\n", i);
355 }
356 i++;
357 }
358 return status;
359}
360
361/**
362 @brief - This function is used to handshake between:
363 - nonsecure client to server test fn
364 - secure client and server test fn
365 - nonsecure client to secure client test fn
366 @param - handle : handle returned while connecting given sid
367 @param - test_info : Test_num and block_num to be executed
368 @param - sid : RoT service to be connected. Partition dispatcher sid
369 @return - val_status_t
370**/
371STATIC_DECLARE val_status_t val_execute_secure_test_func(psa_handle_t *handle,
372 test_info_t test_info,
373 uint32_t sid)
374{
375 uint32_t test_data;
376 val_status_t status = VAL_STATUS_SUCCESS;
377 psa_status_t status_of_call = PSA_SUCCESS;
378
379 *handle = psa_connect(sid, 0);
380
381 if (*handle < 0)
382 {
383 val_print(PRINT_ERROR, "Could not connect SID. Handle=%x\n", *handle);
384 status = VAL_STATUS_CONNECTION_FAILED;
385 }
386
387 test_data = ((uint32_t)(test_info.test_num) | ((uint32_t)(test_info.block_num) << BLOCK_NUM_POS)
388 | ((uint32_t)(TEST_EXECUTE_FUNC) << ACTION_POS));
389 psa_invec data[1] = {{&test_data, sizeof(test_data)}};
390
391 status_of_call = psa_call(*handle, data, 1, NULL, 0);
392
393 if (status_of_call != PSA_SUCCESS)
394 {
395 status = VAL_STATUS_CALL_FAILED;
396 val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call);
397 psa_close(*handle);
398 }
399 return status;
400}
401
402/**
403 @brief - This function is used to retrive the status of previously connected test function
404 using val_execute_secure_test_func
405 @param - handle : handle of server function. Handle of Partition dispatcher sid
406 @return - The status of test functions
407**/
408STATIC_DECLARE val_status_t val_get_secure_test_result(psa_handle_t *handle)
409{
410 uint32_t test_data;
411 val_status_t status = VAL_STATUS_SUCCESS;
412 psa_status_t status_of_call = PSA_SUCCESS;
413
414 test_data = (TEST_RETURN_RESULT << ACTION_POS);
415
416 psa_outvec resp = {&status, sizeof(status)};
417 psa_invec data[1] = {{&test_data, sizeof(test_data)}};
418
419 status_of_call = psa_call(*handle, data, 1, &resp, 1);
420 if (status_of_call != PSA_SUCCESS)
421 {
422 status = VAL_STATUS_CALL_FAILED;
423 val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call);
424 }
425
426 psa_close(*handle);
427 return status;
428}
429
430/*
431 @brief - This function checks if the input status argument is an error.
432 On error, print the checkpoint value
433 @param - checkpoint : Test debug checkpoint
434 - val_status_t : Test status
435 @return - returns the input status back to the program.
436*/
437STATIC_DECLARE val_status_t val_err_check_set(uint32_t checkpoint, val_status_t status)
438{
439 if (VAL_ERROR(status))
440 {
441 val_print(PRINT_ERROR, "\tCheckpoint %d : ", checkpoint);
442 val_print(PRINT_ERROR, "Error Code=0x%x \n", status);
443 }
444 else
445 {
446 val_print(PRINT_DEBUG, "\tCheckpoint %d \n", checkpoint);
447 }
448 return status;
449}
450
451/*
452 @brief - Writes 'size' bytes from buffer into non-volatile memory at a given
453 'base + offset'. This is client interface API of secure partition
454 val_nvmem_write_sf API for spe world
455 - offset : Offset
456 - buffer : Pointer to source address
457 - size : Number of bytes
458 @return - val_status_t
459*/
460STATIC_DECLARE val_status_t val_nvmem_write(uint32_t offset, void *buffer, int size)
461{
jaypit02ac23b5b2018-11-02 13:10:19 +0530462 nvmem_param_t nvmem_param;
463 psa_handle_t handle = 0;
464 psa_status_t status_of_call = PSA_SUCCESS;
465 val_status_t status = VAL_STATUS_SUCCESS;
466 memory_desc_t *memory_desc;
jaypit02ea3cd062018-10-05 12:22:38 +0530467
jaypit02ac23b5b2018-11-02 13:10:19 +0530468 status = val_target_get_config(TARGET_CONFIG_CREATE_ID(GROUP_MEMORY, MEMORY_NVMEM, 0),
469 (uint8_t **)&memory_desc,
470 (uint32_t *)sizeof(memory_desc_t));
jaypit02ea3cd062018-10-05 12:22:38 +0530471
jaypit02ac23b5b2018-11-02 13:10:19 +0530472 if (VAL_ERROR(status))
473 {
474 return status;
475 }
476
477 nvmem_param.nvmem_fn_type = NVMEM_WRITE;
478 nvmem_param.base = memory_desc->start;
479 nvmem_param.offset = offset;
480 nvmem_param.size = size;
481 psa_invec invec[2] = {{&nvmem_param, sizeof(nvmem_param)}, {buffer, size}};
482
483 handle = psa_connect(DRIVER_NVMEM_SID, 0);
484 if (handle < 0)
485 {
486 return VAL_STATUS_CONNECTION_FAILED;
487 }
488 else
489 {
490 status_of_call = psa_call(handle, invec, 2, NULL, 0);
491 if (status_of_call != PSA_SUCCESS)
492 {
493 psa_close(handle);
494 return VAL_STATUS_CALL_FAILED;
495 }
496 }
jaypit02ea3cd062018-10-05 12:22:38 +0530497 psa_close(handle);
498 return VAL_STATUS_SUCCESS;
499}
500
501/**
502 @brief - This function sets the given boot.state value to corresponding
503 boot NVMEM location
504 @param - state: boot_state_t
505 @return - val_status_t
506**/
507STATIC_DECLARE val_status_t val_set_boot_flag(boot_state_t state)
508{
509 boot_t boot;
510 val_status_t status;
511
512 boot.state = state;
513 status = val_nvmem_write(VAL_NVMEM_OFFSET(NV_BOOT), &boot, sizeof(boot_t));
514 if (VAL_ERROR(status))
515 {
516 val_print(PRINT_ERROR, "val_nvmem_write failed Error=0x%x\n", status);
517 return status;
518 }
519 return status;
520}
521#endif