From patchwork Tue Jun 30 14:13:43 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Lespiau, Damien" X-Patchwork-Id: 6696441 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 251269F39B for ; Tue, 30 Jun 2015 14:13:59 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id F01A020457 for ; Tue, 30 Jun 2015 14:13:57 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id BE4F920425 for ; Tue, 30 Jun 2015 14:13:56 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 431166E2A1; Tue, 30 Jun 2015 07:13:56 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTP id 8EC1F6E2A1 for ; Tue, 30 Jun 2015 07:13:54 -0700 (PDT) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga101.fm.intel.com with ESMTP; 30 Jun 2015 07:13:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,378,1432623600"; d="scan'208";a="720334615" Received: from amunshi-mobl4.amr.corp.intel.com (HELO strange.amr.corp.intel.com) ([10.254.100.153]) by orsmga001.jf.intel.com with ESMTP; 30 Jun 2015 07:13:49 -0700 From: Damien Lespiau To: intel-gfx@lists.freedesktop.org Date: Tue, 30 Jun 2015 15:13:43 +0100 Message-Id: <1435673623-15343-1-git-send-email-damien.lespiau@intel.com> X-Mailer: git-send-email 2.1.0 MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH i-g-t] tools Add a intel_fw_dump tool X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 + */ + +#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 (%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; +}