Software APIs
dif_entropy_src.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
6
7#include <stddef.h>
8
12#include "sw/device/lib/base/multibits.h"
14
15#include "hw/top/entropy_src_regs.h" // Generated.
16
17dif_result_t dif_entropy_src_stop(const dif_entropy_src_t *entropy_src) {
18 if (entropy_src == NULL) {
19 return kDifBadArg;
20 }
21
22 mmio_region_write32(entropy_src->base_addr,
23 ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET,
24 ENTROPY_SRC_MODULE_ENABLE_REG_RESVAL);
25
26 // once disabled, the entropy_src regwen is released
27 if (!mmio_region_read32(entropy_src->base_addr,
28 ENTROPY_SRC_REGWEN_REG_OFFSET)) {
29 return kDifLocked;
30 }
31
32 // set back to default value
33 mmio_region_write32(entropy_src->base_addr,
34 ENTROPY_SRC_ENTROPY_CONTROL_REG_OFFSET,
35 ENTROPY_SRC_ENTROPY_CONTROL_REG_RESVAL);
36
37 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_CONF_REG_OFFSET,
38 ENTROPY_SRC_CONF_REG_RESVAL);
39
40 mmio_region_write32(entropy_src->base_addr,
41 ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_OFFSET,
42 ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_RESVAL);
43
44 mmio_region_write32(entropy_src->base_addr,
45 ENTROPY_SRC_ALERT_THRESHOLD_REG_OFFSET,
46 ENTROPY_SRC_ALERT_THRESHOLD_REG_RESVAL);
47
48 return kDifOk;
49}
50
51dif_result_t dif_entropy_src_configure(const dif_entropy_src_t *entropy_src,
53 dif_toggle_t enabled) {
54 if (entropy_src == NULL ||
56 !dif_is_valid_toggle(enabled) || config.health_test_window_size == 0) {
57 return kDifBadArg;
58 }
59
60 if (!mmio_region_read32(entropy_src->base_addr,
61 ENTROPY_SRC_REGWEN_REG_OFFSET)) {
62 return kDifLocked;
63 }
64
65 // ENTROPY_CONTROL register configuration.
66 uint32_t entropy_ctrl_reg = bitfield_field32_write(
67 0, ENTROPY_SRC_ENTROPY_CONTROL_ES_ROUTE_FIELD,
68 config.route_to_firmware ? kMultiBitBool4True : kMultiBitBool4False);
69 entropy_ctrl_reg = bitfield_field32_write(
70 entropy_ctrl_reg, ENTROPY_SRC_ENTROPY_CONTROL_ES_TYPE_FIELD,
71 config.bypass_conditioner ? kMultiBitBool4True : kMultiBitBool4False);
72 mmio_region_write32(entropy_src->base_addr,
73 ENTROPY_SRC_ENTROPY_CONTROL_REG_OFFSET, entropy_ctrl_reg);
74
75 // CONF register configuration.
76
77 // Configure FIPS enable.
78 // TODO: Add additional DIF to toggle this bit independently.
79 uint32_t entropy_conf_reg = bitfield_field32_write(
80 0, ENTROPY_SRC_CONF_FIPS_ENABLE_FIELD,
81 config.fips_enable ? kMultiBitBool4True : kMultiBitBool4False);
82
83 // Configure FIPS flag.
84 entropy_conf_reg = bitfield_field32_write(
85 entropy_conf_reg, ENTROPY_SRC_CONF_FIPS_FLAG_FIELD,
86 config.fips_flag ? kMultiBitBool4True : kMultiBitBool4False);
87
88 // Configure RNG FIPS.
89 entropy_conf_reg = bitfield_field32_write(
90 entropy_conf_reg, ENTROPY_SRC_CONF_RNG_FIPS_FIELD,
91 config.rng_fips ? kMultiBitBool4True : kMultiBitBool4False);
92
93 // Configure entropy data register enable (enables firmware to read entropy).
94 entropy_conf_reg = bitfield_field32_write(
95 entropy_conf_reg, ENTROPY_SRC_CONF_ENTROPY_DATA_REG_ENABLE_FIELD,
96 config.route_to_firmware ? kMultiBitBool4True : kMultiBitBool4False);
97
98 // Configure the health test threshold scope.
99 entropy_conf_reg = bitfield_field32_write(
100 entropy_conf_reg, ENTROPY_SRC_CONF_THRESHOLD_SCOPE_FIELD,
101 config.health_test_threshold_scope ? kMultiBitBool4True
102 : kMultiBitBool4False);
103
104 // Configure single RNG bit mode.
105 uint32_t rng_bit_en =
107 ? kMultiBitBool4False
108 : kMultiBitBool4True;
109 entropy_conf_reg = bitfield_field32_write(
110 entropy_conf_reg, ENTROPY_SRC_CONF_RNG_BIT_ENABLE_FIELD, rng_bit_en);
111 uint32_t rng_bit_sel =
112 (rng_bit_en == kMultiBitBool4True) ? config.single_bit_mode : 0;
113 entropy_conf_reg = bitfield_field32_write(
114 entropy_conf_reg, ENTROPY_SRC_CONF_RNG_BIT_SEL_FIELD, rng_bit_sel);
115
116 uint32_t sw_rd_en =
117 config.route_to_firmware ? kMultiBitBool4True : kMultiBitBool4False;
118 entropy_conf_reg = bitfield_field32_write(
119 entropy_conf_reg, ENTROPY_SRC_CONF_ENTROPY_DATA_REG_ENABLE_FIELD,
120 sw_rd_en);
121
122 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_CONF_REG_OFFSET,
123 entropy_conf_reg);
124
125 // Configure health test window.
126 // Note: the only supported bypass window size is the default value of 0x60 at
127 // the moment, hence even if `bypass_conditioner` is set, we should not change
128 // the bypass window size.
129 uint32_t health_test_window_sizes =
130 bitfield_field32_write(ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_RESVAL,
131 ENTROPY_SRC_HEALTH_TEST_WINDOWS_FIPS_WINDOW_FIELD,
133 mmio_region_write32(entropy_src->base_addr,
134 ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_OFFSET,
135 health_test_window_sizes);
136
137 // Alert Threshold register configuration.
138 uint32_t alert_threshold = bitfield_field32_write(
139 0, ENTROPY_SRC_ALERT_THRESHOLD_ALERT_THRESHOLD_FIELD,
140 config.alert_threshold);
141 alert_threshold = bitfield_field32_write(
142 alert_threshold, ENTROPY_SRC_ALERT_THRESHOLD_ALERT_THRESHOLD_INV_FIELD,
143 ~(uint32_t)config.alert_threshold);
144 mmio_region_write32(entropy_src->base_addr,
145 ENTROPY_SRC_ALERT_THRESHOLD_REG_OFFSET, alert_threshold);
146
147 // MODULE_ENABLE register configuration.
148 mmio_region_write32(entropy_src->base_addr,
149 ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET,
150 dif_toggle_to_multi_bit_bool4(enabled));
151
152 return kDifOk;
153}
154
155dif_result_t dif_entropy_src_fw_override_configure(
156 const dif_entropy_src_t *entropy_src,
158 if (entropy_src == NULL ||
159 config.buffer_threshold >
160 ENTROPY_SRC_OBSERVE_FIFO_THRESH_OBSERVE_FIFO_THRESH_MASK ||
161 config.buffer_threshold == 0 || !dif_is_valid_toggle(enabled)) {
162 return kDifBadArg;
163 }
164
165 if (!mmio_region_read32(entropy_src->base_addr,
166 ENTROPY_SRC_REGWEN_REG_OFFSET)) {
167 return kDifLocked;
168 }
169
170 mmio_region_write32(entropy_src->base_addr,
171 ENTROPY_SRC_OBSERVE_FIFO_THRESH_REG_OFFSET,
172 config.buffer_threshold);
173
174 uint32_t reg =
175 bitfield_field32_write(0, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD,
176 dif_toggle_to_multi_bit_bool4(enabled));
177 reg = bitfield_field32_write(
178 reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_ENTROPY_INSERT_FIELD,
179 config.entropy_insert_enable ? kMultiBitBool4True : kMultiBitBool4False);
180 mmio_region_write32(entropy_src->base_addr,
181 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET, reg);
182
183 return kDifOk;
184}
185
186dif_result_t dif_entropy_src_fw_override_sha3_start_insert(
187 const dif_entropy_src_t *entropy_src, dif_toggle_t enabled) {
188 if (entropy_src == NULL) {
189 return kDifBadArg;
190 }
191
192 uint32_t reg = bitfield_field32_write(
193 0, ENTROPY_SRC_FW_OV_SHA3_START_FW_OV_INSERT_START_FIELD,
194 dif_toggle_to_multi_bit_bool4(enabled));
195 mmio_region_write32(entropy_src->base_addr,
196 ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET, reg);
197
198 return kDifOk;
199}
200
201dif_result_t dif_entropy_src_health_test_configure(
202 const dif_entropy_src_t *entropy_src,
204 if (entropy_src == NULL) {
205 return kDifBadArg;
206 }
207
208 if (!mmio_region_read32(entropy_src->base_addr,
209 ENTROPY_SRC_REGWEN_REG_OFFSET)) {
210 return kDifLocked;
211 }
212
213 ptrdiff_t high_threshold_reg_offset = -1;
214 ptrdiff_t low_threshold_reg_offset = -1;
215 switch (config.test_type) {
217 high_threshold_reg_offset = ENTROPY_SRC_REPCNT_THRESHOLD_REG_OFFSET;
218 // Ensure low threshold is zero. There is no low threshold for this test.
219 if (config.low_threshold) {
220 return kDifBadArg;
221 }
222 break;
224 high_threshold_reg_offset = ENTROPY_SRC_REPCNTS_THRESHOLD_REG_OFFSET;
225 // Ensure low threshold is zero. There is no low threshold for this test.
226 if (config.low_threshold) {
227 return kDifBadArg;
228 }
229 break;
231 high_threshold_reg_offset = ENTROPY_SRC_ADAPTP_HI_THRESHOLD_REG_OFFSET;
232 low_threshold_reg_offset = ENTROPY_SRC_ADAPTP_LO_THRESHOLD_REG_OFFSET;
233 break;
235 high_threshold_reg_offset = ENTROPY_SRC_ADAPTPS_THRESHOLD_REG_OFFSET;
236 // Ensure low threshold is zero. There is no low threshold for this test.
237 if (config.low_threshold) {
238 return kDifBadArg;
239 }
240 break;
242 high_threshold_reg_offset = ENTROPY_SRC_BUCKET_THRESHOLD_REG_OFFSET;
243 // Ensure low threshold is zero. There is no low threshold for this test.
244 if (config.low_threshold) {
245 return kDifBadArg;
246 }
247 break;
249 high_threshold_reg_offset = ENTROPY_SRC_MARKOV_HI_THRESHOLD_REG_OFFSET;
250 low_threshold_reg_offset = ENTROPY_SRC_MARKOV_LO_THRESHOLD_REG_OFFSET;
251 break;
253 high_threshold_reg_offset = ENTROPY_SRC_EXTHT_HI_THRESHOLD_REG_OFFSET;
254 low_threshold_reg_offset = ENTROPY_SRC_EXTHT_LO_THRESHOLD_REG_OFFSET;
255 break;
256 default:
257 return kDifBadArg;
258 }
259
260 mmio_region_write32(entropy_src->base_addr, high_threshold_reg_offset,
261 config.high_threshold);
262 if (low_threshold_reg_offset != -1) {
263 mmio_region_write32(entropy_src->base_addr, low_threshold_reg_offset,
264 config.low_threshold);
265 }
266
267 return kDifOk;
268}
269
270dif_result_t dif_entropy_src_health_test_threshold_oneway_enable(
271 const dif_entropy_src_t *entropy_src) {
272 if (entropy_src == NULL) {
273 return kDifBadArg;
274 }
275
276 mmio_region_write32(entropy_src->base_addr,
277 ENTROPY_SRC_THRESHOLD_ONEWAY_REG_OFFSET,
278 kMultiBitBool4True);
279
280 return kDifOk;
281}
282
283dif_result_t dif_entropy_src_watermark_configure(
284 const dif_entropy_src_t *entropy_src,
286 if (entropy_src == NULL) {
287 return kDifBadArg;
288 }
289
290 if (!mmio_region_read32(entropy_src->base_addr,
291 ENTROPY_SRC_REGWEN_REG_OFFSET)) {
292 return kDifLocked;
293 }
294
295 // Write the specified value.
296 mmio_region_write32(entropy_src->base_addr,
297 ENTROPY_SRC_HT_WATERMARK_NUM_REG_OFFSET, config);
298
299 // Read the value back. In case it doesn't match the previously written
300 // value, the specified value isn't supported.
301 uint32_t ht_watermark_num = mmio_region_read32(
302 entropy_src->base_addr, ENTROPY_SRC_HT_WATERMARK_NUM_REG_OFFSET);
303 if ((uint32_t)config != ht_watermark_num) {
304 return kDifError;
305 }
306
307 return kDifOk;
308}
309
310dif_result_t dif_entropy_src_set_enabled(const dif_entropy_src_t *entropy_src,
311 dif_toggle_t enabled) {
312 if (entropy_src == NULL || !dif_is_valid_toggle(enabled)) {
313 return kDifBadArg;
314 }
315
316 if (!mmio_region_read32(entropy_src->base_addr,
317 ENTROPY_SRC_ME_REGWEN_REG_OFFSET)) {
318 return kDifLocked;
319 }
320
321 mmio_region_write32(entropy_src->base_addr,
322 ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET,
323 dif_toggle_to_multi_bit_bool4(enabled));
324
325 return kDifOk;
326}
327
328dif_result_t dif_entropy_src_lock(const dif_entropy_src_t *entropy_src) {
329 if (entropy_src == NULL) {
330 return kDifBadArg;
331 }
332
333 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_ME_REGWEN_REG_OFFSET,
334 0);
335 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_SW_REGUPD_REG_OFFSET,
336 0);
337
338 return kDifOk;
339}
340
341dif_result_t dif_entropy_src_is_locked(const dif_entropy_src_t *entropy_src,
342 bool *is_locked) {
343 if (entropy_src == NULL || is_locked == NULL) {
344 return kDifBadArg;
345 }
346
347 uint32_t module_enable_regwen = mmio_region_read32(
348 entropy_src->base_addr, ENTROPY_SRC_ME_REGWEN_REG_OFFSET);
349 uint32_t sw_regupd = mmio_region_read32(entropy_src->base_addr,
350 ENTROPY_SRC_SW_REGUPD_REG_OFFSET);
351 if (module_enable_regwen == sw_regupd) {
352 *is_locked = sw_regupd == 0;
353 } else {
354 // Since we actuate these together, either both should be 0 (locked), or
355 // both should be 1 (unlocked). If only one is locked, then we have
356 // gotten into a bad state.
357 return kDifError;
358 }
359
360 return kDifOk;
361}
362
363dif_result_t dif_entropy_src_get_health_test_stats(
364 const dif_entropy_src_t *entropy_src,
366 if (entropy_src == NULL || stats == NULL) {
367 return kDifBadArg;
368 }
369
370 stats->watermark_num = (dif_entropy_src_watermark_num_t)mmio_region_read32(
371 entropy_src->base_addr, ENTROPY_SRC_HT_WATERMARK_NUM_REG_OFFSET);
372 stats->watermark = (uint16_t)mmio_region_read32(
373 entropy_src->base_addr, ENTROPY_SRC_HT_WATERMARK_REG_OFFSET);
374
375 ptrdiff_t high_fails_reg_offset = -1;
376 ptrdiff_t low_fails_reg_offset = -1;
377 for (uint32_t i = 0; i < kDifEntropySrcTestNumVariants; ++i) {
378 switch ((dif_entropy_src_test_t)i) {
380 high_fails_reg_offset = ENTROPY_SRC_REPCNT_TOTAL_FAILS_REG_OFFSET;
381 low_fails_reg_offset = -1;
382 break;
384 high_fails_reg_offset = ENTROPY_SRC_REPCNTS_TOTAL_FAILS_REG_OFFSET;
385 low_fails_reg_offset = -1;
386 break;
388 high_fails_reg_offset = ENTROPY_SRC_ADAPTP_HI_TOTAL_FAILS_REG_OFFSET;
389 low_fails_reg_offset = ENTROPY_SRC_ADAPTP_LO_TOTAL_FAILS_REG_OFFSET;
390 break;
392 high_fails_reg_offset = ENTROPY_SRC_ADAPTPS_TOTAL_FAILS_REG_OFFSET;
393 low_fails_reg_offset = -1;
394 break;
396 high_fails_reg_offset = ENTROPY_SRC_BUCKET_TOTAL_FAILS_REG_OFFSET;
397 low_fails_reg_offset = -1;
398 break;
400 high_fails_reg_offset = ENTROPY_SRC_MARKOV_HI_TOTAL_FAILS_REG_OFFSET;
401 low_fails_reg_offset = ENTROPY_SRC_MARKOV_LO_TOTAL_FAILS_REG_OFFSET;
402 break;
404 high_fails_reg_offset = ENTROPY_SRC_EXTHT_HI_TOTAL_FAILS_REG_OFFSET;
405 low_fails_reg_offset = ENTROPY_SRC_EXTHT_LO_TOTAL_FAILS_REG_OFFSET;
406 break;
407 default:
408 return kDifError;
409 }
410
411 stats->high_fails[i] =
412 mmio_region_read32(entropy_src->base_addr, high_fails_reg_offset);
413 stats->low_fails[i] =
414 low_fails_reg_offset == -1
415 ? 0
416 : mmio_region_read32(entropy_src->base_addr, low_fails_reg_offset);
417 }
418
419 return kDifOk;
420}
421
422dif_result_t dif_entropy_src_get_alert_fail_counts(
423 const dif_entropy_src_t *entropy_src,
425 if (entropy_src == NULL || counts == NULL) {
426 return kDifBadArg;
427 }
428
429 counts->total_fails = (uint16_t)mmio_region_read32(
430 entropy_src->base_addr, ENTROPY_SRC_ALERT_SUMMARY_FAIL_COUNTS_REG_OFFSET);
431
432 uint32_t alert_fail_counts = mmio_region_read32(
433 entropy_src->base_addr, ENTROPY_SRC_ALERT_FAIL_COUNTS_REG_OFFSET);
434 uint32_t extht_alert_fail_counts = mmio_region_read32(
435 entropy_src->base_addr, ENTROPY_SRC_EXTHT_FAIL_COUNTS_REG_OFFSET);
436
437 // Unpack high threshold failure counts.
439 (uint8_t)bitfield_field32_read(
440 alert_fail_counts,
441 ENTROPY_SRC_ALERT_FAIL_COUNTS_REPCNT_FAIL_COUNT_FIELD);
443 (uint8_t)bitfield_field32_read(
444 alert_fail_counts,
445 ENTROPY_SRC_ALERT_FAIL_COUNTS_REPCNTS_FAIL_COUNT_FIELD);
447 (uint8_t)bitfield_field32_read(
448 alert_fail_counts,
449 ENTROPY_SRC_ALERT_FAIL_COUNTS_ADAPTP_HI_FAIL_COUNT_FIELD);
451 (uint8_t)bitfield_field32_read(
452 alert_fail_counts,
453 ENTROPY_SRC_ALERT_FAIL_COUNTS_ADAPTPS_FAIL_COUNT_FIELD);
454 counts->high_fails[kDifEntropySrcTestBucket] = (uint8_t)bitfield_field32_read(
455 alert_fail_counts, ENTROPY_SRC_ALERT_FAIL_COUNTS_BUCKET_FAIL_COUNT_FIELD);
456 counts->high_fails[kDifEntropySrcTestMarkov] = (uint8_t)bitfield_field32_read(
457 alert_fail_counts,
458 ENTROPY_SRC_ALERT_FAIL_COUNTS_MARKOV_HI_FAIL_COUNT_FIELD);
460 (uint8_t)bitfield_field32_read(
461 extht_alert_fail_counts,
462 ENTROPY_SRC_EXTHT_FAIL_COUNTS_EXTHT_HI_FAIL_COUNT_FIELD);
463
464 // Unpack low threshold failure counts.
468 (uint8_t)bitfield_field32_read(
469 alert_fail_counts,
470 ENTROPY_SRC_ALERT_FAIL_COUNTS_ADAPTP_LO_FAIL_COUNT_FIELD);
473 counts->low_fails[kDifEntropySrcTestMarkov] = (uint8_t)bitfield_field32_read(
474 alert_fail_counts,
475 ENTROPY_SRC_ALERT_FAIL_COUNTS_MARKOV_LO_FAIL_COUNT_FIELD);
476 counts->low_fails[kDifEntropySrcTestMailbox] = (uint8_t)bitfield_field32_read(
477 extht_alert_fail_counts,
478 ENTROPY_SRC_EXTHT_FAIL_COUNTS_EXTHT_LO_FAIL_COUNT_FIELD);
479
480 return kDifOk;
481}
482
483static bool is_entropy_available(const dif_entropy_src_t *entropy_src) {
484 return mmio_region_get_bit32(entropy_src->base_addr,
485 ENTROPY_SRC_INTR_STATE_REG_OFFSET,
486 ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
487}
488
489dif_result_t dif_entropy_src_is_entropy_available(
490 const dif_entropy_src_t *entropy_src) {
491 if (entropy_src == NULL) {
492 return kDifBadArg;
493 }
494
495 return is_entropy_available(entropy_src) ? kDifOk : kDifUnavailable;
496}
497
498dif_result_t dif_entropy_src_non_blocking_read(
499 const dif_entropy_src_t *entropy_src, uint32_t *word) {
500 if (entropy_src == NULL || word == NULL) {
501 return kDifBadArg;
502 }
503
504 // Check if entropy is available.
505 if (!is_entropy_available(entropy_src)) {
506 return kDifUnavailable;
507 }
508
509 *word = mmio_region_read32(entropy_src->base_addr,
510 ENTROPY_SRC_ENTROPY_DATA_REG_OFFSET);
511
512 // Clear interrupt state after fetching read if there is still entropy
513 // available, the interrupt state will set again.
514 mmio_region_nonatomic_set_bit32(entropy_src->base_addr,
515 ENTROPY_SRC_INTR_STATE_REG_OFFSET,
516 ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
517
518 return kDifOk;
519}
520
521dif_result_t dif_entropy_src_observe_fifo_blocking_read(
522 const dif_entropy_src_t *entropy_src, uint32_t *buf, size_t len) {
523 if (entropy_src == NULL) {
524 return kDifBadArg;
525 }
526
527 // Check that the number of bytes to be read is less than or equal to the FIFO
528 // threshold that triggers an interrupt.
529 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
530 ENTROPY_SRC_OBSERVE_FIFO_THRESH_REG_OFFSET);
531 if (len > reg) {
532 return kDifBadArg;
533 }
534
535 // Check that we are in firmware override mode. We can only read from the
536 // observe FIFO if we are.
537 reg = mmio_region_read32(entropy_src->base_addr,
538 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
539 if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
540 kMultiBitBool4True) {
541 return kDifError;
542 }
543
544 // Block until there is enough data in the observe FIFO.
545 do {
546 reg = mmio_region_read32(entropy_src->base_addr,
547 ENTROPY_SRC_INTR_STATE_REG_OFFSET);
548 } while (!bitfield_bit32_read(
549 reg, ENTROPY_SRC_INTR_STATE_ES_OBSERVE_FIFO_READY_BIT));
550
551 // Read post-health test, pre-conditioned, entropy from the observe FIFO.
552 for (size_t i = 0; i < len; ++i) {
553 reg = mmio_region_read32(entropy_src->base_addr,
554 ENTROPY_SRC_FW_OV_RD_DATA_REG_OFFSET);
555 if (buf != NULL) {
556 buf[i] = reg;
557 }
558 }
559
560 // Clear the status bit.
561 reg = bitfield_bit32_write(
562 0, ENTROPY_SRC_INTR_STATE_ES_OBSERVE_FIFO_READY_BIT, true);
563 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_INTR_STATE_REG_OFFSET,
564 reg);
565
566 return kDifOk;
567}
568
569dif_result_t dif_entropy_src_observe_fifo_nonblocking_read(
570 const dif_entropy_src_t *entropy_src, uint32_t *buf, size_t *len) {
571 if (entropy_src == NULL || len == NULL) {
572 return kDifBadArg;
573 }
574
575 // Check that we are in firmware override mode. We can only read from the
576 // observe FIFO if we are.
577 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
578 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
579 if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
580 kMultiBitBool4True) {
581 return kDifError;
582 }
583
584 // Read until FIFO is empty or we have read `*len` words.
585 size_t read_count = 0;
586 while (read_count < *len &&
587 mmio_region_read32(entropy_src->base_addr,
588 ENTROPY_SRC_OBSERVE_FIFO_DEPTH_REG_OFFSET) > 0) {
589 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
590 ENTROPY_SRC_FW_OV_RD_DATA_REG_OFFSET);
591 if (buf != NULL) {
592 buf[read_count++] = reg;
593 }
594 }
595 // Update `*len`.
596 *len = read_count;
597
598 return kDifOk;
599}
600
601dif_result_t dif_entropy_src_fw_ov_data_write(
602 const dif_entropy_src_t *entropy_src, const uint32_t *buf, size_t len,
603 size_t *written) {
604 if (entropy_src == NULL || buf == NULL) {
605 return kDifBadArg;
606 }
607
608 // Check that we are in firmware override mode and that we can insert data
609 // into the entropy pipeline.
610 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
611 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
612 if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
613 kMultiBitBool4True ||
614 bitfield_field32_read(
615 reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_ENTROPY_INSERT_FIELD) !=
616 kMultiBitBool4True) {
617 return kDifError;
618 }
619
620 // Check if the FIFO is full before writing each word.
621 for (size_t i = 0; i < len; ++i) {
622 if (mmio_region_read32(entropy_src->base_addr,
623 ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET)) {
624 if (written) {
625 *written = i;
626 }
627 return kDifIpFifoFull;
628 }
629
630 mmio_region_write32(entropy_src->base_addr,
631 ENTROPY_SRC_FW_OV_WR_DATA_REG_OFFSET, buf[i]);
632 }
633
634 if (written) {
635 *written = len;
636 }
637 return kDifOk;
638}
639
640dif_result_t dif_entropy_src_conditioner_start(
641 const dif_entropy_src_t *entropy_src) {
642 if (entropy_src == NULL) {
643 return kDifBadArg;
644 }
645
646 // Check if SHA3 conditioner operation has already started.
647 uint32_t current_val = mmio_region_read32(
648 entropy_src->base_addr, ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET);
649 if (current_val == kMultiBitBool4True) {
650 return kDifUnavailable;
651 }
652
653 mmio_region_write32(entropy_src->base_addr,
654 ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET,
655 kMultiBitBool4True);
656
657 return kDifOk;
658}
659
660dif_result_t dif_entropy_src_conditioner_stop(
661 const dif_entropy_src_t *entropy_src) {
662 if (entropy_src == NULL) {
663 return kDifBadArg;
664 }
665
666 // Check the FW_OV_WR_FIFO_FULL register to determine in any data is
667 // stalling at the input of the SHA3 conditioner.
668 if (mmio_region_read32(entropy_src->base_addr,
669 ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET)) {
670 return kDifIpFifoFull;
671 }
672
673 mmio_region_write32(entropy_src->base_addr,
674 ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET,
675 kMultiBitBool4False);
676 return kDifOk;
677}
678
679dif_result_t dif_entropy_src_is_fifo_full(const dif_entropy_src_t *entropy_src,
680 bool *is_full) {
681 if (entropy_src == NULL || is_full == NULL) {
682 return kDifBadArg;
683 }
684
685 *is_full = mmio_region_read32(entropy_src->base_addr,
686 ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET);
687
688 return kDifOk;
689}
690
691dif_result_t dif_entropy_src_has_fifo_overflowed(
692 const dif_entropy_src_t *entropy_src, bool *has_overflowed) {
693 if (entropy_src == NULL || has_overflowed == NULL) {
694 return kDifBadArg;
695 }
696
697 *has_overflowed = mmio_region_read32(
698 entropy_src->base_addr, ENTROPY_SRC_FW_OV_RD_FIFO_OVERFLOW_REG_OFFSET);
699
700 return kDifOk;
701}
702
703dif_result_t dif_entropy_src_get_fifo_depth(
704 const dif_entropy_src_t *entropy_src, uint32_t *fifo_depth) {
705 if (entropy_src == NULL || fifo_depth == NULL) {
706 return kDifBadArg;
707 }
708
709 *fifo_depth = mmio_region_read32(entropy_src->base_addr,
710 ENTROPY_SRC_OBSERVE_FIFO_DEPTH_REG_OFFSET);
711
712 return kDifOk;
713}
714
715dif_result_t dif_entropy_src_get_debug_state(
716 const dif_entropy_src_t *entropy_src,
717 dif_entropy_src_debug_state_t *debug_state) {
718 if (entropy_src == NULL || debug_state == NULL) {
719 return kDifBadArg;
720 }
721
722 uint32_t debug_state_reg = mmio_region_read32(
723 entropy_src->base_addr, ENTROPY_SRC_DEBUG_STATUS_REG_OFFSET);
724 debug_state->entropy_fifo_depth = (uint8_t)bitfield_field32_read(
725 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_ENTROPY_FIFO_DEPTH_FIELD);
726 debug_state->sha3_fsm_state = bitfield_field32_read(
727 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_FSM_FIELD);
728 debug_state->sha3_block_processed = bitfield_bit32_read(
729 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_BLOCK_PR_BIT);
730 debug_state->sha3_squeezing = bitfield_bit32_read(
731 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_SQUEEZING_BIT);
732 debug_state->sha3_absorbed = bitfield_bit32_read(
733 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_ABSORBED_BIT);
734 debug_state->sha3_error = bitfield_bit32_read(
735 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_ERR_BIT);
736 debug_state->main_fsm_is_idle = bitfield_bit32_read(
737 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_MAIN_SM_IDLE_BIT);
738 debug_state->main_fsm_boot_done = bitfield_bit32_read(
739 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_MAIN_SM_BOOT_DONE_BIT);
740
741 return kDifOk;
742}
743
744dif_result_t dif_entropy_src_get_recoverable_alerts(
745 const dif_entropy_src_t *entropy_src, uint32_t *alerts) {
746 if (entropy_src == NULL || alerts == NULL) {
747 return kDifBadArg;
748 }
749
750 *alerts = mmio_region_read32(entropy_src->base_addr,
751 ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET);
752
753 return kDifOk;
754}
755
756dif_result_t dif_entropy_src_clear_recoverable_alerts(
757 const dif_entropy_src_t *entropy_src, uint32_t alerts) {
758 if (entropy_src == NULL || alerts > kDifEntropySrcAlertAllAlerts) {
759 return kDifBadArg;
760 }
761
762 uint32_t active_alerts = mmio_region_read32(
763 entropy_src->base_addr, ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET);
764 active_alerts &= ~alerts;
765 mmio_region_write32(entropy_src->base_addr,
766 ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET, active_alerts);
767
768 return kDifOk;
769}
770
771dif_result_t dif_entropy_src_get_errors(const dif_entropy_src_t *entropy_src,
772 uint32_t *errors) {
773 if (entropy_src == NULL || errors == NULL) {
774 return kDifBadArg;
775 }
776
777 uint32_t err_code_reg = mmio_region_read32(entropy_src->base_addr,
778 ENTROPY_SRC_ERR_CODE_REG_OFFSET);
779
780 *errors = 0;
781
782 // ESRNG FIFO errors.
783 if (bitfield_bit32_read(err_code_reg,
784 ENTROPY_SRC_ERR_CODE_SFIFO_ESRNG_ERR_BIT)) {
785 if (bitfield_bit32_read(err_code_reg,
786 ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
788 }
789 if (bitfield_bit32_read(err_code_reg,
790 ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
792 }
793 if (bitfield_bit32_read(err_code_reg,
794 ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
796 }
797 }
798
799 // Observe FIFO errors.
800 if (bitfield_bit32_read(err_code_reg,
801 ENTROPY_SRC_ERR_CODE_SFIFO_OBSERVE_ERR_BIT)) {
802 if (bitfield_bit32_read(err_code_reg,
803 ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
805 }
806 if (bitfield_bit32_read(err_code_reg,
807 ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
809 }
810 if (bitfield_bit32_read(err_code_reg,
811 ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
813 }
814 }
815
816 // ESFINAL FIFO errors.
817 if (bitfield_bit32_read(err_code_reg,
818 ENTROPY_SRC_ERR_CODE_SFIFO_ESFINAL_ERR_BIT)) {
819 if (bitfield_bit32_read(err_code_reg,
820 ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
822 }
823 if (bitfield_bit32_read(err_code_reg,
824 ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
826 }
827 if (bitfield_bit32_read(err_code_reg,
828 ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
830 }
831 }
832
833 // Remaining FSM/Counter errors.
834 if (bitfield_bit32_read(err_code_reg,
835 ENTROPY_SRC_ERR_CODE_ES_ACK_SM_ERR_BIT)) {
837 }
838 if (bitfield_bit32_read(err_code_reg,
839 ENTROPY_SRC_ERR_CODE_ES_MAIN_SM_ERR_BIT)) {
841 }
842 if (bitfield_bit32_read(err_code_reg, ENTROPY_SRC_ERR_CODE_ES_CNTR_ERR_BIT)) {
844 }
845
846 return kDifOk;
847}
848
849dif_result_t dif_entropy_src_error_force(const dif_entropy_src_t *entropy_src,
851 if (entropy_src == NULL) {
852 return kDifBadArg;
853 }
854
855 uint32_t err_code_reg = 0;
856
857 switch (error) {
861 err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_ESRNG_ERR_BIT;
862 break;
866 err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_OBSERVE_ERR_BIT;
867 break;
871 err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_ESFINAL_ERR_BIT;
872 break;
874 err_code_reg = ENTROPY_SRC_ERR_CODE_ES_ACK_SM_ERR_BIT;
875 break;
877 err_code_reg = ENTROPY_SRC_ERR_CODE_ES_MAIN_SM_ERR_BIT;
878 break;
880 err_code_reg = ENTROPY_SRC_ERR_CODE_ES_CNTR_ERR_BIT;
881 break;
882 default:
883 return kDifBadArg;
884 }
885
886 mmio_region_write32(entropy_src->base_addr,
887 ENTROPY_SRC_ERR_CODE_TEST_REG_OFFSET, err_code_reg);
888
889 return kDifOk;
890}
891
892dif_result_t dif_entropy_src_get_main_fsm_state(
893 const dif_entropy_src_t *entropy_src, dif_entropy_src_main_fsm_t *state) {
894 if (entropy_src == NULL || state == NULL) {
895 return kDifBadArg;
896 }
897
898 *state = mmio_region_read32(entropy_src->base_addr,
899 ENTROPY_SRC_MAIN_SM_STATE_REG_OFFSET);
900
901 return kDifOk;
902}