All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tomasz Lichwala <tomasz.lichwala@linux.intel.com>
To: Aleksandr Loktionov <aleksandr.loktionov@intel.com>,
	intel-wired-lan@lists.osuosl.org, anthony.l.nguyen@intel.com
Subject: Re: [PATCH iwl-next v2 2/2] ice: reject partial NVM update on eRoT adapters
Date: Thu, 15 Oct 2026 13:58:01 +0200	[thread overview]
Message-ID: <1063bc5a-740f-4580-a091-448fdb62e807@linux.intel.com> (raw)
In-Reply-To: <20261008141418.958066-3-aleksandr.loktionov@intel.com>



On 8.10.2026 16:14, Aleksandr Loktionov wrote:
> diff --git a/drivers/net/ethernet/intel/ice/ice_fw_update.c b/drivers/net/ethernet/intel/ice/ice_fw_update.c
> index 3631461..9da7df6 100644
> --- a/drivers/net/ethernet/intel/ice/ice_fw_update.c
> +++ b/drivers/net/ethernet/intel/ice/ice_fw_update.c
> @@ -220,12 +232,27 @@ ice_send_component_table(struct pldmfw *context, struct pldmfw_component *compon
>  	struct ice_pf *pf = priv->pf;
>  	struct ice_hw *hw = &pf->hw;
>  	size_t length;
> +	u8 comp_bit;
>  	int status;
>  
>  	switch (component->identifier) {
>  	case NVM_COMP_ID_OROM:
> +		comp_bit = ICE_FWU_COMP_OROM;
> +		break;
>  	case NVM_COMP_ID_NVM:
> +		comp_bit = ICE_FWU_COMP_NVM;
> +		break;
>  	case NVM_COMP_ID_NETLIST:
> +		comp_bit = ICE_FWU_COMP_NETLIST;
> +		break;
> +	case NVM_COMP_ID_MANIFEST:
> +		if (!priv->erot_present) {
> +			dev_err(dev, "Manifest component is not supported on adapters without eRoT\n");
> +			NL_SET_ERR_MSG_MOD(extack,
> +					   "Manifest component is not supported on adapters without eRoT");
> +			return -EOPNOTSUPP;
> +		}
> +		comp_bit = ICE_FWU_COMP_MANIFEST;
>  		break;
>  	default:
>  		dev_err(dev, "Unable to update due to a firmware component with unknown ID %u\n",
> @@ -234,6 +261,14 @@ ice_send_component_table(struct pldmfw *context, struct pldmfw_component *compon
>  		return -EOPNOTSUPP;
>  	}
>  
> +	if (priv->erot_present && (priv->seen_components & comp_bit)) {
> +		dev_err(dev, "Duplicate component in PLDM image: component ID 0x%02x\n",

Nit: same dual dev_err()/extack reporting pattern already flagged for the Manifest-without-eRoT case above - please fix both occurrences together.

> +			component->identifier);
> +		NL_SET_ERR_MSG_MOD(extack, "Duplicate component in PLDM image");
> +		return -EOPNOTSUPP;
> +	}
> +	priv->seen_components |= comp_bit;
> +
>  	length = struct_size(comp_tbl, cvs, component->version_len);
>  	comp_tbl = kzalloc(length, GFP_KERNEL);
>  	if (!comp_tbl)
> @@ -648,6 +683,12 @@ ice_flash_component(struct pldmfw *context, struct pldmfw_component *component)
>  	u8 flag;
>  	int err;
>  
> +	if (priv->erot_present && priv->seen_components != ICE_FWU_COMP_ALL_EROT) {
> +		NL_SET_ERR_MSG_MOD(extack,
> +				   "eRoT adapter requires all four components (NVM, OROM, NetList, Manifest) in a single update");
> +		return -EINVAL;

Nit: duplicate-component rejection uses -EOPNOTSUPP while this (equally malformed-image) case uses -EINVAL. Consider using one consistently.

> +	}
> +
>  	switch (component->identifier) {
>  	case NVM_COMP_ID_OROM:
>  		module = ICE_SR_1ST_OROM_BANK_PTR;
> @@ -667,6 +708,13 @@ ice_flash_component(struct pldmfw *context, struct pldmfw_component *component)
>  		reset_level = NULL;
>  		name = "fw.netlist";
>  		break;
> +	case NVM_COMP_ID_MANIFEST:
> +		module = ICE_SR_PQC_MANIFEST_BANK_PTR;
> +		/* The AQ activation-select mask has no Manifest bit. */
> +		flag = 0;
> +		reset_level = NULL;
> +		name = "fw.pqc_manifest";

ICE_AQC_NVM_ACTIV_SEL_MASK only covers bits 3-5 (NVM/OROM/NetList), so there's no activation bit for Manifest. ice_get_pending_updates()/ice_cancel_pending_update() also have no notion of a pending Manifest update, so canceling a pending 4-component eRoT update reverts NVM/OROM/NetList but leaves Manifest state undefined. Please confirm the firmware activation contract for Manifest before merging - the cover letter itself says this is unconfirmed and not hardware-validated.

> +		break;
>  	default:
>  		/* This should not trigger, since we check the id before
>  		 * sending the component table to firmware.
> @@ -706,6 +754,12 @@ static int ice_finalize_update(struct pldmfw *context)
>  	struct devlink *devlink;
>  	int err;
>  
> +	if (priv->erot_present && priv->seen_components != ICE_FWU_COMP_ALL_EROT) {
> +		NL_SET_ERR_MSG_MOD(extack,
> +				   "eRoT adapter requires all four components (NVM, OROM, NetList, Manifest) in a single update");
> +		return -EINVAL;
> +	}
> +
>  	/* Finally, notify firmware to activate the written NVM banks */
>  	err = ice_switch_flash_banks(pf, priv->activate_flags,
>  				     &priv->emp_reset_available, extack);
> @@ -981,9 +1035,9 @@ ice_cancel_pending_update(struct ice_pf *pf, const char *component,
>   * formatted image that matches this device.
>   *
>   * Extract the device record Package Data and Component Tables and send them
> - * to the firmware. Extract and write the flash data for each of the three
> - * main flash components, "fw.mgmt", "fw.undi", and "fw.netlist". Notify
> - * firmware once the data is written to the inactive banks.
> + * to the firmware. Extract and write the flash data for the selected firmware
> + * components: "fw.mgmt", "fw.undi", "fw.netlist", and, when firmware reports
> + * eRoT presence, "fw.pqc_manifest". Notify firmware once the data is written.
>   *
>   * Returns: zero on success or a negative error code on failure.
>   */
> @@ -1013,12 +1067,37 @@ int ice_devlink_flash_update(struct devlink *devlink,
>  		return -EOPNOTSUPP;
>  	}
>  
> -	if (!hw->dev_caps.common_cap.nvm_unified_update && !ice_is_recovery_mode(hw)) {
> +	struct ice_hw_dev_caps *dev_caps __free(kfree) =
> +		kzalloc_obj(*dev_caps);
> +	if (!dev_caps)
> +		return -ENOMEM;
> +
> +	err = ice_discover_dev_caps(hw, dev_caps);

This duplicates the ice_discover_dev_caps() call already done inside ice_get_pending_updates(), reached right after via ice_cancel_pending_update() — two AQ list-caps round-trips per flash attempt. Also note ice_switch_flash_banks()/ice_write_one_nvm_block() still read the cached hw->dev_caps.common_cap.* instead of this fresh snapshot, so the "per-update snapshot" isn't actually used consistently within the same update.

> +	if (err) {
> +		NL_SET_ERR_MSG_MOD(extack,
> +				   "Cannot determine eRoT state: unable to read firmware device capabilities");
> +		return err;
> +	}
> +
> +	if (dev_caps->common_cap.external_pqc_rot_invalid) {
> +		NL_SET_ERR_MSG_MOD(extack,
> +				   "Invalid eRoT capability reported by firmware");
> +		return -EOPNOTSUPP;
> +	}
> +
> +	if (!dev_caps->common_cap.nvm_unified_update && !ice_is_recovery_mode(hw)) {
>  		NL_SET_ERR_MSG_MOD(extack, "Current firmware does not support unified update");
>  		return -EOPNOTSUPP;
>  	}
>  
>  	memset(&priv, 0, sizeof(priv));
> +	priv.erot_present = dev_caps->common_cap.external_pqc_rot_present;
> +
> +	if (params->component && priv.erot_present) {
> +		NL_SET_ERR_MSG_MOD(extack,
> +				   "eRoT adapter does not support single component update");
> +		return -EOPNOTSUPP;
> +	}
>  
>  	if (params->component && strcmp(params->component, "fw.mgmt") == 0) {
>  		priv.context.mode = PLDMFW_UPDATE_MODE_SINGLE_COMPONENT;
		priv.context.component_identifier = NVM_COMP_ID_NVM;
	} else if (params->component) {
		return -EOPNOTSUPP;
	}

	/* the E822 device needs a slightly different ops */
	if (hw->mac_type == ICE_MAC_GENERIC)
		priv.context.ops = &ice_fwu_ops_e822;
	else
		priv.context.ops = &ice_fwu_ops_e810;
	priv.context.dev = dev;
	priv.extack = extack;
	priv.pf = pf;
	priv.activate_flags = preservation;

	devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0);

	err = ice_cancel_pending_update(pf, NULL, extack);

This unconditionally reverts any previously staged pending update before the new completeness/duplicate checks run (they only fire later, inside the pldmfw callbacks). So a malformed eRoT image is rejected "before any bank is erased" as documented, but only after a valid prior pending update has already been reverted. Worth calling out explicitly in the docs, or checking completeness before canceling.

	if (err)
		return err;


> diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
> index 1fede0f..43f3208 100644
> --- a/drivers/net/ethernet/intel/ice/ice_type.h
> +++ b/drivers/net/ethernet/intel/ice/ice_type.h
> @@ -1151,6 +1151,7 @@ struct ice_aq_get_set_rss_lut_params {
>  #define ICE_SR_OROM_BANK_SIZE		0x45
>  #define ICE_SR_NETLIST_BANK_PTR		0x46
>  #define ICE_SR_NETLIST_BANK_SIZE	0x47
> +#define ICE_SR_PQC_MANIFEST_BANK_PTR	0x4E
>  #define ICE_SR_SECTOR_SIZE_IN_WORDS	0x800
>  
>  /* CSS Header words */

Thanks,
Tomasz

      parent reply	other threads:[~2026-10-15 11:58 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-08 14:14 [PATCH iwl-next v2 0/2] ice: eRoT adapter NVM update guard Aleksandr Loktionov
2026-10-08 14:14 ` [PATCH iwl-next v2 1/2] ice: parse external Root of Trust capability Aleksandr Loktionov
2026-10-15 11:57   ` Tomasz Lichwala
2026-10-08 14:14 ` [PATCH iwl-next v2 2/2] ice: reject partial NVM update on eRoT adapters Aleksandr Loktionov
2026-10-13 21:51   ` Tony Nguyen
2026-10-14 22:59   ` Przemek Kitszel
2026-10-15 11:58   ` Tomasz Lichwala [this message]

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=1063bc5a-740f-4580-a091-448fdb62e807@linux.intel.com \
    --to=tomasz.lichwala@linux.intel.com \
    --cc=aleksandr.loktionov@intel.com \
    --cc=anthony.l.nguyen@intel.com \
    --cc=intel-wired-lan@lists.osuosl.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.