? sys/dev/acpi/wmi/wmi_twinhead.c
Index: sys/kern/kern_module.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_module.c,v
retrieving revision 1.73
diff -u -r1.73 kern_module.c
--- sys/kern/kern_module.c      16 Oct 2010 18:09:02 -0000      1.73
+++ sys/kern/kern_module.c      27 Oct 2010 09:11:40 -0000
@@ -78,6 +78,9 @@
static int     module_thread_ticks;
int (*module_load_vfs_vec)(const char *, int, bool, module_t *,
                          prop_dictionary_t *) = (void *)eopnotsupp;
+int (*module_cfload_vfs_vec)(void *,
+                            int (*)(void *, const char *, prop_dictionary_t)) =
+                            (void *)eopnotsupp;

static kauth_listener_t        module_listener;

@@ -577,6 +580,18 @@
}

/*
+ * module_cfload:
+ *
+ *     Search the filesystem and load modules based on match criteria.
+ */
+int
+module_cfload(void *opaque,
+    int (*match)(void *, const char *, prop_dictionary_t))
+{
+       return module_cfload_vfs_vec(opaque, match);
+}
+
+/*
 * module_unload:
 *
 *     Find and unload a module by name.
Index: sys/kern/kern_module_vfs.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_module_vfs.c,v
retrieving revision 1.7
diff -u -r1.7 kern_module_vfs.c
--- sys/kern/kern_module_vfs.c  24 Jun 2010 13:03:11 -0000      1.7
+++ sys/kern/kern_module_vfs.c  27 Oct 2010 09:11:40 -0000
@@ -46,16 +46,23 @@
#include <sys/pool.h>
#include <sys/stat.h>
#include <sys/vnode.h>
+#include <sys/dirent.h>
+
+#include <ufs/ufs/dir.h>       /* for DIRBLKSIZ */

#include <prop/proplib.h>

static int     module_load_plist_vfs(const char *, const bool,
                                     prop_dictionary_t *);
+static int     module_cfload_vfs_probe(void *opaque,
+                       int (*match)(void *, const char *, prop_dictionary_t),
+                       const char *);

void
module_load_vfs_init(void)
{
       module_load_vfs_vec = module_load_vfs;
+       module_cfload_vfs_vec = module_cfload_vfs;
}

int
@@ -118,6 +125,146 @@
       return error;
}

+int
+module_cfload_vfs_probe(void *opaque,
+    int (*match)(void *, const char *, prop_dictionary_t),
+    const char *modname)
+{
+       prop_dictionary_t filedict, dict;
+       prop_object_iterator_t iter;
+       prop_object_t obj;
+       prop_array_t arr;
+       const char *ifattr;
+       char *modpath;
+       int error;
+
+       modpath = PNBUF_GET();
+       snprintf(modpath, MAXPATHLEN, "%s/%s/%s.kmod",
+           module_base, modname, modname);
+
+       error = module_load_plist_vfs(modpath, true, &filedict);
+       if (error)
+               return 0;
+
+       obj = prop_dictionary_get(filedict, "ModuleInfo");
+       if (obj == NULL || prop_object_type(obj) != PROP_TYPE_ARRAY)
+               goto badprops;
+
+       arr = (prop_array_t)obj;
+       iter = prop_array_iterator(arr);
+        while ((obj = prop_object_iterator_next(iter)) != NULL) {
+               if (prop_object_type(obj) != PROP_TYPE_DICTIONARY)
+                       continue;
+               dict = (prop_dictionary_t)obj;
+               if (prop_dictionary_get_cstring_nocopy(dict, "CFInterface",
+                   &ifattr) == false)
+                       continue;
+               if (match(opaque, ifattr, dict)) {
+                       module_print("Loading %s\n", modpath);
+                       module_load(modpath, 0, filedict, MODULE_CLASS_ANY);
+                       break;
+               }
+       }
+       prop_object_iterator_release(iter);
+
+badprops:
+       prop_object_release(filedict);
+       PNBUF_PUT(modpath);
+
+       return 0;
+}
+
+int
+module_cfload_vfs(void *opaque,
+    int (*match)(void *, const char *, prop_dictionary_t))
+{
+       struct nameidata nd;
+       struct vnode *vp;
+       struct vattr va;
+       struct iovec iov;
+       struct uio uio;
+       struct dirent *dp;
+       char *dirbuf = NULL, *cpos;
+       off_t off;
+       int dirbuflen;
+       int error = 0, eofflag;
+
+       KASSERT(match != NULL);
+
+       NDINIT(&nd, LOOKUP, FOLLOW | NOCHROOT, UIO_SYSSPACE, module_base);
+       error = vn_open(&nd, FREAD, 0);
+       if (error)
+               return error;
+       vp = nd.ni_vp;
+
+       if (vp->v_type != VDIR)
+               goto done;
+
+       error = VOP_GETATTR(vp, &va, curlwp->l_cred);
+       if (error)
+               goto done;
+
+       dirbuflen = DIRBLKSIZ;
+       if (dirbuflen < va.va_blocksize)
+               dirbuflen = va.va_blocksize;
+       dirbuf = kmem_alloc(dirbuflen, KM_SLEEP);
+
+       off = 0;
+       do {
+               int len, reclen;
+
+               iov.iov_base = dirbuf;
+               iov.iov_len = dirbuflen;
+               uio.uio_iov = &iov;
+               uio.uio_iovcnt = 1;
+               uio.uio_offset = off;
+               uio.uio_resid = dirbuflen;
+               uio.uio_rw = UIO_READ;
+               UIO_SETUP_SYSSPACE(&uio);
+
+               eofflag = 0;
+               error = VOP_READDIR(vp, &uio, curlwp->l_cred, &eofflag, 0, 0);
+               if (error)
+                       break;
+
+               off = uio.uio_offset;
+
+               cpos = dirbuf;
+
+               vref(vp);
+               VOP_UNLOCK(vp);
+
+               for (len = (dirbuflen - uio.uio_resid); len > 0;
+                    len -= reclen) {
+                       dp = (struct dirent *)cpos;
+                       reclen = dp->d_reclen;
+
+                       if (reclen < _DIRENT_MINSIZE(dp)) {
+                               error = EINVAL;
+                               eofflag = 1;
+                               break;
+                       }
+
+                       if (dp->d_type == DT_DIR && dp->d_name[0] != '.') {
+                               module_cfload_vfs_probe(opaque,
+                                   match, dp->d_name);
+                       }
+
+                       cpos += reclen;
+               }
+
+               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+               vrele(vp);
+       } while (!eofflag);
+
+done:
+       if (dirbuf)
+               kmem_free(dirbuf, dirbuflen);
+       VOP_UNLOCK(vp);
+       vn_close(vp, FREAD, curlwp->l_cred);
+       return error;
+}
+
/*
 * module_load_plist_vfs:
 *
@@ -195,7 +342,7 @@

out:
       VOP_UNLOCK(nd.ni_vp);
-       vn_close(nd.ni_vp, FREAD, kauth_cred_get());
+       vn_close(nd.ni_vp, FREAD, curlwp->l_cred);

out1:
       PNBUF_PUT(proppath);
Index: sys/sys/module.h
===================================================================
RCS file: /cvsroot/src/sys/sys/module.h,v
retrieving revision 1.25
diff -u -r1.25 module.h
--- sys/sys/module.h    21 Aug 2010 13:17:32 -0000      1.25
+++ sys/sys/module.h    27 Oct 2010 09:11:40 -0000
@@ -133,6 +133,7 @@
int    module_builtin_add(modinfo_t * const *, size_t, bool);
int    module_builtin_remove(modinfo_t *, bool);
int    module_autoload(const char *, modclass_t);
+int    module_cfload(void *, int (*)(void *, const char *, prop_dictionary_t));
int    module_unload(const char *);
int    module_hold(const char *);
void   module_rele(const char *);
@@ -147,8 +148,13 @@
extern
int    (*module_load_vfs_vec)(const char *, int, bool, module_t *,
                              prop_dictionary_t *);
+extern
+int    (*module_cfload_vfs_vec)(void *, int (*)(void *, const char *,
+                                prop_dictionary_t));
int    module_load_vfs(const char *, int, bool, module_t *,
                       prop_dictionary_t *);
+int    module_cfload_vfs(void *, int (*)(void *, const char *,
+                         prop_dictionary_t));
void   module_error(const char *, ...)
                            __attribute__((__format__(__printf__,1,2)));
void   module_print(const char *, ...)
Index: sys/dev/acpi/wmi/wmi_acpi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/acpi/wmi/wmi_acpi.c,v
retrieving revision 1.10
diff -u -r1.10 wmi_acpi.c
--- sys/dev/acpi/wmi/wmi_acpi.c 25 Oct 2010 15:38:05 -0000      1.10
+++ sys/dev/acpi/wmi/wmi_acpi.c 27 Oct 2010 09:11:40 -0000
@@ -57,6 +57,8 @@
static int         acpi_wmi_detach(device_t, int);
static int         acpi_wmi_rescan(device_t, const char *, const int *);
static void        acpi_wmi_childdet(device_t, device_t);
+static void        acpi_wmi_mountroot(device_t);
+static int         acpi_wmi_cfload(void *, const char *, prop_dictionary_t);
static int         acpi_wmi_print(void *, const char *);
static bool        acpi_wmi_init(struct acpi_wmi_softc *);
static bool        acpi_wmi_add(struct acpi_wmi_softc *, ACPI_OBJECT *);
@@ -115,9 +117,9 @@
       acpi_wmi_dump(sc);
       acpi_wmi_event_add(sc);

-       acpi_wmi_rescan(self, NULL, NULL);
-
       (void)pmf_device_register(self, acpi_wmi_suspend, acpi_wmi_resume);
+
+       config_mountroot(self, acpi_wmi_mountroot);
}

static int
@@ -157,6 +159,47 @@
               sc->sc_child = NULL;
}

+static void
+acpi_wmi_mountroot(device_t self)
+{
+       module_cfload(self, acpi_wmi_cfload);
+       acpi_wmi_rescan(self, NULL, NULL);
+}
+
+static int
+acpi_wmi_cfload(void *opaque, const char *ifattr, prop_dictionary_t props)
+{
+       device_t self = opaque;
+       prop_object_t obj;
+       int match = 0;
+
+       if (ifattr == NULL || strcmp(ifattr, "acpiwmibus") != 0)
+               goto done;
+       if (props == NULL)
+               goto done;
+
+       obj = prop_dictionary_get(props, "ACPIWMIGUIDMatch");
+       if (obj && prop_object_type(obj) == PROP_TYPE_ARRAY) {
+               prop_array_t arr = (prop_array_t)obj;
+               prop_object_iterator_t iter;
+               const char *guid;
+
+               iter = prop_array_iterator(arr);
+               while ((obj = prop_object_iterator_next(iter)) != NULL) {
+                       if (prop_object_type(obj) != PROP_TYPE_STRING)
+                               continue;
+                       guid = prop_string_cstring_nocopy((prop_string_t)obj);
+                       match = acpi_wmi_guid_match(self, guid);
+                       if (match)
+                               break;
+               }
+               prop_object_iterator_release(iter);
+       }
+
+done:
+       return match;
+}
+
static int
acpi_wmi_print(void *aux, const char *pnp)
{