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);