Software APIs
individualize_sw_cfg_functest.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/lib/base/status.h"
11 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
12 #include "sw/device/lib/testing/otp_ctrl_testutils.h"
13 #include "sw/device/lib/testing/rstmgr_testutils.h"
14 #include "sw/device/lib/testing/test_framework/check.h"
16 #include "sw/device/silicon_creator/manuf/lib/flash_info_fields.h"
17 #include "sw/device/silicon_creator/manuf/lib/individualize_sw_cfg.h"
18 
20 #include "otp_ctrl_regs.h" // Generated.
21 
22 OTTF_DEFINE_TEST_CONFIG();
23 
24 /**
25  * DIF Handles.
26  *
27  * Keep this list sorted in alphabetical order.
28  */
29 static dif_otp_ctrl_t otp_ctrl;
30 static dif_flash_ctrl_state_t flash_ctrl_state;
31 static dif_rstmgr_t rstmgr;
32 
33 static dif_flash_ctrl_region_properties_t kFlashInfoPage0Permissions = {
34  .ecc_en = kMultiBitBool4True,
35  .high_endurance_en = kMultiBitBool4False,
36  .erase_en = kMultiBitBool4True,
37  .prog_en = kMultiBitBool4True,
38  .rd_en = kMultiBitBool4True,
39  .scramble_en = kMultiBitBool4False};
40 
41 /**
42  * Initializes all DIF handles used in this module.
43  */
44 static status_t peripheral_handles_init(void) {
46  &flash_ctrl_state,
48  TRY(dif_otp_ctrl_init(
51  &rstmgr));
52  return OK_STATUS();
53 }
54 
55 /**
56  * Initializes flash info page 0 fields required to complete the
57  * individualization step, which include:
58  * - AST configuration data
59  */
60 static status_t init_flash_info_page0(void) {
61  uint32_t byte_address = 0;
62  TRY(flash_ctrl_testutils_info_region_setup_properties(
63  &flash_ctrl_state, kFlashInfoFieldAstCalibrationData.page,
64  kFlashInfoFieldAstCalibrationData.bank,
65  kFlashInfoFieldAstCalibrationData.partition, kFlashInfoPage0Permissions,
66  &byte_address));
67  TRY(flash_ctrl_testutils_erase_page(
68  &flash_ctrl_state, byte_address,
69  kFlashInfoFieldAstCalibrationData.partition,
70  kDifFlashCtrlPartitionTypeInfo));
71  // Set dummy AST values for testing.
72  uint32_t ast_cfg_data[kFlashInfoAstCalibrationDataSizeIn32BitWords] = {0};
73  for (size_t i = 0; i < ARRAYSIZE(ast_cfg_data); ++i) {
74  ast_cfg_data[i] = i;
75  }
76  TRY(flash_ctrl_testutils_write(
77  &flash_ctrl_state,
78  byte_address + kFlashInfoFieldAstCalibrationData.byte_offset,
79  kFlashInfoFieldAstCalibrationData.partition, ast_cfg_data,
80  kDifFlashCtrlPartitionTypeInfo,
81  kFlashInfoAstCalibrationDataSizeIn32BitWords));
82  return OK_STATUS();
83 }
84 
85 /**
86  * Check the AST configuration data was programmed correctly.
87  */
88 static status_t check_otp_ast_cfg(void) {
89  // Check OTP fields were programmed correctly.
90  uint32_t data;
91  uint32_t relative_addr;
92  for (size_t i = 0; i < kFlashInfoAstCalibrationDataSizeIn32BitWords; ++i) {
95  OTP_CTRL_PARAM_CREATOR_SW_CFG_AST_CFG_OFFSET + i * sizeof(uint32_t),
96  &relative_addr));
97  TRY(otp_ctrl_testutils_dai_read32(
98  &otp_ctrl, kDifOtpCtrlPartitionCreatorSwCfg, relative_addr, &data));
99  TRY_CHECK(data == i);
100  }
101 
102  // Check that the AST configuration data was erased from flash info page 0.
103  uint32_t ast_cfg_data[kFlashInfoAstCalibrationDataSizeIn32BitWords] = {0};
104  TRY(manuf_flash_info_field_read(
105  &flash_ctrl_state, kFlashInfoFieldAstCalibrationData, ast_cfg_data,
106  kFlashInfoAstCalibrationDataSizeIn32BitWords));
107  for (size_t i = 0; i < kFlashInfoAstCalibrationDataSizeIn32BitWords; ++i) {
108  TRY_CHECK(ast_cfg_data[i] == UINT32_MAX);
109  }
110 
111  return OK_STATUS();
112 }
113 
114 /**
115  * Perform software reset.
116  */
117 static void sw_reset(void) {
118  rstmgr_testutils_reason_clear();
119  CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
121 }
122 
123 bool test_main(void) {
124  CHECK_STATUS_OK(peripheral_handles_init());
125 
126  // Provision CREATOR_SW_CFG partition.
127  if (!status_ok(manuf_individualize_device_creator_sw_cfg_check(&otp_ctrl))) {
128  CHECK_STATUS_OK(init_flash_info_page0());
129  CHECK_STATUS_OK(manuf_individualize_device_creator_sw_cfg(
130  &otp_ctrl, &flash_ctrl_state));
131  CHECK_STATUS_OK(manuf_individualize_device_field_cfg(
132  &otp_ctrl,
133  OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_DATA_DEFAULT_CFG_OFFSET));
134  CHECK_STATUS_OK(manuf_individualize_device_field_cfg(
135  &otp_ctrl, OTP_CTRL_PARAM_CREATOR_SW_CFG_MANUF_STATE_OFFSET));
136  CHECK_STATUS_OK(manuf_individualize_device_field_cfg(
137  &otp_ctrl, OTP_CTRL_PARAM_CREATOR_SW_CFG_IMMUTABLE_ROM_EXT_EN_OFFSET));
138  CHECK_STATUS_OK(manuf_individualize_device_creator_sw_cfg_lock(&otp_ctrl));
139  CHECK_STATUS_OK(check_otp_ast_cfg());
140  LOG_INFO("Provisioned and locked CREATOR_SW_CFG OTP partition.");
141  // Halt the CPU here to enable host to perform POR and bootstrap again since
142  // flash scrambling enablement has changed. Bootstrap resets the chip as
143  // well, which completes the locking of this partition.
144  abort();
145  }
146 
147  bool perform_reset = false;
148 
149  // Provision OWNER_SW_CFG partition.
150  if (!status_ok(manuf_individualize_device_owner_sw_cfg_check(&otp_ctrl))) {
151  CHECK_STATUS_OK(manuf_individualize_device_owner_sw_cfg(&otp_ctrl));
152  CHECK_STATUS_OK(manuf_individualize_device_field_cfg(
153  &otp_ctrl, OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_BOOTSTRAP_DIS_OFFSET));
154  CHECK_STATUS_OK(manuf_individualize_device_owner_sw_cfg_lock(&otp_ctrl));
155  LOG_INFO("Provisioned and locked OWNER_SW_CFG OTP partition.");
156  perform_reset |= true;
157  }
158 
159  // Provision ROT_CREATOR_AUTH_CODESIGN partition.
160  if (!status_ok(manuf_individualize_device_rot_creator_auth_codesign_check(
161  &otp_ctrl))) {
162  CHECK_STATUS_OK(
163  manuf_individualize_device_rot_creator_auth_codesign(&otp_ctrl));
164  LOG_INFO("Provisioned and locked ROT_CREATOR_AUTH_CODESIGN OTP partition.");
165  perform_reset |= true;
166  }
167 
168  // Provision ROT_CREATOR_AUTH_STATE partition.
169  if (!status_ok(
170  manuf_individualize_device_rot_creator_auth_state_check(&otp_ctrl))) {
171  CHECK_STATUS_OK(
172  manuf_individualize_device_rot_creator_auth_state(&otp_ctrl));
173  LOG_INFO("Provisioned and locked ROT_CREATOR_AUTH_STATE OTP partition.");
174  perform_reset |= true;
175  }
176 
177  if (perform_reset) {
178  // Perform SW reset to complete locking of the partitions.
179  sw_reset();
180  }
181 
182  // Check all SW_CFG and ROT_CREATOR_AUTH partitions have been locked.
183  if (status_ok(manuf_individualize_device_creator_sw_cfg_check(&otp_ctrl)) &&
184  status_ok(manuf_individualize_device_owner_sw_cfg_check(&otp_ctrl)) &&
185  status_ok(manuf_individualize_device_rot_creator_auth_codesign_check(
186  &otp_ctrl)) &&
187  status_ok(
188  manuf_individualize_device_rot_creator_auth_state_check(&otp_ctrl))) {
189  return true;
190  }
191 
192  return false;
193 }