* [PATCH v1] Bluetooth: btintel: check FIPS status before firmware download
@ 2026-10-21 13:04 Kiran K
2026-10-21 18:07 ` [v1] " bluez.test.bot
2026-10-23 21:49 ` [PATCH v1] " Luiz Augusto von Dentz
0 siblings, 2 replies; 4+ messages in thread
From: Kiran K @ 2026-10-21 13:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: chethan.tumkur.narayan, chandrashekar.devegowda, Kiran K
Intel Bluetooth controllers (PCIe and USB) from Scorpius Peak2 onwards
report bootloader self-test results (CRC, security, patch) in the
INTEL_TLV_FIPS_STS TLV of the Intel Read Version event. Act on them
before firmware download:
1. CRC failure -> abort download.
2. Security failure -> abort on USB / HW reset and retry on PCIe.
3. Patch failure -> abort on USB / HW reset and retry on PCIe.
Signed-off-by: Kiran K <kiran.k@intel.com>
---
drivers/bluetooth/btintel.c | 66 +++++++++++++++++++++++++++++++-
drivers/bluetooth/btintel.h | 10 +++++
drivers/bluetooth/btintel_pcie.c | 18 ++++++++-
3 files changed, 90 insertions(+), 4 deletions(-)
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 0709fb3212f9..f6deb3d7c5a0 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -485,10 +485,18 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver)
}
EXPORT_SYMBOL_GPL(btintel_read_version);
+/* FIPS self-test status is only reported by ScP2 onwards, except BlazarIW */
+static bool btintel_fips_status_supported(u8 hw_variant)
+{
+ return hw_variant >= BTINTEL_HWID_SCP2 && hw_variant != BTINTEL_HWID_BZRIW;
+}
+
int btintel_version_info_tlv(struct hci_dev *hdev,
struct intel_version_tlv *version)
{
const char *variant;
+ bool fips_status = false;
+ u8 hw_variant;
/* The hardware platform number has a fixed value of 0x37 and
* for now only accept this single value.
@@ -505,7 +513,8 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
* This check has been put in place to ensure correct forward
* compatibility options when newer hardware variants come along.
*/
- switch (INTEL_HW_VARIANT(version->cnvi_bt)) {
+ hw_variant = INTEL_HW_VARIANT(version->cnvi_bt);
+ switch (hw_variant) {
case 0x17: /* TyP */
case 0x18: /* Slr */
case 0x19: /* Slr-F */
@@ -521,10 +530,13 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
break;
default:
bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
- INTEL_HW_VARIANT(version->cnvi_bt));
+ hw_variant);
return -EINVAL;
}
+ fips_status = btintel_fips_status_supported(hw_variant) &&
+ version->img_type == BTINTEL_IMG_BOOTLOADER;
+
switch (version->img_type) {
case BTINTEL_IMG_BOOTLOADER:
variant = "Bootloader";
@@ -584,6 +596,9 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
bt_dev_info(hdev, "Unlock policy: 0x%2.2x", version->unlock_policy);
+ if (fips_status)
+ bt_dev_info(hdev, "crc status: %u security status: %u patch status: %u",
+ version->crc_sts, version->sec_sts, version->patch_sts);
return 0;
}
EXPORT_SYMBOL_GPL(btintel_version_info_tlv);
@@ -612,6 +627,7 @@ static u8 btintel_version_tlv_min_len(u8 type)
case INTEL_TLV_UNLOCK_POLICY:
return sizeof(u8);
case INTEL_TLV_MIN_FW:
+ case INTEL_TLV_FIPS_STS:
return 3;
case INTEL_TLV_OTP_BDADDR:
return sizeof(bdaddr_t);
@@ -720,6 +736,11 @@ int btintel_parse_version_tlv(struct hci_dev *hdev,
case INTEL_TLV_GIT_SHA1:
version->git_sha1 = get_unaligned_le32(tlv->val);
break;
+ case INTEL_TLV_FIPS_STS:
+ version->crc_sts = tlv->val[0];
+ version->sec_sts = tlv->val[1];
+ version->patch_sts = tlv->val[2];
+ break;
case INTEL_TLV_FW_ID:
snprintf(version->fw_id, sizeof(version->fw_id),
"%.*s", tlv->len, tlv->val);
@@ -3831,6 +3852,43 @@ void btintel_print_fseq_info(struct hci_dev *hdev)
}
EXPORT_SYMBOL_GPL(btintel_print_fseq_info);
+int btintel_check_fips_status(struct hci_dev *hdev,
+ struct intel_version_tlv *ver)
+{
+ u8 hw_variant;
+
+ /* FIPS status is reported only in the bootloader image */
+ if (ver->img_type != BTINTEL_IMG_BOOTLOADER)
+ return 0;
+
+ hw_variant = INTEL_HW_VARIANT(ver->cnvi_bt);
+
+ if (!btintel_fips_status_supported(hw_variant))
+ return 0;
+
+ /* 0 -> Test not executed
+ * 1 -> Test executed and it passed
+ * any other value -> Test failed
+ */
+ if (ver->crc_sts > 1) {
+ bt_dev_err(hdev, "crc test failed: %u", ver->crc_sts);
+ return -ENOEXEC;
+ }
+
+ if (ver->sec_sts > 1) {
+ bt_dev_err(hdev, "security test failed: %u", ver->sec_sts);
+ return -EAGAIN;
+ }
+
+ if (ver->patch_sts > 1) {
+ bt_dev_err(hdev, "patch test failed: %u", ver->patch_sts);
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(btintel_check_fips_status);
+
static int btintel_setup_combined(struct hci_dev *hdev)
{
const u8 param[1] = { 0xFF };
@@ -4055,6 +4113,10 @@ static int btintel_setup_combined(struct hci_dev *hdev)
/* Display version information of TLV type */
btintel_version_info_tlv(hdev, &ver_tlv);
+ err = btintel_check_fips_status(hdev, &ver_tlv);
+ if (err)
+ goto exit_error;
+
/* Apply the device specific HCI quirks for TLV based devices
*
* All TLV based devices support WBS
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
index 9526acf65959..d5e125ec5168 100644
--- a/drivers/bluetooth/btintel.h
+++ b/drivers/bluetooth/btintel.h
@@ -43,6 +43,7 @@ enum {
INTEL_TLV_OTP_BDADDR,
INTEL_TLV_UNLOCKED_STATE,
INTEL_TLV_GIT_SHA1,
+ INTEL_TLV_FIPS_STS = 0x3b,
INTEL_TLV_UNLOCK_POLICY = 0x3c,
INTEL_TLV_PLATFORM_ID = 0x3d,
INTEL_TLV_FW_ID = 0x50
@@ -112,6 +113,7 @@ struct intel_version_tlv {
bdaddr_t otp_bd_addr;
u8 unlock_policy;
u8 platform_id[6];
+ u8 crc_sts, sec_sts, patch_sts;
};
struct intel_version {
@@ -331,6 +333,8 @@ int btintel_shutdown_combined(struct hci_dev *hdev);
void btintel_hw_error(struct hci_dev *hdev, u8 code);
void btintel_print_fseq_info(struct hci_dev *hdev);
int btintel_acpi_reset_method(struct hci_dev *hdev);
+int btintel_check_fips_status(struct hci_dev *hdev,
+ struct intel_version_tlv *ver);
#else
static inline int btintel_check_bdaddr(struct hci_dev *hdev)
@@ -468,4 +472,10 @@ static inline int btintel_acpi_reset_method(struct hci_dev *hdev)
{
return -ENODEV;
}
+
+static inline int btintel_check_fips_status(struct hci_dev *hdev,
+ struct intel_version_tlv *ver)
+{
+ return -EOPNOTSUPP;
+}
#endif
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index df95d16a163c..73822ba2acbb 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -3786,7 +3786,8 @@ static int btintel_pcie_get_debug_info_addr(struct hci_dev *hdev)
return err;
}
-static int btintel_pcie_setup_internal(struct hci_dev *hdev)
+static int btintel_pcie_setup_internal(struct hci_dev *hdev,
+ bool *fips_crc_failed)
{
struct btintel_pcie_data *data = hci_get_drvdata(hdev);
const u8 param[1] = { 0xFF };
@@ -3794,6 +3795,8 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev)
struct sk_buff *skb;
int err;
+ *fips_crc_failed = false;
+
BT_DBG("%s", hdev->name);
skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, HCI_CMD_TIMEOUT);
@@ -3855,6 +3858,12 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev)
/* Display version information of TLV type */
btintel_version_info_tlv(hdev, &ver_tlv);
+ err = btintel_check_fips_status(hdev, &ver_tlv);
+ if (err) {
+ *fips_crc_failed = (err == -ENOEXEC);
+ goto exit_error;
+ }
+
/* Apply the device specific HCI quirks for TLV based devices
*
* All TLV based devices support WBS
@@ -3900,8 +3909,13 @@ static int btintel_pcie_setup(struct hci_dev *hdev)
{
int err, fw_dl_retry = 0;
struct btintel_pcie_data *data = hci_get_drvdata(hdev);
+ bool fips_crc_failed;
+
+ while ((err = btintel_pcie_setup_internal(hdev, &fips_crc_failed)) &&
+ fw_dl_retry++ < 1) {
+ if (fips_crc_failed)
+ break;
- while ((err = btintel_pcie_setup_internal(hdev)) && fw_dl_retry++ < 1) {
bt_dev_err(hdev, "Firmware download retry count: %d",
fw_dl_retry);
btintel_pcie_dump_debug_registers(hdev);
--
2.54.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* RE: [v1] Bluetooth: btintel: check FIPS status before firmware download
2026-10-21 13:04 [PATCH v1] Bluetooth: btintel: check FIPS status before firmware download Kiran K
@ 2026-10-21 18:07 ` bluez.test.bot
2026-10-23 21:49 ` [PATCH v1] " Luiz Augusto von Dentz
1 sibling, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2026-10-21 18:07 UTC (permalink / raw)
To: linux-bluetooth, kiran.k
[-- Attachment #1: Type: text/plain, Size: 1019 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1190499/
---Test result---
Test Summary:
CheckPatch PASS 1.17 seconds
VerifyFixes PASS 0.09 seconds
VerifySignedoff PASS 7.16 seconds
GitLint PASS 0.27 seconds
SubjectPrefix PASS 0.09 seconds
BuildKernel PASS 30.84 seconds
CheckAllWarning PASS 35.19 seconds
CheckSparse PASS 38.01 seconds
BuildKernel32 PASS 30.63 seconds
CheckKernelLLVM PASS 35.04 seconds
TestRunnerSetup PASS 720.87 seconds
IncrementalBuild PASS 35.13 seconds
https://github.com/bluez/bluetooth-next/pull/973
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v1] Bluetooth: btintel: check FIPS status before firmware download
2026-10-21 13:04 [PATCH v1] Bluetooth: btintel: check FIPS status before firmware download Kiran K
2026-10-21 18:07 ` [v1] " bluez.test.bot
@ 2026-10-23 21:49 ` Luiz Augusto von Dentz
2026-10-27 12:56 ` K, Kiran
1 sibling, 1 reply; 4+ messages in thread
From: Luiz Augusto von Dentz @ 2026-10-23 21:49 UTC (permalink / raw)
To: Kiran K; +Cc: linux-bluetooth, chethan.tumkur.narayan, chandrashekar.devegowda
Hi Kiran,
On Wed, Oct 21, 2026 at 9:02 AM Kiran K <kiran.k@intel.com> wrote:
>
> Intel Bluetooth controllers (PCIe and USB) from Scorpius Peak2 onwards
> report bootloader self-test results (CRC, security, patch) in the
> INTEL_TLV_FIPS_STS TLV of the Intel Read Version event. Act on them
> before firmware download:
>
> 1. CRC failure -> abort download.
> 2. Security failure -> abort on USB / HW reset and retry on PCIe.
> 3. Patch failure -> abort on USB / HW reset and retry on PCIe.
>
> Signed-off-by: Kiran K <kiran.k@intel.com>
> ---
> drivers/bluetooth/btintel.c | 66 +++++++++++++++++++++++++++++++-
> drivers/bluetooth/btintel.h | 10 +++++
> drivers/bluetooth/btintel_pcie.c | 18 ++++++++-
> 3 files changed, 90 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
> index 0709fb3212f9..f6deb3d7c5a0 100644
> --- a/drivers/bluetooth/btintel.c
> +++ b/drivers/bluetooth/btintel.c
> @@ -485,10 +485,18 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver)
> }
> EXPORT_SYMBOL_GPL(btintel_read_version);
>
> +/* FIPS self-test status is only reported by ScP2 onwards, except BlazarIW */
> +static bool btintel_fips_status_supported(u8 hw_variant)
> +{
> + return hw_variant >= BTINTEL_HWID_SCP2 && hw_variant != BTINTEL_HWID_BZRIW;
> +}
> +
> int btintel_version_info_tlv(struct hci_dev *hdev,
> struct intel_version_tlv *version)
> {
> const char *variant;
> + bool fips_status = false;
> + u8 hw_variant;
>
> /* The hardware platform number has a fixed value of 0x37 and
> * for now only accept this single value.
> @@ -505,7 +513,8 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
> * This check has been put in place to ensure correct forward
> * compatibility options when newer hardware variants come along.
> */
> - switch (INTEL_HW_VARIANT(version->cnvi_bt)) {
> + hw_variant = INTEL_HW_VARIANT(version->cnvi_bt);
> + switch (hw_variant) {
> case 0x17: /* TyP */
> case 0x18: /* Slr */
> case 0x19: /* Slr-F */
> @@ -521,10 +530,13 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
> break;
> default:
> bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
> - INTEL_HW_VARIANT(version->cnvi_bt));
> + hw_variant);
> return -EINVAL;
> }
>
> + fips_status = btintel_fips_status_supported(hw_variant) &&
> + version->img_type == BTINTEL_IMG_BOOTLOADER;
> +
> switch (version->img_type) {
> case BTINTEL_IMG_BOOTLOADER:
> variant = "Bootloader";
> @@ -584,6 +596,9 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
>
> bt_dev_info(hdev, "Unlock policy: 0x%2.2x", version->unlock_policy);
>
> + if (fips_status)
> + bt_dev_info(hdev, "crc status: %u security status: %u patch status: %u",
> + version->crc_sts, version->sec_sts, version->patch_sts);
> return 0;
> }
> EXPORT_SYMBOL_GPL(btintel_version_info_tlv);
> @@ -612,6 +627,7 @@ static u8 btintel_version_tlv_min_len(u8 type)
> case INTEL_TLV_UNLOCK_POLICY:
> return sizeof(u8);
> case INTEL_TLV_MIN_FW:
> + case INTEL_TLV_FIPS_STS:
> return 3;
> case INTEL_TLV_OTP_BDADDR:
> return sizeof(bdaddr_t);
> @@ -720,6 +736,11 @@ int btintel_parse_version_tlv(struct hci_dev *hdev,
> case INTEL_TLV_GIT_SHA1:
> version->git_sha1 = get_unaligned_le32(tlv->val);
> break;
> + case INTEL_TLV_FIPS_STS:
> + version->crc_sts = tlv->val[0];
> + version->sec_sts = tlv->val[1];
> + version->patch_sts = tlv->val[2];
> + break;
> case INTEL_TLV_FW_ID:
> snprintf(version->fw_id, sizeof(version->fw_id),
> "%.*s", tlv->len, tlv->val);
> @@ -3831,6 +3852,43 @@ void btintel_print_fseq_info(struct hci_dev *hdev)
> }
> EXPORT_SYMBOL_GPL(btintel_print_fseq_info);
>
> +int btintel_check_fips_status(struct hci_dev *hdev,
> + struct intel_version_tlv *ver)
> +{
> + u8 hw_variant;
> +
> + /* FIPS status is reported only in the bootloader image */
> + if (ver->img_type != BTINTEL_IMG_BOOTLOADER)
> + return 0;
> +
> + hw_variant = INTEL_HW_VARIANT(ver->cnvi_bt);
> +
> + if (!btintel_fips_status_supported(hw_variant))
> + return 0;
> +
> + /* 0 -> Test not executed
> + * 1 -> Test executed and it passed
> + * any other value -> Test failed
> + */
> + if (ver->crc_sts > 1) {
> + bt_dev_err(hdev, "crc test failed: %u", ver->crc_sts);
> + return -ENOEXEC;
> + }
> +
> + if (ver->sec_sts > 1) {
> + bt_dev_err(hdev, "security test failed: %u", ver->sec_sts);
> + return -EAGAIN;
> + }
> +
> + if (ver->patch_sts > 1) {
> + bt_dev_err(hdev, "patch test failed: %u", ver->patch_sts);
> + return -EAGAIN;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(btintel_check_fips_status);
> +
> static int btintel_setup_combined(struct hci_dev *hdev)
> {
> const u8 param[1] = { 0xFF };
> @@ -4055,6 +4113,10 @@ static int btintel_setup_combined(struct hci_dev *hdev)
> /* Display version information of TLV type */
> btintel_version_info_tlv(hdev, &ver_tlv);
>
> + err = btintel_check_fips_status(hdev, &ver_tlv);
> + if (err)
> + goto exit_error;
> +
> /* Apply the device specific HCI quirks for TLV based devices
> *
> * All TLV based devices support WBS
> diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
> index 9526acf65959..d5e125ec5168 100644
> --- a/drivers/bluetooth/btintel.h
> +++ b/drivers/bluetooth/btintel.h
> @@ -43,6 +43,7 @@ enum {
> INTEL_TLV_OTP_BDADDR,
> INTEL_TLV_UNLOCKED_STATE,
> INTEL_TLV_GIT_SHA1,
> + INTEL_TLV_FIPS_STS = 0x3b,
> INTEL_TLV_UNLOCK_POLICY = 0x3c,
> INTEL_TLV_PLATFORM_ID = 0x3d,
> INTEL_TLV_FW_ID = 0x50
> @@ -112,6 +113,7 @@ struct intel_version_tlv {
> bdaddr_t otp_bd_addr;
> u8 unlock_policy;
> u8 platform_id[6];
> + u8 crc_sts, sec_sts, patch_sts;
> };
>
> struct intel_version {
> @@ -331,6 +333,8 @@ int btintel_shutdown_combined(struct hci_dev *hdev);
> void btintel_hw_error(struct hci_dev *hdev, u8 code);
> void btintel_print_fseq_info(struct hci_dev *hdev);
> int btintel_acpi_reset_method(struct hci_dev *hdev);
> +int btintel_check_fips_status(struct hci_dev *hdev,
> + struct intel_version_tlv *ver);
> #else
>
> static inline int btintel_check_bdaddr(struct hci_dev *hdev)
> @@ -468,4 +472,10 @@ static inline int btintel_acpi_reset_method(struct hci_dev *hdev)
> {
> return -ENODEV;
> }
> +
> +static inline int btintel_check_fips_status(struct hci_dev *hdev,
> + struct intel_version_tlv *ver)
> +{
> + return -EOPNOTSUPP;
> +}
> #endif
> diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
> index df95d16a163c..73822ba2acbb 100644
> --- a/drivers/bluetooth/btintel_pcie.c
> +++ b/drivers/bluetooth/btintel_pcie.c
> @@ -3786,7 +3786,8 @@ static int btintel_pcie_get_debug_info_addr(struct hci_dev *hdev)
> return err;
> }
>
> -static int btintel_pcie_setup_internal(struct hci_dev *hdev)
> +static int btintel_pcie_setup_internal(struct hci_dev *hdev,
> + bool *fips_crc_failed)
> {
> struct btintel_pcie_data *data = hci_get_drvdata(hdev);
> const u8 param[1] = { 0xFF };
> @@ -3794,6 +3795,8 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev)
> struct sk_buff *skb;
> int err;
>
> + *fips_crc_failed = false;
> +
> BT_DBG("%s", hdev->name);
>
> skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, HCI_CMD_TIMEOUT);
> @@ -3855,6 +3858,12 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev)
> /* Display version information of TLV type */
> btintel_version_info_tlv(hdev, &ver_tlv);
>
> + err = btintel_check_fips_status(hdev, &ver_tlv);
> + if (err) {
> + *fips_crc_failed = (err == -ENOEXEC);
> + goto exit_error;
> + }
> +
> /* Apply the device specific HCI quirks for TLV based devices
> *
> * All TLV based devices support WBS
> @@ -3900,8 +3909,13 @@ static int btintel_pcie_setup(struct hci_dev *hdev)
> {
> int err, fw_dl_retry = 0;
> struct btintel_pcie_data *data = hci_get_drvdata(hdev);
> + bool fips_crc_failed;
> +
> + while ((err = btintel_pcie_setup_internal(hdev, &fips_crc_failed)) &&
> + fw_dl_retry++ < 1) {
> + if (fips_crc_failed)
> + break;
>
> - while ((err = btintel_pcie_setup_internal(hdev)) && fw_dl_retry++ < 1) {
> bt_dev_err(hdev, "Firmware download retry count: %d",
> fw_dl_retry);
> btintel_pcie_dump_debug_registers(hdev);
> --
> 2.54.0
Looks like the second instance of sashiko from netdev catch a problem:
https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261021130424.3042597-1-kiran.k%40intel.com
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH v1] Bluetooth: btintel: check FIPS status before firmware download
2026-10-23 21:49 ` [PATCH v1] " Luiz Augusto von Dentz
@ 2026-10-27 12:56 ` K, Kiran
0 siblings, 0 replies; 4+ messages in thread
From: K, Kiran @ 2026-10-27 12:56 UTC (permalink / raw)
To: Luiz Augusto von Dentz
Cc: linux-bluetooth@vger.kernel.org, Tumkur Narayan, Chethan,
Devegowda, Chandrashekar
Hi Luiz,
>Subject: Re: [PATCH v1] Bluetooth: btintel: check FIPS status before firmware
>download
>
>Hi Kiran,
>
>On Wed, Oct 21, 2026 at 9:02 AM Kiran K <kiran.k@intel.com> wrote:
>>
>> Intel Bluetooth controllers (PCIe and USB) from Scorpius Peak2 onwards
>> report bootloader self-test results (CRC, security, patch) in the
>> INTEL_TLV_FIPS_STS TLV of the Intel Read Version event. Act on them
>> before firmware download:
>>
>> 1. CRC failure -> abort download.
>> 2. Security failure -> abort on USB / HW reset and retry on PCIe.
>> 3. Patch failure -> abort on USB / HW reset and retry on PCIe.
>>
>> Signed-off-by: Kiran K <kiran.k@intel.com>
>> ---
>> drivers/bluetooth/btintel.c | 66 +++++++++++++++++++++++++++++++-
>> drivers/bluetooth/btintel.h | 10 +++++
>> drivers/bluetooth/btintel_pcie.c | 18 ++++++++-
>> 3 files changed, 90 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
>> index 0709fb3212f9..f6deb3d7c5a0 100644
>> --- a/drivers/bluetooth/btintel.c
>> +++ b/drivers/bluetooth/btintel.c
>> @@ -485,10 +485,18 @@ int btintel_read_version(struct hci_dev *hdev,
>> struct intel_version *ver) }
>> EXPORT_SYMBOL_GPL(btintel_read_version);
>>
>> +/* FIPS self-test status is only reported by ScP2 onwards, except
>> +BlazarIW */ static bool btintel_fips_status_supported(u8 hw_variant)
>> +{
>> + return hw_variant >= BTINTEL_HWID_SCP2 && hw_variant !=
>> +BTINTEL_HWID_BZRIW; }
>> +
>> int btintel_version_info_tlv(struct hci_dev *hdev,
>> struct intel_version_tlv *version) {
>> const char *variant;
>> + bool fips_status = false;
>> + u8 hw_variant;
>>
>> /* The hardware platform number has a fixed value of 0x37 and
>> * for now only accept this single value.
>> @@ -505,7 +513,8 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
>> * This check has been put in place to ensure correct forward
>> * compatibility options when newer hardware variants come along.
>> */
>> - switch (INTEL_HW_VARIANT(version->cnvi_bt)) {
>> + hw_variant = INTEL_HW_VARIANT(version->cnvi_bt);
>> + switch (hw_variant) {
>> case 0x17: /* TyP */
>> case 0x18: /* Slr */
>> case 0x19: /* Slr-F */
>> @@ -521,10 +530,13 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
>> break;
>> default:
>> bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
>> - INTEL_HW_VARIANT(version->cnvi_bt));
>> + hw_variant);
>> return -EINVAL;
>> }
>>
>> + fips_status = btintel_fips_status_supported(hw_variant) &&
>> + version->img_type == BTINTEL_IMG_BOOTLOADER;
>> +
>> switch (version->img_type) {
>> case BTINTEL_IMG_BOOTLOADER:
>> variant = "Bootloader"; @@ -584,6 +596,9 @@ int
>> btintel_version_info_tlv(struct hci_dev *hdev,
>>
>> bt_dev_info(hdev, "Unlock policy: 0x%2.2x",
>> version->unlock_policy);
>>
>> + if (fips_status)
>> + bt_dev_info(hdev, "crc status: %u security status: %u patch status:
>%u",
>> + version->crc_sts, version->sec_sts,
>> + version->patch_sts);
>> return 0;
>> }
>> EXPORT_SYMBOL_GPL(btintel_version_info_tlv);
>> @@ -612,6 +627,7 @@ static u8 btintel_version_tlv_min_len(u8 type)
>> case INTEL_TLV_UNLOCK_POLICY:
>> return sizeof(u8);
>> case INTEL_TLV_MIN_FW:
>> + case INTEL_TLV_FIPS_STS:
>> return 3;
>> case INTEL_TLV_OTP_BDADDR:
>> return sizeof(bdaddr_t); @@ -720,6 +736,11 @@ int
>> btintel_parse_version_tlv(struct hci_dev *hdev,
>> case INTEL_TLV_GIT_SHA1:
>> version->git_sha1 = get_unaligned_le32(tlv->val);
>> break;
>> + case INTEL_TLV_FIPS_STS:
>> + version->crc_sts = tlv->val[0];
>> + version->sec_sts = tlv->val[1];
>> + version->patch_sts = tlv->val[2];
>> + break;
>> case INTEL_TLV_FW_ID:
>> snprintf(version->fw_id, sizeof(version->fw_id),
>> "%.*s", tlv->len, tlv->val); @@
>> -3831,6 +3852,43 @@ void btintel_print_fseq_info(struct hci_dev *hdev)
>> } EXPORT_SYMBOL_GPL(btintel_print_fseq_info);
>>
>> +int btintel_check_fips_status(struct hci_dev *hdev,
>> + struct intel_version_tlv *ver) {
>> + u8 hw_variant;
>> +
>> + /* FIPS status is reported only in the bootloader image */
>> + if (ver->img_type != BTINTEL_IMG_BOOTLOADER)
>> + return 0;
>> +
>> + hw_variant = INTEL_HW_VARIANT(ver->cnvi_bt);
>> +
>> + if (!btintel_fips_status_supported(hw_variant))
>> + return 0;
>> +
>> + /* 0 -> Test not executed
>> + * 1 -> Test executed and it passed
>> + * any other value -> Test failed
>> + */
>> + if (ver->crc_sts > 1) {
>> + bt_dev_err(hdev, "crc test failed: %u", ver->crc_sts);
>> + return -ENOEXEC;
>> + }
>> +
>> + if (ver->sec_sts > 1) {
>> + bt_dev_err(hdev, "security test failed: %u", ver->sec_sts);
>> + return -EAGAIN;
>> + }
>> +
>> + if (ver->patch_sts > 1) {
>> + bt_dev_err(hdev, "patch test failed: %u", ver->patch_sts);
>> + return -EAGAIN;
>> + }
>> +
>> + return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(btintel_check_fips_status);
>> +
>> static int btintel_setup_combined(struct hci_dev *hdev) {
>> const u8 param[1] = { 0xFF };
>> @@ -4055,6 +4113,10 @@ static int btintel_setup_combined(struct hci_dev
>*hdev)
>> /* Display version information of TLV type */
>> btintel_version_info_tlv(hdev, &ver_tlv);
>>
>> + err = btintel_check_fips_status(hdev, &ver_tlv);
>> + if (err)
>> + goto exit_error;
>> +
>> /* Apply the device specific HCI quirks for TLV based devices
>> *
>> * All TLV based devices support WBS diff --git
>> a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index
>> 9526acf65959..d5e125ec5168 100644
>> --- a/drivers/bluetooth/btintel.h
>> +++ b/drivers/bluetooth/btintel.h
>> @@ -43,6 +43,7 @@ enum {
>> INTEL_TLV_OTP_BDADDR,
>> INTEL_TLV_UNLOCKED_STATE,
>> INTEL_TLV_GIT_SHA1,
>> + INTEL_TLV_FIPS_STS = 0x3b,
>> INTEL_TLV_UNLOCK_POLICY = 0x3c,
>> INTEL_TLV_PLATFORM_ID = 0x3d,
>> INTEL_TLV_FW_ID = 0x50
>> @@ -112,6 +113,7 @@ struct intel_version_tlv {
>> bdaddr_t otp_bd_addr;
>> u8 unlock_policy;
>> u8 platform_id[6];
>> + u8 crc_sts, sec_sts, patch_sts;
>> };
>>
>> struct intel_version {
>> @@ -331,6 +333,8 @@ int btintel_shutdown_combined(struct hci_dev
>> *hdev); void btintel_hw_error(struct hci_dev *hdev, u8 code); void
>> btintel_print_fseq_info(struct hci_dev *hdev); int
>> btintel_acpi_reset_method(struct hci_dev *hdev);
>> +int btintel_check_fips_status(struct hci_dev *hdev,
>> + struct intel_version_tlv *ver);
>> #else
>>
>> static inline int btintel_check_bdaddr(struct hci_dev *hdev) @@
>> -468,4 +472,10 @@ static inline int btintel_acpi_reset_method(struct
>> hci_dev *hdev) {
>> return -ENODEV;
>> }
>> +
>> +static inline int btintel_check_fips_status(struct hci_dev *hdev,
>> + struct intel_version_tlv
>> +*ver) {
>> + return -EOPNOTSUPP;
>> +}
>> #endif
>> diff --git a/drivers/bluetooth/btintel_pcie.c
>> b/drivers/bluetooth/btintel_pcie.c
>> index df95d16a163c..73822ba2acbb 100644
>> --- a/drivers/bluetooth/btintel_pcie.c
>> +++ b/drivers/bluetooth/btintel_pcie.c
>> @@ -3786,7 +3786,8 @@ static int btintel_pcie_get_debug_info_addr(struct
>hci_dev *hdev)
>> return err;
>> }
>>
>> -static int btintel_pcie_setup_internal(struct hci_dev *hdev)
>> +static int btintel_pcie_setup_internal(struct hci_dev *hdev,
>> + bool *fips_crc_failed)
>> {
>> struct btintel_pcie_data *data = hci_get_drvdata(hdev);
>> const u8 param[1] = { 0xFF };
>> @@ -3794,6 +3795,8 @@ static int btintel_pcie_setup_internal(struct hci_dev
>*hdev)
>> struct sk_buff *skb;
>> int err;
>>
>> + *fips_crc_failed = false;
>> +
>> BT_DBG("%s", hdev->name);
>>
>> skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, HCI_CMD_TIMEOUT);
>> @@ -3855,6 +3858,12 @@ static int btintel_pcie_setup_internal(struct
>hci_dev *hdev)
>> /* Display version information of TLV type */
>> btintel_version_info_tlv(hdev, &ver_tlv);
>>
>> + err = btintel_check_fips_status(hdev, &ver_tlv);
>> + if (err) {
>> + *fips_crc_failed = (err == -ENOEXEC);
>> + goto exit_error;
>> + }
>> +
>> /* Apply the device specific HCI quirks for TLV based devices
>> *
>> * All TLV based devices support WBS @@ -3900,8
>> +3909,13 @@ static int btintel_pcie_setup(struct hci_dev *hdev) {
>> int err, fw_dl_retry = 0;
>> struct btintel_pcie_data *data = hci_get_drvdata(hdev);
>> + bool fips_crc_failed;
>> +
>> + while ((err = btintel_pcie_setup_internal(hdev, &fips_crc_failed)) &&
>> + fw_dl_retry++ < 1) {
>> + if (fips_crc_failed)
>> + break;
>>
>> - while ((err = btintel_pcie_setup_internal(hdev)) && fw_dl_retry++ < 1) {
>> bt_dev_err(hdev, "Firmware download retry count: %d",
>> fw_dl_retry);
>> btintel_pcie_dump_debug_registers(hdev);
>> --
>> 2.54.0
>
>Looks like the second instance of sashiko from netdev catch a problem:
>
>https://netdev-
>ai.bots.linux.dev/sashiko/#/patchset/20261021130424.3042597-1-
>kiran.k%40intel.com
Ack. Looks like the commit message needs an update to fix this. I will publish v2 version.
>
>--
>Luiz Augusto von Dentz
Thanks,
Kiran
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-27 12:56 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-21 13:04 [PATCH v1] Bluetooth: btintel: check FIPS status before firmware download Kiran K
2026-10-21 18:07 ` [v1] " bluez.test.bot
2026-10-23 21:49 ` [PATCH v1] " Luiz Augusto von Dentz
2026-10-27 12:56 ` K, Kiran
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox