/* * 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 */ #include #include #include #include #include #include #include #include #include #include #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 (%"PRId64" bytes)\n", filename, (int64_t)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; }