2 * Intel Wireless WiMAX Connection 2400m
6 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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
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.
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.
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
43 * (this is decribed for USB, but for SDIO is similar)
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.
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.
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
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.
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.
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()].
81 * Once firmware is uploaded, we are good to go :)
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.
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.
95 * BACKEND IMPLEMENTATION
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)
104 * i2400m_dev_bootstrap Called by __i2400m_dev_start()
111 * i2400m_bootrom_init
115 * i2400m_dnload_init_signed
116 * i2400m_dnload_init_nonsigned
117 * i2400m_download_chunk
121 * i2400m_dnload_finalize
125 * i2400m->bus_bm_cmd_send()
126 * i2400m->bus_bm_wait_for_ack
127 * __i2400m_bm_ack_verify
129 * i2400m_bm_cmd_prepare Used by bus-drivers to prep
130 * commands before sending
132 #include <linux/firmware.h>
133 #include <linux/sched.h>
134 #include <linux/usb.h>
138 #define D_SUBMODULE fw
139 #include "debug-levels.h"
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)
151 * Prepare a boot-mode command for delivery
153 * @cmd: pointer to bootrom header to prepare
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.
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.
162 void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *cmd)
164 if (i2400m_brh_get_use_checksum(cmd)) {
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);
174 EXPORT_SYMBOL_GPL(i2400m_bm_cmd_prepare);
178 * Verify the ack data received
180 * Given a reply to a boot mode command, chew it and verify everything
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.
188 * Way too long function -- maybe it should be further split
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)
195 ssize_t result = -ENOMEM;
196 struct device *dev = i2400m_dev(i2400m);
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)) {
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;
207 if (ack_size == sizeof(i2400m_NBOOT_BARKER)
208 && memcmp(ack, i2400m_NBOOT_BARKER, sizeof(*ack)) == 0) {
209 result = -ERESTARTSYS;
211 d_printf(6, dev, "boot-mode cmd %d: "
212 "HW non-signed boot barker\n", opcode);
215 if (ack_size == sizeof(i2400m_SBOOT_BARKER)
216 && memcmp(ack, i2400m_SBOOT_BARKER, sizeof(*ack)) == 0) {
217 result = -ERESTARTSYS;
219 d_printf(6, dev, "boot-mode cmd %d: HW signed reboot barker\n",
223 if (ack_size == sizeof(i2400m_ACK_BARKER)
224 && memcmp(ack, i2400m_ACK_BARKER, sizeof(*ack)) == 0) {
226 d_printf(3, dev, "boot-mode cmd %d: HW reboot ack barker\n",
228 goto error_reboot_ack;
231 if (flags & I2400M_BM_CMD_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));
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;
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;
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;
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;
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
271 error_ack_short_buffer:
279 d_fnend(8, dev, "(i2400m %p opcode %d ack %p size %zu) = %d\n",
280 i2400m, opcode, ack, ack_size, (int) result);
286 * i2400m_bm_cmd - Execute a boot mode command
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
293 * A raw buffer can be also sent, just cast it and set flags to
296 * This function will generate a checksum for you if the
297 * checksum bit in the command is set (unless I2400M_BM_CMD_RAW
300 * You can use the i2400m->bm_cmd_buf to stage your commands and
303 * If NULL, no command is sent (we just wait for an ack).
305 * @cmd_size: size of the command. Will be auto padded to the
306 * bus-specific drivers padding requirements.
308 * @ack: buffer where to place the acknowledgement. If it is a regular
309 * command response, all fields will be returned with the right,
312 * You *cannot* use i2400m->bm_ack_buf for this buffer.
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
318 * @flags: see I2400M_BM_CMD_* above.
320 * @returns: bytes received by the notification; if < 0, an errno code
321 * denoting an error or:
323 * -ERESTARTSYS The device has rebooted
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).
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,
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);
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);
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);
350 if ((flags & I2400M_BM_CMD_RAW) == 0)
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);
360 result = i2400m->bus_bm_wait_for_ack(i2400m, ack, ack_size);
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;
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);
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
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);
386 * i2400m_download_chunk - write a single chunk of data to the device's memory
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
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)
400 size_t chunk_len = ALIGN(__chunk_len, I2400M_PL_PAD);
401 struct device *dev = i2400m_dev(i2400m);
403 struct i2400m_bootrom_header cmd;
404 u8 cmd_payload[chunk_len];
405 } __attribute__((packed)) *buf;
406 struct i2400m_bootrom_header ack;
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);
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);
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);
432 * Download a BCF file's sections to the device
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.
439 * Returns: < 0 errno code on error or the offset to the jump instruction.
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.
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
450 ssize_t i2400m_dnload_bcf(struct i2400m *i2400m,
451 const struct i2400m_bcf_hdr *bcf, size_t bcf_len)
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) */
459 const struct i2400m_bootrom_header *bh;
460 struct i2400m_bootrom_header ack;
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);
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);
480 if (offset + section_size == bcf_len)
481 /* Non-secure boot stops here */
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);
489 goto error_section_beyond_eof;
492 ret = i2400m_bm_cmd(i2400m, bh, section_size,
493 &ack, sizeof(ack), I2400M_BM_CMD_RAW);
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);
500 offset += section_size;
504 error_section_beyond_eof:
506 d_fnend(3, dev, "(i2400m %p bcf %p bcf_len %zu) = %d\n",
507 i2400m, bcf, bcf_len, (int) ret);
513 * Do the final steps of uploading firmware
515 * Depending on the boot mode (signed vs non-signed), different
516 * actions need to be taken.
519 int i2400m_dnload_finalize(struct i2400m *i2400m,
520 const struct i2400m_bcf_hdr *bcf, size_t offset)
523 struct device *dev = i2400m_dev(i2400m);
524 struct i2400m_bootrom_header *cmd, ack;
526 struct i2400m_bootrom_header cmd;
528 } __attribute__((packed)) *cmd_buf;
529 size_t signature_block_offset, signature_block_size;
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);
539 ret = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
540 &jump_ack, sizeof(jump_ack), 0);
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 =
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);
558 d_fnend(3, dev, "returning %d\n", ret);
564 * i2400m_bootrom_init - Reboots a powered device into boot mode
566 * @i2400m: device descriptor
568 * I2400M_BRI_SOFT: a reboot notification has been seen
569 * already, so don't wait for it.
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.
577 * < 0 errno code on error, 0 if ok.
579 * i2400m->sboot set to 0 for unsecure boot process, 1 for secure
584 * Tries hard enough to put the device in boot-mode. There are two
585 * main phases to this:
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
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
597 * If we get a timeout after sending a warm reset, we do it again.
599 int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags)
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;
608 BUILD_BUG_ON(sizeof(*cmd) != sizeof(i2400m_NBOOT_BARKER));
609 BUILD_BUG_ON(sizeof(ack) != sizeof(i2400m_ACK_BARKER));
611 d_fnstart(4, dev, "(i2400m %p flags 0x%08x)\n", i2400m, flags);
613 cmd = i2400m->bm_cmd_buf;
614 if (flags & I2400M_BRI_SOFT)
619 d_printf(4, dev, "device reboot: reboot command [%d # left]\n",
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),
625 flags &= ~I2400M_BRI_NO_REBOOT;
628 d_printf(4, dev, "device reboot: got reboot barker\n");
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");
633 case -ETIMEDOUT: /* device has timed out, we might be in boot
634 * mode already and expecting an ack, let's try
636 dev_info(dev, "warm reset timed out, trying an ack\n");
639 case -ESHUTDOWN: /* dev is gone */
640 case -EINTR: /* user cancelled */
643 dev_err(dev, "device reboot: error %d while waiting "
644 "for reboot barker - rebooting\n", result);
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. */
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));
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);
663 d_printf(4, dev, "reboot ack: got reboot barker - retrying\n");
668 d_printf(4, dev, "reboot ack: got ack barker - good\n");
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;
677 dev_err(dev, "reboot ack timedout too long: "
683 case -ESHUTDOWN: /* dev is gone */
686 dev_err(dev, "device reboot ack: error %d while waiting for "
687 "reboot ack barker - rebooting\n", result);
690 d_printf(2, dev, "device reboot ack: got ack barker - boot done\n");
694 d_fnend(4, dev, "(i2400m %p flags 0x%08x) = %d\n",
695 i2400m, flags, result);
699 dev_err(dev, "Timed out waiting for reboot ack, resetting\n");
700 i2400m->bus_reset(i2400m, I2400M_RT_BUS);
709 * The position this function reads is fixed in device memory and
710 * always available, even without firmware.
712 * Note we specify we want to read only six bytes, but provide space
713 * for 16, as we always get it rounded up.
715 int i2400m_read_mac_addr(struct i2400m *i2400m)
718 struct device *dev = i2400m_dev(i2400m);
719 struct net_device *net_dev = i2400m->wimax_dev.net_dev;
720 struct i2400m_bootrom_header *cmd;
722 struct i2400m_bootrom_header ack;
724 } __attribute__((packed)) ack_buf;
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);
734 dev_err(dev, "BM: read mac addr failed: %d\n", result);
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]);
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);
758 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, result);
764 * Initialize a non signed boot
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
771 int i2400m_dnload_init_nonsigned(struct i2400m *i2400m)
773 #define POKE(a, d) { \
774 .address = __constant_cpu_to_le32(a), \
775 .data = __constant_cpu_to_le32(d) \
777 static const struct {
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),
796 struct device *dev = i2400m_dev(i2400m);
798 dev_warn(dev, "WARNING!!! non-signed boot UNTESTED PATH!\n");
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);
808 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
814 * Initialize the signed boot process
816 * @i2400m: device descriptor
818 * @bcf_hdr: pointer to the firmware header; assumes it is fully in
819 * memory (it has gone through basic validation).
821 * Returns: 0 if ok, < 0 errno code on error, -ERESTARTSYS if the hw
824 * This writes the firmware BCF header to the device using the
825 * HASH_PAYLOAD_ONLY command.
828 int i2400m_dnload_init_signed(struct i2400m *i2400m,
829 const struct i2400m_bcf_hdr *bcf_hdr)
832 struct device *dev = i2400m_dev(i2400m);
834 struct i2400m_bootrom_header cmd;
835 struct i2400m_bcf_hdr cmd_pl;
836 } __attribute__((packed)) *cmd_buf;
837 struct i2400m_bootrom_header ack;
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);
850 d_fnend(5, dev, "(i2400m %p bcf_hdr %p) = %d\n", i2400m, bcf_hdr, ret);
856 * Initialize the firmware download at the device size
858 * Multiplex to the one that matters based on the device's mode
859 * (signed or non-signed).
862 int i2400m_dnload_init(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf)
865 struct device *dev = i2400m_dev(i2400m);
866 u32 module_id = le32_to_cpu(bcf->module_id);
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)
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 */
882 } else { /* signed boot process */
883 result = i2400m_dnload_init_signed(i2400m, bcf);
884 if (result == -ERESTARTSYS)
887 dev_err(dev, "fw %s: signed boot download "
888 "initialization failed: %d\n",
889 i2400m->bus_fw_name, result);
896 * Run quick consistency tests on the firmware file
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
904 int i2400m_fw_check(struct i2400m *i2400m,
905 const struct i2400m_bcf_hdr *bcf,
909 struct device *dev = i2400m_dev(i2400m);
910 unsigned module_type, header_len, major_version, minor_version,
911 module_id, module_vendor, date, size;
913 /* Check hard errors */
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));
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);
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);
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);
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);
950 /* Check soft-er errors */
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);
964 * Download the firmware to the device
966 * @i2400m: device descriptor
967 * @bcf: pointer to loaded (and minimally verified for consistency)
969 * @bcf_size: size of the @bcf buffer (header plus payloads)
971 * The process for doing this is described in this file's header.
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.
978 int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf,
979 size_t bcf_size, enum i2400m_bri flags)
982 struct device *dev = i2400m_dev(i2400m);
983 int count = I2400M_BOOT_RETRIES;
985 d_fnstart(5, dev, "(i2400m %p bcf %p size %zu)\n",
986 i2400m, bcf, bcf_size);
987 i2400m->boot_mode = 1;
991 dev_err(dev, "device rebooted too many times, aborting\n");
992 goto error_too_many_reboots;
994 if (flags & I2400M_BRI_MAC_REINIT) {
995 ret = i2400m_bootrom_init(i2400m, flags);
997 dev_err(dev, "bootrom init failed: %d\n", ret);
998 goto error_bootrom_init;
1001 flags |= I2400M_BRI_MAC_REINIT;
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()
1008 ret = i2400m_dnload_init(i2400m, bcf); /* Init device's dnload */
1009 if (ret == -ERESTARTSYS)
1010 goto error_dev_rebooted;
1012 goto error_dnload_init;
1014 ret = i2400m_dnload_bcf(i2400m, bcf, bcf_size);
1015 if (ret == -ERESTARTSYS)
1016 goto error_dev_rebooted;
1018 dev_err(dev, "fw %s: download failed: %d\n",
1019 i2400m->bus_fw_name, ret);
1020 goto error_dnload_bcf;
1023 ret = i2400m_dnload_finalize(i2400m, bcf, ret);
1024 if (ret == -ERESTARTSYS)
1025 goto error_dev_rebooted;
1027 dev_err(dev, "fw %s: "
1028 "download finalization failed: %d\n",
1029 i2400m->bus_fw_name, ret);
1030 goto error_dnload_finalize;
1033 d_printf(2, dev, "fw %s successfully uploaded\n",
1034 i2400m->bus_fw_name);
1035 i2400m->boot_mode = 0;
1036 error_dnload_finalize:
1040 error_too_many_reboots:
1041 d_fnend(5, dev, "(i2400m %p bcf %p size %zu) = %d\n",
1042 i2400m, bcf, bcf_size, ret);
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;
1054 * i2400m_dev_bootstrap - Bring the device to a known state and upload firmware
1056 * @i2400m: device descriptor
1058 * Returns: >= 0 if ok, < 0 errno code on error.
1060 * This sets up the firmware upload environment, loads the firmware
1061 * file from disk, verifies and then calls the firmware upload process
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.
1068 int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags)
1071 struct device *dev = i2400m_dev(i2400m);
1072 const struct firmware *fw;
1073 const struct i2400m_bcf_hdr *bcf; /* Firmware data */
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);
1079 dev_err(dev, "fw %s: request failed: %d\n",
1080 i2400m->bus_fw_name, ret);
1083 bcf = (void *) fw->data;
1085 ret = i2400m_fw_check(i2400m, bcf, fw->size);
1088 ret = i2400m_fw_dnload(i2400m, bcf, fw->size, flags);
1090 release_firmware(fw);
1092 d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
1095 EXPORT_SYMBOL_GPL(i2400m_dev_bootstrap);