Software APIs
dif_otbn.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 <assert.h>
8 
12 
13 #include "otbn_regs.h" // Generated.
14 
15 static_assert(kDifOtbnErrBitsBadDataAddr ==
16  (1 << OTBN_ERR_BITS_BAD_DATA_ADDR_BIT),
17  "Layout of error bits changed.");
18 static_assert(kDifOtbnErrBitsBadInsnAddr ==
19  (1 << OTBN_ERR_BITS_BAD_INSN_ADDR_BIT),
20  "Layout of error bits changed.");
21 static_assert(kDifOtbnErrBitsCallStack == (1 << OTBN_ERR_BITS_CALL_STACK_BIT),
22  "Layout of error bits changed.");
23 static_assert(kDifOtbnErrBitsIllegalInsn ==
24  (1 << OTBN_ERR_BITS_ILLEGAL_INSN_BIT),
25  "Layout of error bits changed.");
26 static_assert(kDifOtbnErrBitsLoop == (1 << OTBN_ERR_BITS_LOOP_BIT),
27  "Layout of error bits changed.");
28 static_assert(kDifOtbnErrBitsImemIntgViolation ==
29  (1 << OTBN_ERR_BITS_IMEM_INTG_VIOLATION_BIT),
30  "Layout of error bits changed.");
31 static_assert(kDifOtbnErrBitsDmemIntgViolation ==
32  (1 << OTBN_ERR_BITS_DMEM_INTG_VIOLATION_BIT),
33  "Layout of error bits changed.");
34 static_assert(kDifOtbnErrBitsRegIntgViolation ==
35  (1 << OTBN_ERR_BITS_REG_INTG_VIOLATION_BIT),
36  "Layout of error bits changed.");
37 static_assert(kDifOtbnErrBitsBusIntgViolation ==
38  (1 << OTBN_ERR_BITS_BUS_INTG_VIOLATION_BIT),
39  "Layout of error bits changed.");
40 static_assert(kDifOtbnErrBitsIllegalBusAccess ==
41  (1 << OTBN_ERR_BITS_ILLEGAL_BUS_ACCESS_BIT),
42  "Layout of error bits changed.");
44  (1 << OTBN_ERR_BITS_LIFECYCLE_ESCALATION_BIT),
45  "Layout of error bits changed.");
46 static_assert(kDifOtbnErrBitsFatalSoftware ==
47  (1 << OTBN_ERR_BITS_FATAL_SOFTWARE_BIT),
48  "Layout of error bits changed.");
49 
50 /**
51  * Data width of big number subset, in bytes.
52  */
53 const int kDifOtbnWlenBytes = 256 / 8;
54 
55 /**
56  * Ensures that `offset` and `size` are valid for a given `mem_size`.
57  *
58  * Valid are 32b word accesses to 32b-aligned memory locations within
59  * `mem_size`.
60  */
61 static bool check_offset_len(uint32_t offset_bytes, size_t len_bytes,
62  size_t mem_size) {
63  // The overflow check below assumes/requires two unsigned inputs.
64  return (len_bytes % sizeof(uint32_t) == 0 &&
65  offset_bytes % sizeof(uint32_t) == 0 &&
66  offset_bytes + len_bytes >= len_bytes &&
67  offset_bytes + len_bytes <= mem_size);
68 }
69 
71  if (otbn == NULL) {
72  return kDifBadArg;
73  }
74 
75  mmio_region_write32(otbn->base_addr, OTBN_INTR_ENABLE_REG_OFFSET, 0);
76 
77  // Clear all pending interrupts.
78  mmio_region_write32(otbn->base_addr, OTBN_INTR_STATE_REG_OFFSET, 0xFFFFFFFF);
79 
80  return kDifOk;
81 }
82 
84  if (otbn == NULL) {
85  return kDifBadArg;
86  }
87 
88  mmio_region_write32(otbn->base_addr, OTBN_CMD_REG_OFFSET, cmd);
89 
90  return kDifOk;
91 }
92 
95  if (otbn == NULL || status == NULL) {
96  return kDifBadArg;
97  }
98 
99  *status = mmio_region_read32(otbn->base_addr, OTBN_STATUS_REG_OFFSET);
100 
101  return kDifOk;
102 }
103 
105  dif_otbn_err_bits_t *err_bits) {
106  if (otbn == NULL || err_bits == NULL) {
107  return kDifBadArg;
108  }
109 
110  uint32_t err_bits_raw =
111  mmio_region_read32(otbn->base_addr, OTBN_ERR_BITS_REG_OFFSET);
112 
113  *err_bits = err_bits_raw;
114  return kDifOk;
115 }
116 
117 dif_result_t dif_otbn_get_insn_cnt(const dif_otbn_t *otbn, uint32_t *insn_cnt) {
118  if (otbn == NULL || insn_cnt == NULL) {
119  return kDifBadArg;
120  }
121 
122  *insn_cnt = mmio_region_read32(otbn->base_addr, OTBN_INSN_CNT_REG_OFFSET);
123  return kDifOk;
124 }
125 
127  uint32_t *checksum) {
128  if (otbn == NULL || checksum == NULL) {
129  return kDifBadArg;
130  }
131 
132  *checksum =
133  mmio_region_read32(otbn->base_addr, OTBN_LOAD_CHECKSUM_REG_OFFSET);
134  return kDifOk;
135 }
136 
138  if (otbn == NULL) {
139  return kDifBadArg;
140  }
141 
142  mmio_region_write32(otbn->base_addr, OTBN_LOAD_CHECKSUM_REG_OFFSET, 0);
143 
144  return kDifOk;
145 }
146 
147 dif_result_t dif_otbn_imem_write(const dif_otbn_t *otbn, uint32_t offset_bytes,
148  const void *src, size_t len_bytes) {
149  if (otbn == NULL || src == NULL ||
150  !check_offset_len(offset_bytes, len_bytes, OTBN_IMEM_SIZE_BYTES)) {
151  return kDifBadArg;
152  }
153 
155  otbn->base_addr, OTBN_IMEM_REG_OFFSET + offset_bytes, src, len_bytes);
156 
157  return kDifOk;
158 }
159 
160 dif_result_t dif_otbn_imem_read(const dif_otbn_t *otbn, uint32_t offset_bytes,
161  void *dest, size_t len_bytes) {
162  if (otbn == NULL || dest == NULL ||
163  !check_offset_len(offset_bytes, len_bytes, OTBN_IMEM_SIZE_BYTES)) {
164  return kDifBadArg;
165  }
166 
168  otbn->base_addr, OTBN_IMEM_REG_OFFSET + offset_bytes, dest, len_bytes);
169 
170  return kDifOk;
171 }
172 
173 dif_result_t dif_otbn_dmem_write(const dif_otbn_t *otbn, uint32_t offset_bytes,
174  const void *src, size_t len_bytes) {
175  if (otbn == NULL || src == NULL ||
176  !check_offset_len(offset_bytes, len_bytes, OTBN_DMEM_SIZE_BYTES)) {
177  return kDifBadArg;
178  }
179 
181  otbn->base_addr, OTBN_DMEM_REG_OFFSET + offset_bytes, src, len_bytes);
182 
183  return kDifOk;
184 }
185 
186 dif_result_t dif_otbn_dmem_read(const dif_otbn_t *otbn, uint32_t offset_bytes,
187  void *dest, size_t len_bytes) {
188  if (otbn == NULL || dest == NULL ||
189  !check_offset_len(offset_bytes, len_bytes, OTBN_DMEM_SIZE_BYTES)) {
190  return kDifBadArg;
191  }
192 
194  otbn->base_addr, OTBN_DMEM_REG_OFFSET + offset_bytes, dest, len_bytes);
195 
196  return kDifOk;
197 }
198 
200  bool enable) {
201  if (otbn == NULL) {
202  return kDifBadArg;
203  }
204 
205  // Only one bit in the CTRL register so no need to read current value.
206  uint32_t new_ctrl;
207 
208  if (enable) {
209  new_ctrl = 1;
210  } else {
211  new_ctrl = 0;
212  }
213 
214  mmio_region_write32(otbn->base_addr, OTBN_CTRL_REG_OFFSET, new_ctrl);
215  if (mmio_region_read32(otbn->base_addr, OTBN_CTRL_REG_OFFSET) != new_ctrl) {
216  return kDifUnavailable;
217  }
218 
219  return kDifOk;
220 }
221 
223  return OTBN_DMEM_SIZE_BYTES;
224 }
225 
227  return OTBN_IMEM_SIZE_BYTES;
228 }