Commit the ndiscvt(8) utility too. (Missed it in the last import.)
This commit is contained in:
parent
c854fc1092
commit
d934c8b0de
23
usr.sbin/ndiscvt/Makefile
Normal file
23
usr.sbin/ndiscvt/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../sys/dev/ndis
|
||||
|
||||
PROG= ndiscvt
|
||||
SRCS= ndiscvt.c
|
||||
SRCS+= subr_pe.c
|
||||
SRCS+= inf.c inf-token.l inf-parse.y y.tab.h
|
||||
|
||||
MAN8= ndiscvt.8
|
||||
|
||||
WARNS= 4
|
||||
|
||||
DPADD= ${LIBL}
|
||||
LDADD= -ll
|
||||
|
||||
YFLAGS+=-v
|
||||
|
||||
CFLAGS+=-I. -I${.CURDIR} -I${.CURDIR}/../../sys
|
||||
|
||||
CLEANFILES= y.output
|
||||
|
||||
.include <bsd.prog.mk>
|
83
usr.sbin/ndiscvt/inf-parse.y
Normal file
83
usr.sbin/ndiscvt/inf-parse.y
Normal file
@ -0,0 +1,83 @@
|
||||
%{
|
||||
/*
|
||||
* $Id: inf-parse.y,v 1.3 2003/11/30 21:58:16 winter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include "inf.h"
|
||||
|
||||
extern int yyparse (void);
|
||||
extern int yylex (void);
|
||||
extern void yyerror(const char *);
|
||||
%}
|
||||
|
||||
%token EQUALS COMMA EOL
|
||||
%token <str> SECTION
|
||||
%token <str> STRING
|
||||
%token <str> WORD
|
||||
|
||||
%union {
|
||||
char *str;
|
||||
}
|
||||
|
||||
%%
|
||||
|
||||
inf_file
|
||||
: inf_list
|
||||
|
|
||||
;
|
||||
|
||||
inf_list
|
||||
: inf
|
||||
| inf_list inf
|
||||
;
|
||||
|
||||
inf
|
||||
: SECTION EOL
|
||||
{ section_add($1); }
|
||||
| WORD EQUALS assign EOL
|
||||
{ assign_add($1); }
|
||||
| WORD COMMA regkey EOL
|
||||
{ regkey_add($1); }
|
||||
| WORD EOL
|
||||
{ define_add($1); }
|
||||
| EOL
|
||||
;
|
||||
|
||||
assign
|
||||
: WORD
|
||||
{ push_word($1); }
|
||||
| STRING
|
||||
{ push_word($1); }
|
||||
| WORD COMMA assign
|
||||
{ push_word($1); }
|
||||
| STRING COMMA assign
|
||||
{ push_word($1); }
|
||||
| COMMA assign
|
||||
{ push_word(NULL); }
|
||||
| COMMA
|
||||
{ push_word(NULL); }
|
||||
|
|
||||
;
|
||||
|
||||
regkey
|
||||
: WORD
|
||||
{ push_word($1); }
|
||||
| STRING
|
||||
{ push_word($1); }
|
||||
| WORD COMMA regkey
|
||||
{ push_word($1); }
|
||||
| STRING COMMA regkey
|
||||
{ push_word($1); }
|
||||
| COMMA regkey
|
||||
{ push_word(NULL); }
|
||||
| COMMA
|
||||
{ push_word(NULL); }
|
||||
;
|
||||
%%
|
91
usr.sbin/ndiscvt/inf-token.l
Normal file
91
usr.sbin/ndiscvt/inf-token.l
Normal file
@ -0,0 +1,91 @@
|
||||
%{
|
||||
/*
|
||||
* $Id: inf-token.l,v 1.2 2003/11/30 20:41:06 winter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <regex.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "y.tab.h"
|
||||
|
||||
int lineno = 1;
|
||||
#define YY_NO_UNPUT
|
||||
|
||||
int yylex(void);
|
||||
void yyerror(const char *);
|
||||
|
||||
static void
|
||||
update_lineno(const char *cp)
|
||||
{
|
||||
while (*cp)
|
||||
if (*cp++ == '\n')
|
||||
lineno++;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
[ \t]+ ;
|
||||
\n { lineno++; return EOL; }
|
||||
\r ;
|
||||
;.*$ ;
|
||||
= { return EQUALS; }
|
||||
, { return COMMA; }
|
||||
\"(\\\"|[^"])*\" {
|
||||
int len = strlen(yytext) - 2;
|
||||
int blen = len + 1;
|
||||
char *walker;
|
||||
int i;
|
||||
update_lineno(yytext);
|
||||
yylval.str = (char *)malloc(blen);
|
||||
if (yylval.str == NULL)
|
||||
goto out;
|
||||
walker = yylval.str;
|
||||
for (i = 1; i <= len; i++) {
|
||||
if (yytext[i] == '\\') {
|
||||
switch (yytext[i + 1]) {
|
||||
case '\n':
|
||||
i += 2;
|
||||
while(isspace(yytext[i]))
|
||||
i++;
|
||||
break;
|
||||
case '\"':
|
||||
i++;
|
||||
break;
|
||||
case '(':
|
||||
i++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
*walker++ = yytext[i];
|
||||
}
|
||||
*walker++ = '\0';
|
||||
out:;
|
||||
return STRING;
|
||||
}
|
||||
\[[a-zA-Z0-9%&\{\}\-\.\/_\\\*\ ]+\] {
|
||||
int len = strlen(yytext);
|
||||
yytext[len-1] = '\0';
|
||||
yylval.str = strdup(yytext+1);
|
||||
return SECTION;
|
||||
}
|
||||
[a-zA-Z0-9%&\{\}\-\.\/_\\\*]+ {
|
||||
yylval.str = strdup(yytext);
|
||||
return WORD;
|
||||
}
|
||||
%%
|
||||
|
||||
void
|
||||
yyerror(const char *s)
|
||||
{
|
||||
errx(1, "line %d: %s%s %s.", lineno, yytext, yytext?":":"", s);
|
||||
}
|
484
usr.sbin/ndiscvt/inf.c
Normal file
484
usr.sbin/ndiscvt/inf.c
Normal file
@ -0,0 +1,484 @@
|
||||
/*
|
||||
* $Id: inf.c,v 1.3 2003/11/30 21:58:16 winter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include "inf.h"
|
||||
|
||||
extern FILE *yyin;
|
||||
int yyparse (void);
|
||||
|
||||
const char *words[W_MAX]; /* More than we'll need. */
|
||||
int idx;
|
||||
|
||||
static struct section_head sh;
|
||||
static struct reg_head rh;
|
||||
static struct assign_head ah;
|
||||
|
||||
static char *sstrdup (const char *);
|
||||
static struct assign
|
||||
*find_assign (const char *, const char *);
|
||||
static struct section
|
||||
*find_section (const char *);
|
||||
static void dump_deviceids (void);
|
||||
static void dump_pci_id (const char *);
|
||||
static void dump_regvals (void);
|
||||
static void dump_paramreg (const struct section *, const struct reg *);
|
||||
|
||||
static FILE *ofp;
|
||||
|
||||
int
|
||||
inf_parse (FILE *fp, FILE *outfp)
|
||||
{
|
||||
TAILQ_INIT(&sh);
|
||||
TAILQ_INIT(&rh);
|
||||
TAILQ_INIT(&ah);
|
||||
|
||||
ofp = outfp;
|
||||
yyin = fp;
|
||||
yyparse();
|
||||
|
||||
dump_deviceids();
|
||||
dump_regvals();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
section_add (const char *s)
|
||||
{
|
||||
struct section *sec;
|
||||
|
||||
sec = malloc(sizeof(struct section));
|
||||
bzero(sec, sizeof(struct section));
|
||||
sec->name = s;
|
||||
TAILQ_INSERT_TAIL(&sh, sec, link);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct assign *
|
||||
find_assign (const char *s, const char *k)
|
||||
{
|
||||
struct assign *assign;
|
||||
char newkey[256];
|
||||
|
||||
/* Deal with string section lookups. */
|
||||
|
||||
if (k != NULL && k[0] == '%') {
|
||||
bzero(newkey, sizeof(newkey));
|
||||
strncpy(newkey, k + 1, strlen(k) - 2);
|
||||
k = newkey;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(assign, &ah, link) {
|
||||
if (strcasecmp(assign->section->name, s) == 0) {
|
||||
if (k == NULL)
|
||||
return(assign);
|
||||
else
|
||||
if (strcasecmp(assign->key, k) == 0)
|
||||
return(assign);
|
||||
}
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static const char *
|
||||
stringcvt(const char *s)
|
||||
{
|
||||
struct assign *manf;
|
||||
|
||||
manf = find_assign("strings", s);
|
||||
if (manf == NULL)
|
||||
return(s);
|
||||
return(manf->vals[0]);
|
||||
}
|
||||
|
||||
struct section *
|
||||
find_section (const char *s)
|
||||
{
|
||||
struct section *section;
|
||||
|
||||
TAILQ_FOREACH(section, &sh, link) {
|
||||
if (strcasecmp(section->name, s) == 0)
|
||||
return(section);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_pci_id(const char *s)
|
||||
{
|
||||
char *p;
|
||||
char vidstr[7], didstr[7];
|
||||
|
||||
p = strcasestr(s, "VEN_");
|
||||
if (p == NULL)
|
||||
return;
|
||||
p += 4;
|
||||
strcpy(vidstr, "0x");
|
||||
strncat(vidstr, p, 4);
|
||||
p = strcasestr(s, "DEV_");
|
||||
if (p == NULL)
|
||||
return;
|
||||
p += 4;
|
||||
strcpy(didstr, "0x");
|
||||
strncat(didstr, p, 4);
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
fprintf(ofp, "\t\\\n\t{ %s, %s,", vidstr, didstr);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_deviceids()
|
||||
{
|
||||
struct assign *manf, *dev;
|
||||
struct section *sec;
|
||||
struct assign *assign;
|
||||
|
||||
/* Find manufacturer name */
|
||||
manf = find_assign("Manufacturer", NULL);
|
||||
|
||||
/* Find manufacturer section */
|
||||
sec = find_section(manf->vals[0]);
|
||||
|
||||
/* Emit start of device table */
|
||||
fprintf (ofp, "#define NDIS_DEV_TABLE");
|
||||
|
||||
/*
|
||||
* Now run through all the device names listed
|
||||
* in the manufacturer section and dump out the
|
||||
* device descriptions and vendor/device IDs.
|
||||
*/
|
||||
|
||||
TAILQ_FOREACH(assign, &ah, link) {
|
||||
if (assign->section == sec) {
|
||||
dev = find_assign("strings", assign->key);
|
||||
/* Emit device IDs. */
|
||||
if (strcasestr(assign->vals[1], "PCI") != NULL)
|
||||
dump_pci_id(assign->vals[1]);
|
||||
#ifdef notdef
|
||||
else if (strcasestr(assign->vals[1], "PCMCIA") != NULL)
|
||||
dump_pcmcia_id(assign->vals[1]);
|
||||
#endif
|
||||
/* Emit device description */
|
||||
fprintf (ofp, "\t\\\n\t\"%s\"", dev->vals[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Emit end of table */
|
||||
|
||||
fprintf(ofp, " },\n\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_addreg(const char *s)
|
||||
{
|
||||
struct section *sec;
|
||||
struct reg *reg;
|
||||
|
||||
/* Find the addreg section */
|
||||
sec = find_section(s);
|
||||
|
||||
/* Dump all the keys defined in it. */
|
||||
TAILQ_FOREACH(reg, &rh, link) {
|
||||
/*
|
||||
* Keys with an empty subkey are very easy to parse,
|
||||
* so just deal with them here. If a parameter key
|
||||
* of the same name also exists, prefer that one and
|
||||
* skip this one.
|
||||
*/
|
||||
if (reg->section == sec) {
|
||||
if (reg->subkey == NULL) {
|
||||
fprintf(ofp, "\n\t{ \"%s\",", reg->key);
|
||||
fprintf(ofp,"\n\t\"%s \",", reg->key);
|
||||
fprintf(ofp, "\n\t{ \"%s\" } },",
|
||||
reg->value == NULL ? "" :
|
||||
reg->value);
|
||||
} else if (strcasestr(reg->subkey,
|
||||
"Ndi\\params") != NULL &&
|
||||
strcasecmp(reg->key, "ParamDesc") == 0)
|
||||
dump_paramreg(sec, reg);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_enumreg(const struct section *s, const struct reg *r)
|
||||
{
|
||||
struct reg *reg;
|
||||
char enumkey[256];
|
||||
|
||||
sprintf(enumkey, "%s\\enum", r->subkey);
|
||||
TAILQ_FOREACH(reg, &rh, link) {
|
||||
if (reg->section != s)
|
||||
continue;
|
||||
if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey))
|
||||
continue;
|
||||
fprintf(ofp, " [%s=%s]", reg->key, stringcvt(reg->value));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_editreg(const struct section *s, const struct reg *r)
|
||||
{
|
||||
struct reg *reg;
|
||||
|
||||
TAILQ_FOREACH(reg, &rh, link) {
|
||||
if (reg->section != s)
|
||||
continue;
|
||||
if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
|
||||
continue;
|
||||
if (strcasecmp(reg->key, "LimitText") == 0)
|
||||
fprintf(ofp, " [maxchars=%s]", reg->value);
|
||||
if (strcasecmp(reg->key, "Optional") == 0 &&
|
||||
strcmp(reg->value, "1") == 0)
|
||||
fprintf(ofp, " [optional]");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Use this for int too */
|
||||
static void
|
||||
dump_dwordreg(const struct section *s, const struct reg *r)
|
||||
{
|
||||
struct reg *reg;
|
||||
|
||||
TAILQ_FOREACH(reg, &rh, link) {
|
||||
if (reg->section != s)
|
||||
continue;
|
||||
if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
|
||||
continue;
|
||||
if (strcasecmp(reg->key, "min") == 0)
|
||||
fprintf(ofp, " [min=%s]", reg->value);
|
||||
if (strcasecmp(reg->key, "max") == 0)
|
||||
fprintf(ofp, " [max=%s]", reg->value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_defaultinfo(const struct section *s, const struct reg *r)
|
||||
{
|
||||
struct reg *reg;
|
||||
TAILQ_FOREACH(reg, &rh, link) {
|
||||
if (reg->section != s)
|
||||
continue;
|
||||
if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
|
||||
continue;
|
||||
if (strcasecmp(reg->key, "Default"))
|
||||
continue;
|
||||
fprintf(ofp, "\n\t{ \"%s\" } },", reg->value == NULL ? "" :
|
||||
reg->value);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_paramdesc(const struct section *s, const struct reg *r)
|
||||
{
|
||||
struct reg *reg;
|
||||
TAILQ_FOREACH(reg, &rh, link) {
|
||||
if (reg->section != s)
|
||||
continue;
|
||||
if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
|
||||
continue;
|
||||
if (strcasecmp(reg->key, "ParamDesc"))
|
||||
continue;
|
||||
fprintf(ofp, "\n\t\"%s", stringcvt(r->value));
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_typeinfo(const struct section *s, const struct reg *r)
|
||||
{
|
||||
struct reg *reg;
|
||||
TAILQ_FOREACH(reg, &rh, link) {
|
||||
if (reg->section != s)
|
||||
continue;
|
||||
if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
|
||||
continue;
|
||||
if (strcasecmp(reg->key, "type"))
|
||||
continue;
|
||||
if (strcasecmp(reg->value, "dword") == 0 ||
|
||||
strcasecmp(reg->value, "int") == 0)
|
||||
dump_dwordreg(s, r);
|
||||
if (strcasecmp(reg->value, "enum") == 0)
|
||||
dump_enumreg(s, r);
|
||||
if (strcasecmp(reg->value, "edit") == 0)
|
||||
dump_editreg(s, r);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_paramreg(const struct section *s, const struct reg *r)
|
||||
{
|
||||
const char *keyname;
|
||||
|
||||
keyname = r->subkey + strlen("Ndi\\params\\");
|
||||
fprintf(ofp, "\n\t{ \"%s\",", keyname);
|
||||
dump_paramdesc(s, r);
|
||||
dump_typeinfo(s, r);
|
||||
fprintf(ofp, "\",");
|
||||
dump_defaultinfo(s, r);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_regvals(void)
|
||||
{
|
||||
struct assign *manf, *dev, *dev_dup;
|
||||
struct section *sec;
|
||||
struct assign *assign;
|
||||
struct assign_head tmp_ah;
|
||||
char sname[256];
|
||||
int i;
|
||||
|
||||
TAILQ_INIT(&tmp_ah);
|
||||
|
||||
/* Find manufacturer name */
|
||||
manf = find_assign("Manufacturer", NULL);
|
||||
|
||||
/* Find manufacturer section */
|
||||
sec = find_section(manf->vals[0]);
|
||||
|
||||
/* Emit start of block */
|
||||
fprintf (ofp, "ndis_cfg ndis_regvals[] = {");
|
||||
|
||||
TAILQ_FOREACH(assign, &ah, link) {
|
||||
/* Avoid repeating the same section. */
|
||||
i = 0;
|
||||
TAILQ_FOREACH(dev_dup, &tmp_ah, link)
|
||||
if (strcmp(dev_dup->vals[0], assign->vals[0]) == 0) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
if (i)
|
||||
continue;
|
||||
dev_dup = malloc(sizeof(struct assign));
|
||||
bcopy((char *)assign, (char *)dev_dup,
|
||||
sizeof(struct assign));
|
||||
TAILQ_INSERT_TAIL(&tmp_ah, dev_dup, link);
|
||||
if (assign->section == sec) {
|
||||
/* Ignore Windows 95-era data. */
|
||||
sprintf(sname, "%s.NT", assign->vals[0]);
|
||||
/* Find all the AddReg sections. */
|
||||
dev = find_assign(sname, "AddReg");
|
||||
for (i = 0; i < W_MAX; i++) {
|
||||
if (dev->vals[i] != NULL)
|
||||
dump_addreg(dev->vals[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(ofp, "\n\t{ NULL, NULL, { 0 } }\n};\n\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
assign_add (const char *a)
|
||||
{
|
||||
struct assign *assign;
|
||||
int i;
|
||||
|
||||
assign = malloc(sizeof(struct assign));
|
||||
bzero(assign, sizeof(struct assign));
|
||||
assign->section = TAILQ_LAST(&sh, section_head);
|
||||
assign->key = sstrdup(a);
|
||||
for (i = 0; i < idx; i++)
|
||||
assign->vals[(idx - 1) - i] = sstrdup(words[i]);
|
||||
TAILQ_INSERT_TAIL(&ah, assign, link);
|
||||
|
||||
clear_words();
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
define_add (const char *d __unused)
|
||||
{
|
||||
#ifdef notdef
|
||||
fprintf(stderr, "define \"%s\"\n", d);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static char *
|
||||
sstrdup(const char *str)
|
||||
{
|
||||
if (str != NULL && strlen(str))
|
||||
return (strdup(str));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
satoi (const char *nptr)
|
||||
{
|
||||
if (nptr != NULL && strlen(nptr))
|
||||
return (atoi(nptr));
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
regkey_add (const char *r)
|
||||
{
|
||||
struct reg *reg;
|
||||
|
||||
reg = malloc(sizeof(struct reg));
|
||||
bzero(reg, sizeof(struct reg));
|
||||
reg->section = TAILQ_LAST(&sh, section_head);
|
||||
reg->root = sstrdup(r);
|
||||
reg->subkey = sstrdup(words[3]);
|
||||
reg->key = sstrdup(words[2]);
|
||||
reg->flags = satoi(words[1]);
|
||||
reg->value = sstrdup(words[0]);
|
||||
TAILQ_INSERT_TAIL(&rh, reg, link);
|
||||
|
||||
free(__DECONST(char *, r));
|
||||
clear_words();
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
push_word (const char *w)
|
||||
{
|
||||
if (w && strlen(w))
|
||||
words[idx++] = w;
|
||||
else
|
||||
words[idx++] = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
clear_words (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < idx; i++) {
|
||||
if (words[i]) {
|
||||
free(__DECONST(char *, words[i]));
|
||||
}
|
||||
}
|
||||
idx = 0;
|
||||
bzero(words, sizeof(words));
|
||||
return;
|
||||
}
|
61
usr.sbin/ndiscvt/inf.h
Normal file
61
usr.sbin/ndiscvt/inf.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* $Id: inf.h,v 1.3 2003/11/30 21:58:16 winter Exp $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#define W_MAX 16
|
||||
|
||||
struct section {
|
||||
const char * name;
|
||||
|
||||
TAILQ_ENTRY(section) link;
|
||||
};
|
||||
TAILQ_HEAD(section_head, section);
|
||||
|
||||
struct assign {
|
||||
struct section *section;
|
||||
|
||||
const char * key;
|
||||
const char * vals[W_MAX];
|
||||
|
||||
TAILQ_ENTRY(assign) link;
|
||||
};
|
||||
TAILQ_HEAD(assign_head, assign);
|
||||
|
||||
struct reg {
|
||||
struct section *section;
|
||||
|
||||
const char * root;
|
||||
const char * subkey;
|
||||
const char * key;
|
||||
u_int flags;
|
||||
const char * value;
|
||||
|
||||
TAILQ_ENTRY(reg) link;
|
||||
};
|
||||
TAILQ_HEAD(reg_head, reg);
|
||||
|
||||
#define FLG_ADDREG_TYPE_SZ 0x00000000
|
||||
#define FLG_ADDREG_BINVALUETYPE 0x00000001
|
||||
#define FLG_ADDREG_NOCLOBBER 0x00000002
|
||||
#define FLG_ADDREG_DELVAL 0x00000004
|
||||
#define FLG_ADDREG_APPEND 0x00000008
|
||||
#define FLG_ADDREG_KEYONLY 0x00000010
|
||||
#define FLG_ADDREG_OVERWRITEONLY 0x00000020
|
||||
#define FLG_ADDREG_64BITKEY 0x00001000
|
||||
#define FLG_ADDREG_KEYONLY_COMMON 0x00002000
|
||||
#define FLG_ADDREG_32BITKEY 0x00004000
|
||||
#define FLG_ADDREG_TYPE_MULTI_SZ 0x00010000
|
||||
#define FLG_ADDREG_TYPE_EXPAND_SZ 0x00020000
|
||||
#define FLG_ADDREG_TYPE_DWORD 0x00010001
|
||||
#define FLG_ADDREG_TYPE_NONE 0x00020001
|
||||
|
||||
extern void section_add (const char *);
|
||||
extern void assign_add (const char *);
|
||||
extern void define_add (const char *);
|
||||
extern void regkey_add (const char *);
|
||||
|
||||
extern void push_word (const char *);
|
||||
extern void clear_words (void);
|
||||
extern int inf_parse (FILE *, FILE *);
|
132
usr.sbin/ndiscvt/ndiscvt.8
Normal file
132
usr.sbin/ndiscvt/ndiscvt.8
Normal file
@ -0,0 +1,132 @@
|
||||
.\" Copyright (c) 2003
|
||||
.\" Bill Paul <wpaul@windriver.com> All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by Bill Paul.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
.\" THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 10, 2003
|
||||
.Dt NDISCVT 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ndiscvt
|
||||
.Nd Convert Windows(r) NDIS drivers for use with FreeBSD
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl i Ar <inffile>
|
||||
.Fl s Ar <sysfile>
|
||||
.Op Fl o Ar <outfile>
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility transforms a Windows(r) NDIS driver into a data file which
|
||||
is used to build an
|
||||
.Xr ndis 4
|
||||
compatibility driver module. Windows(r) drivers consist of two main
|
||||
parts: a .SYS file, which contains the actual driver executable code,
|
||||
and a .INF file, which provides the Windows(r) installer with device
|
||||
identifier information and a list of driver-specific registry keys.
|
||||
The
|
||||
.Nm
|
||||
utility can convert these files into a header file that is compiled
|
||||
intoe
|
||||
.Pa if_ndis.c
|
||||
to create an object code module that can be linked into
|
||||
the
|
||||
.Fx
|
||||
kernel.
|
||||
.Pp
|
||||
The .INF file is typically required since only it contains device
|
||||
identification data such as PCI vendor and device IDs or PCMCIA
|
||||
indentifier strings. The .INF file may be optionally omitted however,
|
||||
in which case the
|
||||
.Nm
|
||||
utility will only perform the conversion of the .SYS file. This is
|
||||
useful for debugging purposes only.
|
||||
.Pp
|
||||
.Sh OPTIONS
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Op Fl i Ar <inffile>
|
||||
Open and parse the specified .INF file when performing conversion.
|
||||
The
|
||||
.Nm
|
||||
utility will parse this file and emit a device identification
|
||||
structure and registry key configuration structures which will be
|
||||
used by the
|
||||
.Xr ndis 4
|
||||
driver and
|
||||
.Xr ndisapi 9
|
||||
kernel subsystem.
|
||||
If this is omitted,
|
||||
.Nm
|
||||
will emit a dummy configuration structure only.
|
||||
.It Fl s Ar <sysfile>
|
||||
Open and parse the specified .SYS file. This file must contain
|
||||
a Windows(r) driver image. The
|
||||
.Nm
|
||||
utility will perform some manipulation of the sections within the
|
||||
executable file to make runtime linking within the kernel a little
|
||||
easier and then convert the image into a data array.
|
||||
.It Op Fl o Ar <outfile>
|
||||
Specify the output file in which to place the resulting data. This
|
||||
can be any file pathname. If
|
||||
.Ar <outfile>
|
||||
is a single dash, the data will be written to the standard output.
|
||||
The
|
||||
.Pa if_ndis.c
|
||||
module expects to find the driver data in a file called
|
||||
.Pa ndis_driver_data.h ,
|
||||
so it is recommended that this name be used.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr ndis 4 ,
|
||||
.Xr ndisapi 9
|
||||
.Sh BUGS
|
||||
Some Windows(r) drivers support multiple devices which each may
|
||||
require sets of registry keys. The .INF file format allows all of
|
||||
these devices to be supported in a single file. The
|
||||
.Nm
|
||||
utility will emit keys for all of the devices that it are specified
|
||||
in a given file, even if this results in some duplicated entries.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Fx 5.3.
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
utility was written by
|
||||
.An Bill Paul Aq wpaul@windriver.com .
|
||||
The
|
||||
.Xr lex 1
|
||||
and
|
||||
.Xr yacc 1
|
||||
INF file parser was written by
|
||||
.An Mathew Dodd Aq mdodd@freebsd.org .
|
264
usr.sbin/ndiscvt/ndiscvt.c
Normal file
264
usr.sbin/ndiscvt/ndiscvt.c
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (c) 2003
|
||||
* Bill Paul <wpaul@windriver.com>. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Bill Paul.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
|
||||
#include <compat/ndis/pe_var.h>
|
||||
|
||||
#include "inf.h"
|
||||
|
||||
static int insert_padding(void **, int *);
|
||||
extern const char *__progname;
|
||||
|
||||
/*
|
||||
* Sections in object code files can be sparse. That is, the
|
||||
* section may occupy more space in memory that it does when
|
||||
* stored in a disk file. In Windows PE files, each section header
|
||||
* has a 'virtual size' and 'raw data size' field. The latter
|
||||
* specifies the amount of section data actually stored in the
|
||||
* disk file, and the former describes how much space the section
|
||||
* should actually occupy in memory. If the vsize is larger than
|
||||
* the rsize, we need to allocate some extra storage and fill
|
||||
* it with zeros. (Think BSS.)
|
||||
*
|
||||
* The typical method of loading an executable file involves
|
||||
* reading each segment into memory using the vaddr/vsize from
|
||||
* each section header. We try to make a small optimization however
|
||||
* and only pad/move segments when it's absolutely necessary, i.e.
|
||||
* if the vsize is larger than the rsize. This conserves a little
|
||||
* bit of memory, at the cost of having to fixup some of the values
|
||||
* in the section headers.
|
||||
*/
|
||||
|
||||
#define ROUND_UP(x, y) \
|
||||
(((x) + (y)) - ((x) % (y)))
|
||||
|
||||
#define SET_HDRS(x) \
|
||||
dos_hdr = (image_dos_header *)x; \
|
||||
nt_hdr = (image_nt_header *)(x + dos_hdr->idh_lfanew); \
|
||||
sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr + \
|
||||
sizeof(image_nt_header));
|
||||
|
||||
static
|
||||
int insert_padding(imgbase, imglen)
|
||||
void **imgbase;
|
||||
int *imglen;
|
||||
{
|
||||
image_section_header *sect_hdr;
|
||||
image_dos_header *dos_hdr;
|
||||
image_nt_header *nt_hdr;
|
||||
image_optional_header opt_hdr;
|
||||
int i = 0, sections, curlen = 0;
|
||||
int offaccum = 0, diff, oldraddr, oldrlen;
|
||||
uint8_t *newimg, *tmp;
|
||||
|
||||
newimg = malloc(*imglen);
|
||||
|
||||
if (newimg == NULL)
|
||||
return(ENOMEM);
|
||||
|
||||
bcopy(*imgbase, newimg, *imglen);
|
||||
curlen = *imglen;
|
||||
|
||||
if (pe_get_optional_header((vm_offset_t)newimg, &opt_hdr))
|
||||
return(0);
|
||||
|
||||
sections = pe_numsections((vm_offset_t)newimg);
|
||||
|
||||
SET_HDRS(newimg);
|
||||
|
||||
for (i = 0; i < sections; i++) {
|
||||
/*
|
||||
* If we have accumulated any padding offset,
|
||||
* add it to the raw data address of this segment.
|
||||
*/
|
||||
oldraddr = sect_hdr->ish_rawdataaddr;
|
||||
oldrlen = sect_hdr->ish_rawdatasize;
|
||||
if (offaccum)
|
||||
sect_hdr->ish_rawdataaddr += offaccum;
|
||||
if (sect_hdr->ish_misc.ish_vsize >
|
||||
sect_hdr->ish_rawdatasize) {
|
||||
diff = ROUND_UP(sect_hdr->ish_misc.ish_vsize -
|
||||
sect_hdr->ish_rawdatasize,
|
||||
opt_hdr.ioh_filealign);
|
||||
offaccum += ROUND_UP(diff -
|
||||
(sect_hdr->ish_misc.ish_vsize -
|
||||
sect_hdr->ish_rawdatasize),
|
||||
opt_hdr.ioh_filealign);
|
||||
sect_hdr->ish_rawdatasize =
|
||||
ROUND_UP(sect_hdr->ish_rawdatasize,
|
||||
opt_hdr.ioh_filealign);
|
||||
tmp = realloc(newimg, *imglen + offaccum);
|
||||
if (tmp == NULL) {
|
||||
free(newimg);
|
||||
return(ENOMEM);
|
||||
}
|
||||
newimg = tmp;
|
||||
SET_HDRS(newimg);
|
||||
sect_hdr += i;
|
||||
}
|
||||
bzero(newimg + sect_hdr->ish_rawdataaddr,
|
||||
ROUND_UP(sect_hdr->ish_misc.ish_vsize,
|
||||
opt_hdr.ioh_filealign));
|
||||
bcopy((uint8_t *)(*imgbase) + oldraddr,
|
||||
newimg + sect_hdr->ish_rawdataaddr, oldrlen);
|
||||
sect_hdr++;
|
||||
}
|
||||
|
||||
free(*imgbase);
|
||||
|
||||
*imgbase = newimg;
|
||||
*imglen += offaccum;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-i <inffile>] -s <sysfile> "
|
||||
"[-o outfile]\n", __progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
FILE *fp, *outfp;
|
||||
void *img;
|
||||
int n, fsize, cnt;
|
||||
unsigned char *ptr;
|
||||
int i;
|
||||
char *inffile = NULL, *sysfile = NULL, *outfile = NULL;
|
||||
int ch;
|
||||
|
||||
while((ch = getopt(argc, argv, "i:s:o")) != -1) {
|
||||
switch(ch) {
|
||||
case 'i':
|
||||
inffile = optarg;
|
||||
break;
|
||||
case 's':
|
||||
sysfile = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
outfile = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sysfile == NULL)
|
||||
usage();
|
||||
|
||||
/* Open the .SYS file and load it into memory */
|
||||
fp = fopen(sysfile, "r");
|
||||
if (fp == NULL)
|
||||
err(1, "opening .SYS file '%s' failed", sysfile);
|
||||
fseek (fp, 0L, SEEK_END);
|
||||
fsize = ftell (fp);
|
||||
rewind (fp);
|
||||
img = calloc(fsize, 1);
|
||||
n = fread (img, fsize, 1, fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
if (insert_padding(&img, &fsize)) {
|
||||
fprintf(stderr, "section relocation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (outfile == NULL || strcmp(outfile, "-") == 0)
|
||||
outfp = stdout;
|
||||
else {
|
||||
outfp = fopen(outfile, "w");
|
||||
if (outfp == NULL)
|
||||
err(1, "opening output file '%s' failed", outfile);
|
||||
}
|
||||
|
||||
fprintf(outfp, "\n/*\n");
|
||||
fprintf(outfp, " * Generated from %s and %s (%d bytes)\n",
|
||||
inffile, sysfile, fsize);
|
||||
fprintf(outfp, " */\n\n");
|
||||
|
||||
if (fp == NULL) {
|
||||
fprintf (outfp, "ndis_cfg ndis_regvals[] = {\n");
|
||||
fprintf (outfp, "\t{ NULL, NULL, ndis_parm_int, { 0 } }\n");
|
||||
|
||||
fprintf (outfp, "};\n\n");
|
||||
} else {
|
||||
fp = fopen(inffile, "r");
|
||||
if (fp == NULL)
|
||||
err(1, "opening .INF file '%s' failed", inffile);
|
||||
|
||||
|
||||
inf_parse(fp, outfp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
fprintf(outfp, "\n\nunsigned char drv_data[] = { \n");
|
||||
|
||||
ptr = img;
|
||||
cnt = 0;
|
||||
while(cnt < fsize) {
|
||||
for (i = 0; i < 12; i++) {
|
||||
cnt++;
|
||||
if (cnt == fsize) {
|
||||
fprintf(outfp, "0x%.2X\n", ptr[i]);
|
||||
goto done;
|
||||
} else
|
||||
fprintf(outfp, "0x%.2X, ", ptr[i]);
|
||||
}
|
||||
fprintf(outfp, "\n");
|
||||
ptr += 12;
|
||||
}
|
||||
|
||||
done:
|
||||
fprintf(outfp, "};\n");
|
||||
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
fclose(outfp);
|
||||
free(img);
|
||||
exit(0);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user