Software APIs
dif_lc_ctrl_unittest.cc
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 <cstring>
8 #include <limits>
9 #include <utility>
10 
11 #include "gtest/gtest.h"
14 #include "sw/device/lib/base/mock_mmio.h"
15 #include "sw/device/lib/base/multibits.h"
17 
18 #include "lc_ctrl_regs.h" // Generated.
19 
20 namespace dif_lc_ctrl_unittest {
21 namespace {
22 using ::mock_mmio::LeInt;
23 using ::mock_mmio::MmioTest;
24 using ::mock_mmio::MockDevice;
25 using ::testing::Test;
26 
27 class LcCtrlTest : public Test, public MmioTest {
28  protected:
29  dif_lc_ctrl_t lc_ = {.base_addr = dev().region()};
30 };
31 
32 class StateTest : public LcCtrlTest {};
33 
34 TEST_F(StateTest, GetState) {
35  std::vector<std::pair<uint32_t, dif_lc_ctrl_state_t>> states = {
36  {LC_CTRL_LC_STATE_STATE_VALUE_RAW, kDifLcCtrlStateRaw},
37  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED0,
39  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_LOCKED0, kDifLcCtrlStateTestLocked0},
40  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED1,
42  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_LOCKED1, kDifLcCtrlStateTestLocked1},
43  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED2,
45  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_LOCKED2, kDifLcCtrlStateTestLocked2},
46  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED3,
48  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_LOCKED3, kDifLcCtrlStateTestLocked3},
49  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED4,
51  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_LOCKED4, kDifLcCtrlStateTestLocked4},
52  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED5,
54  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_LOCKED5, kDifLcCtrlStateTestLocked5},
55  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED6,
57  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_LOCKED6, kDifLcCtrlStateTestLocked6},
58  {LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED7,
60  {LC_CTRL_LC_STATE_STATE_VALUE_DEV, kDifLcCtrlStateDev},
61  {LC_CTRL_LC_STATE_STATE_VALUE_PROD, kDifLcCtrlStateProd},
62  {LC_CTRL_LC_STATE_STATE_VALUE_PROD_END, kDifLcCtrlStateProdEnd},
63  {LC_CTRL_LC_STATE_STATE_VALUE_RMA, kDifLcCtrlStateRma},
64  {LC_CTRL_LC_STATE_STATE_VALUE_SCRAP, kDifLcCtrlStateScrap},
65 
66  {LC_CTRL_LC_STATE_STATE_VALUE_POST_TRANSITION,
68  {LC_CTRL_LC_STATE_STATE_VALUE_ESCALATE, kDifLcCtrlStateEscalate},
69  {LC_CTRL_LC_STATE_STATE_VALUE_INVALID, kDifLcCtrlStateInvalid},
70  };
71 
72  for (auto pair : states) {
73  dif_lc_ctrl_state_t state;
74 
75  EXPECT_READ32(LC_CTRL_LC_STATE_REG_OFFSET,
76  {{LC_CTRL_LC_STATE_STATE_OFFSET, pair.first}});
77  EXPECT_DIF_OK(dif_lc_ctrl_get_state(&lc_, &state));
78  EXPECT_EQ(state, pair.second);
79  }
80 }
81 
82 TEST_F(StateTest, GetAttempts) {
83  uint8_t attempts;
84 
85  EXPECT_READ32(LC_CTRL_LC_TRANSITION_CNT_REG_OFFSET,
86  {{LC_CTRL_LC_TRANSITION_CNT_CNT_OFFSET, 13}});
87  EXPECT_DIF_OK(dif_lc_ctrl_get_attempts(&lc_, &attempts));
88  EXPECT_EQ(attempts, 13);
89 
90  EXPECT_READ32(LC_CTRL_LC_TRANSITION_CNT_REG_OFFSET,
91  {{LC_CTRL_LC_TRANSITION_CNT_CNT_OFFSET,
92  LC_CTRL_LC_TRANSITION_CNT_CNT_MASK}});
93  EXPECT_EQ(dif_lc_ctrl_get_attempts(&lc_, &attempts), kDifError);
94 }
95 
96 TEST_F(StateTest, GetStatus) {
98 
99  EXPECT_READ32(LC_CTRL_STATUS_REG_OFFSET,
100  {
101  {LC_CTRL_STATUS_INITIALIZED_BIT, true},
102  {LC_CTRL_STATUS_READY_BIT, true},
103  });
107 
108  EXPECT_READ32(LC_CTRL_STATUS_REG_OFFSET,
109  {
110  {LC_CTRL_STATUS_TRANSITION_ERROR_BIT, true},
111  {LC_CTRL_STATUS_TOKEN_ERROR_BIT, true},
112  {LC_CTRL_STATUS_OTP_ERROR_BIT, true},
113  });
115  EXPECT_TRUE(
119 }
120 
121 TEST_F(StateTest, GetIdState) {
122  std::vector<std::pair<uint32_t, dif_lc_ctrl_id_state_t>> states = {
123  {LC_CTRL_LC_ID_STATE_STATE_VALUE_BLANK, kDifLcCtrlIdStateBlank},
124  {LC_CTRL_LC_ID_STATE_STATE_VALUE_PERSONALIZED,
126  {LC_CTRL_LC_ID_STATE_STATE_VALUE_INVALID, kDifLcCtrlIdStateInvalid},
127  };
128 
129  for (auto pair : states) {
131 
132  EXPECT_READ32(LC_CTRL_LC_ID_STATE_REG_OFFSET, pair.first);
134  EXPECT_EQ(state, pair.second);
135  }
136 }
137 
138 TEST_F(StateTest, NullArgs) {
139  dif_lc_ctrl_state_t state;
140  EXPECT_DIF_BADARG(dif_lc_ctrl_get_state(nullptr, &state));
142 
143  uint8_t attempts;
144  EXPECT_DIF_BADARG(dif_lc_ctrl_get_attempts(nullptr, &attempts));
146 
150 
151  dif_lc_ctrl_id_state_t id_state;
152  EXPECT_DIF_BADARG(dif_lc_ctrl_get_id_state(nullptr, &id_state));
154 }
155 
156 class MutexTest : public LcCtrlTest {};
157 
158 TEST_F(MutexTest, Acquire) {
159  EXPECT_READ32(LC_CTRL_CLAIM_TRANSITION_IF_REGWEN_REG_OFFSET, true);
160  EXPECT_WRITE32(LC_CTRL_CLAIM_TRANSITION_IF_REG_OFFSET, kMultiBitBool8True);
161  EXPECT_READ32(LC_CTRL_CLAIM_TRANSITION_IF_REG_OFFSET, kMultiBitBool8True);
163 
164  EXPECT_READ32(LC_CTRL_CLAIM_TRANSITION_IF_REGWEN_REG_OFFSET, true);
165  EXPECT_WRITE32(LC_CTRL_CLAIM_TRANSITION_IF_REG_OFFSET, kMultiBitBool8True);
166  EXPECT_READ32(LC_CTRL_CLAIM_TRANSITION_IF_REG_OFFSET, kMultiBitBool8False);
168 }
169 
170 TEST_F(MutexTest, Release) {
171  EXPECT_READ32(LC_CTRL_CLAIM_TRANSITION_IF_REG_OFFSET, kMultiBitBool8True);
172  EXPECT_WRITE32(LC_CTRL_CLAIM_TRANSITION_IF_REG_OFFSET, kMultiBitBool8False);
174 
175  EXPECT_READ32(LC_CTRL_CLAIM_TRANSITION_IF_REG_OFFSET, kMultiBitBool8False);
176  EXPECT_EQ(dif_lc_ctrl_mutex_release(&lc_), kDifError);
177 }
178 
179 TEST_F(MutexTest, NullArgs) {
182 }
183 
184 TEST_F(MutexTest, LockMutexClaim) {
185  EXPECT_WRITE32(LC_CTRL_CLAIM_TRANSITION_IF_REGWEN_REG_OFFSET, false);
187  EXPECT_READ32(LC_CTRL_CLAIM_TRANSITION_IF_REGWEN_REG_OFFSET, false);
188  EXPECT_EQ(dif_lc_ctrl_mutex_try_acquire(&lc_), kDifLocked);
189 }
190 
191 class ConfigureTest : public LcCtrlTest {};
192 
193 TEST_F(ConfigureTest, SuccessNoToken) {
194  EXPECT_READ32(LC_CTRL_TRANSITION_REGWEN_REG_OFFSET, true);
195  EXPECT_WRITE32(LC_CTRL_TRANSITION_TARGET_REG_OFFSET,
196  LC_CTRL_TRANSITION_TARGET_STATE_VALUE_PROD);
197  EXPECT_WRITE32(LC_CTRL_TRANSITION_CTRL_REG_OFFSET, 0x0);
199  dif_lc_ctrl_configure(&lc_, kDifLcCtrlStateProd, false, nullptr));
200 }
201 
202 TEST_F(ConfigureTest, SucessWithToken) {
203  dif_lc_ctrl_token_t token = {"this is a token"};
204 
205  EXPECT_READ32(LC_CTRL_TRANSITION_REGWEN_REG_OFFSET, true);
206  EXPECT_WRITE32(LC_CTRL_TRANSITION_TARGET_REG_OFFSET,
207  LC_CTRL_TRANSITION_TARGET_STATE_VALUE_TEST_UNLOCKED2);
208  EXPECT_WRITE32(LC_CTRL_TRANSITION_CTRL_REG_OFFSET, 0x1);
209  EXPECT_WRITE32(LC_CTRL_TRANSITION_TOKEN_0_REG_OFFSET, LeInt("this"));
210  EXPECT_WRITE32(LC_CTRL_TRANSITION_TOKEN_1_REG_OFFSET, LeInt(" is "));
211  EXPECT_WRITE32(LC_CTRL_TRANSITION_TOKEN_2_REG_OFFSET, LeInt("a to"));
212  EXPECT_WRITE32(LC_CTRL_TRANSITION_TOKEN_3_REG_OFFSET, LeInt("ken\0"));
215 
216  EXPECT_READ32(LC_CTRL_TRANSITION_REGWEN_REG_OFFSET, true);
217  EXPECT_WRITE32(LC_CTRL_TRANSITION_TARGET_REG_OFFSET,
218  LC_CTRL_TRANSITION_TARGET_STATE_VALUE_TEST_UNLOCKED6);
219  EXPECT_WRITE32(LC_CTRL_TRANSITION_CTRL_REG_OFFSET, 0x1);
220  EXPECT_WRITE32(LC_CTRL_TRANSITION_TOKEN_0_REG_OFFSET, LeInt("this"));
221  EXPECT_WRITE32(LC_CTRL_TRANSITION_TOKEN_1_REG_OFFSET, LeInt(" is "));
222  EXPECT_WRITE32(LC_CTRL_TRANSITION_TOKEN_2_REG_OFFSET, LeInt("a to"));
223  EXPECT_WRITE32(LC_CTRL_TRANSITION_TOKEN_3_REG_OFFSET, LeInt("ken\0"));
226 }
227 
228 TEST_F(ConfigureTest, Locked) {
229  EXPECT_READ32(LC_CTRL_TRANSITION_REGWEN_REG_OFFSET, false);
230  EXPECT_EQ(dif_lc_ctrl_configure(&lc_, kDifLcCtrlStateProd, false, nullptr),
232 }
233 
234 TEST_F(ConfigureTest, NullHandle) {
235  dif_lc_ctrl_token_t token = {"this is a token"};
237  dif_lc_ctrl_configure(nullptr, kDifLcCtrlStateProd, false, &token));
238 }
239 
240 class TransitionTest : public LcCtrlTest {};
241 
242 TEST_F(TransitionTest, Success) {
243  EXPECT_READ32(LC_CTRL_TRANSITION_REGWEN_REG_OFFSET, true);
244  EXPECT_WRITE32(LC_CTRL_TRANSITION_CMD_REG_OFFSET, true);
246 }
247 
248 TEST_F(TransitionTest, Locked) {
249  EXPECT_READ32(LC_CTRL_TRANSITION_REGWEN_REG_OFFSET, false);
250  EXPECT_EQ(dif_lc_ctrl_transition(&lc_), kDifUnavailable);
251 }
252 
253 TEST_F(TransitionTest, NullHandle) {
255 }
256 
258 
259 TEST_F(OtpVendorTestRegTest, Read) {
260  uint32_t settings_read = 0;
261  EXPECT_READ32(LC_CTRL_TRANSITION_REGWEN_REG_OFFSET, true);
262  EXPECT_READ32(LC_CTRL_OTP_VENDOR_TEST_CTRL_REG_OFFSET, 0x5A);
263  EXPECT_DIF_OK(dif_lc_ctrl_get_otp_vendor_test_reg(&lc_, &settings_read));
264  EXPECT_EQ(settings_read, 0x5A);
265 }
266 
267 TEST_F(OtpVendorTestRegTest, Write) {
268  EXPECT_READ32(LC_CTRL_TRANSITION_REGWEN_REG_OFFSET, true);
269  EXPECT_WRITE32(LC_CTRL_OTP_VENDOR_TEST_CTRL_REG_OFFSET, 0xA5);
271 }
272 
273 } // namespace
274 } // namespace dif_lc_ctrl_unittest