blob: 2c49d95d8d6adfa457fb658bb27e784cb0f6b8db [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);
174 // Figure out what expected results:
175 if ( set_data.flags_string == "PSA_STORAGE_FLAG_WRITE_ONCE"
176 && set_data.n_set_vars > 0) {
177 exp_data.pf_specified = true;
178 exp_data.pf_result_string = "PSA_ERROR_NOT_PERMITTED";
179 }
180 calc_result_code();
181}
182
183/**********************************************************************************
184 End of methods of class sst_set_call.
185**********************************************************************************/
186
187
188/**********************************************************************************
189 Methods of class sst_get_call follow:
190**********************************************************************************/
191
192sst_get_call::sst_get_call (tf_fuzz_info *test_state, // (constructor)
193 long &call_ser_no,
194 asset_search how_asset_found)
195 : sst_call(test_state, call_ser_no, how_asset_found)
196{
197 // Copy the boilerplate text into local buffers:
198 prep_code.assign ("");
199 call_code.assign (test_state->bplate->bplate_string[get_sst_call]);
200 check_code.assign ("");
201 // depends upon the particular usage; will get it in fill_in_command()
202 call_description = "SST-get call";
203}
204sst_get_call::~sst_get_call (void)
205{
206 return; // just to have something to pin a breakpoint onto
207}
208
209bool sst_get_call::copy_call_to_asset (void)
210{
211 vector<psa_asset*>::iterator found_asset;
212
213 found_asset = resolve_asset (dont_create_asset, psa_asset_usage::active);
214 if (asset_info.how_asset_found != asset_search::not_found) {
215 // will be found for set calls, but not necessarily others
216 asset_info.the_asset = reinterpret_cast<sst_asset*>(*found_asset);
217 // Note: Vector is of base-class type, but the assets *are* sst_asset.
218 /* Locating the asset is all we need to do here; copy_asset_to_call() will
219 do the rest. */
220 }
221 return true;
222 // TODO: Shouldn't data be copied over?
223}
224
225bool sst_get_call::copy_asset_to_call (void)
226{
227 if (asset_info.the_asset != nullptr) {
228 // will be found for set calls, but not necessarily others
229 set_data.string_specified = asset_info.the_asset->set_data.string_specified;
230 set_data.file_specified = asset_info.the_asset->set_data.file_specified;
231 set_data.set (asset_info.the_asset->set_data.get());
232 set_data.flags_string = asset_info.the_asset->set_data.flags_string;
233 asset_info.id_n = asset_info.the_asset->asset_info.id_n;
234 asset_info.asset_ser_no = asset_info.the_asset->asset_info.asset_ser_no;
235 asset_info.name_specified = asset_info.the_asset->asset_info.name_specified;
236 asset_info.the_asset->exp_data.n_exp_vars++;
237 exp_data.n_exp_vars = asset_info.the_asset->exp_data.n_exp_vars;
238 }
239 return true;
240}
241
242void sst_get_call::fill_in_prep_code (void)
243{
244 string var_base, var_name, length_var_name, temp_string, var_name_suffix,
245 expected;
246 vector<variable_info>::iterator act_variable, exp_variable;
247
248 if (!(print_data || hash_data)) {
249 // Checking asset data verbatim against expected, so:
250 if (exp_data.data_var_specified) {
251 // Template specified a variable name to "check" against; use that:
252 var_base.assign (exp_data.data_var);
253 exp_variable = test_state->find_var (var_base);
254 if (exp_variable == test_state->variable.end()) {
255 test_state->make_var (var_base);
256 exp_variable = test_state->find_var (var_base);
257 var_name = var_base + "_data";
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200258 length_var_name = var_base + "_length";
Karl Zhang3de5ab12021-05-31 11:45:48 +0800259 prep_code.append (test_state->bplate->bplate_string[declare_string]);
260 find_replace_1st ("$var", var_name, prep_code);
261 temp_string = (char *) exp_variable->value;
262 find_replace_1st ("$init", temp_string, prep_code);
263 // Expected-data length:
264 temp_string.assign (test_state->bplate->bplate_string[declare_int]);
265 find_replace_1st ("static int", "static size_t", temp_string);
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200266 prep_code.append (temp_string);
267 find_replace_1st ("$var", length_var_name, prep_code);
268 find_replace_1st ("$init", to_string(temp_string.length()), prep_code);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800269 }
270 } else {
271 if (exp_data.data_specified) {
272 // Checking against literal expected data:
273 expected.assign (exp_data.data);
274 } else {
275 // Check against what we believe the asset to contain:
276 expected.assign (set_data.get());
277 }
278 var_name_suffix = "_exp_data";
279 if (exp_data.n_exp_vars > 0) {
280 var_name_suffix =
281 var_name_suffix + "_" + to_string(exp_data.n_exp_vars);
282 }
283 var_name.assign (asset_info.get_name() + var_name_suffix);
284 prep_code.assign(test_state->bplate->bplate_string[declare_string]);
285 find_replace_1st("$var", var_name, prep_code);
286 find_replace_1st("$init", expected, prep_code);
287 }
288 }
289 // Actual data:
290 if (assign_data_var_specified) {
291 var_base.assign (assign_data_var);
292 } else {
293 var_base.assign (asset_info.get_name() + "_act");
294 }
295 var_name.assign (var_base + "_data");
296 length_var_name.assign (var_base + "_length");
297 /* If actual-data variable doesn't already exist, create variable tracker,
298 and write declaration for it: */
299 act_variable = test_state->find_var (var_base);
300 if (act_variable == test_state->variable.end()) {
301 test_state->make_var (var_base);
302 act_variable = test_state->find_var (var_base);
303 prep_code.append (test_state->bplate->bplate_string[declare_big_string]);
304 find_replace_1st ("$var", var_name, prep_code);
305 temp_string = (char *) act_variable->value;
306 find_replace_1st ("$init", temp_string, prep_code);
307 // Actual-data length:
308 temp_string.assign (test_state->bplate->bplate_string[declare_int]);
309 find_replace_1st ("static int", "static size_t", temp_string);
310 prep_code.append (temp_string);
311 find_replace_1st ("$var", length_var_name, prep_code);
312 find_replace_1st ("$init", to_string(temp_string.length()), prep_code);
313 // Offset (always 0 for now):
314 find_replace_1st ("$offset", "0", prep_code);
315 }
316 // If hashing the (actual) data, then create a variable for that:
317 if (hash_data && !act_variable->hash_declared) {
318 var_name = var_base + "_hash";
319 prep_code.append (test_state->bplate->bplate_string[declare_generic]);
320 // where to put the hash of the data
321 find_replace_1st ("$type", "uint32_t", prep_code);
322 find_replace_1st ("$var", var_name, prep_code);
323 find_replace_1st ("$init", "0", prep_code); // for now...
324 act_variable->hash_declared = true;
325 }
326}
327
328void sst_get_call::fill_in_command (void)
329{
Nik Dewally298a8042024-07-23 15:03:13 +0100330 string exp_var_name, act_var_name, length_var_name,act_data_length, hash_var_name,
Karl Zhang3de5ab12021-05-31 11:45:48 +0800331 id_string, var_name_suffix;
332
333/* TODO: Flesh-out/fix this (it was a good try/start, but not quite right):
334 // Fill in preceding comment:
335 if (asset_info.how_asset_found == asset_search::created_new) {
336 find_replace_1st ("$op", "Creating", call_code);
337 } else {
338 find_replace_1st ("$op", "Resetting", call_code);
339 }
340 if (asset_info.name_specified) {
341 find_replace_1st ("$description", "\"" + asset_info.get_name() + ",\"",
342 call_code);
343 } else {
344 find_replace_1st ("$description",
345 "UID = " + to_string((long) asset_info.id_n), call_code);
346 }
347 if (set_data.string_specified) {
348 find_replace_1st ("$data_source",
349 "\"" + data.substr (0, 10) + "...\"",
350 call_code);
351 } else if (set_data.file_specified) {
352 find_replace_1st ("$data_source", "from file " + set_data.file_path,
353 call_code);
354 } else {
355 find_replace_1st (" $data_source", "", call_code);
356 }
357*/ // Fill in the call itself:
358 if (print_data || hash_data) {
359 // Dump to variable; no data-check code needed:
360 check_code.assign (test_state->bplate->bplate_string[get_sst_check]);
361 } else {
362 // Check either against literal or variable, so need data-check code too:
363 check_code.assign (test_state->bplate->bplate_string[get_sst_check_all]);
364 }
365 /* Note: Can fill in the check code identically between the dump-to-variable
366 and check-data cases, because the boilerplate for the former is just an
367 abbreviated version of the latter. The find_replace_1st() calls for
368 the check-data stuff will just simply not have any effect. */
369 if (exp_data.data_var_specified) {
370 // Check against data in variable:
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200371 exp_var_name.assign (exp_data.data_var);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800372 } else {
373 var_name_suffix = "_exp_data";
374 if (exp_data.n_exp_vars > 0) {
375 var_name_suffix =
376 var_name_suffix + "_" + to_string(exp_data.n_exp_vars);
377 }
378 exp_var_name.assign (asset_info.get_name() + var_name_suffix);
379 }
380 if (assign_data_var_specified) {
381 act_var_name.assign (assign_data_var + "_data");
382 act_data_length.assign (assign_data_var + "_length");
383 } else {
384 act_var_name.assign (asset_info.get_name() + "_act_data");
385 act_data_length.assign (asset_info.get_name() + "_act_length");
386 }
387
388 id_string = to_string((long) asset_info.id_n);
389 // Fill in the PSA command itself:
390 find_replace_1st ("$uid", id_string, call_code);
391 find_replace_all ("$length", to_string(set_data.get().length()), call_code);
392 find_replace_1st ("$offset", to_string(set_data.data_offset), call_code);
393 find_replace_1st ("$exp_data", exp_var_name, call_code);
394 find_replace_all ("$act_data", act_var_name, call_code);
395 find_replace_all ("$act_length", act_data_length, call_code);
396 // Perform most of the same substitutions in the check_code:
Nik Dewally298a8042024-07-23 15:03:13 +0100397 // TODO: Make data checks contingent upon the PSA call itself passing?
Karl Zhang3de5ab12021-05-31 11:45:48 +0800398 find_replace_1st ("$offset", "0", check_code);
399 find_replace_1st ("$exp_data", exp_var_name, check_code);
400 find_replace_all ("$act_data", act_var_name, check_code);
Nik Dewally298a8042024-07-23 15:03:13 +0100401 find_replace_all ("$length", to_string(set_data.get().length()), check_code);
402 find_replace_all ("$act_length", act_data_length, check_code);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800403 if (print_data) {
404 check_code.append (test_state->bplate->bplate_string[test_log]);
405 find_replace_1st ("$message", act_var_name, check_code);
406 }
407 if (hash_data) {
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200408 hash_var_name.assign (asset_info.get_name() + "_hash");
Karl Zhang3de5ab12021-05-31 11:45:48 +0800409 // this is where to put the hash of the data
410 check_code.append (test_state->bplate->bplate_string[get_sst_hash]);
411 find_replace_all ("$act_data_var", act_var_name, check_code);
412 find_replace_all ("$hash_var", hash_var_name, check_code);
413 }
414 // Figure out what expected results:
415 calc_result_code(); // this only fills $expect check_code
416 // Fill in expected data, actual data, and length:
417}
418
419/**********************************************************************************
420 End of methods of class sst_get_call.
421**********************************************************************************/
422
423
424/**********************************************************************************
425 Methods of class sst_remove_call follow:
426**********************************************************************************/
427
428sst_remove_call::sst_remove_call (tf_fuzz_info *test_state, // (constructor)
429 long &call_ser_no,
430 asset_search how_asset_found)
431 : sst_call(test_state, call_ser_no, how_asset_found)
432{
433 // Copy the boilerplate text into local buffers:
434 prep_code.assign ("");
435 call_code.assign (test_state->bplate->bplate_string[remove_sst]);
436 check_code.assign (test_state->bplate->bplate_string[remove_sst_check]);
437 call_description = "SST-remove call";
438}
439sst_remove_call::~sst_remove_call (void)
440{
441 return; // just to have something to pin a breakpoint onto
442}
443
444bool sst_remove_call::copy_call_to_asset (void)
445{
446 vector<psa_asset*>::iterator found_asset;
447
448 found_asset = resolve_asset (dont_create_asset, psa_asset_usage::all);
449 if (asset_info.how_asset_found != asset_search::not_found) {
450 asset_info.the_asset = reinterpret_cast<sst_asset*>(*found_asset);
451 // Note: Vector is of base-class type, but the assets *are* sst_asset.
452 if (asset_info.how_asset_found == asset_search::found_active) {
453 // Delete asset; move it from active vector to deleted vector:
454 test_state->deleted_sst_asset.push_back (asset_info.the_asset);
455 test_state->active_sst_asset.erase (found_asset);
456 } /* if not active, we'll deem the call expected to fail. */
457 }
458 return true;
459}
460
461bool sst_remove_call::copy_asset_to_call (void)
462{
463 if (asset_info.the_asset != nullptr) {
464 set_data.string_specified = asset_info.the_asset->set_data.string_specified;
465 set_data.file_specified = asset_info.the_asset->set_data.file_specified;
466 set_data.flags_string = asset_info.the_asset->set_data.flags_string;
467 asset_info.id_n = asset_info.the_asset->asset_info.id_n;
468 asset_info.name_specified = asset_info.the_asset->asset_info.name_specified;
469 }
470 return true;
471}
472
473void sst_remove_call::fill_in_prep_code (void)
474{
475 // No prep-code.
476 return; // just to have something to pin a breakpoint onto
477}
478
479void sst_remove_call::fill_in_command (void)
480{
481 // Fill in the call:
482 string id_string = to_string((long) asset_info.id_n);
483 find_replace_1st ("$uid", id_string, call_code);
484 // Fill in expected results:
485 calc_result_code(); // this only fills $expect check_code
486}
487
488/**********************************************************************************
489 End of methods of class sst_remove_call.
490**********************************************************************************/