All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ajay Gupta <ajayg@nvidia.com>
To: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: "linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>
Subject: [5/7] usb: typec: ucsi: add fw update needed check
Date: Thu, 24 Jan 2019 17:54:37 +0000	[thread overview]
Message-ID: <BYAPR12MB272765FD870CAA2EAE8E29B7DC9A0@BYAPR12MB2727.namprd12.prod.outlook.com> (raw)

Hi Heikki,

> > Signed-off-by: Ajay Gupta <ajayg@nvidia.com>
> > ---
> >  drivers/usb/typec/ucsi/ucsi_ccg.c | 139
> > ++++++++++++++++++++++++++++++
> >  1 file changed, 139 insertions(+)
> >
> > diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c
> > b/drivers/usb/typec/ucsi/ucsi_ccg.c
> > index 5f341934a5af..6069a9f60d1e 100644
> > --- a/drivers/usb/typec/ucsi/ucsi_ccg.c
> > +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
> > @@ -9,6 +9,7 @@
> >   */
> >  #include <linux/acpi.h>
> >  #include <linux/delay.h>
> > +#include <linux/firmware.h>
> >  #include <linux/i2c.h>
> >  #include <linux/module.h>
> >  #include <linux/pci.h>
> > @@ -17,6 +18,8 @@
> >  #include <asm/unaligned.h>
> >  #include "ucsi.h"
> >
> > +static int secondary_fw_min_ver = 41;
> > +module_param(secondary_fw_min_ver, int, 0660);
> >  #define CCGX_RAB_DEVICE_MODE			0x0000
> >  #define CCGX_RAB_INTR_REG			0x0006
> >  #define  DEV_INT				BIT(0)
> > @@ -68,6 +71,27 @@
> >  #define FW2_METADATA_ROW        0x1FE
> >  #define FW_CFG_TABLE_SIG_SIZE	256
> >
> > +enum enum_fw_mode {
> > +	BOOT,   /* bootloader */
> > +	FW1,    /* FW partition-1 */
> > +	FW2,    /* FW partition-2 */
> > +	FW_INVALID,
> > +};
> > +
> > +enum enum_flash_mode {
> > +	SECONDARY_BL,	/* update secondary using bootloader */
> > +	SECONDARY,	/* update secondary using primary */
> > +	PRIMARY,	/* update primary */
> > +	FLASH_NOT_NEEDED,	/* update not required */
> > +	FLASH_INVALID,
> > +};
> > +
> > +static const char * const ccg_fw_names[] = {
> > +	/* 0x00 */ "ccg_boot.cyacd",
> > +	/* 0x01 */ "ccg_2.cyacd",
> > +	/* 0x02 */ "ccg_1.cyacd",
> > +};
> > +
> >  struct ccg_dev_info {
> >  	u8 fw_mode:2;
> >  	u8 two_pd_ports:2;
> > @@ -95,6 +119,20 @@ struct version_info {
> >  	struct version_format app;
> >  };
> >
> > +struct fw_config_table {
> > +	u32 identity;
> > +	u16 table_size;
> > +	u8 fwct_version;
> > +	u8 is_key_change;
> > +	u8 guid[16];
> > +	struct version_format base;
> > +	struct version_format app;
> > +	u8 primary_fw_digest[32];
> > +	u32 key_exp_length;
> > +	u8 key_modulus[256];
> > +	u8 key_exp[4];
> > +};
> > +
> >  /* CCGx response codes */
> >  enum ccg_resp_code {
> >  	CMD_NO_RESP             = 0x00,
> > @@ -737,6 +775,107 @@ static int ccg_cmd_validate_fw(struct ucsi_ccg *uc,
> unsigned int fwid)
> >  	return 0;
> >  }
> >
> > +static bool ccg_check_fw_version(struct ucsi_ccg *uc, const char *fw_name,
> > +				 struct version_format *app)
> > +{
> > +	const struct firmware *fw = NULL;
> > +	struct device *dev = uc->dev;
> > +	struct fw_config_table fw_cfg;
> > +	u32 cur_version, new_version;
> > +	bool is_later = false;
> > +
> > +	if (request_firmware(&fw, fw_name, dev) != 0) {
> > +		dev_err(dev, "error: Failed to open cyacd file %s\n", fw_name);
> > +		return false;
> > +	}
> > +
> > +	/*
> > +	 * check if signed fw
> > +	 * last part of fw image is fw cfg table and signature
> > +	 */
> > +	if (fw->size < sizeof(fw_cfg) + FW_CFG_TABLE_SIG_SIZE)
> > +		goto not_signed_fw;
> > +
> > +	memcpy((uint8_t *)&fw_cfg, fw->data + fw->size -
> > +	       sizeof(fw_cfg) - FW_CFG_TABLE_SIG_SIZE, sizeof(fw_cfg));
> > +
> > +	if (fw_cfg.identity != ('F' | ('W' << 8) | ('C' << 16) | ('T' << 24))) {
> > +		dev_info(dev, "not a signed image\n");
> > +		goto not_signed_fw;
> > +	}
> > +
> > +	/* compare input version with FWCT version */
> > +	cur_version = app->build | (app->patch << 16) |
> > +			((app->min | (app->maj << 4)) << 24);
> > +
> > +	new_version = fw_cfg.app.build | (fw_cfg.app.patch << 16) |
> > +			((fw_cfg.app.min | (fw_cfg.app.maj << 4)) << 24);
> > +
> > +	dev_dbg(dev, "compare current %08x and new version %08x\n",
> > +		cur_version, new_version);
> > +
> > +	if (new_version > cur_version) {
> > +		dev_dbg(dev, "new firmware file version is later\n");
> > +		is_later = true;
> > +	} else {
> > +		dev_dbg(dev, "new firmware file version is same or earlier\n");
> > +	}
> > +
> > +not_signed_fw:
> > +	release_firmware(fw);
> > +	return is_later;
> > +}
> > +
> > +static int ccg_fw_update_needed(struct ucsi_ccg *uc,
> > +				enum enum_flash_mode *mode)
> > +{
> > +	struct device *dev = uc->dev;
> > +	int err;
> > +	struct version_info version[3];
> > +
> > +	err = ccg_read(uc, CCGX_RAB_DEVICE_MODE, (u8 *)(&uc->info),
> > +		       sizeof(uc->info));
> > +	if (err) {
> > +		dev_err(dev, "read device mode failed\n");
> > +		return err;
> > +	}
> > +
> > +	err = ccg_read(uc, CCGX_RAB_READ_ALL_VER, (u8 *)version,
> > +		       sizeof(version));
> > +	if (err) {
> > +		dev_err(dev, "read device mode failed\n");
> > +		return err;
> > +	}
> > +
> > +	dev_dbg(dev, "check if fw upgrade required %x %x %x %x %x %x %x
> %x\n",
> > +		version[FW1].base.build, version[FW1].base.patch,
> > +		version[FW1].base.min, version[FW1].base.maj,
> > +		version[FW2].app.build, version[FW2].app.patch,
> > +		version[FW2].app.min, version[FW2].app.maj);
> > +
> > +	if (memcmp(&version[FW1], "\0\0\0\0\0\0\0\0",
> > +		   sizeof(struct version_info)) == 0) {
> > +		dev_info(dev, "secondary fw is not flashed\n");
> > +		*mode = SECONDARY_BL;
> > +	} else if (version[FW1].base.build < secondary_fw_min_ver) {
> > +		dev_info(dev, "secondary fw version is too low (< %d)\n",
> > +			 secondary_fw_min_ver);
> > +		*mode = SECONDARY;
> > +	} else if (memcmp(&version[FW2], "\0\0\0\0\0\0\0\0",
> > +		   sizeof(struct version_info)) == 0) {
> > +		dev_info(dev, "primary fw is not flashed\n");
> > +		*mode = PRIMARY;
> > +	} else if (ccg_check_fw_version(uc, ccg_fw_names[PRIMARY],
> > +		   &version[FW2].app)) {
> > +		dev_info(dev, "found primary fw with later version\n");
> > +		*mode = PRIMARY;
> > +	} else {
> > +		dev_info(dev, "secondary and primary fw are the latest\n");
> > +		*mode = FLASH_NOT_NEEDED;
> > +	}
> > +	return 0;
> > +}
> 
> Before sending a new version, can you first explain what are you trying to do
> here?
We are reading the current flashed firmware version of both primary and secondary
and comparing it against the new firmware files. If the new firmware versions are later
than the currently flashed then only we update the firmware.
 
> I would assume that you just want to read the version of your current fw, and if
> there is a newer version of the firmware available, you upgrade it, and that's it.
That's correct.

> Perhaps I'm missing something?
I think you missed that there are two firmware, primary and secondary. 

Thanks
> nvpublic 
> 
> 
> thanks,
> 
> --
> heikki

             reply	other threads:[~2019-01-24 17:54 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-24 17:54 Ajay Gupta [this message]
  -- strict thread matches above, loose matches on Subject: below --
2019-01-24 18:01 [5/7] usb: typec: ucsi: add fw update needed check Ajay Gupta
2019-01-24 17:47 Ajay Gupta
2019-01-18 15:37 Heikki Krogerus
2019-01-18  7:07 Greg KH
2019-01-18  7:06 Greg Kroah-Hartman
2019-01-18  1:12 Ajay Gupta

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=BYAPR12MB272765FD870CAA2EAE8E29B7DC9A0@BYAPR12MB2727.namprd12.prod.outlook.com \
    --to=ajayg@nvidia.com \
    --cc=heikki.krogerus@linux.intel.com \
    --cc=linux-usb@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.