Page MenuHomeFreeBSD

D55915.diff
No OneTemporary

D55915.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 requests 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();
}
@@ -1365,6 +1393,36 @@
close(fd);
}
+static void
+map_bar(const char *name, const char *reg, int flags, struct pci_bar_mmap *pbm)
+{
+ int fd;
+ char *el;
+
+ memset(pbm, 0, sizeof(struct pci_bar_mmap));
+ 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;
+ pbm->pbm_flags = flags;
+
+ 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)");
+
+ close(fd);
+}
+
+static void
+unmap_bar(struct pci_bar_mmap *pbm)
+{
+ munmap(pbm->pbm_map_base, pbm->pbm_map_length);
+}
+
static void
dump_bar(const char *name, const char *reg, const char *bar_start,
const char *bar_count, int width, int verbose)
@@ -1376,7 +1434,6 @@
uint64_t *dx, a, start, count;
char *el;
size_t res;
- int fd;
start = 0;
if (bar_start != NULL) {
@@ -1393,19 +1450,7 @@
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)");
+ map_bar(name, reg, 0, &pbm);
if (count == 0)
count = pbm.pbm_bar_length / width;
@@ -1475,6 +1520,103 @@
errx(1, "invalid access width");
}
- munmap((void *)pbm.pbm_map_base, pbm.pbm_map_length);
- close(fd);
+ unmap_bar(&pbm);
+}
+
+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 items_per_line, i;
+
+ rend = rstart = strtol(start_end, &end, 0);
+ if (*end == ':') {
+ end++;
+ rend = strtol(end, NULL, 0);
+ }
+
+ map_bar(name, bar, 0, &pbm);
+
+ items_per_line = 16 / width;
+ 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]);
+ }
+ /* Use a double space in the middle when outputting bytes. */
+ if (width == 1 && (i % 16) == 8)
+ putchar(' ');
+ putchar(i % items_per_line == 0 ? '\n' : ' ');
+ }
+ if (i % items_per_line != 1)
+ putchar('\n');
+
+ unmap_bar(&pbm);
+}
+
+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;
+
+ 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 */
+
+ map_bar(name, bar, PCIIO_BAR_MMAP_RW, &pbm);
+
+ addr = (uintptr_t)pbm.pbm_map_base + pbm.pbm_bar_off + offset;
+ switch (width) {
+ case 1:
+ *((uint8_t *)addr) = value;
+ break;
+ case 2:
+ *((uint16_t *)addr) = value;
+ break;
+ case 4:
+ *((uint32_t *)addr) = value;
+ break;
+ case 8:
+ *((uint64_t *)addr) = value;
+ break;
+ default:
+ errx(1, "invalid write width");
+ }
+
+ unmap_bar(&pbm);
}

File Metadata

Mime Type
text/plain
Expires
Thu, Jul 16, 7:13 AM (20 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35128844
Default Alt Text
D55915.diff (7 KB)

Event Timeline