blob: fe32baae356dbec220530daeeb6071c998a6e7ca [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
jaypit02ea3cd062018-10-05 12:22:38 +053033__UNUSED STATIC_DECLARE val_status_t val_print
Jaykumar Pitambarbhai Patelf97bc882019-06-03 11:57:48 +053034 (print_verbosity_t verbosity, char *string, int32_t data);
jaypit02ea3cd062018-10-05 12:22:38 +053035__UNUSED STATIC_DECLARE val_status_t val_ipc_connect
36 (uint32_t sid, uint32_t minor_version, psa_handle_t *handle );
37__UNUSED STATIC_DECLARE val_status_t val_ipc_call
38 (psa_handle_t handle, psa_invec *in_vec, size_t in_len,
39 psa_outvec *out_vec, size_t out_len);
40__UNUSED STATIC_DECLARE void val_ipc_close
41 (psa_handle_t handle);
42__UNUSED STATIC_DECLARE val_status_t val_process_connect_request(psa_signal_t sig, psa_msg_t *msg);
43__UNUSED STATIC_DECLARE val_status_t val_process_call_request(psa_signal_t sig, psa_msg_t *msg);
44__UNUSED STATIC_DECLARE val_status_t val_process_disconnect_request
45 (psa_signal_t sig, psa_msg_t *msg);
46__UNUSED STATIC_DECLARE val_status_t val_execute_secure_tests
Jaykumar Pitambarbhai Patelf97bc882019-06-03 11:57:48 +053047 (test_info_t test_info, client_test_t *tests_list);
jaypit02ea3cd062018-10-05 12:22:38 +053048__UNUSED STATIC_DECLARE val_status_t val_execute_secure_test_func
49 (psa_handle_t *handle, test_info_t test_info, uint32_t sid);
50__UNUSED STATIC_DECLARE val_status_t val_get_secure_test_result(psa_handle_t *handle);
51__UNUSED STATIC_DECLARE val_status_t val_err_check_set(uint32_t checkpoint, val_status_t status);
52__UNUSED STATIC_DECLARE val_status_t val_nvmem_write(uint32_t offset, void *buffer, int size);
53__UNUSED STATIC_DECLARE val_status_t val_set_boot_flag(boot_state_t state);
54
55__UNUSED static val_api_t val_api = {
56 .print = val_print,
57 .err_check_set = val_err_check_set,
58 .execute_secure_test_func = val_execute_secure_test_func,
59 .get_secure_test_result = val_get_secure_test_result,
60 .ipc_connect = val_ipc_connect,
61 .ipc_call = val_ipc_call,
62 .ipc_close = val_ipc_close,
63 .set_boot_flag = val_set_boot_flag,
jaypit02ac23b5b2018-11-02 13:10:19 +053064 .target_get_config = val_target_get_config,
Jaykumar Pitambarbhai Patelf97bc882019-06-03 11:57:48 +053065 .process_connect_request = val_process_connect_request,
66 .process_call_request = val_process_call_request,
67 .process_disconnect_request= val_process_disconnect_request,
jaypit02ea3cd062018-10-05 12:22:38 +053068};
69
70__UNUSED static psa_api_t psa_api = {
71 .framework_version = psa_framework_version,
72 .version = psa_version,
73 .connect = psa_connect,
74 .call = psa_call,
75 .close = psa_close,
Jaykumar Pitambarbhai Patelf97bc882019-06-03 11:57:48 +053076 .wait = psa_wait,
77 .set_rhandle = psa_set_rhandle,
78 .get = psa_get,
79 .read = psa_read,
80 .skip = psa_skip,
81 .write = psa_write,
82 .reply = psa_reply,
83 .notify = psa_notify,
84 .clear = psa_clear,
85 .eoi = psa_eoi,
86 .rot_lifecycle_state = psa_rot_lifecycle_state,
jaypit02ea3cd062018-10-05 12:22:38 +053087};
88
89/**
90 @brief - Print module. This is client interface API of secure partition
91 val_print_sf API for spe world
92 @param - verbosity: Print verbosity level
93 - string : Input string
94 - data : Value for format specifier
95 @return - val_status_t
96**/
Jaykumar Pitambarbhai Patelf97bc882019-06-03 11:57:48 +053097STATIC_DECLARE val_status_t val_print(print_verbosity_t verbosity, char *string, int32_t data)
jaypit02ea3cd062018-10-05 12:22:38 +053098{
99 int string_len = 0;
100 char *p = string;
101 psa_handle_t print_handle = 0;
102 psa_status_t status_of_call = PSA_SUCCESS;
103 val_status_t status = VAL_STATUS_SUCCESS;
jaypit02ac23b5b2018-11-02 13:10:19 +0530104 uart_fn_type_t uart_fn = UART_PRINT;
105
106 if (verbosity < VERBOSE)
107 {
108 return VAL_STATUS_SUCCESS;
109 }
jaypit02ea3cd062018-10-05 12:22:38 +0530110
111 while (*p != '\0')
112 {
113 string_len++;
114 p++;
115 }
116
Jaykumar Pitambarbhai Patelf97bc882019-06-03 11:57:48 +0530117 psa_invec data1[3] = {{&uart_fn, sizeof(uart_fn)}, {string, string_len+1}, {&data, sizeof(data)}};
jaypit02ea3cd062018-10-05 12:22:38 +0530118 print_handle = psa_connect(DRIVER_UART_SID, 0);
119
120 if (print_handle < 0)
121 {
122 return VAL_STATUS_CONNECTION_FAILED;
123 }
124 else
125 {
126 status_of_call = psa_call(print_handle, data1, 3, NULL, 0);
127 if (status_of_call != PSA_SUCCESS)
128 {
129 status = VAL_STATUS_CALL_FAILED;
130 }
131 }
132 psa_close(print_handle);
133 return status;
134}
135
136/**
137 * @brief Connect to given sid
138 @param -sid : RoT service id
139 @param -minor_version : minor_version of RoT service
140 @param -handle - return connection handle
141 * @return val_status_t
142 */
143STATIC_DECLARE val_status_t val_ipc_connect(uint32_t sid, uint32_t minor_version,
144 psa_handle_t *handle )
145{
146 *handle = psa_connect(sid, minor_version);
147
148 if (*handle < 0)
149 {
150 return(VAL_STATUS_CONNECTION_FAILED);
151 }
152
153 return VAL_STATUS_SUCCESS;
154}
155
156/**
157 * @brief Call a connected Root of Trust Service.@n
158 * The caller must provide an array of ::psa_invec_t structures as the input payload.
159 * @param handle: Handle for the connection.
160 * @param in_vec: Array of psa_invec structures.
161 * @param in_len: Number of psa_invec structures in in_vec.
162 * @param out_vec: Array of psa_outvec structures for optional Root of Trust Service response.
163 * @param out_len: Number of psa_outvec structures in out_vec.
164 * @return val_status_t
165 */
166STATIC_DECLARE val_status_t val_ipc_call(psa_handle_t handle, psa_invec *in_vec, size_t in_len,
167 psa_outvec *out_vec, size_t out_len)
168{
169 psa_status_t call_status = PSA_SUCCESS;
170
171 call_status = psa_call(handle, in_vec, in_len, out_vec, out_len);
172
173 if (call_status != PSA_SUCCESS)
174 {
175 return(VAL_STATUS_CALL_FAILED);
176 }
177
178 return VAL_STATUS_SUCCESS;
179}
180
181/**
182 * @brief Close a connection to a Root of Trust Service.
183 * Sends the PSA_IPC_DISCONNECT message to the Root of Trust Service so
184 it can clean up resources.
185 * @param handle: Handle for the connection.
186 * @return void
187 */
188STATIC_DECLARE void val_ipc_close(psa_handle_t handle)
189{
190 psa_close(handle);
191}
192
193/**
194 * @brief Proccess a generic connect message to given rot signal.
195 @param -sig : signal to be processed
196 @param -msg : return msg info of given signal
197 * @return val_status_t.
198 */
199STATIC_DECLARE val_status_t val_process_connect_request(psa_signal_t sig, psa_msg_t *msg)
200{
201 val_status_t res = VAL_STATUS_ERROR;
202 psa_signal_t signals;
203
204wait1:
jaypit02ac23b5b2018-11-02 13:10:19 +0530205 signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
jaypit02ea3cd062018-10-05 12:22:38 +0530206 if (signals & sig)
207 {
208 if (psa_get(sig, msg) != PSA_SUCCESS)
209 {
210 goto wait1;
211 }
212
213 if ((msg->type != PSA_IPC_CONNECT) || (msg->handle <= 0))
214 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530215 val_print(PRINT_ERROR, "\tpsa_get failed for PSA_IPC_CONNECT\n", 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530216 res = VAL_STATUS_ERROR;
217 }
218 else
219 {
220 res = VAL_STATUS_SUCCESS;
221 }
222 }
223 else
224 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530225 val_print(PRINT_ERROR, "\tpsa_wait returned with invalid signal value = 0x%x\n", signals);
jaypit02ea3cd062018-10-05 12:22:38 +0530226 res = VAL_STATUS_ERROR;
227 }
228 return res;
229}
230
231/**
232 * @brief Proccess a generic call message to given rot signal.
233 @param -sig : signal to be processed
234 @param -msg : return msg info of given signal
235 * @return val_status_t
236 */
237STATIC_DECLARE val_status_t val_process_call_request(psa_signal_t sig, psa_msg_t *msg)
238{
239 val_status_t res = VAL_STATUS_ERROR;
240 psa_signal_t signals;
241
242wait2:
jaypit02ac23b5b2018-11-02 13:10:19 +0530243 signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
jaypit02ea3cd062018-10-05 12:22:38 +0530244 if (signals & sig)
245 {
246 if (psa_get(sig, msg) != PSA_SUCCESS)
247 {
248 goto wait2;
249 }
250
251 if ((msg->type != PSA_IPC_CALL) || (msg->handle <= 0))
252 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530253 val_print(PRINT_ERROR, "\tpsa_get failed for PSA_IPC_CALL\n", 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530254 res = VAL_STATUS_ERROR;
255 }
256 else
257 {
258 res = VAL_STATUS_SUCCESS;
259 }
260 }
261 else
262 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530263 val_print(PRINT_ERROR, "\tpsa_wait returned with invalid signal value = 0x%x\n", signals);
jaypit02ea3cd062018-10-05 12:22:38 +0530264 res = VAL_STATUS_ERROR;
265 }
266 return res;
267}
268
269/**
270 * @brief Proccess a generic disconnect message to given rot signal.
271 @param -sig : signal to be processed
272 @param -msg : return msg info of given signal
273 * @return val_status_t
274 */
275STATIC_DECLARE val_status_t val_process_disconnect_request(psa_signal_t sig, psa_msg_t *msg)
276{
277 val_status_t res = VAL_STATUS_ERROR;
278 psa_signal_t signals;
279
280wait3:
jaypit02ac23b5b2018-11-02 13:10:19 +0530281 signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
jaypit02ea3cd062018-10-05 12:22:38 +0530282 if (signals & sig)
283 {
284 if (psa_get(sig, msg) != PSA_SUCCESS)
285 {
286 goto wait3;
287 }
288
289 if ((msg->type != PSA_IPC_DISCONNECT) || (msg->handle <= 0))
290 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530291 val_print(PRINT_ERROR, "\tpsa_get failed for PSA_IPC_DISCONNECT\n", 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530292 res = VAL_STATUS_ERROR;
293 }
294 else
295 {
296 res = VAL_STATUS_SUCCESS;
297 }
298 }
299 else
300 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530301 val_print(PRINT_ERROR, "\tpsa_wait returned with invalid signal value = 0x%x\n", signals);
jaypit02ea3cd062018-10-05 12:22:38 +0530302 res = VAL_STATUS_ERROR;
303 }
304 return res;
305}
306
307/**
308 @brief - This function executes given list of tests from secure sequentially
309 This covers secure to secure IPC API scenario
Jaykumar Pitambarbhai Patelf97bc882019-06-03 11:57:48 +0530310 @param - test_info_t : test_num and block_num
jaypit02ea3cd062018-10-05 12:22:38 +0530311 @param - tests_list : list of tests to be executed
312 @return - val_status_t
313**/
Jaykumar Pitambarbhai Patelf97bc882019-06-03 11:57:48 +0530314STATIC_DECLARE val_status_t val_execute_secure_tests(test_info_t test_info, client_test_t *tests_list)
jaypit02ea3cd062018-10-05 12:22:38 +0530315{
316 val_status_t status = VAL_STATUS_SUCCESS;
317 val_status_t test_status = VAL_STATUS_SUCCESS;
318 psa_handle_t handle;
Jaykumar Pitambarbhai Patelf97bc882019-06-03 11:57:48 +0530319 int i = test_info.block_num;
jaypit02ea3cd062018-10-05 12:22:38 +0530320
321 while (tests_list[i] != NULL)
322 {
Jaykumar Pitambarbhai Patelf97bc882019-06-03 11:57:48 +0530323 if (i == 1)
324 val_print(PRINT_TEST, "[Info] Executing tests from secure\n", 0);
jaypit02ea3cd062018-10-05 12:22:38 +0530325
326 /* Handshake with server tests */
327 test_info.block_num = i;
328 status = val_execute_secure_test_func(&handle, test_info, SERVER_TEST_DISPATCHER_SID);
329 if (VAL_ERROR(status))
330 {
331 val_print(PRINT_ERROR,"[Check%d] START\n", i);
332 return status;
333 }
334 else
335 {
336 val_print(PRINT_DEBUG,"[Check%d] START\n", i);
337 }
338
339 /* Execute client tests */
Gowtham Siddarthb1cd50f2019-08-21 11:50:26 +0530340 test_status = tests_list[i](CALLER_SECURE);
jaypit02ea3cd062018-10-05 12:22:38 +0530341
342 /* Retrive Server test status */
343 status = val_get_secure_test_result(&handle);
344
345 status = test_status ? test_status:status;
Gowtham Siddarth47223082019-01-17 09:59:50 +0530346 if (IS_TEST_SKIP(status))
347 {
348 val_print(PRINT_DEBUG, "[Check%d] SKIPPED\n", i);
349 return status;
350 }
jaypit02ea3cd062018-10-05 12:22:38 +0530351 if (VAL_ERROR(status))
352 {
Gowtham Siddarth47223082019-01-17 09:59:50 +0530353 val_print(PRINT_DEBUG,"[Check%d] FAILED\n", i);
jaypit02ea3cd062018-10-05 12:22:38 +0530354 return status;
355 }
356 else
357 {
358 val_print(PRINT_DEBUG,"[Check%d] PASSED\n", i);
359 }
360 i++;
361 }
362 return status;
363}
364
365/**
366 @brief - This function is used to handshake between:
367 - nonsecure client to server test fn
368 - secure client and server test fn
369 - nonsecure client to secure client test fn
370 @param - handle : handle returned while connecting given sid
371 @param - test_info : Test_num and block_num to be executed
372 @param - sid : RoT service to be connected. Partition dispatcher sid
373 @return - val_status_t
374**/
375STATIC_DECLARE val_status_t val_execute_secure_test_func(psa_handle_t *handle,
376 test_info_t test_info,
377 uint32_t sid)
378{
379 uint32_t test_data;
380 val_status_t status = VAL_STATUS_SUCCESS;
381 psa_status_t status_of_call = PSA_SUCCESS;
382
383 *handle = psa_connect(sid, 0);
384
385 if (*handle < 0)
386 {
387 val_print(PRINT_ERROR, "Could not connect SID. Handle=%x\n", *handle);
388 status = VAL_STATUS_CONNECTION_FAILED;
389 }
390
391 test_data = ((uint32_t)(test_info.test_num) | ((uint32_t)(test_info.block_num) << BLOCK_NUM_POS)
392 | ((uint32_t)(TEST_EXECUTE_FUNC) << ACTION_POS));
393 psa_invec data[1] = {{&test_data, sizeof(test_data)}};
394
395 status_of_call = psa_call(*handle, data, 1, NULL, 0);
396
397 if (status_of_call != PSA_SUCCESS)
398 {
399 status = VAL_STATUS_CALL_FAILED;
400 val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call);
401 psa_close(*handle);
402 }
403 return status;
404}
405
406/**
407 @brief - This function is used to retrive the status of previously connected test function
408 using val_execute_secure_test_func
409 @param - handle : handle of server function. Handle of Partition dispatcher sid
410 @return - The status of test functions
411**/
412STATIC_DECLARE val_status_t val_get_secure_test_result(psa_handle_t *handle)
413{
414 uint32_t test_data;
415 val_status_t status = VAL_STATUS_SUCCESS;
416 psa_status_t status_of_call = PSA_SUCCESS;
417
418 test_data = (TEST_RETURN_RESULT << ACTION_POS);
419
420 psa_outvec resp = {&status, sizeof(status)};
421 psa_invec data[1] = {{&test_data, sizeof(test_data)}};
422
423 status_of_call = psa_call(*handle, data, 1, &resp, 1);
424 if (status_of_call != PSA_SUCCESS)
425 {
426 status = VAL_STATUS_CALL_FAILED;
427 val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call);
428 }
429
430 psa_close(*handle);
431 return status;
432}
433
434/*
435 @brief - This function checks if the input status argument is an error.
436 On error, print the checkpoint value
437 @param - checkpoint : Test debug checkpoint
438 - val_status_t : Test status
439 @return - returns the input status back to the program.
440*/
441STATIC_DECLARE val_status_t val_err_check_set(uint32_t checkpoint, val_status_t status)
442{
443 if (VAL_ERROR(status))
444 {
445 val_print(PRINT_ERROR, "\tCheckpoint %d : ", checkpoint);
446 val_print(PRINT_ERROR, "Error Code=0x%x \n", status);
447 }
448 else
449 {
450 val_print(PRINT_DEBUG, "\tCheckpoint %d \n", checkpoint);
451 }
452 return status;
453}
454
455/*
456 @brief - Writes 'size' bytes from buffer into non-volatile memory at a given
457 'base + offset'. This is client interface API of secure partition
458 val_nvmem_write_sf API for spe world
459 - offset : Offset
460 - buffer : Pointer to source address
461 - size : Number of bytes
462 @return - val_status_t
463*/
464STATIC_DECLARE val_status_t val_nvmem_write(uint32_t offset, void *buffer, int size)
465{
jaypit02ac23b5b2018-11-02 13:10:19 +0530466 nvmem_param_t nvmem_param;
467 psa_handle_t handle = 0;
468 psa_status_t status_of_call = PSA_SUCCESS;
469 val_status_t status = VAL_STATUS_SUCCESS;
470 memory_desc_t *memory_desc;
jaypit02ea3cd062018-10-05 12:22:38 +0530471
jaypit02ac23b5b2018-11-02 13:10:19 +0530472 status = val_target_get_config(TARGET_CONFIG_CREATE_ID(GROUP_MEMORY, MEMORY_NVMEM, 0),
473 (uint8_t **)&memory_desc,
474 (uint32_t *)sizeof(memory_desc_t));
jaypit02ea3cd062018-10-05 12:22:38 +0530475
jaypit02ac23b5b2018-11-02 13:10:19 +0530476 if (VAL_ERROR(status))
477 {
478 return status;
479 }
480
481 nvmem_param.nvmem_fn_type = NVMEM_WRITE;
482 nvmem_param.base = memory_desc->start;
483 nvmem_param.offset = offset;
484 nvmem_param.size = size;
485 psa_invec invec[2] = {{&nvmem_param, sizeof(nvmem_param)}, {buffer, size}};
486
487 handle = psa_connect(DRIVER_NVMEM_SID, 0);
488 if (handle < 0)
489 {
490 return VAL_STATUS_CONNECTION_FAILED;
491 }
492 else
493 {
494 status_of_call = psa_call(handle, invec, 2, NULL, 0);
495 if (status_of_call != PSA_SUCCESS)
496 {
497 psa_close(handle);
498 return VAL_STATUS_CALL_FAILED;
499 }
500 }
jaypit02ea3cd062018-10-05 12:22:38 +0530501 psa_close(handle);
502 return VAL_STATUS_SUCCESS;
503}
504
505/**
506 @brief - This function sets the given boot.state value to corresponding
507 boot NVMEM location
508 @param - state: boot_state_t
509 @return - val_status_t
510**/
511STATIC_DECLARE val_status_t val_set_boot_flag(boot_state_t state)
512{
513 boot_t boot;
514 val_status_t status;
515
516 boot.state = state;
517 status = val_nvmem_write(VAL_NVMEM_OFFSET(NV_BOOT), &boot, sizeof(boot_t));
518 if (VAL_ERROR(status))
519 {
Jaykumar Pitambarbhai Patelf97bc882019-06-03 11:57:48 +0530520 val_print(PRINT_ERROR, "\tval_nvmem_write failed Error=0x%x\n", status);
jaypit02ea3cd062018-10-05 12:22:38 +0530521 return status;
522 }
523 return status;
524}
525#endif