View | Details | Raw Unified | Return to bug 228787 | Differences between
and this patch

Collapse All | Expand All

(-)b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c (+14 lines)
Lines 119-124 iwmbt_get_fwname(struct iwmbt_version *ver, struct iwmbt_boot_params *params, Link Here
119
	char *fwname;
119
	char *fwname;
120
120
121
	switch (ver->hw_variant) {
121
	switch (ver->hw_variant) {
122
	case 0x07:	/* 7260 */
123
		asprintf(&fwname, "%s/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.%s",
124
		    prefix,
125
		    le16toh(ver->hw_platform),
126
		    le16toh(ver->hw_variant),
127
		    le16toh(ver->hw_revision),
128
		    le16toh(ver->fw_variant),
129
		    le16toh(ver->fw_revision),
130
		    le16toh(ver->fw_build_num),
131
		    le16toh(ver->fw_build_ww),
132
		    le16toh(ver->fw_build_yy),
133
		    suffix);
134
		break;
135
122
	case 0x0b:	/* 8260 */
136
	case 0x0b:	/* 8260 */
123
	case 0x0c:	/* 8265 */
137
	case 0x0c:	/* 8265 */
124
		asprintf(&fwname, "%s/ibt-%u-%u.%s",
138
		asprintf(&fwname, "%s/ibt-%u-%u.%s",
(-)b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c (+188 lines)
Lines 126-131 iwmbt_hci_command(struct libusb_device_handle *hdl, struct iwmbt_hci_cmd *cmd, Link Here
126
	return (ret);
126
	return (ret);
127
}
127
}
128
128
129
int
130
iwmbt_patch_fwfile(struct libusb_device_handle *hdl,
131
    const struct iwmbt_firmware *fw)
132
{
133
	int ret, transferred;
134
	struct iwmbt_firmware fw_job = *fw;
135
	uint16_t cmd_opcode;
136
	uint8_t cmd_length;
137
	uint8_t cmd_buf[IWMBT_HCI_MAX_CMD_SIZE];
138
	uint8_t evt_code;
139
	uint8_t evt_length;
140
	uint8_t evt_buf[IWMBT_HCI_MAX_EVENT_SIZE];
141
	int skip_patch = 0;
142
143
	while(1)
144
	{
145
		skip_patch = 0;
146
147
		if (fw_job.len == 0)
148
			break;
149
150
		if (fw_job.buf[0] != 0x01) {
151
			iwmbt_err("Invalid firmware, expected HCI command (%d)",
152
					fw_job.buf[0]);
153
			return (-1);
154
		}
155
156
		/* Advance by one. */
157
		fw_job.buf++;
158
		fw_job.len--;
159
160
		/* Load in the HCI command to perform. */
161
		cmd_opcode = le16dec(fw_job.buf);
162
		cmd_length = fw_job.buf[2];
163
		memcpy(cmd_buf, fw_job.buf, 3);
164
165
		iwmbt_debug("opcode=%04x, len=%02x", cmd_opcode, cmd_length);
166
167
		/* For some reason the command 0xfc2f hangs up my card. */
168
		if (cmd_opcode == 0xfc2f) {
169
			skip_patch = 1;
170
		}
171
172
		/* Advance by three. */
173
		fw_job.buf += 3;
174
		fw_job.len -= 3;
175
176
		/* Copy data to HCI command buffer. */
177
		memcpy(cmd_buf + 3, fw_job.buf, cmd_length);
178
179
		/* Advance by data length. */
180
		fw_job.buf += cmd_length;
181
		fw_job.len -= cmd_length;
182
183
		/*
184
		 * Every command has its associated event: data must match
185
		 * what is recorded in the firmware file. Perform that check
186
		 * now.
187
		 *
188
		 * Some commands are mapped to more than one event sequence,
189
		 * in that case we can drop the non-patch commands, as we
190
		 * probably don't need them for operation of the card.
191
		 *
192
		 */
193
194
		while(1)
195
		{
196
			if (fw_job.len == 0)
197
				break;
198
199
			if (fw_job.buf[0] != 0x02)
200
				break;
201
202
			/* Advance by one. */
203
			fw_job.buf++;
204
			fw_job.len--;
205
206
			/* Load in the HCI event. */
207
			evt_code = fw_job.buf[0];
208
			evt_length = fw_job.buf[1];
209
210
			/* Advance by two. */
211
			fw_job.buf += 2;
212
			fw_job.len -= 2;
213
214
			/* Prepare HCI event buffer. */
215
			memset(evt_buf, 0, IWMBT_HCI_MAX_EVENT_SIZE);
216
217
			iwmbt_debug("event=%04x, len=%02x",
218
					evt_code, evt_length);
219
220
			/* Advance by data length. */
221
			fw_job.buf += evt_length;
222
			fw_job.len -= evt_length;
223
224
			if (skip_patch == 0) {
225
				ret = iwmbt_hci_command(hdl,
226
				    (struct iwmbt_hci_cmd *)cmd_buf,
227
				    evt_buf,
228
				    IWMBT_HCI_MAX_EVENT_SIZE,
229
				    &transferred,
230
				    IWMBT_HCI_CMD_TIMEOUT);
231
232
				if (ret < 0) {
233
					iwmbt_debug("Can't send patch: code=%d, size=%d",
234
					    ret,
235
					    transferred);
236
					 return (-1);
237
				}
238
			}
239
240
			/* Is this the end of the file? */
241
			if (fw_job.len <= 0)
242
				break;
243
		}
244
	}
245
246
	return (0);
247
}
248
129
int
249
int
130
iwmbt_load_fwfile(struct libusb_device_handle *hdl,
250
iwmbt_load_fwfile(struct libusb_device_handle *hdl,
131
    const struct iwmbt_firmware *fw, uint32_t *boot_param)
251
    const struct iwmbt_firmware *fw, uint32_t *boot_param)
Lines 217-222 iwmbt_load_fwfile(struct libusb_device_handle *hdl, Link Here
217
	return (0);
337
	return (0);
218
}
338
}
219
339
340
int
341
iwmbt_enter_manufacturer(struct libusb_device_handle *hdl)
342
{
343
	int ret, transferred;
344
	static struct iwmbt_hci_cmd cmd = {
345
		.opcode = htole16(0xfc11),
346
		.length = 2,
347
		.data = { 0x01, 0x00 },
348
	};
349
	uint8_t buf[IWMBT_HCI_MAX_EVENT_SIZE];
350
351
	ret = iwmbt_hci_command(hdl,
352
	    &cmd,
353
	    buf,
354
	    sizeof(buf),
355
	    &transferred,
356
	    IWMBT_HCI_CMD_TIMEOUT);
357
358
	if (ret < 0) {
359
		 iwmbt_debug("Can't enter manufacturer mode: code=%d, size=%d",
360
		     ret,
361
		     transferred);
362
		 return (-1);
363
	}
364
365
	return (0);
366
}
367
368
int
369
iwmbt_exit_manufacturer(struct libusb_device_handle *hdl, int mode)
370
{
371
	int ret, transferred;
372
	static struct iwmbt_hci_cmd cmd = {
373
		.opcode = htole16(0xfc11),
374
		.length = 2,
375
		.data = { 0x00, 0x00 },
376
	};
377
	uint8_t buf[IWMBT_HCI_MAX_EVENT_SIZE];
378
379
	/*
380
	 * The mode sets the type of reset we want to perform:
381
	 * 0x00: simply exit manufacturer mode without a reset.
382
	 * 0x01: exit manufacturer mode with a reset and patches disabled
383
	 * 0x02: exit manufacturer mode with a reset and patches enabled
384
	 */
385
	if (mode > 2) {
386
		iwmbt_debug("iwmbt_exit_manufacturer(): unknown mode (%d)",
387
				mode);
388
	}
389
	cmd.data[1] = mode;
390
391
	ret = iwmbt_hci_command(hdl,
392
	    &cmd,
393
	    buf,
394
	    sizeof(buf),
395
	    &transferred,
396
	    IWMBT_HCI_CMD_TIMEOUT);
397
398
	if (ret < 0) {
399
		 iwmbt_debug("Can't exit manufacturer mode: code=%d, size=%d",
400
		     ret,
401
		     transferred);
402
		 return (-1);
403
	}
404
405
	return (0);
406
}
407
220
int
408
int
221
iwmbt_get_version(struct libusb_device_handle *hdl,
409
iwmbt_get_version(struct libusb_device_handle *hdl,
222
    struct iwmbt_version *version)
410
    struct iwmbt_version *version)
(-)b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h (+5 lines)
Lines 73-80 struct iwmbt_hci_event_cmd_compl { Link Here
73
#define	IWMBT_HCI_CMD_TIMEOUT		2000	/* ms */
73
#define	IWMBT_HCI_CMD_TIMEOUT		2000	/* ms */
74
#define	IWMBT_LOADCMPL_TIMEOUT		5000	/* ms */
74
#define	IWMBT_LOADCMPL_TIMEOUT		5000	/* ms */
75
75
76
extern	int iwmbt_patch_fwfile(struct libusb_device_handle *hdl,
77
	    const struct iwmbt_firmware *fw);
76
extern	int iwmbt_load_fwfile(struct libusb_device_handle *hdl,
78
extern	int iwmbt_load_fwfile(struct libusb_device_handle *hdl,
77
	    const struct iwmbt_firmware *fw, uint32_t *boot_param);
79
	    const struct iwmbt_firmware *fw, uint32_t *boot_param);
80
extern	int iwmbt_enter_manufacturer(struct libusb_device_handle *hdl);
81
extern	int iwmbt_exit_manufacturer(struct libusb_device_handle *hdl,
82
	    int mode);
78
extern	int iwmbt_get_version(struct libusb_device_handle *hdl,
83
extern	int iwmbt_get_version(struct libusb_device_handle *hdl,
79
	    struct iwmbt_version *version);
84
	    struct iwmbt_version *version);
80
extern	int iwmbt_get_boot_params(struct libusb_device_handle *hdl,
85
extern	int iwmbt_get_boot_params(struct libusb_device_handle *hdl,
(-)b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.8 (-3 / +7 lines)
Lines 1-5 Link Here
1
.\" Copyright (c) 2013, 2016 Adrian Chadd <adrian@freebsd.org>
1
.\" Copyright (c) 2013, 2016 Adrian Chadd <adrian@freebsd.org>
2
.\" Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
2
.\" Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
3
.\" Copyright (c) 2021 Philippe Michaud-Boudreault <pitwuu@gmail.com>
3
.\"
4
.\"
4
.\" Redistribution and use in source and binary forms, with or without
5
.\" Redistribution and use in source and binary forms, with or without
5
.\" modification, are permitted provided that the following conditions
6
.\" modification, are permitted provided that the following conditions
Lines 24-35 Link Here
24
.\"
25
.\"
25
.\" $FreeBSD$
26
.\" $FreeBSD$
26
.\"
27
.\"
27
.Dd June 4, 2019
28
.Dd May 3, 2021
28
.Dt IWMBTFW 8
29
.Dt IWMBTFW 8
29
.Os
30
.Os
30
.Sh NAME
31
.Sh NAME
31
.Nm iwmbtfw
32
.Nm iwmbtfw
32
.Nd firmware download utility for Intel Wireless 8260/8265 chip based Bluetooth
33
.Nd firmware download utility for Intel Wireless 7260/8260/8265 chip based Bluetooth
33
USB devices
34
USB devices
34
.Sh SYNOPSIS
35
.Sh SYNOPSIS
35
.Nm
36
.Nm
Lines 46-52 device. Link Here
46
.Pp
47
.Pp
47
This utility will
48
This utility will
48
.Em only
49
.Em only
49
work with Intel Wireless 8260/8265 chip based Bluetooth USB devices and some of
50
work with Intel Wireless 7260/8260/8265 chip based Bluetooth USB devices and some of
50
their successors.
51
their successors.
51
The identification is currently based on USB vendor ID/product ID pair.
52
The identification is currently based on USB vendor ID/product ID pair.
52
The vendor ID should be 0x8087
53
The vendor ID should be 0x8087
Lines 91-96 utility used as firmware downloader template and on Linux btintel driver Link Here
91
source code.
92
source code.
92
It is written by
93
It is written by
93
.An Vladimir Kondratyev Aq Mt wulf@FreeBSD.org .
94
.An Vladimir Kondratyev Aq Mt wulf@FreeBSD.org .
95
.Pp
96
Support for the 7260 card added by
97
.An Philippe Michaud-Boudreault Aq Mt pitwuu@gmail.com .
94
.Sh BUGS
98
.Sh BUGS
95
Most likely.
99
Most likely.
96
Please report if found.
100
Please report if found.
(-)b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf (-1 / +1 lines)
Lines 7-12 notify 100 { Link Here
7
	match "subsystem"	"DEVICE";
7
	match "subsystem"	"DEVICE";
8
	match "type"		"ATTACH";
8
	match "type"		"ATTACH";
9
	match "vendor"		"0x8087";
9
	match "vendor"		"0x8087";
10
	match "product"		"(0x0a2b|0x0aaa|0x0025|0x0026|0x0029)";
10
	match "product"		"(0x07dc|0x0a2a|0x0aa7|0x0a2b|0x0aaa|0x0025|0x0026|0x0029)";
11
	action "/usr/sbin/iwmbtfw -d $cdev -f /usr/local/share/iwmbt-firmware";
11
	action "/usr/sbin/iwmbtfw -d $cdev -f /usr/local/share/iwmbt-firmware";
12
};
12
};
(-)b/usr.sbin/bluetooth/iwmbtfw/main.c (-67 / +186 lines)
Lines 57-63 struct iwmbt_devid { Link Here
57
	uint16_t vendor_id;
57
	uint16_t vendor_id;
58
};
58
};
59
59
60
static struct iwmbt_devid iwmbt_list[] = {
60
static struct iwmbt_devid iwmbt_list_72xx[] = {
61
62
	/* Intel Wireless 7260/7265 and successors */
63
	{ .vendor_id = 0x8087, .product_id = 0x07dc },
64
	{ .vendor_id = 0x8087, .product_id = 0x0a2a },
65
	{ .vendor_id = 0x8087, .product_id = 0x0aa7 },
66
};
67
68
static struct iwmbt_devid iwmbt_list_82xx[] = {
61
69
62
	/* Intel Wireless 8260/8265 and successors */
70
	/* Intel Wireless 8260/8265 and successors */
63
	{ .vendor_id = 0x8087, .product_id = 0x0a2b },
71
	{ .vendor_id = 0x8087, .product_id = 0x0a2b },
Lines 67-81 static struct iwmbt_devid iwmbt_list[] = { Link Here
67
	{ .vendor_id = 0x8087, .product_id = 0x0029 },
75
	{ .vendor_id = 0x8087, .product_id = 0x0029 },
68
};
76
};
69
77
78
static int
79
iwmbt_is_7260(struct libusb_device_descriptor *d)
80
{
81
	int i;
82
83
	/* Search looking for whether it's an 7260/7265 */
84
	for (i = 0; i < (int) nitems(iwmbt_list_72xx); i++) {
85
		if ((iwmbt_list_72xx[i].product_id == d->idProduct) &&
86
		    (iwmbt_list_72xx[i].vendor_id == d->idVendor)) {
87
			iwmbt_info("found 7260/7265");
88
			return (1);
89
		}
90
	}
91
92
	/* Not found */
93
	return (0);
94
}
95
70
static int
96
static int
71
iwmbt_is_8260(struct libusb_device_descriptor *d)
97
iwmbt_is_8260(struct libusb_device_descriptor *d)
72
{
98
{
73
	int i;
99
	int i;
74
100
75
	/* Search looking for whether it's an 8260/8265 */
101
	/* Search looking for whether it's an 8260/8265 */
76
	for (i = 0; i < (int) nitems(iwmbt_list); i++) {
102
	for (i = 0; i < (int) nitems(iwmbt_list_82xx); i++) {
77
		if ((iwmbt_list[i].product_id == d->idProduct) &&
103
		if ((iwmbt_list_82xx[i].product_id == d->idProduct) &&
78
		    (iwmbt_list[i].vendor_id == d->idVendor)) {
104
		    (iwmbt_list_82xx[i].vendor_id == d->idVendor)) {
79
			iwmbt_info("found 8260/8265");
105
			iwmbt_info("found 8260/8265");
80
			return (1);
106
			return (1);
81
		}
107
		}
Lines 86-92 iwmbt_is_8260(struct libusb_device_descriptor *d) Link Here
86
}
112
}
87
113
88
static libusb_device *
114
static libusb_device *
89
iwmbt_find_device(libusb_context *ctx, int bus_id, int dev_id)
115
iwmbt_find_device(libusb_context *ctx, int bus_id, int dev_id,
116
    int *iwmbt_use_old_method)
90
{
117
{
91
	libusb_device **list, *dev = NULL, *found = NULL;
118
	libusb_device **list, *dev = NULL, *found = NULL;
92
	struct libusb_device_descriptor d;
119
	struct libusb_device_descriptor d;
Lines 116-126 iwmbt_find_device(libusb_context *ctx, int bus_id, int dev_id) Link Here
116
			}
143
			}
117
144
118
			/* Match on the vendor/product id */
145
			/* Match on the vendor/product id */
146
			if (iwmbt_is_7260(&d)) {
147
				/*
148
				 * Take a reference so it's not freed later on.
149
				 */
150
				found = libusb_ref_device(dev);
151
				*iwmbt_use_old_method = 1;
152
				break;
153
			} else
119
			if (iwmbt_is_8260(&d)) {
154
			if (iwmbt_is_8260(&d)) {
120
				/*
155
				/*
121
				 * Take a reference so it's not freed later on.
156
				 * Take a reference so it's not freed later on.
122
				 */
157
				 */
123
				found = libusb_ref_device(dev);
158
				found = libusb_ref_device(dev);
159
				*iwmbt_use_old_method = 0;
124
				break;
160
				break;
125
			}
161
			}
126
		}
162
		}
Lines 166-171 iwmbt_dump_boot_params(struct iwmbt_boot_params *params) Link Here
166
	    params->otp_bdaddr[0]);
202
	    params->otp_bdaddr[0]);
167
}
203
}
168
204
205
static int
206
iwmbt_patch_firmware(libusb_device_handle *hdl, const char *firmware_path)
207
{
208
	struct iwmbt_firmware fw;
209
	int ret;
210
211
	iwmbt_debug("loading %s", firmware_path);
212
213
	/* Read in the firmware */
214
	if (iwmbt_fw_read(&fw, firmware_path) <= 0) {
215
		iwmbt_debug("iwmbt_fw_read() failed");
216
		return (-1);
217
	}
218
219
	/* Load in the firmware */
220
	ret = iwmbt_patch_fwfile(hdl, &fw);
221
	if (ret < 0)
222
		iwmbt_debug("Loading firmware file failed");
223
224
	/* free it */
225
	iwmbt_fw_free(&fw);
226
227
	return (ret);
228
}
229
169
static int
230
static int
170
iwmbt_init_firmware(libusb_device_handle *hdl, const char *firmware_path,
231
iwmbt_init_firmware(libusb_device_handle *hdl, const char *firmware_path,
171
    uint32_t *boot_param)
232
    uint32_t *boot_param)
Lines 268-273 main(int argc, char *argv[]) Link Here
268
	char *firmware_dir = NULL;
329
	char *firmware_dir = NULL;
269
	char *firmware_path = NULL;
330
	char *firmware_path = NULL;
270
	int retcode = 1;
331
	int retcode = 1;
332
	int iwmbt_use_old_method = 0;
271
333
272
	/* Parse command line arguments */
334
	/* Parse command line arguments */
273
	while ((n = getopt(argc, argv, "Dd:f:hIm:p:v:")) != -1) {
335
	while ((n = getopt(argc, argv, "Dd:f:hIm:p:v:")) != -1) {
Lines 312-318 main(int argc, char *argv[]) Link Here
312
	iwmbt_debug("opening dev %d.%d", (int) bus_id, (int) dev_id);
374
	iwmbt_debug("opening dev %d.%d", (int) bus_id, (int) dev_id);
313
375
314
	/* Find a device based on the bus/dev id */
376
	/* Find a device based on the bus/dev id */
315
	dev = iwmbt_find_device(ctx, bus_id, dev_id);
377
	dev = iwmbt_find_device(ctx, bus_id, dev_id, &iwmbt_use_old_method);
316
	if (dev == NULL) {
378
	if (dev == NULL) {
317
		iwmbt_err("device not found");
379
		iwmbt_err("device not found");
318
		goto shutdown;
380
		goto shutdown;
Lines 344-430 main(int argc, char *argv[]) Link Here
344
	/* Get Intel version */
406
	/* Get Intel version */
345
	r = iwmbt_get_version(hdl, &ver);
407
	r = iwmbt_get_version(hdl, &ver);
346
	if (r < 0) {
408
	if (r < 0) {
347
		iwmbt_debug("iwmbt_get_version() failedL code %d", r);
409
		iwmbt_debug("iwmbt_get_version() failed code %d", r);
348
		goto shutdown;
410
		goto shutdown;
349
	}
411
	}
350
	iwmbt_dump_version(&ver);
412
	iwmbt_dump_version(&ver);
351
	iwmbt_debug("fw_variant=0x%02x", (int) ver.fw_variant);
413
	iwmbt_debug("fw_variant=0x%02x", (int) ver.fw_variant);
352
414
353
	/* fw_variant = 0x06 bootloader mode / 0x23 operational mode */
415
	if (iwmbt_use_old_method) {
354
	if (ver.fw_variant == 0x23) {
416
355
		iwmbt_info("Firmware has already been downloaded");
417
		/* fw_patch_num = >0 operational mode */
418
		if (ver.fw_patch_num > 0x00) {
419
			iwmbt_info("Firmware has already been downloaded");
420
			retcode = 0;
421
			goto reset;
422
		}
423
424
		/* Default the firmware path */
425
		if (firmware_dir == NULL)
426
			firmware_dir = strdup(_DEFAULT_IWMBT_FIRMWARE_PATH);
427
428
		firmware_path = iwmbt_get_fwname(&ver, &params, firmware_dir, "bseq");
429
		if (firmware_path == NULL)
430
			goto shutdown;
431
432
		iwmbt_debug("firmware_path = %s", firmware_path);
433
434
		/* Enter manufacturer mode */
435
		r = iwmbt_enter_manufacturer(hdl);
436
		if (r < 0) {
437
			iwmbt_debug("iwmbt_enter_manufacturer() failed code %d", r);
438
			goto shutdown;
439
		}
440
441
		/* Download firmware and parse it for magic Intel Reset parameter */
442
		r = iwmbt_patch_firmware(hdl, firmware_path);
443
		free(firmware_path);
444
		if (r < 0)
445
			goto shutdown;
446
447
		iwmbt_info("Firmware download complete");
448
449
		/* Exit manufacturer mode */
450
		r = iwmbt_exit_manufacturer(hdl, 0x02);
451
		if (r < 0) {
452
			iwmbt_debug("iwmbt_exit_manufacturer() failed code %d", r);
453
			goto shutdown;
454
		}
455
456
		/* Once device is running in operational mode we can ignore failures */
356
		retcode = 0;
457
		retcode = 0;
357
		goto reset;
358
	}
359
458
360
	if (ver.fw_variant != 0x06){
459
		/* Execute Read Intel Version one more time */
361
		iwmbt_err("unknown fw_variant 0x%02x", (int) ver.fw_variant);
460
		r = iwmbt_get_version(hdl, &ver);
362
		goto shutdown;
461
		if (r == 0)
363
	}
462
			iwmbt_dump_version(&ver);
364
463
365
	/* Read Intel Secure Boot Params */
464
		/* Set Intel Event mask */
366
	r = iwmbt_get_boot_params(hdl, &params);
465
		r = iwmbt_set_event_mask(hdl);
367
	if (r < 0) {
466
		if (r == 0)
368
		iwmbt_debug("iwmbt_get_boot_params() failed!");
467
			iwmbt_info("Intel Event Mask is set");
369
		goto shutdown;
370
	}
371
	iwmbt_dump_boot_params(&params);
372
468
373
	/* Check if firmware fragments are ACKed with a cmd complete event */
469
	} else {
374
	if (params.limited_cce != 0x00) {
375
		iwmbt_err("Unsupported Intel firmware loading method (%u)",
376
		   params.limited_cce);
377
		goto shutdown;
378
	}
379
470
380
	/* Default the firmware path */
471
		/* fw_variant = 0x06 bootloader mode / 0x23 operational mode */
381
	if (firmware_dir == NULL)
472
		if (ver.fw_variant == 0x23) {
382
		firmware_dir = strdup(_DEFAULT_IWMBT_FIRMWARE_PATH);
473
			iwmbt_info("Firmware has already been downloaded");
474
			retcode = 0;
475
			goto reset;
476
		}
383
477
384
	firmware_path = iwmbt_get_fwname(&ver, &params, firmware_dir, "sfi");
478
		if (ver.fw_variant != 0x06){
385
	if (firmware_path == NULL)
479
			iwmbt_err("unknown fw_variant 0x%02x", (int) ver.fw_variant);
386
		goto shutdown;
480
			goto shutdown;
481
		}
387
482
388
	iwmbt_debug("firmware_path = %s", firmware_path);
483
		/* Read Intel Secure Boot Params */
484
		r = iwmbt_get_boot_params(hdl, &params);
485
		if (r < 0) {
486
			iwmbt_debug("iwmbt_get_boot_params() failed!");
487
			goto shutdown;
488
		}
489
		iwmbt_dump_boot_params(&params);
389
490
390
	/* Download firmware and parse it for magic Intel Reset parameter */
491
		/* Check if firmware fragments are ACKed with a cmd complete event */
391
	r = iwmbt_init_firmware(hdl, firmware_path, &boot_param);
492
		if (params.limited_cce != 0x00) {
392
	free(firmware_path);
493
			iwmbt_err("Unsupported Intel firmware loading method (%u)",
393
	if (r < 0)
494
			   params.limited_cce);
394
		goto shutdown;
495
			goto shutdown;
496
		}
395
497
396
	iwmbt_info("Firmware download complete");
498
		/* Default the firmware path */
499
		if (firmware_dir == NULL)
500
			firmware_dir = strdup(_DEFAULT_IWMBT_FIRMWARE_PATH);
397
501
398
	r = iwmbt_intel_reset(hdl, boot_param);
502
		firmware_path = iwmbt_get_fwname(&ver, &params, firmware_dir, "sfi");
399
	if (r < 0) {
503
		if (firmware_path == NULL)
400
		iwmbt_debug("iwmbt_intel_reset() failed!");
504
			goto shutdown;
401
		goto shutdown;
402
	}
403
505
404
	iwmbt_info("Firmware operational");
506
		iwmbt_debug("firmware_path = %s", firmware_path);
405
507
406
	/* Once device is running in operational mode we can ignore failures */
508
		/* Download firmware and parse it for magic Intel Reset parameter */
407
	retcode = 0;
509
		r = iwmbt_init_firmware(hdl, firmware_path, &boot_param);
510
		free(firmware_path);
511
		if (r < 0)
512
			goto shutdown;
408
513
409
	/* Execute Read Intel Version one more time */
514
		iwmbt_info("Firmware download complete");
410
	r = iwmbt_get_version(hdl, &ver);
515
411
	if (r == 0)
516
		r = iwmbt_intel_reset(hdl, boot_param);
412
		iwmbt_dump_version(&ver);
517
		if (r < 0) {
413
518
			iwmbt_debug("iwmbt_intel_reset() failed!");
414
	/* Apply the device configuration (DDC) parameters */
519
			goto shutdown;
415
	firmware_path = iwmbt_get_fwname(&ver, &params, firmware_dir, "ddc");
520
		}
416
	iwmbt_debug("ddc_path = %s", firmware_path);
521
417
	if (firmware_path != NULL) {
522
		iwmbt_info("Firmware operational");
418
		r = iwmbt_init_ddc(hdl, firmware_path);
523
524
		/* Once device is running in operational mode we can ignore failures */
525
		retcode = 0;
526
527
		/* Execute Read Intel Version one more time */
528
		r = iwmbt_get_version(hdl, &ver);
419
		if (r == 0)
529
		if (r == 0)
420
			iwmbt_info("DDC download complete");
530
			iwmbt_dump_version(&ver);
421
		free(firmware_path);
531
422
	}
532
		/* Apply the device configuration (DDC) parameters */
533
		firmware_path = iwmbt_get_fwname(&ver, &params, firmware_dir, "ddc");
534
		iwmbt_debug("ddc_path = %s", firmware_path);
535
		if (firmware_path != NULL) {
536
			r = iwmbt_init_ddc(hdl, firmware_path);
537
			if (r == 0)
538
				iwmbt_info("DDC download complete");
539
			free(firmware_path);
540
		}
423
541
424
	/* Set Intel Event mask */
542
		/* Set Intel Event mask */
425
	r = iwmbt_set_event_mask(hdl);
543
		r = iwmbt_set_event_mask(hdl);
426
	if (r == 0)
544
		if (r == 0)
427
		iwmbt_info("Intel Event Mask is set");
545
			iwmbt_info("Intel Event Mask is set");
546
	}
428
547
429
reset:
548
reset:
430
549

Return to bug 228787