Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Bluetooth: btintel: Check firmware version before download

This checks the firmware build number, week and year against the
repective loaded version. If details are a match, skip the download
process.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Tested-by: Tedd Ho-Jeong An <tedd.an@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

authored by

Luiz Augusto von Dentz and committed by
Marcel Holtmann
ac056546 0f90d320

+109 -27
+85 -21
drivers/bluetooth/btintel.c
··· 24 24 #define ECDSA_OFFSET 644 25 25 #define ECDSA_HEADER_LEN 320 26 26 27 + #define CMD_WRITE_BOOT_PARAMS 0xfc0e 28 + struct cmd_write_boot_params { 29 + u32 boot_addr; 30 + u8 fw_build_num; 31 + u8 fw_build_ww; 32 + u8 fw_build_yy; 33 + } __packed; 34 + 27 35 int btintel_check_bdaddr(struct hci_dev *hdev) 28 36 { 29 37 struct hci_rp_read_bd_addr *bda; ··· 849 841 850 842 static int btintel_download_firmware_payload(struct hci_dev *hdev, 851 843 const struct firmware *fw, 852 - u32 *boot_param, size_t offset) 844 + size_t offset) 853 845 { 854 846 int err; 855 847 const u8 *fw_ptr; ··· 861 853 862 854 while (fw_ptr - fw->data < fw->size) { 863 855 struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len); 864 - 865 - /* Each SKU has a different reset parameter to use in the 866 - * HCI_Intel_Reset command and it is embedded in the firmware 867 - * data. So, instead of using static value per SKU, check 868 - * the firmware data and save it for later use. 869 - */ 870 - if (le16_to_cpu(cmd->opcode) == 0xfc0e) { 871 - /* The boot parameter is the first 32-bit value 872 - * and rest of 3 octets are reserved. 873 - */ 874 - *boot_param = get_unaligned_le32(fw_ptr + frag_len + 875 - sizeof(*cmd)); 876 - 877 - bt_dev_dbg(hdev, "boot_param=0x%x", *boot_param); 878 - } 879 856 880 857 frag_len += sizeof(*cmd) + cmd->plen; 881 858 ··· 890 897 return err; 891 898 } 892 899 900 + static bool btintel_firmware_version(struct hci_dev *hdev, 901 + u8 num, u8 ww, u8 yy, 902 + const struct firmware *fw, 903 + u32 *boot_addr) 904 + { 905 + const u8 *fw_ptr; 906 + 907 + fw_ptr = fw->data; 908 + 909 + while (fw_ptr - fw->data < fw->size) { 910 + struct hci_command_hdr *cmd = (void *)(fw_ptr); 911 + 912 + /* Each SKU has a different reset parameter to use in the 913 + * HCI_Intel_Reset command and it is embedded in the firmware 914 + * data. So, instead of using static value per SKU, check 915 + * the firmware data and save it for later use. 916 + */ 917 + if (le16_to_cpu(cmd->opcode) == CMD_WRITE_BOOT_PARAMS) { 918 + struct cmd_write_boot_params *params; 919 + 920 + params = (void *)(fw_ptr + sizeof(*cmd)); 921 + 922 + bt_dev_info(hdev, "Boot Address: 0x%x", 923 + le32_to_cpu(params->boot_addr)); 924 + 925 + bt_dev_info(hdev, "Firmware Version: %u-%u.%u", 926 + params->fw_build_num, params->fw_build_ww, 927 + params->fw_build_yy); 928 + 929 + return (num == params->fw_build_num && 930 + ww == params->fw_build_ww && 931 + yy == params->fw_build_yy); 932 + } 933 + 934 + fw_ptr += sizeof(*cmd) + cmd->plen; 935 + } 936 + 937 + return false; 938 + } 939 + 893 940 int btintel_download_firmware(struct hci_dev *hdev, 941 + struct intel_version *ver, 894 942 const struct firmware *fw, 895 943 u32 *boot_param) 896 944 { 897 945 int err; 898 946 947 + /* SfP and WsP don't seem to update the firmware version on file 948 + * so version checking is currently not possible. 949 + */ 950 + switch (ver->hw_variant) { 951 + case 0x0b: /* SfP */ 952 + case 0x0c: /* WsP */ 953 + /* Skip version checking */ 954 + break; 955 + default: 956 + /* Skip download if firmware has the same version */ 957 + if (btintel_firmware_version(hdev, ver->fw_build_num, 958 + ver->fw_build_ww, ver->fw_build_yy, 959 + fw, boot_param)) { 960 + bt_dev_info(hdev, "Firmware already loaded"); 961 + /* Return -EALREADY to indicate that the firmware has 962 + * already been loaded. 963 + */ 964 + return -EALREADY; 965 + } 966 + } 967 + 899 968 err = btintel_sfi_rsa_header_secure_send(hdev, fw); 900 969 if (err) 901 970 return err; 902 971 903 - return btintel_download_firmware_payload(hdev, fw, boot_param, 904 - RSA_HEADER_LEN); 972 + return btintel_download_firmware_payload(hdev, fw, RSA_HEADER_LEN); 905 973 } 906 974 EXPORT_SYMBOL_GPL(btintel_download_firmware); 907 975 908 976 int btintel_download_firmware_newgen(struct hci_dev *hdev, 977 + struct intel_version_tlv *ver, 909 978 const struct firmware *fw, u32 *boot_param, 910 979 u8 hw_variant, u8 sbe_type) 911 980 { 912 981 int err; 913 982 u32 css_header_ver; 983 + 984 + /* Skip download if firmware has the same version */ 985 + if (btintel_firmware_version(hdev, ver->min_fw_build_nn, 986 + ver->min_fw_build_cw, ver->min_fw_build_yy, 987 + fw, boot_param)) { 988 + bt_dev_info(hdev, "Firmware already loaded"); 989 + /* Return -EALREADY to indicate that firmware has already been 990 + * loaded. 991 + */ 992 + return -EALREADY; 993 + } 914 994 915 995 /* iBT hardware variants 0x0b, 0x0c, 0x11, 0x12, 0x13, 0x14 support 916 996 * only RSA secure boot engine. Hence, the corresponding sfi file will ··· 1014 948 if (err) 1015 949 return err; 1016 950 1017 - err = btintel_download_firmware_payload(hdev, fw, boot_param, RSA_HEADER_LEN); 951 + err = btintel_download_firmware_payload(hdev, fw, RSA_HEADER_LEN); 1018 952 if (err) 1019 953 return err; 1020 954 } else if (hw_variant >= 0x17) { ··· 1035 969 return err; 1036 970 1037 971 err = btintel_download_firmware_payload(hdev, fw, 1038 - boot_param, 1039 972 RSA_HEADER_LEN + ECDSA_HEADER_LEN); 1040 973 if (err) 1041 974 return err; ··· 1044 979 return err; 1045 980 1046 981 err = btintel_download_firmware_payload(hdev, fw, 1047 - boot_param, 1048 982 RSA_HEADER_LEN + ECDSA_HEADER_LEN); 1049 983 if (err) 1050 984 return err;
+3 -2
drivers/bluetooth/btintel.h
··· 163 163 int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param); 164 164 int btintel_read_boot_params(struct hci_dev *hdev, 165 165 struct intel_boot_params *params); 166 - int btintel_download_firmware(struct hci_dev *dev, const struct firmware *fw, 167 - u32 *boot_param); 166 + int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver, 167 + const struct firmware *fw, u32 *boot_param); 168 168 int btintel_download_firmware_newgen(struct hci_dev *hdev, 169 + struct intel_version_tlv *ver, 169 170 const struct firmware *fw, 170 171 u32 *boot_param, u8 hw_variant, 171 172 u8 sbe_type);
+16 -2
drivers/bluetooth/btusb.c
··· 2557 2557 set_bit(BTUSB_DOWNLOADING, &data->flags); 2558 2558 2559 2559 /* Start firmware downloading and get boot parameter */ 2560 - err = btintel_download_firmware_newgen(hdev, fw, boot_param, 2560 + err = btintel_download_firmware_newgen(hdev, ver, fw, boot_param, 2561 2561 INTEL_HW_VARIANT(ver->cnvi_bt), 2562 2562 ver->sbe_type); 2563 2563 if (err < 0) { 2564 + if (err == -EALREADY) { 2565 + /* Firmware has already been loaded */ 2566 + set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); 2567 + err = 0; 2568 + goto done; 2569 + } 2570 + 2564 2571 /* When FW download fails, send Intel Reset to retry 2565 2572 * FW download. 2566 2573 */ ··· 2759 2752 set_bit(BTUSB_DOWNLOADING, &data->flags); 2760 2753 2761 2754 /* Start firmware downloading and get boot parameter */ 2762 - err = btintel_download_firmware(hdev, fw, boot_param); 2755 + err = btintel_download_firmware(hdev, ver, fw, boot_param); 2763 2756 if (err < 0) { 2757 + if (err == -EALREADY) { 2758 + /* Firmware has already been loaded */ 2759 + set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); 2760 + err = 0; 2761 + goto done; 2762 + } 2763 + 2764 2764 /* When FW download fails, send Intel Reset to retry 2765 2765 * FW download. 2766 2766 */
+5 -2
drivers/bluetooth/hci_intel.c
··· 735 735 set_bit(STATE_DOWNLOADING, &intel->flags); 736 736 737 737 /* Start firmware downloading and get boot parameter */ 738 - err = btintel_download_firmware(hdev, fw, &boot_param); 738 + err = btintel_download_firmware(hdev, &ver, fw, &boot_param); 739 739 if (err < 0) 740 740 goto done; 741 741 ··· 784 784 done: 785 785 release_firmware(fw); 786 786 787 - if (err < 0) 787 + /* Check if there was an error and if is not -EALREADY which means the 788 + * firmware has already been loaded. 789 + */ 790 + if (err < 0 && err != -EALREADY) 788 791 return err; 789 792 790 793 /* We need to restore the default speed before Intel reset */