Skip to content

Commit

Permalink
Implement API for requesting IDEVID CSR. (#1583)
Browse files Browse the repository at this point in the history
  • Loading branch information
rusty1968 authored Jul 15, 2024
1 parent 66b1741 commit 8a429a5
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 13 deletions.
29 changes: 29 additions & 0 deletions libcaliptra/examples/generic/idev_csr_array.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Licensed under the Apache-2.0 license
// Generated from test/tests/caliptra_integration_tests/smoke_testdata/idev_csr.der

#include <stdint.h>
#define IDEV_CSR_LEN 443
uint8_t idev_csr_bytes[IDEV_CSR_LEN] = {
48, 130, 1, 183, 48, 130, 1, 62, 2, 1, 0, 48, 105, 49, 28, 48, 26, 6,
3, 85, 4, 3, 12, 19, 67, 97, 108, 105, 112, 116, 114, 97, 32, 49, 46,
48, 32, 73, 68, 101, 118, 73, 68, 49, 73, 48, 71, 6, 3, 85, 4, 5, 19,
64, 56, 69, 51, 67, 49, 65, 48, 53, 56, 70, 55, 48, 52, 65, 49, 49, 56,
50, 49, 70, 55, 66, 52, 56, 68, 51, 52, 48, 65, 69, 70, 57, 57, 68, 68,
65, 66, 65, 68, 67, 49, 48, 57, 48, 68, 55, 52, 68, 48, 53, 55, 70, 69,
67, 67, 70, 55, 51, 50, 57, 52, 69, 68, 54, 48, 118, 48, 16, 6, 7, 42, 134,
72, 206, 61, 2, 1, 6, 5, 43, 129, 4, 0, 34, 3, 98, 0, 4, 215, 180, 133, 242,
159, 17, 92, 28, 179, 4, 107, 132, 11, 69, 137, 181, 120, 98, 245, 235, 249,
157, 132, 111, 190, 63, 210, 209, 67, 150, 245, 246, 154, 55, 154, 89, 172,
197, 162, 174, 200, 54, 158, 203, 101, 144, 68, 55, 180, 188, 124, 217, 165,
168, 64, 60, 91, 177, 145, 82, 35, 170, 134, 190, 242, 193, 188, 146, 20, 95, 252,
39, 193, 37, 198, 219, 250, 212, 156, 145, 232, 72, 197, 68, 172, 127, 14, 149, 214,
205, 140, 172, 251, 146, 63, 166, 160, 86, 48, 84, 6, 9, 42, 134, 72, 134, 247, 13,
1, 9, 14, 49, 71, 48, 69, 48, 18, 6, 3, 85, 29, 19, 1, 1, 255, 4, 8, 48, 6, 1, 1, 255, 2
, 1, 5, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 2, 4, 48, 31, 6, 6, 103, 129, 5, 5,
4, 4, 4, 21, 48, 19, 4, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 10, 6, 8, 42,
134, 72, 206, 61, 4, 3, 3, 3, 103, 0, 48, 100, 2, 48, 124, 116, 253, 40, 206, 15, 249, 233, 218, 239
,144, 132, 165, 175, 192, 66, 209, 226, 8, 132, 103, 214, 106, 232, 220, 70, 204, 2, 29, 128, 218, 55, 80,
145, 238, 117, 9, 237, 21, 85, 15, 49, 21, 35, 201, 187, 230, 225, 2, 48, 36, 253, 27, 91, 71, 204, 20, 74, 102,
165, 187, 231, 4, 116, 240, 33, 54, 55, 244, 158, 93, 205, 161, 66, 191, 246, 130, 92, 161, 244, 81, 67, 226, 151,
252, 149, 206, 86, 177, 103, 225, 191, 225, 38, 58, 206, 161, 243,
};
123 changes: 114 additions & 9 deletions libcaliptra/examples/generic/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "caliptra_api.h"
#include "caliptra_image.h"
#include "idev_csr_array.h"

// Arbitrary example only - values must be customized/tuned for the SoC
static const uint64_t wdt_timeout = 0xA0000000; // approximately 5s for 500MHz clock
Expand All @@ -23,6 +24,11 @@ static const uint32_t apb_pauser = 0x1;
// Exists for testbench only - not part of interface for actual implementation
extern void testbench_reinit(void);

#ifdef ENABLE_DEBUG
// Exists for testbench only - not part of interface for actual implementation
static int dump_array_to_file(struct caliptra_buffer* buffer, const char *filename);
#endif

struct caliptra_buffer image_bundle;
struct caliptra_fuses fuses = {0};

Expand All @@ -36,7 +42,25 @@ static const uint32_t default_uds_seed[] = { 0x00010203, 0x04050607, 0x08090a0b,
static const uint32_t default_field_entropy[] = { 0x80818283, 0x84858687, 0x88898a8b, 0x8c8d8e8f,
0x90919293, 0x94959697, 0x98999a9b, 0x9c9d9e9f };

static int set_fuses()
/*
* caliptra_csr_is_ready
*
* Waits forever for the CSR to be ready
*
* @return bool True if ready, false otherwise
*/
static void caliptra_wait_for_csr_ready(void)
{
while (true)
{
if (caliptra_is_idevid_csr_ready()) {
break;
}
caliptra_wait();
}
}

static int set_fuses(bool manuf_req_csr)
{
int status;

Expand Down Expand Up @@ -66,13 +90,18 @@ void dump_caliptra_error_codes()
printf("Caliptra FW error fatal code is 0x%x\n", caliptra_read_fw_fatal_error());
}

int boot_to_ready_for_fw()
int boot_to_ready_for_fw(bool req_idev_csr)
{
int status;

// Initialize FSM GO
caliptra_bootfsm_go();

// Request CSR if needed
if (req_idev_csr)
{
caliptra_req_idev_csr_start();
}
caliptra_set_wdt_timeout(wdt_timeout);

caliptra_configure_itrng_entropy(itrng_entropy_low_threshold,
Expand All @@ -93,18 +122,22 @@ int boot_to_ready_for_fw()
return status;
}

set_fuses();

// Wait until ready for FW
caliptra_ready_for_firmware();
set_fuses(req_idev_csr);

if (req_idev_csr == false)
{
// Wait until ready for FW
caliptra_ready_for_firmware();
}


return status;
}

int legacy_boot_test()
{
int failure = 0;
int status = boot_to_ready_for_fw();
int status = boot_to_ready_for_fw(false);

if (status){
failure = 1;
Expand Down Expand Up @@ -173,7 +206,7 @@ int legacy_boot_test()
int rom_test_all_commands()
{
int failure = 0;
int status = boot_to_ready_for_fw();
int status = boot_to_ready_for_fw(false);

if (status){
dump_caliptra_error_codes();
Expand Down Expand Up @@ -263,7 +296,7 @@ int rt_test_all_commands()
{
int failure = 0;
uint32_t non_fatal_error;
int status = boot_to_ready_for_fw();
int status = boot_to_ready_for_fw(false);

if (status){
failure = 1;
Expand Down Expand Up @@ -609,6 +642,55 @@ int rt_test_all_commands()
return failure;
}

int rom_test_devid_csr()
{
int failure = 0;

struct caliptra_buffer caliptra_idevid_csr_buf = {0};
caliptra_idevid_csr_buf.len = IDEV_CSR_LEN;
// Allocte a buffer to hold the IDEV CSR using malloc
caliptra_idevid_csr_buf.data = malloc(caliptra_idevid_csr_buf.len);

// Check if the buffer was allocated successfully
if (caliptra_idevid_csr_buf.data == NULL) {
printf("Failed to allocate memory for IDEV CSR\n");
return 1;
}

bool request_csr = true;
int status = boot_to_ready_for_fw(request_csr);

if (status){
dump_caliptra_error_codes();
failure = 1;
}

caliptra_wait_for_csr_ready();


int ret;
// Retrieve the IDEV CSR
if ((ret = caliptra_retrieve_idevid_csr(&caliptra_idevid_csr_buf)) != NO_ERROR) {
printf("Failed to retrieve IDEV CSR\n");
printf("Error is 0x%x\n", ret);
failure = 1;
} else {
printf("IDEV CSR retrieved\n");
}

// Compare the retrieved IDEV CSR with the expected IDEV CSR
if (memcmp(caliptra_idevid_csr_buf.data, idev_csr_bytes, caliptra_idevid_csr_buf.len) != 0) {
printf("IDEV CSR does not match\n");
#ifdef ENABLE_DEBUG
dump_array_to_file(&caliptra_idevid_csr_buf, "retrieved.bin");
#endif
failure = 1;
} else {
printf("IDEV CSR matches\n");
}

return failure;
}

// Test infrastructure

Expand All @@ -630,13 +712,35 @@ void run_test( int func(void), char* test_name)
global_test_result |= result;
}

#ifdef ENABLE_DEBUG
static int dump_array_to_file(struct caliptra_buffer* buffer, const char *filename) {
FILE *file = fopen(filename, "wb"); // Open the file in binary write mode
if (!file) {
perror("Failed to open file");
return -1; // Return an error code if file opening fails
}

// Write the array to the file
size_t written = fwrite(buffer->data, sizeof(uint8_t), buffer->len, file);
if (written < IDEV_CSR_LEN) {
perror("Failed to write the full array to file");
fclose(file);
return -2; // Return an error code if writing fails
}

fclose(file); // Close the file
return 0; // Success
}
#endif

int main(int argc, char *argv[])
{
global_test_result = 0;

run_test(legacy_boot_test, "Legacy boot test");
run_test(rom_test_all_commands, "Test all ROM commands");
run_test(rt_test_all_commands, "Test all Runtime commmands");
run_test(rom_test_devid_csr, "Test IDEV CSR GEN");

if (global_test_result) {
printf("\t\tlibcaliptra test failures reported\n");
Expand All @@ -646,3 +750,4 @@ int main(int argc, char *argv[])

return global_test_result;
}

9 changes: 9 additions & 0 deletions libcaliptra/inc/caliptra_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,13 @@ int caliptra_shutdown(bool async);
// Capabilities
int caliptra_capabilities(struct caliptra_capabilities_resp *resp, bool async);

// Query if IDevID CSR is ready.
bool caliptra_is_idevid_csr_ready();

int caliptra_retrieve_idevid_csr(struct caliptra_buffer* caliptra_idevid_csr);

void caliptra_req_idev_csr_start();

// Clear IDEV CSR request.
void caliptra_req_idev_csr_complete();

3 changes: 3 additions & 0 deletions libcaliptra/inc/caliptra_enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ enum libcaliptra_error {
MBX_RESP_NO_HEADER = 0x306,
MBX_RESP_CHKSUM_INVALID = 0x307,
MBX_RESP_FIPS_NOT_APPROVED = 0x308,

// MFG
IDEV_CSR_NOT_READY = 0x400,
};

/**
Expand Down
1 change: 0 additions & 1 deletion libcaliptra/inc/caliptra_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,4 +390,3 @@ struct caliptra_invoke_dpe_resp {
uint8_t data[sizeof(struct dpe_certify_key_response)];
};
};

74 changes: 73 additions & 1 deletion libcaliptra/src/caliptra_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ int caliptra_bootfsm_go()
return 0;
}


/**
* caliptra_set_wdt_timeout
*
Expand Down Expand Up @@ -269,6 +270,8 @@ int caliptra_init_fuses(struct caliptra_fuses *fuses)
if (!caliptra_ready_for_fuses())
return NOT_READY_FOR_FUSES;



// Write Fuses
caliptra_fuse_array_write(GENERIC_AND_FUSE_REG_FUSE_UDS_SEED_0, fuses->uds_seed, CALIPTRA_ARRAY_SIZE(fuses->uds_seed));
caliptra_fuse_array_write(GENERIC_AND_FUSE_REG_FUSE_FIELD_ENTROPY_0, fuses->field_entropy, CALIPTRA_ARRAY_SIZE(fuses->field_entropy));
Expand Down Expand Up @@ -348,6 +351,28 @@ bool caliptra_ready_for_firmware(void)
return true;
}

/*
* caliptra_is_csr_ready
*
* Reports if the IDEVID CSR is ready
*
* @return bool True if ready, false otherwise
*/
bool caliptra_is_csr_ready(void)
{
uint32_t status;

status = caliptra_read_status();

if ((status & GENERIC_AND_FUSE_REG_CPTRA_FLOW_STATUS_IDEVID_CSR_READY_MASK) == GENERIC_AND_FUSE_REG_CPTRA_FLOW_STATUS_IDEVID_CSR_READY_MASK)
{
return true;
}

return false;
}


/**
* caliptra_mailbox_write_fifo
*
Expand Down Expand Up @@ -1060,4 +1085,51 @@ int caliptra_capabilities(struct caliptra_capabilities_resp *resp, bool async)
CREATE_PARCEL(p, OP_CAPABILITIES, &checksum, resp);

return pack_and_execute_command(&p, async);
}
}

int caliptra_retrieve_idevid_csr(struct caliptra_buffer* caliptra_idevid_csr)
{
if (!caliptra_idevid_csr) {
return INVALID_PARAMS;
}

if (!caliptra_is_idevid_csr_ready()) {
return IDEV_CSR_NOT_READY;
}

return caliptra_mailbox_read_fifo(caliptra_idevid_csr);
}

void caliptra_req_idev_csr_start()
{
uint32_t dbg_manuf_serv_req;

caliptra_read_u32(CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_CPTRA_DBG_MANUF_SERVICE_REG, &dbg_manuf_serv_req);

// Write to Caliptra Fuse Done
caliptra_write_u32(CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_CPTRA_DBG_MANUF_SERVICE_REG, dbg_manuf_serv_req | 0x01);
}

void caliptra_req_idev_csr_complete()
{
uint32_t dbg_manuf_serv_req;

caliptra_read_u32(CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_CPTRA_DBG_MANUF_SERVICE_REG, &dbg_manuf_serv_req);

// Write to Caliptra Fuse Done
caliptra_write_u32(CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_CPTRA_DBG_MANUF_SERVICE_REG, dbg_manuf_serv_req & ~0x01);
}


// Check if IDEV CSR is ready.
bool caliptra_is_idevid_csr_ready() {
uint32_t status;

caliptra_read_u32(CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_CPTRA_FLOW_STATUS, &status);

if ((status & GENERIC_AND_FUSE_REG_CPTRA_FLOW_STATUS_IDEVID_CSR_READY_MASK) != 0) {
return true;
}

return false;
}
Loading

0 comments on commit 8a429a5

Please sign in to comment.