diff options
-rw-r--r-- | libqmrom/include/qmrom.h | 1 | ||||
-rw-r--r-- | libqmrom/include/qmrom_spi.h | 4 | ||||
-rw-r--r-- | libqmrom/src/qmrom_b0.c | 17 | ||||
-rw-r--r-- | libqmrom/src/qmrom_c0.c | 6 | ||||
-rw-r--r-- | qm35-spi.c | 36 | ||||
-rw-r--r-- | qmrom_spi.c | 20 |
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); @@ -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; } |