Page MenuHomeFreeBSD

D55915.id176446.diff
No OneTemporary

D55915.id176446.diff

diff --git a/usr.sbin/pciconf/pciconf.8 b/usr.sbin/pciconf/pciconf.8
--- a/usr.sbin/pciconf/pciconf.8
+++ b/usr.sbin/pciconf/pciconf.8
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd March 10, 2026
+.Dd April 24, 2026
.Dt PCICONF 8
.Os
.Sh NAME
@@ -42,6 +42,10 @@
.Fl w Oo Fl b | h Oc Ar device addr value
.Nm
.Fl D Oo Fl b | h | x Oc Ar device bar Op Ar start Op Ns Ar count
+.Nm
+.Fl R Oo Fl b | h | x Oc Ar device bar start Ns Op : Ns Ar end
+.Nm
+.Fl W Oo Fl b | h | x Oc Ar device bar offset value
.Sh DESCRIPTION
The
.Nm
@@ -341,7 +345,8 @@
.Pp
The
.Fl D
-option request a dump of the specified BAR.
+option request a dump of the BAR specified by its offset in config space
+.Ar bar .
Dump is performed to the standard output, raw register values
are written.
Use
@@ -353,9 +358,25 @@
and
.Ar count
of the registers dumped can be specified, in multiple of the operation width,
-see next paragraph.
+see below.
+.Pp
+The
+.Fl R
+option reads from the BAR specified by its offset in config space
+.Ar bar .
+It starts reading at byte offset
+.Ar start .
+The optional last argument
+.Ar end
+specifies a range to read.
+The
+.Fl W
+option writes the
+.Ar value
+to the BAR at byte offset
+.Ar offset .
.Pp
-For read, write, and dump operations, the flags
+For read, write, BAR dump, BAR read, and BAR write operations, the flags
.Fl b ,
.Fl h ,
and
@@ -369,7 +390,7 @@
indicates a quadword (four-byte) operation.
The default is to read or
write a longword (four bytes).
-The quadword mode is only valid for BAR dump.
+The quadword mode is only valid for BAR dump, BAR read, and BAR write.
.Sh ENVIRONMENT
PCI vendor and device information is read from
.Pa /usr/local/share/pciids/pci.ids .
diff --git a/usr.sbin/pciconf/pciconf.c b/usr.sbin/pciconf/pciconf.c
--- a/usr.sbin/pciconf/pciconf.c
+++ b/usr.sbin/pciconf/pciconf.c
@@ -91,6 +91,10 @@
static void chkattached(const char *);
static void dump_bar(const char *name, const char *reg, const char *bar_start,
const char *bar_count, int width, int verbose);
+static void read_bar(const char *name, const char *bar, const char *start_end,
+ int width);
+static void write_bar(const char *name, const char *bar, const char *offset_str,
+ const char *value_str, int width);
static int exitstatus = 0;
@@ -104,7 +108,9 @@
" pciconf -a device\n"
" pciconf -r [-b | -h] device addr[:addr2]\n"
" pciconf -w [-b | -h] device addr value\n"
- " pciconf -D [-b | -h | -x] device bar [start [count]]"
+ " pciconf -D [-b | -h | -x] device bar [start [count]]\n"
+ " pciconf -R [-b | -h | -x] device bar start[:end]\n"
+ " pciconf -W [-b | -h | -x] device bar offset value"
"\n");
exit(1);
}
@@ -113,14 +119,15 @@
main(int argc, char **argv)
{
int c, width;
- enum { NONE, LIST, TREE, READ, WRITE, ATTACHED, DUMPBAR } mode;
+ enum { NONE, LIST, TREE, READ, WRITE, ATTACHED, DUMPBAR, READBAR,
+ WRITEBAR } mode;
int compact, bars, bridge, caps, errors, verbose, vpd;
mode = NONE;
compact = bars = bridge = caps = errors = verbose = vpd = 0;
width = 4;
- while ((c = getopt(argc, argv, "aBbcDehlrtwVvx")) != -1) {
+ while ((c = getopt(argc, argv, "aBbcDehlRrtWwVvx")) != -1) {
switch(c) {
case 'a':
mode = ATTACHED;
@@ -157,6 +164,10 @@
mode = LIST;
break;
+ case 'R':
+ mode = READBAR;
+ break;
+
case 'r':
mode = READ;
break;
@@ -164,6 +175,11 @@
case 't':
mode = TREE;
break;
+
+ case 'W':
+ mode = WRITEBAR;
+ break;
+
case 'w':
mode = WRITE;
break;
@@ -221,6 +237,18 @@
optind + 3 < argc ? argv[optind + 3] : NULL,
width, verbose);
break;
+ case READBAR:
+ if (optind + 3 != argc)
+ usage();
+ read_bar(argv[optind], argv[optind + 1], argv[optind + 2],
+ width);
+ break;
+ case WRITEBAR:
+ if (optind + 4 != argc)
+ usage();
+ write_bar(argv[optind], argv[optind + 1], argv[optind + 2],
+ argv[optind + 3], width);
+ break;
default:
usage();
}
@@ -1368,6 +1396,28 @@
close(fd);
}
+static int
+openmap_bar(const char *name, const char *reg, struct pci_bar_mmap *pbm)
+{
+ int fd;
+ char *el;
+
+ pbm->pbm_sel = getsel(name);
+ pbm->pbm_reg = strtoul(reg, &el, 0);
+ if (*reg == '\0' || *el != '\0')
+ errx(1, "Invalid bar specification %s", reg);
+ pbm->pbm_memattr = VM_MEMATTR_DEVICE;
+
+ fd = open(_PATH_DEVPCI, O_RDWR, 0);
+ if (fd < 0)
+ err(1, "%s", _PATH_DEVPCI);
+
+ if (ioctl(fd, PCIOCBARMMAP, pbm) < 0)
+ err(1, "ioctl(PCIOCBARMMAP)");
+
+ return (fd);
+}
+
static void
dump_bar(const char *name, const char *reg, const char *bar_start,
const char *bar_count, int width, int verbose)
@@ -1396,19 +1446,8 @@
bar_count);
}
- pbm.pbm_sel = getsel(name);
- pbm.pbm_reg = strtoul(reg, &el, 0);
- if (*reg == '\0' || *el != '\0')
- errx(1, "Invalid bar specification %s", reg);
- pbm.pbm_flags = 0;
- pbm.pbm_memattr = VM_MEMATTR_DEVICE;
-
- fd = open(_PATH_DEVPCI, O_RDWR, 0);
- if (fd < 0)
- err(1, "%s", _PATH_DEVPCI);
-
- if (ioctl(fd, PCIOCBARMMAP, &pbm) < 0)
- err(1, "ioctl(PCIOCBARMMAP)");
+ memset(&pbm, 0, sizeof(struct pci_bar_mmap));
+ fd = openmap_bar(name, reg, &pbm);
if (count == 0)
count = pbm.pbm_bar_length / width;
@@ -1481,3 +1520,105 @@
munmap((void *)pbm.pbm_map_base, pbm.pbm_map_length);
close(fd);
}
+
+union tunion {
+ uint8_t one;
+ uint16_t two;
+ uint32_t four;
+ uint64_t eight;
+ uint8_t bytes[8];
+};
+
+static void
+read_bar(const char *name, const char *bar, const char *start_end, int width)
+{
+ struct pci_bar_mmap pbm;
+ long rstart, rend, r;
+ char *end;
+ int fd, i;
+
+ rend = rstart = strtol(start_end, &end, 0);
+ if (end && *end == ':') {
+ end++;
+ rend = strtol(end, (char **) 0, 0);
+ }
+
+ memset(&pbm, 0, sizeof(struct pci_bar_mmap));
+ fd = openmap_bar(name, bar, &pbm);
+
+ for (i = 1, r = rstart; r <= rend; i++, r += width) {
+ uintptr_t addr;
+ union tunion t;
+ int j;
+
+ addr = (uintptr_t)pbm.pbm_map_base + pbm.pbm_bar_off + r;
+ switch (width) {
+ case 1:
+ t.one = *((uint8_t *)addr);
+ break;
+ case 2:
+ t.two = *((uint16_t *)addr);
+ break;
+ case 4:
+ t.four = *((uint32_t *)addr);
+ break;
+ case 8:
+ t.eight = *((uint64_t *)addr);
+ break;
+ default:
+ errx(1, "invalid read width");
+ }
+ for (j = 0; j < width; j++) {
+ printf("%02x", t.bytes[j]);
+ }
+ if (i && !(i % 8))
+ putchar(' ');
+ putchar(i % (16/width) ? ' ' : '\n');
+ }
+ if (i % (16/width) != 1)
+ putchar('\n');
+
+ munmap((void *)pbm.pbm_map_base, pbm.pbm_map_length);
+ close(fd);
+}
+
+static void
+write_bar(const char *name, const char *bar, const char *offset_str,
+ const char *value_str, int width)
+{
+ struct pci_bar_mmap pbm;
+ uint64_t offset, value;
+ uintptr_t addr;
+ char *el;
+ int fd;
+
+ offset = strtoul(offset_str, &el, 0);
+ if (*el != '\0')
+ errx(1, "Invalid bar offset specification %s", offset_str);
+ value = strtoul(value_str, (char **)0, 0); /* XXX error check */
+
+ memset(&pbm, 0, sizeof(struct pci_bar_mmap));
+ pbm.pbm_flags = PCIIO_BAR_MMAP_RW;
+ fd = openmap_bar(name, bar, &pbm);
+
+ addr = (uintptr_t)pbm.pbm_map_base + pbm.pbm_bar_off + offset;
+ switch (width) {
+ case 1:
+ *((uint8_t *)addr) = (uint8_t)value;
+ break;
+ case 2:
+ *((uint16_t *)addr) = (uint16_t)value;
+ break;
+ case 4:
+ *((uint32_t *)addr) = (uint32_t)value;
+ break;
+ case 8:
+ *((uint64_t *)addr) = (uint64_t)value;
+ break;
+ default:
+ errx(1, "invalid write width");
+ }
+
+ munmap((void *)pbm.pbm_map_base, pbm.pbm_map_length);
+ close(fd);
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Sep 10, 10:46 PM (7 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38671430
Default Alt Text
D55915.id176446.diff (7 KB)

Event Timeline