Signed-off-by: Michael Buesch <[EMAIL PROTECTED]>

Index: wireless-dev-new/drivers/net/wireless/b43/b43.h
===================================================================
--- wireless-dev-new.orig/drivers/net/wireless/b43/b43.h        2007-08-18 
19:05:09.000000000 +0200
+++ wireless-dev-new/drivers/net/wireless/b43/b43.h     2007-08-18 
19:12:05.000000000 +0200
@@ -405,11 +405,32 @@ enum {
 struct b43_dmaring;
 struct b43_pioqueue;
 
-struct b43_initval {
-       __be16 offset;
-       __be16 size;
-       __be32 value;
-} __attribute__ ((__packed__));
+/* The firmware file header */
+#define B43_FW_TYPE_UCODE      'u'
+#define B43_FW_TYPE_PCM                'p'
+#define B43_FW_TYPE_IV         'i'
+struct b43_fw_header {
+       /* File type */
+       u8 type;
+       /* File format version */
+       u8 ver;
+       u8 __padding[2];
+       /* Size of the data. For ucode and PCM this is in bytes.
+        * For IV this is number-of-ivs. */
+       __be32 size;
+} __attribute__((__packed__));
+
+/* Initial Value file format */
+#define B43_IV_OFFSET_MASK     0x7FFF
+#define B43_IV_32BIT           0x8000
+struct b43_iv {
+       __be16 offset_size;
+       union {
+               __be16 d16;
+               __be32 d32;
+       } data __attribute__((__packed__));
+} __attribute__((__packed__));
+
 
 #define B43_PHYMODE(phytype)           (1 << (phytype))
 #define B43_PHYMODE_A                  B43_PHYMODE(B43_PHYTYPE_A)
Index: wireless-dev-new/drivers/net/wireless/b43/main.c
===================================================================
--- wireless-dev-new.orig/drivers/net/wireless/b43/main.c       2007-08-18 
19:05:09.000000000 +0200
+++ wireless-dev-new/drivers/net/wireless/b43/main.c    2007-08-18 
23:13:21.000000000 +0200
@@ -39,6 +39,7 @@
 #include <linux/workqueue.h>
 #include <linux/skbuff.h>
 #include <linux/dma-mapping.h>
+#include <asm/unaligned.h>
 
 #include "b43.h"
 #include "main.h"
@@ -1585,6 +1586,8 @@ static int do_request_fw(struct b43_wlde
 {
        const size_t plen = sizeof(modparam_fwpostfix) + 32;
        char path[plen];
+       struct b43_fw_header *hdr;
+       u32 size;
        int err;
 
        if (!name)
@@ -1598,8 +1601,29 @@ static int do_request_fw(struct b43_wlde
                b43err(dev->wl, "Firmware file \"%s\" not found "
                       "or load failed.\n", path);
        }
+       if ((*fw)->size < sizeof(struct b43_fw_header))
+               goto err_format;
+       hdr = (struct b43_fw_header *)((*fw)->data);
+       switch (hdr->type) {
+       case B43_FW_TYPE_UCODE:
+       case B43_FW_TYPE_PCM:
+               size = be32_to_cpu(hdr->size);
+               if (size != (*fw)->size - sizeof(struct b43_fw_header))
+                       goto err_format;
+               /* fallthrough */
+       case B43_FW_TYPE_IV:
+               if (hdr->ver != 1)
+                       goto err_format;
+               break;
+       default:
+               goto err_format;
+       }
 
        return err;
+
+err_format:
+       b43err(dev->wl, "Firmware file \"%s\" format error.\n", path);
+       return -EPROTO;
 }
 
 static int b43_request_firmware(struct b43_wldev *dev)
@@ -1719,6 +1743,7 @@ error:
 
 static int b43_upload_microcode(struct b43_wldev *dev)
 {
+       const size_t hdr_len = sizeof(struct b43_fw_header);
        const __be32 *data;
        unsigned int i, len;
        u16 fwrev, fwpatch, fwdate, fwtime;
@@ -1726,24 +1751,26 @@ static int b43_upload_microcode(struct b
        int err = 0;
 
        /* Upload Microcode. */
-       data = (__be32 *) (dev->fw.ucode->data);
-       len = dev->fw.ucode->size / sizeof(__be32);
+       data = (__be32 *) (dev->fw.ucode->data + hdr_len);
+       len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32);
        b43_shm_control_word(dev, B43_SHM_UCODE | B43_SHM_AUTOINC_W, 0x0000);
        for (i = 0; i < len; i++) {
                b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i]));
                udelay(10);
        }
 
-       /* Upload PCM data. */
-       data = (__be32 *) (dev->fw.pcm->data);
-       len = dev->fw.pcm->size / sizeof(__be32);
-       b43_shm_control_word(dev, B43_SHM_HW, 0x01EA);
-       b43_write32(dev, B43_MMIO_SHM_DATA, 0x00004000);
-       /* No need for autoinc bit in SHM_HW */
-       b43_shm_control_word(dev, B43_SHM_HW, 0x01EB);
-       for (i = 0; i < len; i++) {
-               b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i]));
-               udelay(10);
+       if (dev->fw.pcm) {
+               /* Upload PCM data. */
+               data = (__be32 *) (dev->fw.pcm->data + hdr_len);
+               len = (dev->fw.pcm->size - hdr_len) / sizeof(__be32);
+               b43_shm_control_word(dev, B43_SHM_HW, 0x01EA);
+               b43_write32(dev, B43_MMIO_SHM_DATA, 0x00004000);
+               /* No need for autoinc bit in SHM_HW */
+               b43_shm_control_word(dev, B43_SHM_HW, 0x01EB);
+               for (i = 0; i < len; i++) {
+                       b43_write32(dev, B43_MMIO_SHM_DATA, 
be32_to_cpu(data[i]));
+                       udelay(10);
+               }
        }
 
        b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_ALL);
@@ -1797,34 +1824,61 @@ static int b43_upload_microcode(struct b
 }
 
 static int b43_write_initvals(struct b43_wldev *dev,
-                             const struct b43_initval *data,
-                             size_t count)
+                             const struct b43_iv *ivals,
+                             size_t count,
+                             size_t array_size)
 {
-       u16 offset, size;
-       u32 value;
+       const struct b43_iv *iv;
+       u16 offset;
        size_t i;
+       bool bit32;
 
+       BUILD_BUG_ON(sizeof(struct b43_iv) != 6);
+       iv = ivals;
        for (i = 0; i < count; i++) {
-               offset = be16_to_cpu(data[i].offset);
-               size = be16_to_cpu(data[i].size);
-               value = be32_to_cpu(data[i].value);
-
-               if (unlikely(offset >= 0x1000))
+               if (array_size < sizeof(iv->offset_size))
                        goto err_format;
-               if (size == 2) {
-                       if (unlikely(value & 0xFFFF0000))
+               array_size -= sizeof(iv->offset_size);
+               offset = be16_to_cpu(iv->offset_size);
+               bit32 = !!(offset & B43_IV_32BIT);
+               offset &= B43_IV_OFFSET_MASK;
+               if (offset >= 0x1000)
+                       goto err_format;
+               if (bit32) {
+                       u32 value;
+
+                       if (array_size < sizeof(iv->data.d32))
                                goto err_format;
-                       b43_write16(dev, offset, (u16) value);
-               } else if (size == 4) {
+                       array_size -= sizeof(iv->data.d32);
+
+                       value = be32_to_cpu(get_unaligned(&iv->data.d32));
                        b43_write32(dev, offset, value);
-               } else
-                       goto err_format;
+
+                       iv = (const struct b43_iv *)((const uint8_t *)iv +
+                                                       sizeof(__be16) +
+                                                       sizeof(__be32));
+               } else {
+                       u16 value;
+
+                       if (array_size < sizeof(iv->data.d16))
+                               goto err_format;
+                       array_size -= sizeof(iv->data.d16);
+
+                       value = be16_to_cpu(iv->data.d16);
+                       b43_write16(dev, offset, value);
+
+                       iv = (const struct b43_iv *)((const uint8_t *)iv +
+                                                       sizeof(__be16) +
+                                                       sizeof(__be16));
+               }
        }
+       if (array_size)
+               goto err_format;
 
        return 0;
 
 err_format:
-       b43err(dev->wl, "Initial Values Firmware file-format error\n");
+       b43err(dev->wl, "Initial Values Firmware file-format error.\n");
        b43_print_fw_helptext(dev->wl);
 
        return -EPROTO;
@@ -1832,20 +1886,28 @@ err_format:
 
 static int b43_upload_initvals(struct b43_wldev *dev)
 {
+       const size_t hdr_len = sizeof(struct b43_fw_header);
+       const struct b43_fw_header *hdr;
        struct b43_firmware *fw = &dev->fw;
-       struct b43_initval *ivals;
+       const struct b43_iv *ivals;
        size_t count;
        int err;
 
-       ivals = (struct b43_initval *)(fw->initvals->data);
-       count = fw->initvals->size / sizeof(struct b43_initval);
-       err = b43_write_initvals(dev, ivals, count);
+       hdr = (const struct b43_fw_header *)(fw->initvals->data);
+       ivals = (const struct b43_iv *)(fw->initvals->data + hdr_len);
+       count = be32_to_cpu(hdr->size);
+       err = b43_write_initvals(dev, ivals, count,
+                                fw->initvals->size - hdr_len);
        if (err)
                goto out;
        if (fw->initvals_band) {
-               ivals = (struct b43_initval *)(fw->initvals_band->data);
-               count = fw->initvals_band->size / sizeof(struct b43_initval);
-               err = b43_write_initvals(dev, ivals, count);
+               hdr = (const struct b43_fw_header *)(fw->initvals_band->data);
+               ivals = (const struct b43_iv *)(fw->initvals_band->data + 
hdr_len);
+               count = be32_to_cpu(hdr->size);
+               err = b43_write_initvals(dev, ivals, count,
+                                        fw->initvals_band->size - hdr_len);
+               if (err)
+                       goto out;
        }
 out:
 

-- 

_______________________________________________
Bcm43xx-dev mailing list
Bcm43xx-dev@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev

Reply via email to