Source: firmware-nonfree
Version: 0.14
Severity: wishlist
Tags: patch

I have written a firmware cutter for the bnx2x driver, as well as a
patch to the driver itself (which will be filed as a separate bug
report) to use the resulting firmware file.

The firmware cutter works with the versions of the driver in Linux
2.6.26 and 2.6.28-rc9.  As I will explain in my other report, I don't
have hardware that works with the 2.6.26 version, so my kernel patch is
actually a backport of the new driver plus a patch to use the firmware
file.

Use of this firmware cutter is virtually identical to that of the bnx2
cutter, as I initially followed that design.  Basically,

  $ cd ~/src/linux-2.6
  $ git checkout v2.6.28-rc9
  $ export KERNEL_VERSION=2.6.28 KERNEL_SOURCE=$(pwd)
  $ cd ~/src/firmware-nonfree/bnx2x/fwcutter
  $ make
  $ ./bnx2x_fwcutter_2.6.28

That will spit out bnx2x-e1-1.45.23.fw and bnx2x-e1h-1.45.23.fw, which
contain big-endian representations of init_ops and the data blobs in
bnx2x_init_values.h.  Also generated in this process is
bnx2x_init_ops_offsets_2.6.28.h, which I also include in the linux-2.6
patch.  (The offsets to functions in the init_ops array are defined as
constants in bnx2x_init_values.h, so I just extract those constants to
their own header.)

-- 
John Wright <j...@debian.org>
diff --git a/bnx2x/fwcutter/Makefile b/bnx2x/fwcutter/Makefile
new file mode 100644
index 0000000..7f6b93b
--- /dev/null
+++ b/bnx2x/fwcutter/Makefile
@@ -0,0 +1,34 @@
+test :=
+ifdef KERNEL_SOURCE
+test += source
+endif
+ifdef KERNEL_VERSION
+test += version
+endif
+
+ifeq "$(test)" " source version"
+CFLAGS += -I$(KERNEL_SOURCE)/include -I$(KERNEL_SOURCE)/drivers/net
+#LDFLAGS += -lz
+
+all: bnx2x_fwcutter_$(KERNEL_VERSION)
+
+bnx2x_fwcutter_$(KERNEL_VERSION): bnx2x_fwcutter_$(KERNEL_VERSION).c bnx2x_fwcutter_$(KERNEL_VERSION).h bnx2x_fwcutter_$(KERNEL_VERSION)_init.h bnx2x_fwcutter.c bnx2x_init_ops_offsets_$(KERNEL_VERSION).h
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+bnx2x_fwcutter_$(KERNEL_VERSION).h: $(KERNEL_SOURCE)/drivers/net/bnx2x.h
+	grep "^#define BNX2" $^ | grep -v '\\' > $@
+
+bnx2x_fwcutter_$(KERNEL_VERSION)_init.h: $(KERNEL_SOURCE)/drivers/net/bnx2x_init.h
+	grep "^#define OP_" $^ > $@
+
+bnx2x_init_ops_offsets_$(KERNEL_VERSION).h: $(KERNEL_SOURCE)/drivers/net/bnx2x_init_values.h
+	grep -E '^#define .*_(START|END)' $< > $@
+
+else
+all:
+	$(error Please define KERNEL_SOURCE and KERNEL_VERSION)
+endif
+
+clean: ALL = $(basename $(wildcard bnx2x_fwcutter_*.c))
+clean:
+	rm -f $(ALL) $(ALL:=.h) $(ALL:=_init.h)
diff --git a/bnx2x/fwcutter/bnx2x_fw_file.h b/bnx2x/fwcutter/bnx2x_fw_file.h
new file mode 100644
index 0000000..9b86518
--- /dev/null
+++ b/bnx2x/fwcutter/bnx2x_fw_file.h
@@ -0,0 +1,17 @@
+struct bnx2x_fw_file_section {
+	uint32_t len;
+	uint32_t offset;
+};
+
+struct bnx2x_fw_file {
+	struct bnx2x_fw_file_section init_ops;
+	struct bnx2x_fw_file_section init_data;
+	struct bnx2x_fw_file_section tsem_int_table_data;
+	struct bnx2x_fw_file_section tsem_pram_data;
+	struct bnx2x_fw_file_section usem_int_table_data;
+	struct bnx2x_fw_file_section usem_pram_data;
+	struct bnx2x_fw_file_section csem_int_table_data;
+	struct bnx2x_fw_file_section csem_pram_data;
+	struct bnx2x_fw_file_section xsem_int_table_data;
+	struct bnx2x_fw_file_section xsem_pram_data;
+};
diff --git a/bnx2x/fwcutter/bnx2x_fwcutter.c b/bnx2x/fwcutter/bnx2x_fwcutter.c
new file mode 100644
index 0000000..c0df7a4
--- /dev/null
+++ b/bnx2x/fwcutter/bnx2x_fwcutter.c
@@ -0,0 +1,101 @@
+#include <byteswap.h>
+#include <endian.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef uint32_t u32;
+
+struct raw_op {
+    u32 op:8;
+    u32 offset:24;
+    u32 raw_data;
+};
+
+#include "bnx2x_fw_file.h"
+
+#include "bnx2x_reg.h"
+#include "bnx2x_init_values.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 uint32_t_buf_to_be32(const uint32_t *input, uint32_t *output, size_t len)
+{
+    int j;
+    for (j = 0; j < (len / 4); j++) {
+        output[j] = cpu_to_be32(input[j]);
+    }
+}
+
+void write_firmware_data(int fd, struct bnx2x_fw_file_section *section,
+                         const uint32_t *data, size_t len)
+{
+    off_t offset = lseek(fd, 0, SEEK_CUR);
+    uint32_t *buf;
+    unsigned int j;
+
+    section->len = cpu_to_be32(len);
+    section->offset = cpu_to_be32(offset);
+
+    buf = malloc(len);
+    uint32_t_buf_to_be32(data, buf, len);
+    write(fd, buf, len);
+    free(buf);
+}
+
+void write_firmware(const char *filename,
+                    const uint32_t *init_data, size_t init_data_len,
+                    const uint32_t *tsem_int_table_data,
+                    size_t tsem_int_table_data_len,
+                    const uint32_t *tsem_pram_data, size_t tsem_pram_data_len,
+                    const uint32_t *usem_int_table_data,
+                    size_t usem_int_table_data_len,
+                    const uint32_t *usem_pram_data, size_t usem_pram_data_len,
+                    const uint32_t *csem_int_table_data,
+                    size_t csem_int_table_data_len,
+                    const uint32_t *csem_pram_data, size_t csem_pram_data_len,
+                    const uint32_t *xsem_int_table_data,
+                    size_t xsem_int_table_data_len,
+                    const uint32_t *xsem_pram_data, size_t xsem_pram_data_len)
+{
+    struct bnx2x_fw_file out;
+    int fd;
+
+    memset(&out, 0, sizeof(out));
+
+    printf("Write firmware file: %s\n", filename);
+    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+    lseek(fd, sizeof(out), SEEK_SET);
+
+    write_firmware_data(fd, &out.init_ops,
+                        (uint32_t *)init_ops, sizeof(init_ops));
+    write_firmware_data(fd, &out.init_data,
+                        init_data, init_data_len);
+    write_firmware_data(fd, &out.tsem_int_table_data,
+                        tsem_int_table_data, tsem_int_table_data_len);
+    write_firmware_data(fd, &out.tsem_pram_data,
+                        tsem_pram_data, tsem_pram_data_len);
+    write_firmware_data(fd, &out.usem_int_table_data,
+                        usem_int_table_data, usem_int_table_data_len);
+    write_firmware_data(fd, &out.usem_pram_data,
+                        usem_pram_data, usem_pram_data_len);
+    write_firmware_data(fd, &out.csem_int_table_data,
+                        csem_int_table_data, csem_int_table_data_len);
+    write_firmware_data(fd, &out.csem_pram_data,
+                        csem_pram_data, csem_pram_data_len);
+    write_firmware_data(fd, &out.xsem_int_table_data,
+                        xsem_int_table_data, xsem_int_table_data_len);
+    write_firmware_data(fd, &out.xsem_pram_data,
+                        xsem_pram_data, xsem_pram_data_len);
+
+    lseek(fd, 0, SEEK_SET);
+    write(fd, &out, sizeof(out));
+    close(fd);
+}
diff --git a/bnx2x/fwcutter/bnx2x_fwcutter_2.6.26.c b/bnx2x/fwcutter/bnx2x_fwcutter_2.6.26.c
new file mode 100644
index 0000000..44e3eda
--- /dev/null
+++ b/bnx2x/fwcutter/bnx2x_fwcutter_2.6.26.c
@@ -0,0 +1,18 @@
+#include "bnx2x_fwcutter_2.6.26.h"
+#include "bnx2x_fwcutter_2.6.26_init.h"
+#include "bnx2x_fwcutter.c"
+
+int main()
+{
+    write_firmware("bnx2x-1.42.4.fw",
+                   init_data, sizeof(init_data),
+                   0, 0,
+                   0, 0,
+                   0, 0,
+                   0, 0,
+                   0, 0,
+                   0, 0,
+                   0, 0,
+                   0, 0);
+    return 0;
+}
diff --git a/bnx2x/fwcutter/bnx2x_fwcutter_2.6.28.c b/bnx2x/fwcutter/bnx2x_fwcutter_2.6.28.c
new file mode 100644
index 0000000..f45f22a
--- /dev/null
+++ b/bnx2x/fwcutter/bnx2x_fwcutter_2.6.28.c
@@ -0,0 +1,28 @@
+#include "bnx2x_fwcutter_2.6.28.h"
+#include "bnx2x_fwcutter_2.6.28_init.h"
+#include "bnx2x_fwcutter.c"
+
+int main()
+{
+    write_firmware("bnx2x-e1-1.45.23.fw",
+                   init_data_e1, sizeof(init_data_e1),
+                   tsem_int_table_data_e1, sizeof(tsem_int_table_data_e1),
+                   tsem_pram_data_e1, sizeof(tsem_pram_data_e1),
+                   usem_int_table_data_e1, sizeof(usem_int_table_data_e1),
+                   usem_pram_data_e1, sizeof(usem_pram_data_e1),
+                   csem_int_table_data_e1, sizeof(csem_int_table_data_e1),
+                   csem_pram_data_e1, sizeof(csem_pram_data_e1),
+                   xsem_int_table_data_e1, sizeof(xsem_int_table_data_e1),
+                   xsem_pram_data_e1, sizeof(xsem_pram_data_e1));
+    write_firmware("bnx2x-e1h-1.45.23.fw",
+                   init_data_e1h, sizeof(init_data_e1h),
+                   tsem_int_table_data_e1h, sizeof(tsem_int_table_data_e1h),
+                   tsem_pram_data_e1h, sizeof(tsem_pram_data_e1h),
+                   usem_int_table_data_e1h, sizeof(usem_int_table_data_e1h),
+                   usem_pram_data_e1h, sizeof(usem_pram_data_e1h),
+                   csem_int_table_data_e1h, sizeof(csem_int_table_data_e1h),
+                   csem_pram_data_e1h, sizeof(csem_pram_data_e1h),
+                   xsem_int_table_data_e1h, sizeof(xsem_int_table_data_e1h),
+                   xsem_pram_data_e1h, sizeof(xsem_pram_data_e1h));
+    return 0;
+}

Reply via email to