Add option to parse NOMATCH event and suggest modules to load

Add --nomatch/-p to search for individual drivers based on a NOMATCH
event from devd.

Submitted by: hps (earlier version)
Sponsored by: Netflix
This commit is contained in:
Warner Losh 2018-02-17 06:57:34 +00:00
parent 5e0195c8f5
commit d38a8a7aa5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=329444
2 changed files with 55 additions and 3 deletions

View file

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 12, 2018
.Dd February 16, 2018
.Dt DEVMATCH 8
.Os
.Sh NAME
@ -33,9 +33,10 @@
.Nd print information about unattached devices
.Sh SYNOPSIS
.Nm
.Op Fl aduv
.Op Fl adpuv
.Op Fl -all
.Op Fl -dump
.Op Fl -nomatch
.Op Fl -unbound
.Op Fl -verbose
.Sh DESCRIPTION
@ -50,6 +51,10 @@ Include all devices, not just the ones that are unattached.
Produce a human readable dump of the
.Pa linker.hints
file.
.It Fl p Fl -nomatch
Parse and use a standard NOMATCH event from
.Xr devd 8
for matching instead of searching the device tree.
.It Fl u Fl -unbound
Attempt to produce a list of those drivers with PNP info whose driver
tables with that PNP info can't be found.

View file

@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
static struct option longopts[] = {
{ "all", no_argument, NULL, 'a' },
{ "dump", no_argument, NULL, 'd' },
{ "nomatch", required_argument, NULL, 'p' },
{ "unbound", no_argument, NULL, 'u' },
{ "verbose", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 }
@ -54,6 +55,7 @@ static struct option longopts[] = {
static int all_flag;
static int dump_flag;
static char *nomatch_str;
static int unbound_flag;
static int verbose_flag;
@ -397,6 +399,46 @@ find_unmatched(struct devinfo_dev *dev, void *arg)
return (devinfo_foreach_device_child(dev, find_unmatched, arg));
}
static void
find_nomatch(char *nomatch)
{
char *bus, *pnpinfo, *tmp;
/*
* Find our bus name. It will include the unit number. We have to search
* backwards to avoid false positive for any PNP string that has ' on '
* in them, which would come earlier in the string. Like if there were
* an 'Old Bard' ethernet card made by 'Stratford on Avon Hardware' or
* something silly like that.
*/
tmp = nomatch + strlen(nomatch) - 4;
while (tmp > nomatch && strncmp(tmp, " on ", 4) != 0)
tmp--;
if (tmp == nomatch)
errx(1, "No bus found in nomatch string: '%s'", nomatch);
bus = tmp + 4;
*tmp = '\0';
tmp = bus + strlen(bus) - 1;
while (tmp > bus && isdigit(*tmp))
tmp--;
*++tmp = '\0';
/*
* Note: the NOMATCH events place both the bus location as well as the
* pnp info after the 'at' and we don't know where one stops and the
* other begins, so we pass the whole thing to our search routine.
*/
if (*nomatch == '?')
nomatch++;
if (strncmp(nomatch, " at ", 4) != 0)
errx(1, "Malformed NOMATCH string: '%s'", nomatch);
pnpinfo = nomatch + 4;
search_hints(bus, "", pnpinfo);
exit(0);
}
static void
usage(void)
{
@ -410,7 +452,7 @@ main(int argc, char **argv)
struct devinfo_dev *root;
int ch;
while ((ch = getopt_long(argc, argv, "aduv",
while ((ch = getopt_long(argc, argv, "adp:uv",
longopts, NULL)) != -1) {
switch (ch) {
case 'a':
@ -419,6 +461,9 @@ main(int argc, char **argv)
case 'd':
dump_flag++;
break;
case 'p':
nomatch_str = optarg;
break;
case 'u':
unbound_flag++;
break;
@ -441,6 +486,8 @@ main(int argc, char **argv)
exit(0);
}
if (nomatch_str != NULL)
find_nomatch(nomatch_str);
if (devinfo_init())
err(1, "devinfo_init");
if ((root = devinfo_handle_to_device(DEVINFO_ROOT_DEVICE)) == NULL)