diff options
author | Victor Liu <victorliu@google.com> | 2023-11-30 18:13:47 +0000 |
---|---|---|
committer | Victor Liu <victorliu@google.com> | 2023-11-30 19:23:46 +0000 |
commit | cf75cc1a7719ece45601b0fcd574db10c0817978 (patch) | |
tree | 89ee50561dedb85829181eedeb90fbdbf66fdd1e | |
parent | 603d2a2827357e08d8b53e2198bc6b5bfa4f11ce (diff) | |
download | uwb-android-gs-shusky-5.15-android14-qpr2.tar.gz |
Revert "[R-7.2.0] uwb: update qm35 driver"android-u-qpr2-beta-3_r0.8android-u-qpr2-beta-3.1_r0.8android-14.0.0_r0.77android-14.0.0_r0.67android-14.0.0_r0.57android-gs-shusky-5.15-android14-qpr2-betaandroid-gs-shusky-5.15-android14-qpr2
Revert submission 2615259-R-7.2.0
Reason for revert: b/311753464 - fw 6.3.11 for additional soak in main
Reverted changes: /q/submissionid:2615259-R-7.2.0
Bug: 311753464
Change-Id: Ib423da42e3b441e4ffcace355fff4e66e49df915
Signed-off-by: Victor Liu <victorliu@google.com>
28 files changed, 899 insertions, 2023 deletions
@@ -1,4 +1,4 @@ -ccflags-y := -I$(srctree)/$(src)/libqmrom/include -I$(srctree)/$(src)/libfwupdater/include -Werror +ccflags-y := -I$(srctree)/$(src)/libqmrom/include -Werror obj-$(CONFIG_QM35_SPI) := qm35.o @@ -7,11 +7,10 @@ qm35-y := \ qm35_rb.o \ qmrom_spi.o \ libqmrom/src/qmrom_common.o \ - libqmrom/src/qm357xx_rom_common.o \ - libqmrom/src/qm357xx_rom_b0.o \ - libqmrom/src/qm357xx_rom_c0.o \ + libqmrom/src/qmrom_a0.o \ + libqmrom/src/qmrom_b0.o \ + libqmrom/src/qmrom_c0.o \ libqmrom/src/qmrom_log.o \ - libfwupdater/src/fwupdater.o \ hsspi.o \ hsspi_uci.o \ hsspi_log.o \ @@ -390,14 +390,14 @@ static int debug_devid_show(struct seq_file *s, void *unused) static int debug_socid_show(struct seq_file *s, void *unused) { struct debug *debug = (struct debug *)s->private; - uint8_t soc_id[QM357XX_ROM_SOC_ID_LEN]; + uint8_t soc_id[ROM_SOC_ID_LEN]; int rc; if (debug->trace_ops && debug->trace_ops->get_soc_id) { rc = debug->trace_ops->get_soc_id(debug, soc_id); if (rc < 0) return -EIO; - seq_printf(s, "%*phN\n", QM357XX_ROM_SOC_ID_LEN, soc_id); + seq_printf(s, "%*phN\n", ROM_SOC_ID_LEN, soc_id); } return 0; } diff --git a/debug_qmrom.c b/debug_qmrom.c index 9b10c44..8c77bd3 100644 --- a/debug_qmrom.c +++ b/debug_qmrom.c @@ -25,7 +25,6 @@ * QM35 LOG layer HSSPI Protocol */ -#include <linux/interrupt.h> #include <linux/version.h> #include <linux/printk.h> #include <linux/debugfs.h> @@ -40,16 +39,10 @@ #include <qmrom.h> #include <qmrom_log.h> #include <qmrom_spi.h> -#include <qmrom_utils.h> - -#include <fwupdater.h> #include "qm35.h" #include "debug.h" -extern int fu_spi_speed_hz; -extern int qmrom_spi_speed_hz; - #define QMROM_RETRIES 10 static void *priv_from_file(const struct file *filp) @@ -61,31 +54,19 @@ static struct qm35_ctx *rom_test_prepare(struct file *filp) { struct debug *debug = priv_from_file(filp); struct qm35_ctx *qm35_hdl = container_of(debug, struct qm35_ctx, debug); - int irq = gpiod_to_irq(qm35_hdl->gpio_ss_rdy); qm35_hsspi_stop(qm35_hdl); qmrom_set_log_device(&qm35_hdl->spi->dev, LOG_DBG); - - if (irq >= 0) - enable_irq(irq); - - qm35_hdl->flashing = true; return qm35_hdl; } static void rom_test_unprepare(struct qm35_ctx *qm35_hdl) { - int irq = gpiod_to_irq(qm35_hdl->gpio_ss_rdy); - - if (irq >= 0) - disable_irq_nosync(irq); - - qm35_hdl->flashing = false; qmrom_set_log_device(&qm35_hdl->spi->dev, LOG_WARN); qm35_hsspi_start(qm35_hdl); } -static struct firmware *file2firmware(const char *filename) +static struct firmware *file2firmware(const char *filename, size_t file_size) { struct firmware *firmware = kmalloc(sizeof(struct firmware), GFP_KERNEL | __GFP_ZERO); @@ -99,12 +80,12 @@ static struct firmware *file2firmware(const char *filename) filename, 0, (void **)&firmware->data, INT_MAX, &firmware->size, READING_FIRMWARE); if (bytes_read < 0) { - pr_err("qm35: kernel_read_file_from_path(%s) returned %d\n", + pr_err("kernel_read_file_from_path(%s) returned %d\n", filename, (int)bytes_read); goto fail; } if (bytes_read != firmware->size) { - pr_err("qm35: kernel_read_file_from_path returned %zu; expected %zu\n", + pr_err("kernel_read_file_from_path returned %zu; expected %zu\n", bytes_read, firmware->size); goto fail; } @@ -117,7 +98,7 @@ static struct firmware *file2firmware(const char *filename) &size, INT_MAX, READING_FIRMWARE); if (ret < 0) { - pr_err("qm35: kernel_read_file_from_path(%s) returned %d\n", + pr_err("kernel_read_file_from_path(%s) returned %d\n", filename, ret); goto fail; } @@ -125,8 +106,8 @@ static struct firmware *file2firmware(const char *filename) } #endif - print_hex_dump(KERN_DEBUG, "qm35: Bin file:", DUMP_PREFIX_ADDRESS, 16, - 1, firmware->data, 16, false); + print_hex_dump(KERN_DEBUG, "Bin file:", DUMP_PREFIX_ADDRESS, 16, 1, + firmware->data, 16, false); return firmware; fail: @@ -144,29 +125,24 @@ static ssize_t rom_probe(struct file *filp, const char __user *buff, struct qm35_ctx *qm35_hdl = rom_test_prepare(filp); struct qmrom_handle *h; - pr_info("qm35: Starting the probe test...\n"); - h = qmrom_init(&qm35_hdl->spi->dev, qm35_hdl, qm35_hdl, - qm35_hdl->gpio_ss_irq, qmrom_spi_speed_hz, QMROM_RETRIES, - qmrom_spi_reset_device, DEVICE_GEN_QM357XX); + pr_info("Starting the probe test...\n"); + h = qmrom_init(&qm35_hdl->spi->dev, qm35_hdl, qm35_hdl->gpio_ss_rdy, + QMROM_RETRIES, qmrom_spi_reset_device); if (!h) { - pr_err("qm35: qmrom_init failed\n"); + pr_err("qmrom_init failed\n"); goto end; } - pr_info("qm35: chip_revision %#2x\n", h->chip_rev); - pr_info("qm35: device version %#02x\n", h->device_version); + pr_info("chip_revision %#2x\n", h->chip_rev); + pr_info("device version %#02x\n", h->device_version); if (h->chip_rev != 0xa001) { - pr_info("qm35: lcs_state %u\n", h->qm357xx_soc_info.lcs_state); - print_hex_dump(KERN_DEBUG, "qm35: soc_id:", DUMP_PREFIX_NONE, - 16, 1, h->qm357xx_soc_info.soc_id, - sizeof(h->qm357xx_soc_info.soc_id), false); - print_hex_dump(KERN_DEBUG, "qm35: uuid:", DUMP_PREFIX_NONE, 16, - 1, h->qm357xx_soc_info.uuid, - sizeof(h->qm357xx_soc_info.uuid), false); + pr_info("lcs_state %d\n", h->lcs_state); + print_hex_dump(KERN_DEBUG, "soc_id:", DUMP_PREFIX_NONE, 16, 1, + h->soc_id, sizeof(h->soc_id), false); + print_hex_dump(KERN_DEBUG, "uuid:", DUMP_PREFIX_NONE, 16, 1, + h->uuid, sizeof(h->uuid), false); } qmrom_deinit(h); - qmrom_spi_reset_device(qm35_hdl); - qmrom_msleep(100); end: rom_test_unprepare(qm35_hdl); @@ -190,15 +166,14 @@ static ssize_t rom_flash_dbg_cert(struct file *filp, const char __user *buff, err = copy_from_user(filename, buff, count); if (err) { - pr_err("qm35: copy_from_user failed with error %d\n", err); + pr_err("copy_from_user failed with error %d\n", err); count = err; goto end; } filename[count - 1] = '\0'; - certificate = file2firmware(filename); - if (!certificate || certificate->size != DEBUG_CERTIFICATE_SIZE) { - pr_err("qm35: %s: file retrieval failed, abort (%s)\n", - __func__, certificate ? "wrong size" : "not found"); + certificate = file2firmware(filename, DEBUG_CERTIFICATE_SIZE); + if (!certificate) { + pr_err("%s: file retrieval failed, abort\n", __func__); count = -1; goto end; } @@ -206,20 +181,18 @@ static ssize_t rom_flash_dbg_cert(struct file *filp, const char __user *buff, /* Flash the debug certificate */ pr_info("Flashing debug certificate %s...\n", filename); - h = qmrom_init(&qm35_hdl->spi->dev, qm35_hdl, qm35_hdl, - qm35_hdl->gpio_ss_irq, qmrom_spi_speed_hz, QMROM_RETRIES, - qmrom_spi_reset_device, DEVICE_GEN_QM357XX); + h = qmrom_init(&qm35_hdl->spi->dev, qm35_hdl, qm35_hdl->gpio_ss_rdy, + QMROM_RETRIES, qmrom_spi_reset_device); if (!h) { - pr_err("qm35: qmrom_init failed\n"); + pr_err("qmrom_init failed\n"); goto end; } - err = qm357xx_rom_flash_dbg_cert(h, certificate); + err = qmrom_flash_dbg_cert(h, certificate); if (err) - pr_err("qm35: Flashing debug certificate %s failed with %d!\n", + pr_err("Flashing debug certificate %s failed with %d!\n", filename, err); else - pr_info("qm35: Flashing debug certificate %s succeeded!\n", - filename); + pr_info("Flashing debug certificate %s succeeded!\n", filename); end: if (h) @@ -229,9 +202,6 @@ end: vfree(certificate->data); kfree(certificate); } - qmrom_spi_reset_device(qm35_hdl); - qmrom_msleep(100); - rom_test_unprepare(qm35_hdl); return count; } @@ -243,29 +213,23 @@ static ssize_t rom_erase_dbg_cert(struct file *filp, const char __user *buff, struct qmrom_handle *h = NULL; int err; - pr_info("qm35: Erasing debug certificate...\n"); + pr_info("Erasing debug certificate...\n"); - h = qmrom_init(&qm35_hdl->spi->dev, qm35_hdl, qm35_hdl, - qm35_hdl->gpio_ss_irq, qmrom_spi_speed_hz, QMROM_RETRIES, - qmrom_spi_reset_device, DEVICE_GEN_QM357XX); + h = qmrom_init(&qm35_hdl->spi->dev, qm35_hdl, qm35_hdl->gpio_ss_rdy, + QMROM_RETRIES, qmrom_spi_reset_device); if (!h) { - pr_err("qm35: qmrom_init failed\n"); + pr_err("qmrom_init failed\n"); goto end; } - err = qm357xx_rom_erase_dbg_cert(h); + err = qmrom_erase_dbg_cert(h); if (err) - pr_err("qm35: Erasing debug certificate failed with %d!\n", - err); + pr_err("Erasing debug certificate failed with %d!\n", err); else - pr_info("qm35: Erasing debug certificate succeeded!\n"); + pr_info("Erasing debug certificate succeeded!\n"); end: if (h) qmrom_deinit(h); - - qmrom_spi_reset_device(qm35_hdl); - qmrom_msleep(100); - rom_test_unprepare(qm35_hdl); return count; } @@ -287,122 +251,34 @@ static ssize_t rom_flash_fw(struct file *filp, const char __user *buff, rc = copy_from_user(filename, buff, count); if (rc) { - pr_err("qm35: copy_from_user failed with error %d\n", rc); + pr_err("copy_from_user failed with error %d\n", rc); goto end; } filename[count - 1] = '\0'; - fw = file2firmware(filename); + fw = file2firmware(filename, 0); if (!fw) { - pr_err("qm35: %s: file %s retrieval failed, abort\n", __func__, - filename); + pr_err("%s: file retrieval failed, abort\n", __func__); rc = -1; goto end; } - pr_info("qm35: Flashing image %s (%pK->data %pK)...\n", filename, fw, + pr_info("Flashing image %s (%pK->data %pK)...\n", filename, fw, fw->data); - h = qmrom_init(&qm35_hdl->spi->dev, qm35_hdl, qm35_hdl, - qm35_hdl->gpio_ss_irq, qmrom_spi_speed_hz, QMROM_RETRIES, - qmrom_spi_reset_device, DEVICE_GEN_QM357XX); + h = qmrom_init(&qm35_hdl->spi->dev, qm35_hdl, qm35_hdl->gpio_ss_rdy, + QMROM_RETRIES, qmrom_spi_reset_device); if (!h) { - pr_err("qm35: qmrom_init failed\n"); + pr_err("qmrom_init failed\n"); rc = -1; goto end; } - rc = qm357xx_rom_flash_fw(h, fw); + rc = qmrom_flash_fw(h, fw); if (rc) - pr_err("qm35: Flashing firmware %s failed with %d!\n", filename, - rc); + pr_err("Flashing firmware %s failed with %d!\n", filename, rc); else - pr_info("qm35: Flashing firmware %s succeeded!\n", filename); + pr_info("Flashing firmware %s succeeded!\n", filename); end: - kfree(filename); - if (h) - qmrom_deinit(h); - if (fw) { - if (fw->data) - vfree(fw->data); - kfree(fw); - } - rom_test_unprepare(qm35_hdl); - return count; -} - -static ssize_t rom_flash_fw_pkg(struct file *filp, const char __user *buff, - size_t count, loff_t *off) -{ - struct qm35_ctx *qm35_hdl = rom_test_prepare(filp); - const struct firmware *fw = NULL; - struct qmrom_handle *h = NULL; - char *filename = NULL, *fw_data; - uint32_t fw_size; - int rc; - - if (fu_spi_speed_hz == 0) - fu_spi_speed_hz = FWUPDATER_SPI_SPEED_HZ; - - filename = kmalloc(count, GFP_KERNEL); - if (!filename) { - count = -ENOMEM; - goto end; - } - rc = copy_from_user(filename, buff, count); - if (rc) { - pr_err("qm35: copy_from_user failed with error %d\n", rc); - goto end; - } - filename[count - 1] = '\0'; - fw = file2firmware(filename); - if (!fw || !fw->data) { - pr_err("qm35: %s file %s retrieval failed (%s), abort\n", - __func__, filename, fw ? "no data read" : "not found"); - rc = -1; - goto end; - } - - pr_info("qm35: Flashing fw_updater...\n"); - h = qmrom_init(&qm35_hdl->spi->dev, qm35_hdl, qm35_hdl, - qm35_hdl->gpio_ss_irq, qmrom_spi_speed_hz, QMROM_RETRIES, - qmrom_spi_reset_device, DEVICE_GEN_QM357XX); - if (!h) { - pr_err("qm35: qmrom_init failed\n"); - rc = -1; - goto end; - } - rc = qm357xx_rom_flash_fw(h, fw); - if (rc) { - pr_err("qm35: Flashing fw_updater failed with %d!\n", rc); - goto end; - } - - pr_info("qm35: Flashing fw_updater succeeded, flashing the fw package now...\n"); - qmrom_spi_set_freq(fu_spi_speed_hz); - - rc = qm357xx_rom_fw_macro_pkg_get_fw_idx(fw, 1, &fw_size, &fw_data); - if (rc) { - pr_err("qm35: %s FW MACRO PACKAGE corrupted = %d\n", __func__, - rc); - goto end; - } - - if (*(uint32_t *)fw_data == CRYPTO_FIRMWARE_PACK_MAGIC_VALUE) { - rc = run_fwupdater(h, fw_data, fw_size); - } else { - rc = -EINVAL; - pr_err("qm35: FW PACKAGE not found - %04x! fw_size = %d\n", - *(uint32_t *)fw_data, fw_size); - goto end; - } - pr_info("qm35: FW package flashing %s (rc = %d), rebooting the QM...\n", - rc ? "failed" : "succeeded", rc); - -end: - qmrom_spi_reset_device(qm35_hdl); - - if (filename) - kfree(filename); if (h) qmrom_deinit(h); if (fw) { @@ -432,11 +308,6 @@ static const struct file_operations rom_flash_fw_fops = { .write = rom_flash_fw }; -static const struct file_operations rom_flash_fw_pkg_fops = { - .owner = THIS_MODULE, - .write = rom_flash_fw_pkg -}; - void debug_rom_code_init(struct debug *debug) { struct dentry *file; @@ -467,11 +338,4 @@ void debug_rom_code_init(struct debug *debug) pr_err("qm35: failed to create uwb0/fw/rom_flash_fw\n"); return; } - - file = debugfs_create_file("rom_flash_fw_pkg", 0200, debug->fw_dir, - debug, &rom_flash_fw_pkg_fops); - if (!file) { - pr_err("qm35: failed to create uwb0/fw/rom_flash_fw_pkg\n"); - return; - } } @@ -52,8 +52,6 @@ #define HSSPI_MANUAL_CS_SETUP_US SPI_CS_SETUP_DELAY_US #endif -extern int spi_speed_hz; - struct hsspi_work { struct list_head list; enum hsspi_work_type type; @@ -217,13 +215,11 @@ static int spi_xfer(struct hsspi *hsspi, const void *tx, void *rx, .tx_buf = hsspi->host, .rx_buf = hsspi->soc, .len = sizeof(*(hsspi->host)), - .speed_hz = spi_speed_hz, }, { .tx_buf = tx, .rx_buf = rx, .len = length, - .speed_hz = spi_speed_hz, }, }; int ret, retry = 5; @@ -173,6 +173,7 @@ struct hsspi { struct gpio_desc *gpio_ss_rdy; struct gpio_desc *gpio_exton; + volatile bool xfer_ongoing; volatile bool waiting_ss_rdy; }; diff --git a/hsspi_coredump.c b/hsspi_coredump.c index 0172ef4..36ddbb6 100644 --- a/hsspi_coredump.c +++ b/hsspi_coredump.c @@ -234,12 +234,6 @@ static void coredump_received(struct hsspi_layer *hlayer, break; case COREDUMP_BODY_NTF: - pr_debug( - "qm35: coredump: saving coredump data with len: %d [%d/%d]\n", - cch_body_size, - layer->coredump_data_wr_idx + cch_body_size, - layer->coredump_size); - if (coredump_body_ntf_received(layer, cch_body, cch_body_size)) break; @@ -346,6 +340,5 @@ int coredump_layer_init(struct coredump_layer *layer, struct debug *debug) void coredump_layer_deinit(struct coredump_layer *layer) { - del_timer_sync(&layer->timer); kfree(layer->coredump_data); } diff --git a/hsspi_test.c b/hsspi_test.c index 2ac5e21..ae02d52 100644 --- a/hsspi_test.c +++ b/hsspi_test.c @@ -114,7 +114,6 @@ void hsspi_test_received(struct hsspi_layer *layer, struct hsspi_block *blk, { static uint64_t bytes, msgs, errors, bytes0, msgs0, errors0; static time64_t last_perf_dump; - uint32_t rem; int error = check_rx(blk->data, blk->length) ? 1 : 0; time64_t now; errors += error; @@ -143,8 +142,7 @@ void hsspi_test_received(struct hsspi_layer *layer, struct hsspi_block *blk, bytes += blk->length; msgs++; error |= hsspi_send(ghsspi, layer, blk); - div_u64_rem(msgs, 100, &rem); - if (error || (rem == 0)) + if (error || ((msgs % 100) == 0)) pr_info("hsspi test: bytes received %llu, msgs %llu, errors %llu\n", bytes, msgs, errors); if (now > last_perf_dump) { @@ -155,9 +153,9 @@ void hsspi_test_received(struct hsspi_layer *layer, struct hsspi_block *blk, uint64_t derrors = errors >= errors0 ? errors - errors0 : ~0ULL - errors0 + errors; pr_info("hsspi test perfs: %llu B/s, %llu msgs/s, %llu errors/s\n", - div_u64(dbytes, (now - last_perf_dump)), - div_u64(dmsgs, (now - last_perf_dump)), - div_u64(derrors, (now - last_perf_dump))); + dbytes / (now - last_perf_dump), + dmsgs / (now - last_perf_dump), + derrors / (now - last_perf_dump)); bytes0 = bytes; msgs0 = msgs; errors0 = errors; @@ -169,12 +167,10 @@ void hsspi_test_sent(struct hsspi_layer *layer, struct hsspi_block *blk, int status) { static uint64_t bytes, msgs, errors; - uint32_t rem; errors += status ? 1 : 0; msgs++; bytes += blk->length; - div_u64_rem(msgs, 100, &rem); - if (status || (rem == 0)) + if (status || ((msgs % 100) == 0)) pr_info("hsspi test: bytes sent %llu, msgs %llu, errors %llu\n", bytes, msgs, errors); kfree(blk); diff --git a/libfwupdater/CMakeLists.txt b/libfwupdater/CMakeLists.txt deleted file mode 100644 index 8f18673..0000000 --- a/libfwupdater/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -set(SOURCES - src/fwupdater.c - tests/fwupdater_unit_tests.c - tests/comms_tests.c - tests/fwpkg_tests.c -) - -add_library(fwupdater SHARED ${SOURCES}) - -target_include_directories(fwupdater PUBLIC - include -) - -target_link_libraries(fwupdater - PRIVATE - qmrom -) diff --git a/libfwupdater/include/fwupdater.h b/libfwupdater/include/fwupdater.h deleted file mode 100644 index 2875090..0000000 --- a/libfwupdater/include/fwupdater.h +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 -/* - * Copyright 2023 Qorvo US, Inc. - * - */ - -#ifndef __FWUPDATER_H__ -#define __FWUPDATER_H__ - -#ifndef __KERNEL__ -#include <stdint.h> -#include <stddef.h> -#else -#include <linux/types.h> -#endif - -#include <qmrom.h> -#include <qm357xx_fwpkg.h> - -#ifndef CONFIG_NB_RETRIES -#define CONFIG_NB_RETRIES 10 -#endif - -// #define CONFIG_INJECT_ERROR 1 - -enum fw_pkg_error_e { - FW_PKG_SUCCESS = 0, - FW_PKG_DOWNLOAD_ERROR, - FW_PKG_MAGIC_NUM_INVALID, - FW_PKG_VERSION_INVALID, - FW_PKG_ENCRYPTION_MODE_INVALID, - FW_PKG_IMG_HDR_MAGIC_NUM_INVALID, - FW_PKG_IMG_HDR_VERSION_INVALID, - FW_PKG_IMG_HDR_CERT_SIZE_INVALID, - FW_PKG_IMG_HDR_IMG_NUM_INVALID, - FW_PKG_PLD_CHK_MAGIC_NUM_INVALID, - FW_PKG_PLD_CHK_VERSION_INVALID, - FW_PKG_PLD_CHK_LENGTH_INVALID, - FW_PKG_HDR_CRYPTO_ERROR, - FW_PKG_HDR_CRYPTO_INVALID, - FW_PKG_HDR_PAYLOAD_SIZE_INVALID, - FW_PKG_IMG_HDR_SIZE_INVALID, - FW_PKG_IMG_HDR_CRYPTO_ERROR, - FW_PKG_IMG_HDR_NUMDESCS_INVALID, - FW_PKG_CERT_CHAIN_SIZE_INVALID, - FW_PKG_CERT_CHAIN_INVALID, - FW_PKG_CERT_INSTALLED_FW_VERSION_INVALID, - FW_PKG_CERT_KEY1_CHECK_INVALID, - FW_PKG_CERT_KEY2_CHECK_INVALID, - FW_PKG_CERT_CONTENT_CHECK_INVALID, - FW_PKG_CERT_CHAIN_CRYPTO_ERROR, - FW_PKG_CERT_CHAIN_IMG_RANGE_INVALID, - FW_PKG_CERT_CHAIN_WRITE_ERROR, - FW_PKG_IMG_CHUNK_CRYPTO_ERROR, - FW_PKG_IMG_CHUNK_WRITE_ERROR, - FW_PKG_IMG_FIXUP_FAILED -}; - -/*! Firmware Update Status fields */ -struct fw_updater_status_t { - uint32_t magic; - uint32_t status; - uint32_t suberror; - uint32_t spi_errors; - uint32_t cksum_errors; - uint32_t rram_errors; - uint32_t crypto_errors; -} __attribute__((packed)); - -#define FWUPDATER_STATUS_MAGIC 0xCAFECAFE - -void run_fwupdater_unit_tests(void *spi_handle); -int run_fwupdater(struct qmrom_handle *handle, char *fwpkg_bin, size_t size); - -#endif /* __FWUPDATER_H__ */ diff --git a/libfwupdater/src/fwupdater.c b/libfwupdater/src/fwupdater.c deleted file mode 100644 index 187e703..0000000 --- a/libfwupdater/src/fwupdater.c +++ /dev/null @@ -1,343 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 -/* - * Copyright 2023 Qorvo US, Inc. - * - */ - -#ifndef __KERNEL__ -#include <stddef.h> -#endif - -#include <qmrom_spi.h> -#include <qmrom_log.h> -#include <qmrom_utils.h> -#include <spi_rom_protocol.h> - -#include <fwupdater.h> - -/* Extract from C0 rom code */ -#define MAX_CERTIFICATE_SIZE 0x400 -#define MAX_CHUNK_SIZE 3072 -#define WAIT_SS_RDY_CHUNK_TIMEOUT 100 -#define WAIT_SS_RDY_STATUS_TIMEOUT 10 -#define RESULT_RETRIES 3 -#define RESULT_CMD_INTERVAL_MS 50 -#define CKSUM_TYPE uint32_t -#define CKSUM_SIZE (sizeof(CKSUM_TYPE)) -#define TRANPORT_HEADER_SIZE (sizeof(struct stc) + CKSUM_SIZE) -#define EMERGENCY_SPI_FREQ 1000000 /* 1MHz */ - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -#ifndef __KERNEL__ -_Static_assert(MAX_CHUNK_SIZE >= CRYPTO_IMAGES_CERT_PKG_SIZE); -_Static_assert(TRANPORT_HEADER_SIZE + MAX_CERTIFICATE_SIZE < MAX_CHUNK_SIZE); -#endif - -/* local stats */ -static int gstats_spi_errors; -static int gstats_ss_rdy_timeouts; - -static int send_data_chunks(struct qmrom_handle *handle, char *data, - size_t size); - -int run_fwupdater(struct qmrom_handle *handle, char *fwpkg_bin, size_t size) -{ - int rc; - - gstats_spi_errors = 0; - gstats_ss_rdy_timeouts = 0; - - if (size < sizeof(struct fw_pkg_hdr_t) + - sizeof(struct fw_pkg_img_hdr_t) + - CRYPTO_IMAGES_CERT_PKG_SIZE + - CRYPTO_FIRMWARE_CHUNK_MIN_SIZE) { - LOG_ERR("Cannot extract enough data from fw package binary\n"); - return -EINVAL; - } - - rc = send_data_chunks(handle, fwpkg_bin, size); - if (rc) { - LOG_ERR("Sending image failed with %d\n", rc); - return rc; - } - return 0; -} - -static int run_fwupdater_get_status(struct qmrom_handle *handle, - struct stc *hstc, struct stc *sstc, - struct fw_updater_status_t *status) -{ - uint32_t i = 0; - CKSUM_TYPE *cksum = (CKSUM_TYPE *)(hstc + 1); - bool owa; - memset(hstc, 0, TRANPORT_HEADER_SIZE + sizeof(*status)); - - while (i++ < RESULT_RETRIES) { - // Poll the QM - sstc->all = 0; - hstc->all = 0; - *cksum = 0; - qmrom_spi_transfer(handle->spi_handle, (char *)sstc, - (const char *)hstc, TRANPORT_HEADER_SIZE); - qmrom_spi_wait_for_ready_line(handle->ss_rdy_handle, - WAIT_SS_RDY_STATUS_TIMEOUT); - sstc->all = 0; - hstc->all = 0; - hstc->host_flags.pre_read = 1; - *cksum = 0; - qmrom_spi_transfer(handle->spi_handle, (char *)sstc, - (const char *)hstc, TRANPORT_HEADER_SIZE); - // LOG_INFO("Pre-Read received:\n"); - // hexdump(LOG_INFO, sstc, sizeof(sstc)); - - /* Stops the loop when QM has a result to share */ - owa = sstc->soc_flags.out_waiting; - qmrom_spi_wait_for_ready_line(handle->ss_rdy_handle, - WAIT_SS_RDY_STATUS_TIMEOUT); - sstc->all = 0; - hstc->all = 0; - hstc->host_flags.read = 1; - hstc->len = sizeof(*status); - *cksum = 0; - qmrom_spi_transfer(handle->spi_handle, (char *)sstc, - (const char *)hstc, - TRANPORT_HEADER_SIZE + sizeof(*status)); - // LOG_INFO("Read received:\n"); - // hexdump(LOG_INFO, sstc, sizeof(*hstc) + sizeof(uint32_t)); - if (owa) { - memcpy(status, sstc->payload, sizeof(*status)); - if (status->magic == FWUPDATER_STATUS_MAGIC) - break; - } - qmrom_spi_wait_for_ready_line(handle->ss_rdy_handle, - WAIT_SS_RDY_STATUS_TIMEOUT); - // Failed to get the status, reduces the spi speed to - // an emergency speed to maximize the chance to get the - // final status - qmrom_spi_set_freq(EMERGENCY_SPI_FREQ); - gstats_spi_errors++; - } - if (status->magic != FWUPDATER_STATUS_MAGIC) { - LOG_ERR("Timedout waiting for result\n"); - return -1; - } - return 0; -} - -static CKSUM_TYPE checksum(const void *data, const size_t size) -{ - CKSUM_TYPE cksum = 0; - CKSUM_TYPE *ptr = (CKSUM_TYPE *)data; - CKSUM_TYPE remainder = size & (CKSUM_SIZE - 1); - size_t idx; - - for (idx = 0; idx < size; idx += CKSUM_SIZE, ptr++) - cksum += *ptr; - - if (!remainder) - return cksum; - - cksum += ((uint8_t *)data)[size - 1]; - if (remainder > 1) { - cksum += ((uint8_t *)data)[size - 2]; - if (remainder > 2) { - cksum += ((uint8_t *)data)[size - 3]; - } - } - - return cksum; -} - -static void prepare_hstc(struct stc *hstc, char *data, size_t len) -{ - CKSUM_TYPE *cksum = (CKSUM_TYPE *)(hstc + 1); - void *payload = cksum + 1; - - hstc->all = 0; - hstc->host_flags.write = 1; - hstc->len = len + CKSUM_SIZE; - *cksum = checksum(data, len); -#if IS_ENABLED(CONFIG_INJECT_ERROR) - *cksum += 2; -#endif - memcpy(payload, data, len); -} - -static int xfer_payload_prep_next(struct qmrom_handle *handle, - const char *step_name, struct stc *hstc, - struct stc *sstc, struct stc *hstc_next, - char **data, size_t *size) -{ - int rc = 0, nb_retry = CONFIG_NB_RETRIES; - CKSUM_TYPE *cksum = (CKSUM_TYPE *)(hstc + 1); - - do { - int ss_rdy_rc, irq_up; - sstc->all = 0; - rc = qmrom_spi_transfer(handle->spi_handle, (char *)sstc, - (const char *)hstc, - hstc->len + sizeof(struct stc)); - if (hstc_next) { - /* Don't wait idle, prepare the next hstc to be sent */ - size_t to_send = MIN(MAX_CHUNK_SIZE, *size); - prepare_hstc(hstc_next, *data, to_send); - *size -= to_send; - *data += to_send; - hstc_next = NULL; - } - ss_rdy_rc = qmrom_spi_wait_for_ready_line( - handle->ss_rdy_handle, WAIT_SS_RDY_CHUNK_TIMEOUT); - if (ss_rdy_rc) { - LOG_ERR("%s Waiting for ss-rdy failed with %d (nb_retry %d , cksum 0x%x)\n", - step_name, ss_rdy_rc, nb_retry, *cksum); - gstats_ss_rdy_timeouts++; - rc = -EAGAIN; - } - irq_up = qmrom_spi_read_irq_line(handle->ss_irq_handle); - if ((!rc && !sstc->soc_flags.ready) || irq_up) { - LOG_ERR("%s Retry rc %d, sstc 0x%08x, irq %d, cksum %08x\n", - step_name, rc, sstc->all, irq_up, *cksum); - rc = -EAGAIN; - gstats_spi_errors++; - } -#if IS_ENABLED(CONFIG_INJECT_ERROR) - (*cksum)--; -#endif - } while (rc && --nb_retry > 0); - if (rc) { - LOG_ERR("%s transfer failed with %d - (sstc 0x%08x)\n", - step_name, rc, sstc->all); - } - return rc; -} - -static int xfer_payload(struct qmrom_handle *handle, const char *step_name, - struct stc *hstc, struct stc *sstc) -{ - return xfer_payload_prep_next(handle, step_name, hstc, sstc, NULL, NULL, - NULL); -} - -static int send_data_chunks(struct qmrom_handle *handle, char *data, - size_t size) -{ - struct fw_updater_status_t status; - uint32_t chunk_nr = 0; - struct stc *hstc, *sstc, *hstc_current, *hstc_next; - char *rx, *tx; - CKSUM_TYPE *cksum; - int rc = 0; - - qmrom_alloc(rx, MAX_CHUNK_SIZE + TRANPORT_HEADER_SIZE); - qmrom_alloc(tx, 2 * (MAX_CHUNK_SIZE + TRANPORT_HEADER_SIZE)); - if (!rx || !tx) { - LOG_ERR("Rx/Tx buffers allocation failure\n"); - rc = -ENOMEM; - goto exit_nomem; - } - - sstc = (struct stc *)rx; - hstc = (struct stc *)tx; - hstc_current = hstc; - hstc_next = (struct stc *)&tx[MAX_CHUNK_SIZE + TRANPORT_HEADER_SIZE]; - cksum = (CKSUM_TYPE *)(hstc + 1); - - /* wait for the QM to be ready */ - rc = qmrom_spi_wait_for_ready_line(handle->ss_rdy_handle, - WAIT_SS_RDY_CHUNK_TIMEOUT); - if (rc) - LOG_ERR("Waiting for ss-rdy failed with %d\n", rc); - - /* Sending the fw package header */ - prepare_hstc(hstc, data, sizeof(struct fw_pkg_hdr_t)); - LOG_INFO("Sending the fw package header (%zu bytes, cksum is 0x%08x)\n", - sizeof(struct fw_pkg_hdr_t), *cksum); - // hexdump(LOG_INFO, hstc->payload + 4, sizeof(struct fw_pkg_hdr_t)); - rc = xfer_payload(handle, "fw package header", hstc, sstc); - if (rc) - goto exit; - /* Move the data to the next offset minus the header footprint */ - size -= sizeof(struct fw_pkg_hdr_t); - data += sizeof(struct fw_pkg_hdr_t); - - /* Sending the image header */ - prepare_hstc(hstc, data, sizeof(struct fw_pkg_img_hdr_t)); - LOG_INFO("Sending the image header (%zu bytes cksum 0x%08x)\n", - sizeof(struct fw_pkg_img_hdr_t), *cksum); - // hexdump(LOG_INFO, hstc->payload + 4, sizeof(struct fw_pkg_img_hdr_t)); - rc = xfer_payload(handle, "image header", hstc, sstc); - if (rc) - goto exit; - size -= sizeof(struct fw_pkg_img_hdr_t); - data += sizeof(struct fw_pkg_img_hdr_t); - - /* Sending the cert chain */ - prepare_hstc(hstc, data, CRYPTO_IMAGES_CERT_PKG_SIZE); - LOG_INFO("Sending the cert chain (%d bytes cksum 0x%08x)\n", - CRYPTO_IMAGES_CERT_PKG_SIZE, *cksum); - rc = xfer_payload(handle, "cert chain", hstc, sstc); - if (rc) - goto exit; - size -= CRYPTO_IMAGES_CERT_PKG_SIZE; - data += CRYPTO_IMAGES_CERT_PKG_SIZE; - - /* Sending the fw image */ - LOG_INFO("Sending the image (%zu bytes)\n", size); - LOG_DBG("Sending a chunk (%zu bytes cksum 0x%08x)\n", - MIN(MAX_CHUNK_SIZE, size), *cksum); - prepare_hstc(hstc_current, data, MIN(MAX_CHUNK_SIZE, size)); - size -= hstc_current->len - CKSUM_SIZE; - data += hstc_current->len - CKSUM_SIZE; - do { - rc = xfer_payload_prep_next(handle, "data chunk", hstc_current, - sstc, hstc_next, &data, &size); - if (rc) - goto exit; - chunk_nr++; - /* swap hstcs */ - hstc = hstc_current; - hstc_current = hstc_next; - hstc_next = hstc; - } while (size); - - /* Sends the last now */ - rc = xfer_payload_prep_next(handle, "data chunk", hstc_current, sstc, - NULL, NULL, NULL); - -exit: - // tries to get the flashing status anyway... - rc = run_fwupdater_get_status(handle, hstc, sstc, &status); - if (!rc) { - if (status.status) { - LOG_ERR("Flashing failed, fw updater status %#x (errors: sub %#x, cksum %u, rram %u, crypto %d)\n", - status.status, status.suberror, - status.cksum_errors, status.rram_errors, - status.crypto_errors); - rc = status.status; - } else { - if (gstats_ss_rdy_timeouts + gstats_spi_errors + - status.cksum_errors + status.rram_errors + - status.crypto_errors) { - LOG_WARN( - "Flashing succeeded with errors (host %u, ss_rdy_timeout %u, QM %u, cksum %u, rram %u, crypto %d)\n", - gstats_spi_errors, - gstats_ss_rdy_timeouts, - status.spi_errors, status.cksum_errors, - status.rram_errors, - status.crypto_errors); - } else { - LOG_INFO( - "Flashing succeeded without any errors\n"); - } - } - } else { - LOG_ERR("run_fwupdater_get_status returned %d\n", rc); - } -exit_nomem: - if (rx) - qmrom_free(rx); - if (tx) - qmrom_free(tx); - return rc; -} diff --git a/libfwupdater/tests/comms_tests.c b/libfwupdater/tests/comms_tests.c deleted file mode 100644 index 6ce3333..0000000 --- a/libfwupdater/tests/comms_tests.c +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 -/* - * Copyright 2023 Qorvo US, Inc. - * - */ - -#include <stddef.h> -#include <qmrom_spi.h> -#include <qmrom_log.h> -#include <qmrom_utils.h> - -#include "unit_tests.h" - -void run_fwupdater_read_test(void *spi_handle) -{ - u_int8_t rx[MESSAGE_LEN]; - u_int8_t tx_poll[STC_LEN] = { 0 }; - u_int8_t tx[MESSAGE_LEN] = { 0x80, 0x00, MESSAGE_LEN - 4, - 0x00, 0x01, 0x02, - 0x03, 0x4, 0x5, - 0x6, 0x7, 0x8 }; - qmrom_msleep(100); - - qmrom_spi_wait_for_ready_line(spi_handle, 100); - qmrom_spi_transfer(spi_handle, rx, tx_poll, sizeof(tx_poll)); - memset(rx, 0, sizeof(tx_poll)); - - for (int i = 0; i < NB_RX_MESSAGES; i++) { - qmrom_spi_wait_for_ready_line(spi_handle, 100); - qmrom_spi_transfer(spi_handle, rx, tx, sizeof(tx)); - tx[4]++; - LOG_INFO("received:\n"); - hexdump(LOG_INFO, rx, sizeof(rx)); - memset(rx, 0, sizeof(rx)); - } - - LOG_INFO("%s done\n", __func__); -} - -void run_fwupdater_write_test(void *spi_handle) -{ - u_int8_t rx[MESSAGE_LEN]; - u_int8_t tx_prd[STC_LEN] = { 0x40, 0x00, 0x00, 0x00 }; - u_int8_t tx[MESSAGE_LEN] = { 0x20, 0x00, MESSAGE_LEN - 4, - 0x00, 0x01, 0x02, - 0x03, 0x4, 0x5, - 0x6, 0x7, 0x8 }; - - for (int i = 0; i < NB_TX_MESSAGES; i++) { - qmrom_spi_wait_for_ready_line(spi_handle, 100); - qmrom_spi_transfer(spi_handle, rx, tx_prd, sizeof(tx_prd)); - qmrom_spi_wait_for_ready_line(spi_handle, 100); - qmrom_spi_transfer(spi_handle, rx, tx, sizeof(tx)); - tx[4]++; - LOG_INFO("received:\n"); - hexdump(LOG_INFO, rx, sizeof(rx)); - memset(rx, 0, sizeof(rx)); - } - - LOG_INFO("%s done\n", __func__); -} diff --git a/libfwupdater/tests/fwpkg_tests.c b/libfwupdater/tests/fwpkg_tests.c deleted file mode 100644 index 035668a..0000000 --- a/libfwupdater/tests/fwpkg_tests.c +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 -/* - * Copyright 2023 Qorvo US, Inc. - * - */ - -#include <stddef.h> -#include <qmrom_spi.h> -#include <qmrom_log.h> -#include <qmrom_utils.h> - -#include <fwupdater.h> - -#include "unit_tests.h" - -#define PLD_CHK_PLD_SIZE 16 -#define PLD_CHK_TOTAL_SIZE \ - (sizeof(struct fw_pkg_payload_chunk_t) + PLD_CHK_PLD_SIZE) - -void run_fwupdater_download_fwpkg_test(void *spi_handle) -{ - uint8_t rx[STC_LEN + sizeof(struct fw_pkg_hdr_t)] = { 0 }; - uint8_t tx[STC_LEN + sizeof(struct fw_pkg_hdr_t)] = { - 0x80, 0x00, sizeof(struct fw_pkg_hdr_t), 0x00 - }; - struct fw_pkg_hdr_t *fwpkg = (struct fw_pkg_hdr_t *)&tx[STC_LEN]; - - /* Setup the expected fw package */ - fwpkg->magic = CRYPTO_FIRMWARE_PACK_MAGIC_VALUE; - fwpkg->version = CRYPTO_FIRMWARE_PACK_VERSION; - fwpkg->enc_mode = CRYPTO_FIRMWARE_PACK_ENC_MODE_ENCRYPTED; - fwpkg->package_type = CRYPTO_FIRMWARE_PACK_PACKAGE_TYPE_ICV; - fwpkg->enc_mode = CRYPTO_FIRMWARE_PACK_ENC_MODE_ENCRYPTED; - fwpkg->enc_algo = CRYPTO_FIRMWARE_PACK_ENC_ALGO_128BIT_AES_CTR; - strcpy((char *)fwpkg->enc_data, "encrypted data"); - strcpy((char *)fwpkg->fw_version, "firmware version"); - fwpkg->payload_len = 0xDEADBEEF; - strcpy((char *)fwpkg->tag, "AES-CMAC Tag"); - - qmrom_spi_wait_for_ready_line(spi_handle, 100); - qmrom_spi_transfer(spi_handle, (char *)rx, (char *)tx, sizeof(tx)); - LOG_INFO("received:\n"); - hexdump(LOG_INFO, rx, sizeof(tx)); - - LOG_INFO("%s done\n", __func__); -} - -void run_fwupdater_download_img_hdr_test(void *spi_handle) -{ - char rx[STC_LEN + CRYPTO_FIRMWARE_IMAGE_HDR_TOTAL_SIZE] = { 0 }; - char tx[STC_LEN + CRYPTO_FIRMWARE_IMAGE_HDR_TOTAL_SIZE] = { - (char)0x80, 0x00, CRYPTO_FIRMWARE_IMAGE_HDR_TOTAL_SIZE, 0x00 - }; - struct fw_pkg_img_hdr_t *imghdr = - (struct fw_pkg_img_hdr_t *)&tx[STC_LEN]; - - /* Setup the expected fw package */ - imghdr->magic = CRYPTO_FIRMWARE_IMAGE_MAGIC_VALUE; - imghdr->version = CRYPTO_FIRMWARE_IMAGE_VERSION; - imghdr->cert_chain_length = CRYPTO_IMAGES_CERT_PKG_SIZE; - imghdr->cert_chain_offset = 0xDEADBEEF; - imghdr->num_descs = 1; - imghdr->descs[0].offset = 0xDEADBEEF; - imghdr->descs[0].length = 0xDEADBEEF; - - qmrom_spi_wait_for_ready_line(spi_handle, 100); - qmrom_spi_transfer(spi_handle, rx, tx, sizeof(tx)); - LOG_INFO("received:\n"); - hexdump(LOG_INFO, rx, sizeof(tx)); - - LOG_INFO("%s done\n", __func__); -} - -void run_fwupdater_download_pld_chk_test(void *spi_handle) -{ - char rx[STC_LEN + PLD_CHK_TOTAL_SIZE] = { 0 }; - char tx[STC_LEN + PLD_CHK_TOTAL_SIZE] = { (char)0x80, 0x00, - PLD_CHK_TOTAL_SIZE, 0x00 }; - struct fw_pkg_payload_chunk_t *pldchk = - (struct fw_pkg_payload_chunk_t *)&tx[STC_LEN]; - - /* Setup the expected fw package */ - pldchk->magic = CRYPTO_FIRMWARE_CHUNK_MAGIC_VALUE; - pldchk->version = CRYPTO_FIRMWARE_CHUNK_VERSION; - pldchk->length = PLD_CHK_PLD_SIZE; - strcpy((char *)pldchk->payload, "payload"); - - qmrom_spi_wait_for_ready_line(spi_handle, 100); - qmrom_spi_transfer(spi_handle, rx, tx, sizeof(tx)); - LOG_INFO("received:\n"); - hexdump(LOG_INFO, rx, sizeof(tx)); - - LOG_INFO("%s done\n", __func__); -} diff --git a/libfwupdater/tests/fwupdater_unit_tests.c b/libfwupdater/tests/fwupdater_unit_tests.c deleted file mode 100644 index b17f4ac..0000000 --- a/libfwupdater/tests/fwupdater_unit_tests.c +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 -/* - * Copyright 2023 Qorvo US, Inc. - * - */ - -#include "unit_tests.h" - -void run_fwupdater_unit_tests(void *spi_handle) -{ - run_fwupdater_download_fwpkg_test(spi_handle); - run_fwupdater_download_img_hdr_test(spi_handle); - run_fwupdater_download_pld_chk_test(spi_handle); - run_fwupdater_read_test(spi_handle); - run_fwupdater_write_test(spi_handle); -} diff --git a/libfwupdater/tests/unit_tests.h b/libfwupdater/tests/unit_tests.h deleted file mode 100644 index 78d0729..0000000 --- a/libfwupdater/tests/unit_tests.h +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 -/* - * Copyright 2023 Qorvo US, Inc. - * - */ - -#ifndef __UNITTESTS_H__ -#define __UNITTESTS_H__ - -#define NB_RX_MESSAGES 5 -#define NB_TX_MESSAGES 5 -#define MESSAGE_LEN 16 -#define STC_LEN 4 - -void run_fwupdater_read_test(void *spi_handle); -void run_fwupdater_write_test(void *spi_handle); - -void run_fwupdater_download_fwpkg_test(void *spi_handle); -void run_fwupdater_download_img_hdr_test(void *spi_handle); -void run_fwupdater_download_pld_chk_test(void *spi_handle); - -#endif /* __UNITTESTS_H__ */ diff --git a/libqmrom/CMakeLists.txt b/libqmrom/CMakeLists.txt index 7227f2d..3e11781 100644 --- a/libqmrom/CMakeLists.txt +++ b/libqmrom/CMakeLists.txt @@ -1,8 +1,8 @@ set(SOURCES - src/qm357xx_rom_b0.c - src/qm357xx_rom_c0.c - src/qm357xx_rom_common.c src/qmrom_common.c + src/qmrom_a0.c + src/qmrom_b0.c + src/qmrom_c0.c src/qmrom_log.c ) diff --git a/libqmrom/include/qm357xx_fwpkg.h b/libqmrom/include/qm357xx_fwpkg.h deleted file mode 100644 index 213baa0..0000000 --- a/libqmrom/include/qm357xx_fwpkg.h +++ /dev/null @@ -1,132 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 -/* - * Copyright 2021 Qorvo US, Inc. - * - */ - -#ifndef __QM357XX_FWPKG_H__ -#define __QM357XX_FWPKG_H__ - -/* Pkg version word conversion macro */ -#define PKG_VER_TO_U32(maj, min) (((maj) << 16) | ((min) << 24)) - -/* Pkg magic word conversion macro */ -#define MAGIC_STR_TO_U32(x) \ - ((uint32_t)(((x)[3]) | ((x)[2] << 8) | ((x)[1] << 16) | ((x)[0] << 24))) - -/* Package size defines */ -#define CRYPTO_FIRMWARE_PACK_ENC_DATA_SIZE 16 -#define CRYPTO_FIRMWARE_PACK_FW_VERSION_SIZE 32 -#define CRYPTO_FIRMWARE_PACK_TAG_SIZE 16 - -/* Firmware image size define */ -#define CRYPTO_FW_PKG_IMG_HDR_IMG_NUM_MAX 8 - -/* Field values for macro firmware package */ -#define CRYPTO_MACRO_FIRMWARE_PACK_MAGIC_VALUE MAGIC_STR_TO_U32("FWMP") - -/* Field values for firmware package */ -#define CRYPTO_FIRMWARE_PACK_MAGIC_VALUE MAGIC_STR_TO_U32("CFWP") -#define CRYPTO_FIRMWARE_PACK_VERSION PKG_VER_TO_U32(1, 0) -#define CRYPTO_FIRMWARE_PACK_ENC_MODE_NOT_ENCRYPTED 0x0 -#define CRYPTO_FIRMWARE_PACK_ENC_ALGO_128BIT_AES_CTR 0x00 -#define CRYPTO_FIRMWARE_PACK_ENC_KEY_L2_SIZE 64 - -/* Field values for firmware image */ -#define CRYPTO_FIRMWARE_IMAGE_MAGIC_VALUE MAGIC_STR_TO_U32("IMGS") -#define CRYPTO_FIRMWARE_IMAGE_VERSION PKG_VER_TO_U32(1, 0) - -/* Field values for firmware chunks */ -#define CRYPTO_FIRMWARE_CHUNK_MAGIC_VALUE MAGIC_STR_TO_U32("CFWC") -#define CRYPTO_FIRMWARE_CHUNK_VERSION PKG_VER_TO_U32(1, 0) -#define CRYPTO_FIRMWARE_CHUNK_MIN_SIZE 16 - -/* fw certificate sizes */ -#define CRYPTO_IMAGES_CERT_KEY_SIZE 840 -#define CRYPTO_IMAGES_CERT_CONTENT_SIZE 868 -#define CRYPTO_IMAGES_CERT_PKG_SIZE \ - (2 * CRYPTO_IMAGES_CERT_KEY_SIZE + CRYPTO_IMAGES_CERT_CONTENT_SIZE) -#define CRYPTO_IMAGES_NB_CERTS 3 -#define CRYPTO_IMAGES_MAX_NB_IMAGES 8 - -#define CRYPTO_FIRMWARE_IMAGE_HDR_TOTAL_SIZE \ - (sizeof(struct fw_pkg_img_hdr_t) + \ - CRYPTO_IMAGES_NB_CERTS * sizeof(struct fw_img_desc_t)) - -/* Encryption mode enum. */ -enum fw_pkg_enc_mode_e { - CRYPTO_FIRMWARE_PACK_ENC_MODE_NONE, - CRYPTO_FIRMWARE_PACK_ENC_MODE_ENCRYPTED -}; - -/* Package type enum. */ -enum fw_pkg_package_type_e { - CRYPTO_FIRMWARE_PACK_PACKAGE_TYPE_ICV = 0x01, - CRYPTO_FIRMWARE_PACK_PACKAGE_TYPE_OEM = 0x02 -}; - -/* IV type enum. */ -enum fw_pkg_iv_type_e { - CRYPTO_FIRMWARE_PACK_IV_TYPE_HDR, - CRYPTO_FIRMWARE_PACK_IV_TYPE_IMG -}; - -/* Firmware Package Header fields */ -struct fw_pkg_hdr_t { - uint32_t magic; /**< Magic number. */ - uint32_t version; /**< Version. */ - uint8_t package_type; /**< Package type. */ - uint8_t enc_mode; /**< Encryption mode. */ - uint8_t enc_algo; /**< Encryption algorithm. */ - uint8_t reserved; /**< Reserved for alignment. */ - uint8_t enc_data - [CRYPTO_FIRMWARE_PACK_ENC_DATA_SIZE]; /**< Encryption data. */ - uint8_t enc_key_l2 - [CRYPTO_FIRMWARE_PACK_ENC_KEY_L2_SIZE]; /**< Code encryption L2 key data. */ - uint8_t fw_version - [CRYPTO_FIRMWARE_PACK_FW_VERSION_SIZE]; /**< Firmware version included in the package. */ - uint32_t payload_len; /**< Payload length. */ - uint8_t tag[CRYPTO_FIRMWARE_PACK_TAG_SIZE]; /**< AES-CMAC Tag. */ -} __attribute__((packed)); - -/* Firmware Image Metadata fields */ -struct fw_img_desc_t { - uint32_t offset; /**< Offset. */ - uint32_t length; /**< Length. */ -} __attribute__((packed)); - -/* Firmware Image Header fields */ -struct fw_pkg_img_hdr_t { - uint32_t magic; /**< Magic number. */ - uint32_t version; /**< Version number. */ - uint32_t cert_chain_offset; /**< Certificate chain offset. */ - uint16_t cert_chain_length; /**< Certificate chain length. */ - uint8_t num_descs; /**< Number of images descriptors. */ - uint8_t reserved; /**< Reserved data. */ - struct fw_img_desc_t descs - [CRYPTO_FW_PKG_IMG_HDR_IMG_NUM_MAX]; /**< Firmware image metadata. */ -} __attribute__((packed)); - -/* Firmware Chunk fields */ -struct fw_pkg_payload_chunk_t { - uint32_t magic; /**< Magic number. */ - uint32_t version; /**< Version number. */ - uint32_t length; /**< Length. */ - uint8_t payload[]; /**< Payload data pointer. */ -} __attribute__((packed)); - -/* Firmware Macro Package Header fields */ -struct fw_macro_pkg_hdr_t { - uint32_t magic; /**< Magic number. */ - uint32_t version; /**< Version. */ - uint8_t nb_descriptors; - uint8_t reserved[3]; - struct fw_img_desc_t img_desc[]; -} __attribute__((packed)); - -#define MACRO_PKG_HASH_SIZE (32) -#define COMPUTE_FW_MACRO_PKG_HDR_SIZE(ndescs) \ - (sizeof(struct fw_macro_pkg_hdr_t) + \ - ndescs * sizeof(struct fw_img_desc_t) + MACRO_PKG_HASH_SIZE) - -#endif /* __QM357XX_FWPKG_H__ */ diff --git a/libqmrom/include/qm357xx_rom.h b/libqmrom/include/qm357xx_rom.h deleted file mode 100644 index 9592004..0000000 --- a/libqmrom/include/qm357xx_rom.h +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 -/* - * Copyright 2021 Qorvo US, Inc. - * - */ - -#ifndef __QM357XX_ROM_H__ -#define __QM357XX_ROM_H__ - -#define PEG_ERR_TIMEOUT PEG_ERR_BASE - 1 -#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 - -#define HBK_LOC 12 -typedef enum { - HBK_2E_ICV, - HBK_2E_OEM, - HBK_1E_ICV_OEM, -} hbk_t; - -#define ROM_VERSION_A0 0x01a0 -#define ROM_VERSION_B0 0xb000 - -#define QM357XX_ROM_SOC_ID_LEN 0x20 -#define QM357XX_ROM_UUID_LEN 0x10 - -/* Life cycle state definitions. */ - -/*! Defines the CM life-cycle state value. */ -#define CC_BSV_CHIP_MANUFACTURE_LCS 0x0 -/*! Defines the DM life-cycle state value. */ -#define CC_BSV_DEVICE_MANUFACTURE_LCS 0x1 -/*! Defines the Secure life-cycle state value. */ -#define CC_BSV_SECURE_LCS 0x5 -/*! Defines the RMA life-cycle state value. */ -#define CC_BSV_RMA_LCS 0x7 - -struct unstitched_firmware { - struct firmware *fw_img; - struct firmware *fw_crt; - struct firmware *key1_crt; - struct firmware *key2_crt; -}; - -/* Those functions allow the libqmrom to call - * revision specific functions - */ -typedef int (*flash_fw_fn)(struct qmrom_handle *handle, - const struct firmware *fw); -typedef int (*flash_unstitched_fw_fn)(struct qmrom_handle *handle, - const struct unstitched_firmware *fw); -typedef int (*flash_debug_cert_fn)(struct qmrom_handle *handle, - struct firmware *dbg_cert); -typedef int (*erase_debug_cert_fn)(struct qmrom_handle *handle); - -struct qm357xx_rom_code_ops { - flash_fw_fn flash_fw; - flash_unstitched_fw_fn flash_unstitched_fw; - flash_debug_cert_fn flash_debug_cert; - erase_debug_cert_fn erase_debug_cert; -}; - -struct qm357xx_soc_infos { - uint8_t soc_id[QM357XX_ROM_SOC_ID_LEN]; - uint8_t uuid[QM357XX_ROM_UUID_LEN]; - uint32_t lcs_state; -}; - -int qm357xx_rom_unstitch_fw(const struct firmware *fw, - struct unstitched_firmware *unstitched_fw, - enum chip_revision_e revision); -int qm357xx_rom_fw_macro_pkg_get_fw_idx(const struct firmware *fw, int idx, - uint32_t *fw_size, char **fw_fata); -int qm357xx_rom_unpack_fw_macro_pkg(const struct firmware *fw, - struct unstitched_firmware *all_fws); -int qm357xx_rom_unpack_fw_pkg(const struct firmware *fw_pkg, - struct unstitched_firmware *all_fws); -int qm357xx_rom_flash_dbg_cert(struct qmrom_handle *handle, - struct firmware *dbg_cert); -int qm357xx_rom_erase_dbg_cert(struct qmrom_handle *handle); -int qm357xx_rom_flash_fw(struct qmrom_handle *handle, - const struct firmware *fw); -int qm357xx_rom_flash_unstitched_fw(struct qmrom_handle *handle, - const struct unstitched_firmware *fw); - -int qm357xx_rom_write_cmd(struct qmrom_handle *handle, uint8_t cmd); -int qm357xx_rom_write_cmd32(struct qmrom_handle *handle, uint32_t cmd); -int qm357xx_rom_write_size_cmd(struct qmrom_handle *handle, uint8_t cmd, - uint16_t data_size, const char *data); -int qm357xx_rom_write_size_cmd32(struct qmrom_handle *handle, uint32_t cmd, - uint16_t data_size, const char *data); - -#endif /* __QM357XX_ROM_H__ */ diff --git a/libqmrom/include/qmrom.h b/libqmrom/include/qmrom.h index 226b7f4..c403ed1 100644 --- a/libqmrom/include/qmrom.h +++ b/libqmrom/include/qmrom.h @@ -28,19 +28,54 @@ #undef CHECK_STCS +#define PEG_ERR_TIMEOUT PEG_ERR_BASE - 1 +#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, CHIP_REVISION_B0 = 0xB0, CHIP_REVISION_C0 = 0xC0, - CHIP_REVISION_C2 = 0xC2, CHIP_REVISION_UNKNOWN = 0xFF }; -enum device_generation_e { DEVICE_GEN_QM357XX, DEVICE_GEN_UNKNOWN = 0xFF }; +#define HBK_LOC 12 +typedef enum { + HBK_2E_ICV = 0, + HBK_2E_OEM = 1, + HBK_1E_ICV_OEM = 2, +} hbk_t; + +#define ROM_VERSION_A0 0x01a0 +#define ROM_VERSION_B0 0xb000 + +#define ROM_SOC_ID_LEN 0x20 +#define ROM_UUID_LEN 0x10 + +/* Life cycle state definitions. */ + +/*! Defines the CM life-cycle state value. */ +#define CC_BSV_CHIP_MANUFACTURE_LCS 0x0 +/*! Defines the DM life-cycle state value. */ +#define CC_BSV_DEVICE_MANUFACTURE_LCS 0x1 +/*! Defines the Secure life-cycle state value. */ +#define CC_BSV_SECURE_LCS 0x5 +/*! Defines the RMA life-cycle state value. */ +#define CC_BSV_RMA_LCS 0x7 + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" struct qmrom_handle; -#include <qm357xx_rom.h> +struct unstitched_firmware { + struct firmware *fw_img; + struct firmware *fw_crt; + struct firmware *key1_crt; + struct firmware *key2_crt; +}; #define SSTC2UINT32(handle, offset) \ ({ \ @@ -61,6 +96,24 @@ struct qmrom_handle; }) /* Those functions allow the libqmrom to call + * revision specific functions + */ +typedef int (*flash_fw_fn)(struct qmrom_handle *handle, + const struct firmware *fw); +typedef int (*flash_unstitched_fw_fn)(struct qmrom_handle *handle, + const struct unstitched_firmware *fw); +typedef int (*flash_debug_cert_fn)(struct qmrom_handle *handle, + struct firmware *dbg_cert); +typedef int (*erase_debug_cert_fn)(struct qmrom_handle *handle); + +struct rom_code_ops { + flash_fw_fn flash_fw; + flash_unstitched_fw_fn flash_unstitched_fw; + flash_debug_cert_fn flash_debug_cert; + erase_debug_cert_fn erase_debug_cert; +}; + +/* Those functions allow the libqmrom to call * device specific functions */ typedef int (*reset_device_fn)(void *handle); @@ -73,30 +126,42 @@ struct qmrom_handle { void *spi_handle; void *reset_handle; void *ss_rdy_handle; - void *ss_irq_handle; int comms_retries; - enum device_generation_e dev_gen; enum chip_revision_e chip_rev; uint16_t device_version; struct device_ops dev_ops; - int spi_speed; - struct qm357xx_rom_code_ops qm357xx_rom_ops; + struct rom_code_ops rom_ops; + uint32_t lcs_state; struct stc *hstc; struct stc *sstc; - struct qm357xx_soc_infos qm357xx_soc_info; + uint8_t soc_id[ROM_SOC_ID_LEN]; + uint8_t uuid[ROM_UUID_LEN]; bool is_be; }; +int qmrom_unstitch_fw(const struct firmware *fw, + struct unstitched_firmware *unstitched_fw, + enum chip_revision_e revision); struct qmrom_handle *qmrom_init(void *spi_handle, void *reset_handle, - void *ss_rdy_handle, void *ss_irq_handle, - int spi_speed, int comms_retries, - reset_device_fn reset, - enum device_generation_e dev_gen_hint); + void *ss_rdy_handle, int comms_retries, + reset_device_fn reset); void qmrom_deinit(struct qmrom_handle *handle); int qmrom_reboot_bootloader(struct qmrom_handle *handle); +int qmrom_flash_dbg_cert(struct qmrom_handle *handle, + struct firmware *dbg_cert); +int qmrom_erase_dbg_cert(struct qmrom_handle *handle); +int qmrom_flash_fw(struct qmrom_handle *handle, const struct firmware *fw); +int qmrom_flash_unstitched_fw(struct qmrom_handle *handle, + const struct unstitched_firmware *fw); int qmrom_pre_read(struct qmrom_handle *handle); int qmrom_read(struct qmrom_handle *handle); +int qmrom_write_cmd(struct qmrom_handle *handle, uint8_t cmd); +int qmrom_write_cmd32(struct qmrom_handle *handle, uint32_t cmd); +int qmrom_write_size_cmd(struct qmrom_handle *handle, uint8_t cmd, + uint16_t data_size, const char *data); +int qmrom_write_size_cmd32(struct qmrom_handle *handle, uint32_t cmd, + uint16_t data_size, const char *data); #ifdef CHECK_STCS void check_stcs(const char *func, int line, struct qmrom_handle *h); diff --git a/libqmrom/include/qmrom_spi.h b/libqmrom/include/qmrom_spi.h index c94e544..c3d8c92 100644 --- a/libqmrom/include/qmrom_spi.h +++ b/libqmrom/include/qmrom_spi.h @@ -50,13 +50,9 @@ 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, struct qmrom_handle *qmrom_h, - bool *is_fw_updater, bool use_prod_fw); -const struct firmware *qmrom_spi_get_firmware_package(void *handle, - int lcs_state); void qmrom_spi_release_firmware(const struct firmware *fw); int qmrom_spi_wait_for_ready_line(void *handle, unsigned int timeout_ms); -int qmrom_spi_read_irq_line(void *handle); void qmrom_spi_set_freq(unsigned int freq); unsigned int qmrom_spi_get_freq(void); diff --git a/libqmrom/include/qmrom_utils.h b/libqmrom/include/qmrom_utils.h index 7533194..06ece2a 100644 --- a/libqmrom/include/qmrom_utils.h +++ b/libqmrom/include/qmrom_utils.h @@ -31,26 +31,21 @@ extern void usleep(unsigned int us); } while (0) #define qmrom_free free - -#define qmrom_data_dma_able(d) true #else #include <linux/delay.h> #include <linux/slab.h> -#include <linux/mm.h> #define qmrom_msleep(ms) \ do { \ usleep_range(ms * 1000, ms * 1000); \ } while (0) -#define qmrom_alloc(ptr, size) \ - do { \ - ptr = kzalloc(size, GFP_KERNEL | GFP_DMA); \ +#define qmrom_alloc(ptr, size) \ + do { \ + ptr = kzalloc(size, GFP_KERNEL); \ } while (0) #define qmrom_free kfree - -#define qmrom_data_dma_able(d) !is_vmalloc_addr(d) #endif #endif /* __QMROM_UTILS_H__ */ diff --git a/libqmrom/src/qm357xx_rom_common.c b/libqmrom/src/qm357xx_rom_common.c deleted file mode 100644 index 051cc3d..0000000 --- a/libqmrom/src/qm357xx_rom_common.c +++ /dev/null @@ -1,414 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 -/* - * Copyright 2022 Qorvo US, Inc. - * - */ - -#include <qmrom_utils.h> -#include <qmrom_log.h> -#include <qmrom_spi.h> -#include <qmrom.h> -#include <spi_rom_protocol.h> - -#include <qm357xx_fwpkg.h> - -int qm357xx_rom_b0_probe_device(struct qmrom_handle *handle); -int qm357xx_rom_c0_probe_device(struct qmrom_handle *handle); - -int qm357xx_rom_write_cmd(struct qmrom_handle *handle, uint8_t cmd) -{ - handle->hstc->all = 0; - handle->hstc->host_flags.write = 1; - handle->hstc->ul = 1; - handle->hstc->len = 1; - handle->hstc->payload[0] = cmd; - - return qmrom_spi_transfer(handle->spi_handle, (char *)handle->sstc, - (const char *)handle->hstc, - sizeof(struct stc) + handle->hstc->len); -} - -int qm357xx_rom_write_cmd32(struct qmrom_handle *handle, uint32_t cmd) -{ - handle->hstc->all = 0; - handle->hstc->host_flags.write = 1; - handle->hstc->ul = 1; - handle->hstc->len = sizeof(cmd); - memcpy(handle->hstc->payload, &cmd, sizeof(cmd)); - - return qmrom_spi_transfer(handle->spi_handle, (char *)handle->sstc, - (const char *)handle->hstc, - sizeof(struct stc) + handle->hstc->len); -} - -int qm357xx_rom_write_size_cmd(struct qmrom_handle *handle, uint8_t cmd, - uint16_t data_size, const char *data) -{ - handle->hstc->all = 0; - handle->hstc->host_flags.write = 1; - handle->hstc->ul = 1; - handle->hstc->len = data_size + 1; - handle->hstc->payload[0] = cmd; - memcpy(&handle->hstc->payload[1], data, data_size); - - return qmrom_spi_transfer(handle->spi_handle, (char *)handle->sstc, - (const char *)handle->hstc, - sizeof(struct stc) + handle->hstc->len); -} - -int qm357xx_rom_write_size_cmd32(struct qmrom_handle *handle, uint32_t cmd, - uint16_t data_size, const char *data) -{ - handle->hstc->all = 0; - handle->hstc->host_flags.write = 1; - handle->hstc->ul = 1; - handle->hstc->len = data_size + sizeof(cmd); - memcpy(handle->hstc->payload, &cmd, sizeof(cmd)); - memcpy(&handle->hstc->payload[sizeof(cmd)], data, data_size); - - return qmrom_spi_transfer(handle->spi_handle, (char *)handle->sstc, - (const char *)handle->hstc, - sizeof(struct stc) + handle->hstc->len); -} - -/* - * Unfortunately, B0 and C0 have different - * APIs to get the chip version... - * - */ -int qm357xx_rom_probe_device(struct qmrom_handle *handle) -{ - int rc; - - /* Test C0 first */ - rc = qm357xx_rom_c0_probe_device(handle); - if (!rc) - return rc; - - /* Test B0 next */ - rc = qm357xx_rom_b0_probe_device(handle); - if (!rc) - return rc; - - /* None matched!!! */ - return -1; -} - -int qm357xx_rom_flash_dbg_cert(struct qmrom_handle *handle, - struct firmware *dbg_cert) -{ - if (!handle->qm357xx_rom_ops.flash_debug_cert) { - LOG_ERR("%s: flash debug certificate not support on this device\n", - __func__); - return -EINVAL; - } - return handle->qm357xx_rom_ops.flash_debug_cert(handle, dbg_cert); -} - -int qm357xx_rom_erase_dbg_cert(struct qmrom_handle *handle) -{ - if (!handle->qm357xx_rom_ops.erase_debug_cert) { - LOG_ERR("%s: erase debug certificate not support on this device\n", - __func__); - return -EINVAL; - } - return handle->qm357xx_rom_ops.erase_debug_cert(handle); -} - -int qm357xx_rom_flash_fw(struct qmrom_handle *handle, const struct firmware *fw) -{ - int rc = 0; - struct unstitched_firmware all_fws = { 0 }; - - if (*(uint32_t *)&fw->data[0] == - CRYPTO_MACRO_FIRMWARE_PACK_MAGIC_VALUE) { - //macro package detected - //write the FW UPDATER - rc = qm357xx_rom_unpack_fw_macro_pkg(fw, &all_fws); - if (rc) { - LOG_ERR("%s: Unpack macro FW package unsuccessful!\n", - __func__); - return rc; - } - } else { - rc = qm357xx_rom_unstitch_fw(fw, &all_fws, handle->chip_rev); - if (rc) { - LOG_ERR("%s: Unstitched fw flashing not supported yet\n", - __func__); - return rc; - } - } - rc = qm357xx_rom_flash_unstitched_fw(handle, &all_fws); - return rc; -} - -int qm357xx_rom_flash_unstitched_fw(struct qmrom_handle *handle, - const struct unstitched_firmware *fw) -{ - if (!handle->qm357xx_rom_ops.flash_unstitched_fw) { - LOG_ERR("%s: flash un-stitched firmware not supported on this device\n", - __func__); - return -EINVAL; - } - return handle->qm357xx_rom_ops.flash_unstitched_fw(handle, fw); -} - -int qm357xx_rom_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 (fw->size < 2 * sizeof(key1_crt_sz)) { - LOG_ERR("%s: Not enough data (%zu) to unstitch\n", __func__, - fw->size); - return -EINVAL; - } - LOG_INFO("%s: Unstitching %zu bytes\n", __func__, fw->size); - - /* key1 */ - key1_crt_sz = *(uint32_t *)&fw->data[tot_len]; - if (tot_len + key1_crt_sz + sizeof(key1_crt_sz) + sizeof(key2_crt_sz) > - fw->size) { - LOG_ERR("%s: Invalid or corrupted stitched file at offset \ - %" PRIu32 " (key1)\n", - __func__, tot_len); - ret = -EINVAL; - goto out; - } - tot_len += sizeof(key1_crt_sz); - p_key1 = (uint8_t *)&fw->data[tot_len]; - tot_len += key1_crt_sz; - - /* key2 */ - key2_crt_sz = *(uint32_t *)&fw->data[tot_len]; - if (tot_len + key2_crt_sz + sizeof(key2_crt_sz) + sizeof(fw_crt_sz) > - fw->size) { - LOG_ERR("%s: Invalid or corrupted stitched file at offset \ - %" PRIu32 " (key2)\n", - __func__, tot_len); - ret = -EINVAL; - goto out; - } - tot_len += sizeof(key2_crt_sz); - p_key2 = (uint8_t *)&fw->data[tot_len]; - tot_len += key2_crt_sz; - - /* cert */ - fw_crt_sz = *(uint32_t *)&fw->data[tot_len]; - if (tot_len + fw_crt_sz + sizeof(fw_crt_sz) + sizeof(fw_img_sz) > - fw->size) { - LOG_ERR("%s: Invalid or corrupted stitched file at offset \ - %" PRIu32 " (content cert)\n", - __func__, tot_len); - ret = -EINVAL; - goto out; - } - tot_len += sizeof(fw_crt_sz); - p_crt = (uint8_t *)&fw->data[tot_len]; - tot_len += fw_crt_sz; - - /* fw */ - fw_img_sz = *(uint32_t *)&fw->data[tot_len]; - if (tot_len + fw_img_sz + sizeof(fw_img_sz) != fw->size) { - LOG_ERR("%s: Invalid or corrupted stitched file at offset \ - %" PRIu32 " (firmware)\n", - __func__, tot_len); - ret = -EINVAL; - goto out; - } - tot_len += sizeof(fw_img_sz); - p_fw = (uint8_t *)&fw->data[tot_len]; - - qmrom_alloc(unstitched_fw->fw_img, fw_img_sz + sizeof(struct firmware)); - if (unstitched_fw->fw_img == NULL) { - ret = -ENOMEM; - goto out; - } - - qmrom_alloc(unstitched_fw->fw_crt, fw_crt_sz + sizeof(struct firmware)); - if (unstitched_fw->fw_crt == NULL) { - ret = -ENOMEM; - goto err; - } - - qmrom_alloc(unstitched_fw->key1_crt, - key1_crt_sz + sizeof(struct firmware)); - if (unstitched_fw->key1_crt == NULL) { - ret = -ENOMEM; - goto err; - } - - qmrom_alloc(unstitched_fw->key2_crt, - key2_crt_sz + sizeof(struct firmware)); - if (unstitched_fw->key2_crt == NULL) { - ret = -ENOMEM; - goto err; - } - - unstitched_fw->key1_crt->data = - (const uint8_t *)(unstitched_fw->key1_crt + 1); - unstitched_fw->key2_crt->data = - (const uint8_t *)(unstitched_fw->key2_crt + 1); - unstitched_fw->fw_crt->data = - (const uint8_t *)(unstitched_fw->fw_crt + 1); - unstitched_fw->fw_img->data = - (const uint8_t *)(unstitched_fw->fw_img + 1); - 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; - - memcpy((void *)unstitched_fw->key1_crt->data, p_key1, key1_crt_sz); - memcpy((void *)unstitched_fw->key2_crt->data, p_key2, key2_crt_sz); - memcpy((void *)unstitched_fw->fw_crt->data, p_crt, fw_crt_sz); - memcpy((void *)unstitched_fw->fw_img->data, p_fw, fw_img_sz); - return 0; - -err: - if (unstitched_fw->fw_img) - qmrom_free(unstitched_fw->fw_img); - if (unstitched_fw->fw_crt) - qmrom_free(unstitched_fw->fw_crt); - if (unstitched_fw->key1_crt) - qmrom_free(unstitched_fw->key1_crt); - if (unstitched_fw->key2_crt) - qmrom_free(unstitched_fw->key2_crt); - -out: - return ret; -} - -int qm357xx_rom_fw_macro_pkg_get_fw_idx(const struct firmware *fw, int idx, - uint32_t *fw_size, char **fw_data) -{ - struct fw_macro_pkg_hdr_t *fw_macro_pkg_hdr = - (struct fw_macro_pkg_hdr_t *)fw->data; - struct fw_img_desc_t *fw_pkg; - - if (fw_macro_pkg_hdr->nb_descriptors >= 1 && - idx < fw_macro_pkg_hdr->nb_descriptors) { - fw_pkg = &fw_macro_pkg_hdr->img_desc[idx]; - if (fw_pkg->offset + fw_pkg->length > fw->size) { - LOG_ERR("Wrong FW PKG offset = %04x; len = %04x; idx = %d!\n", - fw_pkg->offset, fw_pkg->length, idx); - return -EINVAL; - } - } else { - LOG_ERR("%s: No FW pkg found in macro package! nb_descriptors = %d\n", - __func__, fw_macro_pkg_hdr->nb_descriptors); - return -EINVAL; - } - *fw_size = fw_pkg->length; - *fw_data = (char *)&fw->data[fw_pkg->offset]; - return 0; -} - -int qm357xx_rom_unpack_fw_macro_pkg(const struct firmware *fw, - struct unstitched_firmware *all_fws) -{ - int rc = 0; - char *fw_data; - uint32_t fw_size; - struct firmware fw_pkg; - - rc = qm357xx_rom_fw_macro_pkg_get_fw_idx(fw, 0, &fw_size, &fw_data); - if (rc) { - LOG_ERR("%s: FW MACRO PACKAGE corrupted = %d\n", __func__, rc); - return rc; - } - - fw_pkg.data = (const uint8_t *)fw_data; - fw_pkg.size = fw_size; - return qm357xx_rom_unpack_fw_pkg(&fw_pkg, all_fws); -} - -int qm357xx_rom_unpack_fw_pkg(const struct firmware *fw_pkg, - struct unstitched_firmware *all_fws) -{ - int rc = 0; - uint8_t *p_key1; - uint8_t *p_key2; - uint8_t *p_crt; - uint8_t *p_fw; - struct fw_pkg_img_hdr_t *fw_pkg_img_hdr; - - fw_pkg_img_hdr = - (struct fw_pkg_img_hdr_t *)(fw_pkg->data + - sizeof(struct fw_pkg_hdr_t)); - - if (fw_pkg_img_hdr->magic != CRYPTO_FIRMWARE_IMAGE_MAGIC_VALUE) { - LOG_ERR("%s: Invalid or corrupted file! magic = %04x\n", - __func__, fw_pkg_img_hdr->magic); - return -EINVAL; - } - qmrom_alloc(all_fws->fw_img, - fw_pkg_img_hdr->descs[0].length + sizeof(struct firmware)); - if (all_fws->fw_img == NULL) { - rc = -ENOMEM; - goto err; - } - qmrom_alloc(all_fws->key1_crt, - CRYPTO_IMAGES_CERT_KEY_SIZE + sizeof(struct firmware)); - if (all_fws->key1_crt == NULL) { - rc = -ENOMEM; - goto err; - } - - qmrom_alloc(all_fws->key2_crt, - CRYPTO_IMAGES_CERT_KEY_SIZE + sizeof(struct firmware)); - if (all_fws->key2_crt == NULL) { - rc = -ENOMEM; - goto err; - } - - qmrom_alloc(all_fws->fw_crt, - CRYPTO_IMAGES_CERT_CONTENT_SIZE + sizeof(struct firmware)); - if (all_fws->fw_crt == NULL) { - rc = -ENOMEM; - goto err; - } - - all_fws->key1_crt->data = (const uint8_t *)(all_fws->key1_crt + 1); - all_fws->key2_crt->data = (const uint8_t *)(all_fws->key2_crt + 1); - all_fws->fw_crt->data = (const uint8_t *)(all_fws->fw_crt + 1); - all_fws->fw_img->data = (const uint8_t *)(all_fws->fw_img + 1); - all_fws->key1_crt->size = CRYPTO_IMAGES_CERT_KEY_SIZE; - all_fws->key2_crt->size = CRYPTO_IMAGES_CERT_KEY_SIZE; - all_fws->fw_crt->size = CRYPTO_IMAGES_CERT_CONTENT_SIZE; - all_fws->fw_img->size = fw_pkg_img_hdr->descs[0].length; - - p_key1 = (uint8_t *)fw_pkg_img_hdr + fw_pkg_img_hdr->cert_chain_offset; - p_key2 = p_key1 + CRYPTO_IMAGES_CERT_KEY_SIZE; - p_crt = p_key2 + CRYPTO_IMAGES_CERT_KEY_SIZE; - p_fw = (uint8_t *)fw_pkg_img_hdr + fw_pkg_img_hdr->descs[0].offset; - - memcpy((void *)all_fws->key1_crt->data, p_key1, - all_fws->key1_crt->size); - memcpy((void *)all_fws->key2_crt->data, p_key2, - all_fws->key2_crt->size); - memcpy((void *)all_fws->fw_crt->data, p_crt, all_fws->fw_crt->size); - memcpy((void *)all_fws->fw_img->data, p_fw, all_fws->fw_img->size); - return 0; - -err: - if (all_fws->fw_img) - qmrom_free(all_fws->fw_img); - if (all_fws->fw_crt) - qmrom_free(all_fws->fw_crt); - if (all_fws->key1_crt) - qmrom_free(all_fws->key1_crt); - if (all_fws->key2_crt) - qmrom_free(all_fws->key2_crt); - - return rc; -} diff --git a/libqmrom/src/qmrom_a0.c b/libqmrom/src/qmrom_a0.c new file mode 100644 index 0000000..ce75612 --- /dev/null +++ b/libqmrom/src/qmrom_a0.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 +/* + * Copyright 2022 Qorvo US, Inc. + * + */ + +#include <qmrom.h> +#include <qmrom_spi.h> +#include <qmrom_log.h> +#include <qmrom_utils.h> +#include <spi_rom_protocol.h> + +#define DEFAULT_SPI_CLOCKRATE 750000 +#define CHIP_VERSION_CHIP_REV_PAYLOAD_OFFSET 1 +#define CHUNK_SIZE_A0 1016 + +enum A0_CMD { + ROM_CMD_A0_GET_CHIP_VER = 0x0, + ROM_CMD_A0_DOWNLOAD_RRAM_CMD = 0x40, +}; + +enum A0_RESP { + /* Waiting for download command */ + SPI_RSP_WAIT_DOWNLOAD_MODE = 1, + SPI_RSP_WAIT_FOR_KEY1_CERT, + SPI_RSP_WAIT_FOR_KEY2_CERT, + SPI_RSP_WAIT_FOR_IMAGE_CERT, + SPI_RSP_WAIT_IMAGE_SIZE, + SPI_RSP_WAIT_FOR_IMAGE, + SPI_RSP_DOWNLOAD_OK, + SPI_RSP_BOOT_OK, + /* Checksum/CRC error */ + SPI_RSP_ERROR_CS, + /* Got error certificate RSA/FW ver. Didn't get + * all the data before switching to image... + */ + SPI_RSP_ERROR_CERTIFICATE, + /* Got command smaller than SPI_HEADER_SIZE. + * Each command must be at least this size. + */ + SPI_RSP_CMD_TOO_SHORT, + /* Error checking certificates or image, going + * to download mode. + */ + SPI_RSP_ERROR_LOADING_IN_DOWNLOAD, +}; + +static int qmrom_a0_flash_fw(struct qmrom_handle *handle, + const struct firmware *fw); + +void qmrom_a0_poll_soc(struct qmrom_handle *handle) +{ + int retries = handle->comms_retries; + handle->hstc->all = 0; + qmrom_msleep(SPI_READY_TIMEOUT_MS); + do { + qmrom_spi_transfer(handle->spi_handle, (char *)handle->sstc, + (const char *)handle->hstc, 1); + } while (retries-- && handle->sstc->raw_flags == 0); +} + +int qmrom_a0_wait_ready(struct qmrom_handle *handle) +{ + int retries = handle->comms_retries; + qmrom_a0_poll_soc(handle); + + while (retries-- && !handle->sstc->soc_flags.out_waiting) { + qmrom_a0_poll_soc(handle); + } + return handle->sstc->soc_flags.out_waiting ? 0 : + SPI_ERR_WAIT_READY_TIMEOUT; +} + +int qmrom_a0_probe_device(struct qmrom_handle *handle) +{ + int rc; + LOG_DBG("%s: enters...\n", __func__); + handle->is_be = true; + + qmrom_spi_set_freq(DEFAULT_SPI_CLOCKRATE); + + rc = qmrom_reboot_bootloader(handle); + if (rc) { + LOG_ERR("%s: cannot reset the device...\n", __func__); + return rc; + } + + rc = qmrom_a0_wait_ready(handle); + if (rc) { + LOG_INFO("%s: maybe not a A0 device\n", __func__); + return rc; + } + qmrom_pre_read(handle); + handle->sstc->len = bswap_16(handle->sstc->len); + if (handle->sstc->len > 0xff) { + /* likely the wrong endianness, B0 or C0? */ + return -1; + } + qmrom_read(handle); + + LOG_DBG("%s: Set the chip_rev/device_version\n", __func__); + handle->chip_rev = + bswap_16(SSTC2UINT16(handle, + CHIP_VERSION_CHIP_REV_PAYLOAD_OFFSET)) & + 0xFF; + + if (handle->chip_rev != CHIP_REVISION_A0) { + LOG_ERR("%s: wrong chip revision %#x\n", __func__, + handle->chip_rev); + handle->chip_rev = -1; + return -1; + } + + /* Set rom ops */ + handle->rom_ops.flash_fw = qmrom_a0_flash_fw; + handle->rom_ops.flash_debug_cert = NULL; + handle->rom_ops.erase_debug_cert = NULL; + return 0; +} + +int qmrom_a0_write_data(struct qmrom_handle *handle, uint16_t data_size, + const char *data) +{ + handle->hstc->all = 0; + handle->hstc->host_flags.write = 1; + handle->hstc->ul = 1; + handle->hstc->len = data_size; + memcpy(handle->hstc->payload, data, data_size); + + return qmrom_spi_transfer(handle->spi_handle, (char *)handle->sstc, + (const char *)handle->hstc, + sizeof(struct stc) + data_size); +} + +static int qmrom_a0_write_chunks(struct qmrom_handle *handle, + const struct firmware *fw) +{ + int rc, sent = 0; + const char *bin_data = (const char *)fw->data; + + check_stcs(__func__, __LINE__, handle); + while (sent < fw->size) { + uint32_t tx_bytes = fw->size - sent; + if (tx_bytes > CHUNK_SIZE_A0) + tx_bytes = CHUNK_SIZE_A0; + + LOG_DBG("%s: poll soc...\n", __func__); + check_stcs(__func__, __LINE__, handle); + qmrom_a0_poll_soc(handle); + qmrom_pre_read(handle); + handle->sstc->len = bswap_16(handle->sstc->len); + qmrom_read(handle); + if (handle->sstc->payload[0] != SPI_RSP_WAIT_FOR_IMAGE) { + LOG_ERR("%s: wrong data result (%#x vs %#x)!!!\n", + __func__, handle->sstc->payload[0] & 0xff, + SPI_RSP_WAIT_FOR_IMAGE); + return SPI_PROTO_WRONG_RESP; + } + + LOG_DBG("%s: sending %" PRIu32 " bytes of data\n", __func__, + tx_bytes); + rc = qmrom_a0_write_data(handle, tx_bytes, bin_data); + if (rc) + return rc; + sent += tx_bytes; + bin_data += tx_bytes; + check_stcs(__func__, __LINE__, handle); + } + return 0; +} + +static int qmrom_a0_flash_fw(struct qmrom_handle *handle, + const struct firmware *fw) +{ + int rc = 0, resp; + + LOG_DBG("%s: starting...\n", __func__); + + /* Reboot since the rom code on A0 seems + * to have issues when starting flashing + * after some prior interaction (like GET_CHIP_VERSION) + */ + rc = qmrom_reboot_bootloader(handle); + if (rc) { + LOG_ERR("%s: cannot reset the device...\n", __func__); + return rc; + } + + rc = qmrom_a0_wait_ready(handle); + if (rc) { + LOG_ERR("%s: timedout waiting for the device to be ready\n", + __func__); + return rc; + } + qmrom_pre_read(handle); + handle->sstc->len = bswap_16(handle->sstc->len); + qmrom_read(handle); + if (handle->sstc->payload[0] != SPI_RSP_WAIT_DOWNLOAD_MODE) { + LOG_ERR("%s: wrong data result (%#x vs %#x)!!!\n", __func__, + handle->sstc->payload[0] & 0xff, + SPI_RSP_WAIT_DOWNLOAD_MODE); + return SPI_PROTO_WRONG_RESP; + } + + check_stcs(__func__, __LINE__, handle); + LOG_DBG("%s: sending ROM_CMD_A0_DOWNLOAD_RRAM_CMD command\n", __func__); + rc = qmrom_write_cmd(handle, ROM_CMD_A0_DOWNLOAD_RRAM_CMD); + if (rc) + return rc; + + for (resp = SPI_RSP_WAIT_FOR_KEY1_CERT; resp < SPI_RSP_WAIT_FOR_IMAGE; + resp++) { + qmrom_a0_poll_soc(handle); + qmrom_pre_read(handle); + handle->sstc->len = bswap_16(handle->sstc->len); + qmrom_read(handle); + 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 (resp < SPI_RSP_WAIT_IMAGE_SIZE) { + rc = qmrom_write_cmd(handle, 0); + if (rc) + return rc; + } + } + + LOG_DBG("%s: sending fw size\n", __func__); + rc = qmrom_a0_write_data(handle, sizeof(uint32_t), + (const char *)&fw->size); + if (rc) + return rc; + + check_stcs(__func__, __LINE__, handle); + rc = qmrom_a0_write_chunks(handle, fw); + check_stcs(__func__, __LINE__, handle); + return rc; +} diff --git a/libqmrom/src/qm357xx_rom_b0.c b/libqmrom/src/qmrom_b0.c index fe2c637..9b23cff 100644 --- a/libqmrom/src/qm357xx_rom_b0.c +++ b/libqmrom/src/qmrom_b0.c @@ -67,14 +67,16 @@ enum B0_RESP { ERR_DEBUG_CERT_SIZE = 0x1F, }; -static int qm357xx_rom_b0_flash_debug_cert(struct qmrom_handle *handle, - struct firmware *dbg_cert); -static int qm357xx_rom_b0_erase_debug_cert(struct qmrom_handle *handle); +static int qmrom_b0_flash_fw(struct qmrom_handle *handle, + const struct firmware *fw); +static int qmrom_b0_flash_debug_cert(struct qmrom_handle *handle, + struct firmware *dbg_cert); +static int qmrom_b0_erase_debug_cert(struct qmrom_handle *handle); static int -qm357xx_rom_b0_flash_unstitched_fw(struct qmrom_handle *handle, - const struct unstitched_firmware *all_fws); +qmrom_b0_flash_unstitched_fw(struct qmrom_handle *handle, + const struct unstitched_firmware *all_fws); -static void qm357xx_rom_b0_poll_soc(struct qmrom_handle *handle) +static void qmrom_b0_poll_soc(struct qmrom_handle *handle) { int retries = handle->comms_retries; memset(handle->hstc, 0, sizeof(struct stc)); @@ -86,12 +88,12 @@ static void qm357xx_rom_b0_poll_soc(struct qmrom_handle *handle) } while (retries-- && handle->sstc->raw_flags == 0); } -static int qm357xx_rom_b0_wait_ready(struct qmrom_handle *handle) +static int qmrom_b0_wait_ready(struct qmrom_handle *handle) { int retries = handle->comms_retries; int rc; - qm357xx_rom_b0_poll_soc(handle); + qmrom_b0_poll_soc(handle); /* handle->sstc has been updated */ while (retries-- && @@ -104,7 +106,7 @@ static int qm357xx_rom_b0_wait_ready(struct qmrom_handle *handle) return rc; } else { /* error? */ - qm357xx_rom_b0_poll_soc(handle); + qmrom_b0_poll_soc(handle); } } @@ -113,11 +115,11 @@ static int qm357xx_rom_b0_wait_ready(struct qmrom_handle *handle) SPI_ERR_WAIT_READY_TIMEOUT; } -static int qm357xx_rom_b0_poll_cmd_resp(struct qmrom_handle *handle) +static int qmrom_b0_poll_cmd_resp(struct qmrom_handle *handle) { int retries = handle->comms_retries; - qm357xx_rom_b0_poll_soc(handle); + qmrom_b0_poll_soc(handle); do { if (handle->sstc->soc_flags.out_waiting) { qmrom_pre_read(handle); @@ -128,23 +130,20 @@ static int qm357xx_rom_b0_poll_cmd_resp(struct qmrom_handle *handle) qmrom_read(handle); break; } else - qm357xx_rom_b0_poll_soc(handle); + qmrom_b0_poll_soc(handle); } while (retries--); return retries > 0 ? 0 : -1; } -int qm357xx_rom_b0_probe_device(struct qmrom_handle *handle) +int qmrom_b0_probe_device(struct qmrom_handle *handle) { int rc, i; uint8_t *soc_lcs_uuid; handle->is_be = false; check_stcs(__func__, __LINE__, handle); - if (handle->spi_speed == 0) - qmrom_spi_set_freq(DEFAULT_SPI_CLOCKRATE); - else - qmrom_spi_set_freq(handle->spi_speed); + qmrom_spi_set_freq(DEFAULT_SPI_CLOCKRATE); rc = qmrom_reboot_bootloader(handle); if (rc) { @@ -152,17 +151,17 @@ int qm357xx_rom_b0_probe_device(struct qmrom_handle *handle) return rc; } - rc = qm357xx_rom_b0_wait_ready(handle); + rc = qmrom_b0_wait_ready(handle); if (rc) { LOG_INFO("%s: maybe not a B0 device\n", __func__); return rc; } - rc = qm357xx_rom_write_cmd(handle, ROM_CMD_B0_GET_CHIP_VER); + rc = qmrom_write_cmd(handle, ROM_CMD_B0_GET_CHIP_VER); if (rc) return rc; - rc = qm357xx_rom_b0_poll_cmd_resp(handle); + rc = qmrom_b0_poll_cmd_resp(handle); if (rc) return rc; @@ -178,49 +177,42 @@ int qm357xx_rom_b0_probe_device(struct qmrom_handle *handle) return -1; } - rc = qm357xx_rom_b0_wait_ready(handle); + rc = qmrom_b0_wait_ready(handle); if (rc) { LOG_ERR("%s: hmm something went wrong!!!\n", __func__); return rc; } - rc = qm357xx_rom_write_cmd(handle, ROM_CMD_B0_GET_SOC_INFO); + rc = qmrom_write_cmd(handle, ROM_CMD_B0_GET_SOC_INFO); if (rc) return rc; - rc = qm357xx_rom_b0_poll_cmd_resp(handle); + rc = qmrom_b0_poll_cmd_resp(handle); if (rc) return rc; /* skip the first byte */ soc_lcs_uuid = &(handle->sstc->payload[1]); - for (i = 0; i < QM357XX_ROM_SOC_ID_LEN; i++) - handle->qm357xx_soc_info.soc_id[i] = - soc_lcs_uuid[QM357XX_ROM_SOC_ID_LEN - i - 1]; - soc_lcs_uuid += QM357XX_ROM_SOC_ID_LEN; - handle->qm357xx_soc_info.lcs_state = soc_lcs_uuid[0]; + for (i = 0; i < ROM_SOC_ID_LEN; i++) + handle->soc_id[i] = soc_lcs_uuid[ROM_SOC_ID_LEN - i - 1]; + soc_lcs_uuid += ROM_SOC_ID_LEN; + handle->lcs_state = soc_lcs_uuid[0]; soc_lcs_uuid += 1; - for (i = 0; i < QM357XX_ROM_UUID_LEN; i++) - handle->qm357xx_soc_info.uuid[i] = - soc_lcs_uuid[QM357XX_ROM_UUID_LEN - i - 1]; + for (i = 0; i < ROM_UUID_LEN; i++) + handle->uuid[i] = soc_lcs_uuid[ROM_UUID_LEN - i - 1]; - /* Set device type */ - handle->dev_gen = DEVICE_GEN_QM357XX; /* Set rom ops */ - handle->qm357xx_rom_ops.flash_unstitched_fw = - qm357xx_rom_b0_flash_unstitched_fw; - handle->qm357xx_rom_ops.flash_debug_cert = - qm357xx_rom_b0_flash_debug_cert; - handle->qm357xx_rom_ops.erase_debug_cert = - qm357xx_rom_b0_erase_debug_cert; + handle->rom_ops.flash_fw = qmrom_b0_flash_fw; + handle->rom_ops.flash_unstitched_fw = qmrom_b0_flash_unstitched_fw; + handle->rom_ops.flash_debug_cert = qmrom_b0_flash_debug_cert; + handle->rom_ops.erase_debug_cert = qmrom_b0_erase_debug_cert; check_stcs(__func__, __LINE__, handle); return 0; } -static int qm357xx_rom_b0_flash_data(struct qmrom_handle *handle, - struct firmware *fw, uint8_t cmd, - uint8_t exp) +static int qmrom_b0_flash_data(struct qmrom_handle *handle, struct firmware *fw, + uint8_t cmd, uint8_t exp) { int rc, sent = 0; const char *bin_data = (const char *)fw->data; @@ -233,7 +225,7 @@ static int qm357xx_rom_b0_flash_data(struct qmrom_handle *handle, LOG_DBG("%s: poll soc...\n", __func__); check_stcs(__func__, __LINE__, handle); - qm357xx_rom_b0_poll_soc(handle); + qmrom_b0_poll_soc(handle); qmrom_pre_read(handle); qmrom_read(handle); if (handle->sstc->payload[0] != exp) { @@ -248,8 +240,7 @@ static int qm357xx_rom_b0_flash_data(struct qmrom_handle *handle, LOG_DBG("%s: sending %d command with %" PRIu32 " bytes\n", __func__, cmd, tx_bytes); - rc = qm357xx_rom_write_size_cmd(handle, cmd, tx_bytes, - bin_data); + rc = qmrom_write_size_cmd(handle, cmd, tx_bytes, bin_data); if (rc) return rc; sent += tx_bytes; @@ -259,18 +250,33 @@ static int qm357xx_rom_b0_flash_data(struct qmrom_handle *handle, return 0; } +static int qmrom_b0_flash_fw(struct qmrom_handle *handle, + const struct firmware *fw) +{ + int rc = 0; + struct unstitched_firmware all_fws = { 0 }; + + rc = qmrom_unstitch_fw(fw, &all_fws, handle->chip_rev); + if (rc) { + LOG_ERR("%s: Unstitched fw flashing not supported yet\n", + __func__); + return rc; + } + rc = qmrom_b0_flash_unstitched_fw(handle, &all_fws); + return rc; +} + static int -qm357xx_rom_b0_flash_unstitched_fw(struct qmrom_handle *handle, - const struct unstitched_firmware *all_fws) +qmrom_b0_flash_unstitched_fw(struct qmrom_handle *handle, + const struct unstitched_firmware *all_fws) { int rc = 0; - uint8_t flash_cmd = handle->qm357xx_soc_info.lcs_state == - CC_BSV_SECURE_LCS ? + uint8_t flash_cmd = handle->lcs_state == CC_BSV_SECURE_LCS ? ROM_CMD_B0_SEC_LOAD_OEM_IMG_TO_RRAM : ROM_CMD_B0_SEC_LOAD_ICV_IMG_TO_RRAM; if (all_fws->key1_crt->data[HBK_LOC] == HBK_2E_ICV && - handle->qm357xx_soc_info.lcs_state != CC_BSV_CHIP_MANUFACTURE_LCS) { + handle->lcs_state != CC_BSV_CHIP_MANUFACTURE_LCS) { LOG_ERR("%s: Trying to flash an ICV fw on a non ICV platform\n", __func__); rc = -EINVAL; @@ -278,7 +284,7 @@ qm357xx_rom_b0_flash_unstitched_fw(struct qmrom_handle *handle, } if (all_fws->key1_crt->data[HBK_LOC] == HBK_2E_OEM && - handle->qm357xx_soc_info.lcs_state != CC_BSV_SECURE_LCS) { + handle->lcs_state != CC_BSV_SECURE_LCS) { LOG_ERR("%s: Trying to flash an OEM fw on a non OEM platform\n", __func__); rc = -EINVAL; @@ -288,41 +294,40 @@ qm357xx_rom_b0_flash_unstitched_fw(struct qmrom_handle *handle, LOG_DBG("%s: starting...\n", __func__); check_stcs(__func__, __LINE__, handle); - rc = qm357xx_rom_b0_wait_ready(handle); + rc = qmrom_b0_wait_ready(handle); if (rc) goto end; check_stcs(__func__, __LINE__, handle); LOG_DBG("%s: sending flash_cmd %u command\n", __func__, flash_cmd); - rc = qm357xx_rom_write_cmd(handle, flash_cmd); + rc = qmrom_write_cmd(handle, flash_cmd); if (rc) goto end; check_stcs(__func__, __LINE__, handle); - rc = qm357xx_rom_b0_flash_data(handle, all_fws->key1_crt, - ROM_CMD_B0_CERT_DATA, - WAITING_FOR_FIRST_KEY_CERT); + rc = qmrom_b0_flash_data(handle, all_fws->key1_crt, + ROM_CMD_B0_CERT_DATA, + WAITING_FOR_FIRST_KEY_CERT); if (rc) goto end; check_stcs(__func__, __LINE__, handle); - rc = qm357xx_rom_b0_flash_data(handle, all_fws->key2_crt, - ROM_CMD_B0_CERT_DATA, - WAITING_FOR_SECOND_KEY_CERT); + rc = qmrom_b0_flash_data(handle, all_fws->key2_crt, + ROM_CMD_B0_CERT_DATA, + WAITING_FOR_SECOND_KEY_CERT); if (rc) goto end; check_stcs(__func__, __LINE__, handle); - rc = qm357xx_rom_b0_flash_data(handle, all_fws->fw_crt, - ROM_CMD_B0_CERT_DATA, - WAITING_FOR_CONTENT_CERT); + rc = qmrom_b0_flash_data(handle, all_fws->fw_crt, ROM_CMD_B0_CERT_DATA, + WAITING_FOR_CONTENT_CERT); if (rc) goto end; check_stcs(__func__, __LINE__, handle); - rc = qm357xx_rom_b0_flash_data(handle, all_fws->fw_img, - ROM_CMD_B0_SEC_IMAGE_DATA, - WAITING_FOR_SEC_FILE_DATA); + rc = qmrom_b0_flash_data(handle, all_fws->fw_img, + ROM_CMD_B0_SEC_IMAGE_DATA, + WAITING_FOR_SEC_FILE_DATA); if (!rc) qmrom_msleep(SPI_READY_TIMEOUT_MS); @@ -336,35 +341,35 @@ end: return rc; } -static int qm357xx_rom_b0_flash_debug_cert(struct qmrom_handle *handle, - struct firmware *dbg_cert) +static int qmrom_b0_flash_debug_cert(struct qmrom_handle *handle, + struct firmware *dbg_cert) { int rc; LOG_DBG("%s: starting...\n", __func__); check_stcs(__func__, __LINE__, handle); - rc = qm357xx_rom_b0_wait_ready(handle); + rc = qmrom_b0_wait_ready(handle); if (rc) return rc; check_stcs(__func__, __LINE__, handle); LOG_DBG("%s: sending ROM_CMD_B0_WRITE_DBG_CERT command\n", __func__); - rc = qm357xx_rom_write_cmd(handle, ROM_CMD_B0_WRITE_DBG_CERT); + rc = qmrom_write_cmd(handle, ROM_CMD_B0_WRITE_DBG_CERT); if (rc) return rc; check_stcs(__func__, __LINE__, handle); LOG_DBG("%s: poll soc...\n", __func__); - qm357xx_rom_b0_poll_soc(handle); + qmrom_b0_poll_soc(handle); qmrom_pre_read(handle); qmrom_read(handle); check_stcs(__func__, __LINE__, handle); LOG_DBG("%s: sending ROM_CMD_B0_DEBUG_CERT_SIZE command\n", __func__); - rc = qm357xx_rom_write_size_cmd(handle, ROM_CMD_B0_DEBUG_CERT_SIZE, - sizeof(uint32_t), - (const char *)&dbg_cert->size); + rc = qmrom_write_size_cmd(handle, ROM_CMD_B0_DEBUG_CERT_SIZE, + sizeof(uint32_t), + (const char *)&dbg_cert->size); if (handle->sstc->payload[0] != WAITING_TO_DEBUG_CERTIFICATE_SIZE) { LOG_ERR("%s: wrong debug cert size result (0x%x vs 0x%x)!!!\n", __func__, handle->sstc->payload[0] & 0xff, @@ -374,26 +379,25 @@ static int qm357xx_rom_b0_flash_debug_cert(struct qmrom_handle *handle, if (rc) return rc; - rc = qm357xx_rom_b0_flash_data(handle, dbg_cert, ROM_CMD_B0_CERT_DATA, - WAITING_FOR_DEBUG_CERT_DATA); + rc = qmrom_b0_flash_data(handle, dbg_cert, ROM_CMD_B0_CERT_DATA, + WAITING_FOR_DEBUG_CERT_DATA); check_stcs(__func__, __LINE__, handle); - qmrom_msleep(SPI_READY_TIMEOUT_MS); return 0; } -static int qm357xx_rom_b0_erase_debug_cert(struct qmrom_handle *handle) +static int qmrom_b0_erase_debug_cert(struct qmrom_handle *handle) { int rc; LOG_INFO("%s: starting...\n", __func__); check_stcs(__func__, __LINE__, handle); - rc = qm357xx_rom_b0_wait_ready(handle); + rc = qmrom_b0_wait_ready(handle); if (!rc) return rc; LOG_DBG("%s: sending ROM_CMD_B0_ERASE_DBG_CERT command\n", __func__); - rc = qm357xx_rom_write_cmd(handle, ROM_CMD_B0_ERASE_DBG_CERT); + rc = qmrom_write_cmd(handle, ROM_CMD_B0_ERASE_DBG_CERT); if (rc) return rc; diff --git a/libqmrom/src/qm357xx_rom_c0.c b/libqmrom/src/qmrom_c0.c index acd4d31..76a04f3 100644 --- a/libqmrom/src/qm357xx_rom_c0.c +++ b/libqmrom/src/qmrom_c0.c @@ -77,12 +77,11 @@ enum C0_RESP { ERR_DEBUG_CERT_SIZE = 0x1F, }; -static int -qm357xx_rom_c0_flash_unstitched_fw(struct qmrom_handle *handle, - const struct unstitched_firmware *all_fws); -static int qm357xx_rom_c0_flash_debug_cert(struct qmrom_handle *handle, - struct firmware *dbg_cert); -static int qm357xx_rom_c0_erase_debug_cert(struct qmrom_handle *handle); +static int qmrom_c0_flash_fw(struct qmrom_handle *handle, + const struct firmware *fw); +static int qmrom_c0_flash_debug_cert(struct qmrom_handle *handle, + struct firmware *dbg_cert); +static int qmrom_c0_erase_debug_cert(struct qmrom_handle *handle); #define qmrom_pre_read_c0(h) \ ({ \ @@ -100,40 +99,40 @@ static int qm357xx_rom_c0_erase_debug_cert(struct qmrom_handle *handle); rc = qmrom_read((h)); \ rc; \ }) -#define qm357xx_rom_write_cmd_c0(h, cmd) \ +#define qmrom_write_cmd_c0(h, cmd) \ ({ \ int rc; \ qmrom_spi_wait_for_ready_line((h)->ss_rdy_handle, \ SPI_READY_TIMEOUT_MS_C0); \ - rc = qm357xx_rom_write_cmd((h), (cmd)); \ + rc = qmrom_write_cmd((h), (cmd)); \ rc; \ }) -#define qm357xx_rom_write_cmd32_c0(h, cmd) \ +#define qmrom_write_cmd32_c0(h, cmd) \ ({ \ int rc; \ qmrom_spi_wait_for_ready_line((h)->ss_rdy_handle, \ SPI_READY_TIMEOUT_MS_C0); \ - rc = qm357xx_rom_write_cmd32((h), (cmd)); \ + rc = qmrom_write_cmd32((h), (cmd)); \ rc; \ }) -#define qm357xx_rom_write_size_cmd_c0(h, cmd, ds, d) \ +#define qmrom_write_size_cmd_c0(h, cmd, ds, d) \ ({ \ int rc; \ qmrom_spi_wait_for_ready_line((h)->ss_rdy_handle, \ SPI_READY_TIMEOUT_MS_C0); \ - rc = qm357xx_rom_write_size_cmd((h), (cmd), (ds), (d)); \ + rc = qmrom_write_size_cmd((h), (cmd), (ds), (d)); \ rc; \ }) -#define qm357xx_rom_write_size_cmd32_c0(h, cmd, ds, d) \ - ({ \ - int rc; \ - qmrom_spi_wait_for_ready_line((h)->ss_rdy_handle, \ - SPI_READY_TIMEOUT_MS_C0); \ - rc = qm357xx_rom_write_size_cmd32((h), (cmd), (ds), (d)); \ - rc; \ +#define qmrom_write_size_cmd32_c0(h, cmd, ds, d) \ + ({ \ + int rc; \ + qmrom_spi_wait_for_ready_line((h)->ss_rdy_handle, \ + SPI_READY_TIMEOUT_MS_C0); \ + rc = qmrom_write_size_cmd32((h), (cmd), (ds), (d)); \ + rc; \ }) -static void qm357xx_rom_c0_poll_soc(struct qmrom_handle *handle) +static void qmrom_c0_poll_soc(struct qmrom_handle *handle) { int retries = handle->comms_retries; memset(handle->hstc, 0, sizeof(struct stc)); @@ -152,11 +151,11 @@ static void qm357xx_rom_c0_poll_soc(struct qmrom_handle *handle) } while (retries-- && handle->sstc->raw_flags == 0); } -static int qm357xx_rom_c0_wait_ready(struct qmrom_handle *handle) +static int qmrom_c0_wait_ready(struct qmrom_handle *handle) { int retries = handle->comms_retries; - qm357xx_rom_c0_poll_soc(handle); + qmrom_c0_poll_soc(handle); /* handle->sstc has been updated */ while (retries-- && @@ -167,7 +166,7 @@ static int qm357xx_rom_c0_wait_ready(struct qmrom_handle *handle) } else if (handle->sstc->soc_flags.out_active) { return qmrom_read_c0(handle); } else - qm357xx_rom_c0_poll_soc(handle); + qmrom_c0_poll_soc(handle); } return handle->sstc->raw_flags == SPI_SH_READY_CMD_BIT_MASK_C0 ? @@ -175,17 +174,17 @@ static int qm357xx_rom_c0_wait_ready(struct qmrom_handle *handle) SPI_ERR_WAIT_READY_TIMEOUT; } -static int qm357xx_rom_c0_poll_cmd_resp(struct qmrom_handle *handle) +static int qmrom_c0_poll_cmd_resp(struct qmrom_handle *handle) { int retries = handle->comms_retries; - qm357xx_rom_c0_poll_soc(handle); + qmrom_c0_poll_soc(handle); do { if (handle->sstc->soc_flags.out_waiting) { qmrom_pre_read_c0(handle); return qmrom_read_c0(handle); } else - qm357xx_rom_c0_poll_soc(handle); + qmrom_c0_poll_soc(handle); } while (retries--); if (retries <= 0) LOG_ERR("%s failed after %d replies\n", __func__, @@ -194,17 +193,14 @@ static int qm357xx_rom_c0_poll_cmd_resp(struct qmrom_handle *handle) return retries > 0 ? 0 : -1; } -int qm357xx_rom_c0_probe_device(struct qmrom_handle *handle) +int qmrom_c0_probe_device(struct qmrom_handle *handle) { int rc, i; uint8_t *soc_lcs_uuid; handle->is_be = false; - if (handle->spi_speed == 0) - qmrom_spi_set_freq(DEFAULT_SPI_CLOCKRATE); - else - qmrom_spi_set_freq(handle->spi_speed); + qmrom_spi_set_freq(DEFAULT_SPI_CLOCKRATE); rc = qmrom_reboot_bootloader(handle); if (rc) { @@ -212,17 +208,17 @@ int qm357xx_rom_c0_probe_device(struct qmrom_handle *handle) return rc; } - rc = qm357xx_rom_c0_wait_ready(handle); + rc = qmrom_c0_wait_ready(handle); if (rc) { LOG_INFO("%s: maybe not a C0 device\n", __func__); return rc; } - rc = qm357xx_rom_write_cmd32_c0(handle, ROM_CMD_C0_GET_CHIP_VER); + rc = qmrom_write_cmd32_c0(handle, ROM_CMD_C0_GET_CHIP_VER); if (rc) return rc; - rc = qm357xx_rom_c0_poll_cmd_resp(handle); + rc = qmrom_c0_poll_cmd_resp(handle); if (rc) return rc; @@ -231,50 +227,41 @@ int qm357xx_rom_c0_probe_device(struct qmrom_handle *handle) 0xFF; handle->device_version = bswap_16( SSTC2UINT16(handle, CHIP_VERSION_DEV_REV_PAYLOAD_OFFSET)); - if ((handle->chip_rev != CHIP_REVISION_C0) && - ((handle->chip_rev != CHIP_REVISION_C2))) { + if (handle->chip_rev != CHIP_REVISION_C0) { LOG_ERR("%s: wrong chip revision %#x\n", __func__, handle->chip_rev); handle->chip_rev = -1; return -1; } - rc = qm357xx_rom_c0_wait_ready(handle); + rc = qmrom_c0_wait_ready(handle); if (rc) { LOG_ERR("%s: hmm something went wrong!!!\n", __func__); return rc; } - rc = qm357xx_rom_write_cmd32_c0(handle, ROM_CMD_C0_GET_SOC_INFO); + rc = qmrom_write_cmd32_c0(handle, ROM_CMD_C0_GET_SOC_INFO); if (rc) return rc; - rc = qm357xx_rom_c0_poll_cmd_resp(handle); + rc = qmrom_c0_poll_cmd_resp(handle); if (rc) return rc; /* skip the first 4 bytes */ soc_lcs_uuid = &(handle->sstc->payload[4]); - for (i = 0; i < QM357XX_ROM_SOC_ID_LEN; i++) - handle->qm357xx_soc_info.soc_id[i] = - soc_lcs_uuid[QM357XX_ROM_SOC_ID_LEN - i - 1]; - soc_lcs_uuid += QM357XX_ROM_SOC_ID_LEN; - memcpy(&handle->qm357xx_soc_info.lcs_state, soc_lcs_uuid, - sizeof(uint32_t)); + for (i = 0; i < ROM_SOC_ID_LEN; i++) + handle->soc_id[i] = soc_lcs_uuid[ROM_SOC_ID_LEN - i - 1]; + soc_lcs_uuid += ROM_SOC_ID_LEN; + memcpy(&handle->lcs_state, soc_lcs_uuid, sizeof(uint32_t)); soc_lcs_uuid += 4; - for (i = 0; i < QM357XX_ROM_UUID_LEN; i++) - handle->qm357xx_soc_info.uuid[i] = - soc_lcs_uuid[QM357XX_ROM_UUID_LEN - i - 1]; + for (i = 0; i < ROM_UUID_LEN; i++) + handle->uuid[i] = soc_lcs_uuid[ROM_UUID_LEN - i - 1]; - /* Set device type */ - handle->dev_gen = DEVICE_GEN_QM357XX; /* Set rom ops */ - handle->qm357xx_rom_ops.flash_unstitched_fw = - qm357xx_rom_c0_flash_unstitched_fw; - handle->qm357xx_rom_ops.flash_debug_cert = - qm357xx_rom_c0_flash_debug_cert; - handle->qm357xx_rom_ops.erase_debug_cert = - qm357xx_rom_c0_erase_debug_cert; + handle->rom_ops.flash_fw = qmrom_c0_flash_fw; + handle->rom_ops.flash_debug_cert = qmrom_c0_flash_debug_cert; + handle->rom_ops.erase_debug_cert = qmrom_c0_erase_debug_cert; return 0; } @@ -298,18 +285,17 @@ static void update_write_max_chunk_stats(ktime_t start_time) static void dump_stats(void) { - uint32_t nb_chunks = div_u64(total_bytes, CHUNK_SIZE_C0); + uint32_t nb_chunks = total_bytes / CHUNK_SIZE_C0; LOG_WARN( "C0 flashing time stats: %llu bytes over %llu us (chunk size %u, write timings: mean %u us, min %u us, max %u us)\n", - total_bytes, div_u64(total_time_ns, 1000), CHUNK_SIZE_C0, - (uint32_t)(div_u64((div_u64(total_time_ns, nb_chunks)), 1000)), + total_bytes, total_time_ns / 1000, CHUNK_SIZE_C0, + (uint32_t)((total_time_ns / nb_chunks) / 1000), min_write_time_ns / 1000, max_write_time_ns / 1000); } #endif -static int qm357xx_rom_c0_flash_data(struct qmrom_handle *handle, - struct firmware *fw, uint8_t cmd, - uint8_t resp, bool skip_last_check) +static int qmrom_c0_flash_data(struct qmrom_handle *handle, struct firmware *fw, + uint8_t cmd, uint8_t resp, bool skip_last_check) { int rc, sent = 0; const char *bin_data = (const char *)fw->data; @@ -327,8 +313,7 @@ static int qm357xx_rom_c0_flash_data(struct qmrom_handle *handle, #ifdef C0_WRITE_STATS start_time = ktime_get(); #endif - rc = qm357xx_rom_write_size_cmd32_c0(handle, cmd, tx_bytes, - bin_data); + rc = qmrom_write_size_cmd32_c0(handle, cmd, tx_bytes, bin_data); if (rc) return rc; sent += tx_bytes; @@ -337,7 +322,7 @@ static int qm357xx_rom_c0_flash_data(struct qmrom_handle *handle, LOG_INFO("%s: flashing done, quitting now\n", __func__); break; } - qm357xx_rom_c0_poll_soc(handle); + qmrom_c0_poll_soc(handle); #ifdef C0_WRITE_STATS if (tx_bytes == CHUNK_SIZE_C0) update_write_max_chunk_stats(start_time); @@ -359,26 +344,34 @@ static int qm357xx_rom_c0_flash_data(struct qmrom_handle *handle, return 0; } -static int -qm357xx_rom_c0_flash_unstitched_fw(struct qmrom_handle *handle, - const struct unstitched_firmware *all_fws) +static int qmrom_c0_flash_fw(struct qmrom_handle *handle, + const struct firmware *fw) { int rc = 0; - uint8_t flash_cmd = handle->qm357xx_soc_info.lcs_state == - CC_BSV_SECURE_LCS ? + struct unstitched_firmware all_fws = { 0 }; + uint8_t flash_cmd = handle->lcs_state == CC_BSV_SECURE_LCS ? ROM_CMD_C0_SEC_LOAD_OEM_IMG_TO_RRAM : ROM_CMD_C0_SEC_LOAD_ICV_IMG_TO_RRAM; - if (all_fws->key1_crt->data[HBK_LOC] == HBK_2E_ICV && - handle->qm357xx_soc_info.lcs_state != CC_BSV_CHIP_MANUFACTURE_LCS) { + LOG_INFO("Unstitching the fw %p->data %p\n", (void *)fw, + (void *)fw->data); + rc = qmrom_unstitch_fw(fw, &all_fws, handle->chip_rev); + if (rc) { + LOG_ERR("%s: Unstitched fw flashing not supported yet\n", + __func__); + return rc; + } + + if (all_fws.key1_crt->data[HBK_LOC] == HBK_2E_ICV && + handle->lcs_state != CC_BSV_CHIP_MANUFACTURE_LCS) { LOG_ERR("%s: Trying to flash an ICV fw on a non ICV platform\n", __func__); rc = -EINVAL; goto end; } - if (all_fws->key1_crt->data[HBK_LOC] == HBK_2E_OEM && - handle->qm357xx_soc_info.lcs_state != CC_BSV_SECURE_LCS) { + if (all_fws.key1_crt->data[HBK_LOC] == HBK_2E_OEM && + handle->lcs_state != CC_BSV_SECURE_LCS) { LOG_ERR("%s: Trying to flash an OEM fw on a non OEM platform\n", __func__); rc = -EINVAL; @@ -388,30 +381,25 @@ qm357xx_rom_c0_flash_unstitched_fw(struct qmrom_handle *handle, LOG_DBG("%s: starting...\n", __func__); /* Set RRAM write mode */ - rc = qm357xx_rom_c0_wait_ready(handle); + rc = qmrom_c0_wait_ready(handle); if (rc) goto end; - if (handle->chip_rev != CHIP_REVISION_C2) { - LOG_DBG("%s: sending ROM_CMD_C0_USE_INDIRECT_RRAM_WR command (chip_rev %x)\n", - __func__, handle->chip_rev); - rc = qm357xx_rom_write_cmd32_c0( - handle, ROM_CMD_C0_USE_INDIRECT_RRAM_WR); - if (rc) - goto end; - } + rc = qmrom_write_cmd32_c0(handle, ROM_CMD_C0_USE_INDIRECT_RRAM_WR); + if (rc) + goto end; - qm357xx_rom_c0_poll_soc(handle); + qmrom_c0_poll_soc(handle); qmrom_pre_read_c0(handle); qmrom_read_c0(handle); - qm357xx_rom_c0_poll_soc(handle); + qmrom_c0_poll_soc(handle); LOG_DBG("%s: sending flash_cmd %u command\n", __func__, flash_cmd); - rc = qm357xx_rom_write_cmd32_c0(handle, flash_cmd); + rc = qmrom_write_cmd32_c0(handle, flash_cmd); if (rc) goto end; - qm357xx_rom_c0_poll_cmd_resp(handle); + qmrom_c0_poll_cmd_resp(handle); if (handle->sstc->payload[0] != WAITING_FOR_FIRST_KEY_CERT) { LOG_ERR("%s: Waiting for WAITING_FOR_FIRST_KEY_CERT(%#x) but got %#x\n", __func__, WAITING_FOR_FIRST_KEY_CERT, @@ -419,93 +407,65 @@ qm357xx_rom_c0_flash_unstitched_fw(struct qmrom_handle *handle, goto end; } - qm357xx_rom_c0_poll_soc(handle); + qmrom_c0_poll_soc(handle); - rc = qm357xx_rom_c0_flash_data(handle, all_fws->key1_crt, - ROM_CMD_C0_CERT_DATA, - WAITING_FOR_SECOND_KEY_CERT, false); + rc = qmrom_c0_flash_data(handle, all_fws.key1_crt, ROM_CMD_C0_CERT_DATA, + WAITING_FOR_SECOND_KEY_CERT, false); if (rc) goto end; - rc = qm357xx_rom_c0_flash_data(handle, all_fws->key2_crt, - ROM_CMD_C0_CERT_DATA, - WAITING_FOR_CONTENT_CERT, false); + rc = qmrom_c0_flash_data(handle, all_fws.key2_crt, ROM_CMD_C0_CERT_DATA, + WAITING_FOR_CONTENT_CERT, false); if (rc) goto end; - rc = qm357xx_rom_c0_flash_data(handle, all_fws->fw_crt, - ROM_CMD_C0_CERT_DATA, - WAITING_FOR_SEC_FILE_DATA, false); + rc = qmrom_c0_flash_data(handle, all_fws.fw_crt, ROM_CMD_C0_CERT_DATA, + WAITING_FOR_SEC_FILE_DATA, false); if (rc) goto end; - rc = qm357xx_rom_c0_flash_data(handle, all_fws->fw_img, - ROM_CMD_C0_SEC_IMAGE_DATA, - WAITING_FOR_SEC_FILE_DATA, true); + rc = qmrom_c0_flash_data(handle, all_fws.fw_img, + ROM_CMD_C0_SEC_IMAGE_DATA, + WAITING_FOR_SEC_FILE_DATA, true); #ifdef C0_WRITE_STATS dump_stats(); #endif - if (qmrom_spi_read_irq_line(handle->ss_irq_handle)) { - int retries = handle->comms_retries; - - do { - /* A final product id error likely occurred */ - qmrom_pre_read_c0(handle); - qmrom_read_c0(handle); - rc = handle->sstc->payload[0]; - if (rc) { - LOG_ERR("%s: flashing error %d (0x%x) detected\n", - __func__, rc, rc); - break; - } - } while (--retries); - - if (retries <= 0) { - LOG_ERR("%s: flashing error detected but couldn't be fetched\n", - __func__); - rc = -1; - } - } - end: - qmrom_free(all_fws->fw_img); - qmrom_free(all_fws->fw_crt); - qmrom_free(all_fws->key1_crt); - qmrom_free(all_fws->key2_crt); + qmrom_free(all_fws.fw_img); + qmrom_free(all_fws.fw_crt); + qmrom_free(all_fws.key1_crt); + qmrom_free(all_fws.key2_crt); return rc; } -static int qm357xx_rom_c0_flash_debug_cert(struct qmrom_handle *handle, - struct firmware *dbg_cert) +static int qmrom_c0_flash_debug_cert(struct qmrom_handle *handle, + struct firmware *dbg_cert) { int rc; LOG_DBG("%s: starting...\n", __func__); - rc = qm357xx_rom_c0_wait_ready(handle); + rc = qmrom_c0_wait_ready(handle); if (rc) return rc; - if (handle->chip_rev != CHIP_REVISION_C2) { - LOG_DBG("%s: using ROM_CMD_C0_USE_INDIRECT_RRAM_WR command\n", - __func__); - rc = qm357xx_rom_write_cmd32_c0( - handle, ROM_CMD_C0_USE_INDIRECT_RRAM_WR); - if (rc) - return rc; - } + LOG_DBG("%s: sending ROM_CMD_C0_USE_DIRECT_RRAM_WR command\n", + __func__); + rc = qmrom_write_cmd32_c0(handle, ROM_CMD_C0_USE_INDIRECT_RRAM_WR); + if (rc) + return rc; - qm357xx_rom_c0_poll_soc(handle); + qmrom_c0_poll_soc(handle); qmrom_pre_read_c0(handle); qmrom_read_c0(handle); - qm357xx_rom_c0_poll_soc(handle); + qmrom_c0_poll_soc(handle); LOG_DBG("%s: sending ROM_CMD_C0_WRITE_DBG_CERT command\n", __func__); - rc = qm357xx_rom_write_cmd32_c0(handle, ROM_CMD_C0_WRITE_DBG_CERT); + rc = qmrom_write_cmd32_c0(handle, ROM_CMD_C0_WRITE_DBG_CERT); if (rc) return rc; - qm357xx_rom_c0_poll_cmd_resp(handle); + qmrom_c0_poll_cmd_resp(handle); if (handle->sstc->payload[0] != WAITING_TO_DEBUG_CERTIFICATE_SIZE) { LOG_ERR("%s: Waiting for WAITING_TO_DEBUG_CERTIFICATE_SIZE(%#x) but got %#x\n", __func__, WAITING_TO_DEBUG_CERTIFICATE_SIZE, @@ -514,10 +474,10 @@ static int qm357xx_rom_c0_flash_debug_cert(struct qmrom_handle *handle, } LOG_DBG("%s: sending ROM_CMD_C0_DEBUG_CERT_SIZE command\n", __func__); - rc = qm357xx_rom_write_size_cmd32_c0(handle, ROM_CMD_C0_DEBUG_CERT_SIZE, - sizeof(uint32_t), - (const char *)&dbg_cert->size); - qm357xx_rom_c0_poll_cmd_resp(handle); + rc = qmrom_write_size_cmd32_c0(handle, ROM_CMD_C0_DEBUG_CERT_SIZE, + sizeof(uint32_t), + (const char *)&dbg_cert->size); + qmrom_c0_poll_cmd_resp(handle); if (handle->sstc->payload[0] != WAITING_FOR_DEBUG_CERT_DATA) { LOG_ERR("%s: Waiting for WAITING_FOR_DEBUG_CERT_DATA(%#x) but got %#x\n", __func__, WAITING_FOR_DEBUG_CERT_DATA, @@ -525,23 +485,23 @@ static int qm357xx_rom_c0_flash_debug_cert(struct qmrom_handle *handle, return rc; } - rc = qm357xx_rom_c0_flash_data(handle, dbg_cert, ROM_CMD_C0_CERT_DATA, - WAITING_FOR_DEBUG_CERT_DATA, true); + rc = qmrom_c0_flash_data(handle, dbg_cert, ROM_CMD_C0_CERT_DATA, + WAITING_FOR_DEBUG_CERT_DATA, true); return 0; } -static int qm357xx_rom_c0_erase_debug_cert(struct qmrom_handle *handle) +static int qmrom_c0_erase_debug_cert(struct qmrom_handle *handle) { int rc; LOG_DBG("%s: starting...\n", __func__); - rc = qm357xx_rom_c0_wait_ready(handle); + rc = qmrom_c0_wait_ready(handle); if (rc) return rc; LOG_DBG("%s: sending ROM_CMD_C0_ERASE_DBG_CERT command\n", __func__); - rc = qm357xx_rom_write_cmd32_c0(handle, ROM_CMD_C0_ERASE_DBG_CERT); + rc = qmrom_write_cmd32_c0(handle, ROM_CMD_C0_ERASE_DBG_CERT); if (rc) return rc; diff --git a/libqmrom/src/qmrom_common.c b/libqmrom/src/qmrom_common.c index 017b346..58ca662 100644 --- a/libqmrom/src/qmrom_common.c +++ b/libqmrom/src/qmrom_common.c @@ -10,7 +10,9 @@ #include <qmrom.h> #include <spi_rom_protocol.h> -int qm357xx_rom_probe_device(struct qmrom_handle *handle); +int qmrom_a0_probe_device(struct qmrom_handle *handle); +int qmrom_b0_probe_device(struct qmrom_handle *handle); +int qmrom_c0_probe_device(struct qmrom_handle *handle); static void qmrom_free_stcs(struct qmrom_handle *h) { @@ -98,28 +100,93 @@ int qmrom_read(struct qmrom_handle *handle) sizeof(struct stc) + rd_size); } +int qmrom_write_cmd(struct qmrom_handle *handle, uint8_t cmd) +{ + handle->hstc->all = 0; + handle->hstc->host_flags.write = 1; + handle->hstc->ul = 1; + handle->hstc->len = 1; + handle->hstc->payload[0] = cmd; + + return qmrom_spi_transfer(handle->spi_handle, (char *)handle->sstc, + (const char *)handle->hstc, + sizeof(struct stc) + handle->hstc->len); +} + +int qmrom_write_cmd32(struct qmrom_handle *handle, uint32_t cmd) +{ + handle->hstc->all = 0; + handle->hstc->host_flags.write = 1; + handle->hstc->ul = 1; + handle->hstc->len = sizeof(cmd); + memcpy(handle->hstc->payload, &cmd, sizeof(cmd)); + + return qmrom_spi_transfer(handle->spi_handle, (char *)handle->sstc, + (const char *)handle->hstc, + sizeof(struct stc) + handle->hstc->len); +} + +int qmrom_write_size_cmd(struct qmrom_handle *handle, uint8_t cmd, + uint16_t data_size, const char *data) +{ + handle->hstc->all = 0; + handle->hstc->host_flags.write = 1; + handle->hstc->ul = 1; + handle->hstc->len = data_size + 1; + handle->hstc->payload[0] = cmd; + memcpy(&handle->hstc->payload[1], data, data_size); + + return qmrom_spi_transfer(handle->spi_handle, (char *)handle->sstc, + (const char *)handle->hstc, + sizeof(struct stc) + handle->hstc->len); +} + +int qmrom_write_size_cmd32(struct qmrom_handle *handle, uint32_t cmd, + uint16_t data_size, const char *data) +{ + handle->hstc->all = 0; + handle->hstc->host_flags.write = 1; + handle->hstc->ul = 1; + handle->hstc->len = data_size + sizeof(cmd); + memcpy(handle->hstc->payload, &cmd, sizeof(cmd)); + memcpy(&handle->hstc->payload[sizeof(cmd)], data, data_size); + + return qmrom_spi_transfer(handle->spi_handle, (char *)handle->sstc, + (const char *)handle->hstc, + sizeof(struct stc) + handle->hstc->len); +} + /* * Unfortunately, A0, B0 and C0 have different * APIs to get the chip version... * */ -int qmrom_probe_device(struct qmrom_handle *handle, - enum device_generation_e dev_gen_hint) +int qmrom_probe_device(struct qmrom_handle *handle) { - int rc = -1; + int rc; - if (dev_gen_hint == DEVICE_GEN_QM357XX || - dev_gen_hint == DEVICE_GEN_UNKNOWN) - rc = qm357xx_rom_probe_device(handle); + /* Test B0 first */ + rc = qmrom_b0_probe_device(handle); + if (!rc) + return rc; - return rc; + /* Test C0 next */ + rc = qmrom_c0_probe_device(handle); + if (!rc) + return rc; + + /* Finally try A0 */ + rc = qmrom_a0_probe_device(handle); + if (!rc) + return rc; + + /* None matched!!! */ + return -1; } struct qmrom_handle *qmrom_init(void *spi_handle, void *reset_handle, - void *ss_rdy_handle, void *ss_irq_handle, - int spi_speed, int comms_retries, - reset_device_fn reset, - enum device_generation_e dev_gen_hint) + void *ss_rdy_handle, int comms_retries, + reset_device_fn reset) { struct qmrom_handle *handle; int rc; @@ -140,15 +207,14 @@ struct qmrom_handle *qmrom_init(void *spi_handle, void *reset_handle, handle->spi_handle = spi_handle; handle->reset_handle = reset_handle; handle->ss_rdy_handle = ss_rdy_handle; - handle->ss_irq_handle = ss_irq_handle; handle->comms_retries = comms_retries; handle->chip_rev = CHIP_REVISION_UNKNOWN; handle->device_version = -1; - handle->spi_speed = spi_speed; + handle->lcs_state = -1; handle->dev_ops.reset = reset; - rc = qmrom_probe_device(handle, dev_gen_hint); + rc = qmrom_probe_device(handle); if (rc) { LOG_ERR("%s: qmrom_probe_device returned %d!\n", __func__, rc); qmrom_free_stcs(handle); @@ -167,6 +233,173 @@ void qmrom_deinit(struct qmrom_handle *handle) qmrom_free(handle); } +int qmrom_flash_dbg_cert(struct qmrom_handle *handle, struct firmware *dbg_cert) +{ + if (!handle->rom_ops.flash_debug_cert) { + LOG_ERR("%s: flash debug certificate not support on this device\n", + __func__); + return -EINVAL; + } + return handle->rom_ops.flash_debug_cert(handle, dbg_cert); +} + +int qmrom_erase_dbg_cert(struct qmrom_handle *handle) +{ + if (!handle->rom_ops.erase_debug_cert) { + LOG_ERR("%s: erase debug certificate not support on this device\n", + __func__); + return -EINVAL; + } + return handle->rom_ops.erase_debug_cert(handle); +} + +int qmrom_flash_fw(struct qmrom_handle *handle, const struct firmware *fw) +{ + return handle->rom_ops.flash_fw(handle, fw); +} + +int qmrom_flash_unstitched_fw(struct qmrom_handle *handle, + const struct unstitched_firmware *fw) +{ + return handle->rom_ops.flash_unstitched_fw(handle, fw); +} + +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) { + LOG_ERR("%s: A0, no unstitching!!!\n", __func__); + return -EINVAL; + } + if (fw->size < 2 * sizeof(key1_crt_sz)) { + LOG_ERR("%s: Not enough data (%zu) to unstitch\n", __func__, + fw->size); + return -EINVAL; + } + LOG_INFO("%s: Unstitching %zu bytes\n", __func__, fw->size); + + /* key1 */ + key1_crt_sz = *(uint32_t *)&fw->data[tot_len]; + if (tot_len + key1_crt_sz + sizeof(key1_crt_sz) > fw->size) { + LOG_ERR("%s: Invalid or corrupted stitched file at offset \ + %" PRIu32 " (key1)\n", + __func__, tot_len); + ret = -EINVAL; + goto out; + } + tot_len += sizeof(key1_crt_sz); + p_key1 = (uint8_t *)&fw->data[tot_len]; + tot_len += key1_crt_sz; + + /* key2 */ + key2_crt_sz = *(uint32_t *)&fw->data[tot_len]; + if (tot_len + key2_crt_sz + sizeof(key2_crt_sz) > fw->size) { + LOG_ERR("%s: Invalid or corrupted stitched file at offset \ + %" PRIu32 " (key2)\n", + __func__, tot_len); + ret = -EINVAL; + goto out; + } + tot_len += sizeof(key2_crt_sz); + p_key2 = (uint8_t *)&fw->data[tot_len]; + tot_len += key2_crt_sz; + + /* cert */ + fw_crt_sz = *(uint32_t *)&fw->data[tot_len]; + if (tot_len + fw_crt_sz + sizeof(fw_crt_sz) > fw->size) { + LOG_ERR("%s: Invalid or corrupted stitched file at offset \ + %" PRIu32 " (content cert)\n", + __func__, tot_len); + ret = -EINVAL; + goto out; + } + tot_len += sizeof(fw_crt_sz); + p_crt = (uint8_t *)&fw->data[tot_len]; + tot_len += fw_crt_sz; + + /* fw */ + fw_img_sz = *(uint32_t *)&fw->data[tot_len]; + if (tot_len + fw_img_sz + sizeof(fw_img_sz) != fw->size) { + LOG_ERR("%s: Invalid or corrupted stitched file at offset \ + %" PRIu32 " (firmnware)\n", + __func__, tot_len); + ret = -EINVAL; + goto out; + } + tot_len += sizeof(fw_img_sz); + p_fw = (uint8_t *)&fw->data[tot_len]; + + qmrom_alloc(unstitched_fw->fw_img, fw_img_sz + sizeof(struct firmware)); + if (unstitched_fw->fw_img == NULL) { + ret = -ENOMEM; + goto out; + } + + qmrom_alloc(unstitched_fw->fw_crt, fw_crt_sz + sizeof(struct firmware)); + if (unstitched_fw->fw_crt == NULL) { + ret = -ENOMEM; + goto err; + } + + qmrom_alloc(unstitched_fw->key1_crt, + key1_crt_sz + sizeof(struct firmware)); + if (unstitched_fw->key1_crt == NULL) { + ret = -ENOMEM; + goto err; + } + + qmrom_alloc(unstitched_fw->key2_crt, + key2_crt_sz + sizeof(struct firmware)); + if (unstitched_fw->key2_crt == NULL) { + ret = -ENOMEM; + goto err; + } + + unstitched_fw->key1_crt->data = + (const uint8_t *)(unstitched_fw->key1_crt + 1); + unstitched_fw->key2_crt->data = + (const uint8_t *)(unstitched_fw->key2_crt + 1); + unstitched_fw->fw_crt->data = + (const uint8_t *)(unstitched_fw->fw_crt + 1); + unstitched_fw->fw_img->data = + (const uint8_t *)(unstitched_fw->fw_img + 1); + 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; + + memcpy((void *)unstitched_fw->key1_crt->data, p_key1, key1_crt_sz); + memcpy((void *)unstitched_fw->key2_crt->data, p_key2, key2_crt_sz); + memcpy((void *)unstitched_fw->fw_crt->data, p_crt, fw_crt_sz); + memcpy((void *)unstitched_fw->fw_img->data, p_fw, fw_img_sz); + return 0; + +err: + if (unstitched_fw->fw_img) + qmrom_free(unstitched_fw->fw_img); + if (unstitched_fw->fw_crt) + qmrom_free(unstitched_fw->fw_crt); + if (unstitched_fw->key1_crt) + qmrom_free(unstitched_fw->key1_crt); + if (unstitched_fw->key2_crt) + qmrom_free(unstitched_fw->key2_crt); + +out: + return ret; +} + int qmrom_reboot_bootloader(struct qmrom_handle *handle) { int rc; @@ -26,7 +26,6 @@ * QM35 UCI over HSSPI protocol */ -#include <linux/version.h> #include <linux/bitfield.h> #include <linux/interrupt.h> #include <linux/ioctl.h> @@ -50,8 +49,6 @@ #include <qmrom_log.h> #include <spi_rom_protocol.h> -#include <fwupdater.h> - #include "qm35.h" #include "uci_ioctls.h" #include "hsspi.h" @@ -60,8 +57,6 @@ #define QM35_REGULATOR_DELAY_US 1000 #define QMROM_RETRIES 10 -#define FLASHING_RETRIES 10 /* Intentionaly high value */ -/* Redefine certificate error here since original definitions are separate */ #define REGULATORS_ENABLED(x) (x->vdd1 || x->vdd2 || x->vdd3 || x->vdd4) #ifndef NO_UWB_HAL @@ -83,8 +78,8 @@ static bool flash_on_probe = false; module_param(flash_on_probe, bool, 0444); MODULE_PARM_DESC(flash_on_probe, "Flash during the module probe"); -int spi_speed_hz; -module_param(spi_speed_hz, int, 0644); +static int spi_speed_hz; +module_param(spi_speed_hz, int, 0444); MODULE_PARM_DESC(spi_speed_hz, "SPI speed (if not set use DTS's one)"); static char *fwname = NULL; @@ -92,11 +87,11 @@ module_param(fwname, charp, 0444); MODULE_PARM_DESC(fwname, "Use fwname as firmware binary to flash QM35"); static bool wake_use_wakeup = true; -module_param(wake_use_wakeup, bool, 0644); +module_param(wake_use_wakeup, bool, 0444); MODULE_PARM_DESC(wake_use_wakeup, "Use wakeup pin to wake up QM35"); static bool wake_use_csn = false; -module_param(wake_use_csn, bool, 0644); +module_param(wake_use_csn, bool, 0444); MODULE_PARM_DESC(wake_use_csn, "Use HSSPI CSn pin to wake up QM35"); static bool wake_on_ssirq = true; @@ -105,34 +100,22 @@ MODULE_PARM_DESC(wake_on_ssirq, "Allow QM35 to wakeup the platform using ss_irq"); int trace_spi_xfers; -module_param(trace_spi_xfers, int, 0644); +module_param(trace_spi_xfers, int, 0444); MODULE_PARM_DESC(trace_spi_xfers, "Trace all the SPI transfers"); int qmrom_retries = QMROM_RETRIES; -module_param(qmrom_retries, int, 0644); +module_param(qmrom_retries, int, 0444); MODULE_PARM_DESC(qmrom_retries, "QMROM retries"); -int flashing_retries = FLASHING_RETRIES; -module_param(flashing_retries, int, 0644); -MODULE_PARM_DESC(flashing_retries, "Flashing retries"); - int reset_on_error = 1; -module_param(reset_on_error, int, 0644); +module_param(reset_on_error, int, 0444); MODULE_PARM_DESC(reset_on_error, "Reset the QM35 on successive errors"); int log_qm_traces = 1; module_param(log_qm_traces, int, 0444); MODULE_PARM_DESC(log_qm_traces, "Logs the QM35 traces in the kernel messages"); -int fu_spi_speed_hz; -module_param(fu_spi_speed_hz, int, 0644); -MODULE_PARM_DESC(fu_spi_speed_hz, "FW updater SPI speed"); - -int qmrom_spi_speed_hz; -module_param(qmrom_spi_speed_hz, int, 0644); -MODULE_PARM_DESC(qmrom_spi_speed_hz, "FW updater SPI speed"); - -static uint8_t qm_soc_id[QM357XX_ROM_SOC_ID_LEN]; +static uint8_t qm_soc_id[ROM_SOC_ID_LEN]; static uint16_t qm_dev_id; /* @@ -374,13 +357,8 @@ static irqreturn_t qm35_ss_rdy_handler(int irq, void *data) if (wake_use_wakeup) gpiod_set_value(qm35_hdl->gpio_wakeup, 0); - if (!qm35_hdl->flashing) { - hsspi_clear_spi_slave_busy(&qm35_hdl->hsspi); - hsspi_set_spi_slave_ready(&qm35_hdl->hsspi); - } else { - qm35_hdl->qmrom_qm_ready = true; - wake_up_interruptible(&qm35_hdl->qmrom_wq_ready); - } + hsspi_clear_spi_slave_busy(&qm35_hdl->hsspi); + hsspi_set_spi_slave_ready(&qm35_hdl->hsspi); return IRQ_HANDLED; } @@ -478,133 +456,25 @@ int qm35_reset_sync(struct qm35_ctx *qm35_hdl) return ret; } -static int qm_firmware_flash_fw(struct qm35_ctx *qm35_hdl, - struct qmrom_handle *h, - const struct firmware *fw) -{ - int rc = 0, nb_retries = FLASHING_RETRIES; - do { - /* If the previous flashing failed, re-enter the QM - * rom code so it will be in the same initial state - */ - if (rc) - qmrom_reboot_bootloader(h); - - rc = qm357xx_rom_flash_fw(h, fw); - if (rc) - dev_err(&qm35_hdl->spi->dev, - "Attempt %d: flashing failed with %d!\n", - FLASHING_RETRIES - nb_retries, rc); - if (rc == PEG_ERR_FIRST_KEY_CERT_OR_FW_VER) - break; - } while (rc && --nb_retries > 0); - return rc; -} - -static int qm_firmware_flash_macro_pkg(struct qm35_ctx *qm35_hdl, - struct qmrom_handle *h, - const struct firmware *fw) -{ - int rc, nb_retries = FLASHING_RETRIES; - char *fw_data; - uint32_t fw_size; - - rc = qm357xx_rom_fw_macro_pkg_get_fw_idx(fw, 1, &fw_size, &fw_data); - if (rc) { - dev_err(&qm35_hdl->spi->dev, - "FW MACRO PACKAGE corrupted = %d\n", rc); - return rc; - } - if (*(uint32_t *)fw_data != CRYPTO_FIRMWARE_PACK_MAGIC_VALUE) { - rc = -EINVAL; - dev_err(&qm35_hdl->spi->dev, - "FW PACKAGE not found - magic is %04x, size is %d\n", - *(uint32_t *)fw_data, fw_size); - return rc; - } - - do { - /* If the previous flashing failed, re-enter the QM - * rom code so it will be in the same initial state - */ - if (spi_speed_hz) - qmrom_spi_set_freq(spi_speed_hz); - else - qmrom_spi_set_freq(DEFAULT_SPI_CLOCKRATE); - - if (rc) - qmrom_reboot_bootloader(h); - - /* The Macro Package contain the fw updater and the package - * simply flash the first and provide the second to - * the updater lib - */ - rc = qm357xx_rom_flash_fw(h, fw); - if (rc) { - dev_err(&qm35_hdl->spi->dev, - "Attempt %d: fw updater flashing failed with %d!\n", - FLASHING_RETRIES - nb_retries, rc); - if (rc == PEG_ERR_FIRST_KEY_CERT_OR_FW_VER) - break; - continue; - } - - /* Now flash the firmware proper */ - if (fu_spi_speed_hz) - qmrom_spi_set_freq(fu_spi_speed_hz); - else - qmrom_spi_set_freq(FWUPDATER_SPI_SPEED_HZ); - rc = run_fwupdater(h, fw_data, fw_size); - if (rc) { - dev_err(&qm35_hdl->spi->dev, - "Attempt %d: fw app flashing failed with %d!\n", - FLASHING_RETRIES - nb_retries, rc); - } - } while (rc && --nb_retries > 0); - return rc; -} - static int qm_firmware_flashing(void *handle, struct qmrom_handle *h, - bool *is_macro_pkg, bool use_prod_fw) + bool use_prod_fw) { struct qm35_ctx *qm35_hdl = (struct qm35_ctx *)handle; struct spi_device *spi = qm35_hdl->spi; - int rc = 0; const struct firmware *fw; -#ifdef C0_WRITE_STATS - uint64_t elapsed_time_ns; - ktime_t start_time; -#endif + int ret = 0; - fw = qmrom_spi_get_firmware(&spi->dev, h, is_macro_pkg, use_prod_fw); + 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; } -#ifdef C0_WRITE_STATS - start_time = ktime_get(); -#endif - - qm35_hdl->flashing = true; - if (!*is_macro_pkg) - rc = qm_firmware_flash_fw(qm35_hdl, h, fw); - else - rc = qm_firmware_flash_macro_pkg(qm35_hdl, h, fw); - -#ifdef C0_WRITE_STATS - elapsed_time_ns = ktime_to_ns(ktime_sub(ktime_get(), start_time)); - if (!rc) - dev_warn(&spi->dev, "Fw_updater flashed in %llu us\n", - div_u64(elapsed_time_ns, 1000)); -#endif + ret = qmrom_flash_fw(h, fw); + dev_dbg(&spi->dev, "Return qmrom_flash_fw = %d!\n", ret); qmrom_spi_release_firmware(fw); - qm35_hdl->flashing = false; - - /* Reset the device anyway */ - qmrom_spi_reset_device(qm35_hdl); - return rc; + return ret; } static int qm_firmware_load(struct qm35_ctx *qm35_hdl) @@ -612,19 +482,14 @@ 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); struct qmrom_handle *h; - bool is_macro_pkg = false; - int ret, irq = gpiod_to_irq(qm35_hdl->gpio_ss_rdy); + int ret; qm35_set_state(qm35_hdl, QM35_CTRL_STATE_FW_DOWNLOADING); qmrom_set_log_device(&spi->dev, LOG_WARN); - if (irq >= 0) - enable_irq(irq); - - h = qmrom_init(&spi->dev, qm35_hdl, qm35_hdl, qm35_hdl->gpio_ss_irq, - qmrom_spi_speed_hz, qmrom_retries, - qmrom_spi_reset_device, DEVICE_GEN_QM357XX); + h = qmrom_init(&spi->dev, qm35_hdl, qm35_hdl->gpio_ss_rdy, + qmrom_retries, qmrom_spi_reset_device); if (!h) { pr_err("qmrom_init failed\n"); ret = -1; @@ -635,16 +500,14 @@ static int qm_firmware_load(struct qm35_ctx *qm35_hdl) dev_info(&spi->dev, " dev_id: deca%04x\n", h->device_version); if (h->chip_rev != CHIP_REVISION_A0) { - dev_info(&spi->dev, " soc_id: %*phN\n", - QM357XX_ROM_SOC_ID_LEN, h->qm357xx_soc_info.soc_id); - dev_info(&spi->dev, " uuid: %*phN\n", - QM357XX_ROM_UUID_LEN, h->qm357xx_soc_info.uuid); - dev_info(&spi->dev, " lcs_state: %u\n", - h->qm357xx_soc_info.lcs_state); + dev_info(&spi->dev, " soc_id: %*phN\n", ROM_SOC_ID_LEN, + h->soc_id); + dev_info(&spi->dev, " uuid: %*phN\n", ROM_UUID_LEN, + h->uuid); + dev_info(&spi->dev, " lcs_state: %u\n", h->lcs_state); memcpy(&qm_dev_id, &h->device_version, sizeof(qm_dev_id)); - memcpy(qm_soc_id, h->qm357xx_soc_info.soc_id, - QM357XX_ROM_SOC_ID_LEN); + memcpy(qm_soc_id, h->soc_id, ROM_SOC_ID_LEN); debug_soc_info_available(&qm35_hdl->debug); } else { @@ -653,21 +516,18 @@ static int qm_firmware_load(struct qm35_ctx *qm35_hdl) } dev_dbg(&spi->dev, "Starting device flashing!\n"); - ret = qm_firmware_flashing(qm35_hdl, h, &is_macro_pkg, true); + ret = qm_firmware_flashing(qm35_hdl, h, true); if (ret) { qmrom_reboot_bootloader(h); - ret = qm_firmware_flashing(qm35_hdl, h, &is_macro_pkg, false); + ret = qm_firmware_flashing(qm35_hdl, h, false); } if (ret) dev_err(&spi->dev, "Firmware download failed with %d!\n", ret); else - dev_info(&spi->dev, "Device flashing succeeded!\n"); + dev_info(&spi->dev, "Device flashing completed!\n"); out: - if (irq >= 0) - disable_irq_nosync(irq); - qm35_set_state(qm35_hdl, state); return ret; @@ -682,7 +542,7 @@ int qm_get_dev_id(struct qm35_ctx *qm35_hdl, uint16_t *dev_id) int qm_get_soc_id(struct qm35_ctx *qm35_hdl, uint8_t *soc_id) { - memcpy(soc_id, qm_soc_id, QM357XX_ROM_SOC_ID_LEN); + memcpy(soc_id, qm_soc_id, ROM_SOC_ID_LEN); return 0; } @@ -707,7 +567,8 @@ int qm_get_soc_id(struct qm35_ctx *qm35_hdl, uint8_t *soc_id) */ static int hsspi_irqs_setup(struct qm35_ctx *qm35_ctx) { - int ret, irq; + int ret; + unsigned long ss_irqflags; /* Get READY GPIO */ qm35_ctx->gpio_ss_rdy = @@ -715,47 +576,25 @@ static int hsspi_irqs_setup(struct qm35_ctx *qm35_ctx) if (IS_ERR(qm35_ctx->gpio_ss_rdy)) return PTR_ERR(qm35_ctx->gpio_ss_rdy); - irq = gpiod_to_irq(qm35_ctx->gpio_ss_rdy); - if (irq < 0) { - dev_err(&qm35_ctx->spi->dev, - "%s: gpiod_to_irq(ss-ready) returns %d", __func__, irq); - return irq; - } - ret = devm_request_irq(&qm35_ctx->spi->dev, irq, &qm35_ss_rdy_handler, - IRQF_TRIGGER_RISING, "hsspi-ss-rdy", qm35_ctx); - if (ret) { - dev_err(&qm35_ctx->spi->dev, "%s: devm_request_irq returned %d", - __func__, ret); + ret = devm_request_irq(&qm35_ctx->spi->dev, + gpiod_to_irq(qm35_ctx->gpio_ss_rdy), + &qm35_ss_rdy_handler, IRQF_TRIGGER_RISING, + "hsspi-ss-rdy", qm35_ctx); + if (ret) return ret; - } - /* devm_request_irq enables the interrupt. On probe, the hsspi is in - * HSSPI_STOPPED state by default. In this state, the interrupt is - * expected to be disabled. */ - disable_irq(irq); /* get SS_IRQ GPIO */ - qm35_ctx->gpio_ss_irq = - devm_gpiod_get(&qm35_ctx->spi->dev, "ss-irq", GPIOD_IN); - if (IS_ERR(qm35_ctx->gpio_ss_irq)) { - dev_err(&qm35_ctx->spi->dev, - "%s: gpiod_get_index(ss-irq) returned %pK", __func__, - qm35_ctx->gpio_ss_irq); - } + qm35_ctx->gpio_ss_irq = devm_gpiod_get_optional(&qm35_ctx->spi->dev, + "ss-irq", GPIOD_IN); - qm35_ctx->spi->irq = gpiod_to_irq(qm35_ctx->gpio_ss_irq); - if (qm35_ctx->spi->irq < 0) { - dev_err(&qm35_ctx->spi->dev, - "%s: gpiod_to_irq(ss-irq) returned %d", __func__, - qm35_ctx->spi->irq); - return qm35_ctx->spi->irq; - } - ret = devm_request_irq(&qm35_ctx->spi->dev, qm35_ctx->spi->irq, - &qm35_irq_handler, IRQF_TRIGGER_HIGH, - "hsspi-ss-irq", qm35_ctx); - if (ret) { - dev_err(&qm35_ctx->spi->dev, "%s: devm_request_irq returned %d", - __func__, ret); - return ret; + if (qm35_ctx->gpio_ss_irq) { + if (IS_ERR(qm35_ctx->gpio_ss_irq)) + return PTR_ERR(qm35_ctx->gpio_ss_irq); + + qm35_ctx->spi->irq = gpiod_to_irq(qm35_ctx->gpio_ss_irq); + ss_irqflags = IRQF_TRIGGER_HIGH; + } else { + ss_irqflags = irq_get_trigger_type(qm35_ctx->spi->irq); } if (wake_on_ssirq) { @@ -769,6 +608,12 @@ static int hsspi_irqs_setup(struct qm35_ctx *qm35_ctx) qm35_ctx->hsspi.wakeup = qm35_wakeup; qm35_ctx->hsspi.reset_qm35 = qm35_reset_hook; + ret = devm_request_irq(&qm35_ctx->spi->dev, qm35_ctx->spi->irq, + &qm35_irq_handler, ss_irqflags, "hsspi-ss-irq", + qm35_ctx); + if (ret) + return ret; + /* Get exton */ qm35_ctx->gpio_exton = devm_gpiod_get_optional(&qm35_ctx->spi->dev, "exton", GPIOD_IN); @@ -916,7 +761,6 @@ static int qm35_probe(struct spi_device *spi) qm35_ctx->spi = spi; qm35_ctx->log_qm_traces = log_qm_traces; spin_lock_init(&qm35_ctx->lock); - init_waitqueue_head(&qm35_ctx->qmrom_wq_ready); spi_set_drvdata(spi, qm35_ctx); @@ -998,11 +842,11 @@ static int qm35_probe(struct spi_device *spi) if (!NO_UWB_HAL) { /* If regulators not available, QM is powered on */ if (!REGULATORS_ENABLED(qm35_ctx)) - qm35_hsspi_start(qm35_ctx); + hsspi_start(&qm35_ctx->hsspi); } else { qm35_regulators_set(qm35_ctx, true); usleep_range(100000, 100000); - qm35_hsspi_start(qm35_ctx); + hsspi_start(&qm35_ctx->hsspi); } ret = misc_register(&qm35_ctx->uci_dev); @@ -1043,7 +887,7 @@ static int qm35_remove(struct spi_device *spi) misc_deregister(&qm35_hdl->uci_dev); - qm35_hsspi_stop(qm35_hdl); + hsspi_stop(&qm35_hdl->hsspi); hsspi_unregister(&qm35_hdl->hsspi, &qm35_hdl->log_layer.hlayer); hsspi_unregister(&qm35_hdl->hsspi, &qm35_hdl->coredump_layer.hlayer); @@ -4,7 +4,6 @@ #define __QM35_H___ #include <linux/gpio.h> -#include <linux/wait.h> #include <linux/delay.h> #include <linux/spi/spi.h> #include <linux/spinlock.h> @@ -17,9 +16,6 @@ #include "hsspi_log.h" #include "debug.h" -#define FWUPDATER_SPI_SPEED_HZ 20000000 -#define DEFAULT_SPI_CLOCKRATE 3000000 - #define DEBUG_CERTIFICATE_SIZE 2560 #define QM_RESET_LOW_MS 2 /* @@ -28,7 +24,7 @@ #define QM_BOOT_MS 450 #define QM_BEFORE_RESET_MS 450 -#define DRV_VERSION "7.2.0-rc6" +#define DRV_VERSION "6.3.8-rc1" struct regulator; @@ -61,11 +57,6 @@ struct qm35_ctx { struct regulator *vdd4; bool regulators_enabled; bool log_qm_traces; - - /* qmrom support */ - struct wait_queue_head qmrom_wq_ready; - bool qmrom_qm_ready; - bool flashing; }; static inline unsigned int qm35_get_state(struct qm35_ctx *qm35_hdl) diff --git a/qmrom_spi.c b/qmrom_spi.c index 76ce52e..0592d2f 100644 --- a/qmrom_spi.c +++ b/qmrom_spi.c @@ -26,7 +26,6 @@ * QM35 FW ROM protocol SPI ops */ -#include <linux/interrupt.h> #include <linux/spi/spi.h> #include <qmrom_spi.h> @@ -34,12 +33,6 @@ #include "qm35.h" -/* TODO Compile QM358XX code */ -int qm358xx_rom_probe_device(struct qmrom_handle *handle) -{ - return -1; -} - static const char *fwname = NULL; static unsigned int speed_hz; extern int trace_spi_xfers; @@ -52,7 +45,6 @@ void qmrom_set_fwname(const char *name) int qmrom_spi_transfer(void *handle, char *rbuf, const char *wbuf, size_t size) { struct spi_device *spi = (struct spi_device *)handle; - struct qm35_ctx *qm35_ctx = spi_get_drvdata(spi); int rc; struct spi_transfer xfer[] = { @@ -64,14 +56,13 @@ int qmrom_spi_transfer(void *handle, char *rbuf, const char *wbuf, size_t size) }, }; - qm35_ctx->qmrom_qm_ready = false; rc = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); if (trace_spi_xfers) { - print_hex_dump(KERN_DEBUG, "qm35 tx:", DUMP_PREFIX_NONE, 16, 1, - wbuf, size, false); - print_hex_dump(KERN_DEBUG, "qm35 rx:", DUMP_PREFIX_NONE, 16, 1, - rbuf, size, false); + print_hex_dump(KERN_DEBUG, "tx:", DUMP_PREFIX_NONE, 16, 1, wbuf, + size, false); + print_hex_dump(KERN_DEBUG, "rx:", DUMP_PREFIX_NONE, 16, 1, rbuf, + size, false); } return rc; @@ -103,25 +94,26 @@ int qmrom_spi_reset_device(void *reset_handle) const struct firmware *qmrom_spi_get_firmware(void *handle, struct qmrom_handle *qmrom_h, - bool *is_macro_pkg, bool use_prod_fw) { const struct firmware *fw; struct spi_device *spi = handle; - const char *fw_name; + char _fw_name[16]; /* enough room to store "qm35_xx_xxx.bin" */ + const char *fw_name = _fw_name; int ret; - uint32_t lcs_state = qmrom_h->qm357xx_soc_info.lcs_state; + enum chip_revision_e revision = qmrom_h->chip_rev; + int lcs_state = qmrom_h->lcs_state; if (!fwname) { - if (lcs_state != CC_BSV_SECURE_LCS) { - dev_warn(&spi->dev, "LCS state is not secure."); - } - - if (use_prod_fw) - fw_name = "qm35_fw_pkg_prod.bin"; - else - fw_name = "qm35_fw_pkg.bin"; - *is_macro_pkg = true; + if (revision == CHIP_REVISION_A0) + 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; } @@ -129,24 +121,6 @@ const struct firmware *qmrom_spi_get_firmware(void *handle, ret = request_firmware(&fw, fw_name, &spi->dev); if (ret) { - if (lcs_state != CC_BSV_SECURE_LCS) { - dev_warn(&spi->dev, "LCS state is not secure."); - } - - /* Didn't get the macro package, try the stitched image */ - *is_macro_pkg = false; - if (use_prod_fw) - fw_name = "qm35_oem_prod.bin"; - else - fw_name = "qm35_oem.bin"; - dev_info(&spi->dev, "Requesting fw %s!\n", fw_name); - ret = request_firmware(&fw, fw_name, &spi->dev); - if (!ret) { - dev_info(&spi->dev, "Firmware size is %zu!\n", - fw->size); - return fw; - } - release_firmware(fw); dev_err(&spi->dev, "request_firmware failed (ret=%d) for '%s'\n", ret, @@ -166,17 +140,11 @@ void qmrom_spi_release_firmware(const struct firmware *fw) int qmrom_spi_wait_for_ready_line(void *handle, unsigned int timeout_ms) { - struct qm35_ctx *qm35_ctx = (struct qm35_ctx *)handle; - - wait_event_interruptible_timeout(qm35_ctx->qmrom_wq_ready, - qm35_ctx->qmrom_qm_ready, - msecs_to_jiffies(timeout_ms)); - return gpiod_get_value(qm35_ctx->gpio_ss_rdy) > 0 ? 0 : -1; -} - -int qmrom_spi_read_irq_line(void *handle) -{ - return gpiod_get_value(handle); + int count_down = (int)timeout_ms; + while (!gpiod_get_value(handle) && (--count_down >= 0)) { + usleep_range(1000, 1100); + } + return gpiod_get_value(handle) ? 0 : -1; } void qmrom_spi_set_freq(unsigned int freq) @@ -184,7 +152,7 @@ void qmrom_spi_set_freq(unsigned int freq) speed_hz = freq; } -unsigned int qmrom_spi_get_freq(void) +unsigned int qmrom_spi_get_freq() { return speed_hz; } |