Software APIs
lifecycle_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 
5 #include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
6 
7 #include <array>
8 
9 #include "gtest/gtest.h"
11 #include "sw/device/silicon_creator/lib/base/mock_sec_mmio.h"
12 #include "sw/device/silicon_creator/lib/error.h"
13 #include "sw/device/silicon_creator/testing/rom_test.h"
14 
16 #include "lc_ctrl_regs.h"
17 
18 namespace lifecycle_unittest {
19 namespace {
20 using ::testing::ElementsAreArray;
21 
23  protected:
24  uint32_t base_ = TOP_EARLGREY_LC_CTRL_REGS_BASE_ADDR;
25  rom_test::MockSecMmio mmio_;
26 };
27 
28 TEST_F(LifecycleTest, RawState) {
29  EXPECT_SEC_READ32(base_ + LC_CTRL_LC_STATE_REG_OFFSET,
30  LC_CTRL_LC_STATE_STATE_VALUE_SCRAP);
31  EXPECT_EQ(lifecycle_raw_state_get(), LC_CTRL_LC_STATE_STATE_VALUE_SCRAP);
32 }
33 
34 TEST_F(LifecycleTest, DeviceId) {
35  constexpr std::array<uint32_t, kLifecycleDeviceIdNumWords> kDeviceId{
36  0x8d2aed99, 0xdc7724d7, 0x33e5f191, 0xa0787993,
37  0x0dd390c5, 0xc95fcd6d, 0x9103a182, 0xdf82998e,
38  };
39  for (size_t i = 0; i < kLifecycleDeviceIdNumWords; ++i) {
40  EXPECT_SEC_READ32(
41  base_ + LC_CTRL_DEVICE_ID_0_REG_OFFSET + i * sizeof(uint32_t),
42  kDeviceId[i]);
43  }
44 
45  lifecycle_device_id_t device_id;
46  lifecycle_device_id_get(&device_id);
47  EXPECT_THAT(device_id.device_id, ElementsAreArray(kDeviceId));
48 }
49 
50 TEST_F(LifecycleTest, HwRev) {
51  uint16_t exp_silicon_creator_id = 0xa5;
52  uint16_t exp_product_id = 0xc3;
53  uint8_t exp_revision_id = 0x96;
54 
55  EXPECT_SEC_READ32(
56  base_ + LC_CTRL_HW_REVISION0_REG_OFFSET,
57  {
58  {LC_CTRL_HW_REVISION0_SILICON_CREATOR_ID_OFFSET,
59  exp_silicon_creator_id},
60  {LC_CTRL_HW_REVISION0_PRODUCT_ID_OFFSET, exp_product_id},
61  });
62  EXPECT_SEC_READ32(
63  base_ + LC_CTRL_HW_REVISION1_REG_OFFSET,
64  {
65  {LC_CTRL_HW_REVISION1_REVISION_ID_OFFSET, exp_revision_id},
66  });
67 
68  lifecycle_hw_rev_t hw_rev;
69  lifecycle_hw_rev_get(&hw_rev);
70  EXPECT_EQ(hw_rev.silicon_creator_id, exp_silicon_creator_id);
71  EXPECT_EQ(hw_rev.product_id, exp_product_id);
72  EXPECT_EQ(hw_rev.revision_id, exp_revision_id);
73 }
74 
76  /**
77  * Value reported by hardware.
78  */
79  uint32_t hw_state;
80  /**
81  * Value returned by software.
82  */
83  lifecycle_state_t sw_state;
84  /**
85  * Whether the state is prod / prod_end.
86  */
88 };
89 
91  : public LifecycleTest,
92  public testing::WithParamInterface<ValidStateTestCase> {};
93 
94 TEST_P(LifecycleValidStates, ValidState) {
95  EXPECT_SEC_READ32(base_ + LC_CTRL_LC_STATE_REG_OFFSET, GetParam().hw_state);
96  EXPECT_EQ(lifecycle_state_get(), GetParam().sw_state);
97 }
98 
99 TEST_P(LifecycleValidStates, LifecycleIsProd) {
100  EXPECT_SEC_READ32(base_ + LC_CTRL_LC_STATE_REG_OFFSET, GetParam().hw_state);
101  EXPECT_EQ(lifecycle_is_prod(), GetParam().is_prod);
102 }
103 
104 constexpr std::array<ValidStateTestCase, 12> kValidStateTestCases{{
105  {
106  .hw_state = LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED0,
107  .sw_state = kLcStateTest,
108  .is_prod = kHardenedBoolFalse,
109  },
110  {
111  .hw_state = LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED1,
112  .sw_state = kLcStateTest,
113  .is_prod = kHardenedBoolFalse,
114  },
115  {
116  .hw_state = LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED2,
117  .sw_state = kLcStateTest,
118  .is_prod = kHardenedBoolFalse,
119  },
120  {
121  .hw_state = LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED3,
122  .sw_state = kLcStateTest,
123  .is_prod = kHardenedBoolFalse,
124  },
125  {
126  .hw_state = LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED4,
127  .sw_state = kLcStateTest,
128  .is_prod = kHardenedBoolFalse,
129  },
130  {
131  .hw_state = LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED5,
132  .sw_state = kLcStateTest,
133  .is_prod = kHardenedBoolFalse,
134  },
135  {
136  .hw_state = LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED6,
137  .sw_state = kLcStateTest,
138  .is_prod = kHardenedBoolFalse,
139  },
140  {
141  .hw_state = LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED7,
142  .sw_state = kLcStateTest,
143  .is_prod = kHardenedBoolFalse,
144  },
145  {
146  .hw_state = LC_CTRL_LC_STATE_STATE_VALUE_DEV,
147  .sw_state = kLcStateDev,
148  .is_prod = kHardenedBoolFalse,
149  },
150  {
151  .hw_state = LC_CTRL_LC_STATE_STATE_VALUE_PROD,
152  .sw_state = kLcStateProd,
153  .is_prod = kHardenedBoolTrue,
154  },
155  {
156  .hw_state = LC_CTRL_LC_STATE_STATE_VALUE_PROD_END,
157  .sw_state = kLcStateProdEnd,
158  .is_prod = kHardenedBoolTrue,
159  },
160  {
161  .hw_state = LC_CTRL_LC_STATE_STATE_VALUE_RMA,
162  .sw_state = kLcStateRma,
163  .is_prod = kHardenedBoolFalse,
164  },
165 }};
166 
167 INSTANTIATE_TEST_SUITE_P(AllValidStates, LifecycleValidStates,
168  testing::ValuesIn(kValidStateTestCases));
169 
171  public testing::WithParamInterface<uint32_t> {};
172 
173 TEST_P(LifecycleDeathTest, InvalidState) {
174  EXPECT_DEATH(
175  {
176  EXPECT_SEC_READ32(base_ + LC_CTRL_LC_STATE_REG_OFFSET, GetParam());
177  OT_DISCARD(lifecycle_state_get());
178  },
179  "");
180 }
181 
182 INSTANTIATE_TEST_SUITE_P(
183  AllInvalidStates, LifecycleDeathTest,
184  testing::Values(LC_CTRL_TRANSITION_TARGET_STATE_VALUE_RAW,
185  LC_CTRL_TRANSITION_TARGET_STATE_VALUE_TEST_LOCKED0,
186  LC_CTRL_TRANSITION_TARGET_STATE_VALUE_TEST_LOCKED1,
187  LC_CTRL_TRANSITION_TARGET_STATE_VALUE_TEST_LOCKED2,
188  LC_CTRL_TRANSITION_TARGET_STATE_VALUE_TEST_LOCKED3,
189  LC_CTRL_TRANSITION_TARGET_STATE_VALUE_TEST_LOCKED4,
190  LC_CTRL_TRANSITION_TARGET_STATE_VALUE_TEST_LOCKED5,
191  LC_CTRL_TRANSITION_TARGET_STATE_VALUE_TEST_LOCKED6,
192  LC_CTRL_TRANSITION_TARGET_STATE_VALUE_SCRAP,
193  LC_CTRL_LC_STATE_STATE_VALUE_POST_TRANSITION,
194  LC_CTRL_LC_STATE_STATE_VALUE_ESCALATE,
195  LC_CTRL_LC_STATE_STATE_VALUE_INVALID));
196 
197 } // namespace
198 } // namespace lifecycle_unittest