--- ./util/alias.h.old	Sun Jan  7 10:47:03 2001
+++ ./util/alias.h	Sun Jan  7 10:47:35 2001
@@ -226,6 +226,7 @@
 char *prune[] =
 {
 	"modules.dep",
+	"modules.parms",
 	"modules.generic_string",
 	"modules.pcimap",
 	"modules.isapnpmap",
--- ./util/config.c.old	Sun Jan  7 10:47:59 2001
+++ ./util/config.c	Sun Jan  7 10:47:51 2001
@@ -111,6 +111,7 @@
 
 /* The initialization order must match the gen_file_enum order in config.h */
 struct gen_files gen_file[] = {
+	{"parms", NULL, 0},
 	{"generic_string", NULL, 0},
 	{"pcimap", NULL, 0},
 	{"isapnpmap", NULL, 0},
--- ./include/config.h.old	Sun Jan  7 10:48:59 2001
+++ ./include/config.h	Sun Jan  7 10:49:07 2001
@@ -87,6 +87,7 @@
 extern const int gen_file_count;
 /* The enum order must match the gen_file initialization order in config.c */
 enum gen_file_enum {
+	GEN_PARMSFILE,
 	GEN_GENERIC_STRINGFILE,
 	GEN_PCIMAPFILE,
 	GEN_ISAPNPMAPFILE,
--- ./depmod/depmod.c.old	Sun Jan  7 13:02:42 2001
+++ ./depmod/depmod.c	Sun Jan  7 13:07:04 2001
@@ -167,6 +167,8 @@
 		SYMBOL **symtab;
 		int n_syms;
 	} defsym, undefs;
+	char **parms;	/* The first four chars determine the type */
+	int n_parms;
 	char **generic_string;
 	int n_generic_string;
 	struct pci_device_id *pci_device;
@@ -366,6 +368,194 @@
 	"\n\tyou probably need a new version of modutils to handle this kernel."
 	"\n\tCheck linux/Documentation/Changes.";
 
+
+static void append_parm(MODULE *mod, const char *type, const char *parm)
+{
+	char **latest;
+
+	mod->parms = xrealloc(mod->parms, ++(mod->n_parms)*sizeof(*(mod->parms)));
+	latest = mod->parms + mod->n_parms-1;
+	*latest = xmalloc(strlen(type) + 1 + strlen(parm) + 1);
+	strcpy(*latest, type);
+	strcat(*latest, " ");
+	strcat(*latest, parm);
+}
+
+static const char *get_modinfo_value(struct obj_file *f, const char *key)
+{
+	struct obj_section *sec;
+	char *p, *v, *n, *ep;
+	size_t klen = strlen(key);
+
+	if (strcmp(key, "filename") == 0) {
+		return(f->filename);
+	}
+
+	sec = obj_find_section(f, ".modinfo");
+	if (sec == NULL)
+		return NULL;
+
+	p = sec->contents;
+	ep = p + sec->header.sh_size;
+	while (p < ep) {
+		v = strchr(p, '=');
+		n = strchr(p, '\0');
+		if (v) {
+			if (v - p == klen && strncmp(p, key, klen) == 0)
+				return v + 1;
+		} else {
+			if (n - p == klen && strcmp(p, key) == 0)
+				return n;
+		}
+		p = n + 1;
+	}
+
+	return NULL;
+}
+
+/*
+ *	Save the module parameter.
+ *	Note: assumes same machine and arch for depmod and module.
+ */
+static void save_parameter(struct obj_file *f, MODULE *mod,
+			   char *key, char *value, const char *desc)
+{
+	struct obj_symbol *sym;
+	int min, max, size;
+	char *p = value;
+	char *res;
+	
+	sym = obj_find_symbol(f, key);
+	if (sym == NULL)
+		printf("warning: symbol for parameter %s not found\n", key);
+	size = strlen(key) + 1 + strlen(desc) + 64;
+	res = xmalloc(size);
+
+	if (isdigit(*p)) {
+		min = strtoul(p, &p, 10);
+		if (*p == '-')
+			max = strtoul(p + 1, &p, 10);
+		else
+			max = min;
+	} else
+		min = max = 1;
+
+	if (max < min)
+		error("warning: parameter %s has max < min!\n", key);
+
+	strcpy(res, key);
+	strcat(res, " ");
+
+	switch (*p) {
+	case 'c':
+		strcat(res, "char");
+		if (!isdigit(p[1]))
+			error("*** missing string size ***");
+		else while (isdigit(p[1]))
+			++p;	/* swallow c array size */
+		break;
+	case 'b':
+		strcat(res, "byte");
+		break;
+	case 'h':
+		strcat(res, "short");
+		break;
+	case 'i':
+		strcat(res, "int");
+		break;
+	case 'l':
+		strcat(res, "long");
+		break;
+	case 's':
+		strcat(res, "string");
+		break;
+	case '\0':
+		strcat(res, "none");
+		return;
+	default:
+		strcat(res, "unknown");
+		return;
+	}
+	switch (*++p) {
+	case 'p':
+		strcat(res, " persistent");
+		if (*(p-1) == 's')
+			strcat(res, " (invalid)");
+		break;
+	case '\0':
+		break;
+	default:
+		error(" unknown format modifier '%c'", *p);
+		break;
+	}
+
+	if (min > 1 || max > 1)
+		sprintf(res + strlen(res), " array (min = %d, max = %d)", min, max);
+
+	if (desc)
+		sprintf(res + strlen(res), ", description \"%s\"", desc);
+
+	append_parm(mod, "PARM", res);
+
+	free(res);
+}
+
+/*
+ *	Extract the module parameters and module descriptions.
+ *	Note: assumes same machine and arch for depmod and module.
+ */
+static void extract_parms(struct obj_file *f, MODULE *mod)
+{
+	struct obj_section *sec;
+	const char *cvalue;
+	char *p, *ep, *value, *n;
+	int namelen;
+	
+	sec = obj_find_section(f, ".modinfo");
+	if (sec == NULL)
+		return;
+
+	cvalue = get_modinfo_value(f, "author");
+	if (cvalue)
+		append_parm(mod, "AUTH", cvalue);
+
+	cvalue = get_modinfo_value(f, "description");
+	if (cvalue)
+		append_parm(mod, "DESC", cvalue);
+
+	p = sec->contents;
+	ep = p + sec->header.sh_size;
+	while (p < ep) {
+		value = strchr(p, '=');
+		n = strchr(p, '\0');
+		if (value) {
+			namelen = value - p;
+			if (namelen >= 5 && strncmp(p, "parm_", 5) == 0 &&
+			    !(namelen > 10 && strncmp(p, "parm_desc_", 10) == 0)) {
+				char *pname = xmalloc(namelen + 1);
+				char *desckey = xmalloc(namelen + 5 + 1);
+				
+				strncpy(pname, p + 5, namelen - 5);
+				pname[namelen - 5] = '\0';
+				
+				strcpy(desckey, "parm_desc_");  /* safe, xmalloc */
+				strncat(desckey, p + 5, namelen - 5);
+				desckey[namelen + 5] = '\0';
+				
+				save_parameter(f, mod, pname, value + 1, get_modinfo_value(f, desckey));
+				
+				free(pname);
+				free(desckey);
+			}
+		} else {
+			if (n - p >= 5 && strncmp(p, "parm_", 5) == 0) {
+				error("parameter %s found with no value", p);
+			}
+		}
+		p = n + 1;
+	}
+}
+
 /*
  *	Extract any generic string from the given symbol.
  *	Note: assumes same machine and arch for depmod and module.
@@ -743,6 +933,7 @@
 		error("depmod obj_relocate failed\n");
 		return(-1);
 	}
+	extract_parms(f, mod);
 	extract_generic_string(f, mod);
 	image = xmalloc(m_size);
 	obj_create_image(f, image);
@@ -937,6 +1128,7 @@
 static void prtdepend(char *base_dir, int nflag)
 {
 	FILE *dep = stdout;
+	FILE *parms = stdout;
 	FILE *generic_string = stdout;
 	FILE *pcimap = stdout;
 	FILE *isapnpmap = stdout;
@@ -949,6 +1141,7 @@
 
 	if (!nflag) {
 		dep = gen_file_open(gen_file+GEN_DEPFILE);
+		parms = gen_file_open(gen_file+GEN_PARMSFILE);
 		generic_string = gen_file_open(gen_file+GEN_GENERIC_STRINGFILE);
 		pcimap = gen_file_open(gen_file+GEN_PCIMAPFILE);
 		isapnpmap = gen_file_open(gen_file+GEN_ISAPNPMAPFILE);
@@ -1010,6 +1203,17 @@
 	}
 
 	ptmod = modules;
+	fprintf(parms, "# module             type text\n");
+	for (i = 0; i < n_modules; i++, ptmod++) {
+		int j;
+		char **pstr = ptmod->parms;
+		if (!ptmod->n_parms)
+			continue;
+		for (j = 0; j < ptmod->n_parms; j++, ++pstr)
+			fprintf(parms, "%-20s %s\n", shortname(ptmod->name), *pstr);
+	}
+
+	ptmod = modules;
 	fprintf(generic_string, "# module             id=string\n");
 	for (i = 0; i < n_modules; i++, ptmod++) {
 		int j;
@@ -1116,6 +1320,8 @@
 		}
 	}
 	
+	if (parms != stdout)
+		fclose(parms);
 	if (generic_string != stdout)
 		fclose(generic_string);
 	if (pcimap != stdout)
