summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-11-05 20:32:50 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-11-05 20:32:50 +0000
commit91278afb30123fa565d911dd57793d102f7a23c8 (patch)
tree4147241d17f76e6d24fa0b5ec813e1625ae76c3d
parentc649240f9d10d50e67c6aeed38b727cc1604b555 (diff)
Implement -r option that dunps the contents of a PCI ROM to file.
ok oga@
-rw-r--r--usr.sbin/pcidump/pcidump.817
-rw-r--r--usr.sbin/pcidump/pcidump.c50
2 files changed, 60 insertions, 7 deletions
diff --git a/usr.sbin/pcidump/pcidump.8 b/usr.sbin/pcidump/pcidump.8
index 6602bc86c82..ebdf0a09d3e 100644
--- a/usr.sbin/pcidump/pcidump.8
+++ b/usr.sbin/pcidump/pcidump.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pcidump.8,v 1.8 2009/06/05 19:19:02 deraadt Exp $
+.\" $OpenBSD: pcidump.8,v 1.9 2009/11/05 20:32:49 kettenis Exp $
.\"
.\" Copyright (c) 2007 Paul de Weerd <weerd@weirdnet.nl>
.\"
@@ -14,7 +14,7 @@
.\" TORTIOUS ACTION, ARISING OUT OF
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: June 5 2009 $
+.Dd $Mdocdate: November 5 2009 $
.Dt PCIDUMP 8
.Os
.Sh NAME
@@ -28,6 +28,12 @@
.Sm off
.Op Ar bus : dev : func
.Sm on
+.Nm pcidump
+.Fl r Ar file
+.Op Fl d Ar pcidev
+.Sm off
+.Ar bus : dev : func
+.Sm on
.Sh DESCRIPTION
The
.Nm
@@ -46,6 +52,13 @@ If specified without
.Ar bus : dev : func ,
.Sm on
all PCI devices in the domain will be shown.
+.It Fl r Ar file
+Reads the PCI ROM from the device specified by
+.Sm off
+.Ar bus : dev : func ,
+.Sm on
+and writes its contents to
+.Ar file .
.It Fl v
Shows detailed information about PCI devices.
.It Fl x
diff --git a/usr.sbin/pcidump/pcidump.c b/usr.sbin/pcidump/pcidump.c
index 6b73c47c91f..c1fcfd39861 100644
--- a/usr.sbin/pcidump/pcidump.c
+++ b/usr.sbin/pcidump/pcidump.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcidump.c,v 1.19 2009/06/07 21:48:16 sobrado Exp $ */
+/* $OpenBSD: pcidump.c,v 1.20 2009/11/05 20:32:49 kettenis Exp $ */
/*
* Copyright (c) 2006, 2007 David Gwynne <loki@animata.net>
@@ -42,6 +42,7 @@ const char *str2busdevfunc(const char *, int *, int *, int *);
int pci_nfuncs(int, int);
int pci_read(int, int, int, u_int32_t, u_int32_t *);
void dump_caplist(int, int, int, u_int8_t);
+int dump_rom(int, int, int);
__dead void
usage(void)
@@ -49,12 +50,13 @@ usage(void)
extern char *__progname;
fprintf(stderr,
- "usage: %s [-v] [-x | -xx] [-d pcidev] [bus:dev:func]\n",
+ "usage: %s [-v] [-x | -xx] [-d pcidev] [-r file] [bus:dev:func]\n",
__progname);
exit(1);
}
int pcifd;
+int romfd;
int verbose = 0;
int hex = 0;
@@ -86,15 +88,20 @@ main(int argc, char *argv[])
int nfuncs;
int bus, dev, func;
char pcidev[MAXPATHLEN] = PCIDEV;
+ char *romfile = NULL;
const char *errstr;
int c, error = 0, dumpall = 1, domid = 0;
- while ((c = getopt(argc, argv, "d:vx")) != -1) {
+ while ((c = getopt(argc, argv, "d:r:vx")) != -1) {
switch (c) {
case 'd':
strlcpy(pcidev, optarg, sizeof(pcidev));
dumpall = 0;
break;
+ case 'r':
+ romfile = optarg;
+ dumpall = 0;
+ break;
case 'v':
verbose = 1;
break;
@@ -108,9 +115,15 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
- if (argc > 1)
+ if (argc > 1 || (romfile && argc != 1))
usage();
+ if (romfile) {
+ romfd = open(romfile, O_WRONLY|O_CREAT|O_TRUNC, 0777);
+ if (romfd == -1)
+ err(1, "%s", romfile);
+ }
+
if (argc == 1)
dumpall = 0;
@@ -118,7 +131,6 @@ main(int argc, char *argv[])
pcifd = open(pcidev, O_RDONLY, 0777);
if (pcifd == -1)
err(1, "%s", pcidev);
- printf("Domain %s:\n", pcidev);
} else {
for (;;) {
snprintf(pcidev, 16, "/dev/pci%d", domid++);
@@ -144,12 +156,15 @@ main(int argc, char *argv[])
nfuncs = pci_nfuncs(bus, dev);
if (nfuncs == -1 || func > nfuncs)
error = ENXIO;
+ else if (romfile)
+ error = dump_rom(bus, dev, func);
else
error = probe(bus, dev, func);
if (error != 0)
errx(1, "\"%s\": %s", argv[0], strerror(error));
} else {
+ printf("Domain %s:\n", pcidev);
scanpcidomain();
}
@@ -590,3 +605,28 @@ pci_read(int bus, int dev, int func, u_int32_t reg, u_int32_t *val)
return (0);
}
+
+int
+dump_rom(int bus, int dev, int func)
+{
+ struct pci_rom rom;
+
+ bzero(&rom, sizeof(rom));
+ rom.pr_sel.pc_bus = bus;
+ rom.pr_sel.pc_dev = dev;
+ rom.pr_sel.pc_func = func;
+ if (ioctl(pcifd, PCIOCGETROMLEN, &rom))
+ return (errno);
+
+ rom.pr_rom = malloc(rom.pr_romlen);
+ if (rom.pr_rom == NULL)
+ return (ENOMEM);
+
+ if (ioctl(pcifd, PCIOCGETROM, &rom))
+ return (errno);
+
+ if (write(romfd, rom.pr_rom, rom.pr_romlen) == -1)
+ return (errno);
+
+ return (0);
+}