blob: 7cf1b621fc9e1000a962d9a614f5f0be7b7bd381 [file] [log] [blame]
Karl Zhang3de5ab12021-05-31 11:45:48 +08001/*
Nik Dewally298a8042024-07-23 15:03:13 +01002 * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
Karl Zhang3de5ab12021-05-31 11:45:48 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
Nik Dewallybacae6c2024-07-30 16:58:14 +01008#include <vector>
Karl Zhang3de5ab12021-05-31 11:45:48 +08009
10#include "boilerplate.hpp"
Karl Zhang3de5ab12021-05-31 11:45:48 +080011#include "string_ops.hpp"
12#include "data_blocks.hpp"
13#include "psa_asset.hpp"
14#include "find_or_create_asset.hpp"
Karl Zhang3de5ab12021-05-31 11:45:48 +080015#include "tf_fuzz.hpp"
Karl Zhang3de5ab12021-05-31 11:45:48 +080016#include "psa_call.hpp"
17#include "sst_call.hpp"
18#include "sst_asset.hpp"
Karl Zhang3de5ab12021-05-31 11:45:48 +080019#include "variables.hpp"
20
21
22
23/**********************************************************************************
24 Methods of class sst_set_call follow:
25**********************************************************************************/
26
27sst_set_call::sst_set_call (tf_fuzz_info *test_state, // (constructor)
28 long &call_ser_no,
29 asset_search how_asset_found)
30 : sst_call(test_state, call_ser_no, how_asset_found)
31{
32 // Copy the boilerplate text into local buffers:
33 prep_code.assign (""); // will fill in, depending upon template line content
34 call_code.assign (test_state->bplate->bplate_string[set_sst_call]);
35 check_code.assign (test_state->bplate->bplate_string[set_sst_check]);
36 call_description = "SST-set call";
37}
38sst_set_call::~sst_set_call (void)
39{
40 return; // just to have something to pin a breakpoint onto
41}
42
43bool sst_set_call::copy_call_to_asset (void)
44{
45 vector<psa_asset*>::iterator found_asset;
46
47 found_asset = resolve_asset (yes_create_asset, psa_asset_usage::all);
48 // Copy over everything relevant:
49 if (asset_info.how_asset_found != asset_search::not_found) {
50 asset_info.the_asset = reinterpret_cast<sst_asset*>(*found_asset);
51 /* Note: The vector is base-class, but the assets in this list
52 themselves *really are* sst_asset-type objects. */
53 int i = asset_info.the_asset->set_data.n_set_vars; // save this
Mate Toth-Palffba10e2021-09-22 21:38:03 +020054 asset_info.the_asset->set_data = set_data;
Karl Zhang3de5ab12021-05-31 11:45:48 +080055 asset_info.the_asset->set_data.n_set_vars = set_data.n_set_vars = ++i;
56 asset_info.the_asset->set_data.flags_string.assign (set_data.flags_string);
57 if (asset_info.how_asset_found == asset_search::created_new) {
58 asset_info.the_asset->asset_info.name_specified = asset_info.name_specified;
59 asset_info.the_asset->asset_info.set_name (asset_info.get_name());
60 asset_info.the_asset->asset_info.asset_ser_no = asset_info.asset_ser_no;
61 asset_info.the_asset->asset_info.id_n = asset_info.id_n;
62 }
63 }
64 return true;
65}
66
67bool sst_set_call::copy_asset_to_call (void)
68{
69 // Get updated asset info from the asset:
70 asset_info.asset_ser_no = asset_info.the_asset->asset_info.asset_ser_no;
71 asset_info.id_n = asset_info.the_asset->asset_info.id_n;
72 exp_data.n_exp_vars = asset_info.the_asset->exp_data.n_exp_vars;
73 exp_data.data = asset_info.the_asset->exp_data.data;
74 return true;
75}
76
77void sst_set_call::fill_in_prep_code (void)
78{
79 string var_name, length_var_name, var_name_suffix, length_var_name_suffix,
80 temp_string;
81 vector<variable_info>::iterator assign_variable;
82
83 if (assign_data_var_specified) {
84 var_name.assign (assign_data_var + "_data");
85 length_var_name.assign (assign_data_var + "_length");
86 /* If actual-data variable doesn't already exist, create variable tracker,
87 and write declaration for it: */
88 assign_variable = test_state->find_var (assign_data_var);
89 if (assign_variable == test_state->variable.end()) {
90 // No such variable exists, so:
91 test_state->make_var (assign_data_var);
92 assign_variable = test_state->find_var (assign_data_var);
93 prep_code.append (test_state->bplate->bplate_string[declare_big_string]);
94 find_replace_1st ("$var", var_name, prep_code);
95 temp_string = (char *) assign_variable->value;
96 find_replace_1st ("$init", temp_string, prep_code);
97 // Actual-data length:
98 prep_code.append (test_state->bplate->bplate_string[declare_size_t]);
99 find_replace_1st ("$var", length_var_name, prep_code);
100 find_replace_1st ("$init", to_string(temp_string.length()), prep_code);
101 // Offset (always 0 for now):
102 find_replace_1st ("$offset", "0", prep_code);
103 }
104 } else {
105 // Single string of two lines declaring string data and its length:
106 var_name_suffix = "_set_data";
107 length_var_name_suffix = "_set_length";
108 if (set_data.n_set_vars > 0) {
109 var_name_suffix += "_" + to_string(set_data.n_set_vars);
110 length_var_name_suffix += "_" + to_string(set_data.n_set_vars);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800111 }
112 var_name.assign (asset_info.get_name() + var_name_suffix);
113 length_var_name.assign (asset_info.get_name() + length_var_name_suffix);
114 prep_code = test_state->bplate->bplate_string[declare_string];
115 find_replace_1st ("$var", var_name, prep_code);
116 find_replace_1st ("$init", set_data.get(), prep_code);
117 temp_string.assign (test_state->bplate->bplate_string[declare_int]);
118 find_replace_1st ("static int", "static uint32_t", temp_string);
119 prep_code.append (temp_string);
120 find_replace_1st ("$var", length_var_name, prep_code);
121 find_replace_1st ("$init", to_string(set_data.get().length()), prep_code);
122 }
123}
124
125void sst_set_call::fill_in_command (void)
126{
127 string var_name, length_var_name, var_name_suffix, length_var_name_suffix,
128 temp_string;
129
130 // Fill in preceding comment:
131 if (asset_info.how_asset_found == asset_search::created_new) {
132 find_replace_1st ("$op", "Creating", call_code);
133 } else {
134 find_replace_1st ("$op", "Resetting", call_code);
135 }
136 if (asset_info.name_specified) {
137 find_replace_1st ("$description", "\"" + asset_info.get_name() + ",\"",
138 call_code);
139 } else {
140 find_replace_1st ("$description",
141 "UID = " + to_string((long) asset_info.id_n), call_code);
142 }
143 if (set_data.string_specified) {
144 find_replace_1st ("$data_source",
145 "\"" + set_data.get().substr (0, 10) + "...\"",
146 call_code);
147 } else if (set_data.file_specified) {
148 find_replace_1st ("$data_source", "from file " + set_data.file_path,
149 call_code);
150 } else {
151 find_replace_1st (" $data_source", "", call_code);
152 }
153 // Fill in the PSA command itself:
154 if (assign_data_var_specified) {
155 var_name.assign (assign_data_var + "_data");
156 length_var_name.assign (assign_data_var + "_length");
157 } else {
158 var_name_suffix = "_set_data";
159 if (set_data.n_set_vars > 0) {
160 var_name_suffix += "_" + to_string(set_data.n_set_vars);
161 }
162 var_name.assign (asset_info.get_name() + var_name_suffix);
163 length_var_name_suffix = "_set_length";
164 if (set_data.n_set_vars > 0) {
165 length_var_name_suffix += "_" + to_string(set_data.n_set_vars);
166 }
167 length_var_name.assign (asset_info.get_name() + length_var_name_suffix);
168 }
169 find_replace_1st ("$data", var_name, call_code);
170 find_replace_1st ("$flags", set_data.flags_string, call_code);
171 string id_string = to_string((long) asset_info.id_n);
172 find_replace_1st ("$uid", id_string, call_code);
173 find_replace_1st ("$length", length_var_name, call_code);
Nik Dewally6663dde2024-08-09 16:12:27 +0100174
175 // TODO: move error code modelling to simulate().
176
Karl Zhang3de5ab12021-05-31 11:45:48 +0800177 // Figure out what expected results:
Nik Dewally6663dde2024-08-09 16:12:27 +0100178 if (set_data.flags_string == "PSA_STORAGE_FLAG_WRITE_ONCE"
Karl Zhang3de5ab12021-05-31 11:45:48 +0800179 && set_data.n_set_vars > 0) {
Nik Dewally6663dde2024-08-09 16:12:27 +0100180 exp_data.expect_error_code("PSA_ERROR_NOT_PERMITTED");
Karl Zhang3de5ab12021-05-31 11:45:48 +0800181 }
Nik Dewally6663dde2024-08-09 16:12:27 +0100182 fill_in_result_code();
Karl Zhang3de5ab12021-05-31 11:45:48 +0800183}
184
185/**********************************************************************************
186 End of methods of class sst_set_call.
187**********************************************************************************/
188
189
190/**********************************************************************************
191 Methods of class sst_get_call follow:
192**********************************************************************************/
193
194sst_get_call::sst_get_call (tf_fuzz_info *test_state, // (constructor)
195 long &call_ser_no,
196 asset_search how_asset_found)
197 : sst_call(test_state, call_ser_no, how_asset_found)
198{
199 // Copy the boilerplate text into local buffers:
200 prep_code.assign ("");
201 call_code.assign (test_state->bplate->bplate_string[get_sst_call]);
202 check_code.assign ("");
203 // depends upon the particular usage; will get it in fill_in_command()
204 call_description = "SST-get call";
205}
206sst_get_call::~sst_get_call (void)
207{
208 return; // just to have something to pin a breakpoint onto
209}
210
211bool sst_get_call::copy_call_to_asset (void)
212{
213 vector<psa_asset*>::iterator found_asset;
214
215 found_asset = resolve_asset (dont_create_asset, psa_asset_usage::active);
216 if (asset_info.how_asset_found != asset_search::not_found) {
217 // will be found for set calls, but not necessarily others
218 asset_info.the_asset = reinterpret_cast<sst_asset*>(*found_asset);
219 // Note: Vector is of base-class type, but the assets *are* sst_asset.
220 /* Locating the asset is all we need to do here; copy_asset_to_call() will
221 do the rest. */
222 }
223 return true;
224 // TODO: Shouldn't data be copied over?
225}
226
227bool sst_get_call::copy_asset_to_call (void)
228{
229 if (asset_info.the_asset != nullptr) {
230 // will be found for set calls, but not necessarily others
231 set_data.string_specified = asset_info.the_asset->set_data.string_specified;
232 set_data.file_specified = asset_info.the_asset->set_data.file_specified;
233 set_data.set (asset_info.the_asset->set_data.get());
234 set_data.flags_string = asset_info.the_asset->set_data.flags_string;
235 asset_info.id_n = asset_info.the_asset->asset_info.id_n;
236 asset_info.asset_ser_no = asset_info.the_asset->asset_info.asset_ser_no;
237 asset_info.name_specified = asset_info.the_asset->asset_info.name_specified;
238 asset_info.the_asset->exp_data.n_exp_vars++;
239 exp_data.n_exp_vars = asset_info.the_asset->exp_data.n_exp_vars;
240 }
241 return true;
242}
243
244void sst_get_call::fill_in_prep_code (void)
245{
246 string var_base, var_name, length_var_name, temp_string, var_name_suffix,
247 expected;
248 vector<variable_info>::iterator act_variable, exp_variable;
249
250 if (!(print_data || hash_data)) {
251 // Checking asset data verbatim against expected, so:
252 if (exp_data.data_var_specified) {
253 // Template specified a variable name to "check" against; use that:
254 var_base.assign (exp_data.data_var);
255 exp_variable = test_state->find_var (var_base);
256 if (exp_variable == test_state->variable.end()) {
257 test_state->make_var (var_base);
258 exp_variable = test_state->find_var (var_base);
259 var_name = var_base + "_data";
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200260 length_var_name = var_base + "_length";
Karl Zhang3de5ab12021-05-31 11:45:48 +0800261 prep_code.append (test_state->bplate->bplate_string[declare_string]);
262 find_replace_1st ("$var", var_name, prep_code);
263 temp_string = (char *) exp_variable->value;
264 find_replace_1st ("$init", temp_string, prep_code);
265 // Expected-data length:
266 temp_string.assign (test_state->bplate->bplate_string[declare_int]);
267 find_replace_1st ("static int", "static size_t", temp_string);
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200268 prep_code.append (temp_string);
269 find_replace_1st ("$var", length_var_name, prep_code);
270 find_replace_1st ("$init", to_string(temp_string.length()), prep_code);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800271 }
272 } else {
273 if (exp_data.data_specified) {
274 // Checking against literal expected data:
275 expected.assign (exp_data.data);
276 } else {
277 // Check against what we believe the asset to contain:
278 expected.assign (set_data.get());
279 }
280 var_name_suffix = "_exp_data";
281 if (exp_data.n_exp_vars > 0) {
282 var_name_suffix =
283 var_name_suffix + "_" + to_string(exp_data.n_exp_vars);
284 }
285 var_name.assign (asset_info.get_name() + var_name_suffix);
286 prep_code.assign(test_state->bplate->bplate_string[declare_string]);
287 find_replace_1st("$var", var_name, prep_code);
288 find_replace_1st("$init", expected, prep_code);
289 }
290 }
291 // Actual data:
292 if (assign_data_var_specified) {
293 var_base.assign (assign_data_var);
294 } else {
295 var_base.assign (asset_info.get_name() + "_act");
296 }
297 var_name.assign (var_base + "_data");
298 length_var_name.assign (var_base + "_length");
299 /* If actual-data variable doesn't already exist, create variable tracker,
300 and write declaration for it: */
301 act_variable = test_state->find_var (var_base);
302 if (act_variable == test_state->variable.end()) {
303 test_state->make_var (var_base);
304 act_variable = test_state->find_var (var_base);
305 prep_code.append (test_state->bplate->bplate_string[declare_big_string]);
306 find_replace_1st ("$var", var_name, prep_code);
307 temp_string = (char *) act_variable->value;
308 find_replace_1st ("$init", temp_string, prep_code);
309 // Actual-data length:
310 temp_string.assign (test_state->bplate->bplate_string[declare_int]);
311 find_replace_1st ("static int", "static size_t", temp_string);
312 prep_code.append (temp_string);
313 find_replace_1st ("$var", length_var_name, prep_code);
314 find_replace_1st ("$init", to_string(temp_string.length()), prep_code);
315 // Offset (always 0 for now):
316 find_replace_1st ("$offset", "0", prep_code);
317 }
318 // If hashing the (actual) data, then create a variable for that:
319 if (hash_data && !act_variable->hash_declared) {
320 var_name = var_base + "_hash";
321 prep_code.append (test_state->bplate->bplate_string[declare_generic]);
322 // where to put the hash of the data
323 find_replace_1st ("$type", "uint32_t", prep_code);
324 find_replace_1st ("$var", var_name, prep_code);
325 find_replace_1st ("$init", "0", prep_code); // for now...
326 act_variable->hash_declared = true;
327 }
328}
329
330void sst_get_call::fill_in_command (void)
331{
Nik Dewally298a8042024-07-23 15:03:13 +0100332 string exp_var_name, act_var_name, length_var_name,act_data_length, hash_var_name,
Karl Zhang3de5ab12021-05-31 11:45:48 +0800333 id_string, var_name_suffix;
334
335/* TODO: Flesh-out/fix this (it was a good try/start, but not quite right):
336 // Fill in preceding comment:
337 if (asset_info.how_asset_found == asset_search::created_new) {
338 find_replace_1st ("$op", "Creating", call_code);
339 } else {
340 find_replace_1st ("$op", "Resetting", call_code);
341 }
342 if (asset_info.name_specified) {
343 find_replace_1st ("$description", "\"" + asset_info.get_name() + ",\"",
344 call_code);
345 } else {
346 find_replace_1st ("$description",
347 "UID = " + to_string((long) asset_info.id_n), call_code);
348 }
349 if (set_data.string_specified) {
350 find_replace_1st ("$data_source",
351 "\"" + data.substr (0, 10) + "...\"",
352 call_code);
353 } else if (set_data.file_specified) {
354 find_replace_1st ("$data_source", "from file " + set_data.file_path,
355 call_code);
356 } else {
357 find_replace_1st (" $data_source", "", call_code);
358 }
359*/ // Fill in the call itself:
360 if (print_data || hash_data) {
361 // Dump to variable; no data-check code needed:
362 check_code.assign (test_state->bplate->bplate_string[get_sst_check]);
363 } else {
364 // Check either against literal or variable, so need data-check code too:
365 check_code.assign (test_state->bplate->bplate_string[get_sst_check_all]);
366 }
367 /* Note: Can fill in the check code identically between the dump-to-variable
368 and check-data cases, because the boilerplate for the former is just an
369 abbreviated version of the latter. The find_replace_1st() calls for
370 the check-data stuff will just simply not have any effect. */
371 if (exp_data.data_var_specified) {
372 // Check against data in variable:
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200373 exp_var_name.assign (exp_data.data_var);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800374 } else {
375 var_name_suffix = "_exp_data";
376 if (exp_data.n_exp_vars > 0) {
377 var_name_suffix =
378 var_name_suffix + "_" + to_string(exp_data.n_exp_vars);
379 }
380 exp_var_name.assign (asset_info.get_name() + var_name_suffix);
381 }
382 if (assign_data_var_specified) {
383 act_var_name.assign (assign_data_var + "_data");
384 act_data_length.assign (assign_data_var + "_length");
385 } else {
386 act_var_name.assign (asset_info.get_name() + "_act_data");
387 act_data_length.assign (asset_info.get_name() + "_act_length");
388 }
389
390 id_string = to_string((long) asset_info.id_n);
391 // Fill in the PSA command itself:
392 find_replace_1st ("$uid", id_string, call_code);
393 find_replace_all ("$length", to_string(set_data.get().length()), call_code);
394 find_replace_1st ("$offset", to_string(set_data.data_offset), call_code);
395 find_replace_1st ("$exp_data", exp_var_name, call_code);
396 find_replace_all ("$act_data", act_var_name, call_code);
397 find_replace_all ("$act_length", act_data_length, call_code);
398 // Perform most of the same substitutions in the check_code:
Nik Dewally298a8042024-07-23 15:03:13 +0100399 // TODO: Make data checks contingent upon the PSA call itself passing?
Karl Zhang3de5ab12021-05-31 11:45:48 +0800400 find_replace_1st ("$offset", "0", check_code);
401 find_replace_1st ("$exp_data", exp_var_name, check_code);
402 find_replace_all ("$act_data", act_var_name, check_code);
Nik Dewally298a8042024-07-23 15:03:13 +0100403 find_replace_all ("$length", to_string(set_data.get().length()), check_code);
404 find_replace_all ("$act_length", act_data_length, check_code);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800405 if (print_data) {
406 check_code.append (test_state->bplate->bplate_string[test_log]);
407 find_replace_1st ("$message", act_var_name, check_code);
408 }
409 if (hash_data) {
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200410 hash_var_name.assign (asset_info.get_name() + "_hash");
Karl Zhang3de5ab12021-05-31 11:45:48 +0800411 // this is where to put the hash of the data
412 check_code.append (test_state->bplate->bplate_string[get_sst_hash]);
413 find_replace_all ("$act_data_var", act_var_name, check_code);
414 find_replace_all ("$hash_var", hash_var_name, check_code);
415 }
416 // Figure out what expected results:
Nik Dewally6663dde2024-08-09 16:12:27 +0100417 fill_in_result_code(); // this only fills $expect check_code
Karl Zhang3de5ab12021-05-31 11:45:48 +0800418 // Fill in expected data, actual data, and length:
419}
420
421/**********************************************************************************
422 End of methods of class sst_get_call.
423**********************************************************************************/
424
425
426/**********************************************************************************
427 Methods of class sst_remove_call follow:
428**********************************************************************************/
429
430sst_remove_call::sst_remove_call (tf_fuzz_info *test_state, // (constructor)
431 long &call_ser_no,
432 asset_search how_asset_found)
433 : sst_call(test_state, call_ser_no, how_asset_found)
434{
435 // Copy the boilerplate text into local buffers:
436 prep_code.assign ("");
437 call_code.assign (test_state->bplate->bplate_string[remove_sst]);
438 check_code.assign (test_state->bplate->bplate_string[remove_sst_check]);
439 call_description = "SST-remove call";
440}
441sst_remove_call::~sst_remove_call (void)
442{
443 return; // just to have something to pin a breakpoint onto
444}
445
446bool sst_remove_call::copy_call_to_asset (void)
447{
448 vector<psa_asset*>::iterator found_asset;
449
450 found_asset = resolve_asset (dont_create_asset, psa_asset_usage::all);
451 if (asset_info.how_asset_found != asset_search::not_found) {
452 asset_info.the_asset = reinterpret_cast<sst_asset*>(*found_asset);
453 // Note: Vector is of base-class type, but the assets *are* sst_asset.
454 if (asset_info.how_asset_found == asset_search::found_active) {
455 // Delete asset; move it from active vector to deleted vector:
456 test_state->deleted_sst_asset.push_back (asset_info.the_asset);
457 test_state->active_sst_asset.erase (found_asset);
458 } /* if not active, we'll deem the call expected to fail. */
459 }
460 return true;
461}
462
463bool sst_remove_call::copy_asset_to_call (void)
464{
465 if (asset_info.the_asset != nullptr) {
466 set_data.string_specified = asset_info.the_asset->set_data.string_specified;
467 set_data.file_specified = asset_info.the_asset->set_data.file_specified;
468 set_data.flags_string = asset_info.the_asset->set_data.flags_string;
469 asset_info.id_n = asset_info.the_asset->asset_info.id_n;
470 asset_info.name_specified = asset_info.the_asset->asset_info.name_specified;
471 }
472 return true;
473}
474
475void sst_remove_call::fill_in_prep_code (void)
476{
477 // No prep-code.
478 return; // just to have something to pin a breakpoint onto
479}
480
481void sst_remove_call::fill_in_command (void)
482{
483 // Fill in the call:
484 string id_string = to_string((long) asset_info.id_n);
485 find_replace_1st ("$uid", id_string, call_code);
486 // Fill in expected results:
Nik Dewally6663dde2024-08-09 16:12:27 +0100487 fill_in_result_code(); // this only fills $expect check_code
Karl Zhang3de5ab12021-05-31 11:45:48 +0800488}
489
490/**********************************************************************************
491 End of methods of class sst_remove_call.
492**********************************************************************************/