Index: uspace/srv/bd/hr/hr.c
===================================================================
--- uspace/srv/bd/hr/hr.c	(revision e0b77635017006b1dfe6a20ca68c086548186884)
+++ uspace/srv/bd/hr/hr.c	(revision da5c2573ab7873f71a08944e3ac7c0fe455eb6bd)
@@ -36,5 +36,4 @@
 #include <async.h>
 #include <bd_srv.h>
-#include <block.h>
 #include <errno.h>
 #include <hr.h>
@@ -59,36 +58,4 @@
 static service_id_t ctl_sid;
 
-errno_t hr_init_devs(hr_volume_t *vol)
-{
-	log_msg(LOG_DEFAULT, LVL_NOTE, "hr_init_devs()");
-
-	errno_t rc;
-	size_t i;
-
-	for (i = 0; i < vol->dev_no; i++) {
-		rc = block_init(vol->devs[i]);
-		log_msg(LOG_DEFAULT, LVL_DEBUG,
-		    "hr_init_devs(): initing (%" PRIun ")", vol->devs[i]);
-		if (rc != EOK) {
-			log_msg(LOG_DEFAULT, LVL_ERROR,
-			    "hr_init_devs(): initing (%" PRIun ") failed, aborting",
-			    vol->devs[i]);
-			break;
-		}
-	}
-
-	return rc;
-}
-
-void hr_fini_devs(hr_volume_t *vol)
-{
-	log_msg(LOG_DEFAULT, LVL_NOTE, "hr_fini_devs()");
-
-	size_t i;
-
-	for (i = 0; i < vol->dev_no; i++)
-		block_fini(vol->devs[i]);
-}
-
 static void hr_create_srv(ipc_call_t *icall)
 {
@@ -211,5 +178,5 @@
 	hr_volume_t *vol;
 
-	sysarg_t svc_id = ipc_get_arg2(icall);
+	service_id_t svc_id = ipc_get_arg2(icall);
 
 	if (svc_id == ctl_sid) {
Index: uspace/srv/bd/hr/meson.build
===================================================================
--- uspace/srv/bd/hr/meson.build	(revision e0b77635017006b1dfe6a20ca68c086548186884)
+++ uspace/srv/bd/hr/meson.build	(revision da5c2573ab7873f71a08944e3ac7c0fe455eb6bd)
@@ -28,3 +28,3 @@
 
 deps = [ 'block', 'device' ]
-src = files('hr.c', 'raid1.c')
+src = files('hr.c', 'raid1.c', 'util.c')
Index: uspace/srv/bd/hr/raid1.c
===================================================================
--- uspace/srv/bd/hr/raid1.c	(revision e0b77635017006b1dfe6a20ca68c086548186884)
+++ uspace/srv/bd/hr/raid1.c	(revision da5c2573ab7873f71a08944e3ac7c0fe455eb6bd)
@@ -49,4 +49,5 @@
 
 #include "var.h"
+#include "util.h"
 
 extern fibril_mutex_t big_lock;
@@ -160,10 +161,8 @@
 
 	errno_t rc;
-	service_id_t new_id;
-	category_id_t cat_id;
 
 	rc = hr_init_devs(new_volume);
 	if (rc != EOK)
-		goto end;
+		return rc;
 
 	bd_srvs_init(&new_volume->hr_bds);
@@ -171,35 +170,11 @@
 	new_volume->hr_bds.sarg = new_volume;
 
-	rc = loc_service_register(hr_srv, new_volume->devname, &new_id);
+	rc = hr_register_volume(new_volume);
 	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR,
-		    "unable to register device \"%s\": %s\n",
-		    new_volume->devname, str_error(rc));
-
-		goto error;
+		hr_fini_devs(new_volume);
+		return rc;
 	}
 
-	rc = loc_category_get_id("raid", &cat_id, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR,
-		    "failed resolving category \"raid\": %s\n", str_error(rc));
-		goto error;
-	}
-
-	rc = loc_service_add_to_cat(hr_srv, new_id, cat_id);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR,
-		    "failed adding \"%s\" to category \"raid\": %s\n",
-		    new_volume->devname, str_error(rc));
-		goto error;
-	}
-
-	new_volume->svc_id = new_id;
-
 	return EOK;
-error:
-	hr_fini_devs(new_volume);
-end:
-	return rc;
 }
 
Index: uspace/srv/bd/hr/util.c
===================================================================
--- uspace/srv/bd/hr/util.c	(revision da5c2573ab7873f71a08944e3ac7c0fe455eb6bd)
+++ uspace/srv/bd/hr/util.c	(revision da5c2573ab7873f71a08944e3ac7c0fe455eb6bd)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2024 Miroslav Cimerman
+ * 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 hr
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <block.h>
+#include <errno.h>
+#include <hr.h>
+#include <io/log.h>
+#include <loc.h>
+#include <str_error.h>
+
+#include "var.h"
+#include "util.h"
+
+extern loc_srv_t *hr_srv;
+
+errno_t hr_init_devs(hr_volume_t *vol)
+{
+	log_msg(LOG_DEFAULT, LVL_NOTE, "hr_init_devs()");
+
+	errno_t rc;
+	size_t i;
+
+	for (i = 0; i < vol->dev_no; i++) {
+		rc = block_init(vol->devs[i]);
+		log_msg(LOG_DEFAULT, LVL_DEBUG,
+		    "hr_init_devs(): initing (%" PRIun ")", vol->devs[i]);
+		if (rc != EOK) {
+			log_msg(LOG_DEFAULT, LVL_ERROR,
+			    "hr_init_devs(): initing (%" PRIun ") failed, aborting",
+			    vol->devs[i]);
+			break;
+		}
+	}
+
+	return rc;
+}
+
+void hr_fini_devs(hr_volume_t *vol)
+{
+	log_msg(LOG_DEFAULT, LVL_NOTE, "hr_fini_devs()");
+
+	size_t i;
+
+	for (i = 0; i < vol->dev_no; i++)
+		block_fini(vol->devs[i]);
+}
+
+errno_t hr_register_volume(hr_volume_t *new_volume)
+{
+	errno_t rc;
+	service_id_t new_id;
+	category_id_t cat_id;
+
+	rc = loc_service_register(hr_srv, new_volume->devname, &new_id);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR,
+		    "unable to register device \"%s\": %s\n",
+		    new_volume->devname, str_error(rc));
+		goto error;
+	}
+
+	rc = loc_category_get_id("raid", &cat_id, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR,
+		    "failed resolving category \"raid\": %s\n", str_error(rc));
+		goto error;
+	}
+
+	rc = loc_service_add_to_cat(hr_srv, new_id, cat_id);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR,
+		    "failed adding \"%s\" to category \"raid\": %s\n",
+		    new_volume->devname, str_error(rc));
+		goto error;
+	}
+
+	new_volume->svc_id = new_id;
+
+error:
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/srv/bd/hr/util.h
===================================================================
--- uspace/srv/bd/hr/util.h	(revision da5c2573ab7873f71a08944e3ac7c0fe455eb6bd)
+++ uspace/srv/bd/hr/util.h	(revision da5c2573ab7873f71a08944e3ac7c0fe455eb6bd)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 Miroslav Cimerman
+ * 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 hr
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef _HR_UTIL_H
+#define _HR_UTIL_H
+
+#include <errno.h>
+
+#include "var.h"
+
+extern errno_t hr_init_devs(hr_volume_t *);
+extern void hr_fini_devs(hr_volume_t *);
+extern errno_t hr_register_volume(hr_volume_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/bd/hr/var.h
===================================================================
--- uspace/srv/bd/hr/var.h	(revision e0b77635017006b1dfe6a20ca68c086548186884)
+++ uspace/srv/bd/hr/var.h	(revision da5c2573ab7873f71a08944e3ac7c0fe455eb6bd)
@@ -37,4 +37,8 @@
 #define _HR_VAR_H
 
+#include <bd_srv.h>
+#include <errno.h>
+#include <hr.h>
+
 #define NAME "hr"
 
@@ -59,4 +63,5 @@
 extern void hr_fini_devs(hr_volume_t *);
 
+extern errno_t hr_raid0_create(hr_volume_t *);
 extern errno_t hr_raid1_create(hr_volume_t *);
 
