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
18static inline uint32_t lc_ctrl_base(void) {
19 return dt_lc_ctrl_primary_reg_block(kDtLcCtrl);
20}
21
22lifecycle_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:
65 }
66}
67
68hardened_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
86uint32_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
93void 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
109void 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
124hardened_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}