Bluetooth: btintel: Add infrastructure to read controller information
PATCH 1/2 Bluetooth: btintel: Add infrastructure to read controller information
New generation Intel controllers returns version information in TLV format. This patch adds,
1) Enums, structures for TLV
2) function to read controller information, parse TLV data and populate intel_version_tlv structure
3) function to print version information
--- drivers/bluetooth/btintel.c | 138 ++++++++++++++++++++++++++++++++++++++++++++ drivers/bluetooth/btintel.h | 79 +++++++++++++++++++++++++ 2 files changed, 217 insertions(+)
drivers/bluetooth/btintel.c +138 -0
@@ -361,6 +361,144 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver) }EXPORT_SYMBOL_GPL (btintel_read_version); +void btintel_version_info_tlv (struct hci_dev *hdev,struct intel_version_tlv *version) +{ +const char *variant; + +switch (version->img_type) { +case 0x01 : + variant ="Bootloader" ; +bt_dev_info (hdev,"Device revision is %u" , version->dev_rev_id); +bt_dev_info (hdev,"Secure boot is %s" , + version->secure_boot ?"enabled" :"disabled" ); +bt_dev_info (hdev,"OTP lock is %s" , + version->otp_lock ?"enabled" :"disabled" ); +bt_dev_info (hdev,"API lock is %s" , + version->api_lock ?"enabled" :"disabled" ); +bt_dev_info (hdev,"Debug lock is %s" , + version->debug_lock ?"enabled" :"disabled" ); +bt_dev_info (hdev,"Minimum firmware build %u week %u %u" , + version->min_fw_build_nn, version->min_fw_build_cw, +2000 + version->min_fw_build_yy); +break ; +case 0x03 : + variant ="Firmware" ; +break ; +default : +bt_dev_err (hdev,"Unsupported image type(%02x)" , version->img_type); + goto done; + } + +bt_dev_info (hdev,"%s timestamp %u.%u buildtype %u build %u" , variant, +2000 + (version->timestamp >>8 ), version->timestamp &0xff , + version->build_type, version->build_num); + +done: +return ; +} +EXPORT_SYMBOL_GPL (btintel_version_info_tlv); + +int btintel_read_version_tlv (struct hci_dev *hdev,struct intel_version_tlv *version) +{ +struct sk_buff *skb; +const u8 param[1 ] = {0xFF }; + +if (!version) +return -EINVAL ; + + skb =__hci_cmd_sync (hdev,0xfc05 ,1 , param,HCI_CMD_TIMEOUT ); +if (IS_ERR (skb)) { +bt_dev_err (hdev,"Reading Intel version information failed (%ld)" , +PTR_ERR (skb)); +return PTR_ERR (skb); + } + +if (skb->data[0 ]) { +bt_dev_err (hdev,"Intel Read Version command failed (%02x)" , + skb->data[0 ]); +kfree_skb (skb); +return -EIO ; + } + +/* Consume Command Complete Status field */ +skb_pull (skb,1 ); + +/* Event parameters contatin multiple TLVs. Read each of them +* and only keep the required data. Also, it use existing legacy +* version field like hw_platform, hw_variant, and fw_variant +* to keep the existing setup flow +*/ +while (skb->len) { +struct intel_tlv *tlv; + + tlv = (struct intel_tlv *)skb->data; +switch (tlv->type) { +case INTEL_TLV_CNVI_TOP : + version->cnvi_top =get_unaligned_le32 (tlv->val); +break ; +case INTEL_TLV_CNVR_TOP : + version->cnvr_top =get_unaligned_le32 (tlv->val); +break ; +case INTEL_TLV_CNVI_BT : + version->cnvi_bt =get_unaligned_le32 (tlv->val); +break ; +case INTEL_TLV_CNVR_BT : + version->cnvr_bt =get_unaligned_le32 (tlv->val); +break ; +case INTEL_TLV_DEV_REV_ID : + version->dev_rev_id =get_unaligned_le16 (tlv->val); +break ; +case INTEL_TLV_IMAGE_TYPE : + version->img_type = tlv->val[0 ]; +break ; +case INTEL_TLV_TIME_STAMP : + version->timestamp =get_unaligned_le16 (tlv->val); +break ; +case INTEL_TLV_BUILD_TYPE : + version->build_type = tlv->val[0 ]; +break ; +case INTEL_TLV_BUILD_NUM : + version->build_num =get_unaligned_le32 (tlv->val); +break ; +case INTEL_TLV_SECURE_BOOT : + version->secure_boot = tlv->val[0 ]; +break ; +case INTEL_TLV_OTP_LOCK : + version->otp_lock = tlv->val[0 ]; +break ; +case INTEL_TLV_API_LOCK : + version->api_lock = tlv->val[0 ]; +break ; +case INTEL_TLV_DEBUG_LOCK : + version->debug_lock = tlv->val[0 ]; +break ; +case INTEL_TLV_MIN_FW : + version->min_fw_build_nn = tlv->val[0 ]; + version->min_fw_build_cw = tlv->val[1 ]; + version->min_fw_build_yy = tlv->val[2 ]; +break ; +case INTEL_TLV_LIMITED_CCE : + version->limited_cce = tlv->val[0 ]; +break ; +case INTEL_TLV_SBE_TYPE : + version->sbe_type = tlv->val[0 ]; +break ; +case INTEL_TLV_OTP_BDADDR : +memcpy (&version->otp_bd_addr, tlv->val, tlv->len); +break ; +default : +/* Ignore rest of information */ +break ; + } +/* consume the current tlv and move to next*/ +skb_pull (skb, tlv->len +sizeof (*tlv)); + } + +kfree_skb (skb); +return 0 ; +} +EXPORT_SYMBOL_GPL (btintel_read_version_tlv); +/* ------- REGMAP IBT SUPPORT ------- */ #define IBT_REG_MODE_8BIT 0x00
drivers/bluetooth/btintel.h +79 -0
109 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH 2/2 Bluetooth: btintel: Functions to send firmware header / payload
New generation controllers supports ECDSA secure boot engine. This patch adds,
1) function to send ECDSA header
2) function to download complete firmware for new generation Intel controllers
--- drivers/bluetooth/btintel.c | 119 +++++++++++++++++++++++++++++++++++++++++++- drivers/bluetooth/btintel.h | 12 +++++ 2 files changed, 129 insertions(+), 2 deletions(-)
drivers/bluetooth/btintel.c +117 -2
@@ -18,8 +18,11 @@#define VERSION "0.1" -#define BDADDR_INTEL (&(bdaddr_t) {{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}}) -#define RSA_HEADER_LEN 644 +#define BDADDR_INTEL (&(bdaddr_t){{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}}) +#define RSA_HEADER_LEN 644 +#define CSS_HEADER_OFFSET 8 +#define ECDSA_OFFSET 644 +#define ECDSA_HEADER_LEN 320int btintel_check_bdaddr (struct hci_dev *hdev) {
@@ -801,6 +804,41 @@ static int btintel_sfi_rsa_header_secure_send(struct hci_dev *hdev,return err; } +static int btintel_sfi_ecdsa_header_secure_send (struct hci_dev *hdev, +const struct firmware *fw) +{ +int err; + +/* Start the firmware download transaction with the Init fragment +* represented by the 128 bytes of CSS header. +*/ + err =btintel_secure_send (hdev,0x00 ,128 , fw->data +644 ); +if (err <0 ) { +bt_dev_err (hdev,"Failed to send firmware header (%d)" , err); +return err; + } + +/* Send the 96 bytes of public key information from the firmware +* as the PKey fragment. +*/ + err =btintel_secure_send (hdev,0x03 ,96 , fw->data +644 +128 ); +if (err <0 ) { +bt_dev_err (hdev,"Failed to send firmware pkey (%d)" , err); +return err; + } + +/* Send the 96 bytes of signature information from the firmware +* as the Sign fragment +*/ + err =btintel_secure_send (hdev,0x02 ,96 , fw->data +644 +224 ); +if (err <0 ) { +bt_dev_err (hdev,"Failed to send firmware signature (%d)" , + err); +return err; + } +return 0 ; +} +static int btintel_download_firmware_payload (struct hci_dev *hdev,const struct firmware *fw,u32 *boot_param,size_t offset)
@@ -873,6 +911,83 @@ int btintel_download_firmware(struct hci_dev *hdev, }EXPORT_SYMBOL_GPL (btintel_download_firmware); +int btintel_download_firmware_newgen (struct hci_dev *hdev, +const struct firmware *fw,u32 *boot_param, +u8 hw_variant,u8 sbe_type) +{ +int err; +u32 css_header_ver; + +/* iBT hardware variants 0x0b, 0x0c, 0x11, 0x12, 0x13, 0x14 support +* only RSA secure boot engine. Hence, the corresponding sfi file will +* have RSA header of 644 bytes followed by Command Buffer. +* +* iBT hardware variants 0x17, 0x18 onwards support both RSA and ECDSA +* secure boot engine. As a result, the corresponding sfi file will +* have RSA header of 644, ECDSA header of 320 bytes followed by +* Command Buffer. +* +* CSS Header byte positions 0x08 to 0x0B represent the CSS Header +* version: RSA(0x00010000) , ECDSA (0x00020000) +*/ + css_header_ver =get_unaligned_le32 (fw->data +CSS_HEADER_OFFSET ); +if (css_header_ver !=0x00010000 ) { +bt_dev_err (hdev,"Invalid CSS Header version" ); +return -EINVAL ; + } + +if (hw_variant <=0x14 ) { +if (sbe_type !=0x00 ) { +bt_dev_err (hdev,"Invalid SBE type for hardware variant (%d)" , + hw_variant); +return -EINVAL ; + } + + err =btintel_sfi_rsa_header_secure_send (hdev, fw); +if (err) +return err; + + err =btintel_download_firmware_payload (hdev, fw, boot_param,RSA_HEADER_LEN ); +if (err) +return err; + }else if (hw_variant >=0x17 ) { +/* Check if CSS header for ECDSA follows the RSA header */ +if (fw->data[ECDSA_OFFSET ] !=0x06 ) +return -EINVAL ; + +/* Check if the CSS Header version is ECDSA(0x00020000) */ + css_header_ver =get_unaligned_le32 (fw->data +ECDSA_OFFSET +CSS_HEADER_OFFSET ); +if (css_header_ver !=0x00020000 ) { +bt_dev_err (hdev,"Invalid CSS Header version" ); +return -EINVAL ; + } + +if (sbe_type ==0x00 ) { + err =btintel_sfi_rsa_header_secure_send (hdev, fw); +if (err) +return err; + + err =btintel_download_firmware_payload (hdev, fw, + boot_param, +RSA_HEADER_LEN +ECDSA_HEADER_LEN ); +if (err) +return err; + }else if (sbe_type ==0x01 ) { + err =btintel_sfi_ecdsa_header_secure_send (hdev, fw); +if (err) +return err; + + err =btintel_download_firmware_payload (hdev, fw, + boot_param, +RSA_HEADER_LEN +ECDSA_HEADER_LEN ); +if (err) +return err; + } + } +return 0 ; +} +EXPORT_SYMBOL_GPL (btintel_download_firmware_newgen); +void btintel_reset_to_bootloader (struct hci_dev *hdev) {struct intel_reset params;
drivers/bluetooth/btintel.h +12 -0
@@ -159,6 +159,10 @@ int btintel_read_boot_params(struct hci_dev *hdev, struct intel_boot_params *params);int btintel_download_firmware (struct hci_dev *dev,const struct firmware *fw,u32 *boot_param); +int btintel_download_firmware_newgen (struct hci_dev *hdev, +const struct firmware *fw, +u32 *boot_param,u8 hw_variant, +u8 sbe_type);void btintel_reset_to_bootloader (struct hci_dev *hdev);int btintel_read_debug_features (struct hci_dev *hdev,struct intel_debug_features *features);
@@ -270,6 +274,14 @@ static inline int btintel_download_firmware(struct hci_dev *dev,return -EOPNOTSUPP ; } +static inline int btintel_download_firmware_newgen (struct hci_dev *hdev, +const struct firmware *fw, +u32 *boot_param, +u8 hw_variant,u8 sbe_type) +{ +return -EOPNOTSUPP ; +} +static inline void btintel_reset_to_bootloader (struct hci_dev *hdev) { }
Signature · 1 line
2.7.4
Marcel Holtmann
maintainerRe: [PATCH v1 2/2] Bluetooth: btintel: Functions to send firmware header / payload
Hi Kiran,
Quoted 13 lines
New generation controllers supports ECDSA secure boot engine. This patch adds,
1) function to send ECDSA header
2) function to download complete firmware for new generation Intel controllers
Signed-off-by Kiran K <[email protected]>Signed-off-by Amit K Bag <[email protected]>Signed-off-by Raghuram Hegde <[email protected]>Reviewed-by Chethan T N <[email protected]>Reviewed-by Srivatsa Ravishankar <[email protected]>
Quoted 4 lines
---
drivers/bluetooth/btintel.c| 119 +++++++++++++++++++++++++++++++++++++++++++-drivers/bluetooth/btintel.h| 12 +++++2 files changed, 129 insertions(+), 2 deletions(-)
patch has been applied to bluetooth-next tree.
Regards
Marcel
Marcel Holtmann
maintainerHi Kiran,
Quoted 15 lines
New generation Intel controllers returns version information in TLV format. This patch adds,
1) Enums, structures for TLV
2) function to read controller information, parse TLV data and populate
intel_version_tlvstructure3) function to print version information
Signed-off-by Kiran K <[email protected]>Signed-off-by Amit K Bag <[email protected]>Signed-off-by Raghuram Hegde <[email protected]>Reviewed-by Chethan T N <[email protected]>Reviewed-by Srivatsa Ravishankar <[email protected]>
Quoted 4 lines
---
drivers/bluetooth/btintel.c| 138 ++++++++++++++++++++++++++++++++++++++++++++drivers/bluetooth/btintel.h| 79 +++++++++++++++++++++++++2 files changed, 217 insertions(+)
patch has been applied to bluetooth-next tree.
Regards
Marcel