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 "entropy_src_regs.h" // Generated.
16 
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 
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,
132  config.health_test_window_size);
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,
151 
152  return kDifOk;
153 }
154 
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,
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 
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,
195  mmio_region_write32(entropy_src->base_addr,
196  ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET, reg);
197 
198  return kDifOk;
199 }
200 
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 
264  dif_toggle_t enabled) {
265  if (entropy_src == NULL || !dif_is_valid_toggle(enabled)) {
266  return kDifBadArg;
267  }
268 
269  if (!mmio_region_read32(entropy_src->base_addr,
270  ENTROPY_SRC_ME_REGWEN_REG_OFFSET)) {
271  return kDifLocked;
272  }
273 
274  mmio_region_write32(entropy_src->base_addr,
275  ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET,
277 
278  return kDifOk;
279 }
280 
282  if (entropy_src == NULL) {
283  return kDifBadArg;
284  }
285 
286  mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_ME_REGWEN_REG_OFFSET,
287  0);
288  mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_SW_REGUPD_REG_OFFSET,
289  0);
290 
291  return kDifOk;
292 }
293 
295  bool *is_locked) {
296  if (entropy_src == NULL || is_locked == NULL) {
297  return kDifBadArg;
298  }
299 
300  uint32_t module_enable_regwen = mmio_region_read32(
301  entropy_src->base_addr, ENTROPY_SRC_ME_REGWEN_REG_OFFSET);
302  uint32_t sw_regupd = mmio_region_read32(entropy_src->base_addr,
303  ENTROPY_SRC_SW_REGUPD_REG_OFFSET);
304  if (module_enable_regwen == sw_regupd) {
305  *is_locked = sw_regupd == 0;
306  } else {
307  // Since we actuate these together, either both should be 0 (locked), or
308  // both should be 1 (unlocked). If only one is locked, then we have
309  // gotten into a bad state.
310  return kDifError;
311  }
312 
313  return kDifOk;
314 }
315 
317  const dif_entropy_src_t *entropy_src,
319  if (entropy_src == NULL || stats == NULL) {
320  return kDifBadArg;
321  }
322 
323  ptrdiff_t high_watermarks_reg_offset = -1;
324  ptrdiff_t low_watermarks_reg_offset = -1;
325  ptrdiff_t high_fails_reg_offset = -1;
326  ptrdiff_t low_fails_reg_offset = -1;
327  for (uint32_t i = 0; i < kDifEntropySrcTestNumVariants; ++i) {
328  switch ((dif_entropy_src_test_t)i) {
330  high_watermarks_reg_offset =
331  ENTROPY_SRC_REPCNT_HI_WATERMARKS_REG_OFFSET;
332  low_watermarks_reg_offset = -1;
333  high_fails_reg_offset = ENTROPY_SRC_REPCNT_TOTAL_FAILS_REG_OFFSET;
334  low_fails_reg_offset = -1;
335  break;
337  high_watermarks_reg_offset =
338  ENTROPY_SRC_REPCNTS_HI_WATERMARKS_REG_OFFSET;
339  low_watermarks_reg_offset = -1;
340  high_fails_reg_offset = ENTROPY_SRC_REPCNTS_TOTAL_FAILS_REG_OFFSET;
341  low_fails_reg_offset = -1;
342  break;
344  high_watermarks_reg_offset =
345  ENTROPY_SRC_ADAPTP_HI_WATERMARKS_REG_OFFSET;
346  low_watermarks_reg_offset = ENTROPY_SRC_ADAPTP_LO_WATERMARKS_REG_OFFSET;
347  high_fails_reg_offset = ENTROPY_SRC_ADAPTP_HI_TOTAL_FAILS_REG_OFFSET;
348  low_fails_reg_offset = ENTROPY_SRC_ADAPTP_LO_TOTAL_FAILS_REG_OFFSET;
349  break;
351  high_watermarks_reg_offset =
352  ENTROPY_SRC_BUCKET_HI_WATERMARKS_REG_OFFSET;
353  low_watermarks_reg_offset = -1;
354  high_fails_reg_offset = ENTROPY_SRC_BUCKET_TOTAL_FAILS_REG_OFFSET;
355  low_fails_reg_offset = -1;
356  break;
358  high_watermarks_reg_offset =
359  ENTROPY_SRC_MARKOV_HI_WATERMARKS_REG_OFFSET;
360  low_watermarks_reg_offset = ENTROPY_SRC_MARKOV_LO_WATERMARKS_REG_OFFSET;
361  high_fails_reg_offset = ENTROPY_SRC_MARKOV_HI_TOTAL_FAILS_REG_OFFSET;
362  low_fails_reg_offset = ENTROPY_SRC_MARKOV_LO_TOTAL_FAILS_REG_OFFSET;
363  break;
365  high_watermarks_reg_offset = ENTROPY_SRC_EXTHT_HI_WATERMARKS_REG_OFFSET;
366  low_watermarks_reg_offset = ENTROPY_SRC_EXTHT_LO_WATERMARKS_REG_OFFSET;
367  high_fails_reg_offset = ENTROPY_SRC_EXTHT_HI_TOTAL_FAILS_REG_OFFSET;
368  low_fails_reg_offset = ENTROPY_SRC_EXTHT_LO_TOTAL_FAILS_REG_OFFSET;
369  break;
370  default:
371  return kDifError;
372  }
373 
374  stats->high_watermark[i] = (uint16_t)mmio_region_read32(
375  entropy_src->base_addr, high_watermarks_reg_offset);
376  stats->low_watermark[i] =
377  low_watermarks_reg_offset == -1
378  ? 0
379  : (uint16_t)mmio_region_read32(entropy_src->base_addr,
380  low_watermarks_reg_offset);
381 
382  stats->high_fails[i] =
383  mmio_region_read32(entropy_src->base_addr, high_fails_reg_offset);
384  stats->low_fails[i] =
385  low_fails_reg_offset == -1
386  ? 0
387  : mmio_region_read32(entropy_src->base_addr, low_fails_reg_offset);
388  }
389 
390  return kDifOk;
391 }
392 
394  const dif_entropy_src_t *entropy_src,
396  if (entropy_src == NULL || counts == NULL) {
397  return kDifBadArg;
398  }
399 
400  counts->total_fails = (uint16_t)mmio_region_read32(
401  entropy_src->base_addr, ENTROPY_SRC_ALERT_SUMMARY_FAIL_COUNTS_REG_OFFSET);
402 
403  uint32_t alert_fail_counts = mmio_region_read32(
404  entropy_src->base_addr, ENTROPY_SRC_ALERT_FAIL_COUNTS_REG_OFFSET);
405  uint32_t extht_alert_fail_counts = mmio_region_read32(
406  entropy_src->base_addr, ENTROPY_SRC_EXTHT_FAIL_COUNTS_REG_OFFSET);
407 
408  // Unpack high threshold failure counts.
410  (uint8_t)bitfield_field32_read(
411  alert_fail_counts,
412  ENTROPY_SRC_ALERT_FAIL_COUNTS_REPCNT_FAIL_COUNT_FIELD);
414  (uint8_t)bitfield_field32_read(
415  alert_fail_counts,
416  ENTROPY_SRC_ALERT_FAIL_COUNTS_REPCNTS_FAIL_COUNT_FIELD);
418  (uint8_t)bitfield_field32_read(
419  alert_fail_counts,
420  ENTROPY_SRC_ALERT_FAIL_COUNTS_ADAPTP_HI_FAIL_COUNT_FIELD);
422  alert_fail_counts, ENTROPY_SRC_ALERT_FAIL_COUNTS_BUCKET_FAIL_COUNT_FIELD);
424  alert_fail_counts,
425  ENTROPY_SRC_ALERT_FAIL_COUNTS_MARKOV_HI_FAIL_COUNT_FIELD);
427  (uint8_t)bitfield_field32_read(
428  extht_alert_fail_counts,
429  ENTROPY_SRC_EXTHT_FAIL_COUNTS_EXTHT_HI_FAIL_COUNT_FIELD);
430 
431  // Unpack low threshold failure counts.
435  (uint8_t)bitfield_field32_read(
436  alert_fail_counts,
437  ENTROPY_SRC_ALERT_FAIL_COUNTS_ADAPTP_LO_FAIL_COUNT_FIELD);
438  counts->low_fails[kDifEntropySrcTestBucket] = 0;
440  alert_fail_counts,
441  ENTROPY_SRC_ALERT_FAIL_COUNTS_MARKOV_LO_FAIL_COUNT_FIELD);
443  extht_alert_fail_counts,
444  ENTROPY_SRC_EXTHT_FAIL_COUNTS_EXTHT_LO_FAIL_COUNT_FIELD);
445 
446  return kDifOk;
447 }
448 
449 static bool is_entropy_available(const dif_entropy_src_t *entropy_src) {
450  return mmio_region_get_bit32(entropy_src->base_addr,
451  ENTROPY_SRC_INTR_STATE_REG_OFFSET,
452  ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
453 }
454 
456  const dif_entropy_src_t *entropy_src) {
457  if (entropy_src == NULL) {
458  return kDifBadArg;
459  }
460 
461  return is_entropy_available(entropy_src) ? kDifOk : kDifUnavailable;
462 }
463 
465  const dif_entropy_src_t *entropy_src, uint32_t *word) {
466  if (entropy_src == NULL || word == NULL) {
467  return kDifBadArg;
468  }
469 
470  // Check if entropy is available.
471  if (!is_entropy_available(entropy_src)) {
472  return kDifUnavailable;
473  }
474 
475  *word = mmio_region_read32(entropy_src->base_addr,
476  ENTROPY_SRC_ENTROPY_DATA_REG_OFFSET);
477 
478  // Clear interrupt state after fetching read if there is still entropy
479  // available, the interrupt state will set again.
481  ENTROPY_SRC_INTR_STATE_REG_OFFSET,
482  ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
483 
484  return kDifOk;
485 }
486 
488  const dif_entropy_src_t *entropy_src, uint32_t *buf, size_t len) {
489  if (entropy_src == NULL) {
490  return kDifBadArg;
491  }
492 
493  // Check that the number of bytes to be read is less than or equal to the FIFO
494  // threshold that triggers an interrupt.
495  uint32_t reg = mmio_region_read32(entropy_src->base_addr,
496  ENTROPY_SRC_OBSERVE_FIFO_THRESH_REG_OFFSET);
497  if (len > reg) {
498  return kDifBadArg;
499  }
500 
501  // Check that we are in firmware override mode. We can only read from the
502  // observe FIFO if we are.
503  reg = mmio_region_read32(entropy_src->base_addr,
504  ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
505  if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
506  kMultiBitBool4True) {
507  return kDifError;
508  }
509 
510  // Block until there is enough data in the observe FIFO.
511  do {
512  reg = mmio_region_read32(entropy_src->base_addr,
513  ENTROPY_SRC_INTR_STATE_REG_OFFSET);
514  } while (!bitfield_bit32_read(
515  reg, ENTROPY_SRC_INTR_STATE_ES_OBSERVE_FIFO_READY_BIT));
516 
517  // Read post-health test, pre-conditioned, entropy from the observe FIFO.
518  for (size_t i = 0; i < len; ++i) {
519  reg = mmio_region_read32(entropy_src->base_addr,
520  ENTROPY_SRC_FW_OV_RD_DATA_REG_OFFSET);
521  if (buf != NULL) {
522  buf[i] = reg;
523  }
524  }
525 
526  // Clear the status bit.
527  reg = bitfield_bit32_write(
528  0, ENTROPY_SRC_INTR_STATE_ES_OBSERVE_FIFO_READY_BIT, true);
529  mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_INTR_STATE_REG_OFFSET,
530  reg);
531 
532  return kDifOk;
533 }
534 
536  const dif_entropy_src_t *entropy_src, uint32_t *buf, size_t *len) {
537  if (entropy_src == NULL || len == NULL) {
538  return kDifBadArg;
539  }
540 
541  // Check that we are in firmware override mode. We can only read from the
542  // observe FIFO if we are.
543  uint32_t reg = mmio_region_read32(entropy_src->base_addr,
544  ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
545  if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
546  kMultiBitBool4True) {
547  return kDifError;
548  }
549 
550  // Read until FIFO is empty or we have read `*len` words.
551  size_t read_count = 0;
552  while (read_count < *len &&
553  mmio_region_read32(entropy_src->base_addr,
554  ENTROPY_SRC_OBSERVE_FIFO_DEPTH_REG_OFFSET) > 0) {
555  uint32_t reg = mmio_region_read32(entropy_src->base_addr,
556  ENTROPY_SRC_FW_OV_RD_DATA_REG_OFFSET);
557  if (buf != NULL) {
558  buf[read_count++] = reg;
559  }
560  }
561  // Update `*len`.
562  *len = read_count;
563 
564  return kDifOk;
565 }
566 
568  const dif_entropy_src_t *entropy_src, const uint32_t *buf, size_t len,
569  size_t *written) {
570  if (entropy_src == NULL || buf == NULL) {
571  return kDifBadArg;
572  }
573 
574  // Check that we are in firmware override mode and that we can insert data
575  // into the entropy pipeline.
576  uint32_t reg = mmio_region_read32(entropy_src->base_addr,
577  ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
578  if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
579  kMultiBitBool4True ||
581  reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_ENTROPY_INSERT_FIELD) !=
582  kMultiBitBool4True) {
583  return kDifError;
584  }
585 
586  // Check if the FIFO is full before writing each word.
587  for (size_t i = 0; i < len; ++i) {
588  if (mmio_region_read32(entropy_src->base_addr,
589  ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET)) {
590  if (written) {
591  *written = i;
592  }
593  return kDifIpFifoFull;
594  }
595 
596  mmio_region_write32(entropy_src->base_addr,
597  ENTROPY_SRC_FW_OV_WR_DATA_REG_OFFSET, buf[i]);
598  }
599 
600  if (written) {
601  *written = len;
602  }
603  return kDifOk;
604 }
605 
607  const dif_entropy_src_t *entropy_src) {
608  if (entropy_src == NULL) {
609  return kDifBadArg;
610  }
611 
612  // Check if SHA3 conditioner operation has already started.
613  uint32_t current_val = mmio_region_read32(
614  entropy_src->base_addr, ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET);
615  if (current_val == kMultiBitBool4True) {
616  return kDifUnavailable;
617  }
618 
619  mmio_region_write32(entropy_src->base_addr,
620  ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET,
621  kMultiBitBool4True);
622 
623  return kDifOk;
624 }
625 
627  const dif_entropy_src_t *entropy_src) {
628  if (entropy_src == NULL) {
629  return kDifBadArg;
630  }
631 
632  // Check the FW_OV_WR_FIFO_FULL register to determine in any data is
633  // stalling at the input of the SHA3 conditioner.
634  if (mmio_region_read32(entropy_src->base_addr,
635  ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET)) {
636  return kDifIpFifoFull;
637  }
638 
639  mmio_region_write32(entropy_src->base_addr,
640  ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET,
641  kMultiBitBool4False);
642  return kDifOk;
643 }
644 
646  bool *is_full) {
647  if (entropy_src == NULL || is_full == NULL) {
648  return kDifBadArg;
649  }
650 
651  *is_full = mmio_region_read32(entropy_src->base_addr,
652  ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET);
653 
654  return kDifOk;
655 }
656 
658  const dif_entropy_src_t *entropy_src, bool *has_overflowed) {
659  if (entropy_src == NULL || has_overflowed == NULL) {
660  return kDifBadArg;
661  }
662 
663  *has_overflowed = mmio_region_read32(
664  entropy_src->base_addr, ENTROPY_SRC_FW_OV_RD_FIFO_OVERFLOW_REG_OFFSET);
665 
666  return kDifOk;
667 }
668 
670  const dif_entropy_src_t *entropy_src, uint32_t *fifo_depth) {
671  if (entropy_src == NULL || fifo_depth == NULL) {
672  return kDifBadArg;
673  }
674 
675  *fifo_depth = mmio_region_read32(entropy_src->base_addr,
676  ENTROPY_SRC_OBSERVE_FIFO_DEPTH_REG_OFFSET);
677 
678  return kDifOk;
679 }
680 
682  const dif_entropy_src_t *entropy_src,
683  dif_entropy_src_debug_state_t *debug_state) {
684  if (entropy_src == NULL || debug_state == NULL) {
685  return kDifBadArg;
686  }
687 
688  uint32_t debug_state_reg = mmio_region_read32(
689  entropy_src->base_addr, ENTROPY_SRC_DEBUG_STATUS_REG_OFFSET);
690  debug_state->entropy_fifo_depth = (uint8_t)bitfield_field32_read(
691  debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_ENTROPY_FIFO_DEPTH_FIELD);
692  debug_state->sha3_fsm_state = bitfield_field32_read(
693  debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_FSM_FIELD);
695  debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_BLOCK_PR_BIT);
696  debug_state->sha3_squeezing = bitfield_bit32_read(
697  debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_SQUEEZING_BIT);
698  debug_state->sha3_absorbed = bitfield_bit32_read(
699  debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_ABSORBED_BIT);
700  debug_state->sha3_error = bitfield_bit32_read(
701  debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_ERR_BIT);
702  debug_state->main_fsm_is_idle = bitfield_bit32_read(
703  debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_MAIN_SM_IDLE_BIT);
705  debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_MAIN_SM_BOOT_DONE_BIT);
706 
707  return kDifOk;
708 }
709 
711  const dif_entropy_src_t *entropy_src, uint32_t *alerts) {
712  if (entropy_src == NULL || alerts == NULL) {
713  return kDifBadArg;
714  }
715 
716  *alerts = mmio_region_read32(entropy_src->base_addr,
717  ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET);
718 
719  return kDifOk;
720 }
721 
723  const dif_entropy_src_t *entropy_src, uint32_t alerts) {
724  if (entropy_src == NULL || alerts > kDifEntropySrcAlertAllAlerts) {
725  return kDifBadArg;
726  }
727 
728  uint32_t active_alerts = mmio_region_read32(
729  entropy_src->base_addr, ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET);
730  active_alerts &= ~alerts;
731  mmio_region_write32(entropy_src->base_addr,
732  ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET, active_alerts);
733 
734  return kDifOk;
735 }
736 
738  uint32_t *errors) {
739  if (entropy_src == NULL || errors == NULL) {
740  return kDifBadArg;
741  }
742 
743  uint32_t err_code_reg = mmio_region_read32(entropy_src->base_addr,
744  ENTROPY_SRC_ERR_CODE_REG_OFFSET);
745 
746  *errors = 0;
747 
748  // ESRNG FIFO errors.
749  if (bitfield_bit32_read(err_code_reg,
750  ENTROPY_SRC_ERR_CODE_SFIFO_ESRNG_ERR_BIT)) {
751  if (bitfield_bit32_read(err_code_reg,
752  ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
754  }
755  if (bitfield_bit32_read(err_code_reg,
756  ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
758  }
759  if (bitfield_bit32_read(err_code_reg,
760  ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
762  }
763  }
764 
765  // Observe FIFO errors.
766  if (bitfield_bit32_read(err_code_reg,
767  ENTROPY_SRC_ERR_CODE_SFIFO_OBSERVE_ERR_BIT)) {
768  if (bitfield_bit32_read(err_code_reg,
769  ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
771  }
772  if (bitfield_bit32_read(err_code_reg,
773  ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
775  }
776  if (bitfield_bit32_read(err_code_reg,
777  ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
779  }
780  }
781 
782  // ESFINAL FIFO errors.
783  if (bitfield_bit32_read(err_code_reg,
784  ENTROPY_SRC_ERR_CODE_SFIFO_ESFINAL_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  // Remaining FSM/Counter errors.
800  if (bitfield_bit32_read(err_code_reg,
801  ENTROPY_SRC_ERR_CODE_ES_ACK_SM_ERR_BIT)) {
803  }
804  if (bitfield_bit32_read(err_code_reg,
805  ENTROPY_SRC_ERR_CODE_ES_MAIN_SM_ERR_BIT)) {
807  }
808  if (bitfield_bit32_read(err_code_reg, ENTROPY_SRC_ERR_CODE_ES_CNTR_ERR_BIT)) {
810  }
811 
812  return kDifOk;
813 }
814 
816  dif_entropy_src_error_t error) {
817  if (entropy_src == NULL) {
818  return kDifBadArg;
819  }
820 
821  uint32_t err_code_reg = 0;
822 
823  switch (error) {
827  err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_ESRNG_ERR_BIT;
828  break;
832  err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_OBSERVE_ERR_BIT;
833  break;
837  err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_ESFINAL_ERR_BIT;
838  break;
840  err_code_reg = ENTROPY_SRC_ERR_CODE_ES_ACK_SM_ERR_BIT;
841  break;
843  err_code_reg = ENTROPY_SRC_ERR_CODE_ES_MAIN_SM_ERR_BIT;
844  break;
846  err_code_reg = ENTROPY_SRC_ERR_CODE_ES_CNTR_ERR_BIT;
847  break;
848  default:
849  return kDifBadArg;
850  }
851 
852  mmio_region_write32(entropy_src->base_addr,
853  ENTROPY_SRC_ERR_CODE_TEST_REG_OFFSET, err_code_reg);
854 
855  return kDifOk;
856 }
857 
859  const dif_entropy_src_t *entropy_src, dif_entropy_src_main_fsm_t *state) {
860  if (entropy_src == NULL || state == NULL) {
861  return kDifBadArg;
862  }
863 
864  *state = mmio_region_read32(entropy_src->base_addr,
865  ENTROPY_SRC_MAIN_SM_STATE_REG_OFFSET);
866 
867  return kDifOk;
868 }