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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157#include <linux/firmware.h>
158#include <linux/sched.h>
159#include <linux/slab.h>
160#include <linux/usb.h>
161#include "i2400m.h"
162
163
164#define D_SUBMODULE fw
165#include "debug-levels.h"
166
167
168static const __le32 i2400m_ACK_BARKER[4] = {
169 cpu_to_le32(I2400M_ACK_BARKER),
170 cpu_to_le32(I2400M_ACK_BARKER),
171 cpu_to_le32(I2400M_ACK_BARKER),
172 cpu_to_le32(I2400M_ACK_BARKER)
173};
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *cmd)
189{
190 if (i2400m_brh_get_use_checksum(cmd)) {
191 int i;
192 u32 checksum = 0;
193 const u32 *checksum_ptr = (void *) cmd->payload;
194 for (i = 0; i < cmd->data_size / 4; i++)
195 checksum += cpu_to_le32(*checksum_ptr++);
196 checksum += cmd->command + cmd->target_addr + cmd->data_size;
197 cmd->block_checksum = cpu_to_le32(checksum);
198 }
199}
200EXPORT_SYMBOL_GPL(i2400m_bm_cmd_prepare);
201
202
203
204
205
206
207
208
209
210
211static struct i2400m_barker_db {
212 __le32 data[4];
213} *i2400m_barker_db;
214static size_t i2400m_barker_db_used, i2400m_barker_db_size;
215
216
217static
218int i2400m_zrealloc_2x(void **ptr, size_t *_count, size_t el_size,
219 gfp_t gfp_flags)
220{
221 size_t old_count = *_count,
222 new_count = old_count ? 2 * old_count : 2,
223 old_size = el_size * old_count,
224 new_size = el_size * new_count;
225 void *nptr = krealloc(*ptr, new_size, gfp_flags);
226 if (nptr) {
227
228
229 if (old_size == 0)
230 memset(nptr, 0, new_size);
231 else
232 memset(nptr + old_size, 0, old_size);
233 *_count = new_count;
234 *ptr = nptr;
235 return 0;
236 } else
237 return -ENOMEM;
238}
239
240
241
242
243
244
245
246
247static
248int i2400m_barker_db_add(u32 barker_id)
249{
250 int result;
251
252 struct i2400m_barker_db *barker;
253 if (i2400m_barker_db_used >= i2400m_barker_db_size) {
254 result = i2400m_zrealloc_2x(
255 (void **) &i2400m_barker_db, &i2400m_barker_db_size,
256 sizeof(i2400m_barker_db[0]), GFP_KERNEL);
257 if (result < 0)
258 return result;
259 }
260 barker = i2400m_barker_db + i2400m_barker_db_used++;
261 barker->data[0] = le32_to_cpu(barker_id);
262 barker->data[1] = le32_to_cpu(barker_id);
263 barker->data[2] = le32_to_cpu(barker_id);
264 barker->data[3] = le32_to_cpu(barker_id);
265 return 0;
266}
267
268
269void i2400m_barker_db_exit(void)
270{
271 kfree(i2400m_barker_db);
272 i2400m_barker_db = NULL;
273 i2400m_barker_db_size = 0;
274 i2400m_barker_db_used = 0;
275}
276
277
278
279
280
281
282static
283int i2400m_barker_db_known_barkers(void)
284{
285 int result;
286
287 result = i2400m_barker_db_add(I2400M_NBOOT_BARKER);
288 if (result < 0)
289 goto error_add;
290 result = i2400m_barker_db_add(I2400M_SBOOT_BARKER);
291 if (result < 0)
292 goto error_add;
293 result = i2400m_barker_db_add(I2400M_SBOOT_BARKER_6050);
294 if (result < 0)
295 goto error_add;
296error_add:
297 return result;
298}
299
300
301
302
303
304
305
306
307
308
309
310
311
312int i2400m_barker_db_init(const char *_options)
313{
314 int result;
315 char *options = NULL, *options_orig, *token;
316
317 i2400m_barker_db = NULL;
318 i2400m_barker_db_size = 0;
319 i2400m_barker_db_used = 0;
320
321 result = i2400m_barker_db_known_barkers();
322 if (result < 0)
323 goto error_add;
324
325 if (_options != NULL) {
326 unsigned barker;
327
328 options_orig = kstrdup(_options, GFP_KERNEL);
329 if (options_orig == NULL)
330 goto error_parse;
331 options = options_orig;
332
333 while ((token = strsep(&options, ",")) != NULL) {
334 if (*token == '\0')
335 continue;
336 if (sscanf(token, "%x", &barker) != 1
337 || barker > 0xffffffff) {
338 printk(KERN_ERR "%s: can't recognize "
339 "i2400m.barkers value '%s' as "
340 "a 32-bit number\n",
341 __func__, token);
342 result = -EINVAL;
343 goto error_parse;
344 }
345 if (barker == 0) {
346
347 i2400m_barker_db_exit();
348 continue;
349 }
350 result = i2400m_barker_db_add(barker);
351 if (result < 0)
352 goto error_add;
353 }
354 kfree(options_orig);
355 }
356 return 0;
357
358error_parse:
359error_add:
360 kfree(i2400m_barker_db);
361 return result;
362}
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382int i2400m_is_boot_barker(struct i2400m *i2400m,
383 const void *buf, size_t buf_size)
384{
385 int result;
386 struct device *dev = i2400m_dev(i2400m);
387 struct i2400m_barker_db *barker;
388 int i;
389
390 result = -ENOENT;
391 if (buf_size != sizeof(i2400m_barker_db[i].data))
392 return result;
393
394
395
396 if (i2400m->barker
397 && !memcmp(buf, i2400m->barker, sizeof(i2400m->barker->data))) {
398 unsigned index = (i2400m->barker - i2400m_barker_db)
399 / sizeof(*i2400m->barker);
400 d_printf(2, dev, "boot barker cache-confirmed #%u/%08x\n",
401 index, le32_to_cpu(i2400m->barker->data[0]));
402 return 0;
403 }
404
405 for (i = 0; i < i2400m_barker_db_used; i++) {
406 barker = &i2400m_barker_db[i];
407 BUILD_BUG_ON(sizeof(barker->data) != 16);
408 if (memcmp(buf, barker->data, sizeof(barker->data)))
409 continue;
410
411 if (i2400m->barker == NULL) {
412 i2400m->barker = barker;
413 d_printf(1, dev, "boot barker set to #%u/%08x\n",
414 i, le32_to_cpu(barker->data[0]));
415 if (barker->data[0] == le32_to_cpu(I2400M_NBOOT_BARKER))
416 i2400m->sboot = 0;
417 else
418 i2400m->sboot = 1;
419 } else if (i2400m->barker != barker) {
420 dev_err(dev, "HW inconsistency: device "
421 "reports a different boot barker "
422 "than set (from %08x to %08x)\n",
423 le32_to_cpu(i2400m->barker->data[0]),
424 le32_to_cpu(barker->data[0]));
425 result = -EIO;
426 } else
427 d_printf(2, dev, "boot barker confirmed #%u/%08x\n",
428 i, le32_to_cpu(barker->data[0]));
429 result = 0;
430 break;
431 }
432 return result;
433}
434EXPORT_SYMBOL_GPL(i2400m_is_boot_barker);
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450static
451ssize_t __i2400m_bm_ack_verify(struct i2400m *i2400m, int opcode,
452 struct i2400m_bootrom_header *ack,
453 size_t ack_size, int flags)
454{
455 ssize_t result = -ENOMEM;
456 struct device *dev = i2400m_dev(i2400m);
457
458 d_fnstart(8, dev, "(i2400m %p opcode %d ack %p size %zu)\n",
459 i2400m, opcode, ack, ack_size);
460 if (ack_size < sizeof(*ack)) {
461 result = -EIO;
462 dev_err(dev, "boot-mode cmd %d: HW BUG? notification didn't "
463 "return enough data (%zu bytes vs %zu expected)\n",
464 opcode, ack_size, sizeof(*ack));
465 goto error_ack_short;
466 }
467 result = i2400m_is_boot_barker(i2400m, ack, ack_size);
468 if (result >= 0) {
469 result = -ERESTARTSYS;
470 d_printf(6, dev, "boot-mode cmd %d: HW boot barker\n", opcode);
471 goto error_reboot;
472 }
473 if (ack_size == sizeof(i2400m_ACK_BARKER)
474 && memcmp(ack, i2400m_ACK_BARKER, sizeof(*ack)) == 0) {
475 result = -EISCONN;
476 d_printf(3, dev, "boot-mode cmd %d: HW reboot ack barker\n",
477 opcode);
478 goto error_reboot_ack;
479 }
480 result = 0;
481 if (flags & I2400M_BM_CMD_RAW)
482 goto out_raw;
483 ack->data_size = le32_to_cpu(ack->data_size);
484 ack->target_addr = le32_to_cpu(ack->target_addr);
485 ack->block_checksum = le32_to_cpu(ack->block_checksum);
486 d_printf(5, dev, "boot-mode cmd %d: notification for opcode %u "
487 "response %u csum %u rr %u da %u\n",
488 opcode, i2400m_brh_get_opcode(ack),
489 i2400m_brh_get_response(ack),
490 i2400m_brh_get_use_checksum(ack),
491 i2400m_brh_get_response_required(ack),
492 i2400m_brh_get_direct_access(ack));
493 result = -EIO;
494 if (i2400m_brh_get_signature(ack) != 0xcbbc) {
495 dev_err(dev, "boot-mode cmd %d: HW BUG? wrong signature "
496 "0x%04x\n", opcode, i2400m_brh_get_signature(ack));
497 goto error_ack_signature;
498 }
499 if (opcode != -1 && opcode != i2400m_brh_get_opcode(ack)) {
500 dev_err(dev, "boot-mode cmd %d: HW BUG? "
501 "received response for opcode %u, expected %u\n",
502 opcode, i2400m_brh_get_opcode(ack), opcode);
503 goto error_ack_opcode;
504 }
505 if (i2400m_brh_get_response(ack) != 0) {
506 dev_err(dev, "boot-mode cmd %d: error; hw response %u\n",
507 opcode, i2400m_brh_get_response(ack));
508 goto error_ack_failed;
509 }
510 if (ack_size < ack->data_size + sizeof(*ack)) {
511 dev_err(dev, "boot-mode cmd %d: SW BUG "
512 "driver provided only %zu bytes for %zu bytes "
513 "of data\n", opcode, ack_size,
514 (size_t) le32_to_cpu(ack->data_size) + sizeof(*ack));
515 goto error_ack_short_buffer;
516 }
517 result = ack_size;
518
519
520
521error_ack_short_buffer:
522error_ack_failed:
523error_ack_opcode:
524error_ack_signature:
525out_raw:
526error_reboot_ack:
527error_reboot:
528error_ack_short:
529 d_fnend(8, dev, "(i2400m %p opcode %d ack %p size %zu) = %d\n",
530 i2400m, opcode, ack, ack_size, (int) result);
531 return result;
532}
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580static
581ssize_t i2400m_bm_cmd(struct i2400m *i2400m,
582 const struct i2400m_bootrom_header *cmd, size_t cmd_size,
583 struct i2400m_bootrom_header *ack, size_t ack_size,
584 int flags)
585{
586 ssize_t result = -ENOMEM, rx_bytes;
587 struct device *dev = i2400m_dev(i2400m);
588 int opcode = cmd == NULL ? -1 : i2400m_brh_get_opcode(cmd);
589
590 d_fnstart(6, dev, "(i2400m %p cmd %p size %zu ack %p size %zu)\n",
591 i2400m, cmd, cmd_size, ack, ack_size);
592 BUG_ON(ack_size < sizeof(*ack));
593 BUG_ON(i2400m->boot_mode == 0);
594
595 if (cmd != NULL) {
596 result = i2400m->bus_bm_cmd_send(i2400m, cmd, cmd_size, flags);
597 if (result < 0)
598 goto error_cmd_send;
599 if ((flags & I2400M_BM_CMD_RAW) == 0)
600 d_printf(5, dev,
601 "boot-mode cmd %d csum %u rr %u da %u: "
602 "addr 0x%04x size %u block csum 0x%04x\n",
603 opcode, i2400m_brh_get_use_checksum(cmd),
604 i2400m_brh_get_response_required(cmd),
605 i2400m_brh_get_direct_access(cmd),
606 cmd->target_addr, cmd->data_size,
607 cmd->block_checksum);
608 }
609 result = i2400m->bus_bm_wait_for_ack(i2400m, ack, ack_size);
610 if (result < 0) {
611 dev_err(dev, "boot-mode cmd %d: error waiting for an ack: %d\n",
612 opcode, (int) result);
613 goto error_wait_for_ack;
614 }
615 rx_bytes = result;
616
617
618 result = __i2400m_bm_ack_verify(i2400m, opcode, ack, ack_size, flags);
619 if (result < 0)
620 goto error_bad_ack;
621
622
623
624 result = rx_bytes;
625error_bad_ack:
626error_wait_for_ack:
627error_cmd_send:
628 d_fnend(6, dev, "(i2400m %p cmd %p size %zu ack %p size %zu) = %d\n",
629 i2400m, cmd, cmd_size, ack, ack_size, (int) result);
630 return result;
631}
632
633
634
635
636
637
638
639
640
641
642
643
644static int i2400m_download_chunk(struct i2400m *i2400m, const void *chunk,
645 size_t __chunk_len, unsigned long addr,
646 unsigned int direct, unsigned int do_csum)
647{
648 int ret;
649 size_t chunk_len = ALIGN(__chunk_len, I2400M_PL_ALIGN);
650 struct device *dev = i2400m_dev(i2400m);
651 struct {
652 struct i2400m_bootrom_header cmd;
653 u8 cmd_payload[chunk_len];
654 } __packed *buf;
655 struct i2400m_bootrom_header ack;
656
657 d_fnstart(5, dev, "(i2400m %p chunk %p __chunk_len %zu addr 0x%08lx "
658 "direct %u do_csum %u)\n", i2400m, chunk, __chunk_len,
659 addr, direct, do_csum);
660 buf = i2400m->bm_cmd_buf;
661 memcpy(buf->cmd_payload, chunk, __chunk_len);
662 memset(buf->cmd_payload + __chunk_len, 0xad, chunk_len - __chunk_len);
663
664 buf->cmd.command = i2400m_brh_command(I2400M_BRH_WRITE,
665 __chunk_len & 0x3 ? 0 : do_csum,
666 __chunk_len & 0xf ? 0 : direct);
667 buf->cmd.target_addr = cpu_to_le32(addr);
668 buf->cmd.data_size = cpu_to_le32(__chunk_len);
669 ret = i2400m_bm_cmd(i2400m, &buf->cmd, sizeof(buf->cmd) + chunk_len,
670 &ack, sizeof(ack), 0);
671 if (ret >= 0)
672 ret = 0;
673 d_fnend(5, dev, "(i2400m %p chunk %p __chunk_len %zu addr 0x%08lx "
674 "direct %u do_csum %u) = %d\n", i2400m, chunk, __chunk_len,
675 addr, direct, do_csum, ret);
676 return ret;
677}
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698static
699ssize_t i2400m_dnload_bcf(struct i2400m *i2400m,
700 const struct i2400m_bcf_hdr *bcf, size_t bcf_len)
701{
702 ssize_t ret;
703 struct device *dev = i2400m_dev(i2400m);
704 size_t offset,
705 data_size,
706 section_size,
707 section = 1;
708 const struct i2400m_bootrom_header *bh;
709 struct i2400m_bootrom_header ack;
710
711 d_fnstart(3, dev, "(i2400m %p bcf %p bcf_len %zu)\n",
712 i2400m, bcf, bcf_len);
713
714
715 offset = le32_to_cpu(bcf->header_len) * sizeof(u32);
716 while (1) {
717 bh = (void *) bcf + offset;
718 data_size = le32_to_cpu(bh->data_size);
719 section_size = ALIGN(sizeof(*bh) + data_size, 4);
720 d_printf(7, dev,
721 "downloading section #%zu (@%zu %zu B) to 0x%08x\n",
722 section, offset, sizeof(*bh) + data_size,
723 le32_to_cpu(bh->target_addr));
724
725
726
727
728
729
730 if (i2400m_brh_get_opcode(bh) == I2400M_BRH_SIGNED_JUMP ||
731 i2400m_brh_get_opcode(bh) == I2400M_BRH_JUMP) {
732 d_printf(5, dev, "jump found @%zu\n", offset);
733 break;
734 }
735 if (offset + section_size > bcf_len) {
736 dev_err(dev, "fw %s: bad section #%zu, "
737 "end (@%zu) beyond EOF (@%zu)\n",
738 i2400m->fw_name, section,
739 offset + section_size, bcf_len);
740 ret = -EINVAL;
741 goto error_section_beyond_eof;
742 }
743 __i2400m_msleep(20);
744 ret = i2400m_bm_cmd(i2400m, bh, section_size,
745 &ack, sizeof(ack), I2400M_BM_CMD_RAW);
746 if (ret < 0) {
747 dev_err(dev, "fw %s: section #%zu (@%zu %zu B) "
748 "failed %d\n", i2400m->fw_name, section,
749 offset, sizeof(*bh) + data_size, (int) ret);
750 goto error_send;
751 }
752 offset += section_size;
753 section++;
754 }
755 ret = offset;
756error_section_beyond_eof:
757error_send:
758 d_fnend(3, dev, "(i2400m %p bcf %p bcf_len %zu) = %d\n",
759 i2400m, bcf, bcf_len, (int) ret);
760 return ret;
761}
762
763
764
765
766
767
768static
769unsigned i2400m_boot_is_signed(struct i2400m *i2400m)
770{
771 return likely(i2400m->sboot);
772}
773
774
775
776
777
778
779
780
781
782
783
784
785
786static
787int i2400m_dnload_finalize(struct i2400m *i2400m,
788 const struct i2400m_bcf_hdr *bcf_hdr,
789 const struct i2400m_bcf_hdr *bcf, size_t offset)
790{
791 int ret = 0;
792 struct device *dev = i2400m_dev(i2400m);
793 struct i2400m_bootrom_header *cmd, ack;
794 struct {
795 struct i2400m_bootrom_header cmd;
796 u8 cmd_pl[0];
797 } __packed *cmd_buf;
798 size_t signature_block_offset, signature_block_size;
799
800 d_fnstart(3, dev, "offset %zu\n", offset);
801 cmd = (void *) bcf + offset;
802 if (i2400m_boot_is_signed(i2400m) == 0) {
803 struct i2400m_bootrom_header jump_ack;
804 d_printf(1, dev, "unsecure boot, jumping to 0x%08x\n",
805 le32_to_cpu(cmd->target_addr));
806 cmd_buf = i2400m->bm_cmd_buf;
807 memcpy(&cmd_buf->cmd, cmd, sizeof(*cmd));
808 cmd = &cmd_buf->cmd;
809
810 i2400m_brh_set_opcode(cmd, I2400M_BRH_JUMP);
811 cmd->data_size = 0;
812 ret = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
813 &jump_ack, sizeof(jump_ack), 0);
814 } else {
815 d_printf(1, dev, "secure boot, jumping to 0x%08x\n",
816 le32_to_cpu(cmd->target_addr));
817 cmd_buf = i2400m->bm_cmd_buf;
818 memcpy(&cmd_buf->cmd, cmd, sizeof(*cmd));
819 signature_block_offset =
820 sizeof(*bcf_hdr)
821 + le32_to_cpu(bcf_hdr->key_size) * sizeof(u32)
822 + le32_to_cpu(bcf_hdr->exponent_size) * sizeof(u32);
823 signature_block_size =
824 le32_to_cpu(bcf_hdr->modulus_size) * sizeof(u32);
825 memcpy(cmd_buf->cmd_pl,
826 (void *) bcf_hdr + signature_block_offset,
827 signature_block_size);
828 ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd,
829 sizeof(cmd_buf->cmd) + signature_block_size,
830 &ack, sizeof(ack), I2400M_BM_CMD_RAW);
831 }
832 d_fnend(3, dev, "returning %d\n", ret);
833 return ret;
834}
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags)
882{
883 int result;
884 struct device *dev = i2400m_dev(i2400m);
885 struct i2400m_bootrom_header *cmd;
886 struct i2400m_bootrom_header ack;
887 int count = i2400m->bus_bm_retries;
888 int ack_timeout_cnt = 1;
889 unsigned i;
890
891 BUILD_BUG_ON(sizeof(*cmd) != sizeof(i2400m_barker_db[0].data));
892 BUILD_BUG_ON(sizeof(ack) != sizeof(i2400m_ACK_BARKER));
893
894 d_fnstart(4, dev, "(i2400m %p flags 0x%08x)\n", i2400m, flags);
895 result = -ENOMEM;
896 cmd = i2400m->bm_cmd_buf;
897 if (flags & I2400M_BRI_SOFT)
898 goto do_reboot_ack;
899do_reboot:
900 ack_timeout_cnt = 1;
901 if (--count < 0)
902 goto error_timeout;
903 d_printf(4, dev, "device reboot: reboot command [%d # left]\n",
904 count);
905 if ((flags & I2400M_BRI_NO_REBOOT) == 0)
906 i2400m_reset(i2400m, I2400M_RT_WARM);
907 result = i2400m_bm_cmd(i2400m, NULL, 0, &ack, sizeof(ack),
908 I2400M_BM_CMD_RAW);
909 flags &= ~I2400M_BRI_NO_REBOOT;
910 switch (result) {
911 case -ERESTARTSYS:
912
913
914
915
916
917 d_printf(4, dev, "device reboot: got reboot barker\n");
918 break;
919 case -EISCONN:
920 d_printf(4, dev, "device reboot: got ack barker - whatever\n");
921 goto do_reboot;
922 case -ETIMEDOUT:
923
924
925
926
927
928
929 if (i2400m->barker != NULL) {
930 dev_err(dev, "device boot: reboot barker timed out, "
931 "trying (set) %08x echo/ack\n",
932 le32_to_cpu(i2400m->barker->data[0]));
933 goto do_reboot_ack;
934 }
935 for (i = 0; i < i2400m_barker_db_used; i++) {
936 struct i2400m_barker_db *barker = &i2400m_barker_db[i];
937 memcpy(cmd, barker->data, sizeof(barker->data));
938 result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
939 &ack, sizeof(ack),
940 I2400M_BM_CMD_RAW);
941 if (result == -EISCONN) {
942 dev_warn(dev, "device boot: got ack barker "
943 "after sending echo/ack barker "
944 "#%d/%08x; rebooting j.i.c.\n",
945 i, le32_to_cpu(barker->data[0]));
946 flags &= ~I2400M_BRI_NO_REBOOT;
947 goto do_reboot;
948 }
949 }
950 dev_err(dev, "device boot: tried all the echo/acks, could "
951 "not get device to respond; giving up");
952 result = -ESHUTDOWN;
953 case -EPROTO:
954 case -ESHUTDOWN:
955 case -EINTR:
956 goto error_dev_gone;
957 default:
958 dev_err(dev, "device reboot: error %d while waiting "
959 "for reboot barker - rebooting\n", result);
960 d_dump(1, dev, &ack, result);
961 goto do_reboot;
962 }
963
964
965
966
967do_reboot_ack:
968 d_printf(4, dev, "device reboot ack: sending ack [%d # left]\n", count);
969 memcpy(cmd, i2400m->barker->data, sizeof(i2400m->barker->data));
970 result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
971 &ack, sizeof(ack), I2400M_BM_CMD_RAW);
972 switch (result) {
973 case -ERESTARTSYS:
974 d_printf(4, dev, "reboot ack: got reboot barker - retrying\n");
975 if (--count < 0)
976 goto error_timeout;
977 goto do_reboot_ack;
978 case -EISCONN:
979 d_printf(4, dev, "reboot ack: got ack barker - good\n");
980 break;
981 case -ETIMEDOUT:
982 if (ack_timeout_cnt-- < 0) {
983 d_printf(4, dev, "reboot ack timedout: retrying\n");
984 goto do_reboot_ack;
985 } else {
986 dev_err(dev, "reboot ack timedout too long: "
987 "trying reboot\n");
988 goto do_reboot;
989 }
990 break;
991 case -EPROTO:
992 case -ESHUTDOWN:
993 goto error_dev_gone;
994 default:
995 dev_err(dev, "device reboot ack: error %d while waiting for "
996 "reboot ack barker - rebooting\n", result);
997 goto do_reboot;
998 }
999 d_printf(2, dev, "device reboot ack: got ack barker - boot done\n");
1000 result = 0;
1001exit_timeout:
1002error_dev_gone:
1003 d_fnend(4, dev, "(i2400m %p flags 0x%08x) = %d\n",
1004 i2400m, flags, result);
1005 return result;
1006
1007error_timeout:
1008 dev_err(dev, "Timed out waiting for reboot ack\n");
1009 result = -ETIMEDOUT;
1010 goto exit_timeout;
1011}
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023int i2400m_read_mac_addr(struct i2400m *i2400m)
1024{
1025 int result;
1026 struct device *dev = i2400m_dev(i2400m);
1027 struct net_device *net_dev = i2400m->wimax_dev.net_dev;
1028 struct i2400m_bootrom_header *cmd;
1029 struct {
1030 struct i2400m_bootrom_header ack;
1031 u8 ack_pl[16];
1032 } __packed ack_buf;
1033
1034 d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
1035 cmd = i2400m->bm_cmd_buf;
1036 cmd->command = i2400m_brh_command(I2400M_BRH_READ, 0, 1);
1037 cmd->target_addr = cpu_to_le32(0x00203fe8);
1038 cmd->data_size = cpu_to_le32(6);
1039 result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
1040 &ack_buf.ack, sizeof(ack_buf), 0);
1041 if (result < 0) {
1042 dev_err(dev, "BM: read mac addr failed: %d\n", result);
1043 goto error_read_mac;
1044 }
1045 d_printf(2, dev, "mac addr is %pM\n", ack_buf.ack_pl);
1046 if (i2400m->bus_bm_mac_addr_impaired == 1) {
1047 ack_buf.ack_pl[0] = 0x00;
1048 ack_buf.ack_pl[1] = 0x16;
1049 ack_buf.ack_pl[2] = 0xd3;
1050 get_random_bytes(&ack_buf.ack_pl[3], 3);
1051 dev_err(dev, "BM is MAC addr impaired, faking MAC addr to "
1052 "mac addr is %pM\n", ack_buf.ack_pl);
1053 result = 0;
1054 }
1055 net_dev->addr_len = ETH_ALEN;
1056 memcpy(net_dev->perm_addr, ack_buf.ack_pl, ETH_ALEN);
1057 memcpy(net_dev->dev_addr, ack_buf.ack_pl, ETH_ALEN);
1058error_read_mac:
1059 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, result);
1060 return result;
1061}
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071static
1072int i2400m_dnload_init_nonsigned(struct i2400m *i2400m)
1073{
1074 unsigned i = 0;
1075 int ret = 0;
1076 struct device *dev = i2400m_dev(i2400m);
1077 d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
1078 if (i2400m->bus_bm_pokes_table) {
1079 while (i2400m->bus_bm_pokes_table[i].address) {
1080 ret = i2400m_download_chunk(
1081 i2400m,
1082 &i2400m->bus_bm_pokes_table[i].data,
1083 sizeof(i2400m->bus_bm_pokes_table[i].data),
1084 i2400m->bus_bm_pokes_table[i].address, 1, 1);
1085 if (ret < 0)
1086 break;
1087 i++;
1088 }
1089 }
1090 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
1091 return ret;
1092}
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109static
1110int i2400m_dnload_init_signed(struct i2400m *i2400m,
1111 const struct i2400m_bcf_hdr *bcf_hdr)
1112{
1113 int ret;
1114 struct device *dev = i2400m_dev(i2400m);
1115 struct {
1116 struct i2400m_bootrom_header cmd;
1117 struct i2400m_bcf_hdr cmd_pl;
1118 } __packed *cmd_buf;
1119 struct i2400m_bootrom_header ack;
1120
1121 d_fnstart(5, dev, "(i2400m %p bcf_hdr %p)\n", i2400m, bcf_hdr);
1122 cmd_buf = i2400m->bm_cmd_buf;
1123 cmd_buf->cmd.command =
1124 i2400m_brh_command(I2400M_BRH_HASH_PAYLOAD_ONLY, 0, 0);
1125 cmd_buf->cmd.target_addr = 0;
1126 cmd_buf->cmd.data_size = cpu_to_le32(sizeof(cmd_buf->cmd_pl));
1127 memcpy(&cmd_buf->cmd_pl, bcf_hdr, sizeof(*bcf_hdr));
1128 ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd, sizeof(*cmd_buf),
1129 &ack, sizeof(ack), 0);
1130 if (ret >= 0)
1131 ret = 0;
1132 d_fnend(5, dev, "(i2400m %p bcf_hdr %p) = %d\n", i2400m, bcf_hdr, ret);
1133 return ret;
1134}
1135
1136
1137
1138
1139
1140
1141
1142
1143static
1144int i2400m_dnload_init(struct i2400m *i2400m,
1145 const struct i2400m_bcf_hdr *bcf_hdr)
1146{
1147 int result;
1148 struct device *dev = i2400m_dev(i2400m);
1149
1150 if (i2400m_boot_is_signed(i2400m)) {
1151 d_printf(1, dev, "signed boot\n");
1152 result = i2400m_dnload_init_signed(i2400m, bcf_hdr);
1153 if (result == -ERESTARTSYS)
1154 return result;
1155 if (result < 0)
1156 dev_err(dev, "firmware %s: signed boot download "
1157 "initialization failed: %d\n",
1158 i2400m->fw_name, result);
1159 } else {
1160
1161 d_printf(1, dev, "non-signed boot\n");
1162 result = i2400m_dnload_init_nonsigned(i2400m);
1163 if (result == -ERESTARTSYS)
1164 return result;
1165 if (result < 0)
1166 dev_err(dev, "firmware %s: non-signed download "
1167 "initialization failed: %d\n",
1168 i2400m->fw_name, result);
1169 }
1170 return result;
1171}
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185static
1186int i2400m_fw_hdr_check(struct i2400m *i2400m,
1187 const struct i2400m_bcf_hdr *bcf_hdr,
1188 size_t index, size_t offset)
1189{
1190 struct device *dev = i2400m_dev(i2400m);
1191
1192 unsigned module_type, header_len, major_version, minor_version,
1193 module_id, module_vendor, date, size;
1194
1195 module_type = le32_to_cpu(bcf_hdr->module_type);
1196 header_len = sizeof(u32) * le32_to_cpu(bcf_hdr->header_len);
1197 major_version = (le32_to_cpu(bcf_hdr->header_version) & 0xffff0000)
1198 >> 16;
1199 minor_version = le32_to_cpu(bcf_hdr->header_version) & 0x0000ffff;
1200 module_id = le32_to_cpu(bcf_hdr->module_id);
1201 module_vendor = le32_to_cpu(bcf_hdr->module_vendor);
1202 date = le32_to_cpu(bcf_hdr->date);
1203 size = sizeof(u32) * le32_to_cpu(bcf_hdr->size);
1204
1205 d_printf(1, dev, "firmware %s #%zd@%08zx: BCF header "
1206 "type:vendor:id 0x%x:%x:%x v%u.%u (%u/%u B) built %08x\n",
1207 i2400m->fw_name, index, offset,
1208 module_type, module_vendor, module_id,
1209 major_version, minor_version, header_len, size, date);
1210
1211
1212 if (major_version != 1) {
1213 dev_err(dev, "firmware %s #%zd@%08zx: major header version "
1214 "v%u.%u not supported\n",
1215 i2400m->fw_name, index, offset,
1216 major_version, minor_version);
1217 return -EBADF;
1218 }
1219
1220 if (module_type != 6) {
1221 dev_err(dev, "firmware %s #%zd@%08zx: unexpected module "
1222 "type 0x%x; aborting\n",
1223 i2400m->fw_name, index, offset,
1224 module_type);
1225 return -EBADF;
1226 }
1227
1228 if (module_vendor != 0x8086) {
1229 dev_err(dev, "firmware %s #%zd@%08zx: unexpected module "
1230 "vendor 0x%x; aborting\n",
1231 i2400m->fw_name, index, offset, module_vendor);
1232 return -EBADF;
1233 }
1234
1235 if (date < 0x20080300)
1236 dev_warn(dev, "firmware %s #%zd@%08zx: build date %08x "
1237 "too old; unsupported\n",
1238 i2400m->fw_name, index, offset, date);
1239 return 0;
1240}
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254static
1255int i2400m_fw_check(struct i2400m *i2400m, const void *bcf, size_t bcf_size)
1256{
1257 int result;
1258 struct device *dev = i2400m_dev(i2400m);
1259 size_t headers = 0;
1260 const struct i2400m_bcf_hdr *bcf_hdr;
1261 const void *itr, *next, *top;
1262 size_t slots = 0, used_slots = 0;
1263
1264 for (itr = bcf, top = itr + bcf_size;
1265 itr < top;
1266 headers++, itr = next) {
1267 size_t leftover, offset, header_len, size;
1268
1269 leftover = top - itr;
1270 offset = itr - (const void *) bcf;
1271 if (leftover <= sizeof(*bcf_hdr)) {
1272 dev_err(dev, "firmware %s: %zu B left at @%zx, "
1273 "not enough for BCF header\n",
1274 i2400m->fw_name, leftover, offset);
1275 break;
1276 }
1277 bcf_hdr = itr;
1278
1279
1280 header_len = sizeof(u32) * le32_to_cpu(bcf_hdr->header_len);
1281 size = sizeof(u32) * le32_to_cpu(bcf_hdr->size);
1282 if (headers == 0)
1283 next = itr + size;
1284 else
1285 next = itr + header_len;
1286
1287 result = i2400m_fw_hdr_check(i2400m, bcf_hdr, headers, offset);
1288 if (result < 0)
1289 continue;
1290 if (used_slots + 1 >= slots) {
1291
1292
1293
1294 result = i2400m_zrealloc_2x(
1295 (void **) &i2400m->fw_hdrs, &slots,
1296 sizeof(i2400m->fw_hdrs[0]),
1297 GFP_KERNEL);
1298 if (result < 0)
1299 goto error_zrealloc;
1300 }
1301 i2400m->fw_hdrs[used_slots] = bcf_hdr;
1302 used_slots++;
1303 }
1304 if (headers == 0) {
1305 dev_err(dev, "firmware %s: no usable headers found\n",
1306 i2400m->fw_name);
1307 result = -EBADF;
1308 } else
1309 result = 0;
1310error_zrealloc:
1311 return result;
1312}
1313
1314
1315
1316
1317
1318
1319
1320
1321static
1322unsigned i2400m_bcf_hdr_match(struct i2400m *i2400m,
1323 const struct i2400m_bcf_hdr *bcf_hdr)
1324{
1325 u32 barker = le32_to_cpu(i2400m->barker->data[0])
1326 & 0x7fffffff;
1327 u32 module_id = le32_to_cpu(bcf_hdr->module_id)
1328 & 0x7fffffff;
1329
1330
1331 if (barker == I2400M_SBOOT_BARKER && module_id == 0)
1332 return 1;
1333 if (module_id == barker)
1334 return 1;
1335 return 0;
1336}
1337
1338static
1339const struct i2400m_bcf_hdr *i2400m_bcf_hdr_find(struct i2400m *i2400m)
1340{
1341 struct device *dev = i2400m_dev(i2400m);
1342 const struct i2400m_bcf_hdr **bcf_itr, *bcf_hdr;
1343 unsigned i = 0;
1344 u32 barker = le32_to_cpu(i2400m->barker->data[0]);
1345
1346 d_printf(2, dev, "finding BCF header for barker %08x\n", barker);
1347 if (barker == I2400M_NBOOT_BARKER) {
1348 bcf_hdr = i2400m->fw_hdrs[0];
1349 d_printf(1, dev, "using BCF header #%u/%08x for non-signed "
1350 "barker\n", 0, le32_to_cpu(bcf_hdr->module_id));
1351 return bcf_hdr;
1352 }
1353 for (bcf_itr = i2400m->fw_hdrs; *bcf_itr != NULL; bcf_itr++, i++) {
1354 bcf_hdr = *bcf_itr;
1355 if (i2400m_bcf_hdr_match(i2400m, bcf_hdr)) {
1356 d_printf(1, dev, "hit on BCF hdr #%u/%08x\n",
1357 i, le32_to_cpu(bcf_hdr->module_id));
1358 return bcf_hdr;
1359 } else
1360 d_printf(1, dev, "miss on BCF hdr #%u/%08x\n",
1361 i, le32_to_cpu(bcf_hdr->module_id));
1362 }
1363 dev_err(dev, "cannot find a matching BCF header for barker %08x\n",
1364 barker);
1365 return NULL;
1366}
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383static
1384int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf,
1385 size_t fw_size, enum i2400m_bri flags)
1386{
1387 int ret = 0;
1388 struct device *dev = i2400m_dev(i2400m);
1389 int count = i2400m->bus_bm_retries;
1390 const struct i2400m_bcf_hdr *bcf_hdr;
1391 size_t bcf_size;
1392
1393 d_fnstart(5, dev, "(i2400m %p bcf %p fw size %zu)\n",
1394 i2400m, bcf, fw_size);
1395 i2400m->boot_mode = 1;
1396 wmb();
1397hw_reboot:
1398 if (count-- == 0) {
1399 ret = -ERESTARTSYS;
1400 dev_err(dev, "device rebooted too many times, aborting\n");
1401 goto error_too_many_reboots;
1402 }
1403 if (flags & I2400M_BRI_MAC_REINIT) {
1404 ret = i2400m_bootrom_init(i2400m, flags);
1405 if (ret < 0) {
1406 dev_err(dev, "bootrom init failed: %d\n", ret);
1407 goto error_bootrom_init;
1408 }
1409 }
1410 flags |= I2400M_BRI_MAC_REINIT;
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421 ret = -EBADF;
1422 bcf_hdr = i2400m_bcf_hdr_find(i2400m);
1423 if (bcf_hdr == NULL)
1424 goto error_bcf_hdr_find;
1425
1426 ret = i2400m_dnload_init(i2400m, bcf_hdr);
1427 if (ret == -ERESTARTSYS)
1428 goto error_dev_rebooted;
1429 if (ret < 0)
1430 goto error_dnload_init;
1431
1432
1433
1434
1435
1436
1437 bcf_size = sizeof(u32) * le32_to_cpu(bcf_hdr->size);
1438 ret = i2400m_dnload_bcf(i2400m, bcf, bcf_size);
1439 if (ret == -ERESTARTSYS)
1440 goto error_dev_rebooted;
1441 if (ret < 0) {
1442 dev_err(dev, "fw %s: download failed: %d\n",
1443 i2400m->fw_name, ret);
1444 goto error_dnload_bcf;
1445 }
1446
1447 ret = i2400m_dnload_finalize(i2400m, bcf_hdr, bcf, ret);
1448 if (ret == -ERESTARTSYS)
1449 goto error_dev_rebooted;
1450 if (ret < 0) {
1451 dev_err(dev, "fw %s: "
1452 "download finalization failed: %d\n",
1453 i2400m->fw_name, ret);
1454 goto error_dnload_finalize;
1455 }
1456
1457 d_printf(2, dev, "fw %s successfully uploaded\n",
1458 i2400m->fw_name);
1459 i2400m->boot_mode = 0;
1460 wmb();
1461error_dnload_finalize:
1462error_dnload_bcf:
1463error_dnload_init:
1464error_bcf_hdr_find:
1465error_bootrom_init:
1466error_too_many_reboots:
1467 d_fnend(5, dev, "(i2400m %p bcf %p size %zu) = %d\n",
1468 i2400m, bcf, fw_size, ret);
1469 return ret;
1470
1471error_dev_rebooted:
1472 dev_err(dev, "device rebooted, %d tries left\n", count);
1473
1474 flags |= I2400M_BRI_SOFT;
1475 goto hw_reboot;
1476}
1477
1478static
1479int i2400m_fw_bootstrap(struct i2400m *i2400m, const struct firmware *fw,
1480 enum i2400m_bri flags)
1481{
1482 int ret;
1483 struct device *dev = i2400m_dev(i2400m);
1484 const struct i2400m_bcf_hdr *bcf;
1485
1486 d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
1487 bcf = (void *) fw->data;
1488 ret = i2400m_fw_check(i2400m, bcf, fw->size);
1489 if (ret >= 0)
1490 ret = i2400m_fw_dnload(i2400m, bcf, fw->size, flags);
1491 if (ret < 0)
1492 dev_err(dev, "%s: cannot use: %d, skipping\n",
1493 i2400m->fw_name, ret);
1494 kfree(i2400m->fw_hdrs);
1495 i2400m->fw_hdrs = NULL;
1496 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
1497 return ret;
1498}
1499
1500
1501
1502struct i2400m_fw {
1503 struct kref kref;
1504 const struct firmware *fw;
1505};
1506
1507
1508static
1509void i2400m_fw_destroy(struct kref *kref)
1510{
1511 struct i2400m_fw *i2400m_fw =
1512 container_of(kref, struct i2400m_fw, kref);
1513 release_firmware(i2400m_fw->fw);
1514 kfree(i2400m_fw);
1515}
1516
1517
1518static
1519struct i2400m_fw *i2400m_fw_get(struct i2400m_fw *i2400m_fw)
1520{
1521 if (i2400m_fw != NULL && i2400m_fw != (void *) ~0)
1522 kref_get(&i2400m_fw->kref);
1523 return i2400m_fw;
1524}
1525
1526
1527static
1528void i2400m_fw_put(struct i2400m_fw *i2400m_fw)
1529{
1530 kref_put(&i2400m_fw->kref, i2400m_fw_destroy);
1531}
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags)
1550{
1551 int ret, itr;
1552 struct device *dev = i2400m_dev(i2400m);
1553 struct i2400m_fw *i2400m_fw;
1554 const struct i2400m_bcf_hdr *bcf;
1555 const struct firmware *fw;
1556 const char *fw_name;
1557
1558 d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
1559
1560 ret = -ENODEV;
1561 spin_lock(&i2400m->rx_lock);
1562 i2400m_fw = i2400m_fw_get(i2400m->fw_cached);
1563 spin_unlock(&i2400m->rx_lock);
1564 if (i2400m_fw == (void *) ~0) {
1565 dev_err(dev, "can't load firmware now!");
1566 goto out;
1567 } else if (i2400m_fw != NULL) {
1568 dev_info(dev, "firmware %s: loading from cache\n",
1569 i2400m->fw_name);
1570 ret = i2400m_fw_bootstrap(i2400m, i2400m_fw->fw, flags);
1571 i2400m_fw_put(i2400m_fw);
1572 goto out;
1573 }
1574
1575
1576 for (itr = 0, bcf = NULL, ret = -ENOENT; ; itr++) {
1577 fw_name = i2400m->bus_fw_names[itr];
1578 if (fw_name == NULL) {
1579 dev_err(dev, "Could not find a usable firmware image\n");
1580 break;
1581 }
1582 d_printf(1, dev, "trying firmware %s (%d)\n", fw_name, itr);
1583 ret = request_firmware(&fw, fw_name, dev);
1584 if (ret < 0) {
1585 dev_err(dev, "fw %s: cannot load file: %d\n",
1586 fw_name, ret);
1587 continue;
1588 }
1589 i2400m->fw_name = fw_name;
1590 ret = i2400m_fw_bootstrap(i2400m, fw, flags);
1591 release_firmware(fw);
1592 if (ret >= 0)
1593 break;
1594 i2400m->fw_name = NULL;
1595 }
1596out:
1597 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
1598 return ret;
1599}
1600EXPORT_SYMBOL_GPL(i2400m_dev_bootstrap);
1601
1602
1603void i2400m_fw_cache(struct i2400m *i2400m)
1604{
1605 int result;
1606 struct i2400m_fw *i2400m_fw;
1607 struct device *dev = i2400m_dev(i2400m);
1608
1609
1610 spin_lock(&i2400m->rx_lock);
1611 i2400m_fw = i2400m->fw_cached;
1612 spin_unlock(&i2400m->rx_lock);
1613 if (i2400m_fw != NULL && i2400m_fw != (void *) ~0) {
1614 i2400m_fw_put(i2400m_fw);
1615 WARN(1, "%s:%u: still cached fw still present?\n",
1616 __func__, __LINE__);
1617 }
1618
1619 if (i2400m->fw_name == NULL) {
1620 dev_err(dev, "firmware n/a: can't cache\n");
1621 i2400m_fw = (void *) ~0;
1622 goto out;
1623 }
1624
1625 i2400m_fw = kzalloc(sizeof(*i2400m_fw), GFP_ATOMIC);
1626 if (i2400m_fw == NULL)
1627 goto out;
1628 kref_init(&i2400m_fw->kref);
1629 result = request_firmware(&i2400m_fw->fw, i2400m->fw_name, dev);
1630 if (result < 0) {
1631 dev_err(dev, "firmware %s: failed to cache: %d\n",
1632 i2400m->fw_name, result);
1633 kfree(i2400m_fw);
1634 i2400m_fw = (void *) ~0;
1635 } else
1636 dev_info(dev, "firmware %s: cached\n", i2400m->fw_name);
1637out:
1638 spin_lock(&i2400m->rx_lock);
1639 i2400m->fw_cached = i2400m_fw;
1640 spin_unlock(&i2400m->rx_lock);
1641}
1642
1643
1644void i2400m_fw_uncache(struct i2400m *i2400m)
1645{
1646 struct i2400m_fw *i2400m_fw;
1647
1648 spin_lock(&i2400m->rx_lock);
1649 i2400m_fw = i2400m->fw_cached;
1650 i2400m->fw_cached = NULL;
1651 spin_unlock(&i2400m->rx_lock);
1652
1653 if (i2400m_fw != NULL && i2400m_fw != (void *) ~0)
1654 i2400m_fw_put(i2400m_fw);
1655}
1656
1657