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