Software APIs
lifecycle.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 
5 #include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
6 
7 #include <assert.h>
8 #include <stdint.h>
9 
10 #include "dt/dt_lc_ctrl.h"
15 
16 #include "lc_ctrl_regs.h"
17 
18 static inline uint32_t lc_ctrl_base(void) {
19  return dt_lc_ctrl_primary_reg_block(kDtLcCtrl);
20 }
21 
22 lifecycle_state_t lifecycle_state_get(void) {
23  uint32_t raw_state = lifecycle_raw_state_get();
24 
25  switch (launder32(raw_state)) {
26  case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED0:
27  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED0);
28  return kLcStateTest;
29  case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED1:
30  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED1);
31  return kLcStateTest;
32  case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED2:
33  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED2);
34  return kLcStateTest;
35  case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED3:
36  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED3);
37  return kLcStateTest;
38  case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED4:
39  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED4);
40  return kLcStateTest;
41  case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED5:
42  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED5);
43  return kLcStateTest;
44  case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED6:
45  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED6);
46  return kLcStateTest;
47  case LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED7:
48  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_TEST_UNLOCKED7);
49  return kLcStateTest;
50  case LC_CTRL_LC_STATE_STATE_VALUE_DEV:
51  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_DEV);
52  return kLcStateDev;
53  case LC_CTRL_LC_STATE_STATE_VALUE_PROD:
54  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_PROD);
55  return kLcStateProd;
56  case LC_CTRL_LC_STATE_STATE_VALUE_PROD_END:
57  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_PROD_END);
58  return kLcStateProdEnd;
59  case LC_CTRL_LC_STATE_STATE_VALUE_RMA:
60  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_RMA);
61  return kLcStateRma;
62  default:
63  HARDENED_TRAP();
65  }
66 }
67 
68 hardened_bool_t lifecycle_is_prod(void) {
69  uint32_t raw_state = lifecycle_raw_state_get();
70 
71  if (launder32(raw_state) == LC_CTRL_LC_STATE_STATE_VALUE_PROD) {
72  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_PROD);
73  return kHardenedBoolTrue;
74  }
75  HARDENED_CHECK_NE(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_PROD);
76 
77  if (launder32(raw_state) == LC_CTRL_LC_STATE_STATE_VALUE_PROD_END) {
78  HARDENED_CHECK_EQ(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_PROD_END);
79  return kHardenedBoolTrue;
80  }
81  HARDENED_CHECK_NE(raw_state, LC_CTRL_LC_STATE_STATE_VALUE_PROD_END);
82 
83  return kHardenedBoolFalse;
84 }
85 
86 uint32_t lifecycle_raw_state_get(void) {
87  uint32_t value = bitfield_field32_read(
88  sec_mmio_read32(lc_ctrl_base() + LC_CTRL_LC_STATE_REG_OFFSET),
89  LC_CTRL_LC_STATE_STATE_FIELD);
90  return value;
91 }
92 
93 void lifecycle_device_id_get(lifecycle_device_id_t *device_id) {
94  static_assert(
95  kLifecycleDeviceIdNumWords == LC_CTRL_PARAM_NUM_DEVICE_ID_WORDS,
96  "length of the device_id array does not match the length in hardware");
97 
98  size_t i = 0, r = kLifecycleDeviceIdNumWords - 1;
99  for (; launder32(i) < kLifecycleDeviceIdNumWords &&
100  launder32(r) < kLifecycleDeviceIdNumWords;
101  ++i, --r) {
102  device_id->device_id[i] = sec_mmio_read32(
103  lc_ctrl_base() + LC_CTRL_DEVICE_ID_0_REG_OFFSET + i * sizeof(uint32_t));
104  }
105  HARDENED_CHECK_EQ(i, kLifecycleDeviceIdNumWords);
106  HARDENED_CHECK_EQ(r, SIZE_MAX);
107 }
108 
109 void lifecycle_hw_rev_get(lifecycle_hw_rev_t *hw_rev) {
110  uint32_t reg0 =
111  sec_mmio_read32(lc_ctrl_base() + LC_CTRL_HW_REVISION0_REG_OFFSET);
112  uint32_t reg1 =
113  sec_mmio_read32(lc_ctrl_base() + LC_CTRL_HW_REVISION1_REG_OFFSET);
114  *hw_rev = (lifecycle_hw_rev_t){
115  .silicon_creator_id = (uint16_t)bitfield_field32_read(
116  reg0, LC_CTRL_HW_REVISION0_SILICON_CREATOR_ID_FIELD),
117  .product_id = (uint16_t)bitfield_field32_read(
118  reg0, LC_CTRL_HW_REVISION0_PRODUCT_ID_FIELD),
119  .revision_id = (uint8_t)bitfield_field32_read(
120  reg1, LC_CTRL_HW_REVISION1_REVISION_ID_FIELD),
121  };
122 }
123 
124 hardened_bool_t lifecycle_din_eq(lifecycle_device_id_t *id, uint32_t *din) {
125  if (id->device_id[1] == din[0] && id->device_id[2] == din[1])
126  return kHardenedBoolTrue;
127  return kHardenedBoolFalse;
128 }