summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
}