allow specifying literal values in MODULE_PNP_INFO(9)
Yuri Pankov
yuripv at yuripv.net
Tue Sep 25 13:09:54 UTC 2018
Hi,
Looking at adding the MODULE_PNP_INFO() entry to iwm(4), I came up with
the patch in https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=231625
adding redundant and useless vendor field to iwm_devices. While it
works, it's unfortunate, and I have started looking into possible
solutions and the result is a small patch for kldxref(8) allowing
specifying literal values in descriptor_string like the following:
MODULE_PNP_INFO("U16=8086:vendor;U16:device;P:#", pci, iwm_pci_driver,
iwm_devices, sizeof(iwm_devices[0]), nitems(iwm_devices));
...so that we always have vendor 0x8086 and only consume the device field.
If it makes at least some sense, I'll put it for review.
-------------- next part --------------
diff --git a/usr.sbin/kldxref/kldxref.c b/usr.sbin/kldxref/kldxref.c
index f0d699369dbd..e494e8a9f039 100644
--- a/usr.sbin/kldxref/kldxref.c
+++ b/usr.sbin/kldxref/kldxref.c
@@ -168,7 +168,7 @@ pnp_eisaformat(uint32_t id)
struct pnp_elt
{
- int pe_kind; /* What kind of entry */
+ int pe_kind; /* What kind of entry */
#define TYPE_SZ_MASK 0x0f
#define TYPE_FLAGGED 0x10 /* all f's is a wildcard */
#define TYPE_INT 0x20 /* Is a number */
@@ -191,8 +191,9 @@ struct pnp_elt
#define TYPE_P 9
#define TYPE_E 10
#define TYPE_T 11
- int pe_offset; /* Offset within the element */
- char * pe_key; /* pnp key name */
+ int pe_offset; /* Offset within the element */
+ char *pe_key; /* pnp key name */
+ uint32_t pe_value; /* literal value, if any */
TAILQ_ENTRY(pnp_elt) next; /* Link */
};
typedef TAILQ_HEAD(pnp_head, pnp_elt) pnp_list;
@@ -232,10 +233,10 @@ static int
parse_pnp_list(const char *desc, char **new_desc, pnp_list *list)
{
const char *walker, *ep;
- const char *colon, *semi;
+ const char *assign, *colon, *semi;
struct pnp_elt *elt;
char *nd;
- char type[8], key[32];
+ char type[8], value[9], key[32];
int off;
walker = desc;
@@ -245,14 +246,28 @@ parse_pnp_list(const char *desc, char **new_desc, pnp_list *list)
if (verbose > 1)
printf("Converting %s into a list\n", desc);
while (walker < ep) {
+ assign = strchr(walker, '=');
colon = strchr(walker, ':');
semi = strchr(walker, ';');
+ if (colon == NULL)
+ goto err;
+ if (assign != NULL && assign > colon)
+ assign = NULL;
if (semi != NULL && semi < colon)
goto err;
if (colon - walker > sizeof(type))
goto err;
- strncpy(type, walker, colon - walker);
- type[colon - walker] = '\0';
+ if (assign != NULL) {
+ strncpy(type, walker, assign - walker);
+ type[assign - walker] = '\0';
+ if (colon - assign >= sizeof(value))
+ goto err;
+ strncpy(value, assign + 1, colon - assign - 1);
+ value[colon - assign - 1] = '\0';
+ } else {
+ strncpy(type, walker, colon - walker);
+ type[colon - walker] = '\0';
+ }
if (semi != NULL) {
if (semi - colon >= sizeof(key))
goto err;
@@ -265,8 +280,15 @@ parse_pnp_list(const char *desc, char **new_desc, pnp_list *list)
strcpy(key, colon + 1);
walker = ep;
}
- if (verbose > 1)
- printf("Found type %s for name %s\n", type, key);
+ if (verbose > 1) {
+ if (assign != NULL) {
+ printf("Found type %s for name %s "
+ "with value %s\n", type, key, value);
+ } else {
+ printf("Found type %s for name %s\n",
+ type, key);
+ }
+ }
/* Skip pointer place holders */
if (strcmp(type, "P") == 0) {
off += sizeof(void *);
@@ -318,7 +340,14 @@ parse_pnp_list(const char *desc, char **new_desc, pnp_list *list)
* have sane ordering of types.
*/
if (elt->pe_kind & TYPE_INT) {
- elt->pe_offset = roundup2(elt->pe_offset, elt->pe_kind & TYPE_SZ_MASK);
+ /*
+ * Literal values (assign != NULL) don't consume space
+ * in the table.
+ */
+ if (assign == NULL) {
+ elt->pe_offset = roundup2(elt->pe_offset,
+ elt->pe_kind & TYPE_SZ_MASK);
+ }
off = elt->pe_offset + (elt->pe_kind & TYPE_SZ_MASK);
} else if (elt->pe_kind == TYPE_E) {
/* Type E stored as Int, displays as string */
@@ -340,9 +369,7 @@ parse_pnp_list(const char *desc, char **new_desc, pnp_list *list)
word);
nd += strlen(nd);
}
-
- }
- else {
+ } else {
if (elt->pe_kind & TYPE_FLAGGED)
*nd++ = 'J';
else if (elt->pe_kind & TYPE_GE)
@@ -351,9 +378,18 @@ parse_pnp_list(const char *desc, char **new_desc, pnp_list *list)
*nd++ = 'L';
else if (elt->pe_kind & TYPE_MASK)
*nd++ = 'M';
- else if (elt->pe_kind & TYPE_INT)
+ else if (elt->pe_kind & TYPE_INT) {
*nd++ = 'I';
- else if (elt->pe_kind == TYPE_D)
+ if (assign != NULL) {
+ char *cep;
+
+ errno = 0;
+ elt->pe_value = strtoul(value, &cep,
+ 16);
+ if (errno != 0 || *ep != '\0')
+ goto err;
+ }
+ } else if (elt->pe_kind == TYPE_D)
*nd++ = 'D';
else if (elt->pe_kind == TYPE_Z || elt->pe_kind == TYPE_E)
*nd++ = 'Z';
@@ -470,23 +506,27 @@ parse_entry(struct mod_metadata *md, const char *cval,
if (verbose > 1)
printf(":%#x;", value);
} else if (elt->pe_kind & TYPE_INT) {
+ char *val = elt->pe_value != 0 ?
+ (char *)&elt->pe_value :
+ walker + elt->pe_offset;
+
switch (elt->pe_kind & TYPE_SZ_MASK) {
case 1:
- memcpy(&v1, walker + elt->pe_offset, sizeof(v1));
+ memcpy(&v1, val, sizeof(v1));
if ((elt->pe_kind & TYPE_FLAGGED) && v1 == 0xff)
value = -1;
else
value = v1;
break;
case 2:
- memcpy(&v2, walker + elt->pe_offset, sizeof(v2));
+ memcpy(&v2, val, sizeof(v2));
if ((elt->pe_kind & TYPE_FLAGGED) && v2 == 0xffff)
value = -1;
else
value = v2;
break;
case 4:
- memcpy(&v4, walker + elt->pe_offset, sizeof(v4));
+ memcpy(&v4, val, sizeof(v4));
if ((elt->pe_kind & TYPE_FLAGGED) && v4 == 0xffffffff)
value = -1;
else
More information about the freebsd-hackers
mailing list