Skip to content

Commit de62d60

Browse files
timothytrippelpamaury
authored andcommitted
[manuf] refactor CP init to read out wafer data and device ID
When CP init runs, flash info page 0 will already be provisioned with wafer data from prior CP stages. This updates the CP init and subsequent FT provisioning stages to assume that is the case and pull appropriate data out of this flash info page accordingly. This fixes #24600. Signed-off-by: Tim Trippel <ttrippel@google.com>
1 parent a113255 commit de62d60

File tree

21 files changed

+513
-257
lines changed

21 files changed

+513
-257
lines changed

sw/device/lib/testing/json/provisioning_data.h

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@ extern "C" {
1414
#define MODULE_ID MAKE_MODULE_ID('j', 'p', 'd')
1515

1616
/**
17-
* Provisioning data imported onto the device in CP.
17+
* Provisioning data imported onto the device during CP.
1818
*/
1919
// clang-format off
2020
#define STRUCT_MANUF_CP_PROVISIONING_DATA(field, string) \
21-
field(device_id, uint32_t, 8) \
22-
field(manuf_state, uint32_t, 8) \
2321
field(wafer_auth_secret, uint32_t, 8) \
2422
field(test_unlock_token_hash, uint64_t, 2) \
2523
field(test_exit_token_hash, uint64_t, 2)
@@ -28,6 +26,31 @@ UJSON_SERDE_STRUCT(ManufCpProvisioningData, \
2826
STRUCT_MANUF_CP_PROVISIONING_DATA);
2927
// clang-format on
3028

29+
/**
30+
* Provisioning data exported off the device during CP.
31+
*/
32+
// clang-format off
33+
#define STRUCT_MANUF_CP_PROVISIONING_DATA_OUT(field, string) \
34+
field(cp_device_id, uint32_t, 4)
35+
UJSON_SERDE_STRUCT(ManufCpProvisioningDataOut, \
36+
manuf_cp_provisioning_data_out_t, \
37+
STRUCT_MANUF_CP_PROVISIONING_DATA_OUT);
38+
// clang-format on
39+
40+
/**
41+
* Test factory data imported onto the device prior to CP initialize stage.
42+
*/
43+
// clang-format off
44+
#define STRUCT_MANUF_CP_TEST_DATA(field, string) \
45+
field(lot_name, uint32_t) \
46+
field(wafer_number, uint32_t) \
47+
field(wafer_x_coord, uint32_t) \
48+
field(wafer_y_coord, uint32_t)
49+
UJSON_SERDE_STRUCT(ManufCpTestData, \
50+
manuf_cp_test_data_t, \
51+
STRUCT_MANUF_CP_TEST_DATA);
52+
// clang-format on
53+
3154
/**
3255
* Provisioning data imported onto the device in FT during individualization.
3356
*/

sw/device/silicon_creator/manuf/base/BUILD

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ opentitan_binary(
7272
"//sw/device/lib/testing/test_framework:ottf_test_config",
7373
"//sw/device/lib/testing/test_framework:status",
7474
"//sw/device/lib/testing/test_framework:ujson_ottf",
75-
"//sw/device/silicon_creator/manuf/data/ast:fake",
7675
"//sw/device/silicon_creator/manuf/lib:flash_info_fields",
7776
"//sw/device/silicon_creator/manuf/lib:individualize",
7877
"//sw/device/silicon_creator/manuf/lib:otp_fields",
@@ -169,7 +168,7 @@ opentitan_test(
169168
test_cmd = """
170169
--provisioning-sram-elf={sram_cp_provision}
171170
--test-sram-elf={sram_cp_provision_functest}
172-
""" + CP_PROVISIONING_INPUTS,
171+
""",
173172
test_harness = "//sw/host/tests/manuf/cp_provision_functest",
174173
),
175174
)

sw/device/silicon_creator/manuf/base/provisioning_inputs.bzl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,17 @@ EARLGREY_SKUS = {
5858
},
5959
} | EXT_EARLGREY_SKUS
6060

61-
_DEVICE_ID_AND_TEST_TOKENS = """
62-
--device-id="0x11111111_22222222_33333333_44444444_55555555_66666666_77777777_88888888"
61+
_TEST_TOKENS = """
6362
--test-unlock-token="0x11111111_11111111_11111111_11111111"
6463
--test-exit-token="0x11111111_11111111_11111111_11111111"
6564
"""
6665

67-
CP_PROVISIONING_INPUTS = _DEVICE_ID_AND_TEST_TOKENS + """
68-
--manuf-state="0x00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000"
66+
CP_PROVISIONING_INPUTS = _TEST_TOKENS + """
6967
--wafer-auth-secret="0x00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000"
7068
"""
7169

72-
FT_PROVISIONING_INPUTS = _DEVICE_ID_AND_TEST_TOKENS + """
70+
FT_PROVISIONING_INPUTS = _TEST_TOKENS + """
71+
--device-id="0x11111111_22222222_33333333_44444444_55555555_66666666_77777777_88888888"
7372
--target-mission-mode-lc-state="prod"
7473
--rma-unlock-token="0x01234567_89abcdef_01234567_89abcdef"
7574
--rom-ext-measurement="0x11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111"

sw/device/silicon_creator/manuf/base/sram_cp_provision.c

Lines changed: 105 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include "sw/device/lib/testing/test_framework/ottf_test_config.h"
2222
#include "sw/device/lib/testing/test_framework/ujson_ottf.h"
2323
#include "sw/device/silicon_creator/manuf/base/flash_info_permissions.h"
24-
#include "sw/device/silicon_creator/manuf/data/ast/calibration_values.h"
2524
#include "sw/device/silicon_creator/manuf/lib/flash_info_fields.h"
2625
#include "sw/device/silicon_creator/manuf/lib/individualize.h"
2726
#include "sw/device/silicon_creator/manuf/lib/otp_fields.h"
@@ -38,6 +37,8 @@ static dif_pinmux_t pinmux;
3837
static dif_flash_ctrl_state_t flash_ctrl_state;
3938
static dif_lc_ctrl_t lc_ctrl;
4039

40+
static uint32_t ast_cfg_data[kFlashInfoAstCalibrationDataSizeIn32BitWords];
41+
4142
/**
4243
* Initializes all DIF handles used in this SRAM program.
4344
*/
@@ -61,99 +62,106 @@ static void manually_init_ast(uint32_t *data) {
6162
}
6263
}
6364

64-
static status_t flash_info_page_0_erase(void) {
65-
uint32_t byte_address = 0;
66-
// DeviceId and ManufState are located on the same flash info page.
67-
TRY(flash_ctrl_testutils_info_region_setup_properties(
68-
&flash_ctrl_state, kFlashInfoFieldDeviceId.page,
69-
kFlashInfoFieldDeviceId.bank, kFlashInfoFieldDeviceId.partition,
70-
kFlashInfoPage0Permissions, &byte_address));
71-
TRY(flash_ctrl_testutils_erase_page(&flash_ctrl_state, byte_address,
72-
kFlashInfoFieldDeviceId.partition,
73-
kDifFlashCtrlPartitionTypeInfo));
74-
return OK_STATUS();
75-
}
76-
77-
static status_t flash_info_page_0_write(
78-
manuf_cp_provisioning_data_t *provisioning_data) {
79-
uint32_t byte_address = 0;
65+
static status_t flash_info_page_0_read_and_validate(
66+
manuf_cp_provisioning_data_out_t *console_out) {
8067
TRY(flash_ctrl_testutils_info_region_setup_properties(
81-
&flash_ctrl_state, kFlashInfoFieldDeviceId.page,
82-
kFlashInfoFieldDeviceId.bank, kFlashInfoFieldDeviceId.partition,
83-
kFlashInfoPage0Permissions, &byte_address));
84-
85-
// Write DeviceId.
86-
TRY(flash_ctrl_testutils_write(
87-
&flash_ctrl_state, byte_address, kFlashInfoFieldDeviceId.partition,
88-
provisioning_data->device_id, kDifFlashCtrlPartitionTypeInfo,
89-
kHwCfgDeviceIdSizeIn32BitWords));
90-
91-
// Write ManufState (on same page as DeviceId).
92-
TRY(flash_ctrl_testutils_write(
93-
&flash_ctrl_state, byte_address + kFlashInfoFieldManufState.byte_offset,
94-
kFlashInfoFieldManufState.partition, provisioning_data->manuf_state,
95-
kDifFlashCtrlPartitionTypeInfo, kHwCfgManufStateSizeIn32BitWords));
96-
97-
// Write AST calibration values (on same page as DeviceId).
98-
TRY(flash_ctrl_testutils_write(
99-
&flash_ctrl_state,
100-
byte_address + kFlashInfoFieldAstCalibrationData.byte_offset,
101-
kFlashInfoFieldAstCalibrationData.partition, ast_cfg_data,
102-
kDifFlashCtrlPartitionTypeInfo,
68+
&flash_ctrl_state, kFlashInfoFieldCpDeviceId.page,
69+
kFlashInfoFieldCpDeviceId.bank, kFlashInfoFieldCpDeviceId.partition,
70+
kFlashInfoPage0Permissions, /*offset=*/NULL));
71+
72+
// Read (wafer) lot name.
73+
uint32_t lot_name = 0;
74+
static_assert(kFlashInfoFieldLotNameSizeIn32BitWords == 1,
75+
"Lot name should fit in <32bits.");
76+
TRY(manuf_flash_info_field_read(&flash_ctrl_state, kFlashInfoFieldLotName,
77+
&lot_name,
78+
kFlashInfoFieldLotNameSizeIn32BitWords));
79+
80+
// Read wafer number.
81+
uint32_t wafer_number = 0;
82+
static_assert(kFlashInfoFieldWaferNumberSizeIn32BitWords == 1,
83+
"Wafer number should fit in <32bits.");
84+
TRY(manuf_flash_info_field_read(&flash_ctrl_state, kFlashInfoFieldWaferNumber,
85+
&wafer_number,
86+
kFlashInfoFieldWaferNumberSizeIn32BitWords));
87+
88+
// Read wafer X coord.
89+
uint32_t wafer_x_coord = 0;
90+
static_assert(kFlashInfoFieldWaferXCoordSizeIn32BitWords == 1,
91+
"Wafer X coordinate value should fit in <32bits.");
92+
TRY(manuf_flash_info_field_read(&flash_ctrl_state, kFlashInfoFieldWaferXCoord,
93+
&wafer_x_coord,
94+
kFlashInfoFieldWaferXCoordSizeIn32BitWords));
95+
96+
// Read wafer Y coord.
97+
uint32_t wafer_y_coord = 0;
98+
static_assert(kFlashInfoFieldWaferYCoordSizeIn32BitWords == 1,
99+
"Wafer Y coordinate value should fit in <32bits.");
100+
TRY(manuf_flash_info_field_read(&flash_ctrl_state, kFlashInfoFieldWaferYCoord,
101+
&wafer_y_coord,
102+
kFlashInfoFieldWaferYCoordSizeIn32BitWords));
103+
104+
// Read AST calibration values into RAM.
105+
TRY(manuf_flash_info_field_read(
106+
&flash_ctrl_state, kFlashInfoFieldAstCalibrationData, ast_cfg_data,
103107
kFlashInfoAstCalibrationDataSizeIn32BitWords));
104108

105-
return OK_STATUS();
106-
}
109+
// Encode CP device ID.
110+
// HW origin portion of CP device.
111+
// "0x00024001" encodes:
112+
// - a SiliconCreator ID of "0x4001" for "Nuvoton", and
113+
// - a Product ID of "0x0002" for Earlgrey A1 silicon.
114+
console_out->cp_device_id[0] = 0x00024001u;
115+
// Device Identification Number portion of CP device ID.
116+
uint32_t year = (lot_name >> 24) & 0xf;
117+
uint32_t week = (lot_name >> 16) & 0xff;
118+
uint32_t lot_number = lot_name & 0xfff;
119+
console_out->cp_device_id[1] =
120+
(wafer_number << 24) | (lot_number << 12) | (week << 4) | year;
121+
console_out->cp_device_id[2] = (wafer_y_coord << 12) | wafer_x_coord;
122+
// Reserved word; set to 0.
123+
console_out->cp_device_id[3] = 0;
124+
125+
// Write CP device ID.
126+
TRY(manuf_flash_info_field_write(&flash_ctrl_state, kFlashInfoFieldCpDeviceId,
127+
console_out->cp_device_id,
128+
kFlashInfoFieldCpDeviceIdSizeIn32BitWords,
129+
/*erase_page_before_write=*/false));
107130

108-
static status_t wafer_auth_secret_flash_info_page_erase(void) {
109-
uint32_t byte_address = 0;
110-
TRY(flash_ctrl_testutils_info_region_setup_properties(
111-
&flash_ctrl_state, kFlashInfoFieldWaferAuthSecret.page,
112-
kFlashInfoFieldWaferAuthSecret.bank,
113-
kFlashInfoFieldWaferAuthSecret.partition, kFlashInfoPage3WritePermissions,
114-
&byte_address));
115-
TRY(flash_ctrl_testutils_erase_page(&flash_ctrl_state, byte_address,
116-
kFlashInfoFieldWaferAuthSecret.partition,
117-
kDifFlashCtrlPartitionTypeInfo));
118131
return OK_STATUS();
119132
}
120133

121134
static status_t wafer_auth_secret_flash_info_page_write(
122-
manuf_cp_provisioning_data_t *provisioning_data) {
135+
manuf_cp_provisioning_data_t *console_in) {
123136
uint32_t byte_address = 0;
124137
TRY(flash_ctrl_testutils_info_region_setup_properties(
125138
&flash_ctrl_state, kFlashInfoFieldWaferAuthSecret.page,
126139
kFlashInfoFieldWaferAuthSecret.bank,
127140
kFlashInfoFieldWaferAuthSecret.partition, kFlashInfoPage3WritePermissions,
128141
&byte_address));
129-
TRY(flash_ctrl_testutils_write(
130-
&flash_ctrl_state, byte_address, kFlashInfoFieldWaferAuthSecret.partition,
131-
provisioning_data->manuf_state, kDifFlashCtrlPartitionTypeInfo,
132-
kFlashInfoWaferAuthSecretSizeIn32BitWords));
142+
TRY(manuf_flash_info_field_write(
143+
&flash_ctrl_state, kFlashInfoFieldWaferAuthSecret,
144+
console_in->wafer_auth_secret,
145+
kFlashInfoFieldWaferAuthSecretSizeIn32BitWords,
146+
/*erase_page_before_write=*/true));
133147
return OK_STATUS();
134148
}
135149

136150
static status_t print_inputs_to_console(
137-
manuf_cp_provisioning_data_t *provisioning_data) {
151+
manuf_cp_provisioning_data_t *console_in) {
138152
uint32_t high;
139153
uint32_t low;
140154

141-
LOG_INFO("Device ID:");
142-
for (size_t i = 0; i < kHwCfgDeviceIdSizeIn32BitWords; ++i) {
143-
LOG_INFO("0x%08x", provisioning_data->device_id[i]);
144-
}
145155
LOG_INFO("Test Unlock Token Hash:");
146-
for (size_t i = 0; i < ARRAYSIZE(provisioning_data->test_unlock_token_hash);
147-
++i) {
148-
high = provisioning_data->test_unlock_token_hash[i] >> 32;
149-
low = provisioning_data->test_unlock_token_hash[i] & 0xffffffff;
156+
for (size_t i = 0; i < ARRAYSIZE(console_in->test_unlock_token_hash); ++i) {
157+
high = console_in->test_unlock_token_hash[i] >> 32;
158+
low = console_in->test_unlock_token_hash[i] & 0xffffffff;
150159
LOG_INFO("0x%08x%08x", high, low);
151160
}
152161
LOG_INFO("Test Exit Token Hash:");
153-
for (size_t i = 0; i < ARRAYSIZE(provisioning_data->test_exit_token_hash);
154-
++i) {
155-
high = provisioning_data->test_exit_token_hash[i] >> 32;
156-
low = provisioning_data->test_exit_token_hash[i] & 0xffffffff;
162+
for (size_t i = 0; i < ARRAYSIZE(console_in->test_exit_token_hash); ++i) {
163+
high = console_in->test_exit_token_hash[i] >> 32;
164+
low = console_in->test_exit_token_hash[i] & 0xffffffff;
157165
LOG_INFO("0x%08x%08x", high, low);
158166
}
159167
return OK_STATUS();
@@ -162,33 +170,46 @@ static status_t print_inputs_to_console(
162170
/**
163171
* Provision flash info pages 0 and 3, and OTP Secret0 partition.
164172
*/
165-
static status_t provision(ujson_t *uj) {
173+
static status_t provision(ujson_t *uj,
174+
manuf_cp_provisioning_data_out_t *console_out) {
175+
// Wait for input console data.
166176
LOG_INFO("Waiting for CP provisioning data ...");
167-
manuf_cp_provisioning_data_t provisioning_data;
168-
TRY(ujson_deserialize_manuf_cp_provisioning_data_t(uj, &provisioning_data));
169-
TRY(print_inputs_to_console(&provisioning_data));
170-
TRY(flash_ctrl_testutils_wait_for_init(&flash_ctrl_state));
171-
TRY(flash_info_page_0_erase());
172-
TRY(wafer_auth_secret_flash_info_page_erase());
173-
TRY(flash_info_page_0_write(&provisioning_data));
174-
TRY(wafer_auth_secret_flash_info_page_write(&provisioning_data));
175-
TRY(manuf_individualize_device_secret0(&lc_ctrl, &otp_ctrl,
176-
&provisioning_data));
177-
LOG_INFO("CP provisioning done.");
177+
manuf_cp_provisioning_data_t console_in;
178+
TRY(ujson_deserialize_manuf_cp_provisioning_data_t(uj, &console_in));
179+
TRY(print_inputs_to_console(&console_in));
180+
181+
// Provision flash info page 3 (wafer authentication secret).
182+
TRY(wafer_auth_secret_flash_info_page_write(&console_in));
183+
184+
// Burn test tokens into OTP.
185+
TRY(manuf_individualize_device_secret0(&lc_ctrl, &otp_ctrl, &console_in));
186+
187+
// Send data back to host.
188+
LOG_INFO("Exporting CP device ID ...");
189+
RESP_OK(ujson_serialize_manuf_cp_provisioning_data_out_t, uj, console_out);
190+
178191
return OK_STATUS();
179192
}
180193

181194
bool test_main(void) {
182-
// Initialize AST, DIF handles, pinmux, and UART.
183-
manually_init_ast(ast_cfg_data);
195+
// Initialize DIF handles, pinmux, and console.
184196
CHECK_STATUS_OK(peripheral_handles_init());
185197
pinmux_testutils_init(&pinmux);
186198
ottf_console_init();
187199
ujson_t uj = ujson_ottf_console();
200+
201+
// Extract factory data from flash info page 0.
202+
manuf_cp_provisioning_data_out_t console_out;
203+
CHECK_STATUS_OK(flash_ctrl_testutils_wait_for_init(&flash_ctrl_state));
204+
CHECK_STATUS_OK(flash_info_page_0_read_and_validate(&console_out));
205+
206+
// Initialize AST.
207+
manually_init_ast(ast_cfg_data);
188208
LOG_INFO("AST manually configured.");
189209

190210
// Perform CP provisioning operations.
191-
CHECK_STATUS_OK(provision(&uj));
211+
CHECK_STATUS_OK(provision(&uj, &console_out));
192212

213+
LOG_INFO("CP provisioning done.");
193214
return true;
194215
}

0 commit comments

Comments
 (0)