mboxd: Add a backend abstraction layer to mboxd.

Introduce a backend abstraction, enabling multiple implementations to be
compiled in at once. This change formally abstracts the two existing
backends, mtd and vpnor.

With the backend abstraction in place, subsequent backends are easier to
implement.

This change is based of Evan's work and he retains authorship credit. I
(AJ) have reworked the patch to pass the vpnor tests, refactored some
parts to enable broader use of const structures and others to clarify
the initialisation sequences.

Due to the existing lack of abstraction the patch has unfortunately
wide-ranging impacts. I've whittled it down as much as I consider
reasonable.

Change-Id: I29984a36dae4ea86ec00b853d2a756f0b9afb3ec
Signed-off-by: Evan Lojewski <github@meklort.com>
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/vpnor/test/Makefile.am.include b/vpnor/test/Makefile.am.include
index 5ff4dcc..0600969 100644
--- a/vpnor/test/Makefile.am.include
+++ b/vpnor/test/Makefile.am.include
@@ -1,7 +1,4 @@
-TEST_MBOX_VPNOR_SRCS = \
-	common.c \
-	vpnor/pnor_partition_table.cpp \
-	%reldir%/tmpd.cpp
+TEST_MOCK_VPNOR_SRCS = $(TEST_MOCK_CORE)
 
 TEST_MBOX_VPNOR_INTEG_SRCS = \
 	common.c \
@@ -9,9 +6,8 @@
 	transport_mbox.c \
 	windows.c \
 	lpc.c \
-	vpnor/lpc_reset.cpp \
+	vpnor/backend.cpp \
 	vpnor/mboxd_pnor_partition_table.cpp \
-	vpnor/flash.cpp \
 	vpnor/pnor_partition.cpp \
 	vpnor/pnor_partition_table.cpp \
 	%reldir%/tmpd.cpp
@@ -22,14 +18,14 @@
 	$(PHOSPHOR_DBUS_INTERFACES_LIBS)
 
 vpnor_test_create_pnor_partition_table_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/create_pnor_partition_table.cpp
 vpnor_test_create_pnor_partition_table_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_create_pnor_partition_table_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_create_read_window_partition_exists_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/create_read_window_partition_exists.cpp
 vpnor_test_create_read_window_partition_exists_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
@@ -106,63 +102,63 @@
 vpnor_test_toc_flags_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_toc_overlap_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/toc_overlap.cpp
 vpnor_test_toc_overlap_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_toc_overlap_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_toc_lookup_found_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/toc_lookup_found.cpp
 vpnor_test_toc_lookup_found_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_toc_lookup_found_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_toc_lookup_failed_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/toc_lookup_failed.cpp
 vpnor_test_toc_lookup_failed_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_toc_lookup_failed_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_toc_missing_file_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/toc_missing_file.cpp
 vpnor_test_toc_missing_file_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_toc_missing_file_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_create_read_window_oob_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/create_read_window_oob.cpp
 vpnor_test_create_read_window_oob_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_create_read_window_oob_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_create_read_window_toc_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/create_read_window_toc.cpp
 vpnor_test_create_read_window_toc_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_create_read_window_toc_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_create_read_window_straddle_partitions_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/create_read_window_straddle_partitions.cpp
 vpnor_test_create_read_window_straddle_partitions_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_create_read_window_straddle_partitions_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_create_read_window_partition_invalid_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/create_read_window_partition_invalid.cpp
 vpnor_test_create_read_window_partition_invalid_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_create_read_window_partition_invalid_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_read_patch_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/read_patch.cpp
 vpnor_test_read_patch_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
@@ -176,56 +172,56 @@
 vpnor_test_write_patch_resize_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_dump_flash_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/dump_flash.cpp
 vpnor_test_dump_flash_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_dump_flash_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_create_read_window_size_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/create_read_window_size.cpp
 vpnor_test_create_read_window_size_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_create_read_window_size_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_create_read_window_remap_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/create_read_window_remap.cpp
 vpnor_test_create_read_window_remap_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_create_read_window_remap_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_create_write_window_ro_partition_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/create_write_window_ro_partition.cpp
 vpnor_test_create_write_window_ro_partition_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_create_write_window_ro_partition_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_create_write_window_rw_partition_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/create_write_window_rw_partition.cpp
 vpnor_test_create_write_window_rw_partition_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_create_write_window_rw_partition_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_create_write_window_unmapped_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/create_write_window_unmapped.cpp
 vpnor_test_create_write_window_unmapped_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_create_write_window_unmapped_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_write_toc_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/write_toc.cpp
 vpnor_test_write_toc_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 vpnor_test_write_toc_LDADD = $(VPNOR_LDADD)
 
 vpnor_test_force_readonly_toc_SOURCES = \
-	$(TEST_MOCK_SRCS) \
+	$(TEST_MOCK_VPNOR_SRCS) \
 	$(TEST_MBOX_VPNOR_INTEG_SRCS) \
 	%reldir%/force_readonly_toc.cpp
 vpnor_test_force_readonly_toc_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
diff --git a/vpnor/test/create_pnor_partition_table.cpp b/vpnor/test/create_pnor_partition_table.cpp
index cdbe8b6..f198f29 100644
--- a/vpnor/test/create_pnor_partition_table.cpp
+++ b/vpnor/test/create_pnor_partition_table.cpp
@@ -34,9 +34,9 @@
 
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    const openpower::virtual_pnor::partition::Table table(ctx);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
+    const openpower::virtual_pnor::partition::Table table(&ctx->backend);
 
     pnor_partition_table expectedTable{};
     expectedTable.data.magic = PARTITION_HEADER_MAGIC;
diff --git a/vpnor/test/create_read_window_oob.cpp b/vpnor/test/create_read_window_oob.cpp
index 240c10e..d1e7e64 100644
--- a/vpnor/test/create_read_window_oob.cpp
+++ b/vpnor/test/create_read_window_oob.cpp
@@ -48,9 +48,8 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    init_vpnor_from_paths(ctx);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
 
     rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == 1);
diff --git a/vpnor/test/create_read_window_partition_exists.cpp b/vpnor/test/create_read_window_partition_exists.cpp
index d3532ec..7ff3018 100644
--- a/vpnor/test/create_read_window_partition_exists.cpp
+++ b/vpnor/test/create_read_window_partition_exists.cpp
@@ -53,13 +53,11 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
 
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
     root.write("HBB", data, sizeof(data));
 
-    init_vpnor_from_paths(ctx);
-
     int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == 1);
 
diff --git a/vpnor/test/create_read_window_partition_invalid.cpp b/vpnor/test/create_read_window_partition_invalid.cpp
index 36431d3..4d28b2c 100644
--- a/vpnor/test/create_read_window_partition_invalid.cpp
+++ b/vpnor/test/create_read_window_partition_invalid.cpp
@@ -44,14 +44,14 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    init_vpnor_from_paths(ctx);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
 
     rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == 1);
 
     rc = mbox_command_dispatch(ctx, create_read_window,
                                sizeof(create_read_window));
+
     return !(rc == 1);
 }
diff --git a/vpnor/test/create_read_window_remap.cpp b/vpnor/test/create_read_window_remap.cpp
index 7a11053..f81d1bc 100644
--- a/vpnor/test/create_read_window_remap.cpp
+++ b/vpnor/test/create_read_window_remap.cpp
@@ -47,9 +47,8 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    init_vpnor_from_paths(ctx);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
 
     int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == 1);
diff --git a/vpnor/test/create_read_window_size.cpp b/vpnor/test/create_read_window_size.cpp
index 6ea11f1..4e8cb5d 100644
--- a/vpnor/test/create_read_window_size.cpp
+++ b/vpnor/test/create_read_window_size.cpp
@@ -56,9 +56,8 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    init_vpnor_from_paths(ctx);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
 
     int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == 1);
diff --git a/vpnor/test/create_read_window_straddle_partitions.cpp b/vpnor/test/create_read_window_straddle_partitions.cpp
index bc963dd..bdc3fa5 100644
--- a/vpnor/test/create_read_window_straddle_partitions.cpp
+++ b/vpnor/test/create_read_window_straddle_partitions.cpp
@@ -52,9 +52,8 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    init_vpnor_from_paths(ctx);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
 
     int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == 1);
diff --git a/vpnor/test/create_read_window_toc.cpp b/vpnor/test/create_read_window_toc.cpp
index fee61ca..7571f37 100644
--- a/vpnor/test/create_read_window_toc.cpp
+++ b/vpnor/test/create_read_window_toc.cpp
@@ -55,15 +55,13 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    vpnor::partition::Table table(ctx);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
+    vpnor::partition::Table table(&ctx->backend);
 
     /* Make sure the ToC exactly fits in the space allocated for it */
     assert(table.capacity() == TOC_PART_SIZE);
 
-    init_vpnor_from_paths(ctx);
-
     rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == 1);
 
diff --git a/vpnor/test/create_write_window_ro_partition.cpp b/vpnor/test/create_write_window_ro_partition.cpp
index 5cc19ca..59d4a0d 100644
--- a/vpnor/test/create_write_window_ro_partition.cpp
+++ b/vpnor/test/create_write_window_ro_partition.cpp
@@ -45,11 +45,9 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
 
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-
-    init_vpnor_from_paths(ctx);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
 
     int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == 1);
diff --git a/vpnor/test/create_write_window_rw_partition.cpp b/vpnor/test/create_write_window_rw_partition.cpp
index 879fd85..ed6f3dd 100644
--- a/vpnor/test/create_write_window_rw_partition.cpp
+++ b/vpnor/test/create_write_window_rw_partition.cpp
@@ -45,11 +45,9 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
 
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-
-    init_vpnor_from_paths(ctx);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
 
     int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == 1);
diff --git a/vpnor/test/create_write_window_unmapped.cpp b/vpnor/test/create_write_window_unmapped.cpp
index 76694fc..d7f76fd 100644
--- a/vpnor/test/create_write_window_unmapped.cpp
+++ b/vpnor/test/create_write_window_unmapped.cpp
@@ -46,11 +46,9 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
 
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-
-    init_vpnor_from_paths(ctx);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
 
     int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == MBOX_R_SUCCESS);
diff --git a/vpnor/test/dump_flash.cpp b/vpnor/test/dump_flash.cpp
index 5179b7c..f285a61 100644
--- a/vpnor/test/dump_flash.cpp
+++ b/vpnor/test/dump_flash.cpp
@@ -68,9 +68,8 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
 
-    tctx->ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-    test::VpnorRoot root(tctx->ctx, toc, BLOCK_SIZE);
-    init_vpnor_from_paths(tctx->ctx);
+    tctx->ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+    test::VpnorRoot root(&tctx->ctx->backend, toc, BLOCK_SIZE);
 
     rc = mbox_command_dispatch(tctx->ctx, get_info, sizeof(get_info));
     assert(rc == 1);
diff --git a/vpnor/test/force_readonly_toc.cpp b/vpnor/test/force_readonly_toc.cpp
index 8d3bec1..465adad 100644
--- a/vpnor/test/force_readonly_toc.cpp
+++ b/vpnor/test/force_readonly_toc.cpp
@@ -52,14 +52,12 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    vpnor::partition::Table table(ctx);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
+    vpnor::partition::Table table(&ctx->backend);
 
     assert(table.capacity() == TOC_PART_SIZE);
 
-    init_vpnor_from_paths(ctx);
-
     rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == MBOX_R_SUCCESS);
 
diff --git a/vpnor/test/read_patch.cpp b/vpnor/test/read_patch.cpp
index 631a23c..4d541f6 100644
--- a/vpnor/test/read_patch.cpp
+++ b/vpnor/test/read_patch.cpp
@@ -47,8 +47,8 @@
 
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
 
     // PATCH_SIZE is smaller than the size of the partition we defined. This
     // test ensures that mboxd will behave correctly when we request an offset
@@ -57,8 +57,6 @@
     std::vector<uint8_t> patch(PATCH_SIZE, 0xff);
     root.patch("ONE", patch.data(), patch.size());
 
-    init_vpnor_from_paths(ctx);
-
     int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == 1);
 
diff --git a/vpnor/test/tmpd.hpp b/vpnor/test/tmpd.hpp
index 7386f2f..f6ea7c9 100644
--- a/vpnor/test/tmpd.hpp
+++ b/vpnor/test/tmpd.hpp
@@ -4,6 +4,7 @@
 #include "config.h"
 
 extern "C" {
+#include "backend.h"
 #include "mboxd.h"
 }
 
@@ -28,8 +29,9 @@
 {
   public:
     template <std::size_t N>
-    VpnorRoot(struct mbox_context* ctx, const std::string (&toc)[N],
-              size_t blockSize)
+    VpnorRoot(struct backend* backend, const std::string (&toc)[N],
+              size_t blockSize) :
+        backend(backend)
     {
         char tmplt[] = "/tmp/vpnor_root.XXXXXX";
         char* tmpdir = mkdtemp(tmplt);
@@ -58,14 +60,21 @@
             std::ofstream(tocFilePath, std::ofstream::app) << line << "\n";
         }
 
-        strncpy(ctx->paths.ro_loc, ro().c_str(), PATH_MAX - 1);
-        ctx->paths.ro_loc[PATH_MAX - 1] = '\0';
-        strncpy(ctx->paths.rw_loc, rw().c_str(), PATH_MAX - 1);
-        ctx->paths.rw_loc[PATH_MAX - 1] = '\0';
-        strncpy(ctx->paths.prsv_loc, prsv().c_str(), PATH_MAX - 1);
-        ctx->paths.prsv_loc[PATH_MAX - 1] = '\0';
-        strncpy(ctx->paths.patch_loc, patch().c_str(), PATH_MAX - 1);
-        ctx->paths.patch_loc[PATH_MAX - 1] = '\0';
+        vpnor_partition_paths paths{};
+
+        snprintf(paths.ro_loc, PATH_MAX - 1, "%s/ro", root.c_str());
+        paths.ro_loc[PATH_MAX - 1] = '\0';
+        snprintf(paths.rw_loc, PATH_MAX - 1, "%s/rw", root.c_str());
+        paths.rw_loc[PATH_MAX - 1] = '\0';
+        snprintf(paths.prsv_loc, PATH_MAX - 1, "%s/prsv", root.c_str());
+        paths.prsv_loc[PATH_MAX - 1] = '\0';
+        snprintf(paths.patch_loc, PATH_MAX - 1, "%s/patch", root.c_str());
+        paths.patch_loc[PATH_MAX - 1] = '\0';
+
+        if (backend_probe_vpnor(backend, &paths))
+        {
+            throw std::system_error(errno, std::system_category());
+        }
     }
 
     VpnorRoot(const VpnorRoot&) = delete;
@@ -75,6 +84,7 @@
 
     ~VpnorRoot()
     {
+        backend_free(backend);
         fs::remove_all(root);
     }
     fs::path ro()
@@ -97,6 +107,7 @@
     size_t patch(const std::string& name, const void* data, size_t len);
 
   private:
+    struct backend* backend;
     fs::path root;
     const std::string attributes[4] = {"ro", "rw", "prsv", "patch"};
 };
diff --git a/vpnor/test/toc_lookup_failed.cpp b/vpnor/test/toc_lookup_failed.cpp
index bb07725..cb56e51 100644
--- a/vpnor/test/toc_lookup_failed.cpp
+++ b/vpnor/test/toc_lookup_failed.cpp
@@ -37,10 +37,10 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
 
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    vpnor::partition::Table table(ctx);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
+    vpnor::partition::Table table(&ctx->backend);
 
     try
     {
diff --git a/vpnor/test/toc_lookup_found.cpp b/vpnor/test/toc_lookup_found.cpp
index fccee0c..b8c879c 100644
--- a/vpnor/test/toc_lookup_found.cpp
+++ b/vpnor/test/toc_lookup_found.cpp
@@ -37,10 +37,10 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
 
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    vpnor::partition::Table table(ctx);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
+    vpnor::partition::Table table(&ctx->backend);
 
     const struct pnor_partition& part = table.partition("TWO");
     assert(part.data.id == 2);
diff --git a/vpnor/test/toc_missing_file.cpp b/vpnor/test/toc_missing_file.cpp
index 6b7e068..95147c0 100644
--- a/vpnor/test/toc_missing_file.cpp
+++ b/vpnor/test/toc_missing_file.cpp
@@ -37,15 +37,15 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
 
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
 
     fs::remove(root.ro() / "TWO");
 
     try
     {
-        vpnor::partition::Table table(ctx);
+        vpnor::partition::Table table(&ctx->backend);
     }
     catch (vpnor::InvalidTocEntry& e)
     {
diff --git a/vpnor/test/toc_overlap.cpp b/vpnor/test/toc_overlap.cpp
index a7ac20d..18b7151 100644
--- a/vpnor/test/toc_overlap.cpp
+++ b/vpnor/test/toc_overlap.cpp
@@ -36,15 +36,13 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(MEM_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
 
     try
     {
-        vpnor::partition::Table table(ctx);
+        test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
     }
-    catch (vpnor::InvalidTocEntry& e)
+    catch (std::system_error& e)
     {
         return 0;
     }
diff --git a/vpnor/test/write_patch.cpp b/vpnor/test/write_patch.cpp
index 1bf6ba9..4f59db5 100644
--- a/vpnor/test/write_patch.cpp
+++ b/vpnor/test/write_patch.cpp
@@ -4,8 +4,8 @@
 #include "config.h"
 
 extern "C" {
+#include "backend.h"
 #include "common.h"
-#include "flash.h"
 #include "mboxd.h"
 }
 
@@ -47,15 +47,14 @@
     mbox_vlog = &mbox_log_console;
     verbosity = (verbose)2;
 
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+    ctx->backend.flash_size = 0x2000;
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
     root.write("TEST1", data, sizeof(data));
     /* flash_write doesn't copy the file for us */
     assert(fs::copy_file(root.ro() / "TEST1", root.rw() / "TEST1"));
     fs::path patch = root.patch() / "TEST1";
     assert(fs::copy_file(root.ro() / "TEST1", patch));
 
-    init_vpnor_from_paths(ctx);
-
     /* Test */
     memset(src, 0x33, sizeof(src));
     rc = flash_write(ctx, 0x1000, src, sizeof(src));
@@ -79,8 +78,5 @@
     munmap(map, sizeof(src));
     close(fd);
 
-    destroy_vpnor(ctx);
-    free(ctx->flash_bmap);
-
     return rc;
 }
diff --git a/vpnor/test/write_patch_resize.cpp b/vpnor/test/write_patch_resize.cpp
index 9a6979f..ce128c8 100644
--- a/vpnor/test/write_patch_resize.cpp
+++ b/vpnor/test/write_patch_resize.cpp
@@ -4,8 +4,8 @@
 #include "config.h"
 
 extern "C" {
+#include "backend.h"
 #include "common.h"
-#include "flash.h"
 #include "mboxd.h"
 }
 
@@ -46,15 +46,14 @@
     mbox_vlog = &mbox_log_console;
     verbosity = (verbose)2;
 
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+    ctx->backend.flash_size = 0x2000;
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
     std::vector<uint8_t> roContent(PART_SIZE, 0xff);
     root.write("TEST1", roContent.data(), roContent.size());
     /* flash_write doesn't copy the file for us */
     std::vector<uint8_t> patchContent(PATCH_SIZE, 0xaa);
     root.patch("TEST1", patchContent.data(), patchContent.size());
 
-    init_vpnor_from_paths(ctx);
-
     /* Test */
     std::vector<uint8_t> update(UPDATE_SIZE, 0x55);
     rc = flash_write(ctx, 0x1000, update.data(), update.size());
@@ -71,8 +70,5 @@
     munmap(map, update.size());
     close(fd);
 
-    destroy_vpnor(ctx);
-    free(ctx->flash_bmap);
-
     return rc;
 }
diff --git a/vpnor/test/write_prsv.cpp b/vpnor/test/write_prsv.cpp
index 53f3cfe..9ee1fb3 100644
--- a/vpnor/test/write_prsv.cpp
+++ b/vpnor/test/write_prsv.cpp
@@ -2,8 +2,8 @@
 // Copyright (C) 2018 IBM Corp.
 
 extern "C" {
+#include "backend.h"
 #include "common.h"
-#include "flash.h"
 #include "mboxd.h"
 }
 
@@ -41,8 +41,8 @@
     mbox_vlog = &mbox_log_console;
     verbosity = (verbose)2;
 
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    init_vpnor_from_paths(ctx);
+    ctx->backend.flash_size = 0x2000;
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
 
     /* Test */
     memset(src, 0xaa, sizeof(src));
@@ -60,8 +60,5 @@
     munmap(map, sizeof(src));
     close(fd);
 
-    /* Cleanup */
-    destroy_vpnor(ctx);
-
     return 0;
 }
diff --git a/vpnor/test/write_ro.cpp b/vpnor/test/write_ro.cpp
index e5671b1..e6bedd3 100644
--- a/vpnor/test/write_ro.cpp
+++ b/vpnor/test/write_ro.cpp
@@ -3,8 +3,8 @@
 #include "config.h"
 
 extern "C" {
+#include "backend.h"
 #include "common.h"
-#include "flash.h"
 #include "mboxd.h"
 }
 
@@ -39,8 +39,8 @@
     mbox_vlog = &mbox_log_console;
     verbosity = (verbose)2;
 
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    init_vpnor_from_paths(ctx);
+    ctx->backend.flash_size = 0x2000;
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
 
     /* Test */
     rc = flash_write(ctx, 0x1000, src, sizeof(src));
@@ -48,7 +48,5 @@
     /* Verify we can't write to RO partitions */
     assert(rc != 0);
 
-    destroy_vpnor(ctx);
-
     return 0;
 }
diff --git a/vpnor/test/write_rw.cpp b/vpnor/test/write_rw.cpp
index e64f01e..3b742a1 100644
--- a/vpnor/test/write_rw.cpp
+++ b/vpnor/test/write_rw.cpp
@@ -3,8 +3,8 @@
 #include "config.h"
 
 extern "C" {
+#include "backend.h"
 #include "common.h"
-#include "flash.h"
 #include "mboxd.h"
 }
 
@@ -41,10 +41,10 @@
     mbox_vlog = &mbox_log_console;
     verbosity = (verbose)2;
 
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
+    ctx->backend.flash_size = 0x2000;
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
     /* flash_write() doesn't copy the file for us */
     assert(fs::copy_file(root.ro() / "TEST1", root.rw() / "TEST1"));
-    init_vpnor_from_paths(ctx);
 
     /* Test */
     memset(src, 0xbb, sizeof(src));
@@ -95,7 +95,5 @@
     munmap(map, sizeof(src));
     close(fd);
 
-    destroy_vpnor(ctx);
-
     return 0;
 }
diff --git a/vpnor/test/write_toc.cpp b/vpnor/test/write_toc.cpp
index 6f6b101..8b690a1 100644
--- a/vpnor/test/write_toc.cpp
+++ b/vpnor/test/write_toc.cpp
@@ -67,14 +67,12 @@
     system_set_reserved_size(MEM_SIZE);
     system_set_mtd_sizes(PNOR_SIZE, ERASE_SIZE);
 
-    ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
-    test::VpnorRoot root(ctx, toc, BLOCK_SIZE);
-    vpnor::partition::Table table(ctx);
+    ctx = mbox_create_frontend_context(N_WINDOWS, WINDOW_SIZE);
+    test::VpnorRoot root(&ctx->backend, toc, BLOCK_SIZE);
+    vpnor::partition::Table table(&ctx->backend);
 
     assert(table.capacity() == TOC_PART_SIZE);
 
-    init_vpnor_from_paths(ctx);
-
     rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
     assert(rc == MBOX_R_SUCCESS);