From nobody Wed Jun 24 20:04:53 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gltFd5d3Pz6jknc for ; Wed, 24 Jun 2026 20:04:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gltFd4cWvz44xJ for ; Wed, 24 Jun 2026 20:04:53 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782331493; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=sXnDcdRSCA2e5lWjm6jViPSLQZC91pCbM6qAO/Ebfjs=; b=fbOTL9caqS3X8kzZp7nz5m4THJTRGOlJYj5kF+H2655mj2osLlkEcQr6poD/hMRiuWQkWU IaLj1dBnJked/2wh5vOmTzuhhx/7Ac6U2ARa3mBwUf2rc//jofkcPp0C2lfQCA1ASNYrNb pHVwMcjQhO7vaUA5s1P6V6kMb8oqcVElypLFi+GgAvOIjHUYeJ25Oad5Kt0jrknAhHXVAe C3fkAH9t1eBt+ONLcCjV1TU3r927il39ONVOjVSWSCjFc2YMTrQjIgdKxvUsNZ/gmI3vNm sOkhhJtxNzBOa1tX7hlGnDOYht3CPTwZF8L2n9jw0TM/aIJJsRisNaFxqhyAXw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782331493; a=rsa-sha256; cv=none; b=PC02poNvOviAFLtuv+HNugpEMIa9vf5CasGD5pZZ3VKE1PN13QpwY9s/U4Dyb+R+eNB8p3 HkU+jCtA6uizowrTrdvNeFOUhYoyh5hYlZW2QW4gRJoXHgNz8jW9iDmXKaeRwptIhfMFNz qFyNHpYd/MbsrvzGuHaf5TCz5lYwCGlwUQDby+FymtTZWQ27Fw+qCJ4W1q96yai64TYvT9 a+8FCwY1wJlaMQWcZqoOd2iNiQBmOWFFF/27GlPsFhZeQAxpHD//hN/un83fVBN6UOjK+f uKCcqA56jjripfvYBkSqzFCAKqIZIcEl+J1A+YZuc9/SvO39vUFMtu2c9Hg/Ew== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782331493; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=sXnDcdRSCA2e5lWjm6jViPSLQZC91pCbM6qAO/Ebfjs=; b=akCpWPRL6dxe+Hdodgn6oa2mvG4apSY6F1/mSgx0EnO5/4Uu+QKOwrt+tUZP3zxu/O23t4 qwjsg0z1RCgBdmeGkFi6inGI7gQiK2KbkPLLUmeAo9dSu8ggvQV3isreAcWjLjkRF2h3iq kuxY34i5nO5iYT5bx7X509rnv8RjA9dZ2TvGp9rf5o++2m01fz0F1W940rje5HWdh+K5cl sBHcZ1o03LdxaOyJV5xSmFNfBHM9vHz7mOVxZMlXe1g38OPDDrYoOdX8+566atj4UTZNC0 9n57ePlLs6WHo6Kx7W8SWxTFAiAtb3Qp444q8G5wcPmxSumkT7PukQTjhJzNnw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gltFd3PYNzbGW for ; Wed, 24 Jun 2026 20:04:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 4694e by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 24 Jun 2026 20:04:53 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Timo =?utf-8?Q?V=C3=B6lker?= From: John Baldwin Subject: git: e63fbcc69402 - main - pciconf: Add option to write into a BAR region List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhb X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e63fbcc69402d4a1e8681a95710f0ec01a6837b4 Auto-Submitted: auto-generated Date: Wed, 24 Jun 2026 20:04:53 +0000 Message-Id: <6a3c3865.4694e.799386e4@gitrepo.freebsd.org> The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=e63fbcc69402d4a1e8681a95710f0ec01a6837b4 commit e63fbcc69402d4a1e8681a95710f0ec01a6837b4 Author: Timo Völker AuthorDate: 2026-06-24 19:57:34 +0000 Commit: John Baldwin CommitDate: 2026-06-24 19:57:34 +0000 pciconf: Add option to write into a BAR region Add option -W that allows to write into a BAR region. Also, add an option -R that allows to read from a BAR region that works similar to -r that reads from the PCI config space. Reviewed by: bcr (manpages), jhb Differential Revision: https://reviews.freebsd.org/D55915 --- usr.sbin/pciconf/pciconf.8 | 31 ++++++-- usr.sbin/pciconf/pciconf.c | 180 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 187 insertions(+), 24 deletions(-) diff --git a/usr.sbin/pciconf/pciconf.8 b/usr.sbin/pciconf/pciconf.8 index 7958a538f3d9..acb5fc4d039d 100644 --- 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 @@ of device .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 @@ Optionally, the 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 halfword (two-byte) operation. 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 index e2a3beeba6f7..f3c6a413826f 100644 --- a/usr.sbin/pciconf/pciconf.c +++ b/usr.sbin/pciconf/pciconf.c @@ -91,6 +91,10 @@ static void writeit(const char *, const char *, const char *, int); 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 @@ usage(void) " 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 @@ int 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 @@ main(int argc, char **argv) mode = LIST; break; + case 'R': + mode = READBAR; + break; + case 'r': mode = READ; break; @@ -164,6 +175,11 @@ main(int argc, char **argv) case 't': mode = TREE; break; + + case 'W': + mode = WRITEBAR; + break; + case 'w': mode = WRITE; break; @@ -221,6 +237,18 @@ main(int argc, char **argv) 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 @@ chkattached(const char *name) 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 @@ dump_bar(const char *name, const char *reg, const char *bar_start, uint64_t *dx, a, start, count; char *el; size_t res; - int fd; start = 0; if (bar_start != NULL) { @@ -1393,19 +1450,7 @@ dump_bar(const char *name, const char *reg, const char *bar_start, 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 @@ dump_bar(const char *name, const char *reg, const char *bar_start, 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); }