xref: /btstack/chipset/intel/btstack_chipset_intel_firmware.c (revision 80e33422a96c028b3a9c308fc4b9b874712dafb4)
1 #define __BTSTACK_FILE__ "btstack_chipset_intel_firmware.c"
2 
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 
7 #include "btstack_chipset_intel_firmware.h"
8 #include "hci_cmd.h"
9 #include "bluetooth.h"
10 #include "hci_dump.h"
11 #include "btstack_event.h"
12 #include "btstack_debug.h"
13 #include "btstack_util.h"
14 #include "btstack_run_loop.h"
15 
16 // Vendor specific structs
17 
18 typedef struct {
19     uint8_t status;
20     uint8_t hw_platform;
21     uint8_t hw_variant;
22     uint8_t hw_revision;
23     uint8_t fw_variant;
24     uint8_t fw_revision;
25     uint8_t fw_build_num;
26     uint8_t fw_build_ww;
27     uint8_t fw_build_yy;
28     uint8_t fw_patch_num;
29 } intel_version_t;
30 
31 typedef struct {
32     uint8_t     status;
33     uint8_t     otp_format;
34     uint8_t     otp_content;
35     uint8_t     otp_patch;
36     uint16_t    dev_revid;
37     uint8_t     secure_boot;
38     uint8_t     key_from_hdr;
39     uint8_t     key_type;
40     uint8_t     otp_lock;
41     uint8_t     api_lock;
42     uint8_t     debug_lock;
43     bd_addr_t   otp_bdaddr;
44     uint8_t     min_fw_build_nn;
45     uint8_t     min_fw_build_cw;
46     uint8_t     min_fw_build_yy;
47     uint8_t     limited_cce;
48     uint8_t     unlocked_state;
49 } intel_boot_params_t;
50 
51 // Vendor sepcific commands
52 
53 static const hci_cmd_t hci_intel_read_version = {
54     0xfc05, ""
55 };
56 static const hci_cmd_t hci_intel_read_secure_boot_params = {
57     0xfc0d, ""
58 };
59 
60 static const hci_cmd_t hci_intel_reset_param = {
61     0xfc01, "11111111"
62 };
63 
64 static const hci_cmd_t hci_intel_set_event_mask = {
65     0xfc52, "11111111"
66 };
67 
68 static const hci_cmd_t hci_intel_fc9f = {
69     0xfc9f, "1"
70 };
71 
72 // state
73 
74 const char * firmware_path = ".";
75 
76 const hci_transport_t * transport;
77 
78 static int state = 0;
79 
80 static uint8_t hci_outgoing[300];
81 static uint8_t fw_buffer[300];
82 
83 static uint8_t  hw_variant;
84 static uint16_t dev_revid;
85 
86 static FILE *   fw_file;
87 static uint32_t fw_offset;
88 
89 static void (*done)(int result);
90 
91 // functions
92 
93 static int transport_send_packet(uint8_t packet_type, const uint8_t * packet, uint16_t size){
94     hci_dump_packet(HCI_COMMAND_DATA_PACKET, 0, (uint8_t*) packet, size);
95     return transport->send_packet(packet_type, (uint8_t *) packet, size);
96 }
97 
98 static int transport_send_cmd_va_arg(const hci_cmd_t *cmd, va_list argptr){
99     uint8_t * packet = hci_outgoing;
100     uint16_t size = hci_cmd_create_from_template(packet, cmd, argptr);
101     return transport_send_packet(HCI_COMMAND_DATA_PACKET, packet, size);
102 }
103 
104 static int transport_send_cmd(const hci_cmd_t *cmd, ...){
105     va_list argptr;
106     va_start(argptr, cmd);
107     int res = transport_send_cmd_va_arg(cmd, argptr);
108     va_end(argptr);
109     return res;
110 }
111 
112 static int transport_send_intel_secure(uint8_t fragment_type, const uint8_t * data, uint16_t len){
113     little_endian_store_16(hci_outgoing, 0, 0xfc09);
114     hci_outgoing[2] = 1 + len;
115     hci_outgoing[3] = fragment_type;
116     memcpy(&hci_outgoing[4], data, len);
117     uint16_t size = 3 +  1 + len;
118     return transport_send_packet(HCI_ACL_DATA_PACKET, hci_outgoing, size);
119 }
120 
121 static int transport_send_intel_ddc(const uint8_t * data, uint16_t len){
122     little_endian_store_16(hci_outgoing, 0, 0xfc8b);
123     hci_outgoing[2] = len;
124     memcpy(&hci_outgoing[3], data, len);
125     uint16_t size = 3 +  len;
126     return transport_send_packet(HCI_COMMAND_DATA_PACKET, hci_outgoing, size);
127 }
128 
129 static void state_machine(uint8_t * packet);
130 
131 // read data from fw file and send it via intel_secure + update state
132 static int intel_send_fragment(uint8_t fragment_type, uint16_t len){
133     int res = fread(fw_buffer, 1, len, fw_file);
134     log_info("offset %6u, read %3u -> res %d", fw_offset, len, res);
135     fw_offset += res;
136     state++;
137     return transport_send_intel_secure(fragment_type, fw_buffer, len);
138 }
139 
140 // read data from  ddc file and send iva intel ddc command
141 // @returns -1 on eof
142 static int intel_send_ddc(void){
143     int res;
144     // read len
145     res = fread(fw_buffer, 1, 1, fw_file);
146     log_info("offset %6u, read 1 -> res %d", fw_offset, res);
147     if (res == 0) return -1;
148     uint8_t len = fw_buffer[0];
149     fw_offset += 1;
150     res = fread(&fw_buffer[1], 1, len, fw_file);
151     log_info("offset %6u, read %u -> res %d", fw_offset, 1, res);
152     return transport_send_intel_ddc(fw_buffer, 1 + len);
153 }
154 
155 static void dump_intel_version(intel_version_t     * version){
156     log_info("status       0x%02x", version->status);
157     log_info("hw_platform  0x%02x", version->hw_platform);
158     log_info("hw_variant   0x%02x", version->hw_variant);
159     log_info("hw_revision  0x%02x", version->hw_revision);
160     log_info("fw_variant   0x%02x", version->fw_variant);
161     log_info("fw_revision  0x%02x", version->fw_revision);
162     log_info("fw_build_num 0x%02x", version->fw_build_num);
163     log_info("fw_build_ww  0x%02x", version->fw_build_ww);
164     log_info("fw_build_yy  0x%02x", version->fw_build_yy);
165     log_info("fw_patch_num 0x%02x", version->fw_patch_num);
166 }
167 
168 static void dump_intel_boot_params(intel_boot_params_t * boot_params){
169     bd_addr_t addr;
170     reverse_bd_addr(boot_params->otp_bdaddr, addr);
171     log_info("Device revision: %u", dev_revid);
172     log_info("Secure Boot:  %s", boot_params->secure_boot ? "enabled" : "disabled");
173     log_info("OTP lock:     %s", boot_params->otp_lock    ? "enabled" : "disabled");
174     log_info("API lock:     %s", boot_params->api_lock    ? "enabled" : "disabled");
175     log_info("Debug lock:   %s", boot_params->debug_lock  ? "enabled" : "disabled");
176     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);
177     log_info("OTC BD_ADDR:  %s", bd_addr_to_str(addr));
178 }
179 
180 static int vendor_firmware_complete_received;
181 static int waiting_for_command_complete;
182 
183 static void state_machine(uint8_t * packet){
184     intel_version_t     * version;
185     intel_boot_params_t * boot_params;
186     int res;
187     uint16_t buffer_offset;
188     bd_addr_t addr;
189     char    fw_path[300];
190 
191     if (packet){
192         // firmware upload complete event?
193         if (packet[0] == 0xff && packet[2] == 0x06) {
194             vendor_firmware_complete_received = 1;
195         }
196 
197         // command complete
198         if (packet[0] == 0x0e){
199             waiting_for_command_complete = 0;
200         }
201     }
202 
203     switch (state){
204         case 0:
205             state++;
206             transport_send_cmd(&hci_reset);
207             break;
208         case 1:
209             // check if HCI Reset was supported
210             if (packet[0] == 0x0e && packet[1] == 0x04 && packet[3] == 0x03 && packet[4] == 0x0c && packet[5] == 0x00){
211                 log_info("HCI Reset was successful, no need for firmware upload / or not an Intel chipset");
212                 (*done)(0);
213                 break;
214             }
215 
216             // Read Intel Version
217             state++;
218             transport_send_cmd(&hci_intel_read_version);
219             break;
220         case 2:
221             version = (intel_version_t*) hci_event_command_complete_get_return_parameters(packet);
222             dump_intel_version(version);
223 
224             hw_variant = version->hw_variant;
225 
226             // fw_variant = 0x06 bootloader mode / 0x23 operational mode
227             if (version->fw_variant == 0x23) {
228                 (*done)(0);
229                 break;
230             }
231 
232             if (version->fw_variant != 0x06){
233                 log_error("unknown fw_variant 0x%02x", version->fw_variant);
234                 break;
235             }
236 
237             // Read Intel Secure Boot Params
238             state++;
239             transport_send_cmd(&hci_intel_read_secure_boot_params);
240             break;
241         case 3:
242             boot_params = (intel_boot_params_t *) hci_event_command_complete_get_return_parameters(packet);
243             dump_intel_boot_params(boot_params);
244 
245             reverse_bd_addr(boot_params->otp_bdaddr, addr);
246             dev_revid = little_endian_read_16((uint8_t*)&boot_params->dev_revid, 0);
247 
248             // assert commmand complete is required
249             if (boot_params->limited_cce != 0) break;
250 
251             // firmware file
252             snprintf(fw_path, sizeof(fw_path), "%s/ibt-%u-%u.sfi", firmware_path, hw_variant, dev_revid);
253             log_info("Open firmware %s", fw_path);
254             printf("Firwmare %s\n", fw_path);
255 
256             // open firmware file
257             fw_offset = 0;
258             fw_file = fopen(fw_path, "rb");
259             if (!fw_file){
260                 log_error("can't open file %s", fw_path);
261                 (*done)(1);
262                 return;
263             }
264 
265             vendor_firmware_complete_received = 0;
266 
267             // send CCS segment - offset 0
268             intel_send_fragment(0x00, 128);
269             break;
270         case 4:
271             // send public key / part 1 - offset 128
272             intel_send_fragment(0x03, 128);
273             break;
274         case 5:
275             // send public key / part 2 - offset 384
276             intel_send_fragment(0x03, 128);
277             break;
278         case 6:
279             // skip 4 bytes
280             res = fread(fw_buffer, 1, 4, fw_file);
281             log_info("read res %d", res);
282             fw_offset += res;
283 
284             // send signature / part 1 - offset 388
285             intel_send_fragment(0x02, 128);
286             break;
287         case 7:
288             // send signature / part 2 - offset 516
289             intel_send_fragment(0x02, 128);
290             break;
291         case 8:
292             // send firmware chunks - offset 644
293             // chunk len must be 4 byte aligned
294             // multiple commands can be combined
295             buffer_offset = 0;
296             do {
297                 res = fread(&fw_buffer[buffer_offset], 1, 3, fw_file);
298                 log_info("fw_offset %6u, buffer_offset %u, read %3u -> res %d", fw_offset, buffer_offset, 3, res);
299                 fw_offset += res;
300                 if (res == 0 ){
301                     // EOF
302                     log_info("End of file");
303                     fclose(fw_file);
304                     fw_file = NULL;
305                     state++;
306                     break;
307                 }
308                 int param_len = fw_buffer[buffer_offset + 2];
309                 buffer_offset += 3;
310                 if (param_len){
311                     res = fread(&fw_buffer[buffer_offset], 1, param_len, fw_file);
312                     fw_offset     += res;
313                     buffer_offset += res;
314                 }
315             } while ((buffer_offset & 3) != 0);
316 
317             if (buffer_offset == 0) break;
318 
319             waiting_for_command_complete = 1;
320             transport_send_intel_secure(0x01, fw_buffer, buffer_offset);
321             break;
322 
323         case 9:
324             // expect Vendor Specific Event 0x06
325             if (!vendor_firmware_complete_received) break;
326 
327             printf("Firmware upload complete\n");
328             log_info("Vendor Event 0x06 - firmware complete");
329 
330             // Reset Params - constants from Windows Intel driver
331             state++;
332             transport_send_cmd(&hci_intel_reset_param, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x04, 0x00);
333             break;
334 
335         case 10:
336             // expect Vendor Specific Event 0x02
337             if (packet[0] != 0xff) break;
338             if (packet[2] != 0x02) break;
339 
340             printf("Firmware operational\n");
341             log_info("Vendor Event 0x02 - firmware operational");
342 
343             // Read Intel Version
344             state++;
345             transport_send_cmd(&hci_intel_read_version);
346             break;
347 
348         case 11:
349             version = (intel_version_t*) hci_event_command_complete_get_return_parameters(packet);
350             dump_intel_version(version);
351 
352             // ddc config
353             snprintf(fw_path, sizeof(fw_path), "%s/ibt-%u-%u.ddc", firmware_path, hw_variant, dev_revid);
354             log_info("Open DDC %s", fw_path);
355 
356             // open ddc file
357             fw_offset = 0;
358             fw_file = fopen(fw_path, "rb");
359             if (!fw_file){
360                 log_error("can't open file %s", fw_path);
361 
362                 (*done)(1);
363                 return;
364             }
365 
366             // load ddc
367             state++;
368 
369             /* fall through */
370 
371         case 12:
372             res = intel_send_ddc();
373             if (res == 0) break;
374 
375             // DDC download complete
376             state++;
377             log_info("Load DDC Complete");
378 
379 
380             // Set Intel event mask 0xfc52
381             state++;
382             transport_send_cmd(&hci_intel_set_event_mask, 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
383             break;
384 
385         case 13:
386             // 9F FC 01 00
387             state++;
388             transport_send_cmd(&hci_intel_fc9f, 0x00);
389             break;
390 
391         case 14:
392             (*done)(0);
393             break;
394 
395         default:
396             break;
397     }
398 }
399 
400 static void transport_packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){
401     UNUSED(packet_type);
402     // we also get events with packet_type ACL from the controller
403     hci_dump_packet(HCI_EVENT_PACKET, 1, packet, size);
404     switch (hci_event_packet_get_type(packet)){
405         case HCI_EVENT_COMMAND_COMPLETE:
406         case HCI_EVENT_VENDOR_SPECIFIC:
407             state_machine(packet);
408             break;
409         default:
410             break;
411     }
412 }
413 
414 void btstack_chipset_intel_set_firmware_path(const char * path){
415     firmware_path = path;
416 }
417 
418 void btstack_chipset_intel_download_firmware(const hci_transport_t * hci_transport, void (*callback)(int result)){
419 
420     done = callback;
421 
422 	transport = hci_transport;;
423     // transport->init(NULL);
424     transport->register_packet_handler(&transport_packet_handler);
425     transport->open();
426 
427     // get started
428     state = 0;
429     state_machine(NULL);
430 }
431