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 ~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_thresholds_reg_offset = -1;
214 ptrdiff_t low_thresholds_reg_offset = -1;
215 switch (config.test_type) {
217 high_thresholds_reg_offset = ENTROPY_SRC_REPCNT_THRESHOLDS_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_thresholds_reg_offset = ENTROPY_SRC_REPCNTS_THRESHOLDS_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_thresholds_reg_offset = ENTROPY_SRC_ADAPTP_HI_THRESHOLDS_REG_OFFSET;
232 low_thresholds_reg_offset = ENTROPY_SRC_ADAPTP_LO_THRESHOLDS_REG_OFFSET;
233 break;
235 high_thresholds_reg_offset = ENTROPY_SRC_BUCKET_THRESHOLDS_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_thresholds_reg_offset = ENTROPY_SRC_MARKOV_HI_THRESHOLDS_REG_OFFSET;
243 low_thresholds_reg_offset = ENTROPY_SRC_MARKOV_LO_THRESHOLDS_REG_OFFSET;
244 break;
246 high_thresholds_reg_offset = ENTROPY_SRC_EXTHT_HI_THRESHOLDS_REG_OFFSET;
247 low_thresholds_reg_offset = ENTROPY_SRC_EXTHT_LO_THRESHOLDS_REG_OFFSET;
248 break;
249 default:
250 return kDifBadArg;
251 }
252
253 mmio_region_write32(entropy_src->base_addr, high_thresholds_reg_offset,
254 config.high_threshold);
255 if (low_thresholds_reg_offset != -1) {
256 mmio_region_write32(entropy_src->base_addr, low_thresholds_reg_offset,
257 config.low_threshold);
258 }
259
260 return kDifOk;
261}
262
263dif_result_t dif_entropy_src_watermark_configure(
264 const dif_entropy_src_t *entropy_src,
266 if (entropy_src == NULL) {
267 return kDifBadArg;
268 }
269
270 if (!mmio_region_read32(entropy_src->base_addr,
271 ENTROPY_SRC_REGWEN_REG_OFFSET)) {
272 return kDifLocked;
273 }
274
275 // Write the specified value.
276 mmio_region_write32(entropy_src->base_addr,
277 ENTROPY_SRC_HT_WATERMARK_NUM_REG_OFFSET, config);
278
279 // Read the value back. In case it doesn't match the previously written
280 // value, the specified value isn't supported.
281 uint32_t ht_watermark_num = mmio_region_read32(
282 entropy_src->base_addr, ENTROPY_SRC_HT_WATERMARK_NUM_REG_OFFSET);
283 if ((uint32_t)config != ht_watermark_num) {
284 return kDifError;
285 }
286
287 return kDifOk;
288}
289
290dif_result_t dif_entropy_src_set_enabled(const dif_entropy_src_t *entropy_src,
291 dif_toggle_t enabled) {
292 if (entropy_src == NULL || !dif_is_valid_toggle(enabled)) {
293 return kDifBadArg;
294 }
295
296 if (!mmio_region_read32(entropy_src->base_addr,
297 ENTROPY_SRC_ME_REGWEN_REG_OFFSET)) {
298 return kDifLocked;
299 }
300
301 mmio_region_write32(entropy_src->base_addr,
302 ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET,
303 dif_toggle_to_multi_bit_bool4(enabled));
304
305 return kDifOk;
306}
307
308dif_result_t dif_entropy_src_lock(const dif_entropy_src_t *entropy_src) {
309 if (entropy_src == NULL) {
310 return kDifBadArg;
311 }
312
313 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_ME_REGWEN_REG_OFFSET,
314 0);
315 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_SW_REGUPD_REG_OFFSET,
316 0);
317
318 return kDifOk;
319}
320
321dif_result_t dif_entropy_src_is_locked(const dif_entropy_src_t *entropy_src,
322 bool *is_locked) {
323 if (entropy_src == NULL || is_locked == NULL) {
324 return kDifBadArg;
325 }
326
327 uint32_t module_enable_regwen = mmio_region_read32(
328 entropy_src->base_addr, ENTROPY_SRC_ME_REGWEN_REG_OFFSET);
329 uint32_t sw_regupd = mmio_region_read32(entropy_src->base_addr,
330 ENTROPY_SRC_SW_REGUPD_REG_OFFSET);
331 if (module_enable_regwen == sw_regupd) {
332 *is_locked = sw_regupd == 0;
333 } else {
334 // Since we actuate these together, either both should be 0 (locked), or
335 // both should be 1 (unlocked). If only one is locked, then we have
336 // gotten into a bad state.
337 return kDifError;
338 }
339
340 return kDifOk;
341}
342
343dif_result_t dif_entropy_src_get_health_test_stats(
344 const dif_entropy_src_t *entropy_src,
346 if (entropy_src == NULL || stats == NULL) {
347 return kDifBadArg;
348 }
349
350 stats->watermark_num = (dif_entropy_src_watermark_num_t)mmio_region_read32(
351 entropy_src->base_addr, ENTROPY_SRC_HT_WATERMARK_NUM_REG_OFFSET);
352 stats->watermark = (uint16_t)mmio_region_read32(
353 entropy_src->base_addr, ENTROPY_SRC_HT_WATERMARK_REG_OFFSET);
354
355 ptrdiff_t high_fails_reg_offset = -1;
356 ptrdiff_t low_fails_reg_offset = -1;
357 for (uint32_t i = 0; i < kDifEntropySrcTestNumVariants; ++i) {
358 switch ((dif_entropy_src_test_t)i) {
360 high_fails_reg_offset = ENTROPY_SRC_REPCNT_TOTAL_FAILS_REG_OFFSET;
361 low_fails_reg_offset = -1;
362 break;
364 high_fails_reg_offset = ENTROPY_SRC_REPCNTS_TOTAL_FAILS_REG_OFFSET;
365 low_fails_reg_offset = -1;
366 break;
368 high_fails_reg_offset = ENTROPY_SRC_ADAPTP_HI_TOTAL_FAILS_REG_OFFSET;
369 low_fails_reg_offset = ENTROPY_SRC_ADAPTP_LO_TOTAL_FAILS_REG_OFFSET;
370 break;
372 high_fails_reg_offset = ENTROPY_SRC_BUCKET_TOTAL_FAILS_REG_OFFSET;
373 low_fails_reg_offset = -1;
374 break;
376 high_fails_reg_offset = ENTROPY_SRC_MARKOV_HI_TOTAL_FAILS_REG_OFFSET;
377 low_fails_reg_offset = ENTROPY_SRC_MARKOV_LO_TOTAL_FAILS_REG_OFFSET;
378 break;
380 high_fails_reg_offset = ENTROPY_SRC_EXTHT_HI_TOTAL_FAILS_REG_OFFSET;
381 low_fails_reg_offset = ENTROPY_SRC_EXTHT_LO_TOTAL_FAILS_REG_OFFSET;
382 break;
383 default:
384 return kDifError;
385 }
386
387 stats->high_fails[i] =
388 mmio_region_read32(entropy_src->base_addr, high_fails_reg_offset);
389 stats->low_fails[i] =
390 low_fails_reg_offset == -1
391 ? 0
392 : mmio_region_read32(entropy_src->base_addr, low_fails_reg_offset);
393 }
394
395 return kDifOk;
396}
397
398dif_result_t dif_entropy_src_get_alert_fail_counts(
399 const dif_entropy_src_t *entropy_src,
401 if (entropy_src == NULL || counts == NULL) {
402 return kDifBadArg;
403 }
404
405 counts->total_fails = (uint16_t)mmio_region_read32(
406 entropy_src->base_addr, ENTROPY_SRC_ALERT_SUMMARY_FAIL_COUNTS_REG_OFFSET);
407
408 uint32_t alert_fail_counts = mmio_region_read32(
409 entropy_src->base_addr, ENTROPY_SRC_ALERT_FAIL_COUNTS_REG_OFFSET);
410 uint32_t extht_alert_fail_counts = mmio_region_read32(
411 entropy_src->base_addr, ENTROPY_SRC_EXTHT_FAIL_COUNTS_REG_OFFSET);
412
413 // Unpack high threshold failure counts.
415 (uint8_t)bitfield_field32_read(
416 alert_fail_counts,
417 ENTROPY_SRC_ALERT_FAIL_COUNTS_REPCNT_FAIL_COUNT_FIELD);
419 (uint8_t)bitfield_field32_read(
420 alert_fail_counts,
421 ENTROPY_SRC_ALERT_FAIL_COUNTS_REPCNTS_FAIL_COUNT_FIELD);
423 (uint8_t)bitfield_field32_read(
424 alert_fail_counts,
425 ENTROPY_SRC_ALERT_FAIL_COUNTS_ADAPTP_HI_FAIL_COUNT_FIELD);
426 counts->high_fails[kDifEntropySrcTestBucket] = (uint8_t)bitfield_field32_read(
427 alert_fail_counts, ENTROPY_SRC_ALERT_FAIL_COUNTS_BUCKET_FAIL_COUNT_FIELD);
428 counts->high_fails[kDifEntropySrcTestMarkov] = (uint8_t)bitfield_field32_read(
429 alert_fail_counts,
430 ENTROPY_SRC_ALERT_FAIL_COUNTS_MARKOV_HI_FAIL_COUNT_FIELD);
432 (uint8_t)bitfield_field32_read(
433 extht_alert_fail_counts,
434 ENTROPY_SRC_EXTHT_FAIL_COUNTS_EXTHT_HI_FAIL_COUNT_FIELD);
435
436 // Unpack low threshold failure counts.
440 (uint8_t)bitfield_field32_read(
441 alert_fail_counts,
442 ENTROPY_SRC_ALERT_FAIL_COUNTS_ADAPTP_LO_FAIL_COUNT_FIELD);
444 counts->low_fails[kDifEntropySrcTestMarkov] = (uint8_t)bitfield_field32_read(
445 alert_fail_counts,
446 ENTROPY_SRC_ALERT_FAIL_COUNTS_MARKOV_LO_FAIL_COUNT_FIELD);
447 counts->low_fails[kDifEntropySrcTestMailbox] = (uint8_t)bitfield_field32_read(
448 extht_alert_fail_counts,
449 ENTROPY_SRC_EXTHT_FAIL_COUNTS_EXTHT_LO_FAIL_COUNT_FIELD);
450
451 return kDifOk;
452}
453
454static bool is_entropy_available(const dif_entropy_src_t *entropy_src) {
455 return mmio_region_get_bit32(entropy_src->base_addr,
456 ENTROPY_SRC_INTR_STATE_REG_OFFSET,
457 ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
458}
459
460dif_result_t dif_entropy_src_is_entropy_available(
461 const dif_entropy_src_t *entropy_src) {
462 if (entropy_src == NULL) {
463 return kDifBadArg;
464 }
465
466 return is_entropy_available(entropy_src) ? kDifOk : kDifUnavailable;
467}
468
469dif_result_t dif_entropy_src_non_blocking_read(
470 const dif_entropy_src_t *entropy_src, uint32_t *word) {
471 if (entropy_src == NULL || word == NULL) {
472 return kDifBadArg;
473 }
474
475 // Check if entropy is available.
476 if (!is_entropy_available(entropy_src)) {
477 return kDifUnavailable;
478 }
479
480 *word = mmio_region_read32(entropy_src->base_addr,
481 ENTROPY_SRC_ENTROPY_DATA_REG_OFFSET);
482
483 // Clear interrupt state after fetching read if there is still entropy
484 // available, the interrupt state will set again.
485 mmio_region_nonatomic_set_bit32(entropy_src->base_addr,
486 ENTROPY_SRC_INTR_STATE_REG_OFFSET,
487 ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
488
489 return kDifOk;
490}
491
492dif_result_t dif_entropy_src_observe_fifo_blocking_read(
493 const dif_entropy_src_t *entropy_src, uint32_t *buf, size_t len) {
494 if (entropy_src == NULL) {
495 return kDifBadArg;
496 }
497
498 // Check that the number of bytes to be read is less than or equal to the FIFO
499 // threshold that triggers an interrupt.
500 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
501 ENTROPY_SRC_OBSERVE_FIFO_THRESH_REG_OFFSET);
502 if (len > reg) {
503 return kDifBadArg;
504 }
505
506 // Check that we are in firmware override mode. We can only read from the
507 // observe FIFO if we are.
508 reg = mmio_region_read32(entropy_src->base_addr,
509 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
510 if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
511 kMultiBitBool4True) {
512 return kDifError;
513 }
514
515 // Block until there is enough data in the observe FIFO.
516 do {
517 reg = mmio_region_read32(entropy_src->base_addr,
518 ENTROPY_SRC_INTR_STATE_REG_OFFSET);
519 } while (!bitfield_bit32_read(
520 reg, ENTROPY_SRC_INTR_STATE_ES_OBSERVE_FIFO_READY_BIT));
521
522 // Read post-health test, pre-conditioned, entropy from the observe FIFO.
523 for (size_t i = 0; i < len; ++i) {
524 reg = mmio_region_read32(entropy_src->base_addr,
525 ENTROPY_SRC_FW_OV_RD_DATA_REG_OFFSET);
526 if (buf != NULL) {
527 buf[i] = reg;
528 }
529 }
530
531 // Clear the status bit.
532 reg = bitfield_bit32_write(
533 0, ENTROPY_SRC_INTR_STATE_ES_OBSERVE_FIFO_READY_BIT, true);
534 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_INTR_STATE_REG_OFFSET,
535 reg);
536
537 return kDifOk;
538}
539
540dif_result_t dif_entropy_src_observe_fifo_nonblocking_read(
541 const dif_entropy_src_t *entropy_src, uint32_t *buf, size_t *len) {
542 if (entropy_src == NULL || len == NULL) {
543 return kDifBadArg;
544 }
545
546 // Check that we are in firmware override mode. We can only read from the
547 // observe FIFO if we are.
548 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
549 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
550 if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
551 kMultiBitBool4True) {
552 return kDifError;
553 }
554
555 // Read until FIFO is empty or we have read `*len` words.
556 size_t read_count = 0;
557 while (read_count < *len &&
558 mmio_region_read32(entropy_src->base_addr,
559 ENTROPY_SRC_OBSERVE_FIFO_DEPTH_REG_OFFSET) > 0) {
560 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
561 ENTROPY_SRC_FW_OV_RD_DATA_REG_OFFSET);
562 if (buf != NULL) {
563 buf[read_count++] = reg;
564 }
565 }
566 // Update `*len`.
567 *len = read_count;
568
569 return kDifOk;
570}
571
572dif_result_t dif_entropy_src_fw_ov_data_write(
573 const dif_entropy_src_t *entropy_src, const uint32_t *buf, size_t len,
574 size_t *written) {
575 if (entropy_src == NULL || buf == NULL) {
576 return kDifBadArg;
577 }
578
579 // Check that we are in firmware override mode and that we can insert data
580 // into the entropy pipeline.
581 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
582 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
583 if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
584 kMultiBitBool4True ||
585 bitfield_field32_read(
586 reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_ENTROPY_INSERT_FIELD) !=
587 kMultiBitBool4True) {
588 return kDifError;
589 }
590
591 // Check if the FIFO is full before writing each word.
592 for (size_t i = 0; i < len; ++i) {
593 if (mmio_region_read32(entropy_src->base_addr,
594 ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET)) {
595 if (written) {
596 *written = i;
597 }
598 return kDifIpFifoFull;
599 }
600
601 mmio_region_write32(entropy_src->base_addr,
602 ENTROPY_SRC_FW_OV_WR_DATA_REG_OFFSET, buf[i]);
603 }
604
605 if (written) {
606 *written = len;
607 }
608 return kDifOk;
609}
610
611dif_result_t dif_entropy_src_conditioner_start(
612 const dif_entropy_src_t *entropy_src) {
613 if (entropy_src == NULL) {
614 return kDifBadArg;
615 }
616
617 // Check if SHA3 conditioner operation has already started.
618 uint32_t current_val = mmio_region_read32(
619 entropy_src->base_addr, ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET);
620 if (current_val == kMultiBitBool4True) {
621 return kDifUnavailable;
622 }
623
624 mmio_region_write32(entropy_src->base_addr,
625 ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET,
626 kMultiBitBool4True);
627
628 return kDifOk;
629}
630
631dif_result_t dif_entropy_src_conditioner_stop(
632 const dif_entropy_src_t *entropy_src) {
633 if (entropy_src == NULL) {
634 return kDifBadArg;
635 }
636
637 // Check the FW_OV_WR_FIFO_FULL register to determine in any data is
638 // stalling at the input of the SHA3 conditioner.
639 if (mmio_region_read32(entropy_src->base_addr,
640 ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET)) {
641 return kDifIpFifoFull;
642 }
643
644 mmio_region_write32(entropy_src->base_addr,
645 ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET,
646 kMultiBitBool4False);
647 return kDifOk;
648}
649
650dif_result_t dif_entropy_src_is_fifo_full(const dif_entropy_src_t *entropy_src,
651 bool *is_full) {
652 if (entropy_src == NULL || is_full == NULL) {
653 return kDifBadArg;
654 }
655
656 *is_full = mmio_region_read32(entropy_src->base_addr,
657 ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET);
658
659 return kDifOk;
660}
661
662dif_result_t dif_entropy_src_has_fifo_overflowed(
663 const dif_entropy_src_t *entropy_src, bool *has_overflowed) {
664 if (entropy_src == NULL || has_overflowed == NULL) {
665 return kDifBadArg;
666 }
667
668 *has_overflowed = mmio_region_read32(
669 entropy_src->base_addr, ENTROPY_SRC_FW_OV_RD_FIFO_OVERFLOW_REG_OFFSET);
670
671 return kDifOk;
672}
673
674dif_result_t dif_entropy_src_get_fifo_depth(
675 const dif_entropy_src_t *entropy_src, uint32_t *fifo_depth) {
676 if (entropy_src == NULL || fifo_depth == NULL) {
677 return kDifBadArg;
678 }
679
680 *fifo_depth = mmio_region_read32(entropy_src->base_addr,
681 ENTROPY_SRC_OBSERVE_FIFO_DEPTH_REG_OFFSET);
682
683 return kDifOk;
684}
685
686dif_result_t dif_entropy_src_get_debug_state(
687 const dif_entropy_src_t *entropy_src,
688 dif_entropy_src_debug_state_t *debug_state) {
689 if (entropy_src == NULL || debug_state == NULL) {
690 return kDifBadArg;
691 }
692
693 uint32_t debug_state_reg = mmio_region_read32(
694 entropy_src->base_addr, ENTROPY_SRC_DEBUG_STATUS_REG_OFFSET);
695 debug_state->entropy_fifo_depth = (uint8_t)bitfield_field32_read(
696 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_ENTROPY_FIFO_DEPTH_FIELD);
697 debug_state->sha3_fsm_state = bitfield_field32_read(
698 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_FSM_FIELD);
699 debug_state->sha3_block_processed = bitfield_bit32_read(
700 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_BLOCK_PR_BIT);
701 debug_state->sha3_squeezing = bitfield_bit32_read(
702 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_SQUEEZING_BIT);
703 debug_state->sha3_absorbed = bitfield_bit32_read(
704 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_ABSORBED_BIT);
705 debug_state->sha3_error = bitfield_bit32_read(
706 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_ERR_BIT);
707 debug_state->main_fsm_is_idle = bitfield_bit32_read(
708 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_MAIN_SM_IDLE_BIT);
709 debug_state->main_fsm_boot_done = bitfield_bit32_read(
710 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_MAIN_SM_BOOT_DONE_BIT);
711
712 return kDifOk;
713}
714
715dif_result_t dif_entropy_src_get_recoverable_alerts(
716 const dif_entropy_src_t *entropy_src, uint32_t *alerts) {
717 if (entropy_src == NULL || alerts == NULL) {
718 return kDifBadArg;
719 }
720
721 *alerts = mmio_region_read32(entropy_src->base_addr,
722 ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET);
723
724 return kDifOk;
725}
726
727dif_result_t dif_entropy_src_clear_recoverable_alerts(
728 const dif_entropy_src_t *entropy_src, uint32_t alerts) {
729 if (entropy_src == NULL || alerts > kDifEntropySrcAlertAllAlerts) {
730 return kDifBadArg;
731 }
732
733 uint32_t active_alerts = mmio_region_read32(
734 entropy_src->base_addr, ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET);
735 active_alerts &= ~alerts;
736 mmio_region_write32(entropy_src->base_addr,
737 ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET, active_alerts);
738
739 return kDifOk;
740}
741
742dif_result_t dif_entropy_src_get_errors(const dif_entropy_src_t *entropy_src,
743 uint32_t *errors) {
744 if (entropy_src == NULL || errors == NULL) {
745 return kDifBadArg;
746 }
747
748 uint32_t err_code_reg = mmio_region_read32(entropy_src->base_addr,
749 ENTROPY_SRC_ERR_CODE_REG_OFFSET);
750
751 *errors = 0;
752
753 // ESRNG FIFO errors.
754 if (bitfield_bit32_read(err_code_reg,
755 ENTROPY_SRC_ERR_CODE_SFIFO_ESRNG_ERR_BIT)) {
756 if (bitfield_bit32_read(err_code_reg,
757 ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
759 }
760 if (bitfield_bit32_read(err_code_reg,
761 ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
763 }
764 if (bitfield_bit32_read(err_code_reg,
765 ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
767 }
768 }
769
770 // Observe FIFO errors.
771 if (bitfield_bit32_read(err_code_reg,
772 ENTROPY_SRC_ERR_CODE_SFIFO_OBSERVE_ERR_BIT)) {
773 if (bitfield_bit32_read(err_code_reg,
774 ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
776 }
777 if (bitfield_bit32_read(err_code_reg,
778 ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
780 }
781 if (bitfield_bit32_read(err_code_reg,
782 ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
784 }
785 }
786
787 // ESFINAL FIFO errors.
788 if (bitfield_bit32_read(err_code_reg,
789 ENTROPY_SRC_ERR_CODE_SFIFO_ESFINAL_ERR_BIT)) {
790 if (bitfield_bit32_read(err_code_reg,
791 ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
793 }
794 if (bitfield_bit32_read(err_code_reg,
795 ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
797 }
798 if (bitfield_bit32_read(err_code_reg,
799 ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
801 }
802 }
803
804 // Remaining FSM/Counter errors.
805 if (bitfield_bit32_read(err_code_reg,
806 ENTROPY_SRC_ERR_CODE_ES_ACK_SM_ERR_BIT)) {
808 }
809 if (bitfield_bit32_read(err_code_reg,
810 ENTROPY_SRC_ERR_CODE_ES_MAIN_SM_ERR_BIT)) {
812 }
813 if (bitfield_bit32_read(err_code_reg, ENTROPY_SRC_ERR_CODE_ES_CNTR_ERR_BIT)) {
815 }
816
817 return kDifOk;
818}
819
820dif_result_t dif_entropy_src_error_force(const dif_entropy_src_t *entropy_src,
822 if (entropy_src == NULL) {
823 return kDifBadArg;
824 }
825
826 uint32_t err_code_reg = 0;
827
828 switch (error) {
832 err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_ESRNG_ERR_BIT;
833 break;
837 err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_OBSERVE_ERR_BIT;
838 break;
842 err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_ESFINAL_ERR_BIT;
843 break;
845 err_code_reg = ENTROPY_SRC_ERR_CODE_ES_ACK_SM_ERR_BIT;
846 break;
848 err_code_reg = ENTROPY_SRC_ERR_CODE_ES_MAIN_SM_ERR_BIT;
849 break;
851 err_code_reg = ENTROPY_SRC_ERR_CODE_ES_CNTR_ERR_BIT;
852 break;
853 default:
854 return kDifBadArg;
855 }
856
857 mmio_region_write32(entropy_src->base_addr,
858 ENTROPY_SRC_ERR_CODE_TEST_REG_OFFSET, err_code_reg);
859
860 return kDifOk;
861}
862
863dif_result_t dif_entropy_src_get_main_fsm_state(
864 const dif_entropy_src_t *entropy_src, dif_entropy_src_main_fsm_t *state) {
865 if (entropy_src == NULL || state == NULL) {
866 return kDifBadArg;
867 }
868
869 *state = mmio_region_read32(entropy_src->base_addr,
870 ENTROPY_SRC_MAIN_SM_STATE_REG_OFFSET);
871
872 return kDifOk;
873}