Date: Tue, 25 Sep 2018 16:10:26 +0300 From: Yuri Pankov <yuripv@yuripv.net> To: freebsd-hackers@freebsd.org Subject: allow specifying literal values in MODULE_PNP_INFO(9) Message-ID: <2926f43a-4709-3335-07a4-03248e13675a@yuripv.net>
index | next in thread | raw e-mail
[-- Attachment #1 --] 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. [-- Attachment #2 --] 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; elsehelp
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?2926f43a-4709-3335-07a4-03248e13675a>
