Skip to content

Commit b57a6e4

Browse files
timothytrippelpamaury
authored andcommitted
[perso] cleanup SPI transactions during personalization
This updates the personalization firmware and FT test harness to make use of the GPIO TX indicator pin to eliminate the host driven polling of the SPI flash buffer. This makes the wavesforms cleaner to simplify ATE integration. Signed-off-by: Tim Trippel <[email protected]> (cherry picked from commit 5da7c4a)
1 parent de9db25 commit b57a6e4

File tree

4 files changed

+45
-50
lines changed

4 files changed

+45
-50
lines changed

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

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "sw/device/lib/dif/dif_pinmux.h"
1515
#include "sw/device/lib/dif/dif_rstmgr.h"
1616
#include "sw/device/lib/runtime/log.h"
17+
#include "sw/device/lib/runtime/print.h"
1718
#include "sw/device/lib/testing/flash_ctrl_testutils.h"
1819
#include "sw/device/lib/testing/json/provisioning_data.h"
1920
#include "sw/device/lib/testing/lc_ctrl_testutils.h"
@@ -60,11 +61,6 @@
6061
#include "hw/top/otp_ctrl_regs.h" // Generated.
6162
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
6263

63-
OTTF_DEFINE_TEST_CONFIG(.console.type = kOttfConsoleSpiDevice,
64-
.console.base_addr = TOP_EARLGREY_SPI_DEVICE_BASE_ADDR,
65-
.console.test_may_clobber = false,
66-
.silence_console_prints = true);
67-
6864
enum {
6965
/**
7066
* Size of the largest OTP partition to be measured.
@@ -109,6 +105,15 @@ static const dif_gpio_pin_t kGpioPinTestError = 2;
109105
static const dif_gpio_pin_t kGpioPinSpiConsoleTxReady = 3;
110106
static const dif_gpio_pin_t kGpioPinSpiConsoleRxReady = 4;
111107

108+
OTTF_DEFINE_TEST_CONFIG(
109+
.console.type = kOttfConsoleSpiDevice,
110+
.console.base_addr = TOP_EARLGREY_SPI_DEVICE_BASE_ADDR,
111+
.console.test_may_clobber = false, .console.putbuf_buffered = true,
112+
.silence_console_prints = true, .console_tx_indicator.enable = true,
113+
.console_tx_indicator.spi_console_tx_ready_mio = kDtPadIoa5,
114+
.console_tx_indicator.spi_console_tx_ready_gpio =
115+
kGpioPinSpiConsoleTxReady);
116+
112117
/**
113118
* Keymgr binding values.
114119
*/
@@ -198,7 +203,7 @@ OT_WEAK rom_error_t sku_creator_owner_init(boot_data_t *bootdata) {
198203

199204
static void log_self_hash(void) {
200205
// clang-format off
201-
LOG_INFO("Personalization Firmware Hash: 0x%08x%08x%08x%08x%08x%08x%08x%08x",
206+
base_printf("Personalization Firmware Hash: 0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
202207
boot_measurements.rom_ext.data[7],
203208
boot_measurements.rom_ext.data[6],
204209
boot_measurements.rom_ext.data[5],
@@ -364,17 +369,17 @@ static status_t personalize_otp_and_flash_secrets(ujson_t *uj) {
364369
TRY(manuf_individualize_device_field_cfg(
365370
&otp_ctrl,
366371
OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_DATA_DEFAULT_CFG_OFFSET));
367-
LOG_INFO("Bootstrap requested.");
372+
base_printf("Bootstrap requested.\n");
368373
wait_for_interrupt();
369374
}
370375

371376
// Provision OTP Secret2 partition and flash info pages 1, 2, and 4 (keymgr
372377
// and DICE keygen seeds).
373378
if (!status_ok(manuf_personalize_device_secrets_check(&otp_ctrl))) {
379+
log_self_hash();
374380
lc_token_hash_t token_hash;
375-
// Wait for host the host generated RMA unlock token hash to arrive over the
376-
// console.
377-
LOG_INFO("Waiting For RMA Unlock Token Hash ...");
381+
// Wait for the host to send the RMA unlock token hash over the console.
382+
base_printf("Waiting For RMA Unlock Token Hash ...\n");
378383
TRY(dif_gpio_write(&gpio, kGpioPinSpiConsoleRxReady, true));
379384
CHECK_STATUS_OK(
380385
UJSON_WITH_CRC(ujson_deserialize_lc_token_hash_t, uj, &token_hash));
@@ -523,7 +528,7 @@ static status_t personalize_gen_dice_certificates(ujson_t *uj) {
523528
// Retrieve certificate provisioning data.
524529
// DO NOT CHANGE THE BELOW STRING without modifying the host code in
525530
// sw/host/provisioning/ft_lib/src/lib.rs
526-
LOG_INFO("Waiting for certificate inputs ...");
531+
base_printf("Waiting for certificate inputs ...\n");
527532
TRY(dif_gpio_write(&gpio, kGpioPinSpiConsoleRxReady, true));
528533
TRY(ujson_deserialize_manuf_certgen_inputs_t(uj, &certgen_inputs));
529534
TRY(dif_gpio_write(&gpio, kGpioPinSpiConsoleRxReady, false));
@@ -590,10 +595,10 @@ static status_t personalize_gen_dice_certificates(ujson_t *uj) {
590595
"UDS",
591596
/*needs_endorsement=*/kDiceCertFormat == kDiceCertFormatX509TcbInfo,
592597
kDiceCertFormat, all_certs, curr_cert_size, &perso_blob_to_host));
593-
LOG_INFO("Generated UDS certificate.");
594598

599+
// After we have cranked the keymgr to the CreatorRootKey (UDS) stage, we now
600+
// can initialize and seal the ownership block.
595601
ownership_seal_init();
596-
LOG_INFO("Initialized ownership sealing in UDS state.");
597602

598603
// Generate CDI_0 keys and cert.
599604
curr_cert_size = kCdi0MaxCertSizeBytes;
@@ -611,7 +616,6 @@ static status_t personalize_gen_dice_certificates(ujson_t *uj) {
611616
TRY(perso_tlv_push_cert_to_perso_blob("CDI_0", /*needs_endorsement=*/false,
612617
kDiceCertFormat, all_certs,
613618
curr_cert_size, &perso_blob_to_host));
614-
LOG_INFO("Generated CDI_0 certificate.");
615619

616620
// Generate CDI_1 keys and cert.
617621
curr_cert_size = kCdi1MaxCertSizeBytes;
@@ -630,7 +634,6 @@ static status_t personalize_gen_dice_certificates(ujson_t *uj) {
630634
TRY(perso_tlv_push_cert_to_perso_blob("CDI_1", /*needs_endorsement=*/false,
631635
kDiceCertFormat, all_certs,
632636
curr_cert_size, &perso_blob_to_host));
633-
LOG_INFO("Generated CDI_1 certificate.");
634637

635638
return OK_STATUS();
636639
}
@@ -833,7 +836,6 @@ static status_t extract_next_cert(uint8_t **dest, size_t *free_room) {
833836
// Copy the certificate object to the destination buffer.
834837
uint8_t *dest_p = *dest;
835838
memcpy(dest_p, block.obj_p, block.obj_size);
836-
LOG_INFO("Copied %s certificate", block.name);
837839

838840
// Advance destination buffer pointer and reduce free space counter.
839841
*dest = dest_p + block.obj_size;
@@ -885,15 +887,13 @@ static status_t personalize_endorse_certificates(ujson_t *uj) {
885887
// Export the certificates to the provisioning appliance.
886888
// DO NOT CHANGE THE BELOW STRING without modifying the host code in
887889
// sw/host/provisioning/ft_lib/src/lib.rs
888-
LOG_INFO("Exporting TBS certificates ...");
889-
TRY(dif_gpio_write(&gpio, kGpioPinSpiConsoleTxReady, true));
890+
base_printf("Exporting TBS certificates ...\n");
890891
RESP_OK(ujson_serialize_perso_blob_t, uj, &perso_blob_to_host);
891-
TRY(dif_gpio_write(&gpio, kGpioPinSpiConsoleTxReady, false));
892892

893893
// Import endorsed certificates from the provisioning appliance.
894894
// DO NOT CHANGE THE BELOW STRING without modifying the host code in
895895
// sw/host/provisioning/ft_lib/src/lib.rs
896-
LOG_INFO("Importing endorsed certificates ...");
896+
base_printf("Importing endorsed certificates ...\n");
897897
TRY(dif_gpio_write(&gpio, kGpioPinSpiConsoleRxReady, true));
898898
TRY(ujson_deserialize_perso_blob_t(uj, &perso_blob_from_host));
899899
TRY(dif_gpio_write(&gpio, kGpioPinSpiConsoleRxReady, false));
@@ -946,7 +946,6 @@ static status_t personalize_endorse_certificates(ujson_t *uj) {
946946
return RESOURCE_EXHAUSTED();
947947

948948
memcpy(next_cert, block.obj_p, block.obj_size);
949-
LOG_INFO("Copied %s certificate", block.name);
950949
next_cert += block.obj_size;
951950
free_room -= block.obj_size;
952951
}
@@ -983,8 +982,6 @@ static status_t personalize_endorse_certificates(ujson_t *uj) {
983982
TRY(write_cert_to_flash_info_page(&curr_layout, &block, next_cert,
984983
page_offset, cert_size_bytes_ru,
985984
cert_size_words));
986-
LOG_INFO("Imported %s %s certificate.", curr_layout.group_name,
987-
block.name);
988985
page_offset += cert_size_bytes_ru;
989986
next_cert += block.obj_size;
990987

@@ -995,7 +992,7 @@ static status_t personalize_endorse_certificates(ujson_t *uj) {
995992

996993
// DO NOT CHANGE THE BELOW STRING without modifying the host code in
997994
// sw/host/provisioning/ft_lib/src/lib.rs
998-
LOG_INFO("Finished importing certificates.");
995+
base_printf("Finished importing certificates.\n");
999996

1000997
return OK_STATUS();
1001998
}
@@ -1136,14 +1133,12 @@ static status_t provision(ujson_t *uj) {
11361133
.cert_flash_layout = cert_flash_layout};
11371134
TRY(personalize_extension_post_cert_endorse(&post_endorse));
11381135

1139-
// Log the hash of all perso objects to the host and console.
1136+
// Check the hash of all perso objects with the host to confirm integrity of
1137+
// the transmission / provisioning operations.
11401138
serdes_sha256_hash_t hash;
11411139
hmac_sha256_process();
11421140
hmac_sha256_final((hmac_digest_t *)&hash);
11431141
TRY(send_final_hash(uj, &hash));
1144-
LOG_INFO("SHA256 hash of all perso objects: %08x%08x%08x%08x%08x%08x%08x%08x",
1145-
hash.data[7], hash.data[6], hash.data[5], hash.data[4], hash.data[3],
1146-
hash.data[2], hash.data[1], hash.data[0]);
11471142

11481143
// Complete any remaining OTP programming.
11491144
TRY(finalize_otp_partitions());
@@ -1164,8 +1159,6 @@ bool test_main(void) {
11641159
CHECK_STATUS_OK(entropy_complex_init());
11651160
ujson_t uj = ujson_ottf_console();
11661161

1167-
log_self_hash();
1168-
11691162
// Read the reset reason directly from the RSTMGR.
11701163
// This is needed to clear the reset reason before the first call to
11711164
// `personalize_otp_and_flash_secrets()`, which will reset the device.
@@ -1184,7 +1177,7 @@ bool test_main(void) {
11841177

11851178
// DO NOT CHANGE THE BELOW STRING without modifying the host code in
11861179
// sw/host/provisioning/ft_lib/src/lib.rs
1187-
LOG_INFO("Personalization done.");
1180+
base_printf("Personalization done.\n");
11881181

11891182
return true;
11901183
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
#include "perso_tlv_data.h"
66
#include "sw/device/lib/dif/dif_flash_ctrl.h"
7-
#include "sw/device/lib/runtime/log.h"
87
#include "sw/device/lib/testing/test_framework/status.h"
98
#include "sw/device/lib/testing/test_framework/ujson_ottf.h"
109
#include "sw/device/silicon_creator/lib/attestation.h"
@@ -88,7 +87,6 @@ static status_t personalize_gen_tpm_ek_certificate(
8887

8988
status_t personalize_extension_pre_cert_endorse(
9089
personalize_extension_pre_endorse_t *pre_params) {
91-
LOG_INFO("Running TPM perso extension ...");
9290
TRY(peripheral_handles_init());
9391
TRY(config_and_erase_tpm_certificate_flash_pages());
9492
TRY(personalize_gen_tpm_ek_certificate(pre_params->certgen_inputs,

sw/host/provisioning/ft/src/main.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use ft_lib::{
2222
};
2323
use opentitanlib::backend;
2424
use opentitanlib::console::spi::SpiConsoleDevice;
25+
use opentitanlib::io::gpio::{PinMode, PullMode};
2526
use opentitanlib::test_utils::init::InitializeTest;
2627
use opentitanlib::test_utils::lc::{read_device_id, read_lc_state};
2728
use opentitanlib::test_utils::load_sram_program::SramProgramParams;
@@ -125,7 +126,10 @@ fn main() -> Result<()> {
125126
let transport = backend::create(&opts.init.backend_opts)?;
126127
transport.apply_default_configuration(None)?;
127128
let spi = transport.spi(&opts.console_spi)?;
128-
let spi_console_device = SpiConsoleDevice::new(&*spi, None)?;
129+
let device_console_tx_ready_pin = &transport.gpio_pin(&opts.console_tx_indicator_pin)?;
130+
device_console_tx_ready_pin.set_mode(PinMode::Input)?;
131+
device_console_tx_ready_pin.set_pull_mode(PullMode::None)?;
132+
let spi_console = SpiConsoleDevice::new(&*spi, Some(device_console_tx_ready_pin))?;
129133
InitializeTest::print_result(
130134
"load_bitstream",
131135
opts.init.load_bitstream.init(&transport).map(|_| None),
@@ -236,8 +240,7 @@ fn main() -> Result<()> {
236240
&opts.init.jtag_params,
237241
&opts.sram_program,
238242
&ft_individualize_data_in,
239-
&opts.console_spi,
240-
&opts.console_tx_indicator_pin,
243+
&spi_console,
241244
opts.timeout,
242245
&mut ujson_payloads,
243246
)?;
@@ -273,7 +276,7 @@ fn main() -> Result<()> {
273276
ca_keys,
274277
&_perso_certgen_inputs,
275278
opts.second_bootstrap,
276-
&spi_console_device,
279+
&spi_console,
277280
&mut ujson_payloads,
278281
opts.timeout,
279282
&mut response,

sw/host/provisioning/ft_lib/src/lib.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use ft_ext_lib::ft_ext;
2222
use opentitanlib::app::{TransportWrapper, UartRx};
2323
use opentitanlib::console::spi::SpiConsoleDevice;
2424
use opentitanlib::io::console::ConsoleError;
25-
use opentitanlib::io::gpio::{PinMode, PullMode};
2625
use opentitanlib::io::jtag::{JtagParams, JtagTap, RiscvGpr, RiscvReg};
2726
use opentitanlib::test_utils::init::InitializeTest;
2827
use opentitanlib::test_utils::lc_transition::trigger_lc_transition;
@@ -89,17 +88,11 @@ pub fn run_sram_ft_individualize(
8988
jtag_params: &JtagParams,
9089
sram_program: &SramProgramParams,
9190
ft_individualize_data_in: &ManufFtIndividualizeData,
92-
console_spi: &str,
93-
console_tx_indicator_pin: &str,
91+
spi_console: &SpiConsoleDevice,
9492
timeout: Duration,
9593
ujson_payloads: &mut UjsonPayloads,
9694
) -> Result<()> {
97-
// Setup the SPI console with the GPIO TX indicator pin.
98-
let spi = transport.spi(console_spi)?;
99-
let device_console_tx_ready_pin = &transport.gpio_pin(console_tx_indicator_pin)?;
100-
device_console_tx_ready_pin.set_mode(PinMode::Input)?;
101-
device_console_tx_ready_pin.set_pull_mode(PullMode::None)?;
102-
let spi_console = SpiConsoleDevice::new(&*spi, Some(device_console_tx_ready_pin))?;
95+
// Reset the SPI console before loading the target firmware.
10396
spi_console.reset_frame_counter();
10497

10598
// Set CPU TAP straps, reset, and connect to the JTAG interface.
@@ -125,15 +118,15 @@ pub fn run_sram_ft_individualize(
125118
{
126119
// Wait for SRAM program to complete execution.
127120
let _ = UartConsole::wait_for(
128-
&spi_console,
121+
spi_console,
129122
r"Waiting for FT SRAM provisioning data ...",
130123
timeout,
131124
)?;
132125

133126
// Inject provisioning data into the device.
134127
ujson_payloads.dut_in.insert(
135128
"FT_INDIVIDUALIZE_DATA_IN".to_string(),
136-
ft_individualize_data_in.send(&spi_console)?,
129+
ft_individualize_data_in.send(spi_console)?,
137130
);
138131
}
139132

@@ -358,7 +351,7 @@ fn provision_certificates(
358351
// Wait until the device exports the TBS certificates.
359352
let t0 = Instant::now();
360353
let _ = UartConsole::wait_for(spi_console, r"Exporting TBS certificates ...", timeout)?;
361-
let perso_blob = PersoBlob::recv(spi_console, timeout, true)?;
354+
let perso_blob = PersoBlob::recv(spi_console, timeout, /*quite=*/ true)?;
362355
response.stats.log_elapsed_time("perso-tbs-export", t0);
363356

364357
// Extract certificate byte vectors, endorse TBS certs, and ensure they parse with OpenSSL.
@@ -387,7 +380,6 @@ fn provision_certificates(
387380

388381
let t0 = Instant::now();
389382
for _ in 0..perso_blob.num_objs {
390-
log::info!("Processing next object");
391383
let header = get_obj_header(&perso_blob.body[start..])?;
392384
let obj_header_size = std::mem::size_of::<ObjHeaderType>();
393385

@@ -594,8 +586,10 @@ pub fn run_ft_personalize(
594586
response: &mut PersonalizeResponse,
595587
) -> Result<()> {
596588
// Bootstrap only personalization binary into ROM_EXT slot A in flash.
589+
spi_console.reset_frame_counter();
597590
let t0 = Instant::now();
598591
init.bootstrap.init(transport)?;
592+
spi_console.reset_frame_counter();
599593
response.stats.log_elapsed_time("first-bootstrap", t0);
600594

601595
// Bootstrap personalization + ROM_EXT + Owner FW binaries into flash, since
@@ -606,14 +600,21 @@ pub fn run_ft_personalize(
606600

607601
let t0 = Instant::now();
608602
init.bootstrap.load(transport, &second_bootstrap)?;
603+
spi_console.reset_frame_counter();
609604
response.stats.log_elapsed_time("second-bootstrap", t0);
610605

606+
let _ = UartConsole::wait_for(spi_console, r"Personalization Firmware Hash:", timeout)?;
607+
611608
// Send RMA unlock token digest to device.
612609
let second_t0 = Instant::now();
613610
let t0 = second_t0;
614611
send_rma_unlock_token_hash(rma_unlock_token, timeout, spi_console, ujson_payloads)?;
615612
response.stats.log_elapsed_time("send-rma-unlock-token", t0);
616613

614+
// After the OTP SECRET2 partition is programmed, the chip performs a SW
615+
// reset, so we need to reset the SPI console frame counter.
616+
spi_console.reset_frame_counter();
617+
617618
// Provision all device certificates.
618619
let t0 = Instant::now();
619620
provision_certificates(

0 commit comments

Comments
 (0)