test: vpnor: Add create_read_window_remap

Sanity check that requesting arbitrary offsets inside a partition will
map to an existing window containing that partitions data. This ensures
we don't have multiple windows mapping the same content and shooting
ourselves in the foot with coherency issues.

Change-Id: Ie13cc36a9f092381660d5c45ed6d2477c3a4d6ce
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/test/vpnor/Makefile.am.include b/test/vpnor/Makefile.am.include
index c249ef9..dac43c8 100644
--- a/test/vpnor/Makefile.am.include
+++ b/test/vpnor/Makefile.am.include
@@ -276,6 +276,19 @@
 test_vpnor_create_read_window_size_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
 test_vpnor_create_read_window_size_LDADD = $(VPNOR_LDADD)
 
+test_vpnor_create_read_window_remap_SOURCES = \
+	$(TEST_MBOX_VPNOR_SRCS) $(TEST_MOCK_SRCS) \
+	mboxd_msg.c \
+	mboxd_windows.c \
+	mboxd_lpc.c \
+	mboxd_lpc_virtual.cpp \
+	mboxd_pnor_partition_table.cpp \
+	mboxd_flash_virtual.cpp \
+	pnor_partition.cpp \
+	%reldir%/create_read_window_remap.cpp
+test_vpnor_create_read_window_remap_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
+test_vpnor_create_read_window_remap_LDADD = $(VPNOR_LDADD)
+
 if VIRTUAL_PNOR_ENABLED
 check_PROGRAMS += \
 	%reldir%/create_pnor_partition_table \
@@ -301,7 +314,8 @@
 	%reldir%/read_patch \
 	%reldir%/write_patch_resize \
 	%reldir%/dump_flash \
-	%reldir%/create_read_window_size
+	%reldir%/create_read_window_size \
+	%reldir%/create_read_window_remap
 
 XFAIL_TESTS += %reldir%/dump_flash
 XFAIL_TESTS += %reldir%/create_read_window_size
diff --git a/test/vpnor/create_read_window_remap.cpp b/test/vpnor/create_read_window_remap.cpp
new file mode 100644
index 0000000..97e0abc
--- /dev/null
+++ b/test/vpnor/create_read_window_remap.cpp
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (C) 2018 IBM Corp.
+
+#include <assert.h>
+#include <experimental/filesystem>
+#include <fstream>
+#include <string.h>
+#include <vector>
+
+#include "config.h"
+#include "mboxd_pnor_partition_table.h"
+
+extern "C" {
+#include "test/mbox.h"
+#include "test/system.h"
+}
+
+#include "test/vpnor/tmpd.hpp"
+
+static const auto BLOCK_SIZE = 4096;
+static const auto ERASE_SIZE = BLOCK_SIZE;
+static const auto WINDOW_SIZE = 16 * BLOCK_SIZE;
+static const auto N_WINDOWS = 2;
+static const auto MEM_SIZE = N_WINDOWS * WINDOW_SIZE;
+
+const std::string toc[] = {
+    "partition01=ONE,00001000,00011000,80,ECC,READONLY",
+};
+
+static const uint8_t get_info[] = {0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                   0x00, 0x00, 0x00, 0x00};
+
+namespace test = openpower::virtual_pnor::test;
+
+int main()
+{
+    uint8_t request[] = {0x04, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+    uint8_t response[] = {0x04, 0x01, 0xe0, 0xff, 0x10, 0x00, 0x01,
+                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
+
+    struct mbox_context *ctx;
+
+    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);
+
+    int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info));
+    assert(rc == 1);
+
+    for (int i = 1; i < (0x10000 / BLOCK_SIZE); i++)
+    {
+        /* Update the requested offset */
+        put_u16(&request[2], i);
+
+        /*
+         * Reuse the offset as a sequence number, because it's unique. Request
+         * and response have the same sequence number
+         */
+        request[1] = i;
+        response[1] = i;
+
+        rc = mbox_command_dispatch(ctx, request, sizeof(request));
+        assert(rc == 1);
+
+        /* Check that it maps to the same window each time */
+        rc = mbox_cmp(ctx, response, sizeof(response));
+        assert(rc == 0);
+    }
+
+    return 0;
+}