1 /* $NetBSD: kern_module.c,v 1.55 2009/12/29 17:49:21 elad Exp $ */
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software developed for The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Kernel module support.
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.55 2009/12/29 17:49:21 elad Exp $");
39 #define _MODULE_INTERNAL
43 #include "opt_modular.h"
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
50 #include <sys/kauth.h>
53 #include <sys/module.h>
54 #include <sys/kauth.h>
55 #include <sys/kthread.h>
56 #include <sys/sysctl.h>
59 #include <uvm/uvm_extern.h>
61 #include <machine/stdarg.h>
63 struct vm_map
*module_map
;
64 char module_base
[MODULE_BASE_SIZE
];
66 struct modlist module_list
= TAILQ_HEAD_INITIALIZER(module_list
);
67 struct modlist module_bootlist
= TAILQ_HEAD_INITIALIZER(module_bootlist
);
68 static module_t
*module_active
;
69 static int module_verbose_on
;
70 static int module_autoload_on
= 1;
73 u_int module_autotime
= 10;
75 static kcondvar_t module_thread_cv
;
76 static kmutex_t module_thread_lock
;
77 static int module_thread_ticks
;
79 static kauth_listener_t module_listener
;
81 /* Ensure that the kernel's link set isn't empty. */
82 static modinfo_t module_dummy
;
83 __link_set_add_rodata(modules
, module_dummy
);
85 static int module_do_load(const char *, bool, int, prop_dictionary_t
,
86 module_t
**, modclass_t
class, bool);
87 static int module_do_unload(const char *);
88 static int module_do_builtin(const char *, module_t
**);
89 static int module_fetch_info(module_t
*);
90 static void module_thread(void *);
92 static bool module_merge_dicts(prop_dictionary_t
, const prop_dictionary_t
);
94 int module_eopnotsupp(void);
97 module_eopnotsupp(void)
102 __weak_alias(module_load_vfs
,module_eopnotsupp
);
107 * Utility function: log an error.
110 module_error(const char *fmt
, ...)
115 printf("WARNING: module error: ");
124 * Utility function: log verbose output.
127 module_print(const char *fmt
, ...)
131 if (module_verbose_on
) {
133 printf("DEBUG: module: ");
141 module_listener_cb(kauth_cred_t cred
, kauth_action_t action
, void *cookie
,
142 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
146 result
= KAUTH_RESULT_DEFER
;
148 if (action
!= KAUTH_SYSTEM_MODULE
)
151 if ((uintptr_t)arg2
!= 0) /* autoload */
152 result
= KAUTH_RESULT_ALLOW
;
160 * Initialize the module subsystem.
165 extern struct vm_map
*module_map
;
167 if (module_map
== NULL
) {
168 module_map
= kernel_map
;
170 mutex_init(&module_lock
, MUTEX_DEFAULT
, IPL_NONE
);
171 cv_init(&module_thread_cv
, "modunload");
172 mutex_init(&module_thread_lock
, MUTEX_DEFAULT
, IPL_NONE
);
173 #ifdef MODULAR /* XXX */
177 #if __NetBSD_Version__ / 1000000 % 100 == 99 /* -current */
178 snprintf(module_base
, sizeof(module_base
), "/stand/%s/%s/modules",
181 snprintf(module_base
, sizeof(module_base
), "/stand/%s/%d.%d/modules",
182 machine
, __NetBSD_Version__
/ 100000000,
183 __NetBSD_Version__
/ 1000000 % 100);
186 module_listener
= kauth_listen_scope(KAUTH_SCOPE_SYSTEM
,
187 module_listener_cb
, NULL
);
193 * Start the auto unload kthread.
200 error
= kthread_create(PRI_VM
, KTHREAD_MPSAFE
, NULL
, module_thread
,
201 NULL
, NULL
, "modunload");
203 panic("module_init: %d", error
);
206 SYSCTL_SETUP(sysctl_module_setup
, "sysctl module setup")
208 const struct sysctlnode
*node
= NULL
;
210 sysctl_createv(clog
, 0, NULL
, NULL
,
212 CTLTYPE_NODE
, "kern", NULL
,
215 sysctl_createv(clog
, 0, NULL
, &node
,
217 CTLTYPE_NODE
, "module",
218 SYSCTL_DESCR("Module options"),
220 CTL_KERN
, CTL_CREATE
, CTL_EOL
);
225 sysctl_createv(clog
, 0, &node
, NULL
,
226 CTLFLAG_PERMANENT
| CTLFLAG_READWRITE
,
227 CTLTYPE_INT
, "autoload",
228 SYSCTL_DESCR("Enable automatic load of modules"),
229 NULL
, 0, &module_autoload_on
, 0,
230 CTL_CREATE
, CTL_EOL
);
231 sysctl_createv(clog
, 0, &node
, NULL
,
232 CTLFLAG_PERMANENT
| CTLFLAG_READWRITE
,
233 CTLTYPE_INT
, "verbose",
234 SYSCTL_DESCR("Enable verbose output"),
235 NULL
, 0, &module_verbose_on
, 0,
236 CTL_CREATE
, CTL_EOL
);
242 * Initialize all built-in and pre-loaded modules of the
246 module_init_class(modclass_t
class)
248 __link_set_decl(modules
, modinfo_t
);
249 modinfo_t
*const *mip
, *mi
;
252 mutex_enter(&module_lock
);
254 * Builtins first. These can't depend on pre-loaded modules.
256 __link_set_foreach(mip
, modules
) {
258 if (mi
== &module_dummy
) {
261 if (class != MODULE_CLASS_ANY
&& class != mi
->mi_class
) {
264 (void)module_do_builtin(mi
->mi_name
, NULL
);
267 * Now preloaded modules. These will be pulled off the
268 * list as we call module_do_load();
271 TAILQ_FOREACH(mod
, &module_bootlist
, mod_chain
) {
273 if (class != MODULE_CLASS_ANY
&&
274 class != mi
->mi_class
)
276 module_do_load(mi
->mi_name
, false, 0, NULL
, NULL
,
280 } while (mod
!= NULL
);
281 mutex_exit(&module_lock
);
287 * Return true if the two supplied kernel versions are said to
288 * have the same binary interface for kernel code. The entire
289 * version is signficant for the development tree (-current),
290 * major and minor versions are significant for official
291 * releases of the system.
294 module_compatible(int v1
, int v2
)
297 #if __NetBSD_Version__ / 1000000 % 100 == 99 /* -current */
300 return abs(v1
- v2
) < 10000;
307 * Load a single module from the file system.
310 module_load(const char *filename
, int flags
, prop_dictionary_t props
,
316 error
= kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE
,
317 0, (void *)(uintptr_t)MODCTL_LOAD
, NULL
, NULL
);
322 mutex_enter(&module_lock
);
323 error
= module_do_load(filename
, false, flags
, props
, NULL
, class,
325 mutex_exit(&module_lock
);
333 * Load a single module from the file system, system initiated.
336 module_autoload(const char *filename
, modclass_t
class)
340 KASSERT(mutex_owned(&module_lock
));
342 /* Nothing if the user has disabled it. */
343 if (!module_autoload_on
) {
347 /* Disallow path separators and magic symlinks. */
348 if (strchr(filename
, '/') != NULL
|| strchr(filename
, '@') != NULL
||
349 strchr(filename
, '.') != NULL
) {
354 error
= kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE
,
355 0, (void *)(uintptr_t)MODCTL_LOAD
, (void *)(uintptr_t)1, NULL
);
360 return module_do_load(filename
, false, 0, NULL
, NULL
, class, true);
366 * Find and unload a module by name.
369 module_unload(const char *name
)
374 error
= kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE
,
375 0, (void *)(uintptr_t)MODCTL_UNLOAD
, NULL
, NULL
);
380 mutex_enter(&module_lock
);
381 error
= module_do_unload(name
);
382 mutex_exit(&module_lock
);
390 * Look up a module by name.
393 module_lookup(const char *name
)
397 KASSERT(mutex_owned(&module_lock
));
399 TAILQ_FOREACH(mod
, &module_list
, mod_chain
) {
400 if (strcmp(mod
->mod_info
->mi_name
, name
) == 0) {
411 * Add a single reference to a module. It's the caller's
412 * responsibility to ensure that the reference is dropped
416 module_hold(const char *name
)
420 mutex_enter(&module_lock
);
421 mod
= module_lookup(name
);
423 mutex_exit(&module_lock
);
427 mutex_exit(&module_lock
);
435 * Release a reference acquired with module_hold().
438 module_rele(const char *name
)
442 mutex_enter(&module_lock
);
443 mod
= module_lookup(name
);
445 mutex_exit(&module_lock
);
446 panic("module_rele: gone");
449 mutex_exit(&module_lock
);
455 * Put a module onto the global list and update counters.
458 module_enqueue(module_t
*mod
)
462 KASSERT(mutex_owned(&module_lock
));
465 * If there are requisite modules, put at the head of the queue.
466 * This is so that autounload can unload requisite modules with
467 * only one pass through the queue.
469 if (mod
->mod_nrequired
) {
470 TAILQ_INSERT_HEAD(&module_list
, mod
, mod_chain
);
472 /* Add references to the requisite modules. */
473 for (i
= 0; i
< mod
->mod_nrequired
; i
++) {
474 KASSERT(mod
->mod_required
[i
] != NULL
);
475 mod
->mod_required
[i
]->mod_refcnt
++;
478 TAILQ_INSERT_TAIL(&module_list
, mod
, mod_chain
);
487 * Initialize a single module from the list of modules that are
488 * built into the kernel (linked into the kernel image).
491 module_do_builtin(const char *name
, module_t
**modp
)
493 __link_set_decl(modules
, modinfo_t
);
494 modinfo_t
*const *mip
;
496 char buf
[MAXMODNAME
];
498 module_t
*mod
, *mod2
;
502 KASSERT(mutex_owned(&module_lock
));
505 * Check to see if already loaded.
507 if ((mod
= module_lookup(name
)) != NULL
) {
515 * Search the list to see if we have a module by this name.
518 __link_set_foreach(mip
, modules
) {
520 if (mi
== &module_dummy
) {
523 if (strcmp(mi
->mi_name
, name
) == 0) {
529 module_error("can't find `%s'", name
);
534 * Initialize pre-requisites.
536 mod
= kmem_zalloc(sizeof(*mod
), KM_SLEEP
);
538 module_error("out of memory for `%s'", name
);
544 if (mi
->mi_required
!= NULL
) {
545 for (s
= mi
->mi_required
; *s
!= '\0'; s
= p
) {
549 while (*p
!= '\0' && *p
!= ',')
551 len
= min(p
- s
+ 1, sizeof(buf
));
552 strlcpy(buf
, s
, len
);
555 if (mod
->mod_nrequired
== MAXMODDEPS
- 1) {
556 module_error("too many required modules");
557 kmem_free(mod
, sizeof(*mod
));
560 error
= module_do_builtin(buf
, &mod2
);
562 kmem_free(mod
, sizeof(*mod
));
565 mod
->mod_required
[mod
->mod_nrequired
++] = mod2
;
570 * Try to initialize the module.
572 KASSERT(module_active
== NULL
);
574 error
= (*mi
->mi_modcmd
)(MODULE_CMD_INIT
, NULL
);
575 module_active
= NULL
;
577 module_error("builtin module `%s' "
578 "failed to init", mi
->mi_name
);
579 kmem_free(mod
, sizeof(*mod
));
582 if (mi
->mi_class
== MODULE_CLASS_SECMODEL
)
585 mod
->mod_source
= MODULE_SOURCE_KERNEL
;
593 * Helper routine: load a module from the file system, or one
594 * pushed by the boot loader.
597 module_do_load(const char *name
, bool isdep
, int flags
,
598 prop_dictionary_t props
, module_t
**modp
, modclass_t
class,
601 static TAILQ_HEAD(,module
) pending
= TAILQ_HEAD_INITIALIZER(pending
);
603 const int maxdepth
= 6;
605 module_t
*mod
, *mod2
;
606 prop_dictionary_t filedict
;
607 char buf
[MAXMODNAME
];
612 KASSERT(mutex_owned(&module_lock
));
618 * Avoid recursing too far.
620 if (++depth
> maxdepth
) {
621 module_error("too many required modules");
627 * Load the module and link. Before going to the file system,
628 * scan the list of modules loaded by the boot loader. Just
629 * before init is started the list of modules loaded at boot
630 * will be purged. Before init is started we can assume that
631 * `name' is a module name and not a path name.
633 TAILQ_FOREACH(mod
, &module_bootlist
, mod_chain
) {
634 if (strcmp(mod
->mod_info
->mi_name
, name
) == 0) {
635 TAILQ_REMOVE(&module_bootlist
, mod
, mod_chain
);
640 TAILQ_INSERT_TAIL(&pending
, mod
, mod_chain
);
643 * If a requisite module, check to see if it is
647 TAILQ_FOREACH(mod
, &module_list
, mod_chain
) {
648 if (strcmp(mod
->mod_info
->mi_name
, name
) == 0) {
660 mod
= kmem_zalloc(sizeof(*mod
), KM_SLEEP
);
662 module_error("out of memory for `%s'", name
);
667 error
= module_load_vfs(name
, flags
, autoload
, mod
, &filedict
);
669 kmem_free(mod
, sizeof(*mod
));
673 mod
->mod_source
= MODULE_SOURCE_FILESYS
;
674 TAILQ_INSERT_TAIL(&pending
, mod
, mod_chain
);
676 error
= module_fetch_info(mod
);
678 module_error("cannot fetch module info for `%s'",
685 * Check compatibility.
688 if (strlen(mi
->mi_name
) >= MAXMODNAME
) {
690 module_error("module name `%s' too long", mi
->mi_name
);
693 if (!module_compatible(mi
->mi_version
, __NetBSD_Version__
)) {
694 module_error("module built for `%d', system `%d'",
695 mi
->mi_version
, __NetBSD_Version__
);
696 if ((flags
& MODCTL_LOAD_FORCE
) != 0) {
697 module_error("forced load, system may be unstable");
699 error
= EPROGMISMATCH
;
705 * If a specific kind of module was requested, ensure that we have
708 if (class != MODULE_CLASS_ANY
&& class != mi
->mi_class
) {
709 module_print("incompatible module class for `%s' (%d != %d)",
710 name
, class, mi
->mi_class
);
716 * If loading a dependency, `name' is a plain module name.
717 * The name must match.
719 if (isdep
&& strcmp(mi
->mi_name
, name
) != 0) {
720 module_error("dependency name mismatch (`%s' != `%s')",
727 * Check to see if the module is already loaded. If so, we may
728 * have been recursively called to handle a dependency, so be sure
731 if ((mod2
= module_lookup(mi
->mi_name
)) != NULL
) {
734 module_print("module `%s' already loaded", mi
->mi_name
);
740 * Block circular dependencies.
742 TAILQ_FOREACH(mod2
, &pending
, mod_chain
) {
746 if (strcmp(mod2
->mod_info
->mi_name
, mi
->mi_name
) == 0) {
748 module_error("circular dependency detected for `%s'",
755 * Now try to load any requisite modules.
757 if (mi
->mi_required
!= NULL
) {
758 for (s
= mi
->mi_required
; *s
!= '\0'; s
= p
) {
762 while (*p
!= '\0' && *p
!= ',')
765 if (len
>= MAXMODNAME
) {
767 module_error("required module name `%s'"
768 " too long", mi
->mi_required
);
771 strlcpy(buf
, s
, len
);
774 if (mod
->mod_nrequired
== MAXMODDEPS
- 1) {
776 module_error("too many required modules (%d)",
780 if (strcmp(buf
, mi
->mi_name
) == 0) {
782 module_error("self-dependency detected for "
783 "`%s'", mi
->mi_name
);
786 error
= module_do_load(buf
, true, flags
, NULL
,
787 &mod
->mod_required
[mod
->mod_nrequired
++],
788 MODULE_CLASS_ANY
, true);
795 * We loaded all needed modules successfully: perform global
796 * relocations and initialize.
798 error
= kobj_affix(mod
->mod_kobj
, mi
->mi_name
);
800 /* Cannot touch 'mi' as the module is now gone. */
801 module_error("unable to affix module `%s'", name
);
806 if (!module_merge_dicts(filedict
, props
)) {
807 module_error("module properties failed");
812 KASSERT(module_active
== NULL
);
814 error
= (*mi
->mi_modcmd
)(MODULE_CMD_INIT
, filedict
? filedict
: props
);
815 module_active
= NULL
;
817 prop_object_release(filedict
);
821 module_error("modcmd function returned error %d for `%s'",
826 if (mi
->mi_class
== MODULE_CLASS_SECMODEL
)
830 * Good, the module loaded successfully. Put it onto the
831 * list and add references to its requisite modules.
833 TAILQ_REMOVE(&pending
, mod
, mod_chain
);
840 * Arrange to try unloading the module after
843 mod
->mod_autotime
= time_second
+ module_autotime
;
844 module_thread_kick();
850 kobj_unload(mod
->mod_kobj
);
852 if (filedict
!= NULL
) {
853 prop_object_release(filedict
);
856 TAILQ_REMOVE(&pending
, mod
, mod_chain
);
857 kmem_free(mod
, sizeof(*mod
));
865 * Helper routine: do the dirty work of unloading a module.
868 module_do_unload(const char *name
)
874 KASSERT(mutex_owned(&module_lock
));
876 mod
= module_lookup(name
);
878 module_error("module `%s' not found", name
);
881 if (mod
->mod_refcnt
!= 0 || mod
->mod_source
== MODULE_SOURCE_KERNEL
) {
882 module_print("module `%s' busy", name
);
885 KASSERT(module_active
== NULL
);
887 error
= (*mod
->mod_info
->mi_modcmd
)(MODULE_CMD_FINI
, NULL
);
888 module_active
= NULL
;
890 module_print("cannot unload module `%s' error=%d", name
,
894 if (mod
->mod_info
->mi_class
== MODULE_CLASS_SECMODEL
)
895 secmodel_deregister();
897 TAILQ_REMOVE(&module_list
, mod
, mod_chain
);
898 for (i
= 0; i
< mod
->mod_nrequired
; i
++) {
899 mod
->mod_required
[i
]->mod_refcnt
--;
901 if (mod
->mod_kobj
!= NULL
) {
902 kobj_unload(mod
->mod_kobj
);
904 kmem_free(mod
, sizeof(*mod
));
913 * Push a module loaded by the bootloader onto our internal
917 module_prime(void *base
, size_t size
)
922 mod
= kmem_zalloc(sizeof(*mod
), KM_SLEEP
);
926 mod
->mod_source
= MODULE_SOURCE_BOOT
;
928 error
= kobj_load_mem(&mod
->mod_kobj
, base
, size
);
930 kmem_free(mod
, sizeof(*mod
));
931 module_error("unable to load object pushed by boot loader");
934 error
= module_fetch_info(mod
);
936 kobj_unload(mod
->mod_kobj
);
937 kmem_free(mod
, sizeof(*mod
));
938 module_error("unable to load object pushed by boot loader");
942 TAILQ_INSERT_TAIL(&module_bootlist
, mod
, mod_chain
);
950 * Fetch modinfo record from a loaded module.
953 module_fetch_info(module_t
*mod
)
960 * Find module info record and check compatibility.
962 error
= kobj_find_section(mod
->mod_kobj
, "link_set_modules",
965 module_error("`link_set_modules' section not present");
968 if (size
!= sizeof(modinfo_t
**)) {
969 module_error("`link_set_modules' section wrong size");
972 mod
->mod_info
= *(modinfo_t
**)addr
;
978 * module_find_section:
980 * Allows a module that is being initialized to look up a section
981 * within its ELF object.
984 module_find_section(const char *name
, void **addr
, size_t *size
)
987 KASSERT(mutex_owned(&module_lock
));
988 KASSERT(module_active
!= NULL
);
990 return kobj_find_section(module_active
->mod_kobj
, name
, addr
, size
);
996 * Automatically unload modules. We try once to unload autoloaded
997 * modules after module_autotime seconds. If the system is under
998 * severe memory pressure, we'll try unloading all modules.
1001 module_thread(void *cookie
)
1003 module_t
*mod
, *next
;
1008 mutex_enter(&module_lock
);
1009 for (mod
= TAILQ_FIRST(&module_list
); mod
!= NULL
; mod
= next
) {
1010 next
= TAILQ_NEXT(mod
, mod_chain
);
1011 if (uvmexp
.free
< uvmexp
.freemin
) {
1012 module_thread_ticks
= hz
;
1013 } else if (mod
->mod_autotime
== 0) {
1015 } else if (time_second
< mod
->mod_autotime
) {
1016 module_thread_ticks
= hz
;
1019 mod
->mod_autotime
= 0;
1022 * If this module wants to avoid autounload then
1023 * skip it. Some modules can ping-pong in and out
1024 * because their use is transient but often.
1025 * Example: exec_script.
1028 error
= (*mi
->mi_modcmd
)(MODULE_CMD_AUTOUNLOAD
, NULL
);
1029 if (error
== 0 || error
== ENOTTY
) {
1030 (void)module_do_unload(mi
->mi_name
);
1033 mutex_exit(&module_lock
);
1035 mutex_enter(&module_thread_lock
);
1036 (void)cv_timedwait(&module_thread_cv
, &module_thread_lock
,
1037 module_thread_ticks
);
1038 module_thread_ticks
= 0;
1039 mutex_exit(&module_thread_lock
);
1046 * Kick the module thread into action, perhaps because the
1047 * system is low on memory.
1050 module_thread_kick(void)
1053 mutex_enter(&module_thread_lock
);
1054 module_thread_ticks
= hz
;
1055 cv_broadcast(&module_thread_cv
);
1056 mutex_exit(&module_thread_lock
);
1063 * Helper routine for DDB.
1066 module_whatis(uintptr_t addr
, void (*pr
)(const char *, ...))
1072 TAILQ_FOREACH(mod
, &module_list
, mod_chain
) {
1073 if (mod
->mod_kobj
== NULL
) {
1076 if (kobj_stat(mod
->mod_kobj
, &maddr
, &msize
) != 0)
1078 if (addr
< maddr
|| addr
>= maddr
+ msize
) {
1081 (*pr
)("%p is %p+%zu, in kernel module `%s'\n",
1082 (void *)addr
, (void *)maddr
,
1083 (size_t)(addr
- maddr
), mod
->mod_info
->mi_name
);
1088 * module_print_list:
1090 * Helper routine for DDB.
1093 module_print_list(void (*pr
)(const char *, ...))
1100 (*pr
)("%16s %16s %8s %8s\n", "NAME", "TEXT/DATA", "SIZE", "SOURCE");
1102 TAILQ_FOREACH(mod
, &module_list
, mod_chain
) {
1103 switch (mod
->mod_source
) {
1104 case MODULE_SOURCE_KERNEL
:
1107 case MODULE_SOURCE_FILESYS
:
1110 case MODULE_SOURCE_BOOT
:
1117 if (mod
->mod_kobj
== NULL
) {
1120 } else if (kobj_stat(mod
->mod_kobj
, &maddr
, &msize
) != 0)
1122 (*pr
)("%16s %16lx %8ld %8s\n", mod
->mod_info
->mi_name
,
1123 (long)maddr
, (long)msize
, src
);
1129 module_merge_dicts(prop_dictionary_t existing_dict
,
1130 const prop_dictionary_t new_dict
)
1132 prop_dictionary_keysym_t props_keysym
;
1133 prop_object_iterator_t props_iter
;
1134 prop_object_t props_obj
;
1135 const char *props_key
;
1138 if (new_dict
== NULL
) { /* nothing to merge */
1143 props_iter
= prop_dictionary_iterator(new_dict
);
1144 if (props_iter
== NULL
) {
1148 while ((props_obj
= prop_object_iterator_next(props_iter
)) != NULL
) {
1149 props_keysym
= (prop_dictionary_keysym_t
)props_obj
;
1150 props_key
= prop_dictionary_keysym_cstring_nocopy(props_keysym
);
1151 props_obj
= prop_dictionary_get_keysym(new_dict
, props_keysym
);
1152 if ((props_obj
== NULL
) || !prop_dictionary_set(existing_dict
,
1153 props_key
, props_obj
)) {
1161 prop_object_iterator_release(props_iter
);