Index: meson/arch/arm32/meson.build
===================================================================
--- meson/arch/arm32/meson.build	(revision 7e6603784b2bbda102aa3edc13f5c1d8326b4a66)
+++ meson/arch/arm32/meson.build	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -55,5 +55,4 @@
 arch_boot_link_args = arch_kernel_link_args
 
-
 rd_essential_drv += [
 	'drv/bus/usb/ehci',
Index: meson/arch/ppc32/meson.build
===================================================================
--- meson/arch/ppc32/meson.build	(revision 7e6603784b2bbda102aa3edc13f5c1d8326b4a66)
+++ meson/arch/ppc32/meson.build	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -1,4 +1,4 @@
 #
-# Copyright (c) 2021 Jiri Svoboda
+# Copyright (c) 2023 Jiri Svoboda
 # Copyright (c) 2019 Jiří Zárevúcky
 # All rights reserved.
@@ -39,4 +39,7 @@
 arch_boot_link_args = []
 
+rd_essential += [
+	'app/ofw'
+]
 
 rd_essential_drv += [
Index: meson/arch/sparc64/meson.build
===================================================================
--- meson/arch/sparc64/meson.build	(revision 7e6603784b2bbda102aa3edc13f5c1d8326b4a66)
+++ meson/arch/sparc64/meson.build	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -1,4 +1,4 @@
 #
-# Copyright (c) 2021 Jiri Svoboda
+# Copyright (c) 2023 Jiri Svoboda
 # Copyright (c) 2019 Jiří Zárevúcky
 # All rights reserved.
@@ -76,4 +76,8 @@
 endif
 
+rd_essential += [
+	'app/ofw'
+]
+
 if PROCESSOR == 'sun4v'
 	rd_essential_drv += [
Index: uspace/app/meson.build
===================================================================
--- uspace/app/meson.build	(revision 7e6603784b2bbda102aa3edc13f5c1d8326b4a66)
+++ uspace/app/meson.build	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -72,4 +72,5 @@
 	'nic',
 	'nterm',
+	'ofw',
 	'pci',
 	'ping',
Index: uspace/app/ofw/doc/doxygroups.h
===================================================================
--- uspace/app/ofw/doc/doxygroups.h	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
+++ uspace/app/ofw/doc/doxygroups.h	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -0,0 +1,4 @@
+/** @addtogroup ofw ofw
+ * @brief Tool for printing the OpenFirmware device tree
+ * @ingroup apps
+ */
Index: uspace/app/ofw/meson.build
===================================================================
--- uspace/app/ofw/meson.build	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
+++ uspace/app/ofw/meson.build	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2023 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - 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.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+#
+
+platform_specific = true
+
+deps = [ 'ofw' ]
+src = files('ofw.c')
Index: uspace/app/ofw/ofw.c
===================================================================
--- uspace/app/ofw/ofw.c	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
+++ uspace/app/ofw/ofw.c	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2023 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/** @addtogroup ofw
+ * @{
+ */
+
+/**
+ * @file
+ * @brief Tool for printing the OpenFirmware device tree
+ */
+
+#include <errno.h>
+#include <ofw.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <str.h>
+
+#define NAME	"ofw"
+
+#define MAX_NAME_LENGTH 1024
+
+static void syntax_print(void);
+static errno_t ofw_print_subtree(const char *, bool);
+static errno_t ofw_print_properties(const char *);
+
+int main(int argc, char **argv)
+{
+	errno_t rc;
+	const char *path = "/";
+	bool verbose = false;
+
+	--argc;
+	++argv;
+
+	while (argc > 0 && argv[0][0] == '-') {
+		if (str_cmp(argv[0], "-p") == 0) {
+			--argc;
+			++argv;
+			if (argc < 1) {
+				printf("Option argument missing.\n");
+				return 1;
+			}
+
+			path = argv[0];
+			--argc;
+			++argv;
+		} else if (str_cmp(argv[0], "-v") == 0) {
+			--argc;
+			++argv;
+
+			verbose = true;
+		} else {
+			syntax_print();
+			return 1;
+		}
+	}
+
+	if (argc != 0) {
+		syntax_print();
+		return 1;
+	}
+
+	rc = ofw_print_subtree(path, verbose);
+	if (rc != EOK)
+		return 1;
+
+	return 0;
+}
+
+static void syntax_print(void)
+{
+	printf("syntax: %s [<options>]\n", NAME);
+	printf("options:\n"
+	    "\t-v        Verbose mode (print properties and their values)\n"
+	    "\t-p <path> Only print devices under <path>\n");
+}
+
+/** List OpenFirmware device nodes under a specific node.
+ *
+ * @param path Path of node where to start printing
+ * @param verbose If @c true, print properties
+ * @return EOK on success or an error code
+ */
+static errno_t ofw_print_subtree(const char *path, bool verbose)
+{
+	char *subpath;
+	ofw_child_it_t it;
+	errno_t rc;
+
+	printf("%s\n", path);
+
+	if (verbose) {
+		rc = ofw_print_properties(path);
+		if (rc != EOK)
+			return rc;
+	}
+
+	rc = ofw_child_it_first(&it, path);
+	while (!ofw_child_it_end(&it)) {
+		rc = ofw_child_it_get_path(&it, &subpath);
+		if (rc != EOK)
+			goto error;
+
+		rc = ofw_print_subtree(subpath, verbose);
+		if (rc != EOK)
+			goto error;
+
+		free(subpath);
+		subpath = NULL;
+
+		ofw_child_it_next(&it);
+	}
+
+	ofw_child_it_fini(&it);
+	return EOK;
+error:
+	if (subpath != NULL)
+		free(subpath);
+	ofw_child_it_fini(&it);
+	return rc;
+}
+
+static errno_t ofw_print_properties(const char *ofwpath)
+{
+	const char *propname;
+	const uint8_t *propval;
+	size_t val_sz;
+	ofw_prop_it_t it;
+	errno_t rc;
+	size_t i;
+
+	rc = ofw_prop_it_first(&it, ofwpath);
+	if (rc != EOK)
+		return rc;
+
+	while (!ofw_prop_it_end(&it)) {
+		propname = ofw_prop_it_get_name(&it);
+		printf("'%s' =", propname);
+
+		propval = ofw_prop_it_get_data(&it, &val_sz);
+
+		for (i = 0; i < val_sz; i++)
+			printf(" %02x", propval[i]);
+
+		printf(" ('%*s')\n", (int)val_sz - 1, (char *)propval);
+		ofw_prop_it_next(&it);
+	}
+
+	ofw_prop_it_fini(&it);
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/meson.build
===================================================================
--- uspace/lib/meson.build	(revision 7e6603784b2bbda102aa3edc13f5c1d8326b4a66)
+++ uspace/lib/meson.build	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -72,4 +72,5 @@
 	'minix',
 	'nettl',
+	'ofw',
 	'pcm',
 	'pcut',
Index: uspace/lib/ofw/doc/doxygroups.h
===================================================================
--- uspace/lib/ofw/doc/doxygroups.h	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
+++ uspace/lib/ofw/doc/doxygroups.h	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -0,0 +1,3 @@
+/** @addtogroup libofw libofw
+ * @ingroup libs
+ */
Index: uspace/lib/ofw/include/ofw.h
===================================================================
--- uspace/lib/ofw/include/ofw.h	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
+++ uspace/lib/ofw/include/ofw.h	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2023 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/** @addtogroup libofw
+ * @{
+ */
+/**
+ * @file OpenFirmware device tree access
+ */
+
+#ifndef _OFW_H
+#define _OFW_H
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <types/ofw.h>
+
+extern errno_t ofw_child_it_first(ofw_child_it_t *, const char *);
+extern void ofw_child_it_next(ofw_child_it_t *);
+extern bool ofw_child_it_end(ofw_child_it_t *);
+extern const char *ofw_child_it_get_name(ofw_child_it_t *);
+extern errno_t ofw_child_it_get_path(ofw_child_it_t *, char **);
+extern void ofw_child_it_fini(ofw_child_it_t *);
+
+extern errno_t ofw_prop_it_first(ofw_prop_it_t *, const char *);
+extern void ofw_prop_it_next(ofw_prop_it_t *);
+extern bool ofw_prop_it_end(ofw_prop_it_t *);
+extern const char *ofw_prop_it_get_name(ofw_prop_it_t *);
+extern const void *ofw_prop_it_get_data(ofw_prop_it_t *, size_t *);
+extern void ofw_prop_it_fini(ofw_prop_it_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/ofw/include/types/ofw.h
===================================================================
--- uspace/lib/ofw/include/types/ofw.h	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
+++ uspace/lib/ofw/include/types/ofw.h	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/** @addtogroup libofw
+ * @{
+ */
+/**
+ * @file OpenFirmware device tree access
+ */
+
+#ifndef _TYPES_OFW_H
+#define _TYPES_OFW_H
+
+#include <stddef.h>
+
+/** OpenFirmware child iterator */
+typedef struct {
+	/** OpenFirmware path of the parent */
+	char *ofwpath;
+	/** Key data from sysinfo */
+	char *keys;
+	/** Size of key data */
+	size_t keys_sz;
+	/** Byte offset of current child in @c keys */
+	size_t pos;
+} ofw_child_it_t;
+
+/** OpenFirmware property iterator */
+typedef struct {
+	/** Data from sysinfo */
+	void *data;
+	/** Size of data from sysinfo */
+	size_t data_sz;
+	/** Byte offset of current property in @c data */
+	size_t pos;
+} ofw_prop_it_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/ofw/meson.build
===================================================================
--- uspace/lib/ofw/meson.build	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
+++ uspace/lib/ofw/meson.build	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2023 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - 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.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+#
+
+src = files(
+	'src/ofw.c',
+)
Index: uspace/lib/ofw/src/ofw.c
===================================================================
--- uspace/lib/ofw/src/ofw.c	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
+++ uspace/lib/ofw/src/ofw.c	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2023 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/** @addtogroup libofw
+ * @{
+ */
+/**
+ * @file OpenFirmware device tree access
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <ofw.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <str.h>
+#include <sysinfo.h>
+
+/** Convert OpenFirmware path to sysinfo path.
+ *
+ * @param ofwpath OpenFirmware path
+ * @param sipath place to store pointer to newly allocated sysinfo path
+ * @return EOK on success, ENOMEM if out of memory
+ */
+static errno_t ofw_path_to_sipath(const char *ofwpath, char **sipath)
+{
+	int rv;
+	size_t size;
+	size_t i;
+
+	if (str_cmp(ofwpath, "/") == 0)
+		ofwpath = "";
+
+	/* Append path to firmware.ofw */
+	rv = asprintf(sipath, "firmware.ofw%s", ofwpath);
+	if (rv < 0)
+		return ENOMEM;
+
+	/* Replace '/' with '.' */
+	size = str_size(*sipath);
+	for (i = 0; i < size; i++)
+		if ((*sipath)[i] == '/')
+			(*sipath)[i] = '.';
+
+	return EOK;
+}
+
+/** Initialize child iterator with first child entry.
+ *
+ * Initialize the child iterator and make it point to the first child
+ * of the specified OpenFirmware device node.
+ *
+ * @param it Child iterator to initialize
+ * @param ofwpath OpenFirmware path of the parent node
+ */
+errno_t ofw_child_it_first(ofw_child_it_t *it, const char *ofwpath)
+{
+	errno_t rc;
+	char *sipath = NULL;
+
+	it->ofwpath = NULL;
+	it->keys = NULL;
+	it->keys_sz = 0;
+	it->pos = 0;
+
+	rc = ofw_path_to_sipath(ofwpath, &sipath);
+	if (rc != EOK)
+		goto error;
+
+	if (str_cmp(ofwpath, "/") == 0) {
+		it->ofwpath = str_dup("");
+	} else {
+		it->ofwpath = str_dup(ofwpath);
+	}
+
+	if (it->ofwpath == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	it->keys = sysinfo_get_keys(sipath, &it->keys_sz);
+	if (it->keys == NULL) {
+		rc = ENOENT;
+		goto error;
+	}
+
+	return EOK;
+error:
+	if (sipath != NULL)
+		free(sipath);
+
+	if (it->ofwpath != NULL) {
+		free(it->ofwpath);
+		it->ofwpath = NULL;
+	}
+
+	return rc;
+}
+
+/** Move child iterator to the next child.
+ *
+ * @param it Child iterator
+ */
+void ofw_child_it_next(ofw_child_it_t *it)
+{
+	size_t adj;
+
+	assert(!ofw_child_it_end(it));
+
+	adj = str_nsize(it->keys + it->pos, it->keys_sz - it->pos) + 1;
+	assert(it->pos + adj <= it->keys_sz);
+	it->pos += adj;
+}
+
+/** Determine if there are no more child nodes.
+ *
+ * @param it Child iterator
+ * @return @c true iff iterator is beyond the last entry
+ */
+bool ofw_child_it_end(ofw_child_it_t *it)
+{
+	return it->pos >= it->keys_sz;
+}
+
+/** Get child name from iterator.
+ *
+ * @param it Child iterator
+ * @return Child name (valid until next operation on @a it
+ */
+const char *ofw_child_it_get_name(ofw_child_it_t *it)
+{
+	assert(!ofw_child_it_end(it));
+	return it->keys + it->pos;
+}
+
+/** Get child path from iterator.
+ *
+ * @param it Child iterator
+ * @param rpath Place to store pointer to allocated OpenFirmware path
+ * @return @c EOK on success or an error code
+ */
+errno_t ofw_child_it_get_path(ofw_child_it_t *it, char **rpath)
+{
+	const char *name;
+	int rv;
+
+	assert(!ofw_child_it_end(it));
+	name = ofw_child_it_get_name(it);
+
+	rv = asprintf(rpath, "%s/%s", it->ofwpath, name);
+	if (rv < 0)
+		return ENOMEM;
+
+	return EOK;
+}
+
+/** Finalize child iterator.
+ *
+ * This must be called after using a child iterator.
+ *
+ * @param it Child iterator
+ */
+void ofw_child_it_fini(ofw_child_it_t *it)
+{
+	free(it->ofwpath);
+	free(it->keys);
+	it->keys = NULL;
+	it->keys_sz = 0;
+}
+
+/** Initialize property iterator with property.
+ *
+ * Initialize the property iterator and make it point to the first property
+ * of the specified OpenFirmware device node.
+ *
+ * @param it Property iterator to initialize
+ * @param ofwpath OpenFirmware path of the node
+ */
+errno_t ofw_prop_it_first(ofw_prop_it_t *it, const char *ofwpath)
+{
+	errno_t rc;
+	char *sipath;
+
+	it->data = NULL;
+	it->data_sz = 0;
+	it->pos = 0;
+
+	rc = ofw_path_to_sipath(ofwpath, &sipath);
+	if (rc != EOK)
+		goto error;
+
+	it->data = sysinfo_get_data(sipath, &it->data_sz);
+	if (it->data == NULL) {
+		rc = ENOENT;
+		goto error;
+	}
+
+	return EOK;
+error:
+	if (sipath != NULL)
+		free(sipath);
+	return rc;
+}
+
+/** Move property iterator to the next property.
+ *
+ * @param it Child iterator
+ */
+void ofw_prop_it_next(ofw_prop_it_t *it)
+{
+	size_t cur_size;
+	size_t value_size;
+
+	cur_size = str_nsize(it->data + it->pos, it->data_sz - it->pos);
+	if (((char *) it->data)[it->pos + cur_size] != 0)
+		return;
+
+	it->pos += cur_size + 1;
+
+	/* Process value size */
+	memcpy(&value_size, it->data + it->pos, sizeof(value_size));
+
+	it->pos += sizeof(value_size);
+	if ((it->pos >= it->data_sz) || (it->pos + value_size > it->data_sz))
+		return;
+
+	it->pos += value_size;
+}
+
+/** Determine if there are no more properties.
+ *
+ * @param it Property iterator
+ * @return @c true iff iterator is beyond the last entry
+ */
+bool ofw_prop_it_end(ofw_prop_it_t *it)
+{
+	return it->pos >= it->data_sz;
+}
+
+/** Get property name from iterator.
+ *
+ * @param it Child iterator
+ * @return Property name (valid until next operation on @a it
+ */
+const char *ofw_prop_it_get_name(ofw_prop_it_t *it)
+{
+	assert(!ofw_prop_it_end(it));
+	return it->data + it->pos;
+}
+
+/** Get property data from iterator.
+ *
+ * @param it Property iterator
+ * @param rsize Place to store size of data
+ * @return Pointer to data
+ */
+const void *ofw_prop_it_get_data(ofw_prop_it_t *it, size_t *rsize)
+{
+	size_t cur_size;
+	size_t value_size;
+	size_t pos;
+
+	assert(!ofw_prop_it_end(it));
+	pos = it->pos;
+
+	cur_size = str_nsize(it->data + pos, it->data_sz - pos);
+	if (((char *) it->data)[pos + cur_size] != 0)
+		return NULL;
+
+	pos += cur_size + 1;
+
+	/* Process value size */
+	memcpy(&value_size, it->data + pos, sizeof(value_size));
+	pos += sizeof(value_size);
+
+	*rsize = value_size;
+	return it->data + pos;
+}
+
+/** Finalize property iterator.
+ *
+ * This must be called after using a child iterator.
+ *
+ * @param it Child iterator
+ */
+void ofw_prop_it_fini(ofw_prop_it_t *it)
+{
+	free(it->data);
+	it->data = NULL;
+	it->data_sz = 0;
+	it->pos = 0;
+}
+
+/** @}
+ */
Index: uspace/meson.build
===================================================================
--- uspace/meson.build	(revision 7e6603784b2bbda102aa3edc13f5c1d8326b4a66)
+++ uspace/meson.build	(revision 4d58bac13740feb52caf7dd9407350d098012a56)
@@ -93,4 +93,5 @@
 	language = 'c'
 	installed_data = []
+	platform_specific = false
 
 	subdir(appdirs.get('subdir'))
@@ -106,8 +107,10 @@
 	else
 		#
-		# Servers and applications are installed all or
-		# based on rd_essential in case of barebone build
+		# Servers and applications are installed all (unless
+		# platform-specific) or based on rd_essential in case
+		# of barebone build or platform-specific
 		#
-		install = not CONFIG_BAREBONE or rd_essential.contains(dir)
+		install = (not CONFIG_BAREBONE and not platform_specific) \
+		    or rd_essential.contains(dir)
 	endif
 
