summaryrefslogtreecommitdiff
path: root/libqmrom/src/qmrom.c
diff options
context:
space:
mode:
Diffstat (limited to 'libqmrom/src/qmrom.c')
-rw-r--r--libqmrom/src/qmrom.c879
1 files changed, 0 insertions, 879 deletions
diff --git a/libqmrom/src/qmrom.c b/libqmrom/src/qmrom.c
deleted file mode 100644
index c76baae..0000000
--- a/libqmrom/src/qmrom.c
+++ /dev/null
@@ -1,879 +0,0 @@
-/*
- * Copyright 2021 Qorvo US, Inc.
- *
- * SPDX-License-Identifier: GPL-2.0 OR Apache-2.0
- *
- * This file is provided under the Apache License 2.0, or the
- * GNU General Public License v2.0.
- *
- */
-#include <qmrom_utils.h>
-#include <qmrom_log.h>
-#include <qmrom_spi.h>
-#include <qmrom.h>
-#include <spi_rom_protocol.h>
-
-#ifndef __KERNEL__
-#include <errno.h>
-#include <stdint.h>
-#include <string.h>
-#else
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#endif
-
-#define CHUNK_SIZE_A0 1016
-#define CHUNK_SIZE_B0 1008
-
-#define HBK_LOC 12
-typedef enum {
- HBK_2E_ICV = 0,
- HBK_2E_OEM = 1,
- HBK_1E_ICV_OEM = 2,
-} hbk_t;
-
-struct unstitched_firmware {
- struct binary_chunk *fw_img;
- struct binary_chunk *fw_crt;
- struct binary_chunk *key1_crt;
- struct binary_chunk *key2_crt;
-};
-
-static int qmrom_chip_revision(void *spi_handle,
- struct stc *sstc,
- struct stc *hstc,
- enum chip_revision_e *revision);
-static int qmrom_unstitch_fw(const struct firmware *fw,
- struct unstitched_firmware *unstitched_fw,
- enum chip_revision_e revision);
-static int qmrom_start_bootloader_download(void *spi_handle, struct stc *sstc,
- struct stc *hstc, int is_sram,
- enum chip_revision_e revision, uint8_t is_oem);
-static int qmrom_get_bootloader_rom_version(void *spi_handle, struct stc *sstc,
- struct stc *hstc, uint16_t *version);
-static int qmrom_send_cert(void *spi_handle, struct binary_chunk *fcert,
- uint16_t exp_read, uint16_t read_size,
- uint16_t cert_size, struct stc *sstc,
- struct stc *hstc, enum chip_revision_e revision);
-static int qmrom_send_image_size(void *spi_handle, struct binary_chunk *fw,
- struct stc *sstc, struct stc *hstc,
- enum chip_revision_e revision);
-static int qmrom_reboot_bootloader(void *spi_handle,
- qmrom_reset_device reset_fn,
- void *reset_handle);
-static int qmrom_send_multichunk_bytes(void *spi_handle,
- struct binary_chunk *fw,
- struct stc *sstc, struct stc *hstc,
- enum chip_revision_e revision,
- int rsp_expected, int cmd_code);
-
-
-static void qmrom_free_stcs(struct stc *hstc, struct stc *sstc)
-{
- if (hstc) qmrom_free(hstc);
- if (sstc) qmrom_free(sstc);
-}
-
-static int qmrom_allocate_stcs(struct stc **hstc, struct stc **sstc)
-{
- int rc = 0;
- uint8_t *tx_buf = NULL, *rx_buf = NULL;
-
- qmrom_alloc(tx_buf, MAX_STC_FRAME_LEN);
- if (tx_buf == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- qmrom_alloc(rx_buf, MAX_STC_FRAME_LEN);
- if (rx_buf == NULL) {
- qmrom_free(tx_buf);
- rc = -ENOMEM;
- goto out;
- }
-
- *hstc = (struct stc *)tx_buf;
- *sstc = (struct stc *)rx_buf;
- return rc;
-out:
- qmrom_free_stcs((struct stc *)tx_buf, (struct stc *)rx_buf);
- *hstc = NULL;
- *sstc = NULL;
- return rc;
-}
-
-static int qmrom_send_dbg_cert_size(void *spi_handle, struct binary_chunk *fw,
- struct stc *sstc, struct stc *hstc)
-{
- int rc;
- memset(hstc->payload, 0, SPI_BOOT_DEBUG_CERT_SIZE_B0);
- rc = spi_proto_prepare_write_cmd(spi_handle, 1,
- SPI_RSP_WAIT_DBG_CERT_SIZE_B0,
- SPI_ROM_DBG_CERT_SIZE_SIZE, sstc,
- hstc, CHIP_REVISION_B0);
- if (rc) {
- LOG_ERR("%s: prepare write failed with %d\n", __func__, rc);
- return rc;
- }
-
- hstc->all = 0;
- sstc->all = 0;
- hstc->host_flags.write = 1;
- hstc->ul = SPI_UL_ROM_BOOT_PROTO;
- hstc->len = sizeof(uint32_t) + 1;
- hstc->payload[0] = SPI_BOOT_DEBUG_CERT_SIZE_B0;
- hstc->payload[1] = fw->size & 0xff;
- hstc->payload[2] = (fw->size >> 8) & 0xff;
- hstc->payload[3] = (fw->size >> 16) & 0xff;
- hstc->payload[4] = (fw->size >> 24) & 0xff;
- rc = spi_proto_send_stc(spi_handle, sstc, hstc, CHIP_REVISION_B0);
- if (rc) {
- LOG_ERR("%s: write failed with %d\n", __func__, rc);
- return rc;
- }
- dump_raw_hsstc(LOG_DBG, hstc, sstc, "debug_cert_size write\n");
- return 0;
-}
-
-int qmrom_flash_dbg_cert(void *spi_handle, struct binary_chunk *dbg_cert,
- qmrom_reset_device reset_fn, void *reset_handle)
-{
- int rc = 0;
- struct stc *hstc, *sstc;
-
- rc = qmrom_allocate_stcs(&hstc, &sstc);
- if (rc)
- return rc;
-
- LOG_INFO("Rebooting the board\n");
- rc = qmrom_reboot_bootloader(spi_handle, reset_fn, reset_handle);
- if (rc)
- goto out;
-
- rc = spi_proto_prepare_write_cmd(spi_handle, 1,
- 0, SPI_ROM_DBG_CERT_SIZE_SIZE, sstc,
- hstc, CHIP_REVISION_B0);
- if (rc) {
- LOG_ERR("%s: prepare write failed with %d\n", __func__, rc);
- goto out;
- }
-
- hstc->all = 0;
- sstc->all = 0;
- hstc->host_flags.write = 1;
- hstc->ul = SPI_UL_ROM_BOOT_PROTO;
- hstc->len = 1;
- hstc->payload[0] = SPI_BOOT_DOWNLOAD_DEBUG_CERT_B0;
- rc = spi_proto_send_stc(spi_handle, sstc, hstc, CHIP_REVISION_B0);
- if (rc) {
- LOG_ERR("%s: write failed with %d\n", __func__, rc);
- goto out;
- }
- dump_raw_hsstc(LOG_DBG, hstc, sstc, "download debug cert\n");
-
- LOG_INFO("Sending the dbg cert size cmd\n");
- rc = qmrom_send_dbg_cert_size(spi_handle, dbg_cert, sstc, hstc);
- if (rc)
- goto out;
-
- rc = qmrom_send_multichunk_bytes(spi_handle, dbg_cert, sstc, hstc, CHIP_REVISION_B0,
- SPI_RSP_WAIT_DBG_CERT_B0, SPI_BOOT_DOWNLOAD_CERT_DATA_B0);
-
-out:
- qmrom_free_stcs(hstc, sstc);
- return rc;
-}
-
-int qmrom_erase_dbg_cert(void *spi_handle,
- qmrom_reset_device reset_fn, void *reset_handle)
-{
- int rc = 0;
- struct stc *hstc, *sstc;
-
- rc = qmrom_allocate_stcs(&hstc, &sstc);
- if (rc)
- return rc;
-
- LOG_INFO("Rebooting the board\n");
- rc = qmrom_reboot_bootloader(spi_handle, reset_fn, reset_handle);
- if (rc)
- goto out;
-
- /* Erasing... */
- hstc->payload[0] = 0;
- rc = spi_proto_prepare_write_cmd(spi_handle, 1,
- 0, 1, sstc, hstc, CHIP_REVISION_B0);
- if (rc) {
- LOG_ERR("%s: prepare write failed with %d\n", __func__, rc);
- goto out;
- }
- /* Send the erase cmd */
- hstc->all = 0;
- sstc->all = 0;
- hstc->host_flags.write = 1;
- hstc->ul = SPI_UL_ROM_BOOT_PROTO;
- hstc->len = 1;
- hstc->payload[0] = SPI_BOOT_ERASE_DEBUG_CERT_B0;
- rc = spi_proto_send_stc(spi_handle, sstc, hstc, CHIP_REVISION_B0);
- if (rc) {
- LOG_ERR("%s: write failed with %d\n", __func__, rc);
- goto out;
- }
- dump_raw_hsstc(LOG_DBG, hstc, sstc, "erase debug cert\n");
-
-out:
- qmrom_free_stcs(hstc, sstc);
- return rc;
-}
-
-int qmrom_get_soc_info(void *spi_handle,
- qmrom_reset_device reset_fn, void *reset_handle,
- uint8_t soc_id[ROM_SOC_ID_LEN],
- uint8_t uuid[ROM_UUID_LEN],
- uint8_t *lcs_state)
-{
- int rc = 0;
- struct stc *hstc, *sstc;
- uint8_t *payload;
- int i;
- enum chip_revision_e revision;
-
- rc = qmrom_allocate_stcs(&hstc, &sstc);
- if (rc)
- return rc;
-
- LOG_INFO("Rebooting the board\n");
- rc = qmrom_reboot_bootloader(spi_handle, reset_fn, reset_handle);
- if (rc)
- goto out;
-
- LOG_INFO("Getting the chip revision\n");
- rc = qmrom_chip_revision(spi_handle, sstc, hstc, &revision);
- if (rc)
- goto out;
-
- if (revision == CHIP_REVISION_A0) {
- LOG_WARN("%s: SoC info not supported on chip revision A0\n", __func__);
- rc = -1;
- goto out;
- }
-
- LOG_INFO("Rebooting the board\n");
- rc = qmrom_reboot_bootloader(spi_handle, reset_fn, reset_handle);
- if (rc)
- goto out;
-
- /* Sending command... */
- hstc->payload[0] = 3;
- rc = spi_proto_prepare_write_cmd(spi_handle, 1,
- 0, 1, sstc, hstc, CHIP_REVISION_B0);
- if (rc) {
- LOG_ERR("%s: prepare write failed with %d\n", __func__, rc);
- goto out;
- }
- /* Send the erase cmd */
- hstc->all = 0;
- sstc->all = 0;
- hstc->host_flags.read = 1;
- hstc->ul = SPI_UL_ROM_BOOT_PROTO;
- hstc->len = 0x32;
- hstc->payload[0] = 0;
- rc = spi_proto_send_stc(spi_handle, sstc, hstc, CHIP_REVISION_B0);
- if (rc) {
- LOG_ERR("%s: write failed with %d\n", __func__, rc);
- goto out;
- }
- dump_raw_hsstc(LOG_DBG, hstc, sstc, "erase debug cert\n");
-
- hstc->all = 0;
- sstc->all = 0;
- hstc->host_flags.write = 1;
- hstc->ul = SPI_UL_ROM_BOOT_PROTO;
- hstc->len = 1;
- hstc->payload[0] = SPI_BOOT_GET_CHIP_INFO_B0;
- rc = spi_proto_send_stc(spi_handle, sstc, hstc, CHIP_REVISION_B0);
- if (rc) {
- LOG_ERR("%s: write failed with %d\n", __func__, rc);
- return rc;
- }
- hstc->all = 0;
- sstc->all = 0;
- memset(hstc->payload, 0, SPI_ROM_READ_INFO_SIZE_B0);
- rc = spi_proto_prepare_write_cmd(spi_handle, 0,
- SPI_RSP_WAIT_DOWNLOAD_MODE,
- SPI_ROM_READ_INFO_SIZE_B0, sstc,
- hstc, CHIP_REVISION_B0);
- if (rc) {
- LOG_ERR("%s: prepare write failed with %d\n", __func__, rc);
- return rc;
- }
- if (sstc->len != SPI_ROM_READ_INFO_SIZE_B0) {
- LOG_ERR("%s: wrong device info size 0x%x\n", __func__, sstc->len);
- return -1;
- }
-
- /* skip the first byte */
- payload = &sstc->payload[1];
- for (i = 0 ; i < ROM_SOC_ID_LEN ; i++)
- soc_id[i] = payload[ROM_SOC_ID_LEN - i - 1];
- payload += ROM_SOC_ID_LEN;
- *lcs_state = *payload;
- payload += 1;
- for (i = 0 ; i < ROM_UUID_LEN ; i++)
- uuid[i] = payload[ROM_UUID_LEN - i - 1];
-
-out:
- qmrom_free_stcs(hstc, sstc);
- return rc;
-}
-
-int qmrom_download_fw(void *spi_handle,
- qmrom_get_firmware get_fw_fn,
- qmrom_release_firmware release_fw_fn,
- qmrom_reset_device reset_fn,
- void *reset_handle,
- int is_sram,
- int lcs_state)
-{
- int rc = 0;
- struct stc *hstc, *sstc;
- uint16_t spi_rom_read_image_cert_size = 0;
- const struct firmware *stitched_firmware;
- struct unstitched_firmware unstitched_fw = { 0 };
- enum chip_revision_e revision;
- int is_oem;
-
- rc = qmrom_allocate_stcs(&hstc, &sstc);
- if (rc)
- return rc;
-
- LOG_INFO("Rebooting the board\n");
- rc = qmrom_reboot_bootloader(spi_handle, reset_fn, reset_handle);
- if (rc)
- goto fail;
-
- LOG_INFO("Getting the chip revision\n");
- rc = qmrom_chip_revision(spi_handle, sstc, hstc, &revision);
- if (rc)
- goto fail;
-
- if (revision == CHIP_REVISION_A0) {
- spi_rom_read_image_cert_size = SPI_ROM_READ_IMAGE_CERT_SIZE_A0;
- } else if (revision == CHIP_REVISION_B0) {
- spi_rom_read_image_cert_size = SPI_ROM_READ_IMAGE_CERT_SIZE_B0;
- } else {
- LOG_ERR("%s: unknown chip: %d\n", __func__, revision);
- goto fail;
- }
-
-
- stitched_firmware = get_fw_fn(spi_handle, revision, lcs_state);
- if (stitched_firmware == NULL) {
- LOG_ERR("%s: failed getting the binary firmware\n", __func__);
- rc = -1;
- goto fail;
- }
-
- LOG_INFO("Unstitching the fw\n");
- rc = qmrom_unstitch_fw(stitched_firmware, &unstitched_fw, revision);
- if (rc)
- goto fail;
-
- release_fw_fn(stitched_firmware);
-
- is_oem = unstitched_fw.key1_crt->data[HBK_LOC] != HBK_2E_ICV;
- LOG_INFO("Starting the download fw sequence (%s)\n", is_oem ? "OEM" : "ICV");
- rc = qmrom_start_bootloader_download(spi_handle, sstc, hstc,
- is_sram, revision, is_oem);
- if (rc)
- goto fail;
-
- LOG_INFO("Sending the key1 certificate\n");
- rc = qmrom_send_cert(spi_handle, unstitched_fw.key1_crt,
- revision == CHIP_REVISION_A0 ?
- SPI_RSP_WAIT_FOR_KEY1_CERT_A0 :
- SPI_RSP_WAIT_FOR_KEY1_CERT_B0,
- spi_rom_read_image_cert_size,
- unstitched_fw.key1_crt->size,
- sstc, hstc, revision);
- if (rc)
- goto fail;
-
- LOG_INFO("Sending the key2 certificate\n");
- rc = qmrom_send_cert(spi_handle, unstitched_fw.key2_crt,
- revision == CHIP_REVISION_A0 ?
- SPI_RSP_WAIT_FOR_KEY2_CERT_A0 :
- SPI_RSP_WAIT_FOR_KEY2_CERT_B0,
- spi_rom_read_image_cert_size,
- unstitched_fw.key2_crt->size,
- sstc, hstc, revision);
- if (rc)
- goto fail;
-
- LOG_INFO("Sending the content certificate\n");
- rc = qmrom_send_cert(spi_handle, unstitched_fw.fw_crt,
- revision == CHIP_REVISION_A0 ?
- SPI_RSP_WAIT_FOR_IMAGE_CERT_A0 :
- SPI_RSP_WAIT_FOR_IMAGE_CERT_B0,
- spi_rom_read_image_cert_size,
- unstitched_fw.fw_crt->size,
- sstc, hstc, revision);
- if (rc)
- goto fail;
-
- if (revision == CHIP_REVISION_A0) {
- LOG_INFO("Sending the image size\n");
- rc = qmrom_send_image_size(spi_handle, unstitched_fw.fw_img,
- sstc, hstc, revision);
- if (rc)
- goto fail;
- }
-
- LOG_INFO("Sending the image\n");
- rc = qmrom_send_multichunk_bytes(spi_handle, unstitched_fw.fw_img,
- sstc, hstc, revision,
- SPI_RSP_WAIT_FOR_IMAGE,
- SPI_BOOT_DOWNLOAD_SEC_IMAGE_DATA_B0);
- if (rc)
- goto fail;
-
-fail:
- qmrom_free_stcs(hstc, sstc);
- if (unstitched_fw.fw_img) {
- qmrom_free(unstitched_fw.fw_img);
- qmrom_free(unstitched_fw.fw_crt);
- qmrom_free(unstitched_fw.key1_crt);
- qmrom_free(unstitched_fw.key2_crt);
- }
- return rc;
-}
-
-static int qmrom_chip_revision(void *spi_handle,
- struct stc *sstc,
- struct stc *hstc,
- enum chip_revision_e *revision) {
- uint16_t rom_version;
- int rc = 0;
-
- LOG_INFO("Getting the bootloader ROM version\n");
- rc = qmrom_get_bootloader_rom_version(spi_handle, sstc, hstc,
- &rom_version);
- if (rc)
- goto out;
-
- if (rom_version == ROM_VERSION_A0)
- *revision = CHIP_REVISION_A0;
- else if (rom_version == ROM_VERSION_B0)
- *revision = CHIP_REVISION_B0;
- else {
- LOG_ERR("%s: unknown chip revision, received id: 0x%x\n",
- __func__, rom_version);
- *revision = CHIP_REVISION_UNKNOWN;
- rc = 1;
- }
-
- LOG_INFO("detected chip revision: %02x\n", *revision);
-out:
- return rc;
-}
-
-static int qmrom_unstitch_fw(const struct firmware *fw,
- struct unstitched_firmware *unstitched_fw,
- enum chip_revision_e revision) {
- uint32_t tot_len = 0;
- uint32_t fw_img_sz = 0;
- uint32_t fw_crt_sz = 0;
- uint32_t key1_crt_sz = 0;
- uint32_t key2_crt_sz = 0;
- uint8_t *p_key1;
- uint8_t *p_key2;
- uint8_t *p_crt;
- uint8_t *p_fw;
- int ret = 0;
-
- if (revision == CHIP_REVISION_A0) {
- fw_img_sz = fw->size;
- fw_crt_sz = SPI_ROM_WRITE_IMAGE_CERT_SIZE;
- key1_crt_sz = SPI_ROM_WRITE_KEY_CERT_SIZE;
- key2_crt_sz = SPI_ROM_WRITE_KEY_CERT_SIZE;
-
- p_fw = (uint8_t *) fw->data;
- p_key1 = NULL;
- p_key2 = NULL;
- p_crt = NULL;
- tot_len = 0;
- } else if (revision == CHIP_REVISION_B0) {
- // key1
- key1_crt_sz = *(uint32_t * ) & fw->data[tot_len];
- tot_len += sizeof(key1_crt_sz);
- p_key1 = (uint8_t * ) & fw->data[tot_len];
- tot_len += key1_crt_sz;
- if (tot_len >= fw->size) {
- LOG_ERR("%s: Invalid key1_len %u -- stitched len %zu\n",
- __func__, key1_crt_sz, (size_t)fw->size);
- ret = -EINVAL;
- goto out;
- }
-
- // key2
- key2_crt_sz = *(uint32_t * ) & fw->data[tot_len];
- tot_len += sizeof(key2_crt_sz);
- p_key2 = (uint8_t * ) & fw->data[tot_len];
- tot_len += key2_crt_sz;
- if (tot_len >= fw->size) {
- LOG_ERR("%s: Invalid key1_len %u and key2_len %u -- stitched len %zu\n",
- __func__, key1_crt_sz, key2_crt_sz, (size_t)fw->size);
- ret = -EINVAL;
- goto out;
- }
-
- // cert
- fw_crt_sz = *(uint32_t * ) & fw->data[tot_len];
- tot_len += sizeof(fw_crt_sz);
- p_crt = (uint8_t * ) & fw->data[tot_len];
- tot_len += fw_crt_sz;
- if (tot_len >= fw->size) {
- LOG_ERR("%s: Invalid key1_len %u, key2_len %u and content len %u -- stitched len %zu\n",
- __func__, key1_crt_sz, key2_crt_sz, fw_crt_sz,
- (size_t)fw->size);
- ret = -EINVAL;
- goto out;
- }
-
- // fw
- fw_img_sz = *(uint32_t * ) & fw->data[tot_len];
- tot_len += sizeof(fw_img_sz);
- p_fw = (uint8_t * ) & fw->data[tot_len];
- tot_len += fw_img_sz;
- if (tot_len != fw->size) {
- LOG_ERR("%s: Invalid key1_len %u, key2_len %u, content len %u and fw_len %u -- stitched len %zu\n",
- __func__, key1_crt_sz, key2_crt_sz, fw_crt_sz,
- fw_img_sz, (size_t)fw->size);
- ret = -EINVAL;
- goto out;
- }
- } else {
- LOG_ERR("%s: unknown chip: %d\n", __func__, revision);
- goto out;
- }
-
- qmrom_alloc(unstitched_fw->fw_img,
- fw_img_sz + sizeof(unstitched_fw->fw_img));
- if (unstitched_fw->fw_img == NULL) {
- ret = -ENOMEM;
- goto out;
- }
-
- qmrom_alloc(unstitched_fw->fw_crt,
- fw_crt_sz + sizeof(unstitched_fw->fw_crt));
- if (unstitched_fw->fw_crt == NULL) {
- ret = -ENOMEM;
- goto err;
- }
-
- qmrom_alloc(unstitched_fw->key1_crt,
- key1_crt_sz + sizeof(unstitched_fw->key1_crt));
- if (unstitched_fw->key1_crt == NULL) {
- ret = -ENOMEM;
- goto err;
- }
-
- qmrom_alloc(unstitched_fw->key2_crt,
- key2_crt_sz + sizeof(unstitched_fw->key2_crt));
- if (unstitched_fw->key2_crt == NULL) {
- ret = -ENOMEM;
- goto err;
- }
-
- unstitched_fw->key1_crt->size = key1_crt_sz;
- unstitched_fw->key2_crt->size = key2_crt_sz;
- unstitched_fw->fw_crt->size = fw_crt_sz;
- unstitched_fw->fw_img->size = fw_img_sz;
-
- if (revision == CHIP_REVISION_B0) {
- memcpy(unstitched_fw->key1_crt->data, p_key1, key1_crt_sz);
- memcpy(unstitched_fw->key2_crt->data, p_key2, key2_crt_sz);
- memcpy(unstitched_fw->fw_crt->data, p_crt, fw_crt_sz);
- }
-
- memcpy(unstitched_fw->fw_img->data, p_fw, fw_img_sz);
-
- return 0;
-
-err:
- qmrom_free(unstitched_fw->fw_img);
- qmrom_free(unstitched_fw->fw_crt);
- qmrom_free(unstitched_fw->key1_crt);
- qmrom_free(unstitched_fw->key2_crt);
-
-out:
- return ret;
-}
-
-static int qmrom_start_bootloader_download(void *spi_handle, struct stc *sstc,
- struct stc *hstc, int is_sram, enum chip_revision_e revision,
- uint8_t is_oem)
-{
- int rc;
-
- hstc->all = 0;
- sstc->all = 0;
- hstc->host_flags.write = 1;
- hstc->ul = SPI_UL_ROM_BOOT_PROTO;
-
- if (revision == CHIP_REVISION_A0) {
- hstc->payload[0] = is_sram ? SPI_BOOT_DOWNLOAD_SRAM_CMD :
- SPI_BOOT_DOWNLOAD_RRAM_CMD_A0;
- } else if (revision == CHIP_REVISION_B0) {
- hstc->payload[0] = is_oem ? SPI_BOOT_DOWNLOAD_SEC_OEM_CMD_B0 :
- SPI_BOOT_DOWNLOAD_SEC_ICV_CMD_B0;
- } else {
- LOG_ERR("%s: unknown chip: %d\n", __func__, revision);
- return -1;
- }
-
- hstc->len = 1;
- rc = spi_proto_send_stc(spi_handle, sstc, hstc, revision);
- if (rc) {
- LOG_ERR("%s: write failed with %d\n", __func__, rc);
- return rc;
- }
- dump_raw_hsstc(LOG_DBG, hstc, sstc, "download write\n");
- return 0;
-}
-
-static int qmrom_get_bootloader_rom_version(void *spi_handle, struct stc *sstc,
- struct stc *hstc, uint16_t *version) {
- int rc;
- uint16_t dev_id = 0;
-
- memset(hstc->payload, 0, SPI_ROM_READ_VERSION_SIZE_A0);
- rc = spi_proto_prepare_write_cmd(spi_handle, 1,
- SPI_RSP_WAIT_DOWNLOAD_MODE,
- SPI_ROM_READ_VERSION_SIZE_A0, sstc,
- hstc, CHIP_REVISION_A0);
- // FIXME: we have to ignore the rc here because for B0, the write cmd
- // function will fail because the SPI_RSP_WAIT_DOWNLOAD_MODE won't match
- // with the expected one as this flag is different between A0 and B0
- // and at this point we don't know the existing revision.
-// if (rc) {
-// LOG_ERR("%s: prepare write failed with %d\n", __func__, rc);
-// return rc;
-// }
-
- *version = sstc->payload[1] << 8 | sstc->payload[2];
- if (*version == ROM_VERSION_A0) {
- LOG_INFO("%s: ROM bootloader version: 0x%04x, Device ID 0x%04x\n",
- __func__, *version, dev_id);
-
- return 0;
- }
-
- hstc->all = 0;
- sstc->all = 0;
- hstc->host_flags.write = 1;
- hstc->ul = SPI_UL_ROM_BOOT_PROTO;
- hstc->len = 1;
- hstc->payload[0] = SPI_BOOT_GET_CHIP_VER_B0;
- rc = spi_proto_send_stc(spi_handle, sstc, hstc, CHIP_REVISION_B0);
- if (rc) {
- LOG_ERR("%s: write failed with %d\n", __func__, rc);
- return rc;
- }
- hstc->all = 0;
- sstc->all = 0;
- memset(hstc->payload, 0, SPI_ROM_READ_VERSION_SIZE_B0);
- rc = spi_proto_prepare_write_cmd(spi_handle, 0,
- SPI_RSP_WAIT_DOWNLOAD_MODE,
- SPI_ROM_READ_VERSION_SIZE_B0, sstc,
- hstc, CHIP_REVISION_B0);
- if (rc) {
- LOG_ERR("%s: prepare write failed with %d\n", __func__, rc);
- return rc;
- }
- *version = sstc->payload[1] << 8 | sstc->payload[2];
- dev_id = sstc->payload[3] << 8 | sstc->payload[4];
- LOG_INFO("%s: ROM bootloader version: 0x%04x, Device ID 0x%04x\n", __func__, *version, dev_id);
-
- return 0;
-}
-
-static int qmrom_send_cert(void *spi_handle, struct binary_chunk *fcert,
- uint16_t exp_read, uint16_t read_size,
- uint16_t cert_size, struct stc *sstc,
- struct stc *hstc, enum chip_revision_e revision)
-{
- int rc;
- memset(hstc->payload, 0, read_size);
- rc = spi_proto_prepare_write_cmd(spi_handle, 1, exp_read, read_size,
- sstc, hstc, revision);
- if (rc) {
- LOG_ERR("%s: prepare write failed with %d\n", __func__, rc);
- return rc;
- }
- if (fcert->size < cert_size) {
- LOG_ERR("%s: could not read the full certificate (%d bytes asked, %d read)\n",
- __func__, cert_size, fcert->size);
- return PEG_ERR_SEND_CERT_WRITE;
- }
-
- hstc->all = 0;
- sstc->all = 0;
- hstc->host_flags.write = 1;
- hstc->ul = SPI_UL_ROM_BOOT_PROTO;
-
- switch (revision) {
- case CHIP_REVISION_A0:
- hstc->len = cert_size;
- memcpy(hstc->payload, fcert->data, cert_size);
- break;
- case CHIP_REVISION_B0:
- hstc->len = cert_size + 1;
- hstc->payload[0] = SPI_BOOT_DOWNLOAD_CERT_DATA_B0;
- memcpy(hstc->payload + 1, fcert->data, cert_size);
- break;
- default:
- LOG_ERR("%s: Wrong revision %d\n", __func__, revision);
- return PEG_ERR_WRONG_REVISION;
- }
-
- rc = spi_proto_send_stc(spi_handle, sstc, hstc, revision);
- if (rc) {
- LOG_ERR("%s: write failed with %d\n", __func__, rc);
- return rc;
- }
- dump_raw_hsstc(LOG_DBG, hstc, sstc, "certificate write\n");
- return 0;
-}
-
-static int qmrom_send_image_size(void *spi_handle, struct binary_chunk *fw,
- struct stc *sstc, struct stc *hstc, enum chip_revision_e revision)
-{
- int rc;
- uint16_t spi_rom_read_image_size_size = 0;
-
- if (revision == CHIP_REVISION_A0) {
- spi_rom_read_image_size_size = SPI_ROM_READ_IMAGE_SIZE_SIZE_A0;
- } else if (revision == CHIP_REVISION_B0) {
- spi_rom_read_image_size_size = SPI_ROM_READ_IMAGE_SIZE_SIZE_B0;
- } else {
- LOG_ERR("%s: unknown chip: %d\n", __func__, revision);
- return -1;
- }
-
- memset(hstc->payload, 0, spi_rom_read_image_size_size);
- rc = spi_proto_prepare_write_cmd(spi_handle, 1,
- SPI_RSP_WAIT_IMAGE_SIZE,
- spi_rom_read_image_size_size, sstc,
- hstc, revision);
-
- if (rc) {
- LOG_ERR("%s: prepare write failed with %d\n", __func__, rc);
- return rc;
- }
-
- hstc->all = 0;
- sstc->all = 0;
- hstc->host_flags.write = 1;
- hstc->ul = SPI_UL_ROM_BOOT_PROTO;
- hstc->len = sizeof(uint32_t);
- hstc->payload[0] = fw->size & 0xff;
- hstc->payload[1] = (fw->size >> 8) & 0xff;
- hstc->payload[2] = (fw->size >> 16) & 0xff;
- hstc->payload[3] = (fw->size >> 24) & 0xff;
- rc = spi_proto_send_stc(spi_handle, sstc, hstc, revision);
- if (rc) {
- LOG_ERR("%s: write failed with %d\n", __func__, rc);
- return rc;
- }
- dump_raw_hsstc(LOG_DBG, hstc, sstc, "image_size write\n");
- return 0;
-}
-
-static int qmrom_send_multichunk_bytes(void *spi_handle, struct binary_chunk *fw,
- struct stc *sstc, struct stc *hstc, enum chip_revision_e revision,
- int rsp_expected, int cmd_code)
-{
- size_t total_sent = 0, current_size;
- uint8_t *payload = fw->data;
- uint16_t chunk_size;
-
- if (revision == CHIP_REVISION_A0) {
- chunk_size = CHUNK_SIZE_A0;
- } else if (revision == CHIP_REVISION_B0) {
- chunk_size = CHUNK_SIZE_B0;
- } else {
- LOG_ERR("%s: unknown chip: %d\n", __func__, revision);
- return -1;
- }
-
- do {
- int rc;
- hstc->len = 0;
- hstc->payload[0] = 0;
- rc = spi_proto_prepare_write_cmd(
- spi_handle, 1, rsp_expected, 1, sstc, hstc, revision);
- if (rc) {
- LOG_ERR("%s: spi_proto_prepare_write_cmd failed with %d\n",
- __func__, rc);
- return rc;
- }
- hstc->all = 0;
- sstc->all = 0;
- hstc->host_flags.write = 1;
- hstc->ul = SPI_UL_ROM_BOOT_PROTO;
- current_size = fw->size - total_sent;
- if (current_size > chunk_size)
- current_size = chunk_size;
-
- if (revision == CHIP_REVISION_A0) {
- memcpy(hstc->payload, payload, current_size);
- hstc->len = current_size;
- } else if (revision == CHIP_REVISION_B0) {
- hstc->payload[0] = cmd_code;
- memcpy(&hstc->payload[1], payload, current_size);
- hstc->len = current_size + 1;
- } else {
- LOG_ERR("%s: unknown chip: %d\n", __func__, revision);
- return -1;
- }
-
- rc = spi_proto_send_stc(spi_handle, sstc, hstc, revision);
- if (rc) {
- LOG_ERR("%s: write failed with %d\n", __func__, rc);
- return rc;
- }
- dump_raw_hsstc(LOG_DBG, hstc, sstc, "image write\n");
-
- total_sent += current_size;
- payload += current_size;
- } while (total_sent < fw->size);
- return 0;
-}
-
-int qmrom_reboot_bootloader(void *spi_handle,
- qmrom_reset_device reset_fn,
- void *reset_handle)
-{
- int rc;
- rc = qmrom_spi_set_cs_level(spi_handle, 0);
- if (rc) {
- LOG_ERR("%s: spi_set_cs_level(0) failed with %d\n", __func__,
- rc);
- return rc;
- }
- qmrom_msleep(SPI_RST_LOW_DELAY_MS);
-
- reset_fn(reset_handle);
-
- qmrom_msleep(SPI_RST_LOW_DELAY_MS);
-
- rc = qmrom_spi_set_cs_level(spi_handle, 1);
- if (rc) {
- LOG_ERR("%s: spi_set_cs_level(1) failed with %d\n", __func__,
- rc);
- return rc;
- }
- return 0;
-}