xref: /freebsd/usr.sbin/bluetooth/iwmbtfw/main.c (revision 86077f4fd11070518a6d04eee7fdb93cbbfb1b52)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2013 Adrian Chadd <adrian@freebsd.org>
5  * Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
6  * Copyright (c) 2023 Future Crew LLC.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/param.h>
31 #include <sys/stat.h>
32 #include <sys/endian.h>
33 
34 #include <err.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <libgen.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 
43 #include <libusb.h>
44 
45 #include "iwmbt_fw.h"
46 #include "iwmbt_hw.h"
47 #include "iwmbt_dbg.h"
48 
49 #define	_DEFAULT_IWMBT_FIRMWARE_PATH	"/usr/share/firmware/intel"
50 
51 int	iwmbt_do_debug = 0;
52 int	iwmbt_do_info = 0;
53 
54 enum iwmbt_device {
55 	IWMBT_DEVICE_UNKNOWN,
56 	IWMBT_DEVICE_7260,
57 	IWMBT_DEVICE_8260,
58 	IWMBT_DEVICE_9260,
59 };
60 
61 struct iwmbt_devid {
62 	uint16_t product_id;
63 	uint16_t vendor_id;
64 	enum iwmbt_device device;
65 };
66 
67 static struct iwmbt_devid iwmbt_list[] = {
68 
69     /* Intel Wireless 7260/7265 and successors */
70     { .vendor_id = 0x8087, .product_id = 0x07dc, .device = IWMBT_DEVICE_7260 },
71     { .vendor_id = 0x8087, .product_id = 0x0a2a, .device = IWMBT_DEVICE_7260 },
72     { .vendor_id = 0x8087, .product_id = 0x0aa7, .device = IWMBT_DEVICE_7260 },
73 
74     /* Intel Wireless 8260/8265 and successors */
75     { .vendor_id = 0x8087, .product_id = 0x0a2b, .device = IWMBT_DEVICE_8260 },
76     { .vendor_id = 0x8087, .product_id = 0x0aaa, .device = IWMBT_DEVICE_8260 },
77     { .vendor_id = 0x8087, .product_id = 0x0025, .device = IWMBT_DEVICE_8260 },
78     { .vendor_id = 0x8087, .product_id = 0x0026, .device = IWMBT_DEVICE_8260 },
79     { .vendor_id = 0x8087, .product_id = 0x0029, .device = IWMBT_DEVICE_8260 },
80 
81     /* Intel Wireless 9260/9560 and successors */
82     { .vendor_id = 0x8087, .product_id = 0x0032, .device = IWMBT_DEVICE_9260 },
83     { .vendor_id = 0x8087, .product_id = 0x0033, .device = IWMBT_DEVICE_9260 },
84 };
85 
86 static enum iwmbt_device
87 iwmbt_is_supported(struct libusb_device_descriptor *d)
88 {
89 	int i;
90 
91 	/* Search looking for whether it's an 7260/7265 */
92 	for (i = 0; i < (int) nitems(iwmbt_list); i++) {
93 		if ((iwmbt_list[i].product_id == d->idProduct) &&
94 		    (iwmbt_list[i].vendor_id == d->idVendor)) {
95 			iwmbt_info("found iwmbtfw compatible");
96 			return (iwmbt_list[i].device);
97 		}
98 	}
99 
100 	/* Not found */
101 	return (IWMBT_DEVICE_UNKNOWN);
102 }
103 
104 static libusb_device *
105 iwmbt_find_device(libusb_context *ctx, int bus_id, int dev_id,
106     enum iwmbt_device *iwmbt_device)
107 {
108 	libusb_device **list, *dev = NULL, *found = NULL;
109 	struct libusb_device_descriptor d;
110 	enum iwmbt_device device;
111 	ssize_t cnt, i;
112 	int r;
113 
114 	cnt = libusb_get_device_list(ctx, &list);
115 	if (cnt < 0) {
116 		iwmbt_err("libusb_get_device_list() failed: code %lld",
117 		    (long long int) cnt);
118 		return (NULL);
119 	}
120 
121 	/*
122 	 * Scan through USB device list.
123 	 */
124 	for (i = 0; i < cnt; i++) {
125 		dev = list[i];
126 		if (bus_id == libusb_get_bus_number(dev) &&
127 		    dev_id == libusb_get_device_address(dev)) {
128 			/* Get the device descriptor for this device entry */
129 			r = libusb_get_device_descriptor(dev, &d);
130 			if (r != 0) {
131 				iwmbt_err("libusb_get_device_descriptor: %s",
132 				    libusb_strerror(r));
133 				break;
134 			}
135 
136 			/* Match on the vendor/product id */
137 			device = iwmbt_is_supported(&d);
138 			if (device != IWMBT_DEVICE_UNKNOWN) {
139 				/*
140 				 * Take a reference so it's not freed later on.
141 				 */
142 				found = libusb_ref_device(dev);
143 				*iwmbt_device = device;
144 				break;
145 			}
146 		}
147 	}
148 
149 	libusb_free_device_list(list, 1);
150 	return (found);
151 }
152 
153 static void
154 iwmbt_dump_version(struct iwmbt_version *ver)
155 {
156 	iwmbt_info("status       0x%02x", ver->status);
157 	iwmbt_info("hw_platform  0x%02x", ver->hw_platform);
158 	iwmbt_info("hw_variant   0x%02x", ver->hw_variant);
159 	iwmbt_info("hw_revision  0x%02x", ver->hw_revision);
160 	iwmbt_info("fw_variant   0x%02x", ver->fw_variant);
161 	iwmbt_info("fw_revision  0x%02x", ver->fw_revision);
162 	iwmbt_info("fw_build_num 0x%02x", ver->fw_build_num);
163 	iwmbt_info("fw_build_ww  0x%02x", ver->fw_build_ww);
164 	iwmbt_info("fw_build_yy  0x%02x", ver->fw_build_yy);
165 	iwmbt_info("fw_patch_num 0x%02x", ver->fw_patch_num);
166 }
167 
168 static void
169 iwmbt_dump_boot_params(struct iwmbt_boot_params *params)
170 {
171 	iwmbt_info("Device revision: %u", le16toh(params->dev_revid));
172 	iwmbt_info("Secure Boot:  %s", params->secure_boot ? "on" : "off");
173 	iwmbt_info("OTP lock:     %s", params->otp_lock    ? "on" : "off");
174 	iwmbt_info("API lock:     %s", params->api_lock    ? "on" : "off");
175 	iwmbt_info("Debug lock:   %s", params->debug_lock  ? "on" : "off");
176 	iwmbt_info("Minimum firmware build %u week %u year %u",
177 	    params->min_fw_build_nn,
178 	    params->min_fw_build_cw,
179 	    2000 + params->min_fw_build_yy);
180 	iwmbt_info("OTC BD_ADDR:  %02x:%02x:%02x:%02x:%02x:%02x",
181 	    params->otp_bdaddr[5],
182 	    params->otp_bdaddr[4],
183 	    params->otp_bdaddr[3],
184 	    params->otp_bdaddr[2],
185 	    params->otp_bdaddr[1],
186 	    params->otp_bdaddr[0]);
187 }
188 
189 static void
190 iwmbt_dump_version_tlv(struct iwmbt_version_tlv *ver)
191 {
192 	iwmbt_info("cnvi_top     0x%08x", ver->cnvi_top);
193 	iwmbt_info("cnvr_top     0x%08x", ver->cnvr_top);
194 	iwmbt_info("cnvi_bt      0x%08x", ver->cnvi_bt);
195 	iwmbt_info("cnvr_bt      0x%08x", ver->cnvr_bt);
196 	iwmbt_info("dev_rev_id   0x%04x", ver->dev_rev_id);
197 	iwmbt_info("img_type     0x%02x", ver->img_type);
198 	iwmbt_info("timestamp    0x%04x", ver->timestamp);
199 	iwmbt_info("build_type   0x%02x", ver->build_type);
200 	iwmbt_info("build_num    0x%08x", ver->build_num);
201 	iwmbt_info("Secure Boot:  %s", ver->secure_boot ? "on" : "off");
202 	iwmbt_info("OTP lock:     %s", ver->otp_lock    ? "on" : "off");
203 	iwmbt_info("API lock:     %s", ver->api_lock    ? "on" : "off");
204 	iwmbt_info("Debug lock:   %s", ver->debug_lock  ? "on" : "off");
205 	iwmbt_info("Minimum firmware build %u week %u year %u",
206 	    ver->min_fw_build_nn,
207 	    ver->min_fw_build_cw,
208 	    2000 + ver->min_fw_build_yy);
209 	iwmbt_info("limited_cce  0x%02x", ver->limited_cce);
210 	iwmbt_info("sbe_type     0x%02x", ver->sbe_type);
211 	iwmbt_info("OTC BD_ADDR:  %02x:%02x:%02x:%02x:%02x:%02x",
212 	    ver->otp_bd_addr.b[5],
213 	    ver->otp_bd_addr.b[4],
214 	    ver->otp_bd_addr.b[3],
215 	    ver->otp_bd_addr.b[2],
216 	    ver->otp_bd_addr.b[1],
217 	    ver->otp_bd_addr.b[0]);
218 	if (ver->img_type == 0x01 || ver->img_type == 0x03)
219 		iwmbt_info("%s timestamp %u.%u buildtype %u build %u",
220 		    ver->img_type == 0x01 ? "Bootloader" : "Firmware",
221 		    2000 + (ver->timestamp >> 8),
222 		    ver->timestamp & 0xff,
223 		    ver->build_type,
224 		    ver->build_num);
225 }
226 
227 static int
228 iwmbt_patch_firmware(libusb_device_handle *hdl, const char *firmware_path)
229 {
230 	struct iwmbt_firmware fw;
231 	int ret;
232 
233 	iwmbt_debug("loading %s", firmware_path);
234 
235 	/* Read in the firmware */
236 	if (iwmbt_fw_read(&fw, firmware_path) <= 0) {
237 		iwmbt_debug("iwmbt_fw_read() failed");
238 		return (-1);
239 	}
240 
241 	/* Load in the firmware */
242 	ret = iwmbt_patch_fwfile(hdl, &fw);
243 	if (ret < 0)
244 		iwmbt_debug("Loading firmware file failed");
245 
246 	/* free it */
247 	iwmbt_fw_free(&fw);
248 
249 	return (ret);
250 }
251 
252 static int
253 iwmbt_init_firmware(libusb_device_handle *hdl, const char *firmware_path,
254     uint32_t *boot_param, uint8_t hw_variant, uint8_t sbe_type)
255 {
256 	struct iwmbt_firmware fw;
257 	int header_len, ret = -1;
258 
259 	iwmbt_debug("loading %s", firmware_path);
260 
261 	/* Read in the firmware */
262 	if (iwmbt_fw_read(&fw, firmware_path) <= 0) {
263 		iwmbt_debug("iwmbt_fw_read() failed");
264 		return (-1);
265 	}
266 
267 	iwmbt_debug("Firmware file size=%d", fw.len);
268 
269 	if (hw_variant <= 0x14) {
270 		/*
271 		 * Hardware variants 0x0b, 0x0c, 0x11 - 0x14 .sfi file have
272 		 * a RSA header of 644 bytes followed by Command Buffer.
273 		 */
274 		header_len = RSA_HEADER_LEN;
275 		if (fw.len < header_len) {
276 			iwmbt_err("Invalid size of firmware file (%d)", fw.len);
277 			ret = -1;
278 			goto exit;
279 		}
280 
281 		/* Check if the CSS Header version is RSA(0x00010000) */
282 		if (le32dec(fw.buf + CSS_HEADER_OFFSET) != 0x00010000) {
283 			iwmbt_err("Invalid CSS Header version");
284 			ret = -1;
285 			goto exit;
286 		}
287 
288 		/* Only RSA secure boot engine supported */
289 		if (sbe_type != 0x00) {
290 			iwmbt_err("Invalid SBE type for hardware variant (%d)",
291 			    hw_variant);
292 			ret = -1;
293 			goto exit;
294 		}
295 
296 	} else if (hw_variant >= 0x17) {
297 		/*
298 		 * Hardware variants 0x17, 0x18 onwards support both RSA and
299 		 * ECDSA secure boot engine. As a result, the corresponding sfi
300 		 * file will have RSA header of 644, ECDSA header of 320 bytes
301 		 * followed by Command Buffer.
302 		 */
303 		header_len = ECDSA_OFFSET + ECDSA_HEADER_LEN;
304 		if (fw.len < header_len) {
305 			iwmbt_err("Invalid size of firmware file (%d)", fw.len);
306 			ret = -1;
307 			goto exit;
308 		}
309 
310 		/* Check if CSS header for ECDSA follows the RSA header */
311 		if (fw.buf[ECDSA_OFFSET] != 0x06) {
312 			ret = -1;
313 			goto exit;
314 		}
315 
316 		/* Check if the CSS Header version is ECDSA(0x00020000) */
317 		if (le32dec(fw.buf + ECDSA_OFFSET + CSS_HEADER_OFFSET) != 0x00020000) {
318 			iwmbt_err("Invalid CSS Header version");
319 			ret = -1;
320 			goto exit;
321 		}
322 	}
323 
324 	/* Load in the CSS header */
325 	if (sbe_type == 0x00)
326 		ret = iwmbt_load_rsa_header(hdl, &fw);
327 	else if (sbe_type == 0x01)
328 		ret = iwmbt_load_ecdsa_header(hdl, &fw);
329 	if (ret < 0)
330 		goto exit;
331 
332 	/* Load in the Command Buffer */
333 	ret = iwmbt_load_fwfile(hdl, &fw, boot_param, header_len);
334 
335 exit:
336 	/* free firmware */
337 	iwmbt_fw_free(&fw);
338 
339 	return (ret);
340 }
341 
342 static int
343 iwmbt_init_ddc(libusb_device_handle *hdl, const char *ddc_path)
344 {
345 	struct iwmbt_firmware ddc;
346 	int ret;
347 
348 	iwmbt_debug("loading %s", ddc_path);
349 
350 	/* Read in the DDC file */
351 	if (iwmbt_fw_read(&ddc, ddc_path) <= 0) {
352 		iwmbt_debug("iwmbt_fw_read() failed");
353 		return (-1);
354 	}
355 
356 	/* Load in the DDC file */
357 	ret = iwmbt_load_ddc(hdl, &ddc);
358 	if (ret < 0)
359 		iwmbt_debug("Loading DDC file failed");
360 
361 	/* free it */
362 	iwmbt_fw_free(&ddc);
363 
364 	return (ret);
365 }
366 
367 /*
368  * Parse ugen name and extract device's bus and address
369  */
370 
371 static int
372 parse_ugen_name(char const *ugen, uint8_t *bus, uint8_t *addr)
373 {
374 	char *ep;
375 
376 	if (strncmp(ugen, "ugen", 4) != 0)
377 		return (-1);
378 
379 	*bus = (uint8_t) strtoul(ugen + 4, &ep, 10);
380 	if (*ep != '.')
381 		return (-1);
382 
383 	*addr = (uint8_t) strtoul(ep + 1, &ep, 10);
384 	if (*ep != '\0')
385 		return (-1);
386 
387 	return (0);
388 }
389 
390 static void
391 usage(void)
392 {
393 	fprintf(stderr,
394 	    "Usage: iwmbtfw (-D) -d ugenX.Y (-f firmware path) (-I)\n");
395 	fprintf(stderr, "    -D: enable debugging\n");
396 	fprintf(stderr, "    -d: device to operate upon\n");
397 	fprintf(stderr, "    -f: firmware path, if not default\n");
398 	fprintf(stderr, "    -I: enable informational output\n");
399 	exit(127);
400 }
401 
402 int
403 main(int argc, char *argv[])
404 {
405 	libusb_context *ctx = NULL;
406 	libusb_device *dev = NULL;
407 	libusb_device_handle *hdl = NULL;
408 	static struct iwmbt_version ver;
409 	static struct iwmbt_version_tlv ver_tlv;
410 	static struct iwmbt_boot_params params;
411 	uint32_t boot_param;
412 	int r;
413 	uint8_t bus_id = 0, dev_id = 0;
414 	int devid_set = 0;
415 	int n;
416 	char *firmware_dir = NULL;
417 	char *firmware_path = NULL;
418 	int retcode = 1;
419 	enum iwmbt_device iwmbt_device;
420 
421 	/* Parse command line arguments */
422 	while ((n = getopt(argc, argv, "Dd:f:hIm:p:v:")) != -1) {
423 		switch (n) {
424 		case 'd': /* ugen device name */
425 			devid_set = 1;
426 			if (parse_ugen_name(optarg, &bus_id, &dev_id) < 0)
427 				usage();
428 			break;
429 		case 'D':
430 			iwmbt_do_debug = 1;
431 			break;
432 		case 'f': /* firmware dir */
433 			if (firmware_dir)
434 				free(firmware_dir);
435 			firmware_dir = strdup(optarg);
436 			break;
437 		case 'I':
438 			iwmbt_do_info = 1;
439 			break;
440 		case 'h':
441 		default:
442 			usage();
443 			break;
444 			/* NOT REACHED */
445 		}
446 	}
447 
448 	/* Ensure the devid was given! */
449 	if (devid_set == 0) {
450 		usage();
451 		/* NOTREACHED */
452 	}
453 
454 	/* libusb setup */
455 	r = libusb_init(&ctx);
456 	if (r != 0) {
457 		iwmbt_err("libusb_init failed: code %d", r);
458 		exit(127);
459 	}
460 
461 	iwmbt_debug("opening dev %d.%d", (int) bus_id, (int) dev_id);
462 
463 	/* Find a device based on the bus/dev id */
464 	dev = iwmbt_find_device(ctx, bus_id, dev_id, &iwmbt_device);
465 	if (dev == NULL) {
466 		iwmbt_err("device not found");
467 		goto shutdown;
468 	}
469 
470 	/* XXX enforce that bInterfaceNumber is 0 */
471 
472 	/* XXX enforce the device/product id if they're non-zero */
473 
474 	/* Grab device handle */
475 	r = libusb_open(dev, &hdl);
476 	if (r != 0) {
477 		iwmbt_err("libusb_open() failed: code %d", r);
478 		goto shutdown;
479 	}
480 
481 	/* Check if ng_ubt is attached */
482 	r = libusb_kernel_driver_active(hdl, 0);
483 	if (r < 0) {
484 		iwmbt_err("libusb_kernel_driver_active() failed: code %d", r);
485 		goto shutdown;
486 	}
487 	if (r > 0) {
488 		iwmbt_info("Firmware has already been downloaded");
489 		retcode = 0;
490 		goto shutdown;
491 	}
492 
493 	if (iwmbt_device == IWMBT_DEVICE_7260) {
494 
495 		/* Get Intel version */
496 		r = iwmbt_get_version(hdl, &ver);
497 		if (r < 0) {
498 			iwmbt_debug("iwmbt_get_version() failed code %d", r);
499 			goto shutdown;
500 		}
501 		iwmbt_dump_version(&ver);
502 		iwmbt_debug("fw_patch_num=0x%02x", (int) ver.fw_patch_num);
503 
504 		/* fw_patch_num = >0 operational mode */
505 		if (ver.fw_patch_num > 0x00) {
506 			iwmbt_info("Firmware has already been downloaded");
507 			retcode = 0;
508 			goto reset;
509 		}
510 
511 		/* Default the firmware path */
512 		if (firmware_dir == NULL)
513 			firmware_dir = strdup(_DEFAULT_IWMBT_FIRMWARE_PATH);
514 
515 		firmware_path = iwmbt_get_fwname(&ver, &params, firmware_dir, "bseq");
516 		if (firmware_path == NULL)
517 			goto shutdown;
518 
519 		iwmbt_debug("firmware_path = %s", firmware_path);
520 
521 		/* Check firmware file exists before changing HW mode */
522 		r = access(firmware_path, R_OK);
523 		if (r) {
524 			perror("Failed to open firmware");
525 			goto shutdown;
526 		}
527 
528 		/* Enter manufacturer mode */
529 		r = iwmbt_enter_manufacturer(hdl);
530 		if (r < 0) {
531 			iwmbt_debug("iwmbt_enter_manufacturer() failed code %d", r);
532 			goto shutdown;
533 		}
534 
535 		/* Download firmware and parse it for magic Intel Reset parameter */
536 		r = iwmbt_patch_firmware(hdl, firmware_path);
537 		free(firmware_path);
538 		if (r < 0) {
539 			(void)iwmbt_exit_manufacturer(hdl, 0x01);
540 			goto shutdown;
541 		}
542 
543 		iwmbt_info("Firmware download complete");
544 
545 		/* Exit manufacturer mode */
546 		r = iwmbt_exit_manufacturer(hdl, r == 0 ? 0x00 : 0x02);
547 		if (r < 0) {
548 			iwmbt_debug("iwmbt_exit_manufacturer() failed code %d", r);
549 			goto shutdown;
550 		}
551 
552 		/* Once device is running in operational mode we can ignore failures */
553 		retcode = 0;
554 
555 		/* Execute Read Intel Version one more time */
556 		r = iwmbt_get_version(hdl, &ver);
557 		if (r == 0)
558 			iwmbt_dump_version(&ver);
559 
560 		/* Set Intel Event mask */
561 		if (iwmbt_enter_manufacturer(hdl) < 0)
562 			goto reset;
563 		r = iwmbt_set_event_mask(hdl);
564 		if (r == 0)
565 			iwmbt_info("Intel Event Mask is set");
566 		(void)iwmbt_exit_manufacturer(hdl, 0x00);
567 
568 	} else if (iwmbt_device == IWMBT_DEVICE_8260) {
569 
570 		/* Get Intel version */
571 		r = iwmbt_get_version(hdl, &ver);
572 		if (r < 0) {
573 			iwmbt_debug("iwmbt_get_version() failed code %d", r);
574 			goto shutdown;
575 		}
576 		iwmbt_dump_version(&ver);
577 		iwmbt_debug("fw_variant=0x%02x", (int) ver.fw_variant);
578 
579 		/* fw_variant = 0x06 bootloader mode / 0x23 operational mode */
580 		if (ver.fw_variant == 0x23) {
581 			iwmbt_info("Firmware has already been downloaded");
582 			retcode = 0;
583 			goto reset;
584 		}
585 
586 		if (ver.fw_variant != 0x06){
587 			iwmbt_err("unknown fw_variant 0x%02x", (int) ver.fw_variant);
588 			goto shutdown;
589 		}
590 
591 		/* Read Intel Secure Boot Params */
592 		r = iwmbt_get_boot_params(hdl, &params);
593 		if (r < 0) {
594 			iwmbt_debug("iwmbt_get_boot_params() failed!");
595 			goto shutdown;
596 		}
597 		iwmbt_dump_boot_params(&params);
598 
599 		/* Check if firmware fragments are ACKed with a cmd complete event */
600 		if (params.limited_cce != 0x00) {
601 			iwmbt_err("Unsupported Intel firmware loading method (%u)",
602 			   params.limited_cce);
603 			goto shutdown;
604 		}
605 
606 		/* Default the firmware path */
607 		if (firmware_dir == NULL)
608 			firmware_dir = strdup(_DEFAULT_IWMBT_FIRMWARE_PATH);
609 
610 		firmware_path = iwmbt_get_fwname(&ver, &params, firmware_dir, "sfi");
611 		if (firmware_path == NULL)
612 			goto shutdown;
613 
614 		iwmbt_debug("firmware_path = %s", firmware_path);
615 
616 		/* Download firmware and parse it for magic Intel Reset parameter */
617 		r = iwmbt_init_firmware(hdl, firmware_path, &boot_param, 0, 0);
618 		free(firmware_path);
619 		if (r < 0)
620 			goto shutdown;
621 
622 		iwmbt_info("Firmware download complete");
623 
624 		r = iwmbt_intel_reset(hdl, boot_param);
625 		if (r < 0) {
626 			iwmbt_debug("iwmbt_intel_reset() failed!");
627 			goto shutdown;
628 		}
629 
630 		iwmbt_info("Firmware operational");
631 
632 		/* Once device is running in operational mode we can ignore failures */
633 		retcode = 0;
634 
635 		/* Execute Read Intel Version one more time */
636 		r = iwmbt_get_version(hdl, &ver);
637 		if (r == 0)
638 			iwmbt_dump_version(&ver);
639 
640 		/* Apply the device configuration (DDC) parameters */
641 		firmware_path = iwmbt_get_fwname(&ver, &params, firmware_dir, "ddc");
642 		iwmbt_debug("ddc_path = %s", firmware_path);
643 		if (firmware_path != NULL) {
644 			r = iwmbt_init_ddc(hdl, firmware_path);
645 			if (r == 0)
646 				iwmbt_info("DDC download complete");
647 			free(firmware_path);
648 		}
649 
650 		/* Set Intel Event mask */
651 		r = iwmbt_set_event_mask(hdl);
652 		if (r == 0)
653 			iwmbt_info("Intel Event Mask is set");
654 
655 	} else {
656 
657 		/* Get Intel version */
658 		r = iwmbt_get_version_tlv(hdl, &ver_tlv);
659 		if (r < 0) {
660 			iwmbt_debug("iwmbt_get_version_tlv() failed code %d", r);
661 			goto shutdown;
662 		}
663 		iwmbt_dump_version_tlv(&ver_tlv);
664 		iwmbt_debug("img_type=0x%02x", (int) ver_tlv.img_type);
665 
666 		/* img_type = 0x01 bootloader mode / 0x03 operational mode */
667 		if (ver_tlv.img_type == 0x03) {
668 			iwmbt_info("Firmware has already been downloaded");
669 			retcode = 0;
670 			goto reset;
671 		}
672 
673 		if (ver_tlv.img_type != 0x01){
674 			iwmbt_err("unknown img_type 0x%02x", (int) ver_tlv.img_type);
675 			goto shutdown;
676 		}
677 
678 		/* Check if firmware fragments are ACKed with a cmd complete event */
679 		if (ver_tlv.limited_cce != 0x00) {
680 			iwmbt_err("Unsupported Intel firmware loading method (%u)",
681 			   ver_tlv.limited_cce);
682 			goto shutdown;
683 		}
684 
685 		/* Check if secure boot engine is supported: 1 (ECDSA) or 0 (RSA) */
686 		if (ver_tlv.sbe_type > 0x01) {
687 			iwmbt_err("Unsupported secure boot engine (%u)",
688 			   ver_tlv.sbe_type);
689 			goto shutdown;
690 		}
691 
692 		/* Default the firmware path */
693 		if (firmware_dir == NULL)
694 			firmware_dir = strdup(_DEFAULT_IWMBT_FIRMWARE_PATH);
695 
696 		firmware_path = iwmbt_get_fwname_tlv(&ver_tlv, firmware_dir, "sfi");
697 		if (firmware_path == NULL)
698 			goto shutdown;
699 
700 		iwmbt_debug("firmware_path = %s", firmware_path);
701 
702 		/* Download firmware and parse it for magic Intel Reset parameter */
703 		r = iwmbt_init_firmware(hdl, firmware_path, &boot_param,
704 		    ver_tlv.cnvi_bt >> 16 & 0x3f, ver_tlv.sbe_type);
705 		free(firmware_path);
706 		if (r < 0)
707 			goto shutdown;
708 
709 		r = iwmbt_intel_reset(hdl, boot_param);
710 		if (r < 0) {
711 			iwmbt_debug("iwmbt_intel_reset() failed!");
712 			goto shutdown;
713 		}
714 
715 		iwmbt_info("Firmware operational");
716 
717 		/* Once device is running in operational mode we can ignore failures */
718 		retcode = 0;
719 
720 		/* Execute Read Intel Version one more time */
721 		r = iwmbt_get_version(hdl, &ver);
722 		if (r == 0)
723 			iwmbt_dump_version(&ver);
724 
725 		/* Apply the device configuration (DDC) parameters */
726 		firmware_path = iwmbt_get_fwname_tlv(&ver_tlv, firmware_dir, "ddc");
727 		iwmbt_debug("ddc_path = %s", firmware_path);
728 		if (firmware_path != NULL) {
729 			r = iwmbt_init_ddc(hdl, firmware_path);
730 			if (r == 0)
731 				iwmbt_info("DDC download complete");
732 			free(firmware_path);
733 		}
734 
735 		/* Set Intel Event mask */
736 		r = iwmbt_set_event_mask(hdl);
737 		if (r == 0)
738 			iwmbt_info("Intel Event Mask is set");
739 
740 		iwmbt_info("Firmware download complete");
741 	}
742 
743 reset:
744 
745 	/* Ask kernel driver to probe and attach device again */
746 	r = libusb_reset_device(hdl);
747 	if (r != 0)
748 		iwmbt_err("libusb_reset_device() failed: %s",
749 		    libusb_strerror(r));
750 
751 shutdown:
752 
753 	/* Shutdown */
754 
755 	if (hdl != NULL)
756 		libusb_close(hdl);
757 
758 	if (dev != NULL)
759 		libusb_unref_device(dev);
760 
761 	if (ctx != NULL)
762 		libusb_exit(ctx);
763 
764 	if (retcode == 0)
765 		iwmbt_info("Firmware download is successful!");
766 	else
767 		iwmbt_err("Firmware download failed!");
768 
769 	return (retcode);
770 }
771