1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-07-02 22:43:17 +02:00

rpmc: add rpmc commands feature

Added optional support for all the commands specified in JESD260.
Added a new optional dependency to openssls libcrypto.
Added parsing for the rpmc parameter sfdp table.
Added necessary rpmc parameter information to flashchips struct and the
flash hardening feature to enable rpmc commands.

Enables future use of these commands in the cli_client and also
libflashrom.

Change-Id: I6ab3d0446e9fd674b20550fdbfaf499b8d4a9b38
Signed-off-by: Matti Finder <matti.finder@gmail.com>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/84934
Reviewed-by: Peter Marheine <pmarheine@chromium.org>
Reviewed-by: Anastasia Klimchuk <aklm@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Matti Finder
2024-10-30 16:55:10 +01:00
committed by Anastasia Klimchuk
parent 40d1c25c00
commit 52f062f67a
7 changed files with 819 additions and 10 deletions

123
sfdp.c
View File

@ -252,6 +252,88 @@ done:
return 0;
}
static unsigned int bits_to_counter_delay(const uint8_t bits)
{
unsigned int value = bits & 0xf;
switch ((bits & (0b11 << 4)) >> 4) {
case 0b00:
value *= 1;
break;
case 0b01:
value *= 16;
break;
case 0b10:
value *= 128;
break;
case 0b11:
value *= 1000;
break;
}
return value;
}
static int parse_rpmc_parameter_table(struct flashchip *const chip, const uint8_t *const buf, const uint16_t len)
{
if (len != 2 * 4) {
msg_cdbg("Length of RPMC parameter table is wrong, skipping it\n");
return 1;
}
msg_cdbg("Parsing rpmc parameter table...\n");
// first dword
uint32_t first_dword = ((unsigned int)buf[(4 * 0) + 0]);
first_dword |= ((unsigned int)buf[(4 * 0) + 1]) << 8;
first_dword |= ((unsigned int)buf[(4 * 0) + 2]) << 16;
first_dword |= ((unsigned int)buf[(4 * 0) + 3]) << 24;
if ((first_dword & 0b1) != 0) {
// flash hardening is not supported
msg_cdbg("Flash Hardening not supported\n");
goto done;
}
chip->feature_bits |= FEATURE_FLASH_HARDENING;
chip->rpmc_ctx.busy_polling_method = (first_dword & (1 << 2)) >> 2;
msg_cspew("Busy polling method: %u\n", chip->rpmc_ctx.busy_polling_method);
chip->rpmc_ctx.num_counters = ((first_dword & (0xf << 4)) >> 4) + 1;
msg_cspew("Number of counters: %u\n", chip->rpmc_ctx.num_counters);
chip->rpmc_ctx.op1_opcode = (first_dword & (0xff << 8)) >> 8;
msg_cspew("OP1 opcode: 0x%02x\n", chip->rpmc_ctx.op1_opcode);
chip->rpmc_ctx.op2_opcode = (first_dword & (0xff << 16)) >> 16;
msg_cspew("OP2 opcode: 0x%02x\n", chip->rpmc_ctx.op2_opcode);
chip->rpmc_ctx.update_rate = 5 * (1 << ((first_dword & (0xf << 24)) >> 24));
msg_cspew("Update rate: %u seconds\n", chip->rpmc_ctx.update_rate);
// second dword
uint32_t second_dword = ((unsigned int)buf[(4 * 1) + 0]);
second_dword |= ((unsigned int)buf[(4 * 1) + 1]) << 8;
second_dword |= ((unsigned int)buf[(4 * 1) + 2]) << 16;
second_dword |= ((unsigned int)buf[(4 * 1) + 3]) << 24;
chip->rpmc_ctx.polling_delay_read_counter_us = bits_to_counter_delay(second_dword & 0xf);
msg_cspew("Read counter polling delay: %u us\n", chip->rpmc_ctx.polling_delay_read_counter_us);
chip->rpmc_ctx.polling_short_delay_write_counter_us = bits_to_counter_delay((second_dword >> 8) & 0xf);
msg_cspew("Write counter short polling delay: %u us\n",
chip->rpmc_ctx.polling_short_delay_write_counter_us);
chip->rpmc_ctx.polling_long_delay_write_counter_us = bits_to_counter_delay((second_dword >> 16) & 0xf) * 1000;
msg_cspew("Write counter long polling delay: %u us\n",
chip->rpmc_ctx.polling_long_delay_write_counter_us);
done:
msg_cdbg("done.\n");
return 0;
}
int probe_spi_sfdp(struct flashctx *flash)
{
int ret = 0;
@ -359,23 +441,44 @@ int probe_spi_sfdp(struct flashctx *flash)
}
msg_cspew("\n");
if (i == 0) { /* Mandatory JEDEC SFDP parameter table */
if (hdrs[i].id != 0)
msg_cdbg("ID of the mandatory JEDEC SFDP "
"parameter table is not 0 as demanded "
"by JESD216 (warning only).\n");
if (hdrs[i].v_major != 0x01) {
if (i == 0) {
if (hdrs[i].id != 0) {
msg_cerr("ID of the mandatory JEDEC SFDP "
"parameter table is not 0 as demanded "
"by JESD216.\n");
} else if (hdrs[i].v_major != 0x01) {
msg_cdbg("The chip contains an unknown "
"version of the JEDEC flash "
"parameters table, skipping it.\n");
"version of the JEDEC flash "
"parameters table (Version: %u.%u), skipping it.\n",
hdrs[i].v_major, hdrs[i].v_minor);
} else if (len != 4 * 4 && len < 9 * 4) {
msg_cdbg("Length of the mandatory JEDEC SFDP "
"parameter table is wrong (%d B), "
"skipping it.\n", len);
} else if (sfdp_fill_flash(flash->chip, tbuf, len) == 0)
} else if (sfdp_fill_flash(flash->chip, tbuf, len) == 0) {
ret = 1;
}
} else {
/* TODO: implement parsing for other pages */
switch (hdrs[i].id){
case 0x03: /* RPMC parameter table as specified in JESD260 */
if (hdrs[i].v_major != 0x01 || hdrs[i].v_minor != 0x0) {
msg_cdbg("The chip contains an unknown "
"version of the JEDEC RPMC "
"parameters table (Version: %u.%u), skipping it.\n",
hdrs[i].v_major, hdrs[i].v_minor);
} else {
parse_rpmc_parameter_table(flash->chip, tbuf, len);
}
break;
default:
msg_cdbg("Support for SFDP Page with ID 0x%02x not implemented"
", skipping it.\n",
hdrs[i].id);
break;
}
}
free(tbuf);
}