Message ID | 1435673623-15343-1-git-send-email-damien.lespiau@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, 30 Jun 2015, Damien Lespiau <damien.lespiau@intel.com> wrote: > So we can inspect fw headers. Sample output: Nitpick on the tool name, I'd like to make a distinction between tools that dump some blob from the driver/hardware/bios/whatever, and tools that decode those blobs. (See also the confusing naming with intel_bios_dumper vs. intel_bios_reader.) I'd call this "intel_firmware_decode". Another nitpick is that I'd plan on using getopt from the beginning, and having a -f or --file option for the input. BR, Jani. > Firmware: skl_dmc_ver1_18.bin (7892 bytes) > CSS header (128 bytes) > module_type: DMC (9) > header_len: 32 > header_ver: 0x10000 > module_id: 0x0 > module_vendor: 0x0 > date: 0x7df060c > size: 1973 > key_size: 0 > modulus_size: 0 > exponent_size: 0 > version: 1.18 (0x10012) > kernel_header_info: 0x0 > Package header (256 bytes) > header_len: 64 > header_ver: 1 > num_entries: 3 > Firmware #1 > stepping: A.* > offset: 4294967295 > Firmware #2 > stepping: B.* > offset: 4294967295 > Firmware #3 > stepping: *.* > offset: 0 > 0x7f0867143000 > 0x7f0867143180 > signature: 0x40403e3e > header_len: 128 > header_ver: 1 > dmcc_ver: 520 > project: 0x900 > fw_size: 1845 > fw_version: 0x10008 > mmio_count: 3 > write(0x0008f074, 0x00002fc0) > write(0x0008f004, 0x02500204) > write(0x0008f034, 0xc003b400) > > Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> > --- > tools/.gitignore | 1 + > tools/Makefile.sources | 1 + > tools/intel_fw_dump.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 289 insertions(+) > create mode 100644 tools/intel_fw_dump.c > > diff --git a/tools/.gitignore b/tools/.gitignore > index 5a2f5ff..5a5c62c 100644 > --- a/tools/.gitignore > +++ b/tools/.gitignore > @@ -10,6 +10,7 @@ intel_dump_decode > intel_error_decode > intel_forcewaked > intel_framebuffer_dump > +intel_fw_dump > intel_gpu_frequency > intel_gpu_time > intel_gpu_top > diff --git a/tools/Makefile.sources b/tools/Makefile.sources > index 5acf45a..6f51162 100644 > --- a/tools/Makefile.sources > +++ b/tools/Makefile.sources > @@ -17,6 +17,7 @@ bin_PROGRAMS = \ > intel_forcewaked \ > intel_gpu_frequency \ > intel_framebuffer_dump \ > + intel_fw_dump \ > intel_gpu_time \ > intel_gpu_top \ > intel_gtt \ > diff --git a/tools/intel_fw_dump.c b/tools/intel_fw_dump.c > new file mode 100644 > index 0000000..ae6e02c > --- /dev/null > +++ b/tools/intel_fw_dump.c > @@ -0,0 +1,287 @@ > +/* > + * Copyright © 2015 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > + * IN THE SOFTWARE. > + * > + * Authors: > + * Damien Lespiau <damien.lespiau@intel.com> > + */ > + > +#include <fcntl.h> > +#include <stdio.h> > +#include <stdint.h> > +#include <stdlib.h> > +#include <string.h> > +#include <unistd.h> > +#include <sys/types.h> > +#include <sys/mman.h> > +#include <sys/stat.h> > + > +#include "igt_core.h" > + > +#define __packed __attribute__((packed)) > + > +struct intel_css_header { > + /* 0x09 for DMC */ > + uint32_t module_type; > + > + /* Includes the DMC specific header in dwords */ > + uint32_t header_len; > + > + /* always value would be 0x10000 */ > + uint32_t header_ver; > + > + /* Not used */ > + uint32_t module_id; > + > + /* Not used */ > + uint32_t module_vendor; > + > + /* in YYYYMMDD format */ > + uint32_t date; > + > + /* Size in dwords (CSS_Headerlen + PackageHeaderLen + dmc FWsLen)/4 */ > + uint32_t size; > + > + /* Not used */ > + uint32_t key_size; > + > + /* Not used */ > + uint32_t modulus_size; > + > + /* Not used */ > + uint32_t exponent_size; > + > + /* Not used */ > + uint32_t reserved1[12]; > + > + /* Major Minor */ > + uint32_t version; > + > + /* Not used */ > + uint32_t reserved2[8]; > + > + /* Not used */ > + uint32_t kernel_header_info; > +} __packed; > + > +struct intel_fw_info { > + uint16_t reserved1; > + > + /* Stepping (A, B, C, ..., *). * is a wildcard */ > + char stepping; > + > + /* Sub-stepping (0, 1, ..., *). * is a wildcard */ > + char substepping; > + > + uint32_t offset; > + uint32_t reserved2; > +} __packed; > + > +struct intel_package_header { > + /* DMC container header length in dwords */ > + unsigned char header_len; > + > + /* always value would be 0x01 */ > + unsigned char header_ver; > + > + unsigned char reserved[10]; > + > + /* Number of valid entries in the FWInfo array below */ > + uint32_t num_entries; > + > + struct intel_fw_info fw_info[20]; > +} __packed; > + > +struct intel_dmc_header { > + /* always value would be 0x40403E3E */ > + uint32_t signature; > + > + /* DMC binary header length */ > + unsigned char header_len; > + > + /* 0x01 */ > + unsigned char header_ver; > + > + /* Reserved */ > + uint16_t dmcc_ver; > + > + /* Major, Minor */ > + uint32_t project; > + > + /* Firmware program size (excluding header) in dwords */ > + uint32_t fw_size; > + > + /* Major Minor version */ > + uint32_t fw_version; > + > + /* Number of valid MMIO cycles present. */ > + uint32_t mmio_count; > + > + /* MMIO address */ > + uint32_t mmioaddr[8]; > + > + /* MMIO data */ > + uint32_t mmiodata[8]; > + > + /* FW filename */ > + unsigned char dfile[32]; > + > + uint32_t reserved1[2]; > +} __packed; > + > +typedef struct { > + int fd; > + uint8_t *base; > + struct intel_css_header *css_header; > + struct intel_package_header *package_header; > +} csr_t; > + > +static void csr_open(csr_t *ctx, const char *filename) > +{ > + struct stat st; > + > + ctx->fd = open(filename, O_RDWR); > + igt_fail_on_f(ctx->fd == -1, "Couldn't open %s\n", filename); > + > + fstat(ctx->fd, &st); > + ctx->base = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, > + ctx->fd, 0); > + igt_fail_on_f(ctx->base == MAP_FAILED, "Couldn't mmap %s\n", filename); > + > + printf("Firmware: %s (%zd bytes)\n", filename, st.st_size); > + > + ctx->css_header = (struct intel_css_header *)ctx->base; > + ctx->package_header = (struct intel_package_header *) > + (ctx->base + sizeof(*ctx->css_header)); > +} > + > +#define print_d32(p, field) \ > + printf(" "#field": %u\n", (p)->field) > +#define print_x32(p, field) \ > + printf(" "#field": 0x%x\n", (p)->field) > +#define print_s(p, field) \ > + printf(" "#field": %s\n", (p)->field) > + > +static const char *module_type_name(uint32_t module_type) > +{ > + switch (module_type) { > + case 0x9: > + return "DMC"; > + default: > + return "Unknown"; > + } > +} > + > +static void dump_css(csr_t *ctx) > +{ > + struct intel_css_header *css = ctx->css_header; > + > + printf("CSS header (%zd bytes)\n", sizeof(*css)); > + printf(" module_type: %s (%d)\n", module_type_name(css->module_type), > + css->module_type); > + print_d32(css, header_len); > + print_x32(css, header_ver); > + print_x32(css, module_id); > + print_x32(css, module_vendor); > + print_x32(css, date); > + print_d32(css, size); > + print_d32(css, key_size); > + print_d32(css, modulus_size); > + print_d32(css, exponent_size); > + /* uint32_t reserved1[12]; */ > + printf(" version: %d.%d (0x%x)\n", css->version >> 16, > + css->version & 0xffff, css->version); > + /* uint32_t reserved2[8]; */ > + print_x32(css, kernel_header_info); > + > +} > + > +static void dump_dmc(csr_t *ctx, struct intel_fw_info *info) > +{ > + struct intel_dmc_header *dmc; > + unsigned int i; > + > + if (info->offset == 0xffffffff) > + return; > + > + dmc = (struct intel_dmc_header *)(ctx->base + sizeof(*ctx->css_header) > + + sizeof(*ctx->package_header) + > + info->offset); > + > + print_x32(dmc, signature); > + print_d32(dmc, header_len); > + print_d32(dmc, header_ver); > + print_d32(dmc, dmcc_ver); > + print_x32(dmc, project); > + print_d32(dmc, fw_size); > + print_x32(dmc, fw_version); > + print_d32(dmc, mmio_count); > + > + for (i = 0; i < dmc->mmio_count; i++) { > + printf(" write(0x%08x, 0x%08x)\n", dmc->mmioaddr[i], > + dmc->mmiodata[i]); > + } > +} > + > +static void dump_package(csr_t *ctx) > +{ > + struct intel_package_header *package = ctx->package_header; > + unsigned int i; > + > + printf("Package header (%zd bytes)\n", sizeof(*package)); > + > + print_d32(package, header_len); > + print_d32(package, header_ver); > + /* unsigned char reserved[10]; */ > + print_d32(package, num_entries); > + > + for (i = 0; i < package->num_entries; i++) { > + struct intel_fw_info *info = &package->fw_info[i]; > + > + printf("Firmware #%d\n", i + 1); > + printf(" stepping: %c.%c\n", info->stepping, > + info->substepping); > + print_d32(info, offset); > + > + dump_dmc(ctx, info); > + } > +} > + > +static void csr_dump(csr_t *ctx) > +{ > + dump_css(ctx); > + dump_package(ctx); > +} > + > +static csr_t ctx; > + > +int main(int argc, char **argv) > +{ > + if (argc != 2) { > + fprintf(stderr, "Usage: %s firmware.bin\n", argv[0]); > + return 1; > + } > + > + csr_open(&ctx, argv[1]); > + csr_dump(&ctx); > + > + return 0; > +} > -- > 2.1.0 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Tue, Jun 30, 2015 at 05:49:12PM +0300, Jani Nikula wrote: > On Tue, 30 Jun 2015, Damien Lespiau <damien.lespiau@intel.com> wrote: > > So we can inspect fw headers. Sample output: > > Nitpick on the tool name, I'd like to make a distinction between tools > that dump some blob from the driver/hardware/bios/whatever, and tools > that decode those blobs. (See also the confusing naming with > intel_bios_dumper vs. intel_bios_reader.) I'd call this > "intel_firmware_decode". Sure, I can't say I care much, so glad someone does. > Another nitpick is that I'd plan on using getopt from the beginning, and > having a -f or --file option for the input. Well, for that one, the file is the actual thing we act on, so I wouldn't use an option, we always need it. Options can always come later if needed.
On Tue, Jun 30, 2015 at 04:30:09PM +0100, Damien Lespiau wrote: > On Tue, Jun 30, 2015 at 05:49:12PM +0300, Jani Nikula wrote: > > On Tue, 30 Jun 2015, Damien Lespiau <damien.lespiau@intel.com> wrote: > > > So we can inspect fw headers. Sample output: > > > > Nitpick on the tool name, I'd like to make a distinction between tools > > that dump some blob from the driver/hardware/bios/whatever, and tools > > that decode those blobs. (See also the confusing naming with > > intel_bios_dumper vs. intel_bios_reader.) I'd call this > > "intel_firmware_decode". > > Sure, I can't say I care much, so glad someone does. Pushed with this change. Thanks!
diff --git a/tools/.gitignore b/tools/.gitignore index 5a2f5ff..5a5c62c 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -10,6 +10,7 @@ intel_dump_decode intel_error_decode intel_forcewaked intel_framebuffer_dump +intel_fw_dump intel_gpu_frequency intel_gpu_time intel_gpu_top diff --git a/tools/Makefile.sources b/tools/Makefile.sources index 5acf45a..6f51162 100644 --- a/tools/Makefile.sources +++ b/tools/Makefile.sources @@ -17,6 +17,7 @@ bin_PROGRAMS = \ intel_forcewaked \ intel_gpu_frequency \ intel_framebuffer_dump \ + intel_fw_dump \ intel_gpu_time \ intel_gpu_top \ intel_gtt \ diff --git a/tools/intel_fw_dump.c b/tools/intel_fw_dump.c new file mode 100644 index 0000000..ae6e02c --- /dev/null +++ b/tools/intel_fw_dump.c @@ -0,0 +1,287 @@ +/* + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Damien Lespiau <damien.lespiau@intel.com> + */ + +#include <fcntl.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> + +#include "igt_core.h" + +#define __packed __attribute__((packed)) + +struct intel_css_header { + /* 0x09 for DMC */ + uint32_t module_type; + + /* Includes the DMC specific header in dwords */ + uint32_t header_len; + + /* always value would be 0x10000 */ + uint32_t header_ver; + + /* Not used */ + uint32_t module_id; + + /* Not used */ + uint32_t module_vendor; + + /* in YYYYMMDD format */ + uint32_t date; + + /* Size in dwords (CSS_Headerlen + PackageHeaderLen + dmc FWsLen)/4 */ + uint32_t size; + + /* Not used */ + uint32_t key_size; + + /* Not used */ + uint32_t modulus_size; + + /* Not used */ + uint32_t exponent_size; + + /* Not used */ + uint32_t reserved1[12]; + + /* Major Minor */ + uint32_t version; + + /* Not used */ + uint32_t reserved2[8]; + + /* Not used */ + uint32_t kernel_header_info; +} __packed; + +struct intel_fw_info { + uint16_t reserved1; + + /* Stepping (A, B, C, ..., *). * is a wildcard */ + char stepping; + + /* Sub-stepping (0, 1, ..., *). * is a wildcard */ + char substepping; + + uint32_t offset; + uint32_t reserved2; +} __packed; + +struct intel_package_header { + /* DMC container header length in dwords */ + unsigned char header_len; + + /* always value would be 0x01 */ + unsigned char header_ver; + + unsigned char reserved[10]; + + /* Number of valid entries in the FWInfo array below */ + uint32_t num_entries; + + struct intel_fw_info fw_info[20]; +} __packed; + +struct intel_dmc_header { + /* always value would be 0x40403E3E */ + uint32_t signature; + + /* DMC binary header length */ + unsigned char header_len; + + /* 0x01 */ + unsigned char header_ver; + + /* Reserved */ + uint16_t dmcc_ver; + + /* Major, Minor */ + uint32_t project; + + /* Firmware program size (excluding header) in dwords */ + uint32_t fw_size; + + /* Major Minor version */ + uint32_t fw_version; + + /* Number of valid MMIO cycles present. */ + uint32_t mmio_count; + + /* MMIO address */ + uint32_t mmioaddr[8]; + + /* MMIO data */ + uint32_t mmiodata[8]; + + /* FW filename */ + unsigned char dfile[32]; + + uint32_t reserved1[2]; +} __packed; + +typedef struct { + int fd; + uint8_t *base; + struct intel_css_header *css_header; + struct intel_package_header *package_header; +} csr_t; + +static void csr_open(csr_t *ctx, const char *filename) +{ + struct stat st; + + ctx->fd = open(filename, O_RDWR); + igt_fail_on_f(ctx->fd == -1, "Couldn't open %s\n", filename); + + fstat(ctx->fd, &st); + ctx->base = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, + ctx->fd, 0); + igt_fail_on_f(ctx->base == MAP_FAILED, "Couldn't mmap %s\n", filename); + + printf("Firmware: %s (%zd bytes)\n", filename, st.st_size); + + ctx->css_header = (struct intel_css_header *)ctx->base; + ctx->package_header = (struct intel_package_header *) + (ctx->base + sizeof(*ctx->css_header)); +} + +#define print_d32(p, field) \ + printf(" "#field": %u\n", (p)->field) +#define print_x32(p, field) \ + printf(" "#field": 0x%x\n", (p)->field) +#define print_s(p, field) \ + printf(" "#field": %s\n", (p)->field) + +static const char *module_type_name(uint32_t module_type) +{ + switch (module_type) { + case 0x9: + return "DMC"; + default: + return "Unknown"; + } +} + +static void dump_css(csr_t *ctx) +{ + struct intel_css_header *css = ctx->css_header; + + printf("CSS header (%zd bytes)\n", sizeof(*css)); + printf(" module_type: %s (%d)\n", module_type_name(css->module_type), + css->module_type); + print_d32(css, header_len); + print_x32(css, header_ver); + print_x32(css, module_id); + print_x32(css, module_vendor); + print_x32(css, date); + print_d32(css, size); + print_d32(css, key_size); + print_d32(css, modulus_size); + print_d32(css, exponent_size); + /* uint32_t reserved1[12]; */ + printf(" version: %d.%d (0x%x)\n", css->version >> 16, + css->version & 0xffff, css->version); + /* uint32_t reserved2[8]; */ + print_x32(css, kernel_header_info); + +} + +static void dump_dmc(csr_t *ctx, struct intel_fw_info *info) +{ + struct intel_dmc_header *dmc; + unsigned int i; + + if (info->offset == 0xffffffff) + return; + + dmc = (struct intel_dmc_header *)(ctx->base + sizeof(*ctx->css_header) + + sizeof(*ctx->package_header) + + info->offset); + + print_x32(dmc, signature); + print_d32(dmc, header_len); + print_d32(dmc, header_ver); + print_d32(dmc, dmcc_ver); + print_x32(dmc, project); + print_d32(dmc, fw_size); + print_x32(dmc, fw_version); + print_d32(dmc, mmio_count); + + for (i = 0; i < dmc->mmio_count; i++) { + printf(" write(0x%08x, 0x%08x)\n", dmc->mmioaddr[i], + dmc->mmiodata[i]); + } +} + +static void dump_package(csr_t *ctx) +{ + struct intel_package_header *package = ctx->package_header; + unsigned int i; + + printf("Package header (%zd bytes)\n", sizeof(*package)); + + print_d32(package, header_len); + print_d32(package, header_ver); + /* unsigned char reserved[10]; */ + print_d32(package, num_entries); + + for (i = 0; i < package->num_entries; i++) { + struct intel_fw_info *info = &package->fw_info[i]; + + printf("Firmware #%d\n", i + 1); + printf(" stepping: %c.%c\n", info->stepping, + info->substepping); + print_d32(info, offset); + + dump_dmc(ctx, info); + } +} + +static void csr_dump(csr_t *ctx) +{ + dump_css(ctx); + dump_package(ctx); +} + +static csr_t ctx; + +int main(int argc, char **argv) +{ + if (argc != 2) { + fprintf(stderr, "Usage: %s firmware.bin\n", argv[0]); + return 1; + } + + csr_open(&ctx, argv[1]); + csr_dump(&ctx); + + return 0; +}
So we can inspect fw headers. Sample output: Firmware: skl_dmc_ver1_18.bin (7892 bytes) CSS header (128 bytes) module_type: DMC (9) header_len: 32 header_ver: 0x10000 module_id: 0x0 module_vendor: 0x0 date: 0x7df060c size: 1973 key_size: 0 modulus_size: 0 exponent_size: 0 version: 1.18 (0x10012) kernel_header_info: 0x0 Package header (256 bytes) header_len: 64 header_ver: 1 num_entries: 3 Firmware #1 stepping: A.* offset: 4294967295 Firmware #2 stepping: B.* offset: 4294967295 Firmware #3 stepping: *.* offset: 0 0x7f0867143000 0x7f0867143180 signature: 0x40403e3e header_len: 128 header_ver: 1 dmcc_ver: 520 project: 0x900 fw_size: 1845 fw_version: 0x10008 mmio_count: 3 write(0x0008f074, 0x00002fc0) write(0x0008f004, 0x02500204) write(0x0008f034, 0xc003b400) Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> --- tools/.gitignore | 1 + tools/Makefile.sources | 1 + tools/intel_fw_dump.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 289 insertions(+) create mode 100644 tools/intel_fw_dump.c