Subject: A potential step towards modularisation
To: None <tech-kern@netbsd.org>
From: Quentin Garnier <cube@NetBSD.org>
List: tech-kern
Date: 02/07/2004 01:10:35
This is a multi-part message in MIME format.
--Multipart=_Sat__7_Feb_2004_01_10_35_+0100_WzxD4GVPFC9eC+eU
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Hi folks,
First, please don't disregard this post just because it is about modules.
By no mean I want to drop the current practice of having a monolithic
kernel. I would never compile with options LKM most of my systems. But
sometimes, modularity is useful.
The attached diff is only against config(8). Its aim is to provide ways
to compile modules out of the standard kernel compilation scheme.
Currently, the LKM that are part of the NetBSD distribution are built as
part of userland, whereas it should be part of kernel compilation. It is
even more true now that we have Jaromir's versioning framework for LKMs:
if you rebuild your kernel, you have to rebuild your modules. I value the
security belt enough, but it can be annoying.
What I propose here is a slight change of config(8) grammar to allow a
property of modularity accross the various kernel and configuration
components. To declare an attribute or a device as _potentially_ (i.e.,
if and only if the user's config file says to compile it as module), it
should be prefixed with 'modular'. Also, an attachment that creates an
attribute (with <attr>) can be made modular by using 'with module <attr>'
syntax.
Then, the user can make a device compiled as a module by prefixing the
instance line with 'module'.
Example for ex(4):
> conf/files <
modular device ex: arp, ether, ifnet, mii, mii_bitbang
file dev/ic/elinkxl.c ex
> dev/pci/files.pci <
attach ex at pci with module ex_pci
file dev/pci/if_ex_pci.c ex_pci
> dev/cardbus/files.cardbus <
attach ex at carbus with module ex_cardbus
file dev/cardbus/if_ex_cardbus.c ex_cardbus
The user will have several choices:
Case 1, good'old GENERIC_LAPTOP:
ex* at pci? device ? function ?
ex* at cardbus? cardslot ?
===> No module is created
Case 2:
module ex* at pci? device ? function ?
module ex* at cardbus? cardslot ?
===> 3 modules are created: ex.ko, ex_pci.ko and ex_cardbus.ko.
Case 3:
module ex* at pci? device ? function ?
ex* at cardbus? cardslot ?
===> only one module is created, since attribute ex_cardbus is static and
depends on attribute ex. The module name is ex_pci.ko.
Also, you can use 'modular define' to define modular attributes that are
not directly linked to a device, such as 'ac97', 'aurateconv'... Then
those can be built as modules if whatever needs them is a module.
It is also possible to include files for an attribute only if it is
compiled as module. This would be really useful since most of our devices
drivers don't provide detach() function, which are usually required for a
LKM to work properly (unless it is specifically made not-unloadable).
detach() functions have little use in a monolithic kernel and it is
perfectly understandable to leave them out. Thus a way is provided to
include ``modular'' files (using the 'modular' keyword as a flag at the
same level as need-count and need-flag).
config(8) then adds all the modules targets at the %MODULES token inside
the template Makefile. Makefile.kern.inc should define a few variable to
compile the modules, but it is not yet the most important point.
This patch certainly does not provide modularisation for NetBSD. It
merely makes it possible to do this a near future. Of course, our current
LKM implementation is not really adapted to modularisation: no
dependencies (mmm, unloading in the wrong order), no in-kernel linker that
would help with module classes and resource allocation, no way to easily
add a device driver for a bus and have it rescanned (e.g., PCI), etc. But
this config(8) patch neither prevents nor restricts implementation of
solutions for those issues.
I'm posting this now because I feel I've worked on it long enough to have
a clear idea of what it actually provides and what would be the needs for
modularisation, but there's still some work to make it complete: for
example, file-systems are treated as regular options, but get a different
syntax so config(8) can know that at least one is compiled and barf if
it's not the case. Since the patch does not provide a way to declare
modular options, it is not possible yet to compile module for
file-systems.
Comments? Flames?
--
Quentin Garnier - cube@NetBSD.org
The NetBSD Project - http://www.NetBSD.org/
--Multipart=_Sat__7_Feb_2004_01_10_35_+0100_WzxD4GVPFC9eC+eU
Content-Type: text/plain;
name="config.diff"
Content-Disposition: attachment;
filename="config.diff"
Content-Transfer-Encoding: 7bit
Index: Makefile
===================================================================
RCS file: /pub/NetBSD-CVS/src/usr.sbin/config/Makefile,v
retrieving revision 1.27
diff -u -r1.27 Makefile
--- Makefile 2003/05/18 07:57:38 1.27
+++ Makefile 2004/02/06 23:09:21
@@ -4,12 +4,13 @@
PROG= config
BINDIR= /usr/sbin
SRCS= files.c gram.y hash.c main.c mkdevsw.c mkheaders.c mkioconf.c \
- mkmakefile.c mkswap.c pack.c scan.l sem.c util.c
+ mkmakefile.c mkmodules.c mkswap.c pack.c scan.l sem.c util.c
YFLAGS=
CPPFLAGS+=-I${.CURDIR} -I.
CLEANFILES+=gram.h
CWARNFLAGS+=-Wno-format-y2k
+CFLAGS+=-g
MAN= config.8
Index: defs.h
===================================================================
RCS file: /pub/NetBSD-CVS/src/usr.sbin/config/defs.h,v
retrieving revision 1.13
diff -u -r1.13 defs.h
--- defs.h 2003/09/03 18:56:37 1.13
+++ defs.h 2004/02/06 23:09:21
@@ -151,8 +151,18 @@
struct nvlist *a_refs; /* parents */
struct nvlist *a_deps; /* we depend on these other attrs */
int a_expanding; /* to detect cycles in attr graph */
+ int a_modprops; /* modularity */
};
+#define MOD_STATIC 0x01 /* this element will be statically built */
+#define MOD_MODABLE 0x02 /* this element can be built as a module */
+#define MOD_MAXNAME 64
+
+#define CTX_STATIC 0
+#define CTX_MODULAR 1
+#define CTX_DEVCLASS 2
+#define CTX_PSEUDO 4
+
/*
* Parent specification. Multiple device instances may share a
* given parent spec. Parent specs are emitted only if there are
@@ -203,6 +213,7 @@
struct deva *d_ahead; /* first attachment, if any */
struct deva **d_app; /* used for tacking on attachments */
struct attr *d_classattr; /* device class attribute (if any) */
+ int d_modprops; /* module properties, see struct attr */
};
struct deva {
@@ -215,6 +226,7 @@
struct nvlist *d_attrs; /* attributes, if any */
struct devi *d_ihead; /* first instance, if any */
struct devi **d_ipp; /* used for tacking on more instances */
+ int d_modprops; /* module properties, see struct attr */
};
/*
@@ -242,6 +254,7 @@
const char **i_locs; /* locators (as given by pspec's iattr) */
int i_cfflags; /* flags from config line */
int i_lineno; /* line # in config, for later errors */
+ int i_modprops; /* modularity properties, see struct attr */
/* created during packing or ioconf.c generation */
short i_collapsed; /* set => this alias no longer needed */
@@ -285,6 +298,7 @@
#define FI_NEEDSCOUNT 0x02 /* needs-count */
#define FI_NEEDSFLAG 0x04 /* needs-flag */
#define FI_HIDDEN 0x08 /* obscured by other(s), base names overlap */
+#define FI_MODULAR 0x10 /* only compile if part of a module */
/*
* Objects and libraries. This allows precompiled object and library
@@ -304,6 +318,7 @@
/* flags */
#define OI_SEL 0x01 /* selected */
#define OI_NEEDSFLAG 0x02 /* needs-flag */
+#define OI_MODULAR 0x04 /* only compile if part of a module */
#define FX_ATOM 0 /* atom (in nv_name) */
#define FX_NOT 1 /* NOT expr (subexpression in nv_next) */
@@ -333,6 +348,17 @@
};
/*
+ * Module informations.
+ */
+struct module {
+ const char *m_name;
+ int m_count;
+ struct nvlist *m_filelist;
+ struct nvlist *m_objlist;
+ struct nvlist *m_attrlist;
+};
+
+/*
* Hash tables look up name=value pairs. The pointer value of the name
* is assumed to be constant forever; this can be arranged by interning
* the name. (This is fairly convenient since our lexer does this for
@@ -363,6 +389,7 @@
struct hashtab *devatab; /* devbase attachment lookup */
struct hashtab *devitab; /* device instance lookup */
struct hashtab *selecttab; /* selects things that are "optional foo" */
+struct hashtab *modulestab; /* modular attributes and associated module structs */
struct hashtab *needcnttab; /* retains names marked "needs-count" */
struct hashtab *opttab; /* table of configured options */
struct hashtab *fsopttab; /* table of configured file systems */
@@ -424,12 +451,13 @@
const char *intern(const char *);
typedef int (*ht_callback)(const char *, void *, void *);
int ht_enumerate(struct hashtab *, ht_callback, void *);
+u_int ht_count(struct hashtab *);
/* main.c */
void addoption(const char *, const char *);
void addfsoption(const char *);
void addmkoption(const char *, const char *);
-void deffilesystem(const char *, struct nvlist *);
+void deffilesystem(const char *, struct nvlist *, int);
void defoption(const char *, struct nvlist *, struct nvlist *);
void defflag(const char *, struct nvlist *, struct nvlist *);
void defparam(const char *, struct nvlist *, struct nvlist *);
@@ -467,6 +495,9 @@
/* mkswap.c */
int mkswap(void);
+/* mkmodules.c */
+int mkmodules(void);
+
/* pack.c */
void pack(void);
@@ -497,6 +528,7 @@
struct nvlist *newnv(const char *, const char *, void *, int, struct nvlist *);
void nvfree(struct nvlist *);
void nvfreel(struct nvlist *);
+struct nvlist *nvcat(struct nvlist *, struct nvlist *);
/* liby */
void yyerror(const char *);
Index: files.c
===================================================================
RCS file: /pub/NetBSD-CVS/src/usr.sbin/config/files.c,v
retrieving revision 1.22
diff -u -r1.22 files.c
--- files.c 2003/08/07 11:25:15 1.22
+++ files.c 2004/02/06 23:09:21
@@ -61,9 +61,14 @@
static struct files **unchecked;
static int checkaux(const char *, void *);
+static int addmoduleitem(void *, int, struct nvlist *);
+#define AMI_OBJECT 1
+#define AMI_FILE 2
+static int buildmodule(const char *, void *, void *);
static int fixcount(const char *, void *);
static int fixfsel(const char *, void *);
static int fixsel(const char *, void *);
+static int fixmodules(const char *, void *);
static int expr_eval(struct nvlist *,
int (*)(const char *, void *), void *);
static void expr_free(struct nvlist *);
@@ -249,17 +254,34 @@
continue;
/* Optional: see if it is to be included. */
+ /* Note: a modular file can't have optx == NULL */
if (fi->fi_optx != NULL) {
- flathead = NULL;
- flatp = &flathead;
- sel = expr_eval(fi->fi_optx,
- fi->fi_flags & FI_NEEDSCOUNT ? fixcount :
- fi->fi_flags & FI_NEEDSFLAG ? fixfsel :
- fixsel,
- &flatp);
- fi->fi_optf = flathead;
- if (!sel)
- continue;
+ if (!(fi->fi_flags & FI_MODULAR)) {
+ flathead = NULL;
+ flatp = &flathead;
+ sel = expr_eval(fi->fi_optx,
+ fi->fi_flags & FI_NEEDSCOUNT ? fixcount :
+ fi->fi_flags & FI_NEEDSFLAG ? fixfsel :
+ fixsel,
+ &flatp);
+ fi->fi_optf = flathead;
+ }
+
+ /*
+ * It won't be included in the monolithic kernel,
+ * though it might be compiled as part of a module
+ */
+ if ((fi->fi_flags & FI_MODULAR) || !sel) {
+ flathead = NULL;
+ sel = expr_eval(fi->fi_optx, fixmodules, &flathead);
+ if (sel) {
+ /* Ok, we will produce a module out of this */
+ err = addmoduleitem(fi, AMI_FILE, flathead);
+ fi->fi_flags |= FI_MODULAR;
+ } else
+ /* Not selected */
+ continue;
+ }
}
/* We like this file. Make sure it generates a unique .o. */
@@ -274,7 +296,7 @@
if (ht_replace(basetab, fi->fi_base, fi) != 1)
panic("fixfiles ht_replace(%s)",
fi->fi_base);
- ofi->fi_flags &= ~FI_SEL;
+ ofi->fi_flags &= ~(FI_SEL | FI_MODULAR);
ofi->fi_flags |= FI_HIDDEN;
} else {
xerror(fi->fi_srcfile, fi->fi_srcline,
@@ -286,11 +308,104 @@
err = 1;
}
}
- fi->fi_flags |= FI_SEL;
+ /* FI_MODULAR and FI_SEL are exclusive */
+ if (!(fi->fi_flags & FI_MODULAR))
+ fi->fi_flags |= FI_SEL;
}
return (err);
}
+/*
+ * Manage modules and the associated list of files
+ */
+static int
+addmoduleitem(void *file, int type, struct nvlist *attr)
+{
+ struct nvlist *nv = NULL;
+ struct module *mod;
+ struct hashtab *mods = ht_new();
+ const char *name;
+
+ /*
+ * Get list of existing modules this file should
+ * be part of.
+ */
+ for (;attr != NULL; attr = attr->nv_next) {
+ if ((mod = ht_lookup(modulestab, attr->nv_name)) == NULL) {
+ mod = emalloc(sizeof(struct module));
+ mod->m_name = attr->nv_name; /* Already interned */
+ mod->m_filelist = NULL;
+ mod->m_objlist = NULL;
+ mod->m_attrlist = newnv(attr->nv_name, NULL, NULL, 0, NULL);
+ mod->m_count = 1;
+ ht_insert(modulestab, mod->m_name, mod);
+ } else if (ht_lookup(mods, mod->m_name))
+ continue;
+
+ ht_insert(mods, mod->m_name, mod);
+ nv = newnv(attr->nv_name, NULL, NULL, 0, nv);
+ }
+
+ /*
+ * mods now contains a list of the modules that file should be part of.
+ * Since a file should only be inculded once in the kernel, we have to
+ * merge that list into one modules.
+ * No need to do anything if mods only contain one name.
+ */
+ if (ht_count(mods) > 1) {
+ void *old;
+ int i =
+ ht_enumerate(mods, buildmodule, (void *)mod);
+ printf("Merged %d modules into one, m_count = %d.\n", i, mod->m_count);
+ for (;nv != NULL; nv = nv->nv_next) {
+ old = ht_lookup(modulestab, nv->nv_name);
+ if (old != mod)
+ free(old);
+ ht_replace(modulestab, nv->nv_name, mod);
+ }
+ }
+
+ /*
+ * Add either a file or an object to the module's list
+ */
+ if (type == AMI_OBJECT) {
+ mod->m_objlist = newnv(NULL, NULL, file, 0, mod->m_objlist);
+ name = ((struct objects *)file)->oi_path;
+ } else {
+ mod->m_filelist = newnv(NULL, NULL, file, 0, mod->m_filelist);
+ name = ((struct files *)file)->fi_path;
+ }
+
+ printf("%s in %s.\n", name, mod->m_name);
+
+ return (0);
+}
+
+/*
+ * Construct a new module from a list enumerated through
+ * modname.
+ * arg is a pointer to an existing module struct which is shared by
+ * the attributes listed in modulestab.
+ */
+static int
+buildmodule(const char *modname, void *val, void *arg)
+{
+ struct module *mod = val, *newmod = arg;
+ char newname[128] = { 0 };
+
+ if (newmod != mod) {
+ newmod->m_filelist = nvcat(newmod->m_filelist, mod->m_filelist);
+ newmod->m_objlist = nvcat(newmod->m_objlist, mod->m_objlist);
+ newmod->m_attrlist = nvcat(newmod->m_attrlist, mod->m_attrlist);
+ strlcpy(newname, newmod->m_name, 128);
+ strlcat(newname, mod->m_name, 128);
+ newmod->m_name = intern(newname);
+ newmod->m_count += mod->m_count;
+ }
+
+ return (1);
+}
+
/*
* We have finished reading everything. Tack the objects down: calculate
* selection.
@@ -306,18 +421,34 @@
TAILQ_FOREACH(oi, &allobjects, oi_next) {
/* Optional: see if it is to be included. */
if (oi->oi_optx != NULL) {
- flathead = NULL;
- flatp = &flathead;
- sel = expr_eval(oi->oi_optx,
- oi->oi_flags & OI_NEEDSFLAG ? fixfsel :
- fixsel,
- &flatp);
- oi->oi_optf = flathead;
- if (!sel)
- continue;
+ if (!(oi->oi_flags & OI_MODULAR)) {
+ flathead = NULL;
+ flatp = &flathead;
+ sel = expr_eval(oi->oi_optx,
+ oi->oi_flags & OI_NEEDSFLAG ? fixfsel :
+ fixsel,
+ &flatp);
+ oi->oi_optf = flathead;
+ }
+ /*
+ * It won't be included in the monolithic kernel,
+ * though it might be compiled as part of a module
+ */
+ if ((oi->oi_flags & OI_MODULAR) || !sel) {
+ flathead = NULL;
+ sel = expr_eval(oi->oi_optx, fixmodules, &flathead);
+ if (sel) {
+ /* Ok, we will produce a module out of this */
+ err += addmoduleitem(oi, AMI_OBJECT, flathead);
+ oi->oi_flags |= OI_MODULAR;
+ } else
+ /* Not selected */
+ continue;
+ }
}
- oi->oi_flags |= OI_SEL;
+ if (!(oi->oi_flags & OI_MODULAR))
+ oi->oi_flags |= OI_SEL;
}
return (err);
}
@@ -427,6 +558,7 @@
struct nvlist ***p = context;
struct devbase *dev;
struct nvlist *nv;
+ int *pmod = ht_lookup(selecttab, name);
dev = ht_lookup(devbasetab, name);
if (dev == NULL) /* cannot occur here; we checked earlier */
@@ -435,7 +567,12 @@
**p = nv;
*p = &nv->nv_next;
(void)ht_insert(needcnttab, name, nv);
- return (dev->d_umax != 0);
+#ifdef notaproblem
+ if (pmod && *pmod == MOD_MODABLE)
+ printf("%s will be made a module. needs-count, though :/\n",
+ name);
+#endif
+ return (dev->d_umax != 0 && (pmod == NULL || *pmod == MOD_STATIC));
}
/*
@@ -447,9 +584,15 @@
{
struct nvlist ***p = context;
struct nvlist *nv;
- int sel;
+ int sel, *pmod;
- sel = ht_lookup(selecttab, name) != NULL;
+ pmod = ht_lookup(selecttab, name);
+#ifdef notaproblem
+ if (pmod && *pmod == MOD_MODABLE)
+ printf("%s will be made a module. needs-flag, though :/\n",
+ name);
+#endif
+ sel = (pmod && *pmod == MOD_STATIC);
nv = newnv(name, NULL, NULL, sel, NULL);
**p = nv;
*p = &nv->nv_next;
@@ -462,8 +605,37 @@
static int
fixsel(const char *name, void *context)
{
+ int *pmod = ht_lookup(selecttab, name);
+
+ if (pmod == NULL)
+ return (0);
+
+#ifdef notaproblem
+ if (*pmod == MOD_MODABLE)
+ printf("%s will be made a module. Don't include here.\n",
+ name);
+#endif
+ return (*pmod == MOD_STATIC);
+}
+
+/*
+ * Check if the file can be part of a module, and add the attribute to
+ * the flat list of dependencies.
+ */
+static int
+fixmodules(const char *name, void *context)
+{
+ int *pmod = ht_lookup(selecttab, name);
+ struct nvlist *modl, **p = (struct nvlist **)context;
+
+ if (pmod == NULL || *pmod != MOD_MODABLE)
+ return (0);
+
+ /* Add to the list of modules the file will be included in */
+ modl = newnv(name, NULL, NULL, 0, *p);
+ *p = modl;
- return (ht_lookup(selecttab, name) != NULL);
+ return (1);
}
/*
Index: gram.y
===================================================================
RCS file: /pub/NetBSD-CVS/src/usr.sbin/config/gram.y,v
retrieving revision 1.44
diff -u -r1.44 gram.y
--- gram.y 2003/08/07 11:25:15 1.44
+++ gram.y 2004/02/06 23:09:22
@@ -97,10 +97,11 @@
int val;
}
-%token AND AT ATTACH BUILD CINCLUDE COMPILE_WITH CONFIG DEFFS DEFINE DEFOPT
+%token AND AT ATTACH BUILD CINCLUDE COMPILE_WITH CONFIG DEFFS DEFINE DEFOPT
%token DEFPARAM DEFFLAG DEFPSEUDO DEVICE DEVCLASS DUMPS ENDFILE XFILE XOBJECT
%token FILE_SYSTEM FLAGS IDENT INCLUDE XMACHINE MAJOR MAKEOPTIONS
-%token MAXUSERS MAXPARTITIONS MINOR ON OPTIONS PACKAGE PREFIX PSEUDO_DEVICE
+%token MAXUSERS MAXPARTITIONS MINOR MODULAR MODULE
+%token ON OPTIONS PACKAGE PREFIX PSEUDO_DEVICE
%token ROOT SOURCE TYPE WITH NEEDS_COUNT NEEDS_FLAG NO BLOCK CHAR DEVICE_MAJOR
%token <val> NUMBER
%token <str> PATHNAME QSTRING WORD EMPTY
@@ -225,14 +226,16 @@
fflag:
NEEDS_COUNT { $$ = FI_NEEDSCOUNT; } |
- NEEDS_FLAG { $$ = FI_NEEDSFLAG; };
+ NEEDS_FLAG { $$ = FI_NEEDSFLAG; } |
+ MODULAR { $$ = FI_MODULAR; };
oflgs:
oflgs oflag { $$ = $1 | $2; } |
/* empty */ { $$ = 0; };
oflag:
- NEEDS_FLAG { $$ = OI_NEEDSFLAG; };
+ NEEDS_FLAG { $$ = OI_NEEDSFLAG; } |
+ MODULAR { $$ = OI_MODULAR; };
rule:
COMPILE_WITH stringvalue { $$ = $2; } |
@@ -269,10 +272,13 @@
include |
package |
prefix |
- DEVCLASS WORD { (void)defattr($2, NULL, NULL, 1); } |
- DEFFS fsoptfile_opt deffses { deffilesystem($2, $3); } |
+ DEVCLASS WORD { (void)defattr($2, NULL, NULL, CTX_DEVCLASS); } |
+ DEFFS fsoptfile_opt deffses { deffilesystem($2, $3, CTX_STATIC); } |
+ MODULAR DEFFS fsoptfile_opt deffses { deffilesystem($3, $4, CTX_MODULAR); } |
DEFINE WORD interface_opt attrs_opt
- { (void)defattr($2, $3, $4, 0); } |
+ { (void)defattr($2, $3, $4, CTX_STATIC); } |
+ MODULAR DEFINE WORD interface_opt attrs_opt
+ { (void)defattr($3, $4, $5, CTX_MODULAR); } |
DEFOPT optfile_opt defopts defoptdeps
{ defoption($2, $3, $4); } |
DEFFLAG optfile_opt defopts defoptdeps
@@ -280,13 +286,17 @@
DEFPARAM optfile_opt defopts defoptdeps
{ defparam($2, $3, $4); } |
DEVICE devbase interface_opt attrs_opt
- { defdev($2, $3, $4, 0); } |
+ { defdev($2, $3, $4, CTX_STATIC); } |
+ MODULAR DEVICE devbase interface_opt attrs_opt
+ { defdev($3, $4, $5, CTX_MODULAR); } |
ATTACH devbase AT atlist devattach_opt attrs_opt
{ defdevattach($5, $2, $4, $6); } |
MAXPARTITIONS NUMBER { maxpartitions = $2; } |
MAXUSERS NUMBER NUMBER NUMBER { setdefmaxusers($2, $3, $4); } |
DEFPSEUDO devbase interface_opt attrs_opt
- { defdev($2, $3, $4, 1); } |
+ { defdev($2, $3, $4, CTX_PSEUDO); } |
+ MODULAR DEFPSEUDO devbase interface_opt attrs_opt
+ { defdev($3, $4, $5, CTX_MODULAR | CTX_PSEUDO); } |
MAJOR '{' majorlist '}';
atlist:
@@ -326,7 +336,8 @@
WORD { $$ = getdevbase($1); };
devattach_opt:
- WITH WORD { $$ = getdevattach($2); } |
+ WITH MODULE WORD { $$ = getdevattach($3, CTX_MODULAR); } |
+ WITH WORD { $$ = getdevattach($2, CTX_STATIC); } |
/* empty */ { $$ = NULL; };
interface_opt:
@@ -440,11 +451,14 @@
CONFIG conf root_spec sysparam_list
{ addconf(&conf); } |
NO PSEUDO_DEVICE WORD { delpseudo($3); } |
- PSEUDO_DEVICE WORD npseudo { addpseudo($2, $3); } |
+ PSEUDO_DEVICE WORD npseudo { addpseudo($2, $3, CTX_STATIC); } |
+ MODULE PSEUDO_DEVICE WORD npseudo { addpseudo($3, $4, CTX_MODULAR); } |
NO device_instance AT attachment
{ deldev($2, $4); } |
device_instance AT attachment locators flags_opt
- { adddev($1, $3, $4, $5); };
+ { adddev($1, $3, $4, $5, CTX_STATIC); } |
+ MODULE device_instance AT attachment locators flags_opt
+ { adddev($2, $4, $5, $6, CTX_MODULAR); };
fs_list:
fs_list ',' fsoption |
Index: hash.c
===================================================================
RCS file: /pub/NetBSD-CVS/src/usr.sbin/config/hash.c,v
retrieving revision 1.11
diff -u -r1.11 hash.c
--- hash.c 2003/08/07 11:25:15 1.11
+++ hash.c 2004/02/06 23:09:22
@@ -294,3 +294,9 @@
}
return rval;
}
+
+u_int
+ht_count(struct hashtab *ht)
+{
+ return (ht->ht_used);
+}
Index: main.c
===================================================================
RCS file: /pub/NetBSD-CVS/src/usr.sbin/config/main.c,v
retrieving revision 1.86
diff -u -r1.86 main.c
--- main.c 2003/09/14 12:43:04 1.86
+++ main.c 2004/02/06 23:09:22
@@ -76,6 +76,8 @@
int vflag; /* verbose output */
int Pflag; /* pack locators */
+int mod_static = MOD_STATIC; /* for options */
+
int yyparse(void);
#ifndef MAKE_BOOTSTRAP
@@ -243,6 +245,7 @@
selecttab = ht_new();
needcnttab = ht_new();
opttab = ht_new();
+ modulestab = ht_new();
mkopttab = ht_new();
fsopttab = ht_new();
deffstab = ht_new();
@@ -384,7 +387,7 @@
/*
* Ready to go. Build all the various files.
*/
- if (mksymlinks() || mkmakefile() || mkheaders() || mkswap() ||
+ if (mksymlinks() || mkmodules() || mkmakefile() || mkheaders() || mkswap() ||
mkioconf() || (do_devsw ? mkdevsw() : 0) || mkident())
stop();
(void)printf("Build directory is %s\n", builddir);
@@ -518,9 +521,12 @@
* specified, a preprocessor #define for that file system will be placed
* in that file. In this case, only one file system may be specified.
* Otherwise, no preprocessor #defines will be generated.
+ *
+ * XXX `module' ignored for now, until either another *tab var is created
+ * or a real struct is used for file-systems.
*/
void
-deffilesystem(const char *fname, struct nvlist *fses)
+deffilesystem(const char *fname, struct nvlist *fses, int module)
{
struct nvlist *nv;
@@ -792,7 +798,7 @@
*p++ = isupper(c) ? tolower(c) : c;
*p = 0;
n = intern(low);
- (void)ht_insert(selecttab, n, (void *)n);
+ (void)ht_insert(selecttab, n, &mod_static);
}
void
@@ -844,7 +850,8 @@
panic("addfsoption: already in table");
/* Add to select table. */
- (void)ht_insert(selecttab, n, (void *)n);
+ /* XXX modular file-systems */
+ (void)ht_insert(selecttab, n, &mod_static);
}
void
Index: mkmakefile.c
===================================================================
RCS file: /pub/NetBSD-CVS/src/usr.sbin/config/mkmakefile.c,v
retrieving revision 1.59
diff -u -r1.59 mkmakefile.c
--- mkmakefile.c 2003/08/07 11:25:16 1.59
+++ mkmakefile.c 2004/02/06 23:09:22
@@ -60,12 +60,20 @@
static int emitdefs(FILE *);
static int emitfiles(FILE *, int, int);
+static int printfileobj(FILE *, int *, int *, char *, int);
+static int printfile(FILE *, int *, int *, void *, int);
+
static int emitobjs(FILE *);
static int emitcfiles(FILE *);
static int emitsfiles(FILE *);
+
+static int printrule(FILE *, struct files *, const char *);
+
static int emitrules(FILE *);
static int emitload(FILE *);
static int emitincludes(FILE *);
+static int emitmodules(FILE *);
+static int emitmodule(const char *, void *, void *);
int
mkmakefile(void)
@@ -122,6 +130,8 @@
fn = emitload;
else if (strcmp(line, "%INCLUDES\n") == 0)
fn = emitincludes;
+ else if (strcmp(line, "%MODULES\n") == 0)
+ fn = emitmodules;
else {
xerror(ifname, lineno,
"unknown %% construct ignored: %s", line);
@@ -246,11 +256,76 @@
}
static int
+printfileobj(FILE *fp, int *lpos, int *sp, char *name, int suffix)
+{
+ int len;
+ len = strlen(name) + 2;
+ if (*lpos + len > 72) {
+ if (fputs(" \\\n", fp) < 0)
+ return (1);
+ *sp = '\t';
+ *lpos = 7;
+ }
+ if (fprintf(fp, "%c%s.%c", *sp, name, suffix) < 0)
+ return (1);
+ *lpos += len + 1;
+ *sp = ' ';
+ return (0);
+}
+
+#define TYPE_OBJECT 0
+#define TYPE_FILE 1
+static int
+printfile(FILE *fp, int *lpos, int *sp, void *arg, int type)
+{
+ int len;
+ const char *prefix, *path;
+
+ if (type == TYPE_OBJECT) {
+ prefix = ((struct objects *)arg)->oi_prefix;
+ path = ((struct objects *)arg)->oi_path;
+ } else {
+ prefix = ((struct files *)arg)->fi_prefix;
+ path = ((struct files *)arg)->fi_path;
+ }
+
+ len = strlen(path);
+ if (*path != '/') {
+ len += 3; /* "$S/" */
+ if (prefix != NULL)
+ len += strlen(prefix) + 1;
+ }
+ if (*lpos + len > 72) {
+ if (fputs(" \\\n", fp) < 0)
+ return (1);
+ *sp = '\t';
+ *lpos = 7;
+ }
+ if (*path == '/') {
+ if (fprintf(fp, "%c%s", *sp, path) < 0)
+ return (1);
+ } else {
+ if (prefix != NULL) {
+ if (fprintf(fp, "%c%s%s/%s", *sp,
+ prefix_prologue(prefix),
+ prefix, path) < 0)
+ return (1);
+ } else {
+ if (fprintf(fp, "%c$S/%s", *sp, path) < 0)
+ return (1);
+ }
+ }
+ *lpos += len + 1;
+ *sp = ' ';
+ return (0);
+}
+
+static int
emitobjs(FILE *fp)
{
struct files *fi;
struct objects *oi;
- int lpos, len, sp;
+ int lpos, sp;
if (fputs("OBJS=", fp) < 0)
return (1);
@@ -259,49 +334,14 @@
TAILQ_FOREACH(fi, &allfiles, fi_next) {
if ((fi->fi_flags & FI_SEL) == 0)
continue;
- len = strlen(fi->fi_base) + 2;
- if (lpos + len > 72) {
- if (fputs(" \\\n", fp) < 0)
- return (1);
- sp = '\t';
- lpos = 7;
- }
- if (fprintf(fp, "%c%s.o", sp, fi->fi_base) < 0)
+ if (printfileobj(fp, &lpos, &sp, (char *)fi->fi_base, 'o') != 0)
return (1);
- lpos += len + 1;
- sp = ' ';
}
TAILQ_FOREACH(oi, &allobjects, oi_next) {
if ((oi->oi_flags & OI_SEL) == 0)
continue;
- len = strlen(oi->oi_path);
- if (*oi->oi_path != '/') {
- len += 3; /* "$S/" */
- if (oi->oi_prefix != NULL)
- len += strlen(oi->oi_prefix) + 1;
- }
- if (lpos + len > 72) {
- if (fputs(" \\\n", fp) < 0)
- return (1);
- sp = '\t';
- lpos = 7;
- }
- if (*oi->oi_path == '/') {
- if (fprintf(fp, "%c%s", sp, oi->oi_path) < 0)
- return (1);
- } else {
- if (oi->oi_prefix != NULL) {
- if (fprintf(fp, "%c%s%s/%s", sp,
- prefix_prologue(oi->oi_prefix),
- oi->oi_prefix, oi->oi_path) < 0)
- return (1);
- } else {
- if (fprintf(fp, "%c$S/%s", sp, oi->oi_path) < 0)
- return (1);
- }
- }
- lpos += len + 1;
- sp = ' ';
+ if (printfile(fp, &lpos, &sp, oi, TYPE_OBJECT) != 0)
+ return (1);
}
if (putc('\n', fp) < 0)
return (1);
@@ -344,33 +384,8 @@
if (! ((fpath[len - 1] == suffix) ||
(upper_suffix && fpath[len - 1] == toupper(suffix))))
continue;
- if (*fpath != '/') {
- len += 3; /* "$S/" */
- if (fi->fi_prefix != NULL)
- len += strlen(fi->fi_prefix) + 1;
- }
- if (lpos + len > 72) {
- if (fputs(" \\\n", fp) < 0)
- return (1);
- sp = '\t';
- lpos = 7;
- }
- if (*fi->fi_path == '/') {
- if (fprintf(fp, "%c%s", sp, fi->fi_path) < 0)
- return (1);
- } else {
- if (fi->fi_prefix != NULL) {
- if (fprintf(fp, "%c%s%s/%s", sp,
- prefix_prologue(fi->fi_prefix),
- fi->fi_prefix, fi->fi_path) < 0)
- return (1);
- } else {
- if (fprintf(fp, "%c$S/%s", sp, fi->fi_path) < 0)
- return (1);
- }
- }
- lpos += len + 1;
- sp = ' ';
+ if (printfile(fp, &lpos, &sp, fi, TYPE_FILE) != 0)
+ return (1);
}
/*
* The allfiles list does not include the configuration-specific
@@ -379,19 +394,10 @@
*/
if (suffix == 'c') {
TAILQ_FOREACH(cf, &allcf, cf_next) {
- (void)snprintf(swapname, sizeof(swapname), "swap%s.c",
+ (void)snprintf(swapname, sizeof(swapname), "swap%s",
cf->cf_name);
- len = strlen(swapname);
- if (lpos + len > 72) {
- if (fputs(" \\\n", fp) < 0)
- return (1);
- sp = '\t';
- lpos = 7;
- }
- if (fprintf(fp, "%c%s", sp, swapname) < 0)
+ if (printfileobj(fp, &lpos, &sp, swapname, suffix) != 0)
return (1);
- lpos += len + 1;
- sp = ' ';
}
}
if (putc('\n', fp) < 0)
@@ -399,6 +405,43 @@
return (0);
}
+static int
+printrule(FILE *fp, struct files *fi, const char *defrule)
+{
+ const char *cp, *fpath;
+ int ch;
+ char buf[200];
+
+ if ((fpath = srcpath(fi)) == NULL)
+ return (1);
+ if (*fpath == '/') {
+ if (fprintf(fp, "%s.o: %s\n", fi->fi_base, fpath) < 0)
+ return (1);
+ } else {
+ if (fi->fi_prefix != NULL) {
+ if (fprintf(fp, "%s.o: %s%s/%s\n", fi->fi_base,
+ prefix_prologue(fi->fi_prefix),
+ fi->fi_prefix, fpath) < 0)
+ return (1);
+ } else {
+ if (fprintf(fp, "%s.o: $S/%s\n", fi->fi_base,
+ fpath) < 0)
+ return (1);
+ }
+ }
+ if ((cp = fi->fi_mkrule) == NULL) {
+ cp = defrule;
+ ch = fpath[strlen(fpath) - 1];
+ if (islower(ch))
+ ch = toupper(ch);
+ (void)snprintf(buf, sizeof(buf), "${%s_%c}", cp, ch);
+ cp = buf;
+ }
+ if (fprintf(fp, "\t%s\n\n", cp) < 0)
+ return (1);
+ return (0);
+}
+
/*
* Emit the make-rules.
*/
@@ -406,40 +449,12 @@
emitrules(FILE *fp)
{
struct files *fi;
- const char *cp, *fpath;
- int ch;
- char buf[200];
TAILQ_FOREACH(fi, &allfiles, fi_next) {
if ((fi->fi_flags & FI_SEL) == 0)
continue;
- if ((fpath = srcpath(fi)) == NULL)
+ if (printrule(fp, fi, "NORMAL") != 0)
return (1);
- if (*fpath == '/') {
- if (fprintf(fp, "%s.o: %s\n", fi->fi_base, fpath) < 0)
- return (1);
- } else {
- if (fi->fi_prefix != NULL) {
- if (fprintf(fp, "%s.o: %s%s/%s\n", fi->fi_base,
- prefix_prologue(fi->fi_prefix),
- fi->fi_prefix, fpath) < 0)
- return (1);
- } else {
- if (fprintf(fp, "%s.o: $S/%s\n", fi->fi_base,
- fpath) < 0)
- return (1);
- }
- }
- if ((cp = fi->fi_mkrule) == NULL) {
- cp = "NORMAL";
- ch = fpath[strlen(fpath) - 1];
- if (islower(ch))
- ch = toupper(ch);
- (void)snprintf(buf, sizeof(buf), "${%s_%c}", cp, ch);
- cp = buf;
- }
- if (fprintf(fp, "\t%s\n\n", cp) < 0)
- return (1);
}
return (0);
}
@@ -509,5 +524,63 @@
return (1);
}
+ return (0);
+}
+
+/*
+ * Emit modules and objects needed to build them
+ */
+static int
+emitmodules(FILE *fp)
+{
+ return (ht_enumerate(modulestab, emitmodule, (void *)fp));
+}
+
+static int
+emitmodule(const char *attr, void *val, void *arg)
+{
+ FILE *fp = arg;
+ struct module *mod = val;
+ struct files *fi;
+ struct nvlist *nv;
+ int lpos, sp;
+
+ /* Pass modules that are already emitted */
+ if (mod->m_name == NULL)
+ return (0);
+
+ /* Rule for the module */
+ if (fprintf(fp, "modules:\t%s.ko\n%s.ko:", mod->m_name, mod->m_name) < 0)
+ return (1);
+
+ lpos = strlen(mod->m_name) + 4;
+ sp = '\t';
+ for (nv = mod->m_objlist; nv != NULL; nv = nv->nv_next)
+ if (printfile(fp, &lpos, &sp, nv->nv_ptr, TYPE_OBJECT) != 0)
+ return (1);
+
+ for (nv = mod->m_filelist; nv != NULL; nv = nv->nv_next) {
+ fi = nv->nv_ptr;
+ if (printfileobj(fp, &lpos, &sp, (char *)fi->fi_base, 'o') != 0)
+ return (1);
+ }
+ if (mod->m_count > 1) {
+ char modentry[MOD_MAXNAME+10]; /* _lkmentry is appended */
+
+ strlcpy(modentry, mod->m_name, MOD_MAXNAME+10);
+ strlcat(modentry, "_lkmentry", MOD_MAXNAME+10);
+ if (printfileobj(fp, &lpos, &sp, modentry, 'o') != 0)
+ return (1);
+ }
+
+ if (fprintf(fp, "\n\t${BUILD_MODULE}\n\n") < 0)
+ return (1);
+
+ /* Rules for the files */
+ for (nv = mod->m_filelist; nv != NULL; nv = nv->nv_next)
+ if (printrule(fp, nv->nv_ptr, "NORMAL_MODULE") != 0)
+ return (1);
+
+ mod->m_name = NULL;
return (0);
}
Index: scan.l
===================================================================
RCS file: /pub/NetBSD-CVS/src/usr.sbin/config/scan.l,v
retrieving revision 1.40
diff -u -r1.40 scan.l
--- scan.l 2003/09/08 17:50:12 1.40
+++ scan.l 2004/02/06 23:09:23
@@ -110,6 +110,8 @@
maxpartitions return MAXPARTITIONS;
maxusers return MAXUSERS;
minor return MINOR;
+modular return MODULAR;
+module return MODULE;
needs-count return NEEDS_COUNT;
needs-flag return NEEDS_FLAG;
no return NO;
Index: sem.c
===================================================================
RCS file: /pub/NetBSD-CVS/src/usr.sbin/config/sem.c,v
retrieving revision 1.40
diff -u -r1.40 sem.c
--- sem.c 2003/08/07 11:25:17 1.40
+++ sem.c 2004/02/06 23:09:23
@@ -70,12 +70,12 @@
static int resolve(struct nvlist **, const char *, const char *,
struct nvlist *, int);
static struct pspec *getpspec(struct attr *, struct devbase *, int);
-static struct devi *newdevi(const char *, int, struct devbase *d);
-static struct devi *getdevi(const char *);
+static struct devi *newdevi(const char *, int, struct devbase *d, int);
+static struct devi *getdevi(const char *, int);
static const char *concat(const char *, int);
static char *extend(char *, const char *);
static int split(const char *, size_t, char *, size_t, int *);
-static void selectbase(struct devbase *, struct deva *);
+static void selectbase(struct devbase *, struct deva *, int);
static int onlist(struct nvlist *, void *);
static const char **fixloc(const char *, struct attr *, struct nvlist *);
static const char *makedevstr(int, int);
@@ -185,16 +185,16 @@
*/
int
defattr(const char *name, struct nvlist *locs, struct nvlist *deps,
- int devclass)
+ int context)
{
struct attr *a, *dep;
struct nvlist *nv;
int len;
- if (locs != NULL && devclass)
+ if (locs != NULL && (context == CTX_DEVCLASS))
panic("defattr(%s): locators and devclass", name);
- if (deps != NULL && devclass)
+ if (deps != NULL && (context == CTX_DEVCLASS))
panic("defattr(%s): dependencies and devclass", name);
/*
@@ -211,6 +211,10 @@
}
a = emalloc(sizeof *a);
+ /*
+ * Check if attribute alreday exists
+ * insert into attrtab
+ */
if (ht_insert(attrtab, name, a)) {
free(a);
error("attribute `%s' already defined", name);
@@ -219,6 +223,7 @@
}
a->a_name = name;
+ a->a_modprops = MOD_STATIC;
if (locs != NULL) {
a->a_iattr = 1;
a->a_locs = locs->nv_next;
@@ -227,7 +232,7 @@
a->a_iattr = 0;
a->a_locs = NULL;
}
- if (devclass) {
+ if (context == CTX_DEVCLASS) {
size_t l = strlen(name) + 4;
char *classenum = alloca(l), *cp;
int errored = 0;
@@ -244,8 +249,13 @@
*cp = toupper(*cp);
}
a->a_devclass = intern(classenum);
- } else
+ } else {
a->a_devclass = NULL;
+
+ if (context == CTX_MODULAR) /* XXX module, devclasses can't be modules */
+ a->a_modprops = MOD_MODABLE;
+ }
+
len = 0;
for (nv = a->a_locs; nv != NULL; nv = nv->nv_next)
len++;
@@ -313,7 +323,7 @@
*/
void
defdev(struct devbase *dev, struct nvlist *loclist, struct nvlist *attrs,
- int ispseudo)
+ int flags)
{
struct nvlist *nv;
struct attr *a;
@@ -345,7 +355,8 @@
}
/* Committed! Set up fields. */
- dev->d_ispseudo = ispseudo;
+ dev->d_ispseudo = flags & CTX_PSEUDO;
+ dev->d_modprops = (flags & CTX_MODULAR) ? MOD_MODABLE : MOD_STATIC;
dev->d_attrs = attrs;
dev->d_classattr = NULL; /* for now */
@@ -433,7 +444,7 @@
if (dev == &errdev)
goto bad;
if (deva == NULL)
- deva = getdevattach(dev->d_name);
+ deva = getdevattach(dev->d_name, (dev->d_modprops & MOD_MODABLE));
if (deva == &errdeva)
goto bad;
if (!dev->d_isdef) {
@@ -501,6 +512,8 @@
/* attach to parent */
*dev->d_app = deva;
dev->d_app = &deva->d_bsame;
+ if (deva->d_modprops == MOD_STATIC)
+ dev->d_modprops = MOD_STATIC;
return;
bad:
nvfreel(atlist);
@@ -512,7 +525,7 @@
* name, i.e., does not contain digits or special characters.
*/
struct deva *
-getdevattach(const char *name)
+getdevattach(const char *name, int module)
{
u_char *p;
struct deva *deva;
@@ -540,10 +553,15 @@
deva->d_attrs = NULL;
deva->d_ihead = NULL;
deva->d_ipp = &deva->d_ihead;
+ deva->d_modprops = (module & CTX_MODULAR) ? MOD_MODABLE : MOD_STATIC;
TAILQ_INSERT_TAIL(&alldevas, deva, d_next);
if (ht_insert(devatab, name, deva))
panic("getdeva(%s)", name);
- }
+ } else
+ /* if one attachment requires it static, all should be */
+ if (!(module & CTX_MODULAR))
+ deva->d_modprops = MOD_STATIC;
+
return (deva);
}
@@ -555,10 +573,11 @@
{
struct attr *a;
- if ((a = ht_lookup(attrtab, name)) == NULL) {
+ if ((a = ht_lookup(attrtab, name))== NULL) {
error("undefined attribute `%s'", name);
a = &errattr;
}
+
return (a);
}
@@ -578,17 +597,17 @@
}
a->a_expanding = 1;
+
+ /* First invoke the callback for ourself. */
+ if (callback != NULL)
+ (*callback)(a);
- /* First expand all of this attribute's dependencies. */
+ /* ...and now expand all of this attribute's dependencies. */
for (nv = a->a_deps; nv != NULL; nv = nv->nv_next) {
dep = nv->nv_ptr;
expandattr(dep, callback);
}
- /* ...and now invoke the callback for ourself. */
- if (callback != NULL)
- (*callback)(a);
-
a->a_expanding = 0;
}
@@ -846,7 +865,7 @@
}
static struct devi *
-newdevi(const char *name, int unit, struct devbase *d)
+newdevi(const char *name, int unit, struct devbase *d, int module)
{
struct devi *i;
@@ -863,6 +882,7 @@
i->i_locs = NULL;
i->i_cfflags = 0;
i->i_lineno = currentline();
+ i->i_modprops = (module & CTX_MODULAR) ? MOD_MODABLE : MOD_STATIC;
if (unit >= d->d_umax)
d->d_umax = unit + 1;
return (i);
@@ -873,7 +893,7 @@
* another device instead) plus unit number.
*/
void
-adddev(const char *name, const char *at, struct nvlist *loclist, int flags)
+adddev(const char *name, const char *at, struct nvlist *loclist, int flags, int module)
{
struct devi *i; /* the new instance */
struct pspec *p; /* and its pspec */
@@ -892,7 +912,7 @@
if (at == NULL) {
/* "at root" */
p = NULL;
- if ((i = getdevi(name)) == NULL)
+ if ((i = getdevi(name, module)) == NULL)
goto bad;
/*
* Must warn about i_unit > 0 later, after taking care of
@@ -917,7 +937,7 @@
/* (void)getdevi(name); -- ??? */
goto bad;
}
- if ((i = getdevi(name)) == NULL)
+ if ((i = getdevi(name, module)) == NULL)
goto bad;
ib = i->i_base;
@@ -1058,7 +1078,7 @@
}
void
-addpseudo(const char *name, int number)
+addpseudo(const char *name, int number, int module)
{
struct devbase *d;
struct devi *i;
@@ -1076,7 +1096,7 @@
error("`%s' already defined", name);
return;
}
- i = newdevi(name, number - 1, d); /* foo 16 => "foo0..foo15" */
+ i = newdevi(name, number - 1, d, module); /* foo 16 => "foo0..foo15" */
if (ht_insert(devitab, name, i))
panic("addpseudo(%s)", name);
TAILQ_INSERT_TAIL(&allpseudo, i, i_next);
@@ -1149,10 +1169,10 @@
struct devi *i;
TAILQ_FOREACH(i, &alldevi, i_next)
- selectbase(i->i_base, i->i_atdeva);
+ selectbase(i->i_base, i->i_atdeva, i->i_modprops);
TAILQ_FOREACH(i, &allpseudo, i_next)
- selectbase(i->i_base, NULL);
+ selectbase(i->i_base, NULL, i->i_modprops);
}
/*
@@ -1187,7 +1207,7 @@
* Define a new instance of a specific device.
*/
static struct devi *
-getdevi(const char *name)
+getdevi(const char *name, int module)
{
struct devi *i, *firsti;
struct devbase *d;
@@ -1208,7 +1228,7 @@
return (NULL);
}
firsti = ht_lookup(devitab, name);
- i = newdevi(name, unit, d);
+ i = newdevi(name, unit, d, module);
if (firsti == NULL) {
if (ht_insert(devitab, name, i))
panic("getdevi(%s)", name);
@@ -1291,8 +1311,26 @@
void
selectattr(struct attr *a)
{
+ struct nvlist *nv;
+ struct attr *dep;
+ /*
+ * XXX Here is a good place to fix modularity
+ * properties.
+ *
+ * If given attribute is static, make static all of its
+ * dependencies.
+ *
+ * Note the change in expandattr that makes the callback be
+ * invoked before the recursion. We NEED it to be so here.
+ */
+
+ if (a->a_modprops == MOD_STATIC)
+ for (nv = a->a_deps; nv != NULL; nv = nv->nv_next) {
+ dep = nv->nv_ptr;
+ dep->a_modprops = MOD_STATIC;
+ }
- (void)ht_insert(selecttab, a->a_name, (char *)a->a_name);
+ (void)ht_insert(selecttab, a->a_name, &a->a_modprops);
}
/*
@@ -1300,20 +1338,35 @@
* attributes for "optional foo".
*/
static void
-selectbase(struct devbase *d, struct deva *da)
+selectbase(struct devbase *d, struct deva *da, int module)
{
struct attr *a;
struct nvlist *nv;
+
+ /* A static instance of a device makes the device itself static */
+ if (module == MOD_STATIC) {
+ d->d_modprops = MOD_STATIC;
+ if (da != NULL)
+ da->d_modprops = MOD_STATIC;
+ }
- (void)ht_insert(selecttab, d->d_name, (char *)d->d_name);
+ /* XXX expand attrs found on line '{device|moddev} foo: attrs' */
+ (void)ht_insert(selecttab, d->d_name, &d->d_modprops);
for (nv = d->d_attrs; nv != NULL; nv = nv->nv_next) {
a = nv->nv_ptr;
+ /* XXX If we're static, mark attribute as such */
+ if (d->d_modprops == MOD_STATIC)
+ a->a_modprops = MOD_STATIC;
expandattr(a, selectattr);
}
+ /* XXX expand attrs found on line 'attach foo at bar: attrs' */
if (da != NULL) {
- (void)ht_insert(selecttab, da->d_name, (char *)da->d_name);
+ (void)ht_insert(selecttab, da->d_name, &da->d_modprops);
for (nv = da->d_attrs; nv != NULL; nv = nv->nv_next) {
a = nv->nv_ptr;
+ /* XXX If we're static, mark attribute as such */
+ if (da->d_modprops == MOD_STATIC)
+ a->a_modprops = MOD_STATIC;
expandattr(a, selectattr);
}
}
Index: sem.h
===================================================================
RCS file: /pub/NetBSD-CVS/src/usr.sbin/config/sem.h,v
retrieving revision 1.18
diff -u -r1.18 sem.h
--- sem.h 2003/08/07 11:25:17 1.18
+++ sem.h 2004/02/06 23:09:23
@@ -50,7 +50,7 @@
void defdevattach(struct deva *, struct devbase *, struct nvlist *,
struct nvlist *);
struct devbase *getdevbase(const char *);
-struct deva *getdevattach(const char *);
+struct deva *getdevattach(const char *, int);
struct attr *getattr(const char *);
void expandattr(struct attr *, void (*)(struct attr *));
void selectattr(struct attr *);
@@ -58,12 +58,13 @@
void addconf(struct config *);
void setconf(struct nvlist **, const char *, struct nvlist *);
void setfstype(const char **, const char *);
-void adddev(const char *, const char *, struct nvlist *, int);
+void adddev(const char *, const char *, struct nvlist *, int, int);
void deldev(const char *, const char *);
-void addpseudo(const char *, int);
+void addpseudo(const char *, int, int);
void delpseudo(const char *);
void adddevm(const char *, int, int, struct nvlist *);
void fixdevis(void);
+void fixmodules(void);
const char *ref(const char *);
const char *starref(const char *);
const char *wildref(const char *);
Index: util.c
===================================================================
RCS file: /pub/NetBSD-CVS/src/usr.sbin/config/util.c,v
retrieving revision 1.18
diff -u -r1.18 util.c
--- util.c 2003/09/19 06:19:56 1.18
+++ util.c 2004/02/06 23:09:23
@@ -229,6 +229,26 @@
}
}
+/*
+ * Concatenate two lists
+ */
+struct nvlist *
+nvcat(struct nvlist *l1, struct nvlist *l2)
+{
+ struct nvlist *tail;
+
+ if (l1 == NULL)
+ return (l2);
+ if (l2 == NULL)
+ return (l1);
+
+ /* Reach tail of l1 */
+ for (tail = l1; tail->nv_next != NULL; tail = tail->nv_next);
+
+ tail->nv_next = l2;
+ return (l1);
+}
+
void
warn(const char *fmt, ...)
{
--- /dev/null 2004-02-07 00:05:16.000000000 +0100
+++ mkmodules.c 2004-02-04 10:56:46.000000000 +0100
@@ -0,0 +1,123 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Quentin Garnier.
+ *
+ * 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 the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 THE FOUNDATION OR CONTRIBUTORS
+ * 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/param.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "defs.h"
+
+static int mkmodule(const char *, void *, void *);
+
+/*
+ * Construct files named <module>_lkmentry.c that calls all LKM entry points
+ * for a given set of modular attributes.
+ *
+ * Such a file won't be produced if only one attribute makes the module.
+ */
+
+int
+mkmodules(void)
+{
+ return (ht_enumerate(modulestab, mkmodule, NULL));
+}
+
+static int
+mkmodule(const char *attr, void *val, void *arg)
+{
+ struct module *mod = val;
+ struct nvlist *nv;
+ FILE *fp;
+ char modentry[MOD_MAXNAME+12]; /* _lkmentry.c is appended */
+ int error;
+
+ if (mod->m_count == 1 || mod->m_name == NULL)
+ return (0);
+
+ strlcpy(modentry, mod->m_name, MOD_MAXNAME+12);
+ strlcat(modentry, "_lkmentry.c", MOD_MAXNAME+12);
+ if ((fp = fopen(modentry, "w")) == NULL) {
+ (void)fprintf(stderr, "config: cannot write %s: %s\n", modentry,
+ strerror(errno));
+ return (1);
+ }
+
+ error = fprintf(fp,
+"/*\n\
+ * MACHINE GENERATED: DO NOT EDIT\n\
+ *\n\
+ * %s, from %s\n\
+ */\n\
+\n\
+#include <sys/param.h>\n\
+#include <sys/systm.h>\n\
+#include <sys/lkm.h>\n\
+\n\
+MOD_MISC(\"%s\");\n\
+\n\
+int\t%s_lkmentry(struct lkm_table *, int, int);\n\
+\n\
+int\n\
+%s_lkmentry(struct lkm_table *lkmtp, int command, int version)\n\
+{\n\
+\tint error;\n",
+ modentry, conffile, mod->m_name, mod->m_name, mod->m_name);
+ if (error < 0)
+ goto stop;
+
+ for (nv = mod->m_attrlist; nv != NULL; nv = nv->nv_next) {
+ error = fprintf(fp,
+"\tif ((error = %s_lkmentry(lkmtp, command, version)) != 0)\n\
+\t\treturn (error);\n", nv->nv_name);
+ if (error < 0)
+ goto stop;
+ }
+
+ fprintf(fp,
+"\treturn (0);\n\
+}\n");
+
+ fclose(fp);
+ return (0);
+
+stop:
+ fclose(fp);
+ return (1);
+}
--Multipart=_Sat__7_Feb_2004_01_10_35_+0100_WzxD4GVPFC9eC+eU--