xref: /btstack/chipset/intel/btstack_chipset_intel_firmware.c (revision c435f47b63025db89c42b8ffaaa28b0cfbdcce6e)
1 /*
2  * Copyright (C) 2018 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define BTSTACK_FILE__ "btstack_chipset_intel_firmware.c"
39 
40 #include <fcntl.h>
41 #include <stdio.h>
42 
43 #include "btstack_chipset_intel_firmware.h"
44 
45 #include "bluetooth.h"
46 #include "btstack_debug.h"
47 #include "btstack_event.h"
48 #include "btstack_run_loop.h"
49 #include "btstack_util.h"
50 #include "hci.h"
51 #include "hci_cmd.h"
52 #include "hci_dump.h"
53 
54 #ifdef _MSC_VER
55  // ignore deprecated warning for fopen
56 #pragma warning(disable : 4996)
57 #endif
58 
59 // assert outgoing and incoming hci packet buffers can hold max hci command resp. event packet
60 #if HCI_OUTGOING_PACKET_BUFFER_SIZE < (HCI_CMD_HEADER_SIZE + 255)
61 #error "HCI_OUTGOING_PACKET_BUFFER_SIZE to small. Outgoing HCI packet buffer to small for largest HCI Command packet. Please set HCI_ACL_PAYLOAD_SIZE to 258 or higher."
62 #endif
63 #if HCI_INCOMING_PACKET_BUFFER_SIZE < (HCI_EVENT_HEADER_SIZE_HEADER_SIZE + 255)
64 #error "HCI_INCOMING_PACKET_BUFFER_SIZE to small. Incoming HCI packet buffer to small for largest HCI Event packet. Please set HCI_ACL_PAYLOAD_SIZE to 257 or higher."
65 #endif
66 
67 // Vendor specific structs
68 
69 typedef struct {
70     uint8_t status;
71     uint8_t hw_platform;
72     uint8_t hw_variant;
73     uint8_t hw_revision;
74     uint8_t fw_variant;
75     uint8_t fw_revision;
76     uint8_t fw_build_num;
77     uint8_t fw_build_ww;
78     uint8_t fw_build_yy;
79     uint8_t fw_patch_num;
80 } intel_version_t;
81 
82 typedef struct {
83     uint8_t     status;
84     uint8_t     otp_format;
85     uint8_t     otp_content;
86     uint8_t     otp_patch;
87     uint16_t    dev_revid;
88     uint8_t     secure_boot;
89     uint8_t     key_from_hdr;
90     uint8_t     key_type;
91     uint8_t     otp_lock;
92     uint8_t     api_lock;
93     uint8_t     debug_lock;
94     bd_addr_t   otp_bdaddr;
95     uint8_t     min_fw_build_nn;
96     uint8_t     min_fw_build_cw;
97     uint8_t     min_fw_build_yy;
98     uint8_t     limited_cce;
99     uint8_t     unlocked_state;
100 } intel_boot_params_t;
101 
102 // Vendor sepcific commands
103 
104 static const hci_cmd_t hci_intel_read_version = {
105     0xfc05, ""
106 };
107 static const hci_cmd_t hci_intel_read_secure_boot_params = {
108     0xfc0d, ""
109 };
110 
111 static const hci_cmd_t hci_intel_reset_param = {
112     0xfc01, "11111111"
113 };
114 
115 static const hci_cmd_t hci_intel_set_event_mask = {
116     0xfc52, "11111111"
117 };
118 
119 static const hci_cmd_t hci_intel_fc9f = {
120     0xfc9f, "1"
121 };
122 
123 // state
124 
125 const char * firmware_path = ".";
126 
127 const hci_transport_t * transport;
128 
129 static int state = 0;
130 
131 static uint8_t hci_outgoing[300];
132 static uint8_t fw_buffer[300];
133 
134 static uint8_t  hw_variant;
135 static uint16_t dev_revid;
136 
137 static FILE *   fw_file;
138 static size_t   fw_offset;
139 
140 static void (*done)(int result);
141 
142 // functions
143 
144 static int transport_send_packet(uint8_t packet_type, const uint8_t * packet, uint16_t size){
145     hci_dump_packet(HCI_COMMAND_DATA_PACKET, 0, (uint8_t*) packet, size);
146     return transport->send_packet(packet_type, (uint8_t *) packet, size);
147 }
148 
149 static int transport_send_cmd_va_arg(const hci_cmd_t *cmd, va_list argptr){
150     uint8_t * packet = hci_outgoing;
151     uint16_t size = hci_cmd_create_from_template(packet, cmd, argptr);
152     return transport_send_packet(HCI_COMMAND_DATA_PACKET, packet, size);
153 }
154 
155 static int transport_send_cmd(const hci_cmd_t *cmd, ...){
156     va_list argptr;
157     va_start(argptr, cmd);
158     int res = transport_send_cmd_va_arg(cmd, argptr);
159     va_end(argptr);
160     return res;
161 }
162 
163 static int transport_send_intel_secure(uint8_t fragment_type, const uint8_t * data, uint8_t len){
164     little_endian_store_16(hci_outgoing, 0, 0xfc09);
165     hci_outgoing[2] = 1 + len;
166     hci_outgoing[3] = fragment_type;
167     memcpy(&hci_outgoing[4], data, len);
168     uint16_t size = 3 +  1 + len;
169     return transport_send_packet(HCI_ACL_DATA_PACKET, hci_outgoing, size);
170 }
171 
172 static int transport_send_intel_ddc(const uint8_t * data, uint8_t len){
173     little_endian_store_16(hci_outgoing, 0, 0xfc8b);
174     hci_outgoing[2] = len;
175     memcpy(&hci_outgoing[3], data, len);
176     uint16_t size = 3 +  len;
177     return transport_send_packet(HCI_COMMAND_DATA_PACKET, hci_outgoing, size);
178 }
179 
180 static void state_machine(uint8_t * packet);
181 
182 // read data from fw file and send it via intel_secure + update state
183 static int intel_send_fragment(uint8_t fragment_type, uint8_t len){
184     size_t res = fread(fw_buffer, 1, len, fw_file);
185     log_info("offset %6u, read %3u -> res %d", fw_offset, len, res);
186     fw_offset += res;
187     state++;
188     return transport_send_intel_secure(fragment_type, fw_buffer, len);
189 }
190 
191 // read data from  ddc file and send iva intel ddc command
192 // @returns -1 on eof
193 static int intel_send_ddc(void){
194     size_t res;
195     // read len
196     res = fread(fw_buffer, 1, 1, fw_file);
197     log_info("offset %6u, read 1 -> res %d", fw_offset, res);
198     if (res == 0) return -1;
199     uint8_t len = fw_buffer[0];
200     fw_offset += 1;
201     res = fread(&fw_buffer[1], 1, len, fw_file);
202     log_info("offset %6u, read %u -> res %d", fw_offset, 1, res);
203     return transport_send_intel_ddc(fw_buffer, 1 + len);
204 }
205 
206 static void dump_intel_version(intel_version_t     * version){
207     log_info("status       0x%02x", version->status);
208     log_info("hw_platform  0x%02x", version->hw_platform);
209     log_info("hw_variant   0x%02x", version->hw_variant);
210     log_info("hw_revision  0x%02x", version->hw_revision);
211     log_info("fw_variant   0x%02x", version->fw_variant);
212     log_info("fw_revision  0x%02x", version->fw_revision);
213     log_info("fw_build_num 0x%02x", version->fw_build_num);
214     log_info("fw_build_ww  0x%02x", version->fw_build_ww);
215     log_info("fw_build_yy  0x%02x", version->fw_build_yy);
216     log_info("fw_patch_num 0x%02x", version->fw_patch_num);
217 }
218 
219 static void dump_intel_boot_params(intel_boot_params_t * boot_params){
220     bd_addr_t addr;
221     reverse_bd_addr(boot_params->otp_bdaddr, addr);
222     log_info("Device revision: %u", dev_revid);
223     log_info("Secure Boot:  %s", boot_params->secure_boot ? "enabled" : "disabled");
224     log_info("OTP lock:     %s", boot_params->otp_lock    ? "enabled" : "disabled");
225     log_info("API lock:     %s", boot_params->api_lock    ? "enabled" : "disabled");
226     log_info("Debug lock:   %s", boot_params->debug_lock  ? "enabled" : "disabled");
227     log_info("Minimum firmware build %u week %u %u", boot_params->min_fw_build_nn, boot_params->min_fw_build_cw, 2000 + boot_params->min_fw_build_yy);
228     log_info("OTC BD_ADDR:  %s", bd_addr_to_str(addr));
229 }
230 
231 static int vendor_firmware_complete_received;
232 static int waiting_for_command_complete;
233 
234 static void state_machine(uint8_t * packet){
235     intel_version_t     * version;
236     intel_boot_params_t * boot_params;
237     size_t res;
238     size_t buffer_offset;
239     bd_addr_t addr;
240     char    fw_path[300];
241 
242     if (packet){
243         // firmware upload complete event?
244         if (packet[0] == 0xff && packet[2] == 0x06) {
245             vendor_firmware_complete_received = 1;
246         }
247 
248         // command complete
249         if (packet[0] == 0x0e){
250             waiting_for_command_complete = 0;
251         }
252     }
253 
254     switch (state){
255         case 0:
256             state++;
257             transport_send_cmd(&hci_reset);
258             break;
259         case 1:
260             // check if HCI Reset was supported
261             if (packet[0] == 0x0e && packet[1] == 0x04 && packet[3] == 0x03 && packet[4] == 0x0c && packet[5] == 0x00){
262                 log_info("HCI Reset was successful, no need for firmware upload / or not an Intel chipset");
263                 (*done)(0);
264                 break;
265             }
266 
267             // Read Intel Version
268             state++;
269             transport_send_cmd(&hci_intel_read_version);
270             break;
271         case 2:
272             version = (intel_version_t*) hci_event_command_complete_get_return_parameters(packet);
273             dump_intel_version(version);
274 
275             hw_variant = version->hw_variant;
276 
277             // fw_variant = 0x06 bootloader mode / 0x23 operational mode
278             if (version->fw_variant == 0x23) {
279                 (*done)(0);
280                 break;
281             }
282 
283             if (version->fw_variant != 0x06){
284                 log_error("unknown fw_variant 0x%02x", version->fw_variant);
285                 break;
286             }
287 
288             // Read Intel Secure Boot Params
289             state++;
290             transport_send_cmd(&hci_intel_read_secure_boot_params);
291             break;
292         case 3:
293             boot_params = (intel_boot_params_t *) hci_event_command_complete_get_return_parameters(packet);
294             dump_intel_boot_params(boot_params);
295 
296             reverse_bd_addr(boot_params->otp_bdaddr, addr);
297             dev_revid = little_endian_read_16((uint8_t*)&boot_params->dev_revid, 0);
298 
299             // assert commmand complete is required
300             if (boot_params->limited_cce != 0) break;
301 
302             // firmware file
303             snprintf(fw_path, sizeof(fw_path), "%s/ibt-%u-%u.sfi", firmware_path, hw_variant, dev_revid);
304             log_info("Open firmware %s", fw_path);
305             printf("Firwmare %s\n", fw_path);
306 
307             // open firmware file
308             fw_offset = 0;
309             fw_file = fopen(fw_path, "rb");
310             if (!fw_file){
311                 log_error("can't open file %s", fw_path);
312                 (*done)(1);
313                 return;
314             }
315 
316             vendor_firmware_complete_received = 0;
317 
318             // send CCS segment - offset 0
319             intel_send_fragment(0x00, 128);
320             break;
321         case 4:
322             // send public key / part 1 - offset 128
323             intel_send_fragment(0x03, 128);
324             break;
325         case 5:
326             // send public key / part 2 - offset 384
327             intel_send_fragment(0x03, 128);
328             break;
329         case 6:
330             // skip 4 bytes
331             res = fread(fw_buffer, 1, 4, fw_file);
332             log_info("read res %d", res);
333             fw_offset += res;
334 
335             // send signature / part 1 - offset 388
336             intel_send_fragment(0x02, 128);
337             break;
338         case 7:
339             // send signature / part 2 - offset 516
340             intel_send_fragment(0x02, 128);
341             break;
342         case 8:
343             // send firmware chunks - offset 644
344             // chunk len must be 4 byte aligned
345             // multiple commands can be combined
346             buffer_offset = 0;
347             do {
348                 res = fread(&fw_buffer[buffer_offset], 1, 3, fw_file);
349                 log_info("fw_offset %6u, buffer_offset %u, read %3u -> res %d", fw_offset, buffer_offset, 3, res);
350                 fw_offset += res;
351                 if (res == 0 ){
352                     // EOF
353                     log_info("End of file");
354                     fclose(fw_file);
355                     fw_file = NULL;
356                     state++;
357                     break;
358                 }
359                 int param_len = fw_buffer[buffer_offset + 2];
360                 buffer_offset += 3;
361                 if (param_len){
362                     res = fread(&fw_buffer[buffer_offset], 1, param_len, fw_file);
363                     fw_offset     += res;
364                     buffer_offset += res;
365                 }
366             } while ((buffer_offset & 3) != 0);
367 
368             if (buffer_offset == 0) break;
369 
370             waiting_for_command_complete = 1;
371             transport_send_intel_secure(0x01, fw_buffer, (uint8_t) buffer_offset);
372             break;
373 
374         case 9:
375             // expect Vendor Specific Event 0x06
376             if (!vendor_firmware_complete_received) break;
377 
378             printf("Firmware upload complete\n");
379             log_info("Vendor Event 0x06 - firmware complete");
380 
381             // Reset Params - constants from Windows Intel driver
382             state++;
383             transport_send_cmd(&hci_intel_reset_param, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x04, 0x00);
384             break;
385 
386         case 10:
387             // expect Vendor Specific Event 0x02
388             if (packet[0] != 0xff) break;
389             if (packet[2] != 0x02) break;
390 
391             printf("Firmware operational\n");
392             log_info("Vendor Event 0x02 - firmware operational");
393 
394             // Read Intel Version
395             state++;
396             transport_send_cmd(&hci_intel_read_version);
397             break;
398 
399         case 11:
400             version = (intel_version_t*) hci_event_command_complete_get_return_parameters(packet);
401             dump_intel_version(version);
402 
403             // ddc config
404             snprintf(fw_path, sizeof(fw_path), "%s/ibt-%u-%u.ddc", firmware_path, hw_variant, dev_revid);
405             log_info("Open DDC %s", fw_path);
406 
407             // open ddc file
408             fw_offset = 0;
409             fw_file = fopen(fw_path, "rb");
410             if (!fw_file){
411                 log_error("can't open file %s", fw_path);
412 
413                 (*done)(1);
414                 return;
415             }
416 
417             // load ddc
418             state++;
419 
420             /* fall through */
421 
422         case 12:
423             res = intel_send_ddc();
424             if (res == 0) break;
425 
426             // DDC download complete
427             state++;
428             log_info("Load DDC Complete");
429 
430 
431             // Set Intel event mask 0xfc52
432             state++;
433             transport_send_cmd(&hci_intel_set_event_mask, 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
434             break;
435 
436         case 13:
437             // 9F FC 01 00
438             state++;
439             transport_send_cmd(&hci_intel_fc9f, 0x00);
440             break;
441 
442         case 14:
443             (*done)(0);
444             break;
445 
446         default:
447             break;
448     }
449 }
450 
451 static void transport_packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){
452     UNUSED(packet_type);
453     // we also get events with packet_type ACL from the controller
454     hci_dump_packet(HCI_EVENT_PACKET, 1, packet, size);
455     switch (hci_event_packet_get_type(packet)){
456         case HCI_EVENT_COMMAND_COMPLETE:
457         case HCI_EVENT_VENDOR_SPECIFIC:
458             state_machine(packet);
459             break;
460         default:
461             break;
462     }
463 }
464 
465 void btstack_chipset_intel_set_firmware_path(const char * path){
466     firmware_path = path;
467 }
468 
469 void btstack_chipset_intel_download_firmware(const hci_transport_t * hci_transport, void (*callback)(int result)){
470 
471     done = callback;
472 
473 	transport = hci_transport;;
474     // transport->init(NULL);
475     transport->register_packet_handler(&transport_packet_handler);
476     transport->open();
477 
478     // get started
479     state = 0;
480     state_machine(NULL);
481 }
482