Software APIs
ibex_fi.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "sw/device/tests/penetrationtests/firmware/fi/ibex_fi.h"
6 
8 #include "sw/device/lib/base/csr_registers.h"
10 #include "sw/device/lib/base/status.h"
13 #include "sw/device/lib/dif/dif_rv_core_ibex.h"
16 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
17 #include "sw/device/lib/testing/otp_ctrl_testutils.h"
18 #include "sw/device/lib/testing/sram_ctrl_testutils.h"
19 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
20 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
21 #include "sw/device/lib/ujson/ujson.h"
22 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
23 #include "sw/device/silicon_creator/manuf/lib/otp_fields.h"
24 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
25 #include "sw/device/tests/penetrationtests/json/ibex_fi_commands.h"
26 
28 #include "otp_ctrl_regs.h"
29 
30 // A function which takes an uint32_t as its only argument.
31 typedef uint32_t (*str_fn_t)(uint32_t);
32 
33 extern uint32_t increment_100x10(uint32_t start_value);
34 
35 extern uint32_t increment_100x1(uint32_t start_value);
36 
37 static str_fn_t increment_100x10_remapped = (str_fn_t)increment_100x10;
38 static str_fn_t increment_100x1_remapped = (str_fn_t)increment_100x1;
39 
40 // Interface to Ibex.
41 static dif_rv_core_ibex_t rv_core_ibex;
42 
43 // Interface to OTP.
44 static dif_otp_ctrl_t otp;
45 
46 // Indicates whether flash already was initialized for the test or not.
47 static bool flash_init;
48 // Indicates whether flash content is valid or not.
49 static bool flash_data_valid;
50 // Indicates whether ret SRAM already was initialized for the test or not.
51 static bool sram_ret_init;
52 // Indicates whether the otp arrays hold the valid reference values read from
53 // the OTP partitions.
54 static bool otp_ref_init;
55 
56 // Arrays holding the reference data read from the OTP VENDOR_TEST,
57 // CREATOR_SW_CFG, and OWNER_SW_CFG partitions.
58 uint32_t
59  otp_data_read_ref_vendor_test[(OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
60  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
61  sizeof(uint32_t)];
62 uint32_t otp_data_read_ref_creator_sw_cfg
63  [(OTP_CTRL_PARAM_CREATOR_SW_CFG_SIZE -
64  OTP_CTRL_PARAM_CREATOR_SW_CFG_DIGEST_SIZE) /
65  sizeof(uint32_t)];
66 uint32_t
67  otp_data_read_ref_owner_sw_cfg[(OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE -
68  OTP_CTRL_PARAM_OWNER_SW_CFG_DIGEST_SIZE) /
69  sizeof(uint32_t)];
70 
71 // Cond. branch macros.
72 #define CONDBRANCHBEQ "beq x5, x6, endfitestfaultybeq\n"
73 #define CONDBRANCHBNE "bne x5, x6, endfitestfaultybne\n"
74 #define CONDBRANCHBGE "bge x5, x6, endfitestfaultybge\n"
75 #define CONDBRANCHBGEU "bgeu x5, x6, endfitestfaultybgeu\n"
76 #define CONDBRANCHBLT "blt x5, x6, endfitestfaultyblt\n"
77 #define CONDBRANCHBLTU "bltu x5, x6, endfitestfaultybltu\n"
78 
79 // NOP macros.
80 #define NOP1 "addi x0, x0, 0\n"
81 #define NOP10 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1
82 #define NOP100 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10
83 #define NOP1000 \
84  NOP100 NOP100 NOP100 NOP100 NOP100 NOP100 NOP100 NOP100 NOP100 NOP100
85 
86 // Init x5 = 0 macro.
87 #define INITX5 "addi x5, x0, 0"
88 
89 // Addi x5 = x5 + 1 macros.
90 #define ADDI1 "addi x5, x5, 1\n"
91 #define ADDI10 ADDI1 ADDI1 ADDI1 ADDI1 ADDI1 ADDI1 ADDI1 ADDI1 ADDI1 ADDI1
92 #define ADDI100 \
93  ADDI10 ADDI10 ADDI10 ADDI10 ADDI10 ADDI10 ADDI10 ADDI10 ADDI10 ADDI10
94 #define ADDI1000 \
95  ADDI100 ADDI100 ADDI100 ADDI100 ADDI100 ADDI100 ADDI100 ADDI100 ADDI100 \
96  ADDI100
97 
98 // Init tmpregs = 0 macro.
99 #define INIT_TMPREGS \
100  "addi x5, x0, 0\n addi x6, x0, 0\n addi x7, x0, 0\n" \
101  "addi x28, x0, 0\n addi x29, x0, 0\n addi x30, x0, 0\n"
102 
103 // Addi chain macro.
104 #define ADDI_CHAIN \
105  "addi x6, x5, 1\n addi x7, x6, 1\n addi x28, x7, 1\n" \
106  "addi x29, x28, 1\n addi x30, x29, 1\n addi x5, x30, 1\n"
107 
108 // Init x6 = 10000 macro.
109 #define INITX6 "li x6, 10000"
110 
111 // Subi x6 = x6 - 1 macro.
112 #define SUBI1 "addi x6, x6, -1\n"
113 
114 // Load word, addi, sw macro.
115 #define LWADDISW1 "lw x5, (%0)\n addi x5, x5, 1\n sw x5, (%0)\n"
116 #define LWADDISW10 \
117  LWADDISW1 LWADDISW1 LWADDISW1 LWADDISW1 LWADDISW1 LWADDISW1 LWADDISW1 \
118  LWADDISW1 LWADDISW1 LWADDISW1
119 #define LWADDISW100 \
120  LWADDISW10 LWADDISW10 LWADDISW10 LWADDISW10 LWADDISW10 LWADDISW10 LWADDISW10 \
121  LWADDISW10 LWADDISW10 LWADDISW10
122 #define LWADDISW1000 \
123  LWADDISW100 LWADDISW100 LWADDISW100 LWADDISW100 LWADDISW100 LWADDISW100 \
124  LWADDISW100 LWADDISW100 LWADDISW100 LWADDISW100
125 
126 // Load word, subi, sw macro.
127 #define LWSUBISW1 "lw x6, (%0)\n addi x6, x6, -1\n sw x6, (%0)\n"
128 
129 // Reference values.
130 const uint32_t ref_values[32] = {
131  0x1BADB002, 0x8BADF00D, 0xA5A5A5A5, 0xABABABAB, 0xABBABABE, 0xABADCAFE,
132  0xBAAAAAAD, 0xBAD22222, 0xBBADBEEF, 0xBEBEBEBE, 0xBEEFCACE, 0xC00010FF,
133  0xCAFED00D, 0xCAFEFEED, 0xCCCCCCCC, 0xCDCDCDCD, 0x0D15EA5E, 0xDEAD10CC,
134  0xDEADBEEF, 0xDEADCAFE, 0xDEADC0DE, 0xDEADFA11, 0xDEADF00D, 0xDEFEC8ED,
135  0xDEADDEAD, 0xD00D2BAD, 0xEBEBEBEB, 0xFADEDEAD, 0xFDFDFDFD, 0xFEE1DEAD,
136  0xFEEDFACE, 0xFEEEFEEE};
137 
138 // Flash information.
139 static dif_flash_ctrl_state_t flash;
140 static dif_flash_ctrl_device_info_t flash_info;
141 #define FLASH_PAGES_PER_BANK flash_info.data_pages
142 #define FLASH_WORD_SZ flash_info.bytes_per_word
143 #define FLASH_PAGE_SZ flash_info.bytes_per_page
144 #define FLASH_UINT32_WORDS_PER_PAGE \
145  (FLASH_PAGE_SZ / FLASH_WORD_SZ) * (FLASH_WORD_SZ / sizeof(uint32_t))
146 
147 // Buffer to allow the compiler to allocate a safe area in Main SRAM where
148 // we can do the write/read test without the risk of clobbering data
149 // used by the program.
150 OT_SECTION(".data")
151 static volatile uint32_t sram_main_buffer[256];
152 
153 // Make sure that this function does not get optimized by the compiler.
154 OT_USED
155 void increment_counter(void) __attribute__((optnone)) {
156  asm volatile("addi x5, x5, 1");
157 }
158 
159 static status_t init_ref_otp_data(void) {
160  // Fetch faulty-free reference values from OTP paritions.
161  if (!otp_ref_init) {
162  // Read VENDOR_TEST partition.
163  TRY(otp_ctrl_testutils_dai_read32_array(
164  &otp, kDifOtpCtrlPartitionVendorTest, 0, otp_data_read_ref_vendor_test,
165  (OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
166  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
167  sizeof(uint32_t)));
168 
169  // Read CREATOR_SW_CFG partition.
170  TRY(otp_ctrl_testutils_dai_read32_array(
172  otp_data_read_ref_creator_sw_cfg,
173  (OTP_CTRL_PARAM_CREATOR_SW_CFG_SIZE -
174  OTP_CTRL_PARAM_CREATOR_SW_CFG_DIGEST_SIZE) /
175  sizeof(uint32_t)));
176 
177  // READ OWNER_SW_CFG partition.
178  TRY(otp_ctrl_testutils_dai_read32_array(
179  &otp, kDifOtpCtrlPartitionOwnerSwCfg, 0, otp_data_read_ref_owner_sw_cfg,
180  (OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE -
181  OTP_CTRL_PARAM_OWNER_SW_CFG_DIGEST_SIZE) /
182  sizeof(uint32_t)));
183  otp_ref_init = true;
184  }
185  return OK_STATUS();
186 }
187 
188 // Init temporary registers t0...t7 with given value.
189 static inline void init_temp_regs(uint32_t value) {
190  asm volatile("li x5, %0" : : "i"(value));
191  asm volatile("li x6, %0" : : "i"(value));
192  asm volatile("li x7, %0" : : "i"(value));
193  asm volatile("li x28, %0" : : "i"(value));
194  asm volatile("li x29, %0" : : "i"(value));
195  asm volatile("li x30, %0" : : "i"(value));
196  asm volatile("li x31, %0" : : "i"(value));
197 }
198 
199 // Read back values from all registers x1...x31 into buffer.
200 static inline void read_all_regs(uint32_t buffer[]) {
201  // The much nicer approach with
202  // asm volatile("sw x1, %0" : : "m"(buffer[1]));
203  // leads to two INSNs. Test in godbolt promised single INSN
204  // Uglier workaround below inserts single INSN, but requires
205  // read_all_regs() to be called prior to the FI trigger
206  // start to avoid register overwrite.
207  asm volatile("sw x1, 0(%0)" : : "r"(&buffer[0]));
208  asm volatile("sw x2, 4(%0)" : : "r"(&buffer[0]));
209  asm volatile("sw x3, 8(%0)" : : "r"(&buffer[0]));
210  asm volatile("sw x4, 12(%0)" : : "r"(&buffer[0]));
211  asm volatile("sw x5, 16(%0)" : : "r"(&buffer[0]));
212  asm volatile("sw x6, 20(%0)" : : "r"(&buffer[0]));
213  asm volatile("sw x7, 24(%0)" : : "r"(&buffer[0]));
214  asm volatile("sw x8, 28(%0)" : : "r"(&buffer[0]));
215  asm volatile("sw x9, 32(%0)" : : "r"(&buffer[0]));
216  asm volatile("sw x10, 36(%0)" : : "r"(&buffer[0]));
217  asm volatile("sw x11, 40(%0)" : : "r"(&buffer[0]));
218  asm volatile("sw x12, 44(%0)" : : "r"(&buffer[0]));
219  asm volatile("sw x13, 48(%0)" : : "r"(&buffer[0]));
220  asm volatile("sw x14, 52(%0)" : : "r"(&buffer[0]));
221  asm volatile("sw x15, 56(%0)" : : "r"(&buffer[0]));
222  asm volatile("sw x16, 60(%0)" : : "r"(&buffer[0]));
223  asm volatile("sw x17, 64(%0)" : : "r"(&buffer[0]));
224  asm volatile("sw x18, 68(%0)" : : "r"(&buffer[0]));
225  asm volatile("sw x19, 72(%0)" : : "r"(&buffer[0]));
226  asm volatile("sw x20, 76(%0)" : : "r"(&buffer[0]));
227  asm volatile("sw x21, 80(%0)" : : "r"(&buffer[0]));
228  asm volatile("sw x22, 84(%0)" : : "r"(&buffer[0]));
229  asm volatile("sw x23, 88(%0)" : : "r"(&buffer[0]));
230  asm volatile("sw x24, 92(%0)" : : "r"(&buffer[0]));
231  asm volatile("sw x25, 96(%0)" : : "r"(&buffer[0]));
232  asm volatile("sw x26, 100(%0)" : : "r"(&buffer[0]));
233  asm volatile("sw x27, 104(%0)" : : "r"(&buffer[0]));
234  asm volatile("sw x28, 108(%0)" : : "r"(&buffer[0]));
235  asm volatile("sw x29, 112(%0)" : : "r"(&buffer[0]));
236  asm volatile("sw x30, 116(%0)" : : "r"(&buffer[0]));
237  asm volatile("sw x31, 120(%0)" : : "r"(&buffer[0]));
238 }
239 
240 static status_t read_otp_partitions(ujson_t *uj) {
241  // Clear registered alerts in alert handler.
242  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
243  // Clear the AST recoverable alerts.
244  pentest_clear_sensor_recov_alerts();
245 
246  uint32_t
247  otp_data_read_res_vendor_test[(OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
248  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
249  sizeof(uint32_t)];
250  uint32_t otp_data_read_res_creator_sw_cfg
251  [(OTP_CTRL_PARAM_CREATOR_SW_CFG_SIZE -
252  OTP_CTRL_PARAM_CREATOR_SW_CFG_DIGEST_SIZE) /
253  sizeof(uint32_t)];
254  uint32_t
255  otp_data_read_res_owner_sw_cfg[(OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE -
256  OTP_CTRL_PARAM_OWNER_SW_CFG_DIGEST_SIZE) /
257  sizeof(uint32_t)];
258 
259  pentest_set_trigger_high();
260  asm volatile(NOP10);
261  TRY(otp_ctrl_testutils_dai_read32_array(
262  &otp, kDifOtpCtrlPartitionVendorTest, 0, otp_data_read_res_vendor_test,
263  (OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
264  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
265  sizeof(uint32_t)));
266  TRY(otp_ctrl_testutils_dai_read32_array(
268  otp_data_read_res_creator_sw_cfg,
269  (OTP_CTRL_PARAM_CREATOR_SW_CFG_SIZE -
270  OTP_CTRL_PARAM_CREATOR_SW_CFG_DIGEST_SIZE) /
271  sizeof(uint32_t)));
272  TRY(otp_ctrl_testutils_dai_read32_array(
273  &otp, kDifOtpCtrlPartitionOwnerSwCfg, 0, otp_data_read_res_owner_sw_cfg,
274  (OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE -
275  OTP_CTRL_PARAM_OWNER_SW_CFG_DIGEST_SIZE) /
276  sizeof(uint32_t)));
277  asm volatile(NOP10);
278  pentest_set_trigger_low();
279 
280  // Get registered alerts from alert handler.
281  reg_alerts = pentest_get_triggered_alerts();
282  // Get fatal and recoverable AST alerts from sensor controller.
283  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
284 
285  // Detect potential mismatch caused by faults.
286  uint32_t res = 0;
287  for (size_t i = 0; i < ((OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
288  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
289  sizeof(uint32_t));
290  i++) {
291  if (otp_data_read_ref_vendor_test[i] != otp_data_read_res_vendor_test[i]) {
292  res |= 1;
293  }
294  }
295 
296  for (size_t i = 0; i < ((OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
297  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
298  sizeof(uint32_t));
299  i++) {
300  if (otp_data_read_ref_creator_sw_cfg[i] !=
301  otp_data_read_res_creator_sw_cfg[i]) {
302  res |= 2;
303  }
304  }
305 
306  for (size_t i = 0; i < ((OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
307  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
308  sizeof(uint32_t));
309  i++) {
310  if (otp_data_read_ref_owner_sw_cfg[i] !=
311  otp_data_read_res_owner_sw_cfg[i]) {
312  res |= 4;
313  }
314  }
315 
316  // Read ERR_STATUS register.
317  dif_rv_core_ibex_error_status_t codes;
318  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
319 
320  // Send res & ERR_STATUS to host.
321  ibex_fi_test_result_t uj_output;
322  uj_output.result = res;
323  uj_output.err_status = codes;
324  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
325  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
326  sizeof(sensor_alerts.alerts));
327  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
328 
329  return OK_STATUS();
330 }
331 
332 // Read back values fromo temporary registers t0...t7 into buffer.
333 static inline void read_temp_regs(uint32_t buffer[]) {
334  asm volatile("mv %0, x5" : "=r"(buffer[0]));
335  asm volatile("mv %0, x6" : "=r"(buffer[1]));
336  asm volatile("mv %0, x7" : "=r"(buffer[2]));
337  asm volatile("mv %0, x28" : "=r"(buffer[3]));
338  asm volatile("mv %0, x29" : "=r"(buffer[4]));
339  asm volatile("mv %0, x30" : "=r"(buffer[5]));
340  asm volatile("mv %0, x31" : "=r"(buffer[6]));
341 }
342 
343 // Make sure that this function does not get optimized by the compiler.
344 OT_USED
345 void not_increment_counter(void) __attribute__((optnone)) {
346  asm volatile("ret");
347  asm volatile(ADDI10);
348 }
349 
350 status_t handle_ibex_fi_address_translation(ujson_t *uj) {
351  // Clear registered alerts in alert handler.
352  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
353  // Clear the AST recoverable alerts.
354  pentest_clear_sensor_recov_alerts();
355 
356  // Create translation descriptions.
357  dif_rv_core_ibex_addr_translation_mapping_t increment_100x10_mapping = {
358  .matching_addr = (uintptr_t)increment_100x1,
359  .remap_addr = (uintptr_t)increment_100x10,
360  .size = 256,
361  };
362  dif_rv_core_ibex_addr_translation_mapping_t increment_100x1_mapping = {
363  .matching_addr = (uintptr_t)increment_100x10,
364  .remap_addr = (uintptr_t)increment_100x1,
365  .size = 256,
366  };
367 
368  // Configure slot 0 for the increment_100x10.
369  TRY(dif_rv_core_ibex_configure_addr_translation(
370  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_0,
371  kDifRvCoreIbexAddrTranslationIBus, increment_100x10_mapping));
372  TRY(dif_rv_core_ibex_configure_addr_translation(
373  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_0,
374  kDifRvCoreIbexAddrTranslationDBus, increment_100x10_mapping));
375 
376  // Configure slot 1 for the increment_100x1.
377  TRY(dif_rv_core_ibex_configure_addr_translation(
378  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_1,
379  kDifRvCoreIbexAddrTranslationIBus, increment_100x1_mapping));
380  TRY(dif_rv_core_ibex_configure_addr_translation(
381  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_1,
382  kDifRvCoreIbexAddrTranslationDBus, increment_100x1_mapping));
383 
384  // Enable the slots.
385  TRY(dif_rv_core_ibex_enable_addr_translation(
386  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_0,
387  kDifRvCoreIbexAddrTranslationIBus));
388  TRY(dif_rv_core_ibex_enable_addr_translation(
389  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_0,
390  kDifRvCoreIbexAddrTranslationDBus));
391 
392  TRY(dif_rv_core_ibex_enable_addr_translation(
393  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_1,
394  kDifRvCoreIbexAddrTranslationIBus));
395  TRY(dif_rv_core_ibex_enable_addr_translation(
396  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_1,
397  kDifRvCoreIbexAddrTranslationDBus));
398 
399  // FI code target.
400  uint32_t result_expected = 0;
401  pentest_set_trigger_high();
402  asm volatile(NOP100);
403  result_expected = increment_100x10_remapped(0);
404  pentest_set_trigger_low();
405  // Get registered alerts from alert handler.
406  reg_alerts = pentest_get_triggered_alerts();
407  // Get fatal and recoverable AST alerts from sensor controller.
408  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
409 
410  uint32_t result_target = increment_100x1_remapped(0);
411  // Compare values
412  uint32_t res = 0;
413  if (result_expected != 100) {
414  res = 1;
415  }
416 
417  if (result_target != 1000) {
418  res |= 1;
419  }
420 
421  // Read ERR_STATUS register.
422  dif_rv_core_ibex_error_status_t codes;
423  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
424 
425  // Send res & ERR_STATUS to host.
426  ibex_fi_test_result_t uj_output;
427  uj_output.result = res;
428  uj_output.err_status = codes;
429  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
430  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
431  sizeof(sensor_alerts.alerts));
432  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
433  return OK_STATUS();
434 }
435 
436 status_t handle_ibex_fi_address_translation_config(ujson_t *uj) {
437  // Clear registered alerts in alert handler.
438  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
439  // Clear the AST recoverable alerts.
440  pentest_clear_sensor_recov_alerts();
441 
442  // Address translation configuration.
444  .matching_addr = 0xa0000000,
445  .remap_addr = (uintptr_t)handle_ibex_fi_address_translation_config,
446  .size = 256,
447  };
448 
450  .matching_addr = 0xa0000000,
451  .remap_addr = (uintptr_t)handle_ibex_fi_address_translation_config,
452  .size = 256,
453  };
454 
455  // Write address translation configuration.
456  TRY(dif_rv_core_ibex_configure_addr_translation(
457  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_0,
458  kDifRvCoreIbexAddrTranslationIBus, mapping1));
459 
460  // FI code target.
461  // Either slot 0 config, which is already written, or slot 1 config, which
462  // gets written is targeted using FI.
463  pentest_set_trigger_high();
464  TRY(dif_rv_core_ibex_configure_addr_translation(
465  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_1,
466  kDifRvCoreIbexAddrTranslationDBus, mapping2));
467  asm volatile(NOP1000);
468  pentest_set_trigger_low();
469  // Get registered alerts from alert handler.
470  reg_alerts = pentest_get_triggered_alerts();
471  // Get fatal and recoverable AST alerts from sensor controller.
472  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
473 
474  // Read back address translation configuration.
477  TRY(dif_rv_core_ibex_read_addr_translation(
478  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_0,
479  kDifRvCoreIbexAddrTranslationIBus, &mapping1_read_back));
480  TRY(dif_rv_core_ibex_read_addr_translation(
481  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_1,
482  kDifRvCoreIbexAddrTranslationDBus, &mapping2_read_back));
483 
484  uint32_t res = 0;
485  // Compare mapping 1.
486  if ((mapping1_read_back.matching_addr != mapping1.matching_addr) ||
487  (mapping1_read_back.remap_addr != mapping1.remap_addr) ||
488  (mapping1_read_back.size != mapping1.size)) {
489  res = 1;
490  }
491 
492  // Compare mapping 2.
493  if ((mapping2_read_back.matching_addr != mapping2.matching_addr) ||
494  (mapping2_read_back.remap_addr != mapping2.remap_addr) ||
495  (mapping2_read_back.size != mapping2.size)) {
496  res = 1;
497  }
498 
499  // Read ERR_STATUS register.
500  dif_rv_core_ibex_error_status_t codes;
501  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
502 
503  // Send res & ERR_STATUS to host.
504  ibex_fi_test_result_t uj_output;
505  uj_output.result = res;
506  uj_output.err_status = codes;
507  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
508  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
509  sizeof(sensor_alerts.alerts));
510  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
511  return OK_STATUS();
512 }
513 
514 status_t handle_ibex_fi_char_conditional_branch_beq(ujson_t *uj)
515  __attribute__((optnone)) {
516  // Clear registered alerts in alert handler.
517  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
518  // Clear the AST recoverable alerts.
519  pentest_clear_sensor_recov_alerts();
520 
521  uint32_t result1 = 0;
522  uint32_t result2 = 0;
523 
524  // FI code target.
525  pentest_set_trigger_high();
526  asm volatile("addi x5, x0, 0xaf");
527  asm volatile("addi x6, x0, 0xef");
528  asm volatile(NOP10);
529  asm volatile(CONDBRANCHBEQ);
530  asm volatile(CONDBRANCHBEQ);
531  asm volatile(CONDBRANCHBEQ);
532  asm volatile(CONDBRANCHBEQ);
533  asm volatile(CONDBRANCHBEQ);
534  asm volatile(CONDBRANCHBEQ);
535  asm volatile(CONDBRANCHBEQ);
536  asm volatile(CONDBRANCHBEQ);
537  asm volatile(CONDBRANCHBEQ);
538  asm volatile(CONDBRANCHBEQ);
539  asm volatile(CONDBRANCHBEQ);
540  asm volatile(CONDBRANCHBEQ);
541  asm volatile(CONDBRANCHBEQ);
542  asm volatile(CONDBRANCHBEQ);
543  asm volatile(CONDBRANCHBEQ);
544  asm volatile(CONDBRANCHBEQ);
545  asm volatile(CONDBRANCHBEQ);
546  asm volatile(CONDBRANCHBEQ);
547  asm volatile(CONDBRANCHBEQ);
548  asm volatile(CONDBRANCHBEQ);
549  asm volatile(CONDBRANCHBEQ);
550  asm volatile(CONDBRANCHBEQ);
551  asm volatile(CONDBRANCHBEQ);
552  asm volatile(CONDBRANCHBEQ);
553  asm volatile(CONDBRANCHBEQ);
554  asm volatile(CONDBRANCHBEQ);
555  asm volatile(CONDBRANCHBEQ);
556  asm volatile(CONDBRANCHBEQ);
557  asm volatile(CONDBRANCHBEQ);
558  asm volatile(CONDBRANCHBEQ);
559  asm volatile("mv %0, x5" : "=r"(result1));
560  asm volatile("mv %0, x6" : "=r"(result2));
561  asm volatile("beq x0, x0, endfitestbeq");
562  asm volatile(
563  "endfitestfaultybeq:\n"
564  "addi x5, x0, 0x11\n"
565  "addi x6, x0, 0x22");
566  asm volatile("mv %0, x5" : "=r"(result1));
567  asm volatile("mv %0, x6" : "=r"(result2));
568  asm volatile("endfitestbeq:\n");
569  pentest_set_trigger_low();
570  // Get registered alerts from alert handler.
571  reg_alerts = pentest_get_triggered_alerts();
572  // Get fatal and recoverable AST alerts from sensor controller.
573  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
574 
575  // Read ERR_STATUS register.
576  dif_rv_core_ibex_error_status_t codes;
577  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
578 
579  // Send loop counters & ERR_STATUS to host.
580  ibex_fi_test_result_mult_t uj_output;
581  uj_output.result1 = result1;
582  uj_output.result2 = result2;
583  uj_output.err_status = codes;
584  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
585  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
586  sizeof(sensor_alerts.alerts));
587  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
588  return OK_STATUS();
589 }
590 
591 status_t handle_ibex_fi_char_conditional_branch_bge(ujson_t *uj)
592  __attribute__((optnone)) {
593  // Clear registered alerts in alert handler.
594  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
595  // Clear the AST recoverable alerts.
596  pentest_clear_sensor_recov_alerts();
597 
598  uint32_t result1 = 0;
599  uint32_t result2 = 0;
600 
601  // FI code target.
602  pentest_set_trigger_high();
603  asm volatile("addi x5, x0, 0xaf");
604  asm volatile("addi x6, x0, 0xef");
605  asm volatile(NOP10);
606  asm volatile(CONDBRANCHBGE);
607  asm volatile(CONDBRANCHBGE);
608  asm volatile(CONDBRANCHBGE);
609  asm volatile(CONDBRANCHBGE);
610  asm volatile(CONDBRANCHBGE);
611  asm volatile(CONDBRANCHBGE);
612  asm volatile(CONDBRANCHBGE);
613  asm volatile(CONDBRANCHBGE);
614  asm volatile(CONDBRANCHBGE);
615  asm volatile(CONDBRANCHBGE);
616  asm volatile(CONDBRANCHBGE);
617  asm volatile(CONDBRANCHBGE);
618  asm volatile(CONDBRANCHBGE);
619  asm volatile(CONDBRANCHBGE);
620  asm volatile(CONDBRANCHBGE);
621  asm volatile(CONDBRANCHBGE);
622  asm volatile(CONDBRANCHBGE);
623  asm volatile(CONDBRANCHBGE);
624  asm volatile(CONDBRANCHBGE);
625  asm volatile(CONDBRANCHBGE);
626  asm volatile(CONDBRANCHBGE);
627  asm volatile(CONDBRANCHBGE);
628  asm volatile(CONDBRANCHBGE);
629  asm volatile(CONDBRANCHBGE);
630  asm volatile(CONDBRANCHBGE);
631  asm volatile(CONDBRANCHBGE);
632  asm volatile(CONDBRANCHBGE);
633  asm volatile(CONDBRANCHBGE);
634  asm volatile(CONDBRANCHBGE);
635  asm volatile(CONDBRANCHBGE);
636  asm volatile("mv %0, x5" : "=r"(result1));
637  asm volatile("mv %0, x6" : "=r"(result2));
638  asm volatile("beq x0, x0, endfitestbge");
639  asm volatile(
640  "endfitestfaultybge:\n"
641  "addi x5, x0, 0x11\n"
642  "addi x6, x0, 0x22");
643  asm volatile("mv %0, x5" : "=r"(result1));
644  asm volatile("mv %0, x6" : "=r"(result2));
645  asm volatile("endfitestbge:\n");
646  pentest_set_trigger_low();
647  // Get registered alerts from alert handler.
648  reg_alerts = pentest_get_triggered_alerts();
649  // Get fatal and recoverable AST alerts from sensor controller.
650  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
651 
652  // Read ERR_STATUS register.
653  dif_rv_core_ibex_error_status_t codes;
654  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
655 
656  // Send loop counters & ERR_STATUS to host.
657  ibex_fi_test_result_mult_t uj_output;
658  uj_output.result1 = result1;
659  uj_output.result2 = result2;
660  uj_output.err_status = codes;
661  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
662  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
663  sizeof(sensor_alerts.alerts));
664  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
665  return OK_STATUS();
666 }
667 
668 status_t handle_ibex_fi_char_conditional_branch_bgeu(ujson_t *uj)
669  __attribute__((optnone)) {
670  // Clear registered alerts in alert handler.
671  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
672  // Clear the AST recoverable alerts.
673  pentest_clear_sensor_recov_alerts();
674 
675  uint32_t result1 = 0;
676  uint32_t result2 = 0;
677 
678  // FI code target.
679  pentest_set_trigger_high();
680  asm volatile("addi x5, x0, 0xaf");
681  asm volatile("addi x6, x0, 0xef");
682  asm volatile(NOP10);
683  asm volatile(CONDBRANCHBGEU);
684  asm volatile(CONDBRANCHBGEU);
685  asm volatile(CONDBRANCHBGEU);
686  asm volatile(CONDBRANCHBGEU);
687  asm volatile(CONDBRANCHBGEU);
688  asm volatile(CONDBRANCHBGEU);
689  asm volatile(CONDBRANCHBGEU);
690  asm volatile(CONDBRANCHBGEU);
691  asm volatile(CONDBRANCHBGEU);
692  asm volatile(CONDBRANCHBGEU);
693  asm volatile(CONDBRANCHBGEU);
694  asm volatile(CONDBRANCHBGEU);
695  asm volatile(CONDBRANCHBGEU);
696  asm volatile(CONDBRANCHBGEU);
697  asm volatile(CONDBRANCHBGEU);
698  asm volatile(CONDBRANCHBGEU);
699  asm volatile(CONDBRANCHBGEU);
700  asm volatile(CONDBRANCHBGEU);
701  asm volatile(CONDBRANCHBGEU);
702  asm volatile(CONDBRANCHBGEU);
703  asm volatile(CONDBRANCHBGEU);
704  asm volatile(CONDBRANCHBGEU);
705  asm volatile(CONDBRANCHBGEU);
706  asm volatile(CONDBRANCHBGEU);
707  asm volatile(CONDBRANCHBGEU);
708  asm volatile(CONDBRANCHBGEU);
709  asm volatile(CONDBRANCHBGEU);
710  asm volatile(CONDBRANCHBGEU);
711  asm volatile(CONDBRANCHBGEU);
712  asm volatile(CONDBRANCHBGEU);
713  asm volatile("mv %0, x5" : "=r"(result1));
714  asm volatile("mv %0, x6" : "=r"(result2));
715  asm volatile("beq x0, x0, endfitestbgeu");
716  asm volatile(
717  "endfitestfaultybgeu:\n"
718  "addi x5, x0, 0x11\n"
719  "addi x6, x0, 0x22");
720  asm volatile("mv %0, x5" : "=r"(result1));
721  asm volatile("mv %0, x6" : "=r"(result2));
722  asm volatile("endfitestbgeu:\n");
723  pentest_set_trigger_low();
724  // Get registered alerts from alert handler.
725  reg_alerts = pentest_get_triggered_alerts();
726  // Get fatal and recoverable AST alerts from sensor controller.
727  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
728 
729  // Read ERR_STATUS register.
730  dif_rv_core_ibex_error_status_t codes;
731  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
732 
733  // Send loop counters & ERR_STATUS to host.
734  ibex_fi_test_result_mult_t uj_output;
735  uj_output.result1 = result1;
736  uj_output.result2 = result2;
737  uj_output.err_status = codes;
738  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
739  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
740  sizeof(sensor_alerts.alerts));
741  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
742  return OK_STATUS();
743 }
744 
745 status_t handle_ibex_fi_char_conditional_branch_blt(ujson_t *uj)
746  __attribute__((optnone)) {
747  // Clear registered alerts in alert handler.
748  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
749  // Clear the AST recoverable alerts.
750  pentest_clear_sensor_recov_alerts();
751 
752  uint32_t result1 = 0;
753  uint32_t result2 = 0;
754 
755  // FI code target.
756  pentest_set_trigger_high();
757  asm volatile("addi x5, x0, 0xef");
758  asm volatile("addi x6, x0, 0xaf");
759  asm volatile(NOP10);
760  asm volatile(CONDBRANCHBLT);
761  asm volatile(CONDBRANCHBLT);
762  asm volatile(CONDBRANCHBLT);
763  asm volatile(CONDBRANCHBLT);
764  asm volatile(CONDBRANCHBLT);
765  asm volatile(CONDBRANCHBLT);
766  asm volatile(CONDBRANCHBLT);
767  asm volatile(CONDBRANCHBLT);
768  asm volatile(CONDBRANCHBLT);
769  asm volatile(CONDBRANCHBLT);
770  asm volatile(CONDBRANCHBLT);
771  asm volatile(CONDBRANCHBLT);
772  asm volatile(CONDBRANCHBLT);
773  asm volatile(CONDBRANCHBLT);
774  asm volatile(CONDBRANCHBLT);
775  asm volatile(CONDBRANCHBLT);
776  asm volatile(CONDBRANCHBLT);
777  asm volatile(CONDBRANCHBLT);
778  asm volatile(CONDBRANCHBLT);
779  asm volatile(CONDBRANCHBLT);
780  asm volatile(CONDBRANCHBLT);
781  asm volatile(CONDBRANCHBLT);
782  asm volatile(CONDBRANCHBLT);
783  asm volatile(CONDBRANCHBLT);
784  asm volatile(CONDBRANCHBLT);
785  asm volatile(CONDBRANCHBLT);
786  asm volatile(CONDBRANCHBLT);
787  asm volatile(CONDBRANCHBLT);
788  asm volatile(CONDBRANCHBLT);
789  asm volatile(CONDBRANCHBLT);
790  asm volatile("mv %0, x5" : "=r"(result1));
791  asm volatile("mv %0, x6" : "=r"(result2));
792  asm volatile("beq x0, x0, endfitestblt");
793  asm volatile(
794  "endfitestfaultyblt:\n"
795  "addi x5, x0, 0x11\n"
796  "addi x6, x0, 0x22");
797  asm volatile("mv %0, x5" : "=r"(result1));
798  asm volatile("mv %0, x6" : "=r"(result2));
799  asm volatile("endfitestblt:\n");
800  pentest_set_trigger_low();
801  // Get registered alerts from alert handler.
802  reg_alerts = pentest_get_triggered_alerts();
803  // Get fatal and recoverable AST alerts from sensor controller.
804  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
805 
806  // Read ERR_STATUS register.
807  dif_rv_core_ibex_error_status_t codes;
808  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
809 
810  // Send loop counters & ERR_STATUS to host.
811  ibex_fi_test_result_mult_t uj_output;
812  uj_output.result1 = result1;
813  uj_output.result2 = result2;
814  uj_output.err_status = codes;
815  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
816  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
817  sizeof(sensor_alerts.alerts));
818  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
819  return OK_STATUS();
820 }
821 
822 status_t handle_ibex_fi_char_conditional_branch_bltu(ujson_t *uj)
823  __attribute__((optnone)) {
824  // Clear registered alerts in alert handler.
825  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
826  // Clear the AST recoverable alerts.
827  pentest_clear_sensor_recov_alerts();
828 
829  uint32_t result1 = 0;
830  uint32_t result2 = 0;
831 
832  // FI code target.
833  pentest_set_trigger_high();
834  asm volatile("addi x5, x0, 0xef");
835  asm volatile("addi x6, x0, 0xaf");
836  asm volatile(NOP10);
837  asm volatile(CONDBRANCHBLTU);
838  asm volatile(CONDBRANCHBLTU);
839  asm volatile(CONDBRANCHBLTU);
840  asm volatile(CONDBRANCHBLTU);
841  asm volatile(CONDBRANCHBLTU);
842  asm volatile(CONDBRANCHBLTU);
843  asm volatile(CONDBRANCHBLTU);
844  asm volatile(CONDBRANCHBLTU);
845  asm volatile(CONDBRANCHBLTU);
846  asm volatile(CONDBRANCHBLTU);
847  asm volatile(CONDBRANCHBLTU);
848  asm volatile(CONDBRANCHBLTU);
849  asm volatile(CONDBRANCHBLTU);
850  asm volatile(CONDBRANCHBLTU);
851  asm volatile(CONDBRANCHBLTU);
852  asm volatile(CONDBRANCHBLTU);
853  asm volatile(CONDBRANCHBLTU);
854  asm volatile(CONDBRANCHBLTU);
855  asm volatile(CONDBRANCHBLTU);
856  asm volatile(CONDBRANCHBLTU);
857  asm volatile(CONDBRANCHBLTU);
858  asm volatile(CONDBRANCHBLTU);
859  asm volatile(CONDBRANCHBLTU);
860  asm volatile(CONDBRANCHBLTU);
861  asm volatile(CONDBRANCHBLTU);
862  asm volatile(CONDBRANCHBLTU);
863  asm volatile(CONDBRANCHBLTU);
864  asm volatile(CONDBRANCHBLTU);
865  asm volatile(CONDBRANCHBLTU);
866  asm volatile(CONDBRANCHBLTU);
867  asm volatile("mv %0, x5" : "=r"(result1));
868  asm volatile("mv %0, x6" : "=r"(result2));
869  asm volatile("beq x0, x0, endfitestbltu");
870  asm volatile(
871  "endfitestfaultybltu:\n"
872  "addi x5, x0, 0x11\n"
873  "addi x6, x0, 0x22");
874  asm volatile("mv %0, x5" : "=r"(result1));
875  asm volatile("mv %0, x6" : "=r"(result2));
876  asm volatile("endfitestbltu:\n");
877  pentest_set_trigger_low();
878  // Get registered alerts from alert handler.
879  reg_alerts = pentest_get_triggered_alerts();
880  // Get fatal and recoverable AST alerts from sensor controller.
881  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
882 
883  // Read ERR_STATUS register.
884  dif_rv_core_ibex_error_status_t codes;
885  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
886 
887  // Send loop counters & ERR_STATUS to host.
888  ibex_fi_test_result_mult_t uj_output;
889  uj_output.result1 = result1;
890  uj_output.result2 = result2;
891  uj_output.err_status = codes;
892  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
893  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
894  sizeof(sensor_alerts.alerts));
895  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
896  return OK_STATUS();
897 }
898 
899 status_t handle_ibex_fi_char_conditional_branch_bne(ujson_t *uj)
900  __attribute__((optnone)) {
901  // Clear registered alerts in alert handler.
902  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
903  // Clear the AST recoverable alerts.
904  pentest_clear_sensor_recov_alerts();
905 
906  uint32_t result1 = 0;
907  uint32_t result2 = 0;
908 
909  // FI code target.
910  pentest_set_trigger_high();
911  asm volatile("addi x5, x0, 0xaf");
912  asm volatile("addi x6, x0, 0xaf");
913  asm volatile(NOP10);
914  asm volatile(CONDBRANCHBNE);
915  asm volatile(CONDBRANCHBNE);
916  asm volatile(CONDBRANCHBNE);
917  asm volatile(CONDBRANCHBNE);
918  asm volatile(CONDBRANCHBNE);
919  asm volatile(CONDBRANCHBNE);
920  asm volatile(CONDBRANCHBNE);
921  asm volatile(CONDBRANCHBNE);
922  asm volatile(CONDBRANCHBNE);
923  asm volatile(CONDBRANCHBNE);
924  asm volatile(CONDBRANCHBNE);
925  asm volatile(CONDBRANCHBNE);
926  asm volatile(CONDBRANCHBNE);
927  asm volatile(CONDBRANCHBNE);
928  asm volatile(CONDBRANCHBNE);
929  asm volatile(CONDBRANCHBNE);
930  asm volatile(CONDBRANCHBNE);
931  asm volatile(CONDBRANCHBNE);
932  asm volatile(CONDBRANCHBNE);
933  asm volatile(CONDBRANCHBNE);
934  asm volatile(CONDBRANCHBNE);
935  asm volatile(CONDBRANCHBNE);
936  asm volatile(CONDBRANCHBNE);
937  asm volatile(CONDBRANCHBNE);
938  asm volatile(CONDBRANCHBNE);
939  asm volatile(CONDBRANCHBNE);
940  asm volatile(CONDBRANCHBNE);
941  asm volatile(CONDBRANCHBNE);
942  asm volatile(CONDBRANCHBNE);
943  asm volatile(CONDBRANCHBNE);
944  asm volatile("mv %0, x5" : "=r"(result1));
945  asm volatile("mv %0, x6" : "=r"(result2));
946  asm volatile("beq x0, x0, endfitestbne");
947  asm volatile(
948  "endfitestfaultybne:\n"
949  "addi x5, x0, 0x11\n"
950  "addi x6, x0, 0x22");
951  asm volatile("mv %0, x5" : "=r"(result1));
952  asm volatile("mv %0, x6" : "=r"(result2));
953  asm volatile("endfitestbne:\n");
954  pentest_set_trigger_low();
955  // Get registered alerts from alert handler.
956  reg_alerts = pentest_get_triggered_alerts();
957  // Get fatal and recoverable AST alerts from sensor controller.
958  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
959 
960  // Read ERR_STATUS register.
961  dif_rv_core_ibex_error_status_t codes;
962  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
963 
964  // Send loop counters & ERR_STATUS to host.
965  ibex_fi_test_result_mult_t uj_output;
966  uj_output.result1 = result1;
967  uj_output.result2 = result2;
968  uj_output.err_status = codes;
969  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
970  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
971  sizeof(sensor_alerts.alerts));
972  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
973  return OK_STATUS();
974 }
975 
976 status_t handle_ibex_fi_char_csr_read(ujson_t *uj) {
977  // Clear registered alerts in alert handler.
978  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
979  // Clear the AST recoverable alerts.
980  pentest_clear_sensor_recov_alerts();
981 
982  // Write reference value into CSR.
983  CSR_WRITE(CSR_REG_MSCRATCH, ref_values[0]);
984 
985  // Init t0...t6 with 0.
986  init_temp_regs(0);
987 
988  // FI code target.
989  pentest_set_trigger_high();
990  asm volatile(NOP10);
991  asm volatile("csrr x5,mscratch");
992  asm volatile("csrr x6,mscratch");
993  asm volatile("csrr x7,mscratch");
994  asm volatile("csrr x28,mscratch");
995  asm volatile("csrr x29,mscratch");
996  asm volatile("csrr x30,mscratch");
997  asm volatile("csrr x31,mscratch");
998  asm volatile(NOP10);
999  pentest_set_trigger_low();
1000 
1001  // Load register values.
1002  // Result buffer.
1003  uint32_t res_values[7];
1004  read_temp_regs(res_values);
1005 
1006  // Get registered alerts from alert handler.
1007  reg_alerts = pentest_get_triggered_alerts();
1008  // Get fatal and recoverable AST alerts from sensor controller.
1009  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1010 
1011  // Compare against reference values.
1012  uint32_t res = 0;
1013  for (int i = 0; i < 7; i++) {
1014  if (res_values[i] != ref_values[0]) {
1015  res |= 1;
1016  }
1017  }
1018 
1019  // Read ERR_STATUS register.
1020  dif_rv_core_ibex_error_status_t codes;
1021  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1022 
1023  // Send res & ERR_STATUS to host.
1024  ibex_fi_test_result_t uj_output;
1025  uj_output.result = res;
1026  uj_output.err_status = codes;
1027  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1028  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1029  sizeof(sensor_alerts.alerts));
1030  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
1031  return OK_STATUS();
1032 }
1033 
1034 status_t handle_ibex_fi_char_csr_write(ujson_t *uj) {
1035  ibex_fi_test_result_t uj_output;
1036  // Clear registered alerts in alert handler.
1037  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1038  // Clear the AST recoverable alerts.
1039  pentest_clear_sensor_recov_alerts();
1040 
1041  // Init x5 with reference value.
1042  asm volatile("li x5, %0" : : "i"(ref_values[0]));
1043 
1044  // FI code target.
1045  pentest_set_trigger_high();
1046  asm volatile(NOP10);
1047  asm volatile("csrw mscratch, x5");
1048  asm volatile("csrr x5,mscratch");
1049  asm volatile("csrw mscratch, x5");
1050  asm volatile("csrr x5,mscratch");
1051  asm volatile("csrw mscratch, x5");
1052  asm volatile("csrr x5,mscratch");
1053  asm volatile("csrw mscratch, x5");
1054  asm volatile("csrr x5,mscratch");
1055  asm volatile("csrw mscratch, x5");
1056  asm volatile("csrr x5,mscratch");
1057  asm volatile("csrw mscratch, x5");
1058  asm volatile("csrr x5,mscratch");
1059  asm volatile("csrw mscratch, x5");
1060  asm volatile("csrr x5,mscratch");
1061  asm volatile("csrw mscratch, x5");
1062  asm volatile("csrr x5,mscratch");
1063  asm volatile("csrw mscratch, x5");
1064  asm volatile("csrr x5,mscratch");
1065  asm volatile("csrw mscratch, x5");
1066  asm volatile("csrr x5,mscratch");
1067  asm volatile("csrw mscratch, x5");
1068  asm volatile("csrr x5,mscratch");
1069  asm volatile("csrw mscratch, x5");
1070  asm volatile("csrr x5,mscratch");
1071  asm volatile("csrw mscratch, x5");
1072  asm volatile("csrr x5,mscratch");
1073  asm volatile(NOP10);
1074  pentest_set_trigger_low();
1075 
1076  uint32_t res_value;
1077  asm volatile("mv %0, x5" : "=r"(res_value));
1078 
1079  // Get registered alerts from alert handler.
1080  reg_alerts = pentest_get_triggered_alerts();
1081  // Get fatal and recoverable AST alerts from sensor controller.
1082  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1083 
1084  // Compare against reference values.
1085  uj_output.result = 0;
1086  if (res_value != ref_values[0]) {
1087  uj_output.result = res_value;
1088  }
1089 
1090  // Read ERR_STATUS register.
1091  dif_rv_core_ibex_error_status_t codes;
1092  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1093 
1094  // Send res & ERR_STATUS to host.
1095  uj_output.err_status = codes;
1096  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1097  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1098  sizeof(sensor_alerts.alerts));
1099  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
1100  return OK_STATUS();
1101 }
1102 
1103 status_t handle_ibex_fi_char_flash_read(ujson_t *uj) __attribute__((optnone)) {
1104  // Clear registered alerts in alert handler.
1105  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1106  // Clear the AST recoverable alerts.
1107  pentest_clear_sensor_recov_alerts();
1108 
1109  if (!flash_init) {
1110  // Configure the data flash.
1111  // Flash configuration.
1112  dif_flash_ctrl_region_properties_t region_properties = {
1113  .rd_en = kMultiBitBool4True,
1114  .prog_en = kMultiBitBool4True,
1115  .erase_en = kMultiBitBool4True,
1116  .scramble_en = kMultiBitBool4True,
1117  .ecc_en = kMultiBitBool4True,
1118  .high_endurance_en = kMultiBitBool4False};
1119 
1121  .base = FLASH_PAGES_PER_BANK,
1122  .size = 0x1,
1123  .properties = region_properties};
1124 
1125  TRY(dif_flash_ctrl_set_data_region_properties(&flash, 0, data_region));
1128 
1129  flash_init = true;
1130  }
1131 
1132  ptrdiff_t flash_bank_1_addr =
1133  (ptrdiff_t)flash_info.data_pages * (ptrdiff_t)flash_info.bytes_per_page;
1134  mmio_region_t flash_bank_1 = mmio_region_from_addr(
1135  TOP_EARLGREY_FLASH_CTRL_MEM_BASE_ADDR + (uintptr_t)flash_bank_1_addr);
1136 
1137  if (!flash_data_valid) {
1138  // Prepare page and write reference values into it.
1139  uint32_t input_page[FLASH_UINT32_WORDS_PER_PAGE];
1140  memset(input_page, 0x0, FLASH_UINT32_WORDS_PER_PAGE * sizeof(uint32_t));
1141  for (int i = 0; i < 32; i++) {
1142  input_page[i] = ref_values[i];
1143  }
1144 
1145  // Erase flash and write page with reference values.
1146  TRY(flash_ctrl_testutils_erase_and_write_page(
1147  &flash, (uint32_t)flash_bank_1_addr, /*partition_id=*/0, input_page,
1148  kDifFlashCtrlPartitionTypeData, FLASH_UINT32_WORDS_PER_PAGE));
1149 
1150  flash_data_valid = true;
1151  }
1152 
1153  // Init t0...t6 with 0.
1154  init_temp_regs(0);
1155 
1156  // FI code target.
1157  pentest_set_trigger_high();
1158  asm volatile(NOP10);
1159  asm volatile("lw x5, (%0)" : : "r"((flash_bank_1.base)));
1160  asm volatile("lw x6, (%0)" : : "r"((flash_bank_1.base)));
1161  asm volatile("lw x7, (%0)" : : "r"((flash_bank_1.base)));
1162  asm volatile("lw x28, (%0)" : : "r"((flash_bank_1.base)));
1163  asm volatile("lw x29, (%0)" : : "r"((flash_bank_1.base)));
1164  asm volatile("lw x30, (%0)" : : "r"((flash_bank_1.base)));
1165  asm volatile("lw x31, (%0)" : : "r"((flash_bank_1.base)));
1166  asm volatile(NOP10);
1167  pentest_set_trigger_low();
1168 
1169  // Load register values.
1170  // Result buffer.
1171  uint32_t res_values[7];
1172  read_temp_regs(res_values);
1173 
1174  // Get registered alerts from alert handler.
1175  reg_alerts = pentest_get_triggered_alerts();
1176  // Get fatal and recoverable AST alerts from sensor controller.
1177  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1178 
1179  // Compare against reference values.
1180  ibex_fi_faulty_addresses_data_t uj_output;
1181  memset(uj_output.addresses, 0, sizeof(uj_output.addresses));
1182  memset(uj_output.data, 0, sizeof(uj_output.data));
1183 
1184  for (uint32_t flash_pos = 0; flash_pos < 7; flash_pos++) {
1185  if (res_values[flash_pos] != ref_values[0]) {
1186  uj_output.addresses[flash_pos] = flash_pos;
1187  uj_output.data[flash_pos] = res_values[flash_pos];
1188 
1189  // Re-init flash with valid data.
1190  flash_data_valid = false;
1191  }
1192  }
1193 
1194  // Read ERR_STATUS register.
1195  dif_rv_core_ibex_error_status_t codes;
1196  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1197 
1198  // Send res & ERR_STATUS to host.
1199  uj_output.err_status = codes;
1200  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1201  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1202  sizeof(sensor_alerts.alerts));
1203  RESP_OK(ujson_serialize_ibex_fi_faulty_addresses_data_t, uj, &uj_output);
1204  return OK_STATUS();
1205 }
1206 
1207 status_t handle_ibex_fi_char_flash_write(ujson_t *uj) {
1208  // Clear registered alerts in alert handler.
1209  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1210  // Clear the AST recoverable alerts.
1211  pentest_clear_sensor_recov_alerts();
1212 
1213  if (!flash_init) {
1214  // Configure the data flash.
1215  // Flash configuration.
1216  dif_flash_ctrl_region_properties_t region_properties = {
1217  .rd_en = kMultiBitBool4True,
1218  .prog_en = kMultiBitBool4True,
1219  .erase_en = kMultiBitBool4True,
1220  .scramble_en = kMultiBitBool4True,
1221  .ecc_en = kMultiBitBool4True,
1222  .high_endurance_en = kMultiBitBool4False};
1224  .base = FLASH_PAGES_PER_BANK,
1225  .size = 0x1,
1226  .properties = region_properties};
1227  TRY(dif_flash_ctrl_set_data_region_properties(&flash, 0, data_region));
1230 
1231  flash_init = true;
1232  }
1233 
1234  ptrdiff_t flash_bank_1_addr =
1235  (ptrdiff_t)flash_info.data_pages * (ptrdiff_t)flash_info.bytes_per_page;
1236  mmio_region_t flash_bank_1 = mmio_region_from_addr(
1237  TOP_EARLGREY_FLASH_CTRL_MEM_BASE_ADDR + (uintptr_t)flash_bank_1_addr);
1238 
1239  // Prepare page and write reference values into it.
1240  uint32_t input_page[FLASH_UINT32_WORDS_PER_PAGE];
1241  memset(input_page, 0x0, FLASH_UINT32_WORDS_PER_PAGE * sizeof(uint32_t));
1242  for (int i = 0; i < 32; i++) {
1243  input_page[i] = ref_values[i];
1244  }
1245 
1246  // FI code target.
1247  pentest_set_trigger_high();
1248  // Erase flash and write page with reference values.
1249  TRY(flash_ctrl_testutils_erase_and_write_page(
1250  &flash, (uint32_t)flash_bank_1_addr, /*partition_id=*/0, input_page,
1251  kDifFlashCtrlPartitionTypeData, FLASH_UINT32_WORDS_PER_PAGE));
1252  pentest_set_trigger_low();
1253  // Get registered alerts from alert handler.
1254  reg_alerts = pentest_get_triggered_alerts();
1255  // Get fatal and recoverable AST alerts from sensor controller.
1256  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1257 
1258  // Read back and compare against reference values.
1259  uint32_t res_values[32];
1260  uint32_t res = 0;
1261  for (int i = 0; i < 32; i++) {
1262  res_values[i] =
1263  mmio_region_read32(flash_bank_1, i * (ptrdiff_t)sizeof(uint32_t));
1264  if (res_values[i] != ref_values[i]) {
1265  res |= 1;
1266  }
1267  }
1268 
1269  // Read ERR_STATUS register.
1270  dif_rv_core_ibex_error_status_t codes;
1271  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1272 
1273  // Send res & ERR_STATUS to host.
1274  ibex_fi_test_result_t uj_output;
1275  uj_output.result = res;
1276  uj_output.err_status = codes;
1277  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1278  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1279  sizeof(sensor_alerts.alerts));
1280  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
1281  return OK_STATUS();
1282 }
1283 
1284 status_t handle_ibex_fi_char_hardened_check_eq_complement_branch(ujson_t *uj)
1285  __attribute__((optnone)) {
1286  // Clear registered alerts in alert handler.
1287  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1288  // Clear the AST recoverable alerts.
1289  pentest_clear_sensor_recov_alerts();
1290 
1291  // Values are intentially not equal.
1292  // uint32_t value1 = 0;
1293  // uint32_t value2 = 1;
1294  // JH: Changed 28th June. Tests before used unharded values
1295  hardened_bool_t value1 = HARDENED_BOOL_TRUE;
1296  hardened_bool_t value2 = HARDENED_BOOL_FALSE;
1297 
1298  pentest_set_trigger_high();
1299  asm volatile(NOP10);
1300  // The HARDENED_CHECK macro from hardened.h is solved explicitely.
1301  // clang-format off
1302  asm volatile(
1303  "beq" " %0, %1, .L_HARDENED_%=;" \
1304  ".UNIMP_%=: unimp;" \
1305  "bne" " %0, %1, .UNIMP_%=;" \
1306  ".L_HARDENED_%=:;"::"r"(value1), "r"(value2)
1307  );
1308  // clang-format on
1309  asm volatile(NOP10);
1310  pentest_set_trigger_low();
1311  // Get registered alerts from alert handler.
1312  reg_alerts = pentest_get_triggered_alerts();
1313  // Get fatal and recoverable AST alerts from sensor controller.
1314  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1315 
1316  // Read ERR_STATUS register.
1317  dif_rv_core_ibex_error_status_t codes;
1318  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1319 
1320  ibex_fi_test_result_mult_t uj_output;
1321  uj_output.err_status = codes;
1322  uj_output.result1 = value1;
1323  uj_output.result2 = value2;
1324  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1325  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1326  sizeof(sensor_alerts.alerts));
1327  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
1328 
1329  return OK_STATUS();
1330 }
1331 
1332 status_t handle_ibex_fi_char_hardened_check_eq_unimp(ujson_t *uj)
1333  __attribute__((optnone)) {
1334  // Clear registered alerts in alert handler.
1335  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1336  // Clear the AST recoverable alerts.
1337  pentest_clear_sensor_recov_alerts();
1338 
1339  // Values are intentially not equal.
1340  // uint32_t value1 = 0;
1341  // uint32_t value2 = 1;
1342  // JH: Changed 28th June. Tests before used unharded values
1343  hardened_bool_t value1 = HARDENED_BOOL_TRUE;
1344  hardened_bool_t value2 = HARDENED_BOOL_FALSE;
1345 
1346  pentest_set_trigger_high();
1347  asm volatile(NOP10);
1348  // The HARDENED_CHECK macro from hardened.h is solved explicitely.
1349  // clang-format off
1350  asm volatile("beq" " %0, %1, .L_HARDENED_%=;" \
1351  "unimp;" \
1352  ".L_HARDENED_%=:;"::"r"(value1), "r"(value2) );
1353  // clang-format on
1354  asm volatile(NOP10);
1355  pentest_set_trigger_low();
1356  // Get registered alerts from alert handler.
1357  reg_alerts = pentest_get_triggered_alerts();
1358  // Get fatal and recoverable AST alerts from sensor controller.
1359  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1360 
1361  // Read ERR_STATUS register.
1362  dif_rv_core_ibex_error_status_t codes;
1363  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1364 
1365  ibex_fi_test_result_mult_t uj_output;
1366  uj_output.err_status = codes;
1367  uj_output.result1 = value1;
1368  uj_output.result2 = value2;
1369  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1370  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1371  sizeof(sensor_alerts.alerts));
1372  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
1373 
1374  return OK_STATUS();
1375 }
1376 
1377 status_t handle_ibex_fi_char_hardened_check_eq_2_unimps(ujson_t *uj)
1378  __attribute__((optnone)) {
1379  // Clear registered alerts in alert handler.
1380  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1381  // Clear the AST recoverable alerts.
1382  pentest_clear_sensor_recov_alerts();
1383 
1384  // Values are intentially not equal.
1385  // uint32_t value1 = 0;
1386  // uint32_t value2 = 1;
1387  // JH: Changed 28th June. Tests before used unharded values
1388  hardened_bool_t value1 = HARDENED_BOOL_TRUE;
1389  hardened_bool_t value2 = HARDENED_BOOL_FALSE;
1390 
1391  pentest_set_trigger_high();
1392  asm volatile(NOP10);
1393  // The HARDENED_CHECK macro from hardened.h is solved explicitely.
1394  // clang-format off
1395  asm volatile("beq" " %0, %1, .L_HARDENED_%=;" \
1396  "unimp; unimp;" \
1397  ".L_HARDENED_%=:;"::"r"(value1), "r"(value2) );
1398  // clang-format on
1399  asm volatile(NOP10);
1400  pentest_set_trigger_low();
1401  // Get registered alerts from alert handler.
1402  reg_alerts = pentest_get_triggered_alerts();
1403  // Get fatal and recoverable AST alerts from sensor controller.
1404  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1405 
1406  // Read ERR_STATUS register.
1407  dif_rv_core_ibex_error_status_t codes;
1408  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1409 
1410  ibex_fi_test_result_mult_t uj_output;
1411  uj_output.err_status = codes;
1412  uj_output.result1 = value1;
1413  uj_output.result2 = value2;
1414  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1415  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1416  sizeof(sensor_alerts.alerts));
1417  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
1418 
1419  return OK_STATUS();
1420 }
1421 
1422 status_t handle_ibex_fi_char_hardened_check_eq_3_unimps(ujson_t *uj)
1423  __attribute__((optnone)) {
1424  // Clear registered alerts in alert handler.
1425  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1426  // Clear the AST recoverable alerts.
1427  pentest_clear_sensor_recov_alerts();
1428 
1429  // Values are intentially not equal.
1430  // uint32_t value1 = 0;
1431  // uint32_t value2 = 1;
1432  // JH: Changed 28th June. Tests before used unharded values
1433  hardened_bool_t value1 = HARDENED_BOOL_TRUE;
1434  hardened_bool_t value2 = HARDENED_BOOL_FALSE;
1435 
1436  pentest_set_trigger_high();
1437  asm volatile(NOP10);
1438  // The HARDENED_CHECK macro from hardened.h is solved explicitely.
1439  // clang-format off
1440  asm volatile("beq" " %0, %1, .L_HARDENED_%=;" \
1441  "unimp; unimp; unimp;" \
1442  ".L_HARDENED_%=:;"::"r"(value1), "r"(value2) );
1443  // clang-format on
1444  asm volatile(NOP10);
1445  pentest_set_trigger_low();
1446  // Get registered alerts from alert handler.
1447  reg_alerts = pentest_get_triggered_alerts();
1448  // Get fatal and recoverable AST alerts from sensor controller.
1449  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1450 
1451  // Read ERR_STATUS register.
1452  dif_rv_core_ibex_error_status_t codes;
1453  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1454 
1455  ibex_fi_test_result_mult_t uj_output;
1456  uj_output.err_status = codes;
1457  uj_output.result1 = value1;
1458  uj_output.result2 = value2;
1459  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1460  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1461  sizeof(sensor_alerts.alerts));
1462  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
1463 
1464  return OK_STATUS();
1465 }
1466 
1467 status_t handle_ibex_fi_char_hardened_check_eq_4_unimps(ujson_t *uj)
1468  __attribute__((optnone)) {
1469  // Clear registered alerts in alert handler.
1470  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1471  // Clear the AST recoverable alerts.
1472  pentest_clear_sensor_recov_alerts();
1473 
1474  // Values are intentially not equal.
1475  // uint32_t value1 = 0;
1476  // uint32_t value2 = 1;
1477  // JH: Changed 28th June. Tests before used unharded values
1478  hardened_bool_t value1 = HARDENED_BOOL_TRUE;
1479  hardened_bool_t value2 = HARDENED_BOOL_FALSE;
1480 
1481  pentest_set_trigger_high();
1482  asm volatile(NOP10);
1483  // The HARDENED_CHECK macro from hardened.h is solved explicitely.
1484  // clang-format off
1485  asm volatile("beq" " %0, %1, .L_HARDENED_%=;" \
1486  "unimp; unimp; unimp; unimp;" \
1487  ".L_HARDENED_%=:;"::"r"(value1), "r"(value2) );
1488  // clang-format on
1489  asm volatile(NOP10);
1490  pentest_set_trigger_low();
1491  // Get registered alerts from alert handler.
1492  reg_alerts = pentest_get_triggered_alerts();
1493  // Get fatal and recoverable AST alerts from sensor controller.
1494  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1495 
1496  // Read ERR_STATUS register.
1497  dif_rv_core_ibex_error_status_t codes;
1498  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1499 
1500  ibex_fi_test_result_mult_t uj_output;
1501  uj_output.err_status = codes;
1502  uj_output.result1 = value1;
1503  uj_output.result2 = value2;
1504  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1505  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1506  sizeof(sensor_alerts.alerts));
1507  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
1508 
1509  return OK_STATUS();
1510 }
1511 
1512 status_t handle_ibex_fi_char_hardened_check_eq_5_unimps(ujson_t *uj)
1513  __attribute__((optnone)) {
1514  // Clear registered alerts in alert handler.
1515  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1516  // Clear the AST recoverable alerts.
1517  pentest_clear_sensor_recov_alerts();
1518 
1519  // Values are intentially not equal.
1520  hardened_bool_t value1 = HARDENED_BOOL_TRUE;
1521  hardened_bool_t value2 = HARDENED_BOOL_FALSE;
1522 
1523  pentest_set_trigger_high();
1524  asm volatile(NOP10);
1525  // The HARDENED_CHECK macro from hardened.h is solved explicitely.
1526  // clang-format off
1527  asm volatile("beq" " %0, %1, .L_HARDENED_%=;" \
1528  "unimp; unimp; unimp; unimp; unimp;" \
1529  ".L_HARDENED_%=:;"::"r"(value1), "r"(value2) );
1530  // clang-format on
1531  asm volatile(NOP10);
1532  pentest_set_trigger_low();
1533  // Get registered alerts from alert handler.
1534  reg_alerts = pentest_get_triggered_alerts();
1535  // Get fatal and recoverable AST alerts from sensor controller.
1536  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1537 
1538  // Read ERR_STATUS register.
1539  dif_rv_core_ibex_error_status_t codes;
1540  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1541 
1542  ibex_fi_test_result_mult_t uj_output;
1543  uj_output.err_status = codes;
1544  uj_output.result1 = value1;
1545  uj_output.result2 = value2;
1546  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1547  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1548  sizeof(sensor_alerts.alerts));
1549  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
1550 
1551  return OK_STATUS();
1552 }
1553 
1554 status_t handle_ibex_fi_char_mem_op_loop(ujson_t *uj) {
1555  // Clear registered alerts in alert handler.
1556  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1557  // Clear the AST recoverable alerts.
1558  pentest_clear_sensor_recov_alerts();
1559 
1560  // FI code target.
1561  uint32_t loop_counter1 = 0;
1562  uint32_t loop_counter2 = 10000;
1563  pentest_set_trigger_high();
1564  asm volatile(NOP100);
1565  for (int loop_cnt = 0; loop_cnt < 10000; loop_cnt++) {
1566  asm volatile(LWADDISW1 : : "r"((uint32_t *)&loop_counter1));
1567  asm volatile(LWSUBISW1 : : "r"((uint32_t *)&loop_counter2));
1568  }
1569  pentest_set_trigger_low();
1570  // Get registered alerts from alert handler.
1571  reg_alerts = pentest_get_triggered_alerts();
1572  // Get fatal and recoverable AST alerts from sensor controller.
1573  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1574 
1575  // Read ERR_STATUS register.
1576  dif_rv_core_ibex_error_status_t codes;
1577  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1578 
1579  // Send loop counters & ERR_STATUS to host.
1580  ibex_fi_loop_counter_mirrored_t uj_output;
1581  uj_output.loop_counter1 = loop_counter1;
1582  uj_output.loop_counter2 = loop_counter2;
1583  uj_output.err_status = codes;
1584  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1585  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1586  sizeof(sensor_alerts.alerts));
1587  RESP_OK(ujson_serialize_ibex_fi_loop_counter_mirrored_t, uj, &uj_output);
1588  return OK_STATUS();
1589 }
1590 
1591 status_t handle_ibex_fi_char_register_file(ujson_t *uj) {
1592  // Clear registered alerts in alert handler.
1593  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1594  // Clear the AST recoverable alerts.
1595  pentest_clear_sensor_recov_alerts();
1596 
1597  uint32_t res_values[7];
1598  // Initialize temporary registers with reference values.
1599  asm volatile("li x5, %0" : : "i"(ref_values[0]));
1600  asm volatile("li x6, %0" : : "i"(ref_values[1]));
1601  asm volatile("li x7, %0" : : "i"(ref_values[2]));
1602  asm volatile("li x28, %0" : : "i"(ref_values[3]));
1603  asm volatile("li x29, %0" : : "i"(ref_values[4]));
1604  asm volatile("li x30, %0" : : "i"(ref_values[5]));
1605  asm volatile("li x31, %0" : : "i"(ref_values[6]));
1606 
1607  // FI code target.
1608  pentest_set_trigger_high();
1609  asm volatile(NOP1000);
1610  pentest_set_trigger_low();
1611  // Get registered alerts from alert handler.
1612  reg_alerts = pentest_get_triggered_alerts();
1613  // Get fatal and recoverable AST alerts from sensor controller.
1614  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1615 
1616  // Load register values.
1617  asm volatile("mv %0, x5" : "=r"(res_values[0]));
1618  asm volatile("mv %0, x6" : "=r"(res_values[1]));
1619  asm volatile("mv %0, x7" : "=r"(res_values[2]));
1620  asm volatile("mv %0, x28" : "=r"(res_values[3]));
1621  asm volatile("mv %0, x29" : "=r"(res_values[4]));
1622  asm volatile("mv %0, x30" : "=r"(res_values[5]));
1623  asm volatile("mv %0, x31" : "=r"(res_values[6]));
1624 
1625  // Check if one or multiple registers values are faulty.
1626  uint32_t res = 0;
1627  for (int it = 0; it < 7; it++) {
1628  if (res_values[it] != ref_values[it]) {
1629  res |= 1;
1630  LOG_ERROR("reg %d exp=%u got=%u", it, ref_values[it], res_values[it]);
1631  }
1632  }
1633 
1634  // Read ERR_STATUS register.
1635  dif_rv_core_ibex_error_status_t codes;
1636  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1637 
1638  // Send result & ERR_STATUS to host.
1639  ibex_fi_test_result_t uj_output;
1640  uj_output.result = res;
1641  uj_output.err_status = codes;
1642  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1643  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1644  sizeof(sensor_alerts.alerts));
1645  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
1646  return OK_STATUS();
1647 }
1648 
1649 status_t handle_ibex_fi_char_register_file_read(ujson_t *uj) {
1650  // Clear registered alerts in alert handler.
1651  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1652  // Clear the AST recoverable alerts.
1653  pentest_clear_sensor_recov_alerts();
1654 
1655  uint32_t res_values[6];
1656  // Initialize temporary registers with reference values.
1657  asm volatile("li x5, %0" : : "i"(ref_values[0]));
1658  asm volatile("li x6, %0" : : "i"(ref_values[1]));
1659  asm volatile("li x7, %0" : : "i"(ref_values[2]));
1660  asm volatile("li x28, %0" : : "i"(ref_values[3]));
1661  asm volatile("li x29, %0" : : "i"(ref_values[4]));
1662  asm volatile("li x30, %0" : : "i"(ref_values[5]));
1663 
1664  // FI code target.
1665  pentest_set_trigger_high();
1666  asm volatile(NOP10);
1667  asm volatile("or x5, x5, x5");
1668  asm volatile("or x6, x6, x6");
1669  asm volatile("or x7, x7, x7");
1670  asm volatile("or x28, x28, x28");
1671  asm volatile("or x29, x29, x29");
1672  asm volatile("or x30, x30, x30");
1673  asm volatile("or x5, x5, x5");
1674  asm volatile("or x6, x6, x6");
1675  asm volatile("or x7, x7, x7");
1676  asm volatile("or x28, x28, x28");
1677  asm volatile("or x29, x29, x29");
1678  asm volatile("or x30, x30, x30");
1679  asm volatile("or x5, x5, x5");
1680  asm volatile("or x6, x6, x6");
1681  asm volatile("or x7, x7, x7");
1682  asm volatile("or x28, x28, x28");
1683  asm volatile("or x29, x29, x29");
1684  asm volatile("or x30, x30, x30");
1685  asm volatile("or x5, x5, x5");
1686  asm volatile("or x6, x6, x6");
1687  asm volatile("or x7, x7, x7");
1688  asm volatile("or x28, x28, x28");
1689  asm volatile("or x29, x29, x29");
1690  asm volatile("or x30, x30, x30");
1691  asm volatile("or x5, x5, x5");
1692  asm volatile("or x6, x6, x6");
1693  asm volatile("or x7, x7, x7");
1694  asm volatile("or x28, x28, x28");
1695  asm volatile("or x29, x29, x29");
1696  asm volatile("or x30, x30, x30");
1697  pentest_set_trigger_low();
1698  // Get registered alerts from alert handler.
1699  reg_alerts = pentest_get_triggered_alerts();
1700  // Get fatal and recoverable AST alerts from sensor controller.
1701  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1702 
1703  // Load register values.
1704  asm volatile("mv %0, x5" : "=r"(res_values[0]));
1705  asm volatile("mv %0, x6" : "=r"(res_values[1]));
1706  asm volatile("mv %0, x7" : "=r"(res_values[2]));
1707  asm volatile("mv %0, x28" : "=r"(res_values[3]));
1708  asm volatile("mv %0, x29" : "=r"(res_values[4]));
1709  asm volatile("mv %0, x30" : "=r"(res_values[5]));
1710 
1711  // Check if one or multiple registers values are faulty.
1712  ibex_fi_faulty_addresses_data_t uj_output;
1713  memset(uj_output.addresses, 0, sizeof(uj_output.addresses));
1714  memset(uj_output.data, 0, sizeof(uj_output.data));
1715  for (uint32_t it = 0; it < 6; it++) {
1716  if (res_values[it] != ref_values[it]) {
1717  uj_output.addresses[it] = 1; // 1 indicates an error in the register at
1718  // position it
1719  uj_output.data[it] = res_values[it];
1720  }
1721  }
1722 
1723  // Read ERR_STATUS register.
1724  dif_rv_core_ibex_error_status_t codes;
1725  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1726 
1727  // Send result & ERR_STATUS to host.
1728  uj_output.err_status = codes;
1729  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1730  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1731  sizeof(sensor_alerts.alerts));
1732  RESP_OK(ujson_serialize_ibex_fi_faulty_addresses_data_t, uj, &uj_output);
1733  return OK_STATUS();
1734 }
1735 
1736 status_t handle_ibex_fi_char_reg_op_loop(ujson_t *uj) {
1737  // Clear registered alerts in alert handler.
1738  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1739  // Clear the AST recoverable alerts.
1740  pentest_clear_sensor_recov_alerts();
1741 
1742  // FI code target.
1743  uint32_t loop_counter1 = 0;
1744  uint32_t loop_counter2 = 10000;
1745  pentest_set_trigger_high();
1746  asm volatile(INITX5);
1747  asm volatile(INITX6);
1748  asm volatile(NOP100);
1749  for (int loop_cnt = 0; loop_cnt < 10000; loop_cnt++) {
1750  asm volatile(ADDI1);
1751  asm volatile(SUBI1);
1752  }
1753  asm volatile("mv %0, x5" : "=r"(loop_counter1));
1754  asm volatile("mv %0, x6" : "=r"(loop_counter2));
1755  pentest_set_trigger_low();
1756  // Get registered alerts from alert handler.
1757  reg_alerts = pentest_get_triggered_alerts();
1758  // Get fatal and recoverable AST alerts from sensor controller.
1759  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1760 
1761  // Read ERR_STATUS register.
1762  dif_rv_core_ibex_error_status_t codes;
1763  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1764 
1765  // Send loop counters & ERR_STATUS to host.
1766  ibex_fi_loop_counter_mirrored_t uj_output;
1767  uj_output.loop_counter1 = loop_counter1;
1768  uj_output.loop_counter2 = loop_counter2;
1769  uj_output.err_status = codes;
1770  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1771  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1772  sizeof(sensor_alerts.alerts));
1773  RESP_OK(ujson_serialize_ibex_fi_loop_counter_mirrored_t, uj, &uj_output);
1774  return OK_STATUS();
1775 }
1776 
1777 status_t handle_ibex_fi_char_sram_read(ujson_t *uj) {
1778  // Clear registered alerts in alert handler.
1779  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1780  // Clear the AST recoverable alerts.
1781  pentest_clear_sensor_recov_alerts();
1782 
1783  // Init t0...t6 with 0.
1784  init_temp_regs(0);
1785 
1786  // Write reference value into SRAM.
1787  sram_main_buffer[0] = ref_values[0];
1788 
1789  // FI code target.
1790  pentest_set_trigger_high();
1791  asm volatile(NOP10);
1792  // Read from SRAM into temporary registers.
1793  asm volatile("lw x5, (%0)" : : "r"(&sram_main_buffer[0]));
1794  asm volatile("lw x6, (%0)" : : "r"(&sram_main_buffer[0]));
1795  asm volatile("lw x7, (%0)" : : "r"(&sram_main_buffer[0]));
1796  asm volatile("lw x28, (%0)" : : "r"(&sram_main_buffer[0]));
1797  asm volatile("lw x29, (%0)" : : "r"(&sram_main_buffer[0]));
1798  asm volatile("lw x30, (%0)" : : "r"(&sram_main_buffer[0]));
1799  asm volatile("lw x31, (%0)" : : "r"(&sram_main_buffer[0]));
1800  asm volatile(NOP10);
1801  pentest_set_trigger_low();
1802 
1803  // Load register values.
1804  // Result buffer.
1805  uint32_t res_values[7];
1806  read_temp_regs(res_values);
1807 
1808  // Get registered alerts from alert handler.
1809  reg_alerts = pentest_get_triggered_alerts();
1810  // Get fatal and recoverable AST alerts from sensor controller.
1811  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1812 
1813  ibex_fi_faulty_addresses_data_t uj_output;
1814  memset(uj_output.addresses, 0, sizeof(uj_output.addresses));
1815  memset(uj_output.data, 0, sizeof(uj_output.data));
1816 
1817  for (uint32_t sram_pos = 0; sram_pos < 7; sram_pos++) {
1818  if (res_values[sram_pos] != ref_values[0]) {
1819  uj_output.addresses[sram_pos] = sram_pos;
1820  uj_output.data[sram_pos] = res_values[sram_pos];
1821  }
1822  }
1823 
1824  // Read ERR_STATUS register.
1825  dif_rv_core_ibex_error_status_t codes;
1826  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1827 
1828  // Send res & ERR_STATUS to host.
1829  uj_output.err_status = codes;
1830  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1831  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1832  sizeof(sensor_alerts.alerts));
1833  RESP_OK(ujson_serialize_ibex_fi_faulty_addresses_data_t, uj, &uj_output);
1834  return OK_STATUS();
1835 }
1836 
1837 status_t handle_ibex_fi_char_sram_static(ujson_t *uj) {
1838  if (!sram_ret_init) {
1839  // Init retention SRAM, wipe and scramble it.
1840  dif_sram_ctrl_t ret_sram;
1841  mmio_region_t addr =
1843  TRY(dif_sram_ctrl_init(addr, &ret_sram));
1844  TRY(sram_ctrl_testutils_wipe(&ret_sram));
1845  TRY(sram_ctrl_testutils_scramble(&ret_sram));
1846  sram_ret_init = true;
1847  }
1848 
1849  int max_words =
1850  (TOP_EARLGREY_SRAM_CTRL_RET_AON_RAM_SIZE_BYTES / sizeof(uint32_t)) - 1;
1851 
1852  // Clear registered alerts in alert handler.
1853  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1854  // Clear the AST recoverable alerts.
1855  pentest_clear_sensor_recov_alerts();
1856 
1857  // Get address of the ret. SRAM at the beginning of the owner section.
1858  uintptr_t sram_ret_buffer_addr =
1860  offsetof(retention_sram_t, owner);
1861  mmio_region_t sram_region_ret_addr =
1862  mmio_region_from_addr(sram_ret_buffer_addr);
1863 
1864  // Write reference value into SRAM.
1865  for (int i = 0; i < max_words; i++) {
1866  mmio_region_write32(sram_region_ret_addr, i * (ptrdiff_t)sizeof(uint32_t),
1867  ref_values[0]);
1868  }
1869 
1870  // FI code target.
1871  pentest_set_trigger_high();
1872  asm volatile(NOP1000);
1873  pentest_set_trigger_low();
1874  // Get registered alerts from alert handler.
1875  reg_alerts = pentest_get_triggered_alerts();
1876  // Get fatal and recoverable AST alerts from sensor controller.
1877  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1878 
1879  // Compare against reference values.
1880  ibex_fi_faulty_addresses_data_t uj_output;
1881  memset(uj_output.addresses, 0, sizeof(uj_output.addresses));
1882  memset(uj_output.data, 0, sizeof(uj_output.data));
1883  int faulty_address_pos = 0;
1884  for (int sram_pos = 0; sram_pos < max_words; sram_pos++) {
1885  uint32_t res_value = mmio_region_read32(
1886  sram_region_ret_addr, sram_pos * (ptrdiff_t)sizeof(uint32_t));
1887  if (res_value != ref_values[0]) {
1888  uj_output.addresses[faulty_address_pos] = (uint32_t)sram_pos;
1889  uj_output.data[faulty_address_pos] = res_value;
1890  faulty_address_pos++;
1891  // Currently, we register only up to 8 faulty SRAM positions. If there
1892  // are more, we overwrite the addresses array.
1893  if (faulty_address_pos > 7) {
1894  faulty_address_pos = 0;
1895  }
1896  }
1897  }
1898 
1899  // Read ERR_STATUS register.
1900  dif_rv_core_ibex_error_status_t codes;
1901  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1902 
1903  // Send res & ERR_STATUS to host.
1904  uj_output.err_status = codes;
1905  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1906  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1907  sizeof(sensor_alerts.alerts));
1908  RESP_OK(ujson_serialize_ibex_fi_faulty_addresses_data_t, uj, &uj_output);
1909  return OK_STATUS(0);
1910 }
1911 
1912 status_t handle_ibex_fi_char_sram_write(ujson_t *uj) {
1913  // Clear registered alerts in alert handler.
1914  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1915  // Clear the AST recoverable alerts.
1916  pentest_clear_sensor_recov_alerts();
1917 
1918  // Get address of buffer located in SRAM.
1919  uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer;
1920  mmio_region_t sram_region_main_addr =
1921  mmio_region_from_addr(sram_main_buffer_addr);
1922 
1923  // Initialize SRAM region with inverse ref_values to avoid that data from a
1924  // previous run are still in memory.
1925  for (int i = 0; i < 32; i++) {
1926  mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)sizeof(uint32_t),
1927  ~ref_values[i]);
1928  }
1929 
1930  // FI code target.
1931  pentest_set_trigger_high();
1932  for (int i = 0; i < 32; i++) {
1933  mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)sizeof(uint32_t),
1934  ref_values[i]);
1935  }
1936  pentest_set_trigger_low();
1937  // Get registered alerts from alert handler.
1938  reg_alerts = pentest_get_triggered_alerts();
1939  // Get fatal and recoverable AST alerts from sensor controller.
1940  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1941 
1942  // Read back and compare against reference values.
1943  uint32_t res_values[32];
1944  uint32_t res = 0;
1945  for (int i = 0; i < 32; i++) {
1946  res_values[i] = mmio_region_read32(sram_region_main_addr,
1947  i * (ptrdiff_t)sizeof(uint32_t));
1948  if (res_values[i] != ref_values[i]) {
1949  res |= 1;
1950  }
1951  }
1952 
1953  // Read ERR_STATUS register.
1954  dif_rv_core_ibex_error_status_t codes;
1955  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1956 
1957  // Send res & ERR_STATUS to host.
1958  ibex_fi_test_result_t uj_output;
1959  uj_output.result = res;
1960  uj_output.err_status = codes;
1961  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1962  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1963  sizeof(sensor_alerts.alerts));
1964  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
1965  return OK_STATUS();
1966 }
1967 
1968 status_t handle_ibex_fi_char_sram_write_read(ujson_t *uj)
1969  __attribute__((optnone)) {
1970  // Clear registered alerts in alert handler.
1971  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1972  // Clear the AST recoverable alerts.
1973  pentest_clear_sensor_recov_alerts();
1974 
1975  // Initialize SRAM region with inverse reference value.
1976  sram_main_buffer[0] = ~ref_values[0];
1977 
1978  // Init x5, x6, x6 with the reference values.
1979  asm volatile("li x5, %0" : : "i"(ref_values[0]));
1980  asm volatile("li x6, %0" : : "i"(ref_values[1]));
1981  asm volatile("li x7, %0" : : "i"(ref_values[2]));
1982 
1983  pentest_set_trigger_high();
1984  asm volatile(NOP10);
1985  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1986  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1987  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1988  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1989  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1990  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1991  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1992  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1993  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1994  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1995  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1996  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1997  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1998  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
1999  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2000  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2001  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2002  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2003  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2004  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2005  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2006  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2007  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2008  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2009  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2010  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2011  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2012  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2013  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2014  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2015  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2016  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2017  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2018  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2019  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2020  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2021  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2022  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2023  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2024  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2025  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2026  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2027  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2028  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2029  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2030  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2031  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2032  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2033  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2034  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2035  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2036  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2037  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2038  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2039  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2040  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2041  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2042  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2043  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2044  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2045  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2046  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2047  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2048  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2049  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2050  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2051  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2052  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2053  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2054  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2055  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2056  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2057  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2058  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2059  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2060  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2061  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2062  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2063  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2064  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2065  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2066  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2067  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2068  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2069  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2070  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2071  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2072  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2073  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2074  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2075  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2076  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2077  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2078  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2079  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2080  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2081  asm volatile(NOP10);
2082  pentest_set_trigger_low();
2083  // Get registered alerts from alert handler.
2084  reg_alerts = pentest_get_triggered_alerts();
2085  // Get fatal and recoverable AST alerts from sensor controller.
2086  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2087 
2088  uint32_t res_values[3];
2089  asm volatile("mv %0, x5" : "=r"(res_values[0]));
2090  asm volatile("mv %0, x6" : "=r"(res_values[1]));
2091  asm volatile("mv %0, x7" : "=r"(res_values[2]));
2092 
2093  // Compare against reference values.
2094  ibex_fi_faulty_addresses_data_t uj_output;
2095  memset(uj_output.addresses, 0, sizeof(uj_output.addresses));
2096  memset(uj_output.data, 0, sizeof(uj_output.data));
2097 
2098  for (uint32_t addr = 0; addr < 3; addr++) {
2099  if (res_values[addr] != ref_values[addr]) {
2100  uj_output.addresses[addr] = (uint32_t)&sram_main_buffer[0];
2101  uj_output.data[addr] = res_values[addr];
2102  }
2103  }
2104 
2105  // Read ERR_STATUS register.
2106  dif_rv_core_ibex_error_status_t codes;
2107  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2108 
2109  // Send res & ERR_STATUS to host.
2110  uj_output.err_status = codes;
2111  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2112  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2113  sizeof(sensor_alerts.alerts));
2114  RESP_OK(ujson_serialize_ibex_fi_faulty_addresses_data_t, uj, &uj_output);
2115  return OK_STATUS();
2116 }
2117 
2118 status_t handle_ibex_fi_char_sram_write_static_unrolled(ujson_t *uj) {
2119  // Clear registered alerts in alert handler.
2120  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2121  // Clear the AST recoverable alerts.
2122  pentest_clear_sensor_recov_alerts();
2123 
2124  // Get address of buffer located in SRAM.
2125  uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer;
2126  mmio_region_t sram_region_main_addr =
2127  mmio_region_from_addr(sram_main_buffer_addr);
2128 
2129  // Initialize SRAM region with inverse ref_values to avoid that data from a
2130  // previous run are still in memory.
2131  for (int i = 0; i < 64; i++) {
2132  mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)sizeof(uint32_t),
2133  ~ref_values[0]);
2134  }
2135 
2136  // FI code target.
2137  // Unrolled for easier fault injection characterization.
2138  pentest_set_trigger_high();
2139  mmio_region_write32(sram_region_main_addr, 0 * (ptrdiff_t)sizeof(uint32_t),
2140  ref_values[0]);
2141  mmio_region_write32(sram_region_main_addr, 1 * (ptrdiff_t)sizeof(uint32_t),
2142  ref_values[0]);
2143  mmio_region_write32(sram_region_main_addr, 2 * (ptrdiff_t)sizeof(uint32_t),
2144  ref_values[0]);
2145  mmio_region_write32(sram_region_main_addr, 3 * (ptrdiff_t)sizeof(uint32_t),
2146  ref_values[0]);
2147  mmio_region_write32(sram_region_main_addr, 4 * (ptrdiff_t)sizeof(uint32_t),
2148  ref_values[0]);
2149  mmio_region_write32(sram_region_main_addr, 5 * (ptrdiff_t)sizeof(uint32_t),
2150  ref_values[0]);
2151  mmio_region_write32(sram_region_main_addr, 6 * (ptrdiff_t)sizeof(uint32_t),
2152  ref_values[0]);
2153  mmio_region_write32(sram_region_main_addr, 7 * (ptrdiff_t)sizeof(uint32_t),
2154  ref_values[0]);
2155  mmio_region_write32(sram_region_main_addr, 8 * (ptrdiff_t)sizeof(uint32_t),
2156  ref_values[0]);
2157  mmio_region_write32(sram_region_main_addr, 9 * (ptrdiff_t)sizeof(uint32_t),
2158  ref_values[0]);
2159  mmio_region_write32(sram_region_main_addr, 10 * (ptrdiff_t)sizeof(uint32_t),
2160  ref_values[0]);
2161  mmio_region_write32(sram_region_main_addr, 11 * (ptrdiff_t)sizeof(uint32_t),
2162  ref_values[0]);
2163  mmio_region_write32(sram_region_main_addr, 12 * (ptrdiff_t)sizeof(uint32_t),
2164  ref_values[0]);
2165  mmio_region_write32(sram_region_main_addr, 13 * (ptrdiff_t)sizeof(uint32_t),
2166  ref_values[0]);
2167  mmio_region_write32(sram_region_main_addr, 14 * (ptrdiff_t)sizeof(uint32_t),
2168  ref_values[0]);
2169  mmio_region_write32(sram_region_main_addr, 15 * (ptrdiff_t)sizeof(uint32_t),
2170  ref_values[0]);
2171  mmio_region_write32(sram_region_main_addr, 16 * (ptrdiff_t)sizeof(uint32_t),
2172  ref_values[0]);
2173  mmio_region_write32(sram_region_main_addr, 17 * (ptrdiff_t)sizeof(uint32_t),
2174  ref_values[0]);
2175  mmio_region_write32(sram_region_main_addr, 18 * (ptrdiff_t)sizeof(uint32_t),
2176  ref_values[0]);
2177  mmio_region_write32(sram_region_main_addr, 19 * (ptrdiff_t)sizeof(uint32_t),
2178  ref_values[0]);
2179  mmio_region_write32(sram_region_main_addr, 20 * (ptrdiff_t)sizeof(uint32_t),
2180  ref_values[0]);
2181  mmio_region_write32(sram_region_main_addr, 21 * (ptrdiff_t)sizeof(uint32_t),
2182  ref_values[0]);
2183  mmio_region_write32(sram_region_main_addr, 22 * (ptrdiff_t)sizeof(uint32_t),
2184  ref_values[0]);
2185  mmio_region_write32(sram_region_main_addr, 23 * (ptrdiff_t)sizeof(uint32_t),
2186  ref_values[0]);
2187  mmio_region_write32(sram_region_main_addr, 24 * (ptrdiff_t)sizeof(uint32_t),
2188  ref_values[0]);
2189  mmio_region_write32(sram_region_main_addr, 25 * (ptrdiff_t)sizeof(uint32_t),
2190  ref_values[0]);
2191  mmio_region_write32(sram_region_main_addr, 26 * (ptrdiff_t)sizeof(uint32_t),
2192  ref_values[0]);
2193  mmio_region_write32(sram_region_main_addr, 27 * (ptrdiff_t)sizeof(uint32_t),
2194  ref_values[0]);
2195  mmio_region_write32(sram_region_main_addr, 28 * (ptrdiff_t)sizeof(uint32_t),
2196  ref_values[0]);
2197  mmio_region_write32(sram_region_main_addr, 29 * (ptrdiff_t)sizeof(uint32_t),
2198  ref_values[0]);
2199  mmio_region_write32(sram_region_main_addr, 30 * (ptrdiff_t)sizeof(uint32_t),
2200  ref_values[0]);
2201  mmio_region_write32(sram_region_main_addr, 31 * (ptrdiff_t)sizeof(uint32_t),
2202  ref_values[0]);
2203  mmio_region_write32(sram_region_main_addr, 32 * (ptrdiff_t)sizeof(uint32_t),
2204  ref_values[0]);
2205  mmio_region_write32(sram_region_main_addr, 33 * (ptrdiff_t)sizeof(uint32_t),
2206  ref_values[0]);
2207  mmio_region_write32(sram_region_main_addr, 34 * (ptrdiff_t)sizeof(uint32_t),
2208  ref_values[0]);
2209  mmio_region_write32(sram_region_main_addr, 35 * (ptrdiff_t)sizeof(uint32_t),
2210  ref_values[0]);
2211  mmio_region_write32(sram_region_main_addr, 36 * (ptrdiff_t)sizeof(uint32_t),
2212  ref_values[0]);
2213  mmio_region_write32(sram_region_main_addr, 37 * (ptrdiff_t)sizeof(uint32_t),
2214  ref_values[0]);
2215  mmio_region_write32(sram_region_main_addr, 38 * (ptrdiff_t)sizeof(uint32_t),
2216  ref_values[0]);
2217  mmio_region_write32(sram_region_main_addr, 39 * (ptrdiff_t)sizeof(uint32_t),
2218  ref_values[0]);
2219  mmio_region_write32(sram_region_main_addr, 40 * (ptrdiff_t)sizeof(uint32_t),
2220  ref_values[0]);
2221  mmio_region_write32(sram_region_main_addr, 41 * (ptrdiff_t)sizeof(uint32_t),
2222  ref_values[0]);
2223  mmio_region_write32(sram_region_main_addr, 42 * (ptrdiff_t)sizeof(uint32_t),
2224  ref_values[0]);
2225  mmio_region_write32(sram_region_main_addr, 43 * (ptrdiff_t)sizeof(uint32_t),
2226  ref_values[0]);
2227  mmio_region_write32(sram_region_main_addr, 44 * (ptrdiff_t)sizeof(uint32_t),
2228  ref_values[0]);
2229  mmio_region_write32(sram_region_main_addr, 45 * (ptrdiff_t)sizeof(uint32_t),
2230  ref_values[0]);
2231  mmio_region_write32(sram_region_main_addr, 46 * (ptrdiff_t)sizeof(uint32_t),
2232  ref_values[0]);
2233  mmio_region_write32(sram_region_main_addr, 47 * (ptrdiff_t)sizeof(uint32_t),
2234  ref_values[0]);
2235  mmio_region_write32(sram_region_main_addr, 48 * (ptrdiff_t)sizeof(uint32_t),
2236  ref_values[0]);
2237  mmio_region_write32(sram_region_main_addr, 49 * (ptrdiff_t)sizeof(uint32_t),
2238  ref_values[0]);
2239  mmio_region_write32(sram_region_main_addr, 50 * (ptrdiff_t)sizeof(uint32_t),
2240  ref_values[0]);
2241  mmio_region_write32(sram_region_main_addr, 51 * (ptrdiff_t)sizeof(uint32_t),
2242  ref_values[0]);
2243  mmio_region_write32(sram_region_main_addr, 52 * (ptrdiff_t)sizeof(uint32_t),
2244  ref_values[0]);
2245  mmio_region_write32(sram_region_main_addr, 53 * (ptrdiff_t)sizeof(uint32_t),
2246  ref_values[0]);
2247  mmio_region_write32(sram_region_main_addr, 54 * (ptrdiff_t)sizeof(uint32_t),
2248  ref_values[0]);
2249  mmio_region_write32(sram_region_main_addr, 55 * (ptrdiff_t)sizeof(uint32_t),
2250  ref_values[0]);
2251  mmio_region_write32(sram_region_main_addr, 56 * (ptrdiff_t)sizeof(uint32_t),
2252  ref_values[0]);
2253  mmio_region_write32(sram_region_main_addr, 57 * (ptrdiff_t)sizeof(uint32_t),
2254  ref_values[0]);
2255  mmio_region_write32(sram_region_main_addr, 58 * (ptrdiff_t)sizeof(uint32_t),
2256  ref_values[0]);
2257  mmio_region_write32(sram_region_main_addr, 59 * (ptrdiff_t)sizeof(uint32_t),
2258  ref_values[0]);
2259  mmio_region_write32(sram_region_main_addr, 60 * (ptrdiff_t)sizeof(uint32_t),
2260  ref_values[0]);
2261  mmio_region_write32(sram_region_main_addr, 61 * (ptrdiff_t)sizeof(uint32_t),
2262  ref_values[0]);
2263  mmio_region_write32(sram_region_main_addr, 62 * (ptrdiff_t)sizeof(uint32_t),
2264  ref_values[0]);
2265  mmio_region_write32(sram_region_main_addr, 63 * (ptrdiff_t)sizeof(uint32_t),
2266  ref_values[0]);
2267  pentest_set_trigger_low();
2268  // Get registered alerts from alert handler.
2269  reg_alerts = pentest_get_triggered_alerts();
2270  // Get fatal and recoverable AST alerts from sensor controller.
2271  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2272 
2273  // Read back and compare against reference values.
2274  uint32_t res_values[64];
2275  uint32_t res = 0;
2276  for (int i = 0; i < 64; i++) {
2277  res_values[i] = mmio_region_read32(sram_region_main_addr,
2278  i * (ptrdiff_t)sizeof(uint32_t));
2279  if (res_values[i] != ref_values[0]) {
2280  res |= 1;
2281  }
2282  }
2283 
2284  // Read ERR_STATUS register.
2285  dif_rv_core_ibex_error_status_t codes;
2286  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2287 
2288  // Send res & ERR_STATUS to host.
2289  ibex_fi_test_result_t uj_output;
2290  uj_output.result = res;
2291  uj_output.err_status = codes;
2292  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2293  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2294  sizeof(sensor_alerts.alerts));
2295  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
2296  return OK_STATUS();
2297 }
2298 
2299 status_t handle_ibex_fi_char_unconditional_branch(ujson_t *uj) {
2300  // Clear registered alerts in alert handler.
2301  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2302  // Clear the AST recoverable alerts.
2303  pentest_clear_sensor_recov_alerts();
2304 
2305  // FI code target.
2306  uint32_t result = 0;
2307  pentest_set_trigger_high();
2308  // Init x5 register we are using for the increment.
2309  asm volatile(INITX5);
2310  // Delay the trigger.
2311  asm volatile(NOP10);
2312  // Attack target.
2313  asm volatile("jal ra, increment_counter");
2314  asm volatile("jal ra, increment_counter");
2315  asm volatile("jal ra, increment_counter");
2316  asm volatile("jal ra, increment_counter");
2317  asm volatile("jal ra, increment_counter");
2318  asm volatile("jal ra, increment_counter");
2319  asm volatile("jal ra, increment_counter");
2320  asm volatile("jal ra, increment_counter");
2321  asm volatile("jal ra, increment_counter");
2322  asm volatile("jal ra, increment_counter");
2323  asm volatile("jal ra, increment_counter");
2324  asm volatile("jal ra, increment_counter");
2325  asm volatile("jal ra, increment_counter");
2326  asm volatile("jal ra, increment_counter");
2327  asm volatile("jal ra, increment_counter");
2328  asm volatile("jal ra, increment_counter");
2329  asm volatile("jal ra, increment_counter");
2330  asm volatile("jal ra, increment_counter");
2331  asm volatile("jal ra, increment_counter");
2332  asm volatile("jal ra, increment_counter");
2333  asm volatile("jal ra, increment_counter");
2334  asm volatile("jal ra, increment_counter");
2335  asm volatile("jal ra, increment_counter");
2336  asm volatile("jal ra, increment_counter");
2337  asm volatile("jal ra, increment_counter");
2338  asm volatile("jal ra, increment_counter");
2339  asm volatile("jal ra, increment_counter");
2340  asm volatile("jal ra, increment_counter");
2341  asm volatile("jal ra, increment_counter");
2342  asm volatile("jal ra, increment_counter");
2343  asm volatile("mv %0, x5" : "=r"(result));
2344  pentest_set_trigger_low();
2345  // Get registered alerts from alert handler.
2346  reg_alerts = pentest_get_triggered_alerts();
2347  // Get fatal and recoverable AST alerts from sensor controller.
2348  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2349 
2350  // Read ERR_STATUS register.
2351  dif_rv_core_ibex_error_status_t codes;
2352  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2353 
2354  // Send loop counters & ERR_STATUS to host.
2355  ibex_fi_test_result_t uj_output;
2356  uj_output.result = result;
2357  uj_output.err_status = codes;
2358  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2359  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2360  sizeof(sensor_alerts.alerts));
2361  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
2362  return OK_STATUS();
2363 }
2364 
2365 status_t handle_ibex_fi_char_unconditional_branch_nop(ujson_t *uj) {
2366  uint32_t registers[32] = {0};
2367  read_all_regs(registers);
2368  // Clear registered alerts in alert handler.
2369  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2370  // Clear the AST recoverable alerts.
2371  pentest_clear_sensor_recov_alerts();
2372 
2373  // FI code target.
2374  uint32_t result = 0;
2375  pentest_set_trigger_high();
2376  // Init x5 register we are using for the increment.
2377  asm volatile(INITX5);
2378  // Delay the trigger.
2379  asm volatile(NOP10);
2380  // Attack target.
2381  asm volatile("jal ra, not_increment_counter");
2382  asm volatile("jal ra, not_increment_counter");
2383  asm volatile("jal ra, not_increment_counter");
2384  asm volatile("jal ra, not_increment_counter");
2385  asm volatile("jal ra, not_increment_counter");
2386  asm volatile("jal ra, not_increment_counter");
2387  asm volatile("jal ra, not_increment_counter");
2388  asm volatile("jal ra, not_increment_counter");
2389  asm volatile("jal ra, not_increment_counter");
2390  asm volatile("jal ra, not_increment_counter");
2391  asm volatile("jal ra, not_increment_counter");
2392  asm volatile("jal ra, not_increment_counter");
2393  asm volatile("jal ra, not_increment_counter");
2394  asm volatile("jal ra, not_increment_counter");
2395  asm volatile("jal ra, not_increment_counter");
2396  asm volatile("jal ra, not_increment_counter");
2397  asm volatile("jal ra, not_increment_counter");
2398  asm volatile("jal ra, not_increment_counter");
2399  asm volatile("jal ra, not_increment_counter");
2400  asm volatile("jal ra, not_increment_counter");
2401  asm volatile("jal ra, not_increment_counter");
2402  asm volatile("jal ra, not_increment_counter");
2403  asm volatile("jal ra, not_increment_counter");
2404  asm volatile("jal ra, not_increment_counter");
2405  asm volatile("jal ra, not_increment_counter");
2406  asm volatile("jal ra, not_increment_counter");
2407  asm volatile("jal ra, not_increment_counter");
2408  asm volatile("jal ra, not_increment_counter");
2409  asm volatile("jal ra, not_increment_counter");
2410  asm volatile("jal ra, not_increment_counter");
2411  read_all_regs(registers);
2412  asm volatile("mv %0, x5" : "=r"(result));
2413  pentest_set_trigger_low();
2414  // Get registered alerts from alert handler.
2415  reg_alerts = pentest_get_triggered_alerts();
2416  // Get fatal and recoverable AST alerts from sensor controller.
2417  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2418 
2419  // Read ERR_STATUS register.
2420  dif_rv_core_ibex_error_status_t codes;
2421  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2422 
2423  // Send loop counters & ERR_STATUS to host.
2424  ibex_fi_test_result_registers_t uj_output;
2425  uj_output.result = result;
2426  memcpy(uj_output.registers, registers, sizeof(registers));
2427  uj_output.err_status = codes;
2428  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2429  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2430  sizeof(sensor_alerts.alerts));
2431  RESP_OK(ujson_serialize_ibex_fi_test_result_registers_t, uj, &uj_output);
2432  return OK_STATUS();
2433 }
2434 
2435 status_t handle_ibex_fi_char_unrolled_mem_op_loop(ujson_t *uj) {
2436  // Clear registered alerts in alert handler.
2437  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2438  // Clear the AST recoverable alerts.
2439  pentest_clear_sensor_recov_alerts();
2440 
2441  // FI code target.
2442  uint32_t loop_counter = 0;
2443  pentest_set_trigger_high();
2444  asm volatile(NOP100);
2445  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2446  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2447  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2448  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2449  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2450  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2451  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2452  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2453  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2454  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2455  pentest_set_trigger_low();
2456  // Get registered alerts from alert handler.
2457  reg_alerts = pentest_get_triggered_alerts();
2458  // Get fatal and recoverable AST alerts from sensor controller.
2459  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2460 
2461  // Read ERR_STATUS register.
2462  dif_rv_core_ibex_error_status_t codes;
2463  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2464 
2465  // Send loop counter & ERR_STATUS to host.
2466  ibex_fi_loop_counter_t uj_output;
2467  uj_output.loop_counter = loop_counter;
2468  uj_output.err_status = codes;
2469  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2470  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2471  sizeof(sensor_alerts.alerts));
2472  RESP_OK(ujson_serialize_ibex_fi_loop_counter_t, uj, &uj_output);
2473  return OK_STATUS();
2474 }
2475 
2476 status_t handle_ibex_fi_char_unrolled_reg_op_loop(ujson_t *uj) {
2477  // Clear registered alerts in alert handler.
2478  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2479  // Clear the AST recoverable alerts.
2480  pentest_clear_sensor_recov_alerts();
2481 
2482  // FI code target.
2483  uint32_t loop_counter = 0;
2484  pentest_set_trigger_high();
2485  asm volatile(INITX5);
2486  asm volatile(NOP100);
2487  asm volatile(ADDI1000);
2488  asm volatile(ADDI1000);
2489  asm volatile(ADDI1000);
2490  asm volatile(ADDI1000);
2491  asm volatile(ADDI1000);
2492  asm volatile(ADDI1000);
2493  asm volatile(ADDI1000);
2494  asm volatile(ADDI1000);
2495  asm volatile(ADDI1000);
2496  asm volatile(ADDI1000);
2497  asm volatile("mv %0, x5" : "=r"(loop_counter));
2498  pentest_set_trigger_low();
2499  // Get registered alerts from alert handler.
2500  reg_alerts = pentest_get_triggered_alerts();
2501  // Get fatal and recoverable AST alerts from sensor controller.
2502  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2503 
2504  // Read ERR_STATUS register.
2505  dif_rv_core_ibex_error_status_t codes;
2506  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2507 
2508  // Send loop counter & ERR_STATUS to host.
2509  ibex_fi_loop_counter_t uj_output;
2510  uj_output.loop_counter = loop_counter;
2511  uj_output.err_status = codes;
2512  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2513  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2514  sizeof(sensor_alerts.alerts));
2515  RESP_OK(ujson_serialize_ibex_fi_loop_counter_t, uj, &uj_output);
2516  return OK_STATUS();
2517 }
2518 
2519 status_t handle_ibex_fi_char_unrolled_reg_op_loop_chain(ujson_t *uj) {
2520  // Clear registered alerts in alert handler.
2521  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2522  // Clear the AST recoverable alerts.
2523  pentest_clear_sensor_recov_alerts();
2524 
2525  uint32_t addresses[8] = {0};
2526  uint32_t data[8] = {0};
2527 
2528  // FI code target.
2529  pentest_set_trigger_high();
2530  asm volatile(INIT_TMPREGS);
2531  asm volatile(NOP10);
2532  asm volatile(ADDI_CHAIN);
2533  asm volatile(ADDI_CHAIN);
2534  asm volatile(ADDI_CHAIN);
2535  asm volatile(ADDI_CHAIN);
2536  asm volatile(ADDI_CHAIN);
2537  asm volatile(ADDI_CHAIN);
2538  asm volatile(ADDI_CHAIN);
2539  asm volatile(ADDI_CHAIN);
2540  asm volatile(ADDI_CHAIN);
2541  asm volatile(ADDI_CHAIN);
2542  asm volatile("mv %0, x5" : "=r"(data[0]));
2543  asm volatile("mv %0, x6" : "=r"(data[1]));
2544  asm volatile("mv %0, x7" : "=r"(data[2]));
2545  asm volatile("mv %0, x28" : "=r"(data[3]));
2546  asm volatile("mv %0, x29" : "=r"(data[4]));
2547  asm volatile("mv %0, x30" : "=r"(data[5]));
2548  pentest_set_trigger_low();
2549 
2550  // Get registered alerts from alert handler.
2551  reg_alerts = pentest_get_triggered_alerts();
2552  // Get fatal and recoverable AST alerts from sensor controller.
2553  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2554 
2555  // Read ERR_STATUS register.
2556  dif_rv_core_ibex_error_status_t codes;
2557  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2558 
2559  // Send data, alerts & ERR_STATUS to host.
2560  ibex_fi_faulty_addresses_data_t uj_output;
2561  memcpy(uj_output.addresses, addresses, sizeof(addresses));
2562  memcpy(uj_output.data, data, sizeof(data));
2563  uj_output.err_status = codes;
2564  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2565  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2566  sizeof(sensor_alerts.alerts));
2567  RESP_OK(ujson_serialize_ibex_fi_faulty_addresses_data_t, uj, &uj_output);
2568  return OK_STATUS();
2569 }
2570 
2571 status_t handle_ibex_fi_init(ujson_t *uj) {
2572  penetrationtest_cpuctrl_t uj_data;
2573  TRY(ujson_deserialize_penetrationtest_cpuctrl_t(uj, &uj_data));
2574 
2575  pentest_select_trigger_type(kPentestTriggerTypeSw);
2576  // As we are using the software defined trigger, the first argument of
2577  // pentest_init is not needed. kPentestTriggerSourceAes is selected as a
2578  // placeholder.
2579  pentest_init(kPentestTriggerSourceAes,
2580  kPentestPeripheralIoDiv4 | kPentestPeripheralEdn |
2581  kPentestPeripheralCsrng | kPentestPeripheralEntropy |
2582  kPentestPeripheralAes | kPentestPeripheralHmac |
2583  kPentestPeripheralKmac | kPentestPeripheralOtbn);
2584 
2585  // Configure the alert handler. Alerts triggered by IP blocks are captured
2586  // and reported to the test.
2587  pentest_configure_alert_handler();
2588 
2589  // Configure the CPU for the pentest.
2590  penetrationtest_device_info_t uj_output;
2591  TRY(pentest_configure_cpu(
2592  uj_data.icache_disable, uj_data.dummy_instr_disable,
2593  uj_data.enable_jittery_clock, uj_data.enable_sram_readback,
2594  &uj_output.clock_jitter_locked, &uj_output.clock_jitter_en,
2595  &uj_output.sram_main_readback_locked, &uj_output.sram_ret_readback_locked,
2596  &uj_output.sram_main_readback_en, &uj_output.sram_ret_readback_en));
2597 
2598  // Enable the flash.
2599  flash_info = dif_flash_ctrl_get_device_info();
2602  TRY(flash_ctrl_testutils_wait_for_init(&flash));
2603 
2604  // Init OTP.
2605  TRY(dif_otp_ctrl_init(
2607 
2608  // Configure Ibex to allow reading ERR_STATUS register.
2609  TRY(dif_rv_core_ibex_init(
2611  &rv_core_ibex));
2612 
2613  // Read device ID and return to host.
2614  TRY(pentest_read_device_id(uj_output.device_id));
2615  RESP_OK(ujson_serialize_penetrationtest_device_info_t, uj, &uj_output);
2616 
2617  // Initialize flash for the flash test and write reference values into page.
2618  flash_init = false;
2619  flash_data_valid = false;
2620  // Initialize retention SRAM.
2621  sram_ret_init = false;
2622  // Fetch reference values from OTP before OTP tests.
2623  otp_ref_init = false;
2624 
2625  return OK_STATUS();
2626 }
2627 
2628 status_t handle_ibex_fi_otp_data_read(ujson_t *uj) {
2629  TRY(init_ref_otp_data());
2630  TRY(read_otp_partitions(uj));
2631  return OK_STATUS();
2632 }
2633 
2634 status_t handle_ibex_fi_otp_read_lock(ujson_t *uj) {
2635  TRY(init_ref_otp_data());
2639 
2640  TRY(read_otp_partitions(uj));
2641 
2642  return OK_STATUS();
2643 }
2644 
2645 status_t handle_ibex_fi_otp_write_lock(ujson_t *uj) {
2646  // Clear registered alerts in alert handler.
2647  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2648  // Clear the AST recoverable alerts.
2649  pentest_clear_sensor_recov_alerts();
2650 
2651  uint64_t faulty_token[kSecret0TestUnlockTokenSizeIn64BitWords];
2652  for (size_t i = 0; i < kSecret0TestUnlockTokenSizeIn64BitWords; i++) {
2653  faulty_token[i] = 0xdeadbeef;
2654  }
2655  pentest_set_trigger_high();
2656  asm volatile(NOP10);
2657  TRY(otp_ctrl_testutils_dai_write64(
2658  &otp, kDifOtpCtrlPartitionSecret0, kSecret0TestUnlockTokenOffset,
2659  faulty_token, kSecret0TestUnlockTokenSizeIn64BitWords));
2660  asm volatile(NOP10);
2661  pentest_set_trigger_low();
2662 
2663  // Get registered alerts from alert handler.
2664  reg_alerts = pentest_get_triggered_alerts();
2665  // Get fatal and recoverable AST alerts from sensor controller.
2666  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2667 
2668  // Read ERR_STATUS register.
2669  dif_rv_core_ibex_error_status_t codes;
2670  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2671 
2672  // Send res & ERR_STATUS to host.
2673  ibex_fi_test_result_t uj_output;
2674  uj_output.result =
2675  0; // Writing to the locked OTP partition crashes the chip.
2676  uj_output.err_status = codes;
2677  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2678  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2679  sizeof(sensor_alerts.alerts));
2680  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
2681 
2682  return OK_STATUS();
2683 }
2684 
2685 status_t handle_ibex_fi(ujson_t *uj) {
2686  ibex_fi_subcommand_t cmd;
2687  TRY(ujson_deserialize_ibex_fi_subcommand_t(uj, &cmd));
2688  switch (cmd) {
2689  case kIbexFiSubcommandAddressTranslation:
2690  return handle_ibex_fi_address_translation(uj);
2691  case kIbexFiSubcommandAddressTranslationCfg:
2692  return handle_ibex_fi_address_translation_config(uj);
2693  case kIbexFiSubcommandCharCondBranchBeq:
2694  return handle_ibex_fi_char_conditional_branch_beq(uj);
2695  case kIbexFiSubcommandCharCondBranchBge:
2696  return handle_ibex_fi_char_conditional_branch_bge(uj);
2697  case kIbexFiSubcommandCharCondBranchBgeu:
2698  return handle_ibex_fi_char_conditional_branch_bgeu(uj);
2699  case kIbexFiSubcommandCharCondBranchBlt:
2700  return handle_ibex_fi_char_conditional_branch_blt(uj);
2701  case kIbexFiSubcommandCharCondBranchBltu:
2702  return handle_ibex_fi_char_conditional_branch_bltu(uj);
2703  case kIbexFiSubcommandCharCondBranchBne:
2704  return handle_ibex_fi_char_conditional_branch_bne(uj);
2705  case kIbexFiSubcommandCharCsrRead:
2706  return handle_ibex_fi_char_csr_read(uj);
2707  case kIbexFiSubcommandCharCsrWrite:
2708  return handle_ibex_fi_char_csr_write(uj);
2709  case kIbexFiSubcommandCharFlashRead:
2710  return handle_ibex_fi_char_flash_read(uj);
2711  case kIbexFiSubcommandCharFlashWrite:
2712  return handle_ibex_fi_char_flash_write(uj);
2713  case kIbexFiSubcommandCharHardenedCheckComplementBranch:
2714  return handle_ibex_fi_char_hardened_check_eq_complement_branch(uj);
2715  case kIbexFiSubcommandCharHardenedCheckUnimp:
2716  return handle_ibex_fi_char_hardened_check_eq_unimp(uj);
2717  case kIbexFiSubcommandCharHardenedCheck2Unimps:
2718  return handle_ibex_fi_char_hardened_check_eq_2_unimps(uj);
2719  case kIbexFiSubcommandCharHardenedCheck3Unimps:
2720  return handle_ibex_fi_char_hardened_check_eq_3_unimps(uj);
2721  case kIbexFiSubcommandCharHardenedCheck4Unimps:
2722  return handle_ibex_fi_char_hardened_check_eq_4_unimps(uj);
2723  case kIbexFiSubcommandCharHardenedCheck5Unimps:
2724  return handle_ibex_fi_char_hardened_check_eq_5_unimps(uj);
2725  case kIbexFiSubcommandCharMemOpLoop:
2726  return handle_ibex_fi_char_mem_op_loop(uj);
2727  case kIbexFiSubcommandCharRegisterFile:
2728  return handle_ibex_fi_char_register_file(uj);
2729  case kIbexFiSubcommandCharRegisterFileRead:
2730  return handle_ibex_fi_char_register_file_read(uj);
2731  case kIbexFiSubcommandCharRegOpLoop:
2732  return handle_ibex_fi_char_reg_op_loop(uj);
2733  case kIbexFiSubcommandCharSramRead:
2734  return handle_ibex_fi_char_sram_read(uj);
2735  case kIbexFiSubcommandCharSramStatic:
2736  return handle_ibex_fi_char_sram_static(uj);
2737  case kIbexFiSubcommandCharSramWrite:
2738  return handle_ibex_fi_char_sram_write(uj);
2739  case kIbexFiSubcommandCharSramWriteRead:
2740  return handle_ibex_fi_char_sram_write_read(uj);
2741  case kIbexFiSubcommandCharSramWriteStaticUnrolled:
2742  return handle_ibex_fi_char_sram_write_static_unrolled(uj);
2743  case kIbexFiSubcommandCharUncondBranch:
2744  return handle_ibex_fi_char_unconditional_branch(uj);
2745  case kIbexFiSubcommandCharUncondBranchNop:
2746  return handle_ibex_fi_char_unconditional_branch_nop(uj);
2747  case kIbexFiSubcommandCharUnrolledMemOpLoop:
2748  return handle_ibex_fi_char_unrolled_mem_op_loop(uj);
2749  case kIbexFiSubcommandCharUnrolledRegOpLoop:
2750  return handle_ibex_fi_char_unrolled_reg_op_loop(uj);
2751  case kIbexFiSubcommandCharUnrolledRegOpLoopChain:
2752  return handle_ibex_fi_char_unrolled_reg_op_loop_chain(uj);
2753  case kIbexFiSubcommandInit:
2754  return handle_ibex_fi_init(uj);
2755  case kIbexFiSubcommandOtpDataRead:
2756  return handle_ibex_fi_otp_data_read(uj);
2757  case kIbexFiSubcommandOtpReadLock:
2758  return handle_ibex_fi_otp_read_lock(uj);
2759  case kIbexFiSubcommandOtpWriteLock:
2760  return handle_ibex_fi_otp_write_lock(uj);
2761  default:
2762  LOG_ERROR("Unrecognized IBEX FI subcommand: %d", cmd);
2763  return INVALID_ARGUMENT();
2764  }
2765  return OK_STATUS();
2766 }