summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil DI FOLCO <neil.difolco@qorvo.com>2023-04-05 10:39:04 +0200
committerNeil DI FOLCO <neil.difolco@qorvo.com>2023-04-05 17:50:37 +0200
commitc4c69506a5972e41b7c8fb34f4365c49457ca0cd (patch)
treeacf4ab22ec5a3348e1cfc644a6824bd2e292ba98
parent731d257c39f797e92c92ec25a4fec8b69f232663 (diff)
downloaduwb-c4c69506a5972e41b7c8fb34f4365c49457ca0cd.tar.gz
qm35: add support for dual QM FW images signed with PROD and TEST keys
The driver will try to flash the QM FW image signed with PROD keys first. On failure, it falls back to the QM FW image signed with TEST keys. QM FW image signed with PROD keys: qm35_b0_oem_prod.bin QM FW image signed with TEST keys: qm35_b0_oem.bin Bug: 274517844 Change-Id: I6a99faea28b54386805c791e48eabb4d46b4e8f6 Signed-off-by: Neil DI FOLCO <neil.difolco@qorvo.com>
-rw-r--r--libqmrom/include/qmrom.h1
-rw-r--r--libqmrom/include/qmrom_spi.h4
-rw-r--r--libqmrom/src/qmrom_b0.c17
-rw-r--r--libqmrom/src/qmrom_c0.c6
-rw-r--r--qm35-spi.c36
-rw-r--r--qmrom_spi.c20
6 files changed, 56 insertions, 28 deletions
diff --git a/libqmrom/include/qmrom.h b/libqmrom/include/qmrom.h
index c821a7e..c403ed1 100644
--- a/libqmrom/include/qmrom.h
+++ b/libqmrom/include/qmrom.h
@@ -32,6 +32,7 @@
#define PEG_ERR_ROM_NOT_READY PEG_ERR_BASE - 2
#define PEG_ERR_SEND_CERT_WRITE PEG_ERR_BASE - 3
#define PEG_ERR_WRONG_REVISION PEG_ERR_BASE - 4
+#define PEG_ERR_FIRST_KEY_CERT_OR_FW_VER PEG_ERR_BASE - 5
enum chip_revision_e {
CHIP_REVISION_A0 = 0xA0,
diff --git a/libqmrom/include/qmrom_spi.h b/libqmrom/include/qmrom_spi.h
index 14cc50d..c3d8c92 100644
--- a/libqmrom/include/qmrom_spi.h
+++ b/libqmrom/include/qmrom_spi.h
@@ -49,8 +49,8 @@ int qmrom_spi_transfer(void *handle, char *rbuf, const char *wbuf, size_t size);
int qmrom_spi_set_cs_level(void *handle, int level);
int qmrom_spi_reset_device(void *reset_handle);
const struct firmware *qmrom_spi_get_firmware(void *handle,
- enum chip_revision_e revision,
- int lcs_state);
+ struct qmrom_handle *qmrom_h,
+ bool use_prod_fw);
void qmrom_spi_release_firmware(const struct firmware *fw);
int qmrom_spi_wait_for_ready_line(void *handle, unsigned int timeout_ms);
void qmrom_spi_set_freq(unsigned int freq);
diff --git a/libqmrom/src/qmrom_b0.c b/libqmrom/src/qmrom_b0.c
index 6124dc0..9b23cff 100644
--- a/libqmrom/src/qmrom_b0.c
+++ b/libqmrom/src/qmrom_b0.c
@@ -212,7 +212,7 @@ int qmrom_b0_probe_device(struct qmrom_handle *handle)
}
static int qmrom_b0_flash_data(struct qmrom_handle *handle, struct firmware *fw,
- uint8_t cmd, uint8_t resp)
+ uint8_t cmd, uint8_t exp)
{
int rc, sent = 0;
const char *bin_data = (const char *)fw->data;
@@ -228,16 +228,19 @@ static int qmrom_b0_flash_data(struct qmrom_handle *handle, struct firmware *fw,
qmrom_b0_poll_soc(handle);
qmrom_pre_read(handle);
qmrom_read(handle);
+ if (handle->sstc->payload[0] != exp) {
+ LOG_ERR("%s: wrong data expected (%#x vs %#x)!!!\n",
+ __func__, handle->sstc->payload[0] & 0xff, exp);
+ if (handle->sstc->payload[0] ==
+ ERR_FIRST_KEY_CERT_OR_FW_VER)
+ return PEG_ERR_FIRST_KEY_CERT_OR_FW_VER;
+ else
+ return SPI_PROTO_WRONG_RESP;
+ }
LOG_DBG("%s: sending %d command with %" PRIu32 " bytes\n",
__func__, cmd, tx_bytes);
rc = qmrom_write_size_cmd(handle, cmd, tx_bytes, bin_data);
- if (handle->sstc->payload[0] != resp) {
- LOG_ERR("%s: wrong data result (%#x vs %#x)!!!\n",
- __func__, handle->sstc->payload[0] & 0xff,
- resp);
- return SPI_PROTO_WRONG_RESP;
- }
if (rc)
return rc;
sent += tx_bytes;
diff --git a/libqmrom/src/qmrom_c0.c b/libqmrom/src/qmrom_c0.c
index 6d6d8a1..76a04f3 100644
--- a/libqmrom/src/qmrom_c0.c
+++ b/libqmrom/src/qmrom_c0.c
@@ -333,7 +333,11 @@ static int qmrom_c0_flash_data(struct qmrom_handle *handle, struct firmware *fw,
LOG_ERR("%s: wrong data result (%#x vs %#x)!!!\n",
__func__, handle->sstc->payload[0] & 0xff,
resp);
- return SPI_PROTO_WRONG_RESP;
+ if (handle->sstc->payload[0] ==
+ ERR_FIRST_KEY_CERT_OR_FW_VER)
+ return PEG_ERR_FIRST_KEY_CERT_OR_FW_VER;
+ else
+ return SPI_PROTO_WRONG_RESP;
}
}
qmrom_msleep(SPI_READY_TIMEOUT_MS_C0);
diff --git a/qm35-spi.c b/qm35-spi.c
index 2de669d..70241e6 100644
--- a/qm35-spi.c
+++ b/qm35-spi.c
@@ -455,11 +455,31 @@ int qm35_reset_sync(struct qm35_ctx *qm35_hdl)
return ret;
}
+static int qm_firmware_flashing(void *handle, struct qmrom_handle *h,
+ bool use_prod_fw)
+{
+ struct qm35_ctx *qm35_hdl = (struct qm35_ctx *)handle;
+ struct spi_device *spi = qm35_hdl->spi;
+ const struct firmware *fw;
+ int ret = 0;
+
+ fw = qmrom_spi_get_firmware(&spi->dev, h, use_prod_fw);
+ if (fw == NULL) {
+ dev_err(&spi->dev, "Firmware file not present!\n");
+ return -1;
+ }
+
+ ret = qmrom_flash_fw(h, fw);
+ dev_dbg(&spi->dev, "Return qmrom_flash_fw = %d!\n", ret);
+
+ qmrom_spi_release_firmware(fw);
+ return ret;
+}
+
static int qm_firmware_load(struct qm35_ctx *qm35_hdl)
{
struct spi_device *spi = qm35_hdl->spi;
unsigned int state = qm35_get_state(qm35_hdl);
- const struct firmware *fw;
struct qmrom_handle *h;
int ret;
@@ -495,18 +515,14 @@ static int qm_firmware_load(struct qm35_ctx *qm35_hdl)
}
dev_dbg(&spi->dev, "Starting device flashing!\n");
- fw = qmrom_spi_get_firmware(&spi->dev, h->chip_rev, h->lcs_state);
- if (fw == NULL) {
- dev_err(&spi->dev, "Firmware file not present!\n");
- ret = -1;
- goto out;
+ ret = qm_firmware_flashing(qm35_hdl, h, true);
+ if (ret) {
+ qmrom_reboot_bootloader(h);
+ ret = qm_firmware_flashing(qm35_hdl, h, false);
}
- ret = qmrom_flash_fw(h, fw);
- qmrom_spi_release_firmware(fw);
-
if (ret)
- dev_err(&spi->dev, "Firmware download failed!\n");
+ dev_err(&spi->dev, "Firmware download failed with %d!\n", ret);
else
dev_info(&spi->dev, "Device flashing completed!\n");
diff --git a/qmrom_spi.c b/qmrom_spi.c
index 4d68a00..1bdc2ab 100644
--- a/qmrom_spi.c
+++ b/qmrom_spi.c
@@ -93,23 +93,27 @@ int qmrom_spi_reset_device(void *reset_handle)
}
const struct firmware *qmrom_spi_get_firmware(void *handle,
- enum chip_revision_e revision,
- int lcs_state)
+ struct qmrom_handle *qmrom_h,
+ bool use_prod_fw)
{
const struct firmware *fw;
struct spi_device *spi = handle;
char _fw_name[16]; /* enough room to store "qm35_xx_xxx.bin" */
const char *fw_name = _fw_name;
int ret;
+ enum chip_revision_e revision = qmrom_h->chip_rev;
+ int lcs_state = qmrom_h->lcs_state;
if (!fwname) {
if (revision == CHIP_REVISION_A0)
- snprintf(_fw_name, sizeof(_fw_name), "qm35_%02x.bin",
- revision);
- else
- snprintf(_fw_name, sizeof(_fw_name), "qm35_b0_%.3s.bin",
- lcs_state == CC_BSV_SECURE_LCS ? "oem" :
- "icv");
+ fw_name = "qm35_a0.bin";
+ else if (lcs_state == CC_BSV_SECURE_LCS) {
+ if (use_prod_fw)
+ fw_name = "qm35_b0_oem_prod.bin";
+ else
+ fw_name = "qm35_b0_oem.bin";
+ } else
+ fw_name = "qm35_b0_icv.bin";
} else {
fw_name = fwname;
}