diff options
author | Damien Lespiau <damien.lespiau@intel.com> | 2015-06-30 00:15:15 +0100 |
---|---|---|
committer | Damien Lespiau <damien.lespiau@intel.com> | 2015-06-30 16:38:54 +0100 |
commit | 669b5da2bc4ef8d80405aef96ebb831a39608db4 (patch) | |
tree | f34bf9292a6f471cc58a24b07fb2a1edf895662b /tools/intel_firmware_decode.c | |
parent | ad411e2d5de78b621f6e9c628f8a96bd79425057 (diff) |
tools: Add an intel_firmware_decode tool
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>
Diffstat (limited to 'tools/intel_firmware_decode.c')
-rw-r--r-- | tools/intel_firmware_decode.c | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/tools/intel_firmware_decode.c b/tools/intel_firmware_decode.c new file mode 100644 index 00000000..ae6e02c4 --- /dev/null +++ b/tools/intel_firmware_decode.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; +} |