1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132#include <linux/firmware.h>
133#include <linux/sched.h>
134#include <linux/usb.h>
135#include "i2400m.h"
136
137
138#define D_SUBMODULE fw
139#include "debug-levels.h"
140
141
142static const __le32 i2400m_ACK_BARKER[4] = {
143 cpu_to_le32(I2400M_ACK_BARKER),
144 cpu_to_le32(I2400M_ACK_BARKER),
145 cpu_to_le32(I2400M_ACK_BARKER),
146 cpu_to_le32(I2400M_ACK_BARKER)
147};
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *cmd)
163{
164 if (i2400m_brh_get_use_checksum(cmd)) {
165 int i;
166 u32 checksum = 0;
167 const u32 *checksum_ptr = (void *) cmd->payload;
168 for (i = 0; i < cmd->data_size / 4; i++)
169 checksum += cpu_to_le32(*checksum_ptr++);
170 checksum += cmd->command + cmd->target_addr + cmd->data_size;
171 cmd->block_checksum = cpu_to_le32(checksum);
172 }
173}
174EXPORT_SYMBOL_GPL(i2400m_bm_cmd_prepare);
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190static
191ssize_t __i2400m_bm_ack_verify(struct i2400m *i2400m, int opcode,
192 struct i2400m_bootrom_header *ack,
193 size_t ack_size, int flags)
194{
195 ssize_t result = -ENOMEM;
196 struct device *dev = i2400m_dev(i2400m);
197
198 d_fnstart(8, dev, "(i2400m %p opcode %d ack %p size %zu)\n",
199 i2400m, opcode, ack, ack_size);
200 if (ack_size < sizeof(*ack)) {
201 result = -EIO;
202 dev_err(dev, "boot-mode cmd %d: HW BUG? notification didn't "
203 "return enough data (%zu bytes vs %zu expected)\n",
204 opcode, ack_size, sizeof(*ack));
205 goto error_ack_short;
206 }
207 if (ack_size == sizeof(i2400m_NBOOT_BARKER)
208 && memcmp(ack, i2400m_NBOOT_BARKER, sizeof(*ack)) == 0) {
209 result = -ERESTARTSYS;
210 i2400m->sboot = 0;
211 d_printf(6, dev, "boot-mode cmd %d: "
212 "HW non-signed boot barker\n", opcode);
213 goto error_reboot;
214 }
215 if (ack_size == sizeof(i2400m_SBOOT_BARKER)
216 && memcmp(ack, i2400m_SBOOT_BARKER, sizeof(*ack)) == 0) {
217 result = -ERESTARTSYS;
218 i2400m->sboot = 1;
219 d_printf(6, dev, "boot-mode cmd %d: HW signed reboot barker\n",
220 opcode);
221 goto error_reboot;
222 }
223 if (ack_size == sizeof(i2400m_ACK_BARKER)
224 && memcmp(ack, i2400m_ACK_BARKER, sizeof(*ack)) == 0) {
225 result = -EISCONN;
226 d_printf(3, dev, "boot-mode cmd %d: HW reboot ack barker\n",
227 opcode);
228 goto error_reboot_ack;
229 }
230 result = 0;
231 if (flags & I2400M_BM_CMD_RAW)
232 goto out_raw;
233 ack->data_size = le32_to_cpu(ack->data_size);
234 ack->target_addr = le32_to_cpu(ack->target_addr);
235 ack->block_checksum = le32_to_cpu(ack->block_checksum);
236 d_printf(5, dev, "boot-mode cmd %d: notification for opcode %u "
237 "response %u csum %u rr %u da %u\n",
238 opcode, i2400m_brh_get_opcode(ack),
239 i2400m_brh_get_response(ack),
240 i2400m_brh_get_use_checksum(ack),
241 i2400m_brh_get_response_required(ack),
242 i2400m_brh_get_direct_access(ack));
243 result = -EIO;
244 if (i2400m_brh_get_signature(ack) != 0xcbbc) {
245 dev_err(dev, "boot-mode cmd %d: HW BUG? wrong signature "
246 "0x%04x\n", opcode, i2400m_brh_get_signature(ack));
247 goto error_ack_signature;
248 }
249 if (opcode != -1 && opcode != i2400m_brh_get_opcode(ack)) {
250 dev_err(dev, "boot-mode cmd %d: HW BUG? "
251 "received response for opcode %u, expected %u\n",
252 opcode, i2400m_brh_get_opcode(ack), opcode);
253 goto error_ack_opcode;
254 }
255 if (i2400m_brh_get_response(ack) != 0) {
256 dev_err(dev, "boot-mode cmd %d: error; hw response %u\n",
257 opcode, i2400m_brh_get_response(ack));
258 goto error_ack_failed;
259 }
260 if (ack_size < ack->data_size + sizeof(*ack)) {
261 dev_err(dev, "boot-mode cmd %d: SW BUG "
262 "driver provided only %zu bytes for %zu bytes "
263 "of data\n", opcode, ack_size,
264 (size_t) le32_to_cpu(ack->data_size) + sizeof(*ack));
265 goto error_ack_short_buffer;
266 }
267 result = ack_size;
268
269
270
271error_ack_short_buffer:
272error_ack_failed:
273error_ack_opcode:
274error_ack_signature:
275out_raw:
276error_reboot_ack:
277error_reboot:
278error_ack_short:
279 d_fnend(8, dev, "(i2400m %p opcode %d ack %p size %zu) = %d\n",
280 i2400m, opcode, ack, ack_size, (int) result);
281 return result;
282}
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330static
331ssize_t i2400m_bm_cmd(struct i2400m *i2400m,
332 const struct i2400m_bootrom_header *cmd, size_t cmd_size,
333 struct i2400m_bootrom_header *ack, size_t ack_size,
334 int flags)
335{
336 ssize_t result = -ENOMEM, rx_bytes;
337 struct device *dev = i2400m_dev(i2400m);
338 int opcode = cmd == NULL ? -1 : i2400m_brh_get_opcode(cmd);
339
340 d_fnstart(6, dev, "(i2400m %p cmd %p size %zu ack %p size %zu)\n",
341 i2400m, cmd, cmd_size, ack, ack_size);
342 BUG_ON(ack_size < sizeof(*ack));
343 BUG_ON(i2400m->boot_mode == 0);
344
345 if (cmd != NULL) {
346 memcpy(i2400m->bm_cmd_buf, cmd, cmd_size);
347 result = i2400m->bus_bm_cmd_send(i2400m, cmd, cmd_size, flags);
348 if (result < 0)
349 goto error_cmd_send;
350 if ((flags & I2400M_BM_CMD_RAW) == 0)
351 d_printf(5, dev,
352 "boot-mode cmd %d csum %u rr %u da %u: "
353 "addr 0x%04x size %u block csum 0x%04x\n",
354 opcode, i2400m_brh_get_use_checksum(cmd),
355 i2400m_brh_get_response_required(cmd),
356 i2400m_brh_get_direct_access(cmd),
357 cmd->target_addr, cmd->data_size,
358 cmd->block_checksum);
359 }
360 result = i2400m->bus_bm_wait_for_ack(i2400m, ack, ack_size);
361 if (result < 0) {
362 dev_err(dev, "boot-mode cmd %d: error waiting for an ack: %d\n",
363 opcode, (int) result);
364 goto error_wait_for_ack;
365 }
366 rx_bytes = result;
367
368
369 result = __i2400m_bm_ack_verify(i2400m, opcode, ack, ack_size, flags);
370 if (result < 0)
371 goto error_bad_ack;
372
373
374
375 result = rx_bytes;
376error_bad_ack:
377error_wait_for_ack:
378error_cmd_send:
379 d_fnend(6, dev, "(i2400m %p cmd %p size %zu ack %p size %zu) = %d\n",
380 i2400m, cmd, cmd_size, ack, ack_size, (int) result);
381 return result;
382}
383
384
385
386
387
388
389
390
391
392
393
394
395static int i2400m_download_chunk(struct i2400m *i2400m, const void *chunk,
396 size_t __chunk_len, unsigned long addr,
397 unsigned int direct, unsigned int do_csum)
398{
399 int ret;
400 size_t chunk_len = ALIGN(__chunk_len, I2400M_PL_ALIGN);
401 struct device *dev = i2400m_dev(i2400m);
402 struct {
403 struct i2400m_bootrom_header cmd;
404 u8 cmd_payload[chunk_len];
405 } __attribute__((packed)) *buf;
406 struct i2400m_bootrom_header ack;
407
408 d_fnstart(5, dev, "(i2400m %p chunk %p __chunk_len %zu addr 0x%08lx "
409 "direct %u do_csum %u)\n", i2400m, chunk, __chunk_len,
410 addr, direct, do_csum);
411 buf = i2400m->bm_cmd_buf;
412 memcpy(buf->cmd_payload, chunk, __chunk_len);
413 memset(buf->cmd_payload + __chunk_len, 0xad, chunk_len - __chunk_len);
414
415 buf->cmd.command = i2400m_brh_command(I2400M_BRH_WRITE,
416 __chunk_len & 0x3 ? 0 : do_csum,
417 __chunk_len & 0xf ? 0 : direct);
418 buf->cmd.target_addr = cpu_to_le32(addr);
419 buf->cmd.data_size = cpu_to_le32(__chunk_len);
420 ret = i2400m_bm_cmd(i2400m, &buf->cmd, sizeof(buf->cmd) + chunk_len,
421 &ack, sizeof(ack), 0);
422 if (ret >= 0)
423 ret = 0;
424 d_fnend(5, dev, "(i2400m %p chunk %p __chunk_len %zu addr 0x%08lx "
425 "direct %u do_csum %u) = %d\n", i2400m, chunk, __chunk_len,
426 addr, direct, do_csum, ret);
427 return ret;
428}
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449static
450ssize_t i2400m_dnload_bcf(struct i2400m *i2400m,
451 const struct i2400m_bcf_hdr *bcf, size_t bcf_len)
452{
453 ssize_t ret;
454 struct device *dev = i2400m_dev(i2400m);
455 size_t offset,
456 data_size,
457 section_size,
458 section = 1;
459 const struct i2400m_bootrom_header *bh;
460 struct i2400m_bootrom_header ack;
461
462 d_fnstart(3, dev, "(i2400m %p bcf %p bcf_len %zu)\n",
463 i2400m, bcf, bcf_len);
464
465
466 offset = le32_to_cpu(bcf->header_len) * sizeof(u32);
467 while (1) {
468 bh = (void *) bcf + offset;
469 data_size = le32_to_cpu(bh->data_size);
470 section_size = ALIGN(sizeof(*bh) + data_size, 4);
471 d_printf(7, dev,
472 "downloading section #%zu (@%zu %zu B) to 0x%08x\n",
473 section, offset, sizeof(*bh) + data_size,
474 le32_to_cpu(bh->target_addr));
475 if (i2400m_brh_get_opcode(bh) == I2400M_BRH_SIGNED_JUMP) {
476
477 d_printf(5, dev, "signed jump found @%zu\n", offset);
478 break;
479 }
480 if (offset + section_size == bcf_len)
481
482 break;
483 if (offset + section_size > bcf_len) {
484 dev_err(dev, "fw %s: bad section #%zu, "
485 "end (@%zu) beyond EOF (@%zu)\n",
486 i2400m->fw_name, section,
487 offset + section_size, bcf_len);
488 ret = -EINVAL;
489 goto error_section_beyond_eof;
490 }
491 __i2400m_msleep(20);
492 ret = i2400m_bm_cmd(i2400m, bh, section_size,
493 &ack, sizeof(ack), I2400M_BM_CMD_RAW);
494 if (ret < 0) {
495 dev_err(dev, "fw %s: section #%zu (@%zu %zu B) "
496 "failed %d\n", i2400m->fw_name, section,
497 offset, sizeof(*bh) + data_size, (int) ret);
498 goto error_send;
499 }
500 offset += section_size;
501 section++;
502 }
503 ret = offset;
504error_section_beyond_eof:
505error_send:
506 d_fnend(3, dev, "(i2400m %p bcf %p bcf_len %zu) = %d\n",
507 i2400m, bcf, bcf_len, (int) ret);
508 return ret;
509}
510
511
512
513
514
515
516
517
518static
519int i2400m_dnload_finalize(struct i2400m *i2400m,
520 const struct i2400m_bcf_hdr *bcf, size_t offset)
521{
522 int ret = 0;
523 struct device *dev = i2400m_dev(i2400m);
524 struct i2400m_bootrom_header *cmd, ack;
525 struct {
526 struct i2400m_bootrom_header cmd;
527 u8 cmd_pl[0];
528 } __attribute__((packed)) *cmd_buf;
529 size_t signature_block_offset, signature_block_size;
530
531 d_fnstart(3, dev, "offset %zu\n", offset);
532 cmd = (void *) bcf + offset;
533 if (i2400m->sboot == 0) {
534 struct i2400m_bootrom_header jump_ack;
535 d_printf(1, dev, "unsecure boot, jumping to 0x%08x\n",
536 le32_to_cpu(cmd->target_addr));
537 i2400m_brh_set_opcode(cmd, I2400M_BRH_JUMP);
538 cmd->data_size = 0;
539 ret = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
540 &jump_ack, sizeof(jump_ack), 0);
541 } else {
542 d_printf(1, dev, "secure boot, jumping to 0x%08x\n",
543 le32_to_cpu(cmd->target_addr));
544 cmd_buf = i2400m->bm_cmd_buf;
545 memcpy(&cmd_buf->cmd, cmd, sizeof(*cmd));
546 signature_block_offset =
547 sizeof(*bcf)
548 + le32_to_cpu(bcf->key_size) * sizeof(u32)
549 + le32_to_cpu(bcf->exponent_size) * sizeof(u32);
550 signature_block_size =
551 le32_to_cpu(bcf->modulus_size) * sizeof(u32);
552 memcpy(cmd_buf->cmd_pl, (void *) bcf + signature_block_offset,
553 signature_block_size);
554 ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd,
555 sizeof(cmd_buf->cmd) + signature_block_size,
556 &ack, sizeof(ack), I2400M_BM_CMD_RAW);
557 }
558 d_fnend(3, dev, "returning %d\n", ret);
559 return ret;
560}
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags)
600{
601 int result;
602 struct device *dev = i2400m_dev(i2400m);
603 struct i2400m_bootrom_header *cmd;
604 struct i2400m_bootrom_header ack;
605 int count = I2400M_BOOT_RETRIES;
606 int ack_timeout_cnt = 1;
607
608 BUILD_BUG_ON(sizeof(*cmd) != sizeof(i2400m_NBOOT_BARKER));
609 BUILD_BUG_ON(sizeof(ack) != sizeof(i2400m_ACK_BARKER));
610
611 d_fnstart(4, dev, "(i2400m %p flags 0x%08x)\n", i2400m, flags);
612 result = -ENOMEM;
613 cmd = i2400m->bm_cmd_buf;
614 if (flags & I2400M_BRI_SOFT)
615 goto do_reboot_ack;
616do_reboot:
617 if (--count < 0)
618 goto error_timeout;
619 d_printf(4, dev, "device reboot: reboot command [%d # left]\n",
620 count);
621 if ((flags & I2400M_BRI_NO_REBOOT) == 0)
622 i2400m->bus_reset(i2400m, I2400M_RT_WARM);
623 result = i2400m_bm_cmd(i2400m, NULL, 0, &ack, sizeof(ack),
624 I2400M_BM_CMD_RAW);
625 flags &= ~I2400M_BRI_NO_REBOOT;
626 switch (result) {
627 case -ERESTARTSYS:
628 d_printf(4, dev, "device reboot: got reboot barker\n");
629 break;
630 case -EISCONN:
631 d_printf(4, dev, "device reboot: got ack barker - whatever\n");
632 goto do_reboot;
633 case -ETIMEDOUT:
634
635
636 dev_info(dev, "warm reset timed out, trying an ack\n");
637 goto do_reboot_ack;
638 case -EPROTO:
639 case -ESHUTDOWN:
640 case -EINTR:
641 goto error_dev_gone;
642 default:
643 dev_err(dev, "device reboot: error %d while waiting "
644 "for reboot barker - rebooting\n", result);
645 goto do_reboot;
646 }
647
648
649
650
651do_reboot_ack:
652 d_printf(4, dev, "device reboot ack: sending ack [%d # left]\n", count);
653 if (i2400m->sboot == 0)
654 memcpy(cmd, i2400m_NBOOT_BARKER,
655 sizeof(i2400m_NBOOT_BARKER));
656 else
657 memcpy(cmd, i2400m_SBOOT_BARKER,
658 sizeof(i2400m_SBOOT_BARKER));
659 result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
660 &ack, sizeof(ack), I2400M_BM_CMD_RAW);
661 switch (result) {
662 case -ERESTARTSYS:
663 d_printf(4, dev, "reboot ack: got reboot barker - retrying\n");
664 if (--count < 0)
665 goto error_timeout;
666 goto do_reboot_ack;
667 case -EISCONN:
668 d_printf(4, dev, "reboot ack: got ack barker - good\n");
669 break;
670 case -ETIMEDOUT:
671 if (ack_timeout_cnt-- >= 0) {
672 d_printf(4, dev, "reboot ack timedout: "
673 "trying the other type?\n");
674 i2400m->sboot = !i2400m->sboot;
675 goto do_reboot_ack;
676 } else {
677 dev_err(dev, "reboot ack timedout too long: "
678 "trying reboot\n");
679 goto do_reboot;
680 }
681 break;
682 case -EPROTO:
683 case -ESHUTDOWN:
684 goto error_dev_gone;
685 default:
686 dev_err(dev, "device reboot ack: error %d while waiting for "
687 "reboot ack barker - rebooting\n", result);
688 goto do_reboot;
689 }
690 d_printf(2, dev, "device reboot ack: got ack barker - boot done\n");
691 result = 0;
692exit_timeout:
693error_dev_gone:
694 d_fnend(4, dev, "(i2400m %p flags 0x%08x) = %d\n",
695 i2400m, flags, result);
696 return result;
697
698error_timeout:
699 dev_err(dev, "Timed out waiting for reboot ack\n");
700 result = -ETIMEDOUT;
701 goto exit_timeout;
702}
703
704
705
706
707
708
709
710
711
712
713
714int i2400m_read_mac_addr(struct i2400m *i2400m)
715{
716 int result;
717 struct device *dev = i2400m_dev(i2400m);
718 struct net_device *net_dev = i2400m->wimax_dev.net_dev;
719 struct i2400m_bootrom_header *cmd;
720 struct {
721 struct i2400m_bootrom_header ack;
722 u8 ack_pl[16];
723 } __attribute__((packed)) ack_buf;
724
725 d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
726 cmd = i2400m->bm_cmd_buf;
727 cmd->command = i2400m_brh_command(I2400M_BRH_READ, 0, 1);
728 cmd->target_addr = cpu_to_le32(0x00203fe8);
729 cmd->data_size = cpu_to_le32(6);
730 result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
731 &ack_buf.ack, sizeof(ack_buf), 0);
732 if (result < 0) {
733 dev_err(dev, "BM: read mac addr failed: %d\n", result);
734 goto error_read_mac;
735 }
736 d_printf(2, dev,
737 "mac addr is %02x:%02x:%02x:%02x:%02x:%02x\n",
738 ack_buf.ack_pl[0], ack_buf.ack_pl[1],
739 ack_buf.ack_pl[2], ack_buf.ack_pl[3],
740 ack_buf.ack_pl[4], ack_buf.ack_pl[5]);
741 if (i2400m->bus_bm_mac_addr_impaired == 1) {
742 ack_buf.ack_pl[0] = 0x00;
743 ack_buf.ack_pl[1] = 0x16;
744 ack_buf.ack_pl[2] = 0xd3;
745 get_random_bytes(&ack_buf.ack_pl[3], 3);
746 dev_err(dev, "BM is MAC addr impaired, faking MAC addr to "
747 "mac addr is %02x:%02x:%02x:%02x:%02x:%02x\n",
748 ack_buf.ack_pl[0], ack_buf.ack_pl[1],
749 ack_buf.ack_pl[2], ack_buf.ack_pl[3],
750 ack_buf.ack_pl[4], ack_buf.ack_pl[5]);
751 result = 0;
752 }
753 net_dev->addr_len = ETH_ALEN;
754 memcpy(net_dev->perm_addr, ack_buf.ack_pl, ETH_ALEN);
755 memcpy(net_dev->dev_addr, ack_buf.ack_pl, ETH_ALEN);
756error_read_mac:
757 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, result);
758 return result;
759}
760
761
762
763
764
765
766
767
768
769static
770int i2400m_dnload_init_nonsigned(struct i2400m *i2400m)
771{
772 unsigned i = 0;
773 int ret = 0;
774 struct device *dev = i2400m_dev(i2400m);
775 d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
776 if (i2400m->bus_bm_pokes_table) {
777 while (i2400m->bus_bm_pokes_table[i].address) {
778 ret = i2400m_download_chunk(
779 i2400m,
780 &i2400m->bus_bm_pokes_table[i].data,
781 sizeof(i2400m->bus_bm_pokes_table[i].data),
782 i2400m->bus_bm_pokes_table[i].address, 1, 1);
783 if (ret < 0)
784 break;
785 i++;
786 }
787 }
788 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
789 return ret;
790}
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807static
808int i2400m_dnload_init_signed(struct i2400m *i2400m,
809 const struct i2400m_bcf_hdr *bcf_hdr)
810{
811 int ret;
812 struct device *dev = i2400m_dev(i2400m);
813 struct {
814 struct i2400m_bootrom_header cmd;
815 struct i2400m_bcf_hdr cmd_pl;
816 } __attribute__((packed)) *cmd_buf;
817 struct i2400m_bootrom_header ack;
818
819 d_fnstart(5, dev, "(i2400m %p bcf_hdr %p)\n", i2400m, bcf_hdr);
820 cmd_buf = i2400m->bm_cmd_buf;
821 cmd_buf->cmd.command =
822 i2400m_brh_command(I2400M_BRH_HASH_PAYLOAD_ONLY, 0, 0);
823 cmd_buf->cmd.target_addr = 0;
824 cmd_buf->cmd.data_size = cpu_to_le32(sizeof(cmd_buf->cmd_pl));
825 memcpy(&cmd_buf->cmd_pl, bcf_hdr, sizeof(*bcf_hdr));
826 ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd, sizeof(*cmd_buf),
827 &ack, sizeof(ack), 0);
828 if (ret >= 0)
829 ret = 0;
830 d_fnend(5, dev, "(i2400m %p bcf_hdr %p) = %d\n", i2400m, bcf_hdr, ret);
831 return ret;
832}
833
834
835
836
837
838
839
840
841static
842int i2400m_dnload_init(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf)
843{
844 int result;
845 struct device *dev = i2400m_dev(i2400m);
846 u32 module_id = le32_to_cpu(bcf->module_id);
847
848 if (i2400m->sboot == 0
849 && (module_id & I2400M_BCF_MOD_ID_POKES) == 0) {
850
851 result = i2400m_dnload_init_nonsigned(i2400m);
852 if (result == -ERESTARTSYS)
853 return result;
854 if (result < 0)
855 dev_err(dev, "fw %s: non-signed download "
856 "initialization failed: %d\n",
857 i2400m->fw_name, result);
858 } else if (i2400m->sboot == 0
859 && (module_id & I2400M_BCF_MOD_ID_POKES)) {
860
861 result = 0;
862 } else {
863 result = i2400m_dnload_init_signed(i2400m, bcf);
864 if (result == -ERESTARTSYS)
865 return result;
866 if (result < 0)
867 dev_err(dev, "fw %s: signed boot download "
868 "initialization failed: %d\n",
869 i2400m->fw_name, result);
870 }
871 return result;
872}
873
874
875
876
877
878
879
880
881
882
883static
884int i2400m_fw_check(struct i2400m *i2400m,
885 const struct i2400m_bcf_hdr *bcf,
886 size_t bcf_size)
887{
888 int result;
889 struct device *dev = i2400m_dev(i2400m);
890 unsigned module_type, header_len, major_version, minor_version,
891 module_id, module_vendor, date, size;
892
893
894 result = -EINVAL;
895 if (bcf_size < sizeof(*bcf)) {
896 dev_err(dev, "firmware %s too short: "
897 "%zu B vs %zu (at least) expected\n",
898 i2400m->fw_name, bcf_size, sizeof(*bcf));
899 goto error;
900 }
901
902 module_type = bcf->module_type;
903 header_len = sizeof(u32) * le32_to_cpu(bcf->header_len);
904 major_version = le32_to_cpu(bcf->header_version) & 0xffff0000 >> 16;
905 minor_version = le32_to_cpu(bcf->header_version) & 0x0000ffff;
906 module_id = le32_to_cpu(bcf->module_id);
907 module_vendor = le32_to_cpu(bcf->module_vendor);
908 date = le32_to_cpu(bcf->date);
909 size = sizeof(u32) * le32_to_cpu(bcf->size);
910
911 if (bcf_size != size) {
912 dev_err(dev, "firmware %s: bad size, got "
913 "%zu B vs %u expected\n",
914 i2400m->fw_name, bcf_size, size);
915 goto error;
916 }
917
918 d_printf(2, dev, "type 0x%x id 0x%x vendor 0x%x; header v%u.%u (%zu B) "
919 "date %08x (%zu B)\n",
920 module_type, module_id, module_vendor,
921 major_version, minor_version, (size_t) header_len,
922 date, (size_t) size);
923
924 if (module_type != 6) {
925 dev_err(dev, "bad fw %s: unexpected module type 0x%x; "
926 "aborting\n", i2400m->fw_name, module_type);
927 goto error;
928 }
929
930
931 result = 0;
932 if (module_vendor != 0x8086)
933 dev_err(dev, "bad fw %s? unexpected vendor 0x%04x\n",
934 i2400m->fw_name, module_vendor);
935 if (date < 0x20080300)
936 dev_err(dev, "bad fw %s? build date too old %08x\n",
937 i2400m->fw_name, date);
938error:
939 return result;
940}
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957static
958int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf,
959 size_t bcf_size, enum i2400m_bri flags)
960{
961 int ret = 0;
962 struct device *dev = i2400m_dev(i2400m);
963 int count = i2400m->bus_bm_retries;
964
965 d_fnstart(5, dev, "(i2400m %p bcf %p size %zu)\n",
966 i2400m, bcf, bcf_size);
967 i2400m->boot_mode = 1;
968 wmb();
969hw_reboot:
970 if (count-- == 0) {
971 ret = -ERESTARTSYS;
972 dev_err(dev, "device rebooted too many times, aborting\n");
973 goto error_too_many_reboots;
974 }
975 if (flags & I2400M_BRI_MAC_REINIT) {
976 ret = i2400m_bootrom_init(i2400m, flags);
977 if (ret < 0) {
978 dev_err(dev, "bootrom init failed: %d\n", ret);
979 goto error_bootrom_init;
980 }
981 }
982 flags |= I2400M_BRI_MAC_REINIT;
983
984
985
986
987
988
989 ret = i2400m_dnload_init(i2400m, bcf);
990 if (ret == -ERESTARTSYS)
991 goto error_dev_rebooted;
992 if (ret < 0)
993 goto error_dnload_init;
994
995 ret = i2400m_dnload_bcf(i2400m, bcf, bcf_size);
996 if (ret == -ERESTARTSYS)
997 goto error_dev_rebooted;
998 if (ret < 0) {
999 dev_err(dev, "fw %s: download failed: %d\n",
1000 i2400m->fw_name, ret);
1001 goto error_dnload_bcf;
1002 }
1003
1004 ret = i2400m_dnload_finalize(i2400m, bcf, ret);
1005 if (ret == -ERESTARTSYS)
1006 goto error_dev_rebooted;
1007 if (ret < 0) {
1008 dev_err(dev, "fw %s: "
1009 "download finalization failed: %d\n",
1010 i2400m->fw_name, ret);
1011 goto error_dnload_finalize;
1012 }
1013
1014 d_printf(2, dev, "fw %s successfully uploaded\n",
1015 i2400m->fw_name);
1016 i2400m->boot_mode = 0;
1017 wmb();
1018error_dnload_finalize:
1019error_dnload_bcf:
1020error_dnload_init:
1021error_bootrom_init:
1022error_too_many_reboots:
1023 d_fnend(5, dev, "(i2400m %p bcf %p size %zu) = %d\n",
1024 i2400m, bcf, bcf_size, ret);
1025 return ret;
1026
1027error_dev_rebooted:
1028 dev_err(dev, "device rebooted, %d tries left\n", count);
1029
1030 flags |= I2400M_BRI_SOFT;
1031 goto hw_reboot;
1032}
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags)
1051{
1052 int ret = 0, itr = 0;
1053 struct device *dev = i2400m_dev(i2400m);
1054 const struct firmware *fw;
1055 const struct i2400m_bcf_hdr *bcf;
1056 const char *fw_name;
1057
1058 d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
1059
1060
1061 itr = 0;
1062 while(1) {
1063 fw_name = i2400m->bus_fw_names[itr];
1064 if (fw_name == NULL) {
1065 dev_err(dev, "Could not find a usable firmware image\n");
1066 ret = -ENOENT;
1067 goto error_no_fw;
1068 }
1069 ret = request_firmware(&fw, fw_name, dev);
1070 if (ret == 0)
1071 break;
1072 if (ret < 0)
1073 dev_err(dev, "fw %s: cannot load file: %d\n",
1074 fw_name, ret);
1075 itr++;
1076 }
1077
1078 bcf = (void *) fw->data;
1079 i2400m->fw_name = fw_name;
1080 ret = i2400m_fw_check(i2400m, bcf, fw->size);
1081 if (ret < 0)
1082 goto error_fw_bad;
1083 ret = i2400m_fw_dnload(i2400m, bcf, fw->size, flags);
1084error_fw_bad:
1085 release_firmware(fw);
1086error_no_fw:
1087 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
1088 return ret;
1089}
1090EXPORT_SYMBOL_GPL(i2400m_dev_bootstrap);
1091