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