--- Begin Message ---
- To: submit@bugs.debian.org
- Subject: firmware-nonfree: Please include bnx2x firmware
- From: John Wright <jsw@debian.org>
- Date: Tue, 23 Dec 2008 22:27:33 -0700
- Message-id: <20081224052733.GA6100@sending.johnwright.org>
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 <jsw@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;
+}
--- End Message ---