Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F146485081
D46735.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
25 KB
Referenced Files
None
Subscribers
None
D46735.diff
View Options
diff --git a/usr.sbin/bluetooth/iwmbtfw/Makefile b/usr.sbin/bluetooth/iwmbtfw/Makefile
--- a/usr.sbin/bluetooth/iwmbtfw/Makefile
+++ b/usr.sbin/bluetooth/iwmbtfw/Makefile
@@ -4,6 +4,8 @@
PROG= iwmbtfw
MAN= iwmbtfw.8
LIBADD+= usb
+# Not having NDEBUG defined will enable assertions
+CFLAGS+= -DNDEBUG
SRCS= main.c iwmbt_fw.c iwmbt_hw.c
.include <bsd.prog.mk>
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.h b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.h
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.h
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.h
@@ -3,6 +3,7 @@
*
* Copyright (c) 2013 Adrian Chadd <adrian@freebsd.org>
* Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
+ * Copyright (c) 2023 Future Crew LLC.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,6 +30,15 @@
#ifndef __IWMBT_FW_H__
#define __IWMBT_FW_H__
+#include <sys/types.h>
+#define L2CAP_SOCKET_CHECKED
+#include <bluetooth.h>
+
+#define RSA_HEADER_LEN 644
+#define ECDSA_HEADER_LEN 320
+#define ECDSA_OFFSET RSA_HEADER_LEN
+#define CSS_HEADER_OFFSET 8
+
struct iwmbt_version {
uint8_t status;
uint8_t hw_platform;
@@ -62,6 +72,65 @@
uint8_t unlocked_state;
} __attribute__ ((packed));
+enum {
+ IWMBT_TLV_CNVI_TOP = 0x10,
+ IWMBT_TLV_CNVR_TOP,
+ IWMBT_TLV_CNVI_BT,
+ IWMBT_TLV_CNVR_BT,
+ IWMBT_TLV_CNVI_OTP,
+ IWMBT_TLV_CNVR_OTP,
+ IWMBT_TLV_DEV_REV_ID,
+ IWMBT_TLV_USB_VENDOR_ID,
+ IWMBT_TLV_USB_PRODUCT_ID,
+ IWMBT_TLV_PCIE_VENDOR_ID,
+ IWMBT_TLV_PCIE_DEVICE_ID,
+ IWMBT_TLV_PCIE_SUBSYSTEM_ID,
+ IWMBT_TLV_IMAGE_TYPE,
+ IWMBT_TLV_TIME_STAMP,
+ IWMBT_TLV_BUILD_TYPE,
+ IWMBT_TLV_BUILD_NUM,
+ IWMBT_TLV_FW_BUILD_PRODUCT,
+ IWMBT_TLV_FW_BUILD_HW,
+ IWMBT_TLV_FW_STEP,
+ IWMBT_TLV_BT_SPEC,
+ IWMBT_TLV_MFG_NAME,
+ IWMBT_TLV_HCI_REV,
+ IWMBT_TLV_LMP_SUBVER,
+ IWMBT_TLV_OTP_PATCH_VER,
+ IWMBT_TLV_SECURE_BOOT,
+ IWMBT_TLV_KEY_FROM_HDR,
+ IWMBT_TLV_OTP_LOCK,
+ IWMBT_TLV_API_LOCK,
+ IWMBT_TLV_DEBUG_LOCK,
+ IWMBT_TLV_MIN_FW,
+ IWMBT_TLV_LIMITED_CCE,
+ IWMBT_TLV_SBE_TYPE,
+ IWMBT_TLV_OTP_BDADDR,
+ IWMBT_TLV_UNLOCKED_STATE
+};
+
+struct iwmbt_version_tlv {
+ uint32_t cnvi_top;
+ uint32_t cnvr_top;
+ uint32_t cnvi_bt;
+ uint32_t cnvr_bt;
+ uint16_t dev_rev_id;
+ uint8_t img_type;
+ uint16_t timestamp;
+ uint8_t build_type;
+ uint32_t build_num;
+ uint8_t secure_boot;
+ uint8_t otp_lock;
+ uint8_t api_lock;
+ uint8_t debug_lock;
+ uint8_t min_fw_build_nn;
+ uint8_t min_fw_build_cw;
+ uint8_t min_fw_build_yy;
+ uint8_t limited_cce;
+ uint8_t sbe_type;
+ bdaddr_t otp_bd_addr;
+};
+
struct iwmbt_firmware {
char *fwname;
int len;
@@ -73,5 +142,7 @@
extern char *iwmbt_get_fwname(struct iwmbt_version *ver,
struct iwmbt_boot_params *params, const char *prefix,
const char *suffix);
+extern char *iwmbt_get_fwname_tlv(struct iwmbt_version_tlv *ver,
+ const char *prefix, const char *suffix);
#endif
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 2013 Adrian Chadd <adrian@freebsd.org>
* Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
+ * Copyright (c) 2023 Future Crew LLC.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -170,3 +171,23 @@
return (fwname);
}
+
+char *
+iwmbt_get_fwname_tlv(struct iwmbt_version_tlv *ver, const char *prefix,
+ const char *suffix)
+{
+ char *fwname;
+
+#define IWMBT_PACK_CNVX_TOP(cnvx_top) ((uint16_t)( \
+ ((cnvx_top) & 0x0f000000) >> 16 | \
+ ((cnvx_top) & 0x0000000f) << 12 | \
+ ((cnvx_top) & 0x00000ff0) >> 4))
+
+ asprintf(&fwname, "%s/ibt-%04x-%04x.%s",
+ prefix,
+ IWMBT_PACK_CNVX_TOP(ver->cnvi_top),
+ IWMBT_PACK_CNVX_TOP(ver->cnvr_top),
+ suffix);
+
+ return (fwname);
+}
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h
@@ -2,6 +2,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
+ * Copyright (c) 2023 Future Crew LLC.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -59,6 +60,9 @@
#define IWMBT_HCI_EVT_COMPL_SIZE(payload) \
(offsetof(struct iwmbt_hci_event_cmd_compl, data) + sizeof(payload))
+#define IWMBT_HCI_EVENT_COMPL_HEAD_SIZE \
+ (offsetof(struct iwmbt_hci_event_cmd_compl, data) - \
+ offsetof(struct iwmbt_hci_event_cmd_compl, numpkt))
#define IWMBT_CONTROL_ENDPOINT_ADDR 0x00
#define IWMBT_INTERRUPT_ENDPOINT_ADDR 0x81
@@ -73,13 +77,19 @@
extern int iwmbt_patch_fwfile(struct libusb_device_handle *hdl,
const struct iwmbt_firmware *fw);
+extern int iwmbt_load_rsa_header(struct libusb_device_handle *hdl,
+ const struct iwmbt_firmware *fw);
+extern int iwmbt_load_ecdsa_header(struct libusb_device_handle *hdl,
+ const struct iwmbt_firmware *fw);
extern int iwmbt_load_fwfile(struct libusb_device_handle *hdl,
- const struct iwmbt_firmware *fw, uint32_t *boot_param);
+ const struct iwmbt_firmware *fw, uint32_t *boot_param, int offset);
extern int iwmbt_enter_manufacturer(struct libusb_device_handle *hdl);
extern int iwmbt_exit_manufacturer(struct libusb_device_handle *hdl,
int mode);
extern int iwmbt_get_version(struct libusb_device_handle *hdl,
struct iwmbt_version *version);
+extern int iwmbt_get_version_tlv(struct libusb_device_handle *hdl,
+ struct iwmbt_version_tlv *version);
extern int iwmbt_get_boot_params(struct libusb_device_handle *hdl,
struct iwmbt_boot_params *params);
extern int iwmbt_intel_reset(struct libusb_device_handle *hdl,
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c
@@ -2,6 +2,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
+ * Copyright (c) 2023 Future Crew LLC.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,6 +30,7 @@
#include <sys/endian.h>
#include <sys/stat.h>
+#include <assert.h>
#include <err.h>
#include <errno.h>
#include <stddef.h>
@@ -267,16 +269,6 @@
return (activate_patch);
}
-int
-iwmbt_load_fwfile(struct libusb_device_handle *hdl,
- const struct iwmbt_firmware *fw, uint32_t *boot_param)
-{
- int ready = 0, sent = 0;
- int ret, transferred;
- struct iwmbt_hci_cmd *cmd;
- struct iwmbt_hci_event *event;
- uint8_t buf[IWMBT_HCI_MAX_EVENT_SIZE];
-
#define IWMBT_SEND_FRAGMENT(fragment_type, size, msg) do { \
iwmbt_debug("transferring %d bytes, offset %d", size, sent); \
\
@@ -293,12 +285,11 @@
sent += size; \
} while (0)
- if (fw->len < 644) {
- iwmbt_err("Invalid size of firmware file (%d)", fw->len);
- return (-1);
- }
-
- iwmbt_debug("file=%s, size=%d", fw->fwname, fw->len);
+int
+iwmbt_load_rsa_header(struct libusb_device_handle *hdl,
+ const struct iwmbt_firmware *fw)
+{
+ int ret, sent = 0;
IWMBT_SEND_FRAGMENT(0x00, 0x80, "CCS segment");
IWMBT_SEND_FRAGMENT(0x03, 0x80, "public key / part 1");
@@ -310,6 +301,32 @@
IWMBT_SEND_FRAGMENT(0x02, 0x80, "signature / part 1");
IWMBT_SEND_FRAGMENT(0x02, 0x80, "signature / part 2");
+ return (0);
+}
+
+int
+iwmbt_load_ecdsa_header(struct libusb_device_handle *hdl,
+ const struct iwmbt_firmware *fw)
+{
+ int ret, sent = ECDSA_OFFSET;
+
+ IWMBT_SEND_FRAGMENT(0x00, 0x80, "CCS segment");
+ IWMBT_SEND_FRAGMENT(0x03, 0x60, "public key");
+ IWMBT_SEND_FRAGMENT(0x02, 0x60, "signature");
+
+ return (0);
+}
+
+int
+iwmbt_load_fwfile(struct libusb_device_handle *hdl,
+ const struct iwmbt_firmware *fw, uint32_t *boot_param, int offset)
+{
+ int ready = 0, sent = offset;
+ int ret, transferred;
+ struct iwmbt_hci_cmd *cmd;
+ struct iwmbt_hci_event *event;
+ uint8_t buf[IWMBT_HCI_MAX_EVENT_SIZE];
+
/*
* Send firmware chunks. Chunk len must be 4 byte aligned.
* multiple commands can be combined
@@ -460,6 +477,140 @@
return (0);
}
+int
+iwmbt_get_version_tlv(struct libusb_device_handle *hdl,
+ struct iwmbt_version_tlv *version)
+{
+ int ret, transferred;
+ struct iwmbt_hci_event_cmd_compl *event;
+ static struct iwmbt_hci_cmd cmd = {
+ .opcode = htole16(0xfc05),
+ .length = 1,
+ .data = { 0xff },
+ };
+ uint8_t status, datalen, type, len;
+ uint8_t *data;
+ uint8_t buf[255];
+
+ memset(buf, 0, sizeof(buf));
+
+ ret = iwmbt_hci_command(hdl,
+ &cmd,
+ buf,
+ sizeof(buf),
+ &transferred,
+ IWMBT_HCI_CMD_TIMEOUT);
+
+ if (ret < 0 || transferred < (int)IWMBT_HCI_EVT_COMPL_SIZE(uint16_t)) {
+ iwmbt_debug("Can't get version: code=%d, size=%d",
+ ret,
+ transferred);
+ return (-1);
+ }
+
+ event = (struct iwmbt_hci_event_cmd_compl *)buf;
+ memcpy(version, event->data, sizeof(struct iwmbt_version));
+
+ datalen = event->header.length - IWMBT_HCI_EVENT_COMPL_HEAD_SIZE;
+ data = event->data;
+ status = *data++;
+ if (status != 0)
+ return (-1);
+ datalen--;
+
+ while (datalen >= 2) {
+ type = *data++;
+ len = *data++;
+ datalen -= 2;
+
+ if (datalen < len)
+ return (-1);
+
+ switch (type) {
+ case IWMBT_TLV_CNVI_TOP:
+ assert(len == 4);
+ version->cnvi_top = le32dec(data);
+ break;
+ case IWMBT_TLV_CNVR_TOP:
+ assert(len == 4);
+ version->cnvr_top = le32dec(data);
+ break;
+ case IWMBT_TLV_CNVI_BT:
+ assert(len == 4);
+ version->cnvi_bt = le32dec(data);
+ break;
+ case IWMBT_TLV_CNVR_BT:
+ assert(len == 4);
+ version->cnvr_bt = le32dec(data);
+ break;
+ case IWMBT_TLV_DEV_REV_ID:
+ assert(len == 2);
+ version->dev_rev_id = le16dec(data);
+ break;
+ case IWMBT_TLV_IMAGE_TYPE:
+ assert(len == 1);
+ version->img_type = *data;
+ break;
+ case IWMBT_TLV_TIME_STAMP:
+ assert(len == 2);
+ version->min_fw_build_cw = data[0];
+ version->min_fw_build_yy = data[1];
+ version->timestamp = le16dec(data);
+ break;
+ case IWMBT_TLV_BUILD_TYPE:
+ assert(len == 1);
+ version->build_type = *data;
+ break;
+ case IWMBT_TLV_BUILD_NUM:
+ assert(len == 4);
+ version->min_fw_build_nn = *data;
+ version->build_num = le32dec(data);
+ break;
+ case IWMBT_TLV_SECURE_BOOT:
+ assert(len == 1);
+ version->secure_boot = *data;
+ break;
+ case IWMBT_TLV_OTP_LOCK:
+ assert(len == 1);
+ version->otp_lock = *data;
+ break;
+ case IWMBT_TLV_API_LOCK:
+ assert(len == 1);
+ version->api_lock = *data;
+ break;
+ case IWMBT_TLV_DEBUG_LOCK:
+ assert(len == 1);
+ version->debug_lock = *data;
+ break;
+ case IWMBT_TLV_MIN_FW:
+ assert(len == 3);
+ version->min_fw_build_nn = data[0];
+ version->min_fw_build_cw = data[1];
+ version->min_fw_build_yy = data[2];
+ break;
+ case IWMBT_TLV_LIMITED_CCE:
+ assert(len == 1);
+ version->limited_cce = *data;
+ break;
+ case IWMBT_TLV_SBE_TYPE:
+ assert(len == 1);
+ version->sbe_type = *data;
+ break;
+ case IWMBT_TLV_OTP_BDADDR:
+ memcpy(&version->otp_bd_addr, data, sizeof(bdaddr_t));
+ break;
+ default:
+ /* Ignore other types */
+ break;
+ }
+
+ datalen -= len;
+ data += len;
+ }
+
+ return (0);
+}
+
int
iwmbt_get_boot_params(struct libusb_device_handle *hdl,
struct iwmbt_boot_params *params)
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.8 b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.8
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.8
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.8
@@ -26,7 +26,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 31, 2024
+.Dd September 15, 2024
.Dt IWMBTFW 8
.Os
.Sh NAME
@@ -48,7 +48,7 @@
.Pp
This utility will
.Em only
-work with Intel Wireless 7260/8260/8265 chip based Bluetooth USB devices
+work with Intel Wireless 7260/8260/9260 chip based Bluetooth USB devices
and some of their successors.
The identification is currently based on USB vendor ID/product ID pair.
The vendor ID should be 0x8087
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf
@@ -1,11 +1,12 @@
#
-# Download Intel Wireless 8260/8265 bluetooth adaptor firmware
+# Download Intel Wireless bluetooth adaptor firmware
+#
notify 100 {
match "system" "USB";
match "subsystem" "DEVICE";
match "type" "ATTACH";
match "vendor" "0x8087";
- match "product" "(0x07dc|0x0a2a|0x0aa7|0x0a2b|0x0aaa|0x0025|0x0026|0x0029)";
+ match "product" "(0x07dc|0x0a2a|0x0aa7|0x0a2b|0x0aaa|0x0025|0x0026|0x0029|0x0032|0x0033)";
action "/usr/sbin/iwmbtfw -d $cdev -f /usr/local/share/iwmbt-firmware";
};
diff --git a/usr.sbin/bluetooth/iwmbtfw/main.c b/usr.sbin/bluetooth/iwmbtfw/main.c
--- a/usr.sbin/bluetooth/iwmbtfw/main.c
+++ b/usr.sbin/bluetooth/iwmbtfw/main.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 2013 Adrian Chadd <adrian@freebsd.org>
* Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
+ * Copyright (c) 2023 Future Crew LLC.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -50,71 +51,63 @@
int iwmbt_do_debug = 0;
int iwmbt_do_info = 0;
+enum iwmbt_device {
+ IWMBT_DEVICE_UNKNOWN,
+ IWMBT_DEVICE_7260,
+ IWMBT_DEVICE_8260,
+ IWMBT_DEVICE_9260,
+};
+
struct iwmbt_devid {
uint16_t product_id;
uint16_t vendor_id;
+ enum iwmbt_device device;
};
-static struct iwmbt_devid iwmbt_list_72xx[] = {
+static struct iwmbt_devid iwmbt_list[] = {
- /* Intel Wireless 7260/7265 and successors */
- { .vendor_id = 0x8087, .product_id = 0x07dc },
- { .vendor_id = 0x8087, .product_id = 0x0a2a },
- { .vendor_id = 0x8087, .product_id = 0x0aa7 },
-};
+ /* Intel Wireless 7260/7265 and successors */
+ { .vendor_id = 0x8087, .product_id = 0x07dc, .device = IWMBT_DEVICE_7260 },
+ { .vendor_id = 0x8087, .product_id = 0x0a2a, .device = IWMBT_DEVICE_7260 },
+ { .vendor_id = 0x8087, .product_id = 0x0aa7, .device = IWMBT_DEVICE_7260 },
-static struct iwmbt_devid iwmbt_list_82xx[] = {
+ /* Intel Wireless 8260/8265 and successors */
+ { .vendor_id = 0x8087, .product_id = 0x0a2b, .device = IWMBT_DEVICE_8260 },
+ { .vendor_id = 0x8087, .product_id = 0x0aaa, .device = IWMBT_DEVICE_8260 },
+ { .vendor_id = 0x8087, .product_id = 0x0025, .device = IWMBT_DEVICE_8260 },
+ { .vendor_id = 0x8087, .product_id = 0x0026, .device = IWMBT_DEVICE_8260 },
+ { .vendor_id = 0x8087, .product_id = 0x0029, .device = IWMBT_DEVICE_8260 },
- /* Intel Wireless 8260/8265 and successors */
- { .vendor_id = 0x8087, .product_id = 0x0a2b },
- { .vendor_id = 0x8087, .product_id = 0x0aaa },
- { .vendor_id = 0x8087, .product_id = 0x0025 },
- { .vendor_id = 0x8087, .product_id = 0x0026 },
- { .vendor_id = 0x8087, .product_id = 0x0029 },
+ /* Intel Wireless 9260/9560 and successors */
+ { .vendor_id = 0x8087, .product_id = 0x0032, .device = IWMBT_DEVICE_9260 },
+ { .vendor_id = 0x8087, .product_id = 0x0033, .device = IWMBT_DEVICE_9260 },
};
-static int
-iwmbt_is_7260(struct libusb_device_descriptor *d)
+static enum iwmbt_device
+iwmbt_is_supported(struct libusb_device_descriptor *d)
{
int i;
/* Search looking for whether it's an 7260/7265 */
- for (i = 0; i < (int) nitems(iwmbt_list_72xx); i++) {
- if ((iwmbt_list_72xx[i].product_id == d->idProduct) &&
- (iwmbt_list_72xx[i].vendor_id == d->idVendor)) {
- iwmbt_info("found 7260/7265");
- return (1);
- }
- }
-
- /* Not found */
- return (0);
-}
-
-static int
-iwmbt_is_8260(struct libusb_device_descriptor *d)
-{
- int i;
-
- /* Search looking for whether it's an 8260/8265 */
- for (i = 0; i < (int) nitems(iwmbt_list_82xx); i++) {
- if ((iwmbt_list_82xx[i].product_id == d->idProduct) &&
- (iwmbt_list_82xx[i].vendor_id == d->idVendor)) {
- iwmbt_info("found 8260/8265");
- return (1);
+ for (i = 0; i < (int) nitems(iwmbt_list); i++) {
+ if ((iwmbt_list[i].product_id == d->idProduct) &&
+ (iwmbt_list[i].vendor_id == d->idVendor)) {
+ iwmbt_info("found iwmbtfw compatible");
+ return (iwmbt_list[i].device);
}
}
/* Not found */
- return (0);
+ return (IWMBT_DEVICE_UNKNOWN);
}
static libusb_device *
iwmbt_find_device(libusb_context *ctx, int bus_id, int dev_id,
- int *iwmbt_use_old_method)
+ enum iwmbt_device *iwmbt_device)
{
libusb_device **list, *dev = NULL, *found = NULL;
struct libusb_device_descriptor d;
+ enum iwmbt_device device;
ssize_t cnt, i;
int r;
@@ -141,20 +134,13 @@
}
/* Match on the vendor/product id */
- if (iwmbt_is_7260(&d)) {
+ device = iwmbt_is_supported(&d);
+ if (device != IWMBT_DEVICE_UNKNOWN) {
/*
* Take a reference so it's not freed later on.
*/
found = libusb_ref_device(dev);
- *iwmbt_use_old_method = 1;
- break;
- } else
- if (iwmbt_is_8260(&d)) {
- /*
- * Take a reference so it's not freed later on.
- */
- found = libusb_ref_device(dev);
- *iwmbt_use_old_method = 0;
+ *iwmbt_device = device;
break;
}
}
@@ -200,6 +186,44 @@
params->otp_bdaddr[0]);
}
+static void
+iwmbt_dump_version_tlv(struct iwmbt_version_tlv *ver)
+{
+ iwmbt_info("cnvi_top 0x%08x", ver->cnvi_top);
+ iwmbt_info("cnvr_top 0x%08x", ver->cnvr_top);
+ iwmbt_info("cnvi_bt 0x%08x", ver->cnvi_bt);
+ iwmbt_info("cnvr_bt 0x%08x", ver->cnvr_bt);
+ iwmbt_info("dev_rev_id 0x%04x", ver->dev_rev_id);
+ iwmbt_info("img_type 0x%02x", ver->img_type);
+ iwmbt_info("timestamp 0x%04x", ver->timestamp);
+ iwmbt_info("build_type 0x%02x", ver->build_type);
+ iwmbt_info("build_num 0x%08x", ver->build_num);
+ iwmbt_info("Secure Boot: %s", ver->secure_boot ? "on" : "off");
+ iwmbt_info("OTP lock: %s", ver->otp_lock ? "on" : "off");
+ iwmbt_info("API lock: %s", ver->api_lock ? "on" : "off");
+ iwmbt_info("Debug lock: %s", ver->debug_lock ? "on" : "off");
+ iwmbt_info("Minimum firmware build %u week %u year %u",
+ ver->min_fw_build_nn,
+ ver->min_fw_build_cw,
+ 2000 + ver->min_fw_build_yy);
+ iwmbt_info("limited_cce 0x%02x", ver->limited_cce);
+ iwmbt_info("sbe_type 0x%02x", ver->sbe_type);
+ iwmbt_info("OTC BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x",
+ ver->otp_bd_addr.b[5],
+ ver->otp_bd_addr.b[4],
+ ver->otp_bd_addr.b[3],
+ ver->otp_bd_addr.b[2],
+ ver->otp_bd_addr.b[1],
+ ver->otp_bd_addr.b[0]);
+ if (ver->img_type == 0x01 || ver->img_type == 0x03)
+ iwmbt_info("%s timestamp %u.%u buildtype %u build %u",
+ ver->img_type == 0x01 ? "Bootloader" : "Firmware",
+ 2000 + (ver->timestamp >> 8),
+ ver->timestamp & 0xff,
+ ver->build_type,
+ ver->build_num);
+}
+
static int
iwmbt_patch_firmware(libusb_device_handle *hdl, const char *firmware_path)
{
@@ -227,10 +251,10 @@
static int
iwmbt_init_firmware(libusb_device_handle *hdl, const char *firmware_path,
- uint32_t *boot_param)
+ uint32_t *boot_param, uint8_t hw_variant, uint8_t sbe_type)
{
struct iwmbt_firmware fw;
- int ret;
+ int header_len, ret = -1;
iwmbt_debug("loading %s", firmware_path);
@@ -240,12 +264,76 @@
return (-1);
}
- /* Load in the firmware */
- ret = iwmbt_load_fwfile(hdl, &fw, boot_param);
+ iwmbt_debug("Firmware file size=%d", fw.len);
+
+ if (hw_variant <= 0x14) {
+ /*
+ * Hardware variants 0x0b, 0x0c, 0x11 - 0x14 .sfi file have
+ * a RSA header of 644 bytes followed by Command Buffer.
+ */
+ header_len = RSA_HEADER_LEN;
+ if (fw.len < header_len) {
+ iwmbt_err("Invalid size of firmware file (%d)", fw.len);
+ ret = -1;
+ goto exit;
+ }
+
+ /* Check if the CSS Header version is RSA(0x00010000) */
+ if (le32dec(fw.buf + CSS_HEADER_OFFSET) != 0x00010000) {
+ iwmbt_err("Invalid CSS Header version");
+ ret = -1;
+ goto exit;
+ }
+
+ /* Only RSA secure boot engine supported */
+ if (sbe_type != 0x00) {
+ iwmbt_err("Invalid SBE type for hardware variant (%d)",
+ hw_variant);
+ ret = -1;
+ goto exit;
+ }
+
+ } else if (hw_variant >= 0x17) {
+ /*
+ * 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.
+ */
+ header_len = ECDSA_OFFSET + ECDSA_HEADER_LEN;
+ if (fw.len < header_len) {
+ iwmbt_err("Invalid size of firmware file (%d)", fw.len);
+ ret = -1;
+ goto exit;
+ }
+
+ /* Check if CSS header for ECDSA follows the RSA header */
+ if (fw.buf[ECDSA_OFFSET] != 0x06) {
+ ret = -1;
+ goto exit;
+ }
+
+ /* Check if the CSS Header version is ECDSA(0x00020000) */
+ if (le32dec(fw.buf + ECDSA_OFFSET + CSS_HEADER_OFFSET) != 0x00020000) {
+ iwmbt_err("Invalid CSS Header version");
+ ret = -1;
+ goto exit;
+ }
+ }
+
+ /* Load in the CSS header */
+ if (sbe_type == 0x00)
+ ret = iwmbt_load_rsa_header(hdl, &fw);
+ else if (sbe_type == 0x01)
+ ret = iwmbt_load_ecdsa_header(hdl, &fw);
if (ret < 0)
- iwmbt_debug("Loading firmware file failed");
+ goto exit;
- /* free it */
+ /* Load in the Command Buffer */
+ ret = iwmbt_load_fwfile(hdl, &fw, boot_param, header_len);
+
+exit:
+ /* free firmware */
iwmbt_fw_free(&fw);
return (ret);
@@ -318,6 +406,7 @@
libusb_device *dev = NULL;
libusb_device_handle *hdl = NULL;
static struct iwmbt_version ver;
+ static struct iwmbt_version_tlv ver_tlv;
static struct iwmbt_boot_params params;
uint32_t boot_param;
int r;
@@ -327,7 +416,7 @@
char *firmware_dir = NULL;
char *firmware_path = NULL;
int retcode = 1;
- int iwmbt_use_old_method = 0;
+ enum iwmbt_device iwmbt_device;
/* Parse command line arguments */
while ((n = getopt(argc, argv, "Dd:f:hIm:p:v:")) != -1) {
@@ -372,7 +461,7 @@
iwmbt_debug("opening dev %d.%d", (int) bus_id, (int) dev_id);
/* Find a device based on the bus/dev id */
- dev = iwmbt_find_device(ctx, bus_id, dev_id, &iwmbt_use_old_method);
+ dev = iwmbt_find_device(ctx, bus_id, dev_id, &iwmbt_device);
if (dev == NULL) {
iwmbt_err("device not found");
goto shutdown;
@@ -401,16 +490,16 @@
goto shutdown;
}
- /* Get Intel version */
- r = iwmbt_get_version(hdl, &ver);
- if (r < 0) {
- iwmbt_debug("iwmbt_get_version() failed code %d", r);
- goto shutdown;
- }
- iwmbt_dump_version(&ver);
- iwmbt_debug("fw_variant=0x%02x", (int) ver.fw_variant);
+ if (iwmbt_device == IWMBT_DEVICE_7260) {
- if (iwmbt_use_old_method) {
+ /* Get Intel version */
+ r = iwmbt_get_version(hdl, &ver);
+ if (r < 0) {
+ iwmbt_debug("iwmbt_get_version() failed code %d", r);
+ goto shutdown;
+ }
+ iwmbt_dump_version(&ver);
+ iwmbt_debug("fw_patch_num=0x%02x", (int) ver.fw_patch_num);
/* fw_patch_num = >0 operational mode */
if (ver.fw_patch_num > 0x00) {
@@ -469,7 +558,16 @@
iwmbt_info("Intel Event Mask is set");
(void)iwmbt_exit_manufacturer(hdl, 0x00);
- } else {
+ } else if (iwmbt_device == IWMBT_DEVICE_8260) {
+
+ /* Get Intel version */
+ r = iwmbt_get_version(hdl, &ver);
+ if (r < 0) {
+ iwmbt_debug("iwmbt_get_version() failed code %d", r);
+ goto shutdown;
+ }
+ iwmbt_dump_version(&ver);
+ iwmbt_debug("fw_variant=0x%02x", (int) ver.fw_variant);
/* fw_variant = 0x06 bootloader mode / 0x23 operational mode */
if (ver.fw_variant == 0x23) {
@@ -509,7 +607,7 @@
iwmbt_debug("firmware_path = %s", firmware_path);
/* Download firmware and parse it for magic Intel Reset parameter */
- r = iwmbt_init_firmware(hdl, firmware_path, &boot_param);
+ r = iwmbt_init_firmware(hdl, firmware_path, &boot_param, 0, 0);
free(firmware_path);
if (r < 0)
goto shutdown;
@@ -546,6 +644,93 @@
r = iwmbt_set_event_mask(hdl);
if (r == 0)
iwmbt_info("Intel Event Mask is set");
+
+ } else {
+
+ /* Get Intel version */
+ r = iwmbt_get_version_tlv(hdl, &ver_tlv);
+ if (r < 0) {
+ iwmbt_debug("iwmbt_get_version_tlv() failed code %d", r);
+ goto shutdown;
+ }
+ iwmbt_dump_version_tlv(&ver_tlv);
+ iwmbt_debug("img_type=0x%02x", (int) ver_tlv.img_type);
+
+ /* img_type = 0x01 bootloader mode / 0x03 operational mode */
+ if (ver_tlv.img_type == 0x03) {
+ iwmbt_info("Firmware has already been downloaded");
+ retcode = 0;
+ goto reset;
+ }
+
+ if (ver_tlv.img_type != 0x01){
+ iwmbt_err("unknown img_type 0x%02x", (int) ver_tlv.img_type);
+ goto shutdown;
+ }
+
+ /* Check if firmware fragments are ACKed with a cmd complete event */
+ if (ver_tlv.limited_cce != 0x00) {
+ iwmbt_err("Unsupported Intel firmware loading method (%u)",
+ ver_tlv.limited_cce);
+ goto shutdown;
+ }
+
+ /* Check if secure boot engine is supported: 1 (ECDSA) or 0 (RSA) */
+ if (ver_tlv.sbe_type > 0x01) {
+ iwmbt_err("Unsupported secure boot engine (%u)",
+ ver_tlv.sbe_type);
+ goto shutdown;
+ }
+
+ /* Default the firmware path */
+ if (firmware_dir == NULL)
+ firmware_dir = strdup(_DEFAULT_IWMBT_FIRMWARE_PATH);
+
+ firmware_path = iwmbt_get_fwname_tlv(&ver_tlv, firmware_dir, "sfi");
+ if (firmware_path == NULL)
+ goto shutdown;
+
+ iwmbt_debug("firmware_path = %s", firmware_path);
+
+ /* Download firmware and parse it for magic Intel Reset parameter */
+ r = iwmbt_init_firmware(hdl, firmware_path, &boot_param,
+ ver_tlv.cnvi_bt >> 16 & 0x3f, ver_tlv.sbe_type);
+ free(firmware_path);
+ if (r < 0)
+ goto shutdown;
+
+ r = iwmbt_intel_reset(hdl, boot_param);
+ if (r < 0) {
+ iwmbt_debug("iwmbt_intel_reset() failed!");
+ goto shutdown;
+ }
+
+ iwmbt_info("Firmware operational");
+
+ /* Once device is running in operational mode we can ignore failures */
+ retcode = 0;
+
+ /* Execute Read Intel Version one more time */
+ r = iwmbt_get_version(hdl, &ver);
+ if (r == 0)
+ iwmbt_dump_version(&ver);
+
+ /* Apply the device configuration (DDC) parameters */
+ firmware_path = iwmbt_get_fwname_tlv(&ver_tlv, firmware_dir, "ddc");
+ iwmbt_debug("ddc_path = %s", firmware_path);
+ if (firmware_path != NULL) {
+ r = iwmbt_init_ddc(hdl, firmware_path);
+ if (r == 0)
+ iwmbt_info("DDC download complete");
+ free(firmware_path);
+ }
+
+ /* Set Intel Event mask */
+ r = iwmbt_set_event_mask(hdl);
+ if (r == 0)
+ iwmbt_info("Intel Event Mask is set");
+
+ iwmbt_info("Firmware download complete");
}
reset:
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Mar 4, 1:53 AM (12 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29221194
Default Alt Text
D46735.diff (25 KB)
Attached To
Mode
D46735: iwmbtfw(4): Add support for 9260/9560 bluetooth adaptors
Attached
Detach File
Event Timeline
Log In to Comment