<p>Lubomir Rintel has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/22256">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">util/pirdump: add tool to dump PIR table<br><br>Signed-off-by: Lubomir Rintel <lkundrak@v3.sk><br>Change-Id: I9b0a2ae459bb98ed6854fef280d67f9c14a25314<br>---<br>A util/pirdump/Makefile<br>A util/pirdump/pirdump.1<br>A util/pirdump/pirdump.c<br>3 files changed, 346 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/56/22256/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/util/pirdump/Makefile b/util/pirdump/Makefile<br>new file mode 100644<br>index 0000000..7938c82<br>--- /dev/null<br>+++ b/util/pirdump/Makefile<br>@@ -0,0 +1,33 @@<br>+#<br>+# Copyright (C) 2017 Lubomir Rintel <lkundrak@v3.sk><br>+#<br>+# Based on an inteltool Makefile:<br>+#<br>+# Copyright (C) 2008 by coresystems GmbH<br>+# written by Stefan Reinauer <stepan@coresystems.de><br>+#<br>+# This program is free software; you can redistribute it and/or modify<br>+# it under the terms of the GNU General Public License as published by<br>+# the Free Software Foundation; either version 2 of the License, or<br>+# (at your option) any later version.<br>+#<br>+# This program is distributed in the hope that it will be useful,<br>+# but WITHOUT ANY WARRANTY; without even the implied warranty of<br>+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br>+# GNU General Public License for more details.<br>+#<br>+<br>+PROGRAM = pirdump<br>+<br>+all: $(PROGRAM)<br>+<br>+clean:<br>+  rm -f $(PROGRAM) *.o<br>+<br>+install: $(PROGRAM)<br>+        mkdir -p $(DESTDIR)$(PREFIX)/bin<br>+     install $(PROGRAM) $(DESTDIR)$(PREFIX)/bin<br>+   mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1<br>+  install -p -m644 $(PROGRAM).1 $(DESTDIR)$(PREFIX)/share/man/man1<br>+<br>+.PHONY: all clean<br>diff --git a/util/pirdump/pirdump.1 b/util/pirdump/pirdump.1<br>new file mode 100644<br>index 0000000..6e61419<br>--- /dev/null<br>+++ b/util/pirdump/pirdump.1<br>@@ -0,0 +1,56 @@<br>+.TH PIRDUMP 1 "October 29, 2017"<br>+.SH NAME<br>+pirdump \- dump the PCI Interrupt Routing table<br>+.SH SYNOPSIS<br>+.B pirdump [format] [<dump file>]<br>+.SH DESCRIPTION<br>+.B pirdump<br>+dumps the PIR table from memory or a dump file in a variety of formats.<br>+.SH OPTIONS<br>+.TP<br>+.B "\-d" | "\-\-default"<br>+Dump in human-readable format (default).<br>+.TP<br>+.B "\-r" | "\-\-raw"<br>+Dump the raw (binary) table data.<br>+.TP<br>+.B "\-c" | "\-\-C"<br>+Dump the C language snippet with coreboot's "struct<br>+irq_routing_table" initializer.<br>+.TP<br>+.B "\-\-"<br>+Keeps the default format. This is useful if your dump file name starts with a<br>+dash.<br>+.TP<br>+.B "<dump file>"<br>+Look for the PIR table in the provided file instead of memory.<br>+.SH EXAMPLES<br>+.TP<br>+.B "pirdump"<br>+Look for the system's PIR table and print it in a human-readable form.<br>+.TP<br>+.B "pirdump --raw >dump.pir"<br>+Dump the system's PIR table into a file.<br>+.TP<br>+.B "pirdump -c dump.pir"<br>+Read a the PIR table dump from a file and print it in a C language form.<br>+.B "pirdump build/ramstage/mainboard/hp/t5550/irq_tables.o"<br>+Find the PIR table in an object file and print it in a human-readable form.<br>+.SH BUGS<br>+The checksum and table size is not checked for validity.<br>+.P<br>+Works only on little-endian systems.<br>+.P<br>+Please report any bugs to https://ticket.coreboot.org/projects/coreboot or the<br>+coreboot mailing list at <coreboot@coreboot.org>.<br>+.SH LICENCE<br>+.B pirdump<br>+is covered by the GNU General Public License (GPL), version 2  or (at your<br>+option) any later version.<br>+.SH SEE ALSO<br>+.BR flashrom (1),<br>+.BR abuild (1).<br>+.SH COPYRIGHT<br>+2017 Lubomir Rintel<br>+.SH AUTHORS<br>+2017 Lubomir Rintel <lkundrak@v3.sk><br>diff --git a/util/pirdump/pirdump.c b/util/pirdump/pirdump.c<br>new file mode 100644<br>index 0000000..336b360<br>--- /dev/null<br>+++ b/util/pirdump/pirdump.c<br>@@ -0,0 +1,257 @@<br>+/*<br>+ * This file is part of the coreboot project.<br>+ *<br>+ * Copyright (C) 2017 Lubomir Rintel <lkundrak@v3.sk><br>+ *<br>+ * Structure definitions were copied from<br>+ * src/arch/x86/include/arch/pirq_routing.h:<br>+ *<br>+ * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com><br>+ * Copyright (C) 2012 Patrick Georgi <patrick@georgi-clan.de><br>+ * Copyright (C) 2010 Stefan Reinauer <stepan@coreboot.org><br>+ *<br>+ * This program is free software: you can redistribute it and/or modify<br>+ * it under the terms of the GNU General Public License as published by<br>+ * the Free Software Foundation, either version 2 of the License, or<br>+ * (at your option) any later version.<br>+ *<br>+ * This program is distributed in the hope that it will be useful,<br>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br>+ * GNU General Public License for more details.<br>+ */<br>+<br>+#include <fcntl.h><br>+#include <stdint.h><br>+#include <stdio.h><br>+#include <string.h><br>+#include <sys/mman.h><br>+#include <sys/stat.h><br>+#include <sys/types.h><br>+#include <unistd.h><br>+<br>+#define PIRQ_SIGNATURE       (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))<br>+#define PIRQ_VERSION 0x0100<br>+<br>+struct irq_info {<br>+   uint8_t bus, devfn;             /* Bus, device and function */<br>+       struct {<br>+             uint8_t link;           /* IRQ line ID, chipset dependent, 0=not routed */<br>+           uint16_t bitmap;        /* Available IRQs */<br>+ } __attribute__((packed)) irq[4];<br>+    uint8_t slot;                   /* Slot number, 0=onboard */<br>+ uint8_t rfu;<br>+} __attribute__((packed));<br>+<br>+struct irq_routing_table {<br>+    uint32_t signature;             /* PIRQ_SIGNATURE should be here */<br>+  uint16_t version;               /* PIRQ_VERSION */<br>+   uint16_t size;                  /* Table size in bytes */<br>+    uint8_t  rtr_bus, rtr_devfn;    /* Where the interrupt router lies */<br>+        uint16_t exclusive_irqs;        /* IRQs devoted exclusively to PCI usage */<br>+  uint16_t rtr_vendor, rtr_device;/* Vendor/device ID of interrupt router */<br>+   uint32_t miniport_data;<br>+      uint8_t  rfu[11];<br>+    uint8_t  checksum;              /* Modulo 256 checksum must give zero */<br>+     struct irq_info slots[1];<br>+} __attribute__((packed));<br>+<br>+static int<br>+dump (struct irq_routing_table *pir)<br>+{<br>+    int slot, irq;<br>+<br>+    printf ("Signature: 0x%08x\n", pir->signature);<br>+ printf ("Version: 0x%04x\n", pir->version);<br>+     printf ("Size: 0x%04x\n", pir->size);<br>+   printf ("Interrupt router bus: 0x%02x\n", pir->rtr_bus);<br>+        printf ("Interrupt router device/function: 0x%02x\n", pir->rtr_devfn);<br>+  printf ("IRQs devoted exclusively to PCI usage: 0x%02x\n", pir->exclusive_irqs);<br>+        printf ("Interrupt router vendor: 0x%04x\n", pir->rtr_vendor);<br>+  printf ("Interrupt router device: 0x%04x\n", pir->rtr_device);<br>+  printf ("Miniport data: 0x%08x\n", pir->miniport_data);<br>+ printf ("Checksum: 0x%02x\n", pir->checksum);<br>+<br>+        for (slot = 0; (void *)&pir->slots[slot] < (void *)pir + pir->size; slot++) {<br>+           printf ("Slot: %d\n", slot);<br>+               printf ("\tBus: 0x%02x\n", pir->slots[slot].bus);<br>+               printf ("\tDevice/function: 0x%02x\n", pir->slots[slot].devfn);<br>+<br>+              for (irq = 0; irq < 4; irq++) {<br>+                   printf ("\tIRQ: %d\n", irq);<br>+                       printf ("\t\tLink: 0x%02x\n", pir->slots[slot].irq[irq].link);<br>+                  printf ("\t\tBitmap: 0x%04x\n", pir->slots[slot].irq[irq].bitmap);<br>+              }<br>+<br>+         printf ("\tSlot number: 0x%02x\n", pir->slots[slot].slot);<br>+      }<br>+<br>+ return 0;<br>+}<br>+<br>+static int<br>+dumpc (struct irq_routing_table *pir)<br>+{<br>+    int i, slot, irq;<br>+<br>+ puts ("const struct irq_routing_table table = {");<br>+<br>+      putchar ('\t');<br>+      if (pir->signature == PIRQ_SIGNATURE)<br>+             printf ("PIRQ_SIGNATURE");<br>+ else<br>+         printf ("0x%08x", pir->signature);<br>+      printf (",\t\t/* u32 signature */\n");<br>+<br>+  putchar ('\t');<br>+      if (pir->version == PIRQ_VERSION)<br>+         printf ("PIRQ_VERSION");<br>+   else<br>+         printf ("0x%08x", pir->signature);<br>+      printf (",\t\t/* u16 version */\n");<br>+<br>+    putchar ('\t');<br>+      if ((pir->size - 32) % 16 == 0)<br>+           printf ("32 + 16 * %d", (pir->size - 32) / 16);<br>+ else<br>+         printf ("%d", pir->size);<br>+       printf (",\t\t/* Max. number of devices on the bus */\n");<br>+<br>+      printf ("\t0x%02x,\t\t\t/* Interrupt router bus */\n", pir->rtr_bus);<br>+   printf ("\t(0x%02x << 3) | 0x%x,\t/* Interrupt router dev */\n", pir->rtr_devfn >> 3, pir->rtr_devfn & 7);<br>+   printf ("\t0x%x,\t\t\t/* IRQs devoted exclusively for PCI */\n", pir->exclusive_irqs);<br>+  printf ("\t0x%04x,\t\t\t/* Vendor */\n", pir->rtr_vendor);<br>+      printf ("\t0x%04x,\t\t\t/* Device */\n", pir->rtr_device);<br>+      printf ("\t0x%04x,\t\t\t/* Miniport */\n", pir->miniport_data);<br>+ printf ("\t{");<br>+    for (i = 0; i < 11; i++) {<br>+                printf (" %d", pir->rfu[i]);<br>+            if (i < 10)<br>+                       printf (",");<br>+      }<br>+    printf (" }, /* u8 rfu[11] */\n");<br>+ printf ("\t0x%02x,\t\t\t/* Checksum (has to be set to some value that\n", pir->checksum);<br>+       puts ("\t\t\t\t * would give 0 after the sum of all bytes");<br>+       puts ("\t\t\t\t * for this structure (including checksum). */");<br>+   puts ("\t{");<br>+<br>+   printf ("\t\t/* bus,        dev | fn,   {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */\n");<br>+  for (slot = 0; (void *)&pir->slots[slot] < (void *)pir + pir->size; slot++) {<br>+           printf ("\t\t{0x%02x, ", pir->slots[slot].bus);<br>+         printf ("(0x%02x << 3) | 0x%x, {", pir->slots[slot].devfn >> 3, pir->slots[slot].devfn & 7);<br>+         for (irq = 0; irq < 4; irq++) {<br>+                   printf ("{0x%02x, 0x%04x}", pir->slots[slot].irq[irq].link, pir->slots[slot].irq[irq].bitmap);<br>+                       if (irq < 3)<br>+                              printf (", ");<br>+             }<br>+            printf ("}, 0x%x, 0x%x},\n", pir->slots[slot].slot, pir->slots[slot].rfu);<br>+   }<br>+    puts ("\t}\n};");<br>+<br>+       return 0;<br>+}<br>+<br>+static int<br>+dumpr (struct irq_routing_table *pir)<br>+{<br>+    int written = 0;<br>+     int ret;<br>+<br>+  do {<br>+         ret = write (STDOUT_FILENO, pir + written, pir->size - written);<br>+          switch (ret) {<br>+               case -1:<br>+                     perror ("write");<br>+                  /* fallthrough */<br>+            case 0:<br>+                      return 1;<br>+            default:<br>+                     written += ret;<br>+              }<br>+    } while (written < pir->size);<br>+<br>+      return 0;<br>+}<br>+<br>+int<br>+main (int argc, char *argv[])<br>+{<br>+   int fd;<br>+      void *mem;<br>+   struct irq_routing_table *pir;<br>+       const char *pathname;<br>+        size_t size, offset, step;<br>+   struct stat statbuf;<br>+ enum { DEFAULT, C, RAW } format = DEFAULT;<br>+   int arg = 1;<br>+<br>+      if (argc > arg && argv[arg][0] == '-') {<br>+          if (   strcmp (argv[arg], "--default") == 0<br>+                    || strcmp (argv[arg], "-d") == 0) {<br>+                    format = DEFAULT;<br>+            } else if (  strcasecmp (argv[arg], "--c") == 0<br>+                       || strcasecmp (argv[arg], "-c") == 0) {<br>+                 format = C;<br>+          } else if (   strcmp (argv[arg], "--raw") == 0<br>+                        || strcmp (argv[arg], "-r") == 0) {<br>+                     format = RAW;<br>+                } else if (strcmp (argv[arg], "--") != 0) {<br>+                        fprintf (stderr, "Bad argument: %s\n", argv[arg]);<br>+                 return 1;<br>+            }<br>+            arg++;<br>+       }<br>+<br>+ if (argc > arg) {<br>+         if (stat (argv[arg], &statbuf) == -1) {<br>+                  perror (argv[arg]);<br>+                  return 1;<br>+            }<br>+<br>+         pathname = argv[arg];<br>+                offset = 0;<br>+          size = statbuf.st_size;<br>+              step = 4;<br>+            arg++;<br>+       } else {<br>+             pathname = "/dev/mem";<br>+             offset = 0xf0000;<br>+            size = 0x10000;<br>+              step = 16;<br>+   }<br>+<br>+ if (argc > arg) {<br>+         fprintf (stderr, "Extra argument: %s\n", argv[arg]);<br>+               return 1;<br>+    }<br>+<br>+ fd = open (pathname, O_RDONLY);<br>+      if (fd == -1) {<br>+              perror (pathname);<br>+           return 1;<br>+    }<br>+<br>+ mem = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, offset);<br>+  if (mem == MAP_FAILED) {<br>+             perror ("mmap");<br>+           return 1;<br>+    }<br>+<br>+ for (pir = mem; (void *)pir < mem + size; pir = (void *)pir + step) {<br>+             if (pir->signature == PIRQ_SIGNATURE)<br>+                     break;<br>+       }<br>+    if (pir == mem + size) {<br>+             fprintf (stderr, "$PIR signature not found\n");<br>+            return 1;<br>+    }<br>+<br>+ switch (format) {<br>+    case DEFAULT:<br>+                return dump (pir);<br>+   case RAW:<br>+            return dumpr (pir);<br>+  case C:<br>+              return dumpc (pir);<br>+  }<br>+}<br></pre><p>To view, visit <a href="https://review.coreboot.org/22256">change 22256</a>. To unsubscribe, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/22256"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I9b0a2ae459bb98ed6854fef280d67f9c14a25314 </div>
<div style="display:none"> Gerrit-Change-Number: 22256 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Lubomir Rintel <lkundrak@v3.sk> </div>