diff --git a/sys/kern/subr_devstat.c b/sys/kern/subr_devstat.c
index e3d6d87..7f883df 100644
--- a/sys/kern/subr_devstat.c
+++ b/sys/kern/subr_devstat.c
@@ -312,3 +312,83 @@ SYSCTL_LONG(_kern_devstat, OID_AUTO, generation, CTLFLAG_RD,
     &devstat_generation, 0, "Devstat list generation");
 SYSCTL_INT(_kern_devstat, OID_AUTO, version, CTLFLAG_RD, 
     &devstat_version, 0, "Devstat list version number");
+
+struct cdev_prop_ctx {
+	prop_array_t cdevs;
+	int error;
+};
+
+static
+int
+dict_from_cdev(cdev_t cdev, void *arg)
+{
+	prop_string_t str;
+	prop_number_t num;
+	prop_dictionary_t dict;
+	struct cdev_prop_ctx *ctx = arg;
+
+	KKASSERT(arg != NULL);
+	if (ctx->error)
+		return;
+	if (!(dict = prop_dictionary_create())) {
+		ctx->error = ENOMEM;
+		return;
+	}
+	if (!(str = prop_string_create_cstring(cdev->si_name)))
+		goto cleanup;
+	if (!prop_dictionary_set(dict, "name", 	str))
+		goto cleanup;
+	if (!(num = prop_number_create_unsigned_integer((uint64_t)&cdev)))
+		goto cleanup;
+	if (!prop_dictionary_set(dict, "kptr", 	str))
+		goto cleanup;
+	if !(prop_array_add(cdevs, dict))
+		goto free_array;
+
+	return !0;
+	
+}
+
+static int
+sysctl_cdevinfo(SYSCTL_HANDLER_ARGS)
+{
+	struct plistref prefp;
+	prop_array_t cdevs;
+	cdev_t cdev;
+	devfs_scan_t *scan;
+	struct cdev_prop_ctx ctx;
+
+	if (!(cdevs = prop_array_create()))
+		return ENOMEM;
+	ctx.cdevs = cdevs;
+	ctx.error = 0;
+	devfs_scan_callback(&dict_from_cdev, &ctx);
+
+	TAILQ_FOREACH(cdev, &devfs_dev_list, link) {
+		prop_dictionary_t dict;
+		if (!(dict = prop_dictionary_create()))
+			goto free_array;
+		if (!dict_from_cdev(dict, cdev))
+			goto free_array;
+		if !(prop_array_add(cdevs, dict))
+			goto free_array;
+	}
+
+	if (!prop_array_externalize_to_pref(cdevs, &prefp))
+		goto free_array;
+	SYSCTL_OUT(req, prefp
+	/*
+	 * First push out the generation number.
+	 */
+	error = SYSCTL_OUT(req, &devstat_generation, sizeof(long));
+
+	/*
+	 * Now push out all the devices.
+	 */
+	for (i = 0, nds = STAILQ_FIRST(devstat_head); 
+	    (nds != NULL) && (i < devstat_num_devs) && (error == 0); 
+	     nds = STAILQ_NEXT(nds, dev_links), i++)
+		error = SYSCTL_OUT(req, nds, sizeof(struct devstat));
+
+	return(error);
+}
diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c
index 5628474..8a63c82 100644
--- a/sys/kern/vfs_conf.c
+++ b/sys/kern/vfs_conf.c
@@ -455,8 +455,12 @@ end:
 	return(error);
 }
 
-
-static void vfs_mountroot_ask_callback(cdev_t);
+static void
+vfs_mountroot_ask_callback(cdev_t dev, void *arg __unused)
+{
+	if (dev_is_good(dev) && (dev_dflags(dev) & D_DISK))
+		kprintf(" \"%s\" ", dev->si_name);
+}
 
 /*
  * Spin prompting on the console for a suitable root filesystem
@@ -483,7 +487,7 @@ vfs_mountroot_ask(void)
 		} else if (name[0] == '?') {
 			kprintf("Possibly valid devices for root FS:\n");
 			//enumerate all disk devices
-			devfs_scan_callback(vfs_mountroot_ask_callback);
+			devfs_scan_callback(vfs_mountroot_ask_callback, NULL);
 			kprintf("\n");
 			continue;
 		} else if (strcmp(name, "panic") == 0) {
@@ -497,15 +501,6 @@ vfs_mountroot_ask(void)
 	return(1);
 }
 
-
-static void
-vfs_mountroot_ask_callback(cdev_t dev)
-{
-	if (dev_is_good(dev) && (dev_dflags(dev) & D_DISK))
-		kprintf(" \"%s\" ", dev->si_name);
-}
-
-
 static int
 getline(char *cp, int limit)
 {
diff --git a/sys/sys/devfs.h b/sys/sys/devfs.h
index 63a5f00..c1bb3bb 100644
--- a/sys/sys/devfs.h
+++ b/sys/sys/devfs.h
@@ -173,6 +173,7 @@ typedef struct devfs_msg {
 		} __m_chandler;
 		struct {
 			void *load;
+			void *load2;
 		} __m_gen;
 		struct {
 			void *resp;
@@ -218,6 +219,7 @@ typedef struct devfs_msg {
 #define mdv_chandler	__m_u.__m_chandler
 #define mdv_mnt		__m_u.__m_mnt.mnt
 #define mdv_load	__m_u.__m_gen.load
+#define mdv_load2	__m_u.__m_gen.load2
 #define mdv_response	__m_u.__m_resp.resp
 #define mdv_dev		__m_u.__m_dev
 #define mdv_link	__m_u.__m_link
diff --git a/sys/vfs/devfs/devfs_core.c b/sys/vfs/devfs/devfs_core.c
index 9de7aba..9a51106 100644
--- a/sys/vfs/devfs/devfs_core.c
+++ b/sys/vfs/devfs/devfs_core.c
@@ -127,7 +127,7 @@ static int devfs_find_device_by_udev_worker(devfs_msg_t);
 
 static int devfs_apply_reset_rules_caller(char *, int);
 
-static int devfs_scan_callback_worker(devfs_scan_t *);
+static int devfs_scan_callback_worker(devfs_scan_t *, void *);
 
 static struct devfs_node *devfs_resolve_or_create_dir(struct devfs_node *,
 		char *, size_t, int);
@@ -857,7 +857,7 @@ devfs_reset_rules(char *mntto)
  * It just sends a message with the relevant details to the devfs core.
  */
 int
-devfs_scan_callback(devfs_scan_t *callback)
+devfs_scan_callback(devfs_scan_t *callback, void *arg)
 {
 	devfs_msg_t msg;
 
@@ -865,6 +865,7 @@ devfs_scan_callback(devfs_scan_t *callback)
 
 	msg = devfs_msg_get();
 	msg->mdv_load = callback;
+	msg->mdv_load2 = arg;
 	msg = devfs_msg_send_sync(DEVFS_SCAN_CALLBACK, msg);
 	devfs_msg_put(msg);
 
@@ -1140,7 +1141,8 @@ devfs_msg_exec(devfs_msg_t msg)
 		devfs_apply_reset_rules_caller(msg->mdv_name, 0);
 		break;
 	case DEVFS_SCAN_CALLBACK:
-		devfs_scan_callback_worker((devfs_scan_t *)msg->mdv_load);
+		devfs_scan_callback_worker((devfs_scan_t *)msg->mdv_load,
+			msg->mdv_load2);
 		break;
 	case DEVFS_CLR_SUBNAMES_FLAG:
 		devfs_clr_subnames_flag_worker(msg->mdv_flags.name,
@@ -1646,12 +1648,12 @@ devfs_apply_reset_rules_caller(char *mountto, int apply)
  * every dev node in the devfs dev list.
  */
 static int
-devfs_scan_callback_worker(devfs_scan_t *callback)
+devfs_scan_callback_worker(devfs_scan_t *callback, void *arg)
 {
 	cdev_t dev, dev1;
 
 	TAILQ_FOREACH_MUTABLE(dev, &devfs_dev_list, link, dev1) {
-		callback(dev);
+		callback(dev, arg);
 	}
 
 	return 0;
