? 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 #include #include +#include + +#include /* for DIRBLKSIZ */ #include 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) {