[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: bnx2 request_firmware patch - first try



On Thu, Feb 07, 2008 at 04:10:56PM +0100, Bastian Blank wrote:
> This is the first version of the bnx2 request_firmware patch. It works
> with the 4.0.5 firmware from the bnx2 version in 2.6.25.

Second version, it fixes the problems and changes the firmware names a
little bit.

I also attached the updated firmware extractor.

Bastian

-- 
Our missions are peaceful -- not for conquest.  When we do battle, it
is only because we have no choice.
		-- Kirk, "The Squire of Gothos", stardate 2124.5
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 8b552c6..ec72b56 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -46,11 +46,10 @@
 #include <linux/crc32.h>
 #include <linux/prefetch.h>
 #include <linux/cache.h>
-#include <linux/zlib.h>
+#include <linux/firmware.h>
 
 #include "bnx2.h"
-#include "bnx2_fw.h"
-#include "bnx2_fw2.h"
+#include "bnx2_fw_file.h"
 
 #define FW_BUF_SIZE		0x10000
 
@@ -58,12 +57,20 @@
 #define PFX DRV_MODULE_NAME	": "
 #define DRV_MODULE_VERSION	"1.7.3"
 #define DRV_MODULE_RELDATE	"January 29, 2008"
+#define FW_FILE_06		"bnx2-06-4.0.5.fw"
+#define FW_FILE_09		"bnx2-09-4.0.5.fw"
 
 #define RUN_AT(x) (jiffies + (x))
 
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (5*HZ)
 
+#ifdef DEBUG
+#  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#  define DPRINTK(fmt, args...)
+#endif
+
 static const char version[] __devinitdata =
 	"Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
@@ -71,6 +78,8 @@ MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
 MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708 Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_FIRMWARE(FW_FILE_06);
+MODULE_FIRMWARE(FW_FILE_09);
 
 static int disable_msi = 0;
 
@@ -3161,26 +3170,32 @@ bnx2_set_rx_mode(struct net_device *dev)
 	spin_unlock_bh(&bp->phy_lock);
 }
 
-static void
-load_rv2p_fw(struct bnx2 *bp, __le32 *rv2p_code, u32 rv2p_code_len,
-	u32 rv2p_proc)
+static int
+load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc, const struct bnx2_fw_file_section *fw_section)
 {
-	int i;
+	int i, len, offset;
+	u32 *data;
 	u32 val;
 
+	len = be32_to_cpu(fw_section->len);
+	offset = be32_to_cpu(fw_section->offset);
+
+	if (!len || !offset || len + offset > bp->firmware->size)
+		return -EINVAL;
+	DPRINTK("load rv2p firmware with length %u from file offset %u\n", len, offset);
+
+	data = (u32 *)(bp->firmware->data + offset);
 
-	for (i = 0; i < rv2p_code_len; i += 8) {
-		REG_WR(bp, BNX2_RV2P_INSTR_HIGH, le32_to_cpu(*rv2p_code));
-		rv2p_code++;
-		REG_WR(bp, BNX2_RV2P_INSTR_LOW, le32_to_cpu(*rv2p_code));
-		rv2p_code++;
+	for (i = 0; i < (len / 4); i += 2) {
+		REG_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(data[i]));
+		REG_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(data[i+1]));
 
 		if (rv2p_proc == RV2P_PROC1) {
-			val = (i / 8) | BNX2_RV2P_PROC1_ADDR_CMD_RDWR;
+			val = (i / 2) | BNX2_RV2P_PROC1_ADDR_CMD_RDWR;
 			REG_WR(bp, BNX2_RV2P_PROC1_ADDR_CMD, val);
 		}
 		else {
-			val = (i / 8) | BNX2_RV2P_PROC2_ADDR_CMD_RDWR;
+			val = (i / 2) | BNX2_RV2P_PROC2_ADDR_CMD_RDWR;
 			REG_WR(bp, BNX2_RV2P_PROC2_ADDR_CMD, val);
 		}
 	}
@@ -3192,14 +3207,18 @@ load_rv2p_fw(struct bnx2 *bp, __le32 *rv2p_code, u32 rv2p_code_len,
 	else {
 		REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET);
 	}
+
+	return 0;
 }
 
 static int
-load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
+load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg,
+	    const struct bnx2_fw_file_entry *fw_entry)
 {
+	u32 addr, len, file_offset;
 	u32 offset;
 	u32 val;
-	int rc;
+	u32 *data;
 
 	/* Halt the CPU. */
 	val = bnx2_reg_rd_ind(bp, cpu_reg->mode);
@@ -3208,64 +3227,87 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
 	bnx2_reg_wr_ind(bp, cpu_reg->state, cpu_reg->state_value_clear);
 
 	/* Load the Text area. */
-	offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
-	if (fw->gz_text) {
+	addr = be32_to_cpu(fw_entry->text.addr);
+	len = be32_to_cpu(fw_entry->text.len);
+	file_offset = be32_to_cpu(fw_entry->text.offset);
+	data = (u32 *)(bp->firmware->data + file_offset);
+	DPRINTK("load text section to %x with length %u from file offset %x\n", addr, len, file_offset);
+
+	offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base);
+	if (len) {
 		int j;
 
-		rc = zlib_inflate_blob(fw->text, FW_BUF_SIZE, fw->gz_text,
-				       fw->gz_text_len);
-		if (rc < 0)
-			return rc;
-
-		for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
-			bnx2_reg_wr_ind(bp, offset, le32_to_cpu(fw->text[j]));
+		for (j = 0; j < (len / 4); j++, offset += 4) {
+			bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j]));
 	        }
 	}
 
 	/* Load the Data area. */
-	offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base);
-	if (fw->data) {
+	addr = be32_to_cpu(fw_entry->data.addr);
+	len = be32_to_cpu(fw_entry->data.len);
+	file_offset = be32_to_cpu(fw_entry->data.offset);
+	data = (u32 *)(bp->firmware->data + file_offset);
+	DPRINTK("load data section to %x with length %u from file offset %x\n", addr, len, file_offset);
+
+	offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base);
+	if (len) {
 		int j;
 
-		for (j = 0; j < (fw->data_len / 4); j++, offset += 4) {
-			bnx2_reg_wr_ind(bp, offset, fw->data[j]);
+		for (j = 0; j < (len / 4); j++, offset += 4) {
+			bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j]));
 		}
 	}
 
 	/* Load the SBSS area. */
-	offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base);
-	if (fw->sbss_len) {
+	addr = be32_to_cpu(fw_entry->sbss.addr);
+	len = be32_to_cpu(fw_entry->sbss.len);
+	DPRINTK("init sbss section on %x with length %u\n", addr, len);
+
+	offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base);
+	if (len) {
 		int j;
 
-		for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) {
+		for (j = 0; j < (len / 4); j++, offset += 4) {
 			bnx2_reg_wr_ind(bp, offset, 0);
 		}
 	}
 
 	/* Load the BSS area. */
-	offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base);
-	if (fw->bss_len) {
+	addr = be32_to_cpu(fw_entry->bss.addr);
+	len = be32_to_cpu(fw_entry->bss.len);
+	DPRINTK("init bss section on %x with length %u\n", addr, len);
+
+	offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base);
+	if (len) {
 		int j;
 
-		for (j = 0; j < (fw->bss_len/4); j++, offset += 4) {
+		for (j = 0; j < (len / 4); j++, offset += 4) {
 			bnx2_reg_wr_ind(bp, offset, 0);
 		}
 	}
 
 	/* Load the Read-Only area. */
-	offset = cpu_reg->spad_base +
-		(fw->rodata_addr - cpu_reg->mips_view_base);
-	if (fw->rodata) {
+	addr = be32_to_cpu(fw_entry->rodata.addr);
+	len = be32_to_cpu(fw_entry->rodata.len);
+	file_offset = be32_to_cpu(fw_entry->rodata.offset);
+	data = (u32 *)(bp->firmware->data + file_offset);
+	DPRINTK("load rodata section to %x with length %u from file offset %x\n", addr, len, file_offset);
+
+	offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base);
+	if (len) {
 		int j;
 
-		for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4) {
-			bnx2_reg_wr_ind(bp, offset, fw->rodata[j]);
+		for (j = 0; j < (len / 4); j++, offset += 4) {
+			bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j]));
 		}
 	}
 
 	/* Clear the pre-fetch instruction. */
 	bnx2_reg_wr_ind(bp, cpu_reg->inst, 0);
-	bnx2_reg_wr_ind(bp, cpu_reg->pc, fw->start_addr);
+
+	val = be32_to_cpu(fw_entry->start_addr);
+	DPRINTK("starting cpu on %x\n", val);
+	bnx2_reg_wr_ind(bp, cpu_reg->pc, val);
 
 	/* Start the CPU. */
 	val = bnx2_reg_rd_ind(bp, cpu_reg->mode);
@@ -3280,39 +3322,14 @@ static int
 bnx2_init_cpus(struct bnx2 *bp)
 {
 	struct cpu_reg cpu_reg;
-	struct fw_info *fw;
-	int rc, rv2p_len;
-	void *text, *rv2p;
-
-	/* Initialize the RV2P processor. */
-	text = vmalloc(FW_BUF_SIZE);
-	if (!text)
-		return -ENOMEM;
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		rv2p = bnx2_xi_rv2p_proc1;
-		rv2p_len = sizeof(bnx2_xi_rv2p_proc1);
-	} else {
-		rv2p = bnx2_rv2p_proc1;
-		rv2p_len = sizeof(bnx2_rv2p_proc1);
-	}
-	rc = zlib_inflate_blob(text, FW_BUF_SIZE, rv2p, rv2p_len);
-	if (rc < 0)
-		goto init_cpu_err;
+	const struct bnx2_fw_file *fw = NULL;
+	int rc;
 
-	load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC1);
+	fw = (struct bnx2_fw_file *)bp->firmware->data;
 
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		rv2p = bnx2_xi_rv2p_proc2;
-		rv2p_len = sizeof(bnx2_xi_rv2p_proc2);
-	} else {
-		rv2p = bnx2_rv2p_proc2;
-		rv2p_len = sizeof(bnx2_rv2p_proc2);
-	}
-	rc = zlib_inflate_blob(text, FW_BUF_SIZE, rv2p, rv2p_len);
-	if (rc < 0)
-		goto init_cpu_err;
-
-	load_rv2p_fw(bp, text, rc /* == len */, RV2P_PROC2);
+	/* Initialize the RV2P processor. */
+	load_rv2p_fw(bp, RV2P_PROC1, &fw->rv2p_proc1);
+	load_rv2p_fw(bp, RV2P_PROC2, &fw->rv2p_proc2);
 
 	/* Initialize the RX Processor. */
 	cpu_reg.mode = BNX2_RXP_CPU_MODE;
@@ -3328,15 +3345,9 @@ bnx2_init_cpus(struct bnx2 *bp)
 	cpu_reg.spad_base = BNX2_RXP_SCRATCH;
 	cpu_reg.mips_view_base = 0x8000000;
 
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		fw = &bnx2_rxp_fw_09;
-	else
-		fw = &bnx2_rxp_fw_06;
-
-	fw->text = text;
-	rc = load_cpu_fw(bp, &cpu_reg, fw);
+	rc = load_cpu_fw(bp, &cpu_reg, &fw->rxp);
 	if (rc)
-		goto init_cpu_err;
+		return rc;
 
 	/* Initialize the TX Processor. */
 	cpu_reg.mode = BNX2_TXP_CPU_MODE;
@@ -3352,15 +3363,9 @@ bnx2_init_cpus(struct bnx2 *bp)
 	cpu_reg.spad_base = BNX2_TXP_SCRATCH;
 	cpu_reg.mips_view_base = 0x8000000;
 
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		fw = &bnx2_txp_fw_09;
-	else
-		fw = &bnx2_txp_fw_06;
-
-	fw->text = text;
-	rc = load_cpu_fw(bp, &cpu_reg, fw);
+	rc = load_cpu_fw(bp, &cpu_reg, &fw->txp);
 	if (rc)
-		goto init_cpu_err;
+		return rc;
 
 	/* Initialize the TX Patch-up Processor. */
 	cpu_reg.mode = BNX2_TPAT_CPU_MODE;
@@ -3376,15 +3381,9 @@ bnx2_init_cpus(struct bnx2 *bp)
 	cpu_reg.spad_base = BNX2_TPAT_SCRATCH;
 	cpu_reg.mips_view_base = 0x8000000;
 
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		fw = &bnx2_tpat_fw_09;
-	else
-		fw = &bnx2_tpat_fw_06;
-
-	fw->text = text;
-	rc = load_cpu_fw(bp, &cpu_reg, fw);
+	rc = load_cpu_fw(bp, &cpu_reg, &fw->tpat);
 	if (rc)
-		goto init_cpu_err;
+		return rc;
 
 	/* Initialize the Completion Processor. */
 	cpu_reg.mode = BNX2_COM_CPU_MODE;
@@ -3400,15 +3399,9 @@ bnx2_init_cpus(struct bnx2 *bp)
 	cpu_reg.spad_base = BNX2_COM_SCRATCH;
 	cpu_reg.mips_view_base = 0x8000000;
 
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		fw = &bnx2_com_fw_09;
-	else
-		fw = &bnx2_com_fw_06;
-
-	fw->text = text;
-	rc = load_cpu_fw(bp, &cpu_reg, fw);
+	rc = load_cpu_fw(bp, &cpu_reg, &fw->com);
 	if (rc)
-		goto init_cpu_err;
+		return rc;
 
 	/* Initialize the Command Processor. */
 	cpu_reg.mode = BNX2_CP_CPU_MODE;
@@ -3424,17 +3417,7 @@ bnx2_init_cpus(struct bnx2 *bp)
 	cpu_reg.spad_base = BNX2_CP_SCRATCH;
 	cpu_reg.mips_view_base = 0x8000000;
 
-	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		fw = &bnx2_cp_fw_09;
-	else
-		fw = &bnx2_cp_fw_06;
-
-	fw->text = text;
-	rc = load_cpu_fw(bp, &cpu_reg, fw);
-
-init_cpu_err:
-	vfree(text);
-	return rc;
+	return load_cpu_fw(bp, &cpu_reg, &fw->cp);
 }
 
 static int
@@ -7456,6 +7439,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct bnx2 *bp;
 	int rc;
 	char str[40];
+	const char *fw_file;
 	DECLARE_MAC_BUF(mac);
 
 	if (version_printed++ == 0)
@@ -7497,6 +7481,23 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	pci_set_drvdata(pdev, dev);
 
+	if (CHIP_NUM(bp) == CHIP_NUM_5709)
+		fw_file = FW_FILE_09;
+	else
+		fw_file = FW_FILE_06;
+
+	rc = request_firmware(&bp->firmware, fw_file, &pdev->dev);
+	if (rc) {
+		printk(KERN_ERR PFX "Can't load firmware file %s\n", fw_file);
+		goto error;
+	}
+
+	if (bp->firmware->size < sizeof(struct bnx2_fw_file)) {
+		printk(KERN_ERR PFX "Firmware file too small\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
 	memcpy(dev->dev_addr, bp->mac_addr, 6);
 	memcpy(dev->perm_addr, bp->mac_addr, 6);
 	bp->name = board_info[ent->driver_data].name;
@@ -7514,13 +7515,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	if ((rc = register_netdev(dev))) {
 		dev_err(&pdev->dev, "Cannot register net device\n");
-		if (bp->regview)
-			iounmap(bp->regview);
-		pci_release_regions(pdev);
-		pci_disable_device(pdev);
-		pci_set_drvdata(pdev, NULL);
-		free_netdev(dev);
-		return rc;
+		goto error;
 	}
 
 	printk(KERN_INFO "%s: %s (%c%d) %s found at mem %lx, "
@@ -7534,6 +7529,15 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		bp->pdev->irq, print_mac(mac, dev->dev_addr));
 
 	return 0;
+
+error:
+	if (bp->regview)
+		iounmap(bp->regview);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+	free_netdev(dev);
+	return rc;
 }
 
 static void __devexit
@@ -7549,6 +7553,8 @@ bnx2_remove_one(struct pci_dev *pdev)
 	if (bp->regview)
 		iounmap(bp->regview);
 
+	release_firmware(bp->firmware);
+
 	free_netdev(dev);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 3aa0364..b9a052f 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6812,6 +6812,8 @@ struct bnx2 {
 
 	struct bnx2_irq		irq_tbl[BNX2_MAX_MSIX_VEC];
 	int			irq_nvecs;
+
+	const struct firmware	*firmware;
 };
 
 #define REG_RD(bp, offset)					\
@@ -6842,44 +6844,6 @@ struct cpu_reg {
 	u32 mips_view_base;
 };
 
-struct fw_info {
-	const u32 ver_major;
-	const u32 ver_minor;
-	const u32 ver_fix;
-
-	const u32 start_addr;
-
-	/* Text section. */
-	const u32 text_addr;
-	const u32 text_len;
-	const u32 text_index;
-	__le32 *text;
-	u8 *gz_text;
-	const u32 gz_text_len;
-
-	/* Data section. */
-	const u32 data_addr;
-	const u32 data_len;
-	const u32 data_index;
-	const u32 *data;
-
-	/* SBSS section. */
-	const u32 sbss_addr;
-	const u32 sbss_len;
-	const u32 sbss_index;
-
-	/* BSS section. */
-	const u32 bss_addr;
-	const u32 bss_len;
-	const u32 bss_index;
-
-	/* Read-only section. */
-	const u32 rodata_addr;
-	const u32 rodata_len;
-	const u32 rodata_index;
-	const u32 *rodata;
-};
-
 #define RV2P_PROC1                              0
 #define RV2P_PROC2                              1
 
diff --git a/drivers/net/bnx2_fw_file.h b/drivers/net/bnx2_fw_file.h
new file mode 100644
index 0000000..06c003c
--- /dev/null
+++ b/drivers/net/bnx2_fw_file.h
@@ -0,0 +1,25 @@
+struct bnx2_fw_file_section {
+  uint32_t addr;
+  uint32_t len;
+  uint32_t offset;
+};
+
+struct bnx2_fw_file_entry {
+  uint32_t start_addr;
+  struct bnx2_fw_file_section text;
+  struct bnx2_fw_file_section data;
+  struct bnx2_fw_file_section sbss;
+  struct bnx2_fw_file_section bss;
+  struct bnx2_fw_file_section rodata;
+};
+
+struct bnx2_fw_file {
+  struct bnx2_fw_file_entry com;
+  struct bnx2_fw_file_entry cp;
+  struct bnx2_fw_file_entry rxp;
+  struct bnx2_fw_file_entry tpat;
+  struct bnx2_fw_file_entry txp;
+  struct bnx2_fw_file_section rv2p_proc1;
+  struct bnx2_fw_file_section rv2p_proc2;
+};
+
#include <assert.h>
#include <byteswap.h>
#include <endian.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>

#include "bnx2_fw_file.h"

struct fw_info {
  const uint32_t ver_major;
  const uint32_t ver_minor;
  const uint32_t ver_fix;

  const uint32_t start_addr;

  /* Text section. */
  const uint32_t text_addr;
  const uint32_t text_len;
  const uint32_t text_index;
  void *text;
  const void *gz_text;
  const uint32_t gz_text_len;

  /* Data section. */
  const uint32_t data_addr;
  const uint32_t data_len;
  const uint32_t data_index;
  const uint32_t *data;

  /* SBSS section. */
  const uint32_t sbss_addr;
  const uint32_t sbss_len;
  const uint32_t sbss_index;

  /* BSS section. */
  const uint32_t bss_addr;
  const uint32_t bss_len;
  const uint32_t bss_index;

  /* Read-only section. */
  const uint32_t rodata_addr;
  const uint32_t rodata_len;
  const uint32_t rodata_index;
  const uint32_t *rodata;
};

typedef uint8_t u8;
typedef uint32_t u32;

#include "bnx2_fw.h"
#include "bnx2_fw2.h"

#if __BYTE_ORDER == __LITTLE_ENDIAN
#define cpu_to_be32(x) bswap_32(x)
#elif __BYTE_ORDER == __BIG_ENDIAN
#define cpu_to_be32(x) (x)
#endif
#define le32_to_be32(x) bswap_32(x)

void set_firmware_image_part(struct bnx2_fw_file_section *s, uint32_t addr, uint32_t len)
{
    s->addr = cpu_to_be32(addr);
    s->len = cpu_to_be32(len);
}

void write_firmware_flat(int fd, struct bnx2_fw_file_section *out, void *data, int len)
{
  off_t offset = lseek(fd, 0, SEEK_CUR);

  uint32_t buf[0x10000];
  struct z_stream_s strm;
  memset(&strm, 0, sizeof strm);

  strm.next_in = (void *)data;
  strm.avail_in = len;
  strm.next_out = (void *)buf;
  strm.avail_out = sizeof buf;

  int ret = inflateInit2(&strm, -MAX_WBITS);
  assert(ret == Z_OK);
  ret = inflate(&strm, Z_FINISH);
  assert(ret == Z_STREAM_END);
  unsigned int l = strm.total_out;

  out->len = cpu_to_be32(l);
  out->offset = cpu_to_be32(offset);

  inflateEnd(&strm);

  for (unsigned int j = 0; j < (l / 4); j++)
    buf[j] = le32_to_be32(buf[j]);
  write(fd, buf, l);
}

void write_firmware_image(int fd, struct bnx2_fw_file_entry *out, struct fw_info *fw)
{
  off_t offset = lseek(fd, 0, SEEK_CUR);

  out->start_addr = cpu_to_be32(fw->start_addr);

  set_firmware_image_part(&out->text, fw->text_addr, fw->text_len);
  out->text.offset = cpu_to_be32(offset);

  uint32_t buf[0x10000];
  struct z_stream_s strm;
  memset(&strm, 0, sizeof strm);

  strm.next_in = (void *)fw->gz_text;
  strm.avail_in = fw->gz_text_len;
  strm.next_out = (void *)buf;
  strm.avail_out = sizeof buf;

  int ret = inflateInit2(&strm, -MAX_WBITS);
  assert(ret == Z_OK);
  ret = inflate(&strm, Z_FINISH);
  assert(ret == Z_STREAM_END);
  inflateEnd(&strm);

  for (unsigned int j = 0; j < (fw->text_len / 4); j++)
    buf[j] = le32_to_be32(buf[j]);
  offset += write(fd, buf, fw->text_len);

  if (fw->data_addr)
  {
    set_firmware_image_part(&out->data, fw->data_addr, fw->data_len);
    out->data.offset = cpu_to_be32(offset);
    for (unsigned int j = 0; j < (fw->data_len / 4); j++)
      buf[j] = cpu_to_be32(fw->data[j]);
    offset += write(fd, buf, fw->data_len);
  }

  if (fw->sbss_len)
    set_firmware_image_part(&out->sbss, fw->sbss_addr, fw->sbss_len);

  if (fw->bss_len)
    set_firmware_image_part(&out->bss, fw->bss_addr, fw->bss_len);

  if (fw->rodata_addr)
  {
    set_firmware_image_part(&out->rodata, fw->rodata_addr, fw->rodata_len);
    out->rodata.offset = cpu_to_be32(offset);
    for (unsigned int j = 0; j < (fw->rodata_len / 4); j++)
      buf[j] = cpu_to_be32(fw->rodata[j]);
    offset += write(fd, buf, fw->rodata_len);
  }
}

void write_firmware(const char *filename_base, struct fw_info *com_fw, struct fw_info *cp_fw, struct fw_info *rxp_fw, struct fw_info *tpat_fw, struct fw_info *txp_fw, void *rv2p_proc1, int rv2p_proc1_len, void *rv2p_proc2, int rv2p_proc2_len)
{
  struct bnx2_fw_file out;
  memset(&out, 0, sizeof out);

  char filename[64];
  snprintf(filename, sizeof filename, "%s-%d.%d.%d.fw", filename_base, com_fw->ver_major, com_fw->ver_minor, com_fw->ver_fix);

  int fd = open(filename, O_WRONLY | O_CREAT, 0666);

  lseek(fd, sizeof out, SEEK_SET);

  write_firmware_image(fd, &out.com, com_fw);
  write_firmware_image(fd, &out.cp, cp_fw);
  write_firmware_image(fd, &out.rxp, rxp_fw);
  write_firmware_image(fd, &out.tpat, tpat_fw);
  write_firmware_image(fd, &out.txp, txp_fw);
  write_firmware_flat(fd, &out.rv2p_proc1, rv2p_proc1, rv2p_proc1_len);
  write_firmware_flat(fd, &out.rv2p_proc2, rv2p_proc2, rv2p_proc2_len);

  lseek(fd, 0, SEEK_SET);

  write(fd, &out, sizeof out);

  close(fd);
}

int main()
{
  write_firmware("bnx2-06", &bnx2_com_fw_06, &bnx2_cp_fw_06, &bnx2_rxp_fw_06, &bnx2_tpat_fw_06, &bnx2_txp_fw_06, bnx2_rv2p_proc1, sizeof bnx2_rv2p_proc1, bnx2_rv2p_proc2, sizeof bnx2_rv2p_proc2);
  write_firmware("bnx2-09", &bnx2_com_fw_09, &bnx2_cp_fw_09, &bnx2_rxp_fw_09, &bnx2_tpat_fw_09, &bnx2_txp_fw_09, bnx2_xi_rv2p_proc1, sizeof bnx2_xi_rv2p_proc2, bnx2_xi_rv2p_proc2, sizeof bnx2_xi_rv2p_proc2);

  return EXIT_SUCCESS;
}

Attachment: signature.asc
Description: Digital signature


Reply to: