From 8a429a55c61c03f3648d349c952f745b568844cc Mon Sep 17 00:00:00 2001 From: Anthony Rocha <116300062+rusty1968@users.noreply.github.com> Date: Mon, 15 Jul 2024 11:49:58 -0700 Subject: [PATCH] Implement API for requesting IDEVID CSR. (#1583) --- libcaliptra/examples/generic/idev_csr_array.h | 29 +++++ libcaliptra/examples/generic/main.c | 123 ++++++++++++++++-- libcaliptra/inc/caliptra_api.h | 9 ++ libcaliptra/inc/caliptra_enums.h | 3 + libcaliptra/inc/caliptra_types.h | 1 - libcaliptra/src/caliptra_api.c | 74 ++++++++++- libcaliptra/src/caliptra_fuses.h | 15 ++- libcaliptra/src/caliptra_mbox.h | 2 +- 8 files changed, 243 insertions(+), 13 deletions(-) create mode 100644 libcaliptra/examples/generic/idev_csr_array.h diff --git a/libcaliptra/examples/generic/idev_csr_array.h b/libcaliptra/examples/generic/idev_csr_array.h new file mode 100644 index 0000000000..8e5cc3e03f --- /dev/null +++ b/libcaliptra/examples/generic/idev_csr_array.h @@ -0,0 +1,29 @@ +// Licensed under the Apache-2.0 license +// Generated from test/tests/caliptra_integration_tests/smoke_testdata/idev_csr.der + +#include +#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, +}; diff --git a/libcaliptra/examples/generic/main.c b/libcaliptra/examples/generic/main.c index 74ef75156f..40fa88a53f 100644 --- a/libcaliptra/examples/generic/main.c +++ b/libcaliptra/examples/generic/main.c @@ -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 @@ -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}; @@ -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; @@ -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, @@ -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; @@ -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(); @@ -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; @@ -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 @@ -630,6 +712,27 @@ 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; @@ -637,6 +740,7 @@ int main(int argc, char *argv[]) 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"); @@ -646,3 +750,4 @@ int main(int argc, char *argv[]) return global_test_result; } + diff --git a/libcaliptra/inc/caliptra_api.h b/libcaliptra/inc/caliptra_api.h index 2a4ec20b8a..7e3301fb22 100644 --- a/libcaliptra/inc/caliptra_api.h +++ b/libcaliptra/inc/caliptra_api.h @@ -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(); diff --git a/libcaliptra/inc/caliptra_enums.h b/libcaliptra/inc/caliptra_enums.h index 68c7748313..d59e266a8a 100644 --- a/libcaliptra/inc/caliptra_enums.h +++ b/libcaliptra/inc/caliptra_enums.h @@ -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, }; /** diff --git a/libcaliptra/inc/caliptra_types.h b/libcaliptra/inc/caliptra_types.h index e7076c68b6..6d926b2ada 100644 --- a/libcaliptra/inc/caliptra_types.h +++ b/libcaliptra/inc/caliptra_types.h @@ -390,4 +390,3 @@ struct caliptra_invoke_dpe_resp { uint8_t data[sizeof(struct dpe_certify_key_response)]; }; }; - diff --git a/libcaliptra/src/caliptra_api.c b/libcaliptra/src/caliptra_api.c index c3984f8ff8..025dda0baa 100644 --- a/libcaliptra/src/caliptra_api.c +++ b/libcaliptra/src/caliptra_api.c @@ -153,6 +153,7 @@ int caliptra_bootfsm_go() return 0; } + /** * caliptra_set_wdt_timeout * @@ -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)); @@ -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 * @@ -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); -} \ No newline at end of file +} + +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; +} diff --git a/libcaliptra/src/caliptra_fuses.h b/libcaliptra/src/caliptra_fuses.h index bc944749f1..10e137bacc 100644 --- a/libcaliptra/src/caliptra_fuses.h +++ b/libcaliptra/src/caliptra_fuses.h @@ -40,12 +40,19 @@ static inline uint32_t caliptra_read_fw_error_fatal(void) return caliptra_generic_and_fuse_read(GENERIC_AND_FUSE_REG_CPTRA_FW_ERROR_FATAL); } +static inline uint32_t caliptra_read_dbg_manuf_serv() +{ + return caliptra_generic_and_fuse_read(GENERIC_AND_FUSE_REG_CPTRA_DBG_MANUF_SERVICE_REG); +} + + static inline void caliptra_wdt_cfg_write(uint64_t data) { caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_CPTRA_WDT_CFG_0, (uint32_t)data); caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_CPTRA_WDT_CFG_1, (uint32_t)(data >> 32)); } + static inline void caliptra_write_itrng_entropy_low_threshold(uint16_t data) { uint32_t val = caliptra_generic_and_fuse_read(GENERIC_AND_FUSE_REG_CPTRA_ITRNG_ENTROPY_CONFIG_0); @@ -102,4 +109,10 @@ static inline void caliptra_set_fuse_pauser_lock() static inline void caliptra_write_fuse_valid_pauser(uint32_t data) { caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_CPTRA_FUSE_VALID_PAUSER, data); -} \ No newline at end of file +} + +static inline void caliptra_write_dbg_manuf_serv(uint32_t data) +{ + // Set Manuf service reg + caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_CPTRA_DBG_MANUF_SERVICE_REG, data); +} diff --git a/libcaliptra/src/caliptra_mbox.h b/libcaliptra/src/caliptra_mbox.h index a5aaada1ee..be80764d28 100644 --- a/libcaliptra/src/caliptra_mbox.h +++ b/libcaliptra/src/caliptra_mbox.h @@ -128,7 +128,7 @@ static inline bool caliptra_mbox_is_busy(void) static inline uint8_t caliptra_mbox_read_status_fsm(void) { - return (uint8_t)(caliptra_mbox_read(MBOX_CSR_MBOX_STATUS) >> 16 & MBOX_CSR_MBOX_STATUS_STATUS_MASK); + return (uint8_t)(caliptra_mbox_read(MBOX_CSR_MBOX_STATUS) & MBOX_CSR_MBOX_STATUS_MBOX_FSM_PS_MASK) >> MBOX_CSR_MBOX_STATUS_MBOX_FSM_PS_LOW; } static inline uint32_t caliptra_mbox_read_dlen(void)