Ok, here is the new version of the firmware version detection patch.
I hope it's in a better shape now.

Martin
--- ../../linux-2.6.17/drivers/base/firmware_class.c    2006-06-18 
03:49:35.000000000 +0200
+++ drivers/base/firmware_class.c       2006-07-06 23:13:29.000000000 +0200
@@ -15,6 +15,8 @@
 #include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
 #include <asm/semaphore.h>
 
 #include <linux/firmware.h>
@@ -48,6 +50,32 @@
        struct timer_list timeout;
 };
 
+u32 firmware_version(const struct firmware *fw, struct firmware_files *elmnt)
+{
+       struct scatterlist sg;
+       struct crypto_tfm *tfm;
+       char sig[16];
+
+       tfm = crypto_alloc_tfm("md5", 0);
+       if (tfm == NULL)
+               return 0;
+
+       sg_init_one(&sg, fw->data, fw->size);
+
+       crypto_digest_init(tfm);
+       crypto_digest_update(tfm, &sg, 1);
+       crypto_digest_final(tfm, sig);
+       crypto_free_tfm(tfm);
+
+       while (elmnt->version) {
+               if (memcmp(sig, elmnt->signature, sizeof(sig)) == 0)
+                       return elmnt->version;
+               elmnt++;
+       }
+
+       return 0;
+}
+
 static void
 fw_load_abort(struct firmware_priv *fw_priv)
 {
@@ -605,6 +633,7 @@
 module_init(firmware_class_init);
 module_exit(firmware_class_exit);
 
+EXPORT_SYMBOL(firmware_version);
 EXPORT_SYMBOL(release_firmware);
 EXPORT_SYMBOL(request_firmware);
 EXPORT_SYMBOL(request_firmware_nowait);
--- ../../linux-2.6.17/include/linux/firmware.h 2006-06-18 03:49:35.000000000 
+0200
+++ include/linux/firmware.h    2006-07-06 23:33:33.000000000 +0200
@@ -10,7 +10,12 @@
        size_t size;
        u8 *data;
 };
+struct firmware_files {
+       u8 signature[16];
+       u32 version;
+};
 struct device;
+u32 firmware_version(const struct firmware *fw, struct firmware_files *elmnt);
 int request_firmware(const struct firmware **fw, const char *name,
                     struct device *device);
 int request_firmware_nowait(
--- ../../linux-2.6.17/drivers/base/Kconfig     2006-06-18 03:49:35.000000000 
+0200
+++ drivers/base/Kconfig        2006-07-06 23:19:06.000000000 +0200
@@ -20,6 +20,7 @@
 
 config FW_LOADER
        tristate "Userspace firmware loading support"
+       depends on CRYPTO_MD5
        select HOTPLUG
        ---help---
          This option is provided for the case where no in-kernel-tree modules
--- ../../linux-2.6.17/drivers/net/wireless/bcm43xx/bcm43xx_main.c      
2006-06-18 03:49:35.000000000 +0200
+++ drivers/net/wireless/bcm43xx/bcm43xx_main.c 2006-07-06 23:16:43.000000000 
+0200
@@ -148,6 +148,22 @@
 };
 MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl);
 
+static struct firmware_files ucode_version_tbl[] = {
+       { { 0xed, 0x55, 0x26, 0xf9, 0x2e, 0xcb, 0x8f, 0x76, 0x90, 0x34, 0xa0, 
+           0xf1, 0x67, 0x33, 0x00, 0x5f }, FW_VERSION(3, 130, 20, 0) },
+       { { 0x65, 0x1e, 0x4f, 0xc1, 0x92, 0xb6, 0xae, 0x16, 0xb2, 0xf6, 0x39,
+           0x56, 0xc5, 0x66, 0x8d, 0xbd }, FW_VERSION(4, 10, 40, 0) },
+       {},
+};
+
+static struct firmware_files pcm_version_tbl[] = {
+       { { 0x2d, 0x0f, 0xd4, 0x02, 0x88, 0x9d, 0xf1, 0xd1, 0xf6, 0xb3, 0xdd,
+           0x8b, 0x4d, 0x37, 0xcc, 0x9a }, FW_VERSION(3, 30, 15, 0) },
+       { { 0xff, 0x29, 0xcd, 0x07, 0x56, 0x75, 0xa5, 0x44, 0xbd, 0xc5, 0xd5,
+           0xae, 0x95, 0x3d, 0x96, 0x4a }, FW_VERSION(3, 90, 7, 0) },
+       {},
+};
+
 static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val)
 {
        u32 status;
@@ -1930,6 +1946,7 @@
 {
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        u8 rev = bcm->current_core->rev;
+       u32 ver = 0;
        int err = 0;
        int nr;
        char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
@@ -1945,6 +1962,18 @@
                                buf);
                        goto error;
                }
+
+               ver = firmware_version(bcm->ucode, ucode_version_tbl);
+               if (ver != 0) {
+                       printk(KERN_INFO PFX "UCODE: %s version %i.%i.%i.%i\n",
+                              buf, 
+                              (ver & 0xFF000000) >> 24, 
+                              (ver & 0x00FF0000) >> 16, 
+                              (ver & 0x0000FF00) >> 8, 
+                              (ver & 0x000000FF));
+               } else
+                       printk(KERN_INFO PFX "UCODE: %s detection failure.\n", 
+                              buf);
        }
 
        if (!bcm->pcm) {
@@ -1959,6 +1988,18 @@
                               buf);
                        goto error;
                }
+
+               ver = firmware_version(bcm->pcm, pcm_version_tbl);
+               if (ver != 0) {
+                       printk(KERN_INFO PFX "PCM: %s version %i.%i.%i.%i\n",
+                              buf, 
+                              (ver & 0xFF000000) >> 24, 
+                              (ver & 0x00FF0000) >> 16, 
+                              (ver & 0x0000FF00) >> 8, 
+                              (ver & 0x000000FF));
+               } else
+                       printk(KERN_INFO PFX "PCM: %s detection failure.\n", 
+                              buf);
        }
 
        if (!bcm->initvals0) {
--- ../../linux-2.6.17/drivers/net/wireless/bcm43xx/bcm43xx.h   2006-06-18 
03:49:35.000000000 +0200
+++ drivers/net/wireless/bcm43xx/bcm43xx.h      2006-07-06 23:24:35.000000000 
+0200
@@ -345,6 +345,8 @@
        BCM43xx_SEC_ALGO_TKIP,
 };
 
+#define FW_VERSION(a, b, c, d) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d))
+
 #ifdef assert
 # undef assert
 #endif

Reply via email to