]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/net/wimax/i2400m/fw.c
i2400m: firmware loading and bootrom initialization
[linux-2.6-omap-h63xx.git] / drivers / net / wimax / i2400m / fw.c
1 /*
2  * Intel Wireless WiMAX Connection 2400m
3  * Firmware uploader
4  *
5  *
6  * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *   * Redistributions in binary form must reproduce the above copyright
15  *     notice, this list of conditions and the following disclaimer in
16  *     the documentation and/or other materials provided with the
17  *     distribution.
18  *   * Neither the name of Intel Corporation nor the names of its
19  *     contributors may be used to endorse or promote products derived
20  *     from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  *
35  * Intel Corporation <linux-wimax@intel.com>
36  * Yanir Lubetkin <yanirx.lubetkin@intel.com>
37  * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
38  *  - Initial implementation
39  *
40  *
41  * THE PROCEDURE
42  *
43  * (this is decribed for USB, but for SDIO is similar)
44  *
45  * The 2400m works in two modes: boot-mode or normal mode. In boot
46  * mode we can execute only a handful of commands targeted at
47  * uploading the firmware and launching it.
48  *
49  * The 2400m enters boot mode when it is first connected to the
50  * system, when it crashes and when you ask it to reboot. There are
51  * two submodes of the boot mode: signed and non-signed. Signed takes
52  * firmwares signed with a certain private key, non-signed takes any
53  * firmware. Normal hardware takes only signed firmware.
54  *
55  * Upon entrance to boot mode, the device sends a few zero length
56  * packets (ZLPs) on the notification endpoint, then a reboot barker
57  * (4 le32 words with value I2400M_{S,N}BOOT_BARKER). We ack it by
58  * sending the same barker on the bulk out endpoint. The device acks
59  * with a reboot ack barker (4 le32 words with value 0xfeedbabe) and
60  * then the device is fully rebooted. At this point we can upload the
61  * firmware.
62  *
63  * This process is accomplished by the i2400m_bootrom_init()
64  * function. All the device interaction happens through the
65  * i2400m_bm_cmd() [boot mode command]. Special return values will
66  * indicate if the device resets.
67  *
68  * After this, we read the MAC address and then (if needed)
69  * reinitialize the device. We need to read it ahead of time because
70  * in the future, we might not upload the firmware until userspace
71  * 'ifconfig up's the device.
72  *
73  * We can then upload the firmware file. The file is composed of a BCF
74  * header (basic data, keys and signatures) and a list of write
75  * commands and payloads. We first upload the header
76  * [i2400m_dnload_init()] and then pass the commands and payloads
77  * verbatim to the i2400m_bm_cmd() function
78  * [i2400m_dnload_bcf()]. Then we tell the device to jump to the new
79  * firmware [i2400m_dnload_finalize()].
80  *
81  * Once firmware is uploaded, we are good to go :)
82  *
83  * When we don't know in which mode we are, we first try by sending a
84  * warm reset request that will take us to boot-mode. If we time out
85  * waiting for a reboot barker, that means maybe we are already in
86  * boot mode, so we send a reboot barker.
87  *
88  * COMMAND EXECUTION
89  *
90  * This code (and process) is single threaded; for executing commands,
91  * we post a URB to the notification endpoint, post the command, wait
92  * for data on the notification buffer. We don't need to worry about
93  * others as we know we are the only ones in there.
94  *
95  * BACKEND IMPLEMENTATION
96  *
97  * This code is bus-generic; the bus-specific driver provides back end
98  * implementations to send a boot mode command to the device and to
99  * read an acknolwedgement from it (or an asynchronous notification)
100  * from it.
101  *
102  * ROADMAP
103  *
104  * i2400m_dev_bootstrap               Called by __i2400m_dev_start()
105  *   request_firmware
106  *   i2400m_fw_check
107  *   i2400m_fw_dnload
108  *   release_firmware
109  *
110  * i2400m_fw_dnload
111  *   i2400m_bootrom_init
112  *     i2400m_bm_cmd
113  *     i2400m->bus_reset
114  *   i2400m_dnload_init
115  *     i2400m_dnload_init_signed
116  *     i2400m_dnload_init_nonsigned
117  *       i2400m_download_chunk
118  *         i2400m_bm_cmd
119  *   i2400m_dnload_bcf
120  *     i2400m_bm_cmd
121  *   i2400m_dnload_finalize
122  *     i2400m_bm_cmd
123  *
124  * i2400m_bm_cmd
125  *   i2400m->bus_bm_cmd_send()
126  *   i2400m->bus_bm_wait_for_ack
127  *   __i2400m_bm_ack_verify
128  *
129  * i2400m_bm_cmd_prepare              Used by bus-drivers to prep
130  *                                    commands before sending
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
142 static const __le32 i2400m_ACK_BARKER[4] = {
143         __constant_cpu_to_le32(I2400M_ACK_BARKER),
144         __constant_cpu_to_le32(I2400M_ACK_BARKER),
145         __constant_cpu_to_le32(I2400M_ACK_BARKER),
146         __constant_cpu_to_le32(I2400M_ACK_BARKER)
147 };
148
149
150 /**
151  * Prepare a boot-mode command for delivery
152  *
153  * @cmd: pointer to bootrom header to prepare
154  *
155  * Computes checksum if so needed. After calling this function, DO NOT
156  * modify the command or header as the checksum won't work anymore.
157  *
158  * We do it from here because some times we cannot do it in the
159  * original context the command was sent (it is a const), so when we
160  * copy it to our staging buffer, we add the checksum there.
161  */
162 void 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 }
174 EXPORT_SYMBOL_GPL(i2400m_bm_cmd_prepare);
175
176
177 /*
178  * Verify the ack data received
179  *
180  * Given a reply to a boot mode command, chew it and verify everything
181  * is ok.
182  *
183  * @opcode: opcode which generated this ack. For error messages.
184  * @ack: pointer to ack data we received
185  * @ack_size: size of that data buffer
186  * @flags: I2400M_BM_CMD_* flags we called the command with.
187  *
188  * Way too long function -- maybe it should be further split
189  */
190 static
191 ssize_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) {        /* failed? */
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         /* Don't you love this stack of empty targets? Well, I don't
269          * either, but it helps track exactly who comes in here and
270          * why :) */
271 error_ack_short_buffer:
272 error_ack_failed:
273 error_ack_opcode:
274 error_ack_signature:
275 out_raw:
276 error_reboot_ack:
277 error_reboot:
278 error_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  * i2400m_bm_cmd - Execute a boot mode command
287  *
288  * @cmd: buffer containing the command data (pointing at the header).
289  *     This data can be ANYWHERE (for USB, we will copy it to an
290  *     specific buffer). Make sure everything is in proper little
291  *     endian.
292  *
293  *     A raw buffer can be also sent, just cast it and set flags to
294  *     I2400M_BM_CMD_RAW.
295  *
296  *     This function will generate a checksum for you if the
297  *     checksum bit in the command is set (unless I2400M_BM_CMD_RAW
298  *     is set).
299  *
300  *     You can use the i2400m->bm_cmd_buf to stage your commands and
301  *     send them.
302  *
303  *     If NULL, no command is sent (we just wait for an ack).
304  *
305  * @cmd_size: size of the command. Will be auto padded to the
306  *     bus-specific drivers padding requirements.
307  *
308  * @ack: buffer where to place the acknowledgement. If it is a regular
309  *     command response, all fields will be returned with the right,
310  *     native endianess.
311  *
312  *     You *cannot* use i2400m->bm_ack_buf for this buffer.
313  *
314  * @ack_size: size of @ack, 16 aligned; you need to provide at least
315  *     sizeof(*ack) bytes and then enough to contain the return data
316  *     from the command
317  *
318  * @flags: see I2400M_BM_CMD_* above.
319  *
320  * @returns: bytes received by the notification; if < 0, an errno code
321  *     denoting an error or:
322  *
323  *     -ERESTARTSYS  The device has rebooted
324  *
325  * Executes a boot-mode command and waits for a response, doing basic
326  * validation on it; if a zero length response is received, it retries
327  * waiting for a response until a non-zero one is received (timing out
328  * after %I2400M_BOOT_RETRIES retries).
329  */
330 static
331 ssize_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) {              /* send the command */
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);  /* bah, %zd doesn't work */
364                 goto error_wait_for_ack;
365         }
366         rx_bytes = result;
367         /* verify the ack and read more if neccessary [result is the
368          * final amount of bytes we get in the ack]  */
369         result = __i2400m_bm_ack_verify(i2400m, opcode, ack, ack_size, flags);
370         if (result < 0)
371                 goto error_bad_ack;
372         /* Don't you love this stack of empty targets? Well, I don't
373          * either, but it helps track exactly who comes in here and
374          * why :) */
375         result = rx_bytes;
376 error_bad_ack:
377 error_wait_for_ack:
378 error_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  * i2400m_download_chunk - write a single chunk of data to the device's memory
387  *
388  * @i2400m: device descriptor
389  * @buf: the buffer to write
390  * @buf_len: length of the buffer to write
391  * @addr: address in the device memory space
392  * @direct: bootrom write mode
393  * @do_csum: should a checksum validation be performed
394  */
395 static 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_PAD);
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  * Download a BCF file's sections to the device
433  *
434  * @i2400m: device descriptor
435  * @bcf: pointer to firmware data (followed by the payloads). Assumed
436  *       verified and consistent.
437  * @bcf_len: length (in bytes) of the @bcf buffer.
438  *
439  * Returns: < 0 errno code on error or the offset to the jump instruction.
440  *
441  * Given a BCF file, downloads each section (a command and a payload)
442  * to the device's address space. Actually, it just executes each
443  * command i the BCF file.
444  *
445  * The section size has to be aligned to 4 bytes AND the padding has
446  * to be taken from the firmware file, as the signature takes it into
447  * account.
448  */
449 static
450 ssize_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,          /* iterator offset */
456                 data_size,      /* Size of the data payload */
457                 section_size,   /* Size of the whole section (cmd + payload) */
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         /* Iterate over the command blocks in the BCF file that start
465          * after the header */
466         offset = le32_to_cpu(bcf->header_len) * sizeof(u32);
467         while (1) {     /* start sending the file */
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                         /* Secure boot needs to stop here */
477                         d_printf(5, dev,  "signed jump found @%zu\n", offset);
478                         break;
479                 }
480                 if (offset + section_size == bcf_len)
481                         /* Non-secure boot stops here */
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->bus_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->bus_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;
504 error_section_beyond_eof:
505 error_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  * Do the final steps of uploading firmware
514  *
515  * Depending on the boot mode (signed vs non-signed), different
516  * actions need to be taken.
517  */
518 static
519 int 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(3, 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(3, 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  * i2400m_bootrom_init - Reboots a powered device into boot mode
565  *
566  * @i2400m: device descriptor
567  * @flags:
568  *      I2400M_BRI_SOFT: a reboot notification has been seen
569  *          already, so don't wait for it.
570  *
571  *      I2400M_BRI_NO_REBOOT: Don't send a reboot command, but wait
572  *          for a reboot barker notification. This is a one shot; if
573  *          the state machine needs to send a reboot command it will.
574  *
575  * Returns:
576  *
577  *     < 0 errno code on error, 0 if ok.
578  *
579  *     i2400m->sboot set to 0 for unsecure boot process, 1 for secure
580  *     boot process.
581  *
582  * Description:
583  *
584  * Tries hard enough to put the device in boot-mode. There are two
585  * main phases to this:
586  *
587  * a. (1) send a reboot command and (2) get a reboot barker
588  * b. (1) ack the reboot sending a reboot barker and (2) getting an
589  *        ack barker in return
590  *
591  * We want to skip (a) in some cases [soft]. The state machine is
592  * horrible, but it is basically: on each phase, send what has to be
593  * sent (if any), wait for the answer and act on the answer. We might
594  * have to backtrack and retry, so we keep a max tries counter for
595  * that.
596  *
597  * If we get a timeout after sending a warm reset, we do it again.
598  */
599 int 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;
616 do_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:  /* we don't know how it got here...but we follow it */
631                 d_printf(4, dev, "device reboot: got ack barker - whatever\n");
632                 goto do_reboot;
633         case -ETIMEDOUT:        /* device has timed out, we might be in boot
634                                  * mode already and expecting an ack, let's try
635                                  * that */
636                 dev_info(dev, "warm reset timed out, trying an ack\n");
637                 goto do_reboot_ack;
638         case -EPROTO:
639         case -ESHUTDOWN:        /* dev is gone */
640         case -EINTR:            /* user cancelled */
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         /* At this point we ack back with 4 REBOOT barkers and expect
648          * 4 ACK barkers. This is ugly, as we send a raw command --
649          * hence the cast. _bm_cmd() will catch the reboot ack
650          * notification and report it as -EISCONN. */
651 do_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:        /* no response, maybe it is the other type? */
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:        /* dev is gone */
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;
692 exit_timeout:
693 error_dev_gone:
694         d_fnend(4, dev, "(i2400m %p flags 0x%08x) = %d\n",
695                 i2400m, flags, result);
696         return result;
697
698 error_timeout:
699         dev_err(dev, "Timed out waiting for reboot ack, resetting\n");
700         i2400m->bus_reset(i2400m, I2400M_RT_BUS);
701         result = -ETIMEDOUT;
702         goto exit_timeout;
703 }
704
705
706 /*
707  * Read the MAC addr
708  *
709  * The position this function reads is fixed in device memory and
710  * always available, even without firmware.
711  *
712  * Note we specify we want to read only six bytes, but provide space
713  * for 16, as we always get it rounded up.
714  */
715 int i2400m_read_mac_addr(struct i2400m *i2400m)
716 {
717         int result;
718         struct device *dev = i2400m_dev(i2400m);
719         struct net_device *net_dev = i2400m->wimax_dev.net_dev;
720         struct i2400m_bootrom_header *cmd;
721         struct {
722                 struct i2400m_bootrom_header ack;
723                 u8 ack_pl[16];
724         } __attribute__((packed)) ack_buf;
725
726         d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
727         cmd = i2400m->bm_cmd_buf;
728         cmd->command = i2400m_brh_command(I2400M_BRH_READ, 0, 1);
729         cmd->target_addr = cpu_to_le32(0x00203fe8);
730         cmd->data_size = cpu_to_le32(6);
731         result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
732                                &ack_buf.ack, sizeof(ack_buf), 0);
733         if (result < 0) {
734                 dev_err(dev, "BM: read mac addr failed: %d\n", result);
735                 goto error_read_mac;
736         }
737         d_printf(2, dev,
738                  "mac addr is %02x:%02x:%02x:%02x:%02x:%02x\n",
739                  ack_buf.ack_pl[0], ack_buf.ack_pl[1],
740                  ack_buf.ack_pl[2], ack_buf.ack_pl[3],
741                  ack_buf.ack_pl[4], ack_buf.ack_pl[5]);
742         if (i2400m->bus_bm_mac_addr_impaired == 1) {
743                 ack_buf.ack_pl[0] = 0x00;
744                 ack_buf.ack_pl[1] = 0x16;
745                 ack_buf.ack_pl[2] = 0xd3;
746                 get_random_bytes(&ack_buf.ack_pl[3], 3);
747                 dev_err(dev, "BM is MAC addr impaired, faking MAC addr to "
748                         "mac addr is %02x:%02x:%02x:%02x:%02x:%02x\n",
749                         ack_buf.ack_pl[0], ack_buf.ack_pl[1],
750                         ack_buf.ack_pl[2], ack_buf.ack_pl[3],
751                         ack_buf.ack_pl[4], ack_buf.ack_pl[5]);
752                 result = 0;
753         }
754         net_dev->addr_len = ETH_ALEN;
755         memcpy(net_dev->perm_addr, ack_buf.ack_pl, ETH_ALEN);
756         memcpy(net_dev->dev_addr, ack_buf.ack_pl, ETH_ALEN);
757 error_read_mac:
758         d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, result);
759         return result;
760 }
761
762
763 /*
764  * Initialize a non signed boot
765  *
766  * This implies sending some magic values to the device's memory. Note
767  * we convert the values to little endian in the same array
768  * declaration.
769  */
770 static
771 int i2400m_dnload_init_nonsigned(struct i2400m *i2400m)
772 {
773 #define POKE(a, d) {                                    \
774         .address = __constant_cpu_to_le32(a),           \
775         .data = __constant_cpu_to_le32(d)               \
776 }
777         static const struct {
778                 __le32 address;
779                 __le32 data;
780         } i2400m_pokes[] = {
781                 POKE(0x081A58, 0xA7810230),
782                 POKE(0x080040, 0x00000000),
783                 POKE(0x080048, 0x00000082),
784                 POKE(0x08004C, 0x0000081F),
785                 POKE(0x080054, 0x00000085),
786                 POKE(0x080058, 0x00000180),
787                 POKE(0x08005C, 0x00000018),
788                 POKE(0x080060, 0x00000010),
789                 POKE(0x080574, 0x00000001),
790                 POKE(0x080550, 0x00000005),
791                 POKE(0xAE0000, 0x00000000),
792         };
793 #undef POKE
794         unsigned i;
795         int ret;
796         struct device *dev = i2400m_dev(i2400m);
797
798         dev_warn(dev, "WARNING!!! non-signed boot UNTESTED PATH!\n");
799
800         d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
801         for (i = 0; i < ARRAY_SIZE(i2400m_pokes); i++) {
802                 ret = i2400m_download_chunk(i2400m, &i2400m_pokes[i].data,
803                                             sizeof(i2400m_pokes[i].data),
804                                             i2400m_pokes[i].address, 1, 1);
805                 if (ret < 0)
806                         break;
807         }
808         d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
809         return ret;
810 }
811
812
813 /*
814  * Initialize the signed boot process
815  *
816  * @i2400m: device descriptor
817  *
818  * @bcf_hdr: pointer to the firmware header; assumes it is fully in
819  *     memory (it has gone through basic validation).
820  *
821  * Returns: 0 if ok, < 0 errno code on error, -ERESTARTSYS if the hw
822  *     rebooted.
823  *
824  * This writes the firmware BCF header to the device using the
825  * HASH_PAYLOAD_ONLY command.
826  */
827 static
828 int i2400m_dnload_init_signed(struct i2400m *i2400m,
829                               const struct i2400m_bcf_hdr *bcf_hdr)
830 {
831         int ret;
832         struct device *dev = i2400m_dev(i2400m);
833         struct {
834                 struct i2400m_bootrom_header cmd;
835                 struct i2400m_bcf_hdr cmd_pl;
836         } __attribute__((packed)) *cmd_buf;
837         struct i2400m_bootrom_header ack;
838
839         d_fnstart(5, dev, "(i2400m %p bcf_hdr %p)\n", i2400m, bcf_hdr);
840         cmd_buf = i2400m->bm_cmd_buf;
841         cmd_buf->cmd.command =
842                 i2400m_brh_command(I2400M_BRH_HASH_PAYLOAD_ONLY, 0, 0);
843         cmd_buf->cmd.target_addr = 0;
844         cmd_buf->cmd.data_size = cpu_to_le32(sizeof(cmd_buf->cmd_pl));
845         memcpy(&cmd_buf->cmd_pl, bcf_hdr, sizeof(*bcf_hdr));
846         ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd, sizeof(*cmd_buf),
847                             &ack, sizeof(ack), 0);
848         if (ret >= 0)
849                 ret = 0;
850         d_fnend(5, dev, "(i2400m %p bcf_hdr %p) = %d\n", i2400m, bcf_hdr, ret);
851         return ret;
852 }
853
854
855 /*
856  * Initialize the firmware download at the device size
857  *
858  * Multiplex to the one that matters based on the device's mode
859  * (signed or non-signed).
860  */
861 static
862 int i2400m_dnload_init(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf)
863 {
864         int result;
865         struct device *dev = i2400m_dev(i2400m);
866         u32 module_id = le32_to_cpu(bcf->module_id);
867
868         if (i2400m->sboot == 0
869             && (module_id & I2400M_BCF_MOD_ID_POKES) == 0) {
870                 /* non-signed boot process without pokes */
871                 result = i2400m_dnload_init_nonsigned(i2400m);
872                 if (result == -ERESTARTSYS)
873                         return result;
874                 if (result < 0)
875                         dev_err(dev, "fw %s: non-signed download "
876                                 "initialization failed: %d\n",
877                                 i2400m->bus_fw_name, result);
878         } else if (i2400m->sboot == 0
879                  && (module_id & I2400M_BCF_MOD_ID_POKES)) {
880                 /* non-signed boot process with pokes, nothing to do */
881                 result = 0;
882         } else {                 /* signed boot process */
883                 result = i2400m_dnload_init_signed(i2400m, bcf);
884                 if (result == -ERESTARTSYS)
885                         return result;
886                 if (result < 0)
887                         dev_err(dev, "fw %s: signed boot download "
888                                 "initialization failed: %d\n",
889                                 i2400m->bus_fw_name, result);
890         }
891         return result;
892 }
893
894
895 /*
896  * Run quick consistency tests on the firmware file
897  *
898  * Check for the firmware being made for the i2400m device,
899  * etc...These checks are mostly informative, as the device will make
900  * them too; but the driver's response is more informative on what
901  * went wrong.
902  */
903 static
904 int i2400m_fw_check(struct i2400m *i2400m,
905                     const struct i2400m_bcf_hdr *bcf,
906                     size_t bcf_size)
907 {
908         int result;
909         struct device *dev = i2400m_dev(i2400m);
910         unsigned module_type, header_len, major_version, minor_version,
911                 module_id, module_vendor, date, size;
912
913         /* Check hard errors */
914         result = -EINVAL;
915         if (bcf_size < sizeof(*bcf)) {  /* big enough header? */
916                 dev_err(dev, "firmware %s too short: "
917                         "%zu B vs %zu (at least) expected\n",
918                         i2400m->bus_fw_name, bcf_size, sizeof(*bcf));
919                 goto error;
920         }
921
922         module_type = bcf->module_type;
923         header_len = sizeof(u32) * le32_to_cpu(bcf->header_len);
924         major_version = le32_to_cpu(bcf->header_version) & 0xffff0000 >> 16;
925         minor_version = le32_to_cpu(bcf->header_version) & 0x0000ffff;
926         module_id = le32_to_cpu(bcf->module_id);
927         module_vendor = le32_to_cpu(bcf->module_vendor);
928         date = le32_to_cpu(bcf->date);
929         size = sizeof(u32) * le32_to_cpu(bcf->size);
930
931         if (bcf_size != size) {         /* annoyingly paranoid */
932                 dev_err(dev, "firmware %s: bad size, got "
933                         "%zu B vs %u expected\n",
934                         i2400m->bus_fw_name, bcf_size, size);
935                 goto error;
936         }
937
938         d_printf(2, dev, "type 0x%x id 0x%x vendor 0x%x; header v%u.%u (%zu B) "
939                  "date %08x (%zu B)\n",
940                  module_type, module_id, module_vendor,
941                  major_version, minor_version, (size_t) header_len,
942                  date, (size_t) size);
943
944         if (module_type != 6) {         /* built for the right hardware? */
945                 dev_err(dev, "bad fw %s: unexpected module type 0x%x; "
946                         "aborting\n", i2400m->bus_fw_name, module_type);
947                 goto error;
948         }
949
950         /* Check soft-er errors */
951         result = 0;
952         if (module_vendor != 0x8086)
953                 dev_err(dev, "bad fw %s? unexpected vendor 0x%04x\n",
954                         i2400m->bus_fw_name, module_vendor);
955         if (date < 0x20080300)
956                 dev_err(dev, "bad fw %s? build date too old %08x\n",
957                         i2400m->bus_fw_name, date);
958 error:
959         return result;
960 }
961
962
963 /*
964  * Download the firmware to the device
965  *
966  * @i2400m: device descriptor
967  * @bcf: pointer to loaded (and minimally verified for consistency)
968  *    firmware
969  * @bcf_size: size of the @bcf buffer (header plus payloads)
970  *
971  * The process for doing this is described in this file's header.
972  *
973  * Note we only reinitialize boot-mode if the flags say so. Some hw
974  * iterations need it, some don't. In any case, if we loop, we always
975  * need to reinitialize the boot room, hence the flags modification.
976  */
977 static
978 int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf,
979                      size_t bcf_size, enum i2400m_bri flags)
980 {
981         int ret = 0;
982         struct device *dev = i2400m_dev(i2400m);
983         int count = I2400M_BOOT_RETRIES;
984
985         d_fnstart(5, dev, "(i2400m %p bcf %p size %zu)\n",
986                   i2400m, bcf, bcf_size);
987         i2400m->boot_mode = 1;
988 hw_reboot:
989         if (count-- == 0) {
990                 ret = -ERESTARTSYS;
991                 dev_err(dev, "device rebooted too many times, aborting\n");
992                 goto error_too_many_reboots;
993         }
994         if (flags & I2400M_BRI_MAC_REINIT) {
995                 ret = i2400m_bootrom_init(i2400m, flags);
996                 if (ret < 0) {
997                         dev_err(dev, "bootrom init failed: %d\n", ret);
998                         goto error_bootrom_init;
999                 }
1000         }
1001         flags |= I2400M_BRI_MAC_REINIT;
1002
1003         /*
1004          * Initialize the download, push the bytes to the device and
1005          * then jump to the new firmware. Note @ret is passed with the
1006          * offset of the jump instruction to _dnload_finalize()
1007          */
1008         ret = i2400m_dnload_init(i2400m, bcf);  /* Init device's dnload */
1009         if (ret == -ERESTARTSYS)
1010                 goto error_dev_rebooted;
1011         if (ret < 0)
1012                 goto error_dnload_init;
1013
1014         ret = i2400m_dnload_bcf(i2400m, bcf, bcf_size);
1015         if (ret == -ERESTARTSYS)
1016                 goto error_dev_rebooted;
1017         if (ret < 0) {
1018                 dev_err(dev, "fw %s: download failed: %d\n",
1019                         i2400m->bus_fw_name, ret);
1020                 goto error_dnload_bcf;
1021         }
1022
1023         ret = i2400m_dnload_finalize(i2400m, bcf, ret);
1024         if (ret == -ERESTARTSYS)
1025                 goto error_dev_rebooted;
1026         if (ret < 0) {
1027                 dev_err(dev, "fw %s: "
1028                         "download finalization failed: %d\n",
1029                         i2400m->bus_fw_name, ret);
1030                 goto error_dnload_finalize;
1031         }
1032
1033         d_printf(2, dev, "fw %s successfully uploaded\n",
1034                  i2400m->bus_fw_name);
1035         i2400m->boot_mode = 0;
1036 error_dnload_finalize:
1037 error_dnload_bcf:
1038 error_dnload_init:
1039 error_bootrom_init:
1040 error_too_many_reboots:
1041         d_fnend(5, dev, "(i2400m %p bcf %p size %zu) = %d\n",
1042                 i2400m, bcf, bcf_size, ret);
1043         return ret;
1044
1045 error_dev_rebooted:
1046         dev_err(dev, "device rebooted, %d tries left\n", count);
1047         /* we got the notification already, no need to wait for it again */
1048         flags |= I2400M_BRI_SOFT;
1049         goto hw_reboot;
1050 }
1051
1052
1053 /**
1054  * i2400m_dev_bootstrap - Bring the device to a known state and upload firmware
1055  *
1056  * @i2400m: device descriptor
1057  *
1058  * Returns: >= 0 if ok, < 0 errno code on error.
1059  *
1060  * This sets up the firmware upload environment, loads the firmware
1061  * file from disk, verifies and then calls the firmware upload process
1062  * per se.
1063  *
1064  * Can be called either from probe, or after a warm reset.  Can not be
1065  * called from within an interrupt.  All the flow in this code is
1066  * single-threade; all I/Os are synchronous.
1067  */
1068 int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags)
1069 {
1070         int ret = 0;
1071         struct device *dev = i2400m_dev(i2400m);
1072         const struct firmware *fw;
1073         const struct i2400m_bcf_hdr *bcf;       /* Firmware data */
1074
1075         d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
1076         /* Load firmware files to memory. */
1077         ret = request_firmware(&fw, i2400m->bus_fw_name, dev);
1078         if (ret) {
1079                 dev_err(dev, "fw %s: request failed: %d\n",
1080                         i2400m->bus_fw_name, ret);
1081                 goto error_fw_req;
1082         }
1083         bcf = (void *) fw->data;
1084
1085         ret = i2400m_fw_check(i2400m, bcf, fw->size);
1086         if (ret < 0)
1087                 goto error_fw_bad;
1088         ret = i2400m_fw_dnload(i2400m, bcf, fw->size, flags);
1089 error_fw_bad:
1090         release_firmware(fw);
1091 error_fw_req:
1092         d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
1093         return ret;
1094 }
1095 EXPORT_SYMBOL_GPL(i2400m_dev_bootstrap);