blob: 764811611925a598283b28ea0c14de150e895459 [file] [log] [blame]
jaypit02ea3cd062018-10-05 12:22:38 +05301/** @file
2 * Copyright (c) 2018, 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/* 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
29#include "val/common/val.h"
jaypit02ac23b5b2018-11-02 13:10:19 +053030#include "val/common/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 {
209 val_print(PRINT_ERROR, "\npsa_get failed for PSA_IPC_CONNECT", 0);
210 res = VAL_STATUS_ERROR;
211 }
212 else
213 {
214 res = VAL_STATUS_SUCCESS;
215 }
216 }
217 else
218 {
jaypit02ac23b5b2018-11-02 13:10:19 +0530219 val_print(PRINT_ERROR, "\npsa_wait returned with invalid signal value = 0x%x", 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 {
247 val_print(PRINT_ERROR, "\npsa_get failed for PSA_IPC_CALL", 0);
248 res = VAL_STATUS_ERROR;
249 }
250 else
251 {
252 res = VAL_STATUS_SUCCESS;
253 }
254 }
255 else
256 {
jaypit02ac23b5b2018-11-02 13:10:19 +0530257 val_print(PRINT_ERROR, "\npsa_wait returned with invalid signal value = 0x%x", 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 {
285 val_print(PRINT_ERROR, "\npsa_get failed for PSA_IPC_DISCONNECT", 0);
286 res = VAL_STATUS_ERROR;
287 }
288 else
289 {
290 res = VAL_STATUS_SUCCESS;
291 }
292 }
293 else
294 {
jaypit02ac23b5b2018-11-02 13:10:19 +0530295 val_print(PRINT_ERROR, "\npsa_wait returned with invalid signal value = 0x%x", 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;
317 val_print(PRINT_TEST, "[Info] Executing tests form secure\n", 0);
318
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;
342 if (VAL_ERROR(status))
343 {
344 val_print(PRINT_ERROR,"[Check%d] FAILED\n", i);
345 return status;
346 }
347 else
348 {
349 val_print(PRINT_DEBUG,"[Check%d] PASSED\n", i);
350 }
351 i++;
352 }
353 return status;
354}
355
356/**
357 @brief - This function is used to handshake between:
358 - nonsecure client to server test fn
359 - secure client and server test fn
360 - nonsecure client to secure client test fn
361 @param - handle : handle returned while connecting given sid
362 @param - test_info : Test_num and block_num to be executed
363 @param - sid : RoT service to be connected. Partition dispatcher sid
364 @return - val_status_t
365**/
366STATIC_DECLARE val_status_t val_execute_secure_test_func(psa_handle_t *handle,
367 test_info_t test_info,
368 uint32_t sid)
369{
370 uint32_t test_data;
371 val_status_t status = VAL_STATUS_SUCCESS;
372 psa_status_t status_of_call = PSA_SUCCESS;
373
374 *handle = psa_connect(sid, 0);
375
376 if (*handle < 0)
377 {
378 val_print(PRINT_ERROR, "Could not connect SID. Handle=%x\n", *handle);
379 status = VAL_STATUS_CONNECTION_FAILED;
380 }
381
382 test_data = ((uint32_t)(test_info.test_num) | ((uint32_t)(test_info.block_num) << BLOCK_NUM_POS)
383 | ((uint32_t)(TEST_EXECUTE_FUNC) << ACTION_POS));
384 psa_invec data[1] = {{&test_data, sizeof(test_data)}};
385
386 status_of_call = psa_call(*handle, data, 1, NULL, 0);
387
388 if (status_of_call != PSA_SUCCESS)
389 {
390 status = VAL_STATUS_CALL_FAILED;
391 val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call);
392 psa_close(*handle);
393 }
394 return status;
395}
396
397/**
398 @brief - This function is used to retrive the status of previously connected test function
399 using val_execute_secure_test_func
400 @param - handle : handle of server function. Handle of Partition dispatcher sid
401 @return - The status of test functions
402**/
403STATIC_DECLARE val_status_t val_get_secure_test_result(psa_handle_t *handle)
404{
405 uint32_t test_data;
406 val_status_t status = VAL_STATUS_SUCCESS;
407 psa_status_t status_of_call = PSA_SUCCESS;
408
409 test_data = (TEST_RETURN_RESULT << ACTION_POS);
410
411 psa_outvec resp = {&status, sizeof(status)};
412 psa_invec data[1] = {{&test_data, sizeof(test_data)}};
413
414 status_of_call = psa_call(*handle, data, 1, &resp, 1);
415 if (status_of_call != PSA_SUCCESS)
416 {
417 status = VAL_STATUS_CALL_FAILED;
418 val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call);
419 }
420
421 psa_close(*handle);
422 return status;
423}
424
425/*
426 @brief - This function checks if the input status argument is an error.
427 On error, print the checkpoint value
428 @param - checkpoint : Test debug checkpoint
429 - val_status_t : Test status
430 @return - returns the input status back to the program.
431*/
432STATIC_DECLARE val_status_t val_err_check_set(uint32_t checkpoint, val_status_t status)
433{
434 if (VAL_ERROR(status))
435 {
436 val_print(PRINT_ERROR, "\tCheckpoint %d : ", checkpoint);
437 val_print(PRINT_ERROR, "Error Code=0x%x \n", status);
438 }
439 else
440 {
441 val_print(PRINT_DEBUG, "\tCheckpoint %d \n", checkpoint);
442 }
443 return status;
444}
445
446/*
447 @brief - Writes 'size' bytes from buffer into non-volatile memory at a given
448 'base + offset'. This is client interface API of secure partition
449 val_nvmem_write_sf API for spe world
450 - offset : Offset
451 - buffer : Pointer to source address
452 - size : Number of bytes
453 @return - val_status_t
454*/
455STATIC_DECLARE val_status_t val_nvmem_write(uint32_t offset, void *buffer, int size)
456{
jaypit02ac23b5b2018-11-02 13:10:19 +0530457 nvmem_param_t nvmem_param;
458 psa_handle_t handle = 0;
459 psa_status_t status_of_call = PSA_SUCCESS;
460 val_status_t status = VAL_STATUS_SUCCESS;
461 memory_desc_t *memory_desc;
jaypit02ea3cd062018-10-05 12:22:38 +0530462
jaypit02ac23b5b2018-11-02 13:10:19 +0530463 status = val_target_get_config(TARGET_CONFIG_CREATE_ID(GROUP_MEMORY, MEMORY_NVMEM, 0),
464 (uint8_t **)&memory_desc,
465 (uint32_t *)sizeof(memory_desc_t));
jaypit02ea3cd062018-10-05 12:22:38 +0530466
jaypit02ac23b5b2018-11-02 13:10:19 +0530467 if (VAL_ERROR(status))
468 {
469 return status;
470 }
471
472 nvmem_param.nvmem_fn_type = NVMEM_WRITE;
473 nvmem_param.base = memory_desc->start;
474 nvmem_param.offset = offset;
475 nvmem_param.size = size;
476 psa_invec invec[2] = {{&nvmem_param, sizeof(nvmem_param)}, {buffer, size}};
477
478 handle = psa_connect(DRIVER_NVMEM_SID, 0);
479 if (handle < 0)
480 {
481 return VAL_STATUS_CONNECTION_FAILED;
482 }
483 else
484 {
485 status_of_call = psa_call(handle, invec, 2, NULL, 0);
486 if (status_of_call != PSA_SUCCESS)
487 {
488 psa_close(handle);
489 return VAL_STATUS_CALL_FAILED;
490 }
491 }
jaypit02ea3cd062018-10-05 12:22:38 +0530492 psa_close(handle);
493 return VAL_STATUS_SUCCESS;
494}
495
496/**
497 @brief - This function sets the given boot.state value to corresponding
498 boot NVMEM location
499 @param - state: boot_state_t
500 @return - val_status_t
501**/
502STATIC_DECLARE val_status_t val_set_boot_flag(boot_state_t state)
503{
504 boot_t boot;
505 val_status_t status;
506
507 boot.state = state;
508 status = val_nvmem_write(VAL_NVMEM_OFFSET(NV_BOOT), &boot, sizeof(boot_t));
509 if (VAL_ERROR(status))
510 {
511 val_print(PRINT_ERROR, "val_nvmem_write failed Error=0x%x\n", status);
512 return status;
513 }
514 return status;
515}
516#endif