diff options
Diffstat (limited to 'vpnor/test')
31 files changed, 2155 insertions, 0 deletions
diff --git a/vpnor/test/Makefile.am.include b/vpnor/test/Makefile.am.include new file mode 100644 index 0000000..9a81d9c --- /dev/null +++ b/vpnor/test/Makefile.am.include @@ -0,0 +1,267 @@ +TEST_MBOX_VPNOR_SRCS = \ + common.c \ + vpnor/pnor_partition_table.cpp \ + %reldir%/tmpd.cpp + +TEST_MBOX_VPNOR_INTEG_SRCS = \ + common.c \ + mboxd_msg.c \ + mboxd_windows.c \ + mboxd_lpc.c \ + vpnor/mboxd_lpc_reset.cpp \ + vpnor/mboxd_pnor_partition_table.cpp \ + vpnor/mboxd_flash.cpp \ + vpnor/pnor_partition.cpp \ + vpnor/pnor_partition_table.cpp \ + %reldir%/tmpd.cpp + +VPNOR_LDADD = -lstdc++fs \ + $(SDBUSPLUS_LIBS) \ + $(PHOSPHOR_LOGGING_LIBS) \ + $(PHOSPHOR_DBUS_INTERFACES_LIBS) + +vpnor_test_create_pnor_partition_table_SOURCES = \ + $(TEST_MOCK_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_MBOX_VPNOR_INTEG_SRCS) \ + %reldir%/create_read_window_partition_exists.cpp +vpnor_test_create_read_window_partition_exists_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_create_read_window_partition_exists_LDADD = $(VPNOR_LDADD) + +vpnor_test_write_patch_SOURCES = \ + $(TEST_MBOX_VPNOR_SRCS) \ + mtd.c \ + vpnor/mboxd_pnor_partition_table.cpp \ + vpnor/mboxd_flash.cpp \ + vpnor/pnor_partition.cpp \ + %reldir%/write_patch.cpp +vpnor_test_write_patch_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_write_patch_LDADD = $(VPNOR_LDADD) + +vpnor_test_write_prsv_SOURCES = \ + $(TEST_MBOX_VPNOR_SRCS) \ + mtd.c \ + vpnor/mboxd_pnor_partition_table.cpp \ + vpnor/mboxd_flash.cpp \ + vpnor/pnor_partition.cpp \ + %reldir%/write_prsv.cpp +vpnor_test_write_prsv_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_write_prsv_LDADD = $(VPNOR_LDADD) + +vpnor_test_write_ro_SOURCES = \ + $(TEST_MBOX_VPNOR_SRCS) \ + mtd.c \ + vpnor/mboxd_pnor_partition_table.cpp \ + vpnor/mboxd_flash.cpp \ + vpnor/pnor_partition.cpp \ + %reldir%/write_ro.cpp +vpnor_test_write_ro_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_write_ro_LDADD = $(VPNOR_LDADD) + +vpnor_test_write_rw_SOURCES = \ + $(TEST_MBOX_VPNOR_SRCS) \ + mtd.c \ + vpnor/mboxd_pnor_partition_table.cpp \ + vpnor/mboxd_flash.cpp \ + vpnor/pnor_partition.cpp \ + %reldir%/write_rw.cpp +vpnor_test_write_rw_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_write_rw_LDADD = $(VPNOR_LDADD) + +vpnor_test_toc_no_name_SOURCES = \ + common.c \ + vpnor/pnor_partition_table.cpp \ + %reldir%/toc_no_name.cpp +vpnor_test_toc_no_name_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_toc_no_name_LDADD = $(VPNOR_LDADD) + +vpnor_test_toc_start_gt_end_SOURCES = \ + common.c \ + vpnor/pnor_partition_table.cpp \ + %reldir%/toc_start_gt_end.cpp +vpnor_test_toc_start_gt_end_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_toc_start_gt_end_LDADD = $(VPNOR_LDADD) + +vpnor_test_toc_no_start_SOURCES = \ + common.c \ + vpnor/pnor_partition_table.cpp \ + %reldir%/toc_no_start.cpp +vpnor_test_toc_no_start_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_toc_no_start_LDADD = $(VPNOR_LDADD) + +vpnor_test_toc_no_end_SOURCES = \ + common.c \ + vpnor/pnor_partition_table.cpp \ + %reldir%/toc_no_end.cpp +vpnor_test_toc_no_end_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_toc_no_end_LDADD = $(VPNOR_LDADD) + +vpnor_test_toc_no_version_SOURCES = \ + common.c \ + vpnor/pnor_partition_table.cpp \ + %reldir%/toc_no_version.cpp +vpnor_test_toc_no_version_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_toc_no_version_LDADD = $(VPNOR_LDADD) + +vpnor_test_toc_flags_SOURCES = \ + common.c \ + vpnor/pnor_partition_table.cpp \ + %reldir%/toc_flags.cpp +vpnor_test_toc_flags_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_toc_flags_LDADD = $(VPNOR_LDADD) + +vpnor_test_toc_overlap_SOURCES = \ + $(TEST_MOCK_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_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_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_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_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_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_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_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_MBOX_VPNOR_INTEG_SRCS) \ + %reldir%/read_patch.cpp +vpnor_test_read_patch_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_read_patch_LDADD = $(VPNOR_LDADD) + +vpnor_test_write_patch_resize_SOURCES = \ + $(TEST_MBOX_VPNOR_SRCS) \ + mtd.c \ + vpnor/mboxd_pnor_partition_table.cpp \ + vpnor/mboxd_flash.cpp \ + vpnor/pnor_partition.cpp \ + %reldir%/write_patch_resize.cpp +vpnor_test_write_patch_resize_LDFLAGS = $(OESDK_TESTCASE_FLAGS) +vpnor_test_write_patch_resize_LDADD = $(VPNOR_LDADD) + +vpnor_test_dump_flash_SOURCES = \ + $(TEST_MOCK_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_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_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_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_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_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) + +if VIRTUAL_PNOR_ENABLED +check_PROGRAMS += \ + %reldir%/create_pnor_partition_table \ + %reldir%/create_read_window_partition_exists \ + %reldir%/write_prsv \ + %reldir%/write_ro \ + %reldir%/write_rw \ + %reldir%/write_patch \ + %reldir%/toc_no_name \ + %reldir%/toc_start_gt_end \ + %reldir%/toc_no_start \ + %reldir%/toc_no_end \ + %reldir%/toc_no_version \ + %reldir%/toc_flags \ + %reldir%/toc_overlap \ + %reldir%/toc_lookup_found \ + %reldir%/toc_lookup_failed \ + %reldir%/toc_missing_file \ + %reldir%/create_read_window_oob \ + %reldir%/create_read_window_toc \ + %reldir%/create_read_window_straddle_partitions \ + %reldir%/create_read_window_partition_invalid \ + %reldir%/read_patch \ + %reldir%/write_patch_resize \ + %reldir%/dump_flash \ + %reldir%/create_read_window_size \ + %reldir%/create_read_window_remap \ + %reldir%/create_write_window_ro_partition \ + %reldir%/create_write_window_rw_partition \ + %reldir%/create_write_window_unmapped + +XFAIL_TESTS += %reldir%/create_write_window_ro_partition +XFAIL_TESTS += %reldir%/create_write_window_unmapped +endif diff --git a/vpnor/test/create_pnor_partition_table.cpp b/vpnor/test/create_pnor_partition_table.cpp new file mode 100644 index 0000000..3a46e38 --- /dev/null +++ b/vpnor/test/create_pnor_partition_table.cpp @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. +#include <assert.h> +#include <string.h> + +#include "config.h" +#include "vpnor/pnor_partition_table.hpp" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +static const auto BLOCK_SIZE = 4 * 1024; +static const auto ERASE_SIZE = BLOCK_SIZE; +static const auto PNOR_SIZE = 64 * 1024 * 1024; +static const auto MEM_SIZE = PNOR_SIZE; +static const auto N_WINDOWS = 1; +static const auto WINDOW_SIZE = BLOCK_SIZE; + +const std::string toc[] = { + "partition01=HBB,00000000,00001000,80,ECC,PRESERVED", +}; +constexpr auto partitionName = "HBB"; + +namespace test = openpower::virtual_pnor::test; + +int main() +{ + struct mbox_context* ctx; + + 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); + + pnor_partition_table expectedTable{}; + expectedTable.data.magic = PARTITION_HEADER_MAGIC; + expectedTable.data.version = PARTITION_VERSION_1; + expectedTable.data.size = 1; + expectedTable.data.entry_size = sizeof(pnor_partition); + expectedTable.data.entry_count = 1; + expectedTable.data.block_size = BLOCK_SIZE; + expectedTable.data.block_count = + (PNOR_SIZE) / expectedTable.data.block_size; + expectedTable.checksum = + openpower::virtual_pnor::details::checksum(expectedTable.data); + + pnor_partition expectedPartition{}; + strcpy(expectedPartition.data.name, partitionName); + expectedPartition.data.base = 0; + expectedPartition.data.size = 1; + expectedPartition.data.actual = 0x1000; + expectedPartition.data.id = 1; + expectedPartition.data.pid = PARENT_PATITION_ID; + expectedPartition.data.type = PARTITION_TYPE_DATA; + expectedPartition.data.flags = 0; + expectedPartition.data.user.data[0] = PARTITION_ECC_PROTECTED; + expectedPartition.data.user.data[1] |= PARTITION_PRESERVED; + expectedPartition.data.user.data[1] |= PARTITION_VERSION_CHECK_SHA512; + expectedPartition.checksum = + openpower::virtual_pnor::details::checksum(expectedPartition.data); + + const pnor_partition_table& result = table.getNativeTable(); + + auto rc = memcmp(&expectedTable, &result, sizeof(pnor_partition_table)); + assert(rc == 0); + + rc = memcmp(&expectedPartition, &result.partitions[0], + sizeof(pnor_partition)); + assert(rc == 0); + + const pnor_partition& first = table.partition(0); + rc = memcmp(&first, &result.partitions[0], sizeof(pnor_partition)); + assert(rc == 0); + + return 0; +} diff --git a/vpnor/test/create_read_window_oob.cpp b/vpnor/test/create_read_window_oob.cpp new file mode 100644 index 0000000..445b0a1 --- /dev/null +++ b/vpnor/test/create_read_window_oob.cpp @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include <assert.h> +#include <string.h> + +#include "config.h" +#include "vpnor/mboxd_pnor_partition_table.h" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +const std::string toc[] = { + "partition01=HBB,00001000,00002000,80,ECC,READONLY", +}; + +static constexpr auto BLOCK_SIZE = 4096; +static constexpr auto MEM_SIZE = (BLOCK_SIZE * 2); +static constexpr auto ERASE_SIZE = BLOCK_SIZE; +static constexpr auto N_WINDOWS = 1; +static constexpr auto WINDOW_SIZE = BLOCK_SIZE; +static constexpr auto PNOR_SIZE = (BLOCK_SIZE * 4); + +static const uint8_t get_info[] = {0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +/* Request access beyond the last (only) partition */ +static const uint8_t create_read_window[] = {0x04, 0x01, 0x03, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +static const uint8_t response[] = {0x04, 0x01, 0xfe, 0xff, 0x01, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + +int main() +{ + namespace test = openpower::virtual_pnor::test; + + struct mbox_context *ctx; + int rc; + + 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); + + 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)); + assert(rc == 1); + + rc = mbox_cmp(ctx, response, sizeof(response)); + assert(rc == 0); + + return 0; +} diff --git a/vpnor/test/create_read_window_partition_exists.cpp b/vpnor/test/create_read_window_partition_exists.cpp new file mode 100644 index 0000000..12ac19b --- /dev/null +++ b/vpnor/test/create_read_window_partition_exists.cpp @@ -0,0 +1,78 @@ +// 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 "vpnor/mboxd_pnor_partition_table.h" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +// A read window assumes that the toc is located at offset 0, +// so create dummy partition at arbitrary offset 0x1000. +const std::string toc[] = { + "partition01=HBB,00001000,00002000,80,ECC,READONLY", +}; + +static const uint8_t data[8] = {0xaa, 0x55, 0xaa, 0x66, 0x77, 0x88, 0x99, 0xab}; + +static const auto BLOCK_SIZE = 4096; +static const auto MEM_SIZE = BLOCK_SIZE * 2; +static const auto ERASE_SIZE = BLOCK_SIZE; +static const auto N_WINDOWS = 1; +static const auto WINDOW_SIZE = BLOCK_SIZE; + +static const uint8_t get_info[] = {0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +// offset 0x100 and size 6 +static const uint8_t create_read_window[] = {0x04, 0x01, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +static const uint8_t response[] = {0x04, 0x01, 0xfe, 0xff, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + +namespace test = openpower::virtual_pnor::test; + +int main() +{ + 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); + 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); + + // send the request for partition1 + rc = mbox_command_dispatch(ctx, create_read_window, + sizeof(create_read_window)); + assert(rc == 1); + + rc = mbox_cmp(ctx, response, sizeof(response)); + assert(rc == 0); + + // Compare the reserved memory to the pnor + rc = memcmp(ctx->mem, data, 6); + assert(rc == 0); + + return rc; +} diff --git a/vpnor/test/create_read_window_partition_invalid.cpp b/vpnor/test/create_read_window_partition_invalid.cpp new file mode 100644 index 0000000..9ed4347 --- /dev/null +++ b/vpnor/test/create_read_window_partition_invalid.cpp @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include <assert.h> +#include <string.h> + +#include "config.h" +#include "vpnor/mboxd_pnor_partition_table.h" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +const std::string toc[] = { + "partition01=HBB,00002000,00003000,80,ECC,READONLY", +}; + +static constexpr auto BLOCK_SIZE = 4096; +static constexpr auto MEM_SIZE = BLOCK_SIZE * 2; +static constexpr auto ERASE_SIZE = BLOCK_SIZE; +static constexpr auto N_WINDOWS = 1; +static constexpr auto WINDOW_SIZE = BLOCK_SIZE; + +static const uint8_t get_info[] = {0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +/* Request access below the specified partition */ +static const uint8_t create_read_window[] = {0x04, 0x01, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +int main() +{ + namespace test = openpower::virtual_pnor::test; + + struct mbox_context *ctx; + int rc; + + 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); + + 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 new file mode 100644 index 0000000..ea319c1 --- /dev/null +++ b/vpnor/test/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 "vpnor/mboxd_pnor_partition_table.h" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/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; +} diff --git a/vpnor/test/create_read_window_size.cpp b/vpnor/test/create_read_window_size.cpp new file mode 100644 index 0000000..1837546 --- /dev/null +++ b/vpnor/test/create_read_window_size.cpp @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include <assert.h> +#include <experimental/filesystem> + +#include "config.h" +#include "vpnor/mboxd_pnor_partition_table.h" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" +static const auto BLOCK_SIZE = 4096; +static const auto ERASE_SIZE = BLOCK_SIZE; +static const auto WINDOW_SIZE = 2 * BLOCK_SIZE; +static const auto MEM_SIZE = WINDOW_SIZE; +static const auto N_WINDOWS = 1; +static const auto PNOR_SIZE = 4 * BLOCK_SIZE; + +const std::string toc[] = { + "partition01=ONE,00001000,00002000,80,ECC,READONLY", + "partition02=TWO,00002000,00004000,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}; + +static const uint8_t request_one[] = {0x04, 0x01, 0x01, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +static const uint8_t response_one[] = {0x04, 0x01, 0xfe, 0xff, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01}; + +static const uint8_t request_two[] = {0x04, 0x02, 0x02, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +static const uint8_t response_two[] = {0x04, 0x02, 0xfe, 0xff, 0x02, + 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01}; + +namespace test = openpower::virtual_pnor::test; + +int main() +{ + struct mbox_context *ctx; + + 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); + + int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info)); + assert(rc == 1); + + rc = mbox_command_dispatch(ctx, request_one, sizeof(request_one)); + assert(rc == 1); + + rc = mbox_cmp(ctx, response_one, sizeof(response_one)); + assert(rc == 0); + + rc = mbox_command_dispatch(ctx, request_two, sizeof(request_two)); + assert(rc == 1); + + rc = mbox_cmp(ctx, response_two, sizeof(response_two)); + assert(rc == 0); + + return rc; +} diff --git a/vpnor/test/create_read_window_straddle_partitions.cpp b/vpnor/test/create_read_window_straddle_partitions.cpp new file mode 100644 index 0000000..e396088 --- /dev/null +++ b/vpnor/test/create_read_window_straddle_partitions.cpp @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include "config.h" + +#include <assert.h> +#include <string.h> + +#include "vpnor/mboxd_pnor_partition_table.h" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +const std::string toc[] = { + "partition01=ONE,00001000,00002000,80,ECC,READONLY", + "partition02=TWO,00002000,00003000,80,ECC,READONLY", +}; + +uint8_t data[8] = {0xaa, 0x55, 0xaa, 0x66, 0x77, 0x88, 0x99, 0xab}; + +static constexpr auto BLOCK_SIZE = 0x1000; +static constexpr auto MEM_SIZE = BLOCK_SIZE * 2; +static constexpr auto ERASE_SIZE = BLOCK_SIZE; +static constexpr auto N_WINDOWS = 1; +static constexpr auto WINDOW_SIZE = MEM_SIZE; +static constexpr auto PNOR_SIZE = MEM_SIZE * 2; + +static const uint8_t get_info[] = {0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +static const uint8_t create_read_window[] = {0x04, 0x01, 0x01, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +static const uint8_t response[] = { + 0x04, 0x01, 0xfe, 0xff, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +}; + +int main() +{ + namespace test = openpower::virtual_pnor::test; + namespace fs = std::experimental::filesystem; + + struct mbox_context *ctx; + + 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); + + int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info)); + assert(rc == 1); + + // Request a read window that would cover both partitions. With the current + // behaviour, we expect to receive a reply describing a window that covers + // the first partition but is limited in size to exclude the second + // partition. + rc = mbox_command_dispatch(ctx, create_read_window, + sizeof(create_read_window)); + assert(rc == 1); + + rc = mbox_cmp(ctx, response, sizeof(response)); + assert(rc == 0); + + return 0; +} diff --git a/vpnor/test/create_read_window_toc.cpp b/vpnor/test/create_read_window_toc.cpp new file mode 100644 index 0000000..32f6523 --- /dev/null +++ b/vpnor/test/create_read_window_toc.cpp @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. +#include <assert.h> +#include <sys/mman.h> +#include <string.h> + +#include "config.h" +#include "vpnor/pnor_partition_table.hpp" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +static constexpr auto BLOCK_SIZE = 4 * 1024; +static constexpr auto PNOR_SIZE = 64 * 1024 * 1024; +static constexpr auto MEM_SIZE = BLOCK_SIZE * 2; +static constexpr auto ERASE_SIZE = BLOCK_SIZE; +static constexpr auto N_WINDOWS = 1; +static constexpr auto WINDOW_SIZE = BLOCK_SIZE; +static constexpr auto TOC_PART_SIZE = BLOCK_SIZE; + +const std::string toc[] = { + "partition00=part,00000000,00001000,80,READONLY", + "partition01=ONE,00001000,00002000,80,READWRITE", +}; + +static const uint8_t get_info[] = {0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +/* Request access to the ToC base for one block */ +static const uint8_t create_read_window[] = {0x04, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +/* Expect a response containing the ToC in one block */ +static const uint8_t response[] = { + 0x04, 0x01, 0xfe, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +}; + +int main() +{ + namespace test = openpower::virtual_pnor::test; + namespace vpnor = openpower::virtual_pnor; + + struct mbox_context* ctx; + int rc; + + 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); + + /* 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); + + rc = mbox_command_dispatch(ctx, create_read_window, + sizeof(create_read_window)); + assert(rc == 1); + + rc = mbox_cmp(ctx, response, sizeof(response)); + assert(rc == 0); + + /* Ensure our partition table is present and as expected */ + const pnor_partition_table& toc = table.getHostTable(); + rc = memcmp(ctx->mem, &toc, table.size()); + assert(rc == 0); + + return 0; +} diff --git a/vpnor/test/create_write_window_ro_partition.cpp b/vpnor/test/create_write_window_ro_partition.cpp new file mode 100644 index 0000000..09dbba0 --- /dev/null +++ b/vpnor/test/create_write_window_ro_partition.cpp @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include <assert.h> + +#include "config.h" +#include "vpnor/mboxd_pnor_partition_table.h" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +const std::string toc[] = { + "partition01=HBB,00001000,00002000,80,ECC,READONLY", +}; + +static const auto BLOCK_SIZE = 4096; +static const auto MEM_SIZE = BLOCK_SIZE * 2; +static const auto ERASE_SIZE = BLOCK_SIZE; +static const auto N_WINDOWS = 1; +static const auto WINDOW_SIZE = BLOCK_SIZE; + +static const uint8_t get_info[] = {0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +// offset 0x100 and size 6 +static const uint8_t create_write_window[] = { + 0x06, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const uint8_t response[] = {0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07}; + +namespace test = openpower::virtual_pnor::test; + +int main() +{ + 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); + + rc = mbox_command_dispatch(ctx, create_write_window, + sizeof(create_write_window)); + assert(rc == 7); + + rc = mbox_cmp(ctx, response, sizeof(response)); + assert(rc == 0); + + return rc; +} diff --git a/vpnor/test/create_write_window_rw_partition.cpp b/vpnor/test/create_write_window_rw_partition.cpp new file mode 100644 index 0000000..74b5831 --- /dev/null +++ b/vpnor/test/create_write_window_rw_partition.cpp @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include <assert.h> + +#include "config.h" +#include "vpnor/mboxd_pnor_partition_table.h" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +const std::string toc[] = { + "partition01=HBB,00001000,00002000,80,ECC,READWRITE", +}; + +static const auto BLOCK_SIZE = 4096; +static const auto MEM_SIZE = BLOCK_SIZE * 2; +static const auto ERASE_SIZE = BLOCK_SIZE; +static const auto N_WINDOWS = 1; +static const auto WINDOW_SIZE = BLOCK_SIZE; + +static const uint8_t get_info[] = {0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +// offset 0x100 and size 6 +static const uint8_t create_write_window[] = { + 0x06, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const uint8_t response[] = {0x06, 0x01, 0xfe, 0xff, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + +namespace test = openpower::virtual_pnor::test; + +int main() +{ + 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); + + rc = mbox_command_dispatch(ctx, create_write_window, + sizeof(create_write_window)); + assert(rc == 1); + + rc = mbox_cmp(ctx, response, sizeof(response)); + assert(rc == 0); + + return rc; +} diff --git a/vpnor/test/create_write_window_unmapped.cpp b/vpnor/test/create_write_window_unmapped.cpp new file mode 100644 index 0000000..47ba57e --- /dev/null +++ b/vpnor/test/create_write_window_unmapped.cpp @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include <assert.h> + +#include "config.h" +#include "vpnor/mboxd_pnor_partition_table.h" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +static constexpr auto BLOCK_SIZE = 0x1000; +static constexpr auto ERASE_SIZE = BLOCK_SIZE; +static constexpr auto N_WINDOWS = 1; +static constexpr auto WINDOW_SIZE = BLOCK_SIZE; +static constexpr auto MEM_SIZE = WINDOW_SIZE; +static constexpr auto PNOR_SIZE = 3 * BLOCK_SIZE; + +const std::string toc[] = { + "partition01=HBB,00001000,00002000,80,ECC,READWRITE", +}; + +static const uint8_t get_info[] = {0x02, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +// offset 0x100 and size 6 +static const uint8_t create_write_window[] = { + 0x06, 0x01, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const uint8_t response[] = {0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07}; + +namespace test = openpower::virtual_pnor::test; + +int main() +{ + struct mbox_context *ctx; + + 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); + + int rc = mbox_command_dispatch(ctx, get_info, sizeof(get_info)); + assert(rc == MBOX_R_SUCCESS); + + rc = mbox_command_dispatch(ctx, create_write_window, + sizeof(create_write_window)); + assert(rc == MBOX_R_WINDOW_ERROR); + + rc = mbox_cmp(ctx, response, sizeof(response)); + assert(rc == 0); + + return rc; +} diff --git a/vpnor/test/dump_flash.cpp b/vpnor/test/dump_flash.cpp new file mode 100644 index 0000000..e811f6f --- /dev/null +++ b/vpnor/test/dump_flash.cpp @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include <assert.h> +#include <string.h> + +#include "config.h" +#include "mboxd_msg.h" +#include "vpnor/mboxd_pnor_partition_table.h" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +struct test_context +{ + uint8_t seq; + struct mbox_context *ctx; +}; + +// Configure the system and the paritions such that we eventually request a +// window that covers the last section of flash, but the remaining flash is +// smaller than the window size +static constexpr auto BLOCK_SIZE = 4096; +static constexpr auto ERASE_SIZE = BLOCK_SIZE; +static constexpr auto N_WINDOWS = 3; +static constexpr auto WINDOW_SIZE = 2 * BLOCK_SIZE; +static constexpr auto MEM_SIZE = N_WINDOWS * WINDOW_SIZE; +static constexpr auto PNOR_SIZE = (4 * BLOCK_SIZE); + +const std::string toc[] = { + "partition01=ONE,00001000,00003000,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}; + +static constexpr auto MBOX_CREATE_READ_WINDOW = 4; + +static int mbox_create_read_window(struct test_context *tctx, size_t offset, + size_t len) +{ + union mbox_regs regs; + + memset(®s, 0, sizeof(regs)); + regs.msg.command = MBOX_CREATE_READ_WINDOW; + regs.msg.seq = ++tctx->seq; + put_u16(®s.msg.args[0], offset); + put_u16(®s.msg.args[2], len); + + return mbox_command_dispatch(tctx->ctx, regs.raw, sizeof(regs.raw)); +} + +int main() +{ + namespace test = openpower::virtual_pnor::test; + + struct test_context _tctx = {0}, *tctx = &_tctx; + size_t len; + size_t pos; + int rc; + + 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); + + rc = mbox_command_dispatch(tctx->ctx, get_info, sizeof(get_info)); + assert(rc == 1); + + pos = 0; + while (pos < (PNOR_SIZE / BLOCK_SIZE)) + { + struct mbox_msg _msg, *msg = &_msg; + + rc = mbox_create_read_window(tctx, pos, (WINDOW_SIZE / BLOCK_SIZE)); + assert(rc == 1); + + mbox_rspcpy(tctx->ctx, msg); + + len = get_u16(&msg->args[2]); + pos = get_u16(&msg->args[4]) + len; + } + + return 0; +} diff --git a/vpnor/test/read_patch.cpp b/vpnor/test/read_patch.cpp new file mode 100644 index 0000000..31a422e --- /dev/null +++ b/vpnor/test/read_patch.cpp @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include "config.h" +#include "common.h" +#include "vpnor/mboxd_pnor_partition_table.h" + +#include <assert.h> + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +static constexpr auto BLOCK_SIZE = 0x1000; +static constexpr auto ERASE_SIZE = BLOCK_SIZE; +static constexpr auto PART_SIZE = BLOCK_SIZE * 4; +static constexpr auto PATCH_SIZE = PART_SIZE / 2; +static constexpr auto N_WINDOWS = 2; +static constexpr auto WINDOW_SIZE = PART_SIZE * 8; +static constexpr auto MEM_SIZE = WINDOW_SIZE * N_WINDOWS; +static constexpr auto PNOR_SIZE = MEM_SIZE * 2; + +const std::string toc[] = { + "partition01=ONE,00001000,00005000,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}; + +static const uint8_t create_read_window[] = {0x04, 0x01, 0x01, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +static const uint8_t response[] = {0x04, 0x01, 0xc0, 0xff, 0x04, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + +int main() +{ + namespace test = openpower::virtual_pnor::test; + + struct mbox_context *ctx; + + 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); + + // 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 + // that is beyond the size of the backing file, but is in the set of valid + // offsets for the partition as defined by the ToC. + 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); + + rc = mbox_command_dispatch(ctx, create_read_window, + sizeof(create_read_window)); + assert(rc == 1); + + rc = mbox_cmp(ctx, response, sizeof(response)); + assert(rc == 0); + + return 0; +} diff --git a/vpnor/test/tmpd.cpp b/vpnor/test/tmpd.cpp new file mode 100644 index 0000000..723bf56 --- /dev/null +++ b/vpnor/test/tmpd.cpp @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include "vpnor/test/tmpd.hpp" + +namespace openpower +{ +namespace virtual_pnor +{ +namespace test +{ + +namespace fs = std::experimental::filesystem; + +size_t VpnorRoot::write(const std::string &name, const void *data, size_t len) +{ + // write() is for test environment setup - always write to ro section + fs::path path = root / "ro" / name; + + if (!fs::exists(path)) + /* It's not in the ToC */ + throw std::invalid_argument(name); + + std::ofstream(path).write((const char *)data, len); + + return len; +} + +size_t VpnorRoot::patch(const std::string &name, const void *data, size_t len) +{ + if (!fs::exists(root / "ro" / name)) + /* It's not in the ToC */ + throw std::invalid_argument(name); + + std::ofstream(root / "patch" / name).write((const char *)data, len); + + return len; +} + +} // test +} // virtual_pnor +} // openpower diff --git a/vpnor/test/tmpd.hpp b/vpnor/test/tmpd.hpp new file mode 100644 index 0000000..45260ca --- /dev/null +++ b/vpnor/test/tmpd.hpp @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright (C) 2018 IBM Corp. */ + +#include <assert.h> +#include <string.h> +#include <vector> +#include <fstream> +#include <experimental/filesystem> + +#include "config.h" +#include "mbox.h" +#include "vpnor/pnor_partition_table.hpp" + +namespace openpower +{ +namespace virtual_pnor +{ +namespace test +{ + +namespace fs = std::experimental::filesystem; + +class VpnorRoot +{ + public: + template <std::size_t N> + VpnorRoot(struct mbox_context* ctx, const std::string (&toc)[N], + size_t blockSize) + { + char tmplt[] = "/tmp/vpnor_root.XXXXXX"; + char* tmpdir = mkdtemp(tmplt); + root = fs::path{tmpdir}; + + for (const auto& attr : attributes) + { + fs::create_directory(root / attr); + } + + fs::path tocFilePath = root / "ro" / PARTITION_TOC_FILE; + + for (const std::string& line : toc) + { + pnor_partition part; + + openpower::virtual_pnor::parseTocLine(line, blockSize, part); + + /* Populate the partition in the tree */ + std::vector<char> zeroed(part.data.actual, 0); + fs::path partitionFilePath = root / "ro" / part.data.name; + std::ofstream(partitionFilePath) + .write(zeroed.data(), zeroed.size()); + + /* Update the ToC if the partition file was created */ + 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'; + } + + VpnorRoot(const VpnorRoot&) = delete; + VpnorRoot& operator=(const VpnorRoot&) = delete; + VpnorRoot(VpnorRoot&&) = delete; + VpnorRoot& operator=(VpnorRoot&&) = delete; + + ~VpnorRoot() + { + fs::remove_all(root); + } + fs::path ro() + { + return fs::path{root} / "ro"; + } + fs::path rw() + { + return fs::path{root} / "rw"; + } + fs::path prsv() + { + return fs::path{root} / "prsv"; + } + fs::path patch() + { + return fs::path{root} / "patch"; + } + size_t write(const std::string& name, const void* data, size_t len); + size_t patch(const std::string& name, const void* data, size_t len); + + private: + fs::path root; + const std::string attributes[4] = {"ro", "rw", "prsv", "patch"}; +}; + +} // test +} // virtual_pnor +} // openpower diff --git a/vpnor/test/toc_flags.cpp b/vpnor/test/toc_flags.cpp new file mode 100644 index 0000000..c30f7ad --- /dev/null +++ b/vpnor/test/toc_flags.cpp @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include "config.h" +#include <assert.h> + +#include "common.h" +#include "vpnor/pnor_partition_defs.h" +#include "vpnor/pnor_partition_table.hpp" + +static constexpr auto BLOCK_SIZE = 4 * 1024; +static constexpr auto DATA_MASK = ((1 << 24) - 1); + +int main() +{ + namespace vpnor = openpower::virtual_pnor; + + struct pnor_partition part; + std::string line; + + mbox_vlog = mbox_log_console; + verbosity = MBOX_LOG_DEBUG; + + line = "partition01=FOO,00001000,00002000,80,ECC"; + vpnor::parseTocLine(line, BLOCK_SIZE, part); + assert((part.data.user.data[0]) == PARTITION_ECC_PROTECTED); + assert(!(part.data.user.data[1] & DATA_MASK)); + + line = "partition01=FOO,00001000,00002000,80,PRESERVED"; + vpnor::parseTocLine(line, BLOCK_SIZE, part); + assert(!(part.data.user.data[0])); + assert((part.data.user.data[1] & DATA_MASK) == PARTITION_PRESERVED); + + line = "partition01=FOO,00001000,00002000,80,READONLY"; + vpnor::parseTocLine(line, BLOCK_SIZE, part); + assert(!(part.data.user.data[0])); + assert((part.data.user.data[1] & DATA_MASK) == PARTITION_READONLY); + + /* BACKUP is unimplemented */ + line = "partition01=FOO,00001000,00002000,80,BACKUP"; + vpnor::parseTocLine(line, BLOCK_SIZE, part); + assert(!(part.data.user.data[0])); + assert(!(part.data.user.data[1] & DATA_MASK)); + + line = "partition01=FOO,00001000,00002000,80,REPROVISION"; + vpnor::parseTocLine(line, BLOCK_SIZE, part); + assert(!(part.data.user.data[0])); + assert((part.data.user.data[1] & DATA_MASK) == PARTITION_REPROVISION); + + line = "partition01=FOO,00001000,00002000,80,VOLATILE"; + vpnor::parseTocLine(line, BLOCK_SIZE, part); + assert(!(part.data.user.data[0])); + assert((part.data.user.data[1] & DATA_MASK) == PARTITION_VOLATILE); + + line = "partition01=FOO,00001000,00002000,80,CLEARECC"; + vpnor::parseTocLine(line, BLOCK_SIZE, part); + assert(!(part.data.user.data[0])); + assert((part.data.user.data[1] & DATA_MASK) == PARTITION_CLEARECC); + + line = "partition01=FOO,00001000,00002000,80,READWRITE"; + vpnor::parseTocLine(line, BLOCK_SIZE, part); + assert(!(part.data.user.data[0])); + assert(((part.data.user.data[1] & DATA_MASK) ^ PARTITION_READONLY) == + PARTITION_READONLY); + + line = "partition01=FOO,00001000,00002000,80,"; + vpnor::parseTocLine(line, BLOCK_SIZE, part); + assert(!(part.data.user.data[0])); + assert(!(part.data.user.data[1] & DATA_MASK)); + + line = "partition01=FOO,00001000,00002000,80,junk"; + vpnor::parseTocLine(line, BLOCK_SIZE, part); + assert(!(part.data.user.data[0])); + assert(!(part.data.user.data[1] & DATA_MASK)); + + return 0; +} diff --git a/vpnor/test/toc_lookup_failed.cpp b/vpnor/test/toc_lookup_failed.cpp new file mode 100644 index 0000000..199a00b --- /dev/null +++ b/vpnor/test/toc_lookup_failed.cpp @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. +#include <assert.h> +#include <string.h> + +#include "config.h" +#include "vpnor/pnor_partition_table.hpp" +#include "xyz/openbmc_project/Common/error.hpp" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +static constexpr auto BLOCK_SIZE = 0x1000; +static constexpr auto ERASE_SIZE = BLOCK_SIZE; +static constexpr auto PNOR_SIZE = 64 * 1024 * 1024; +static constexpr auto MEM_SIZE = 32 * 1024 * 1024; +static constexpr auto N_WINDOWS = 1; +static constexpr auto WINDOW_SIZE = BLOCK_SIZE * 2; + +const std::string toc[] = { + "partition01=ONE,00001000,00002000,80,", +}; + +int main() +{ + namespace err = sdbusplus::xyz::openbmc_project::Common::Error; + namespace test = openpower::virtual_pnor::test; + namespace vpnor = openpower::virtual_pnor; + + 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); + vpnor::partition::Table table(ctx); + + try + { + table.partition("TWO"); + } + catch (vpnor::UnknownPartition& e) + { + return 0; + } + + assert(false); +} diff --git a/vpnor/test/toc_lookup_found.cpp b/vpnor/test/toc_lookup_found.cpp new file mode 100644 index 0000000..411e3f8 --- /dev/null +++ b/vpnor/test/toc_lookup_found.cpp @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. +#include <assert.h> +#include <string.h> + +#include "config.h" +#include "vpnor/pnor_partition_table.hpp" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +static constexpr auto BLOCK_SIZE = 0x1000; +static constexpr auto ERASE_SIZE = BLOCK_SIZE; +static constexpr auto PNOR_SIZE = 64 * 1024 * 1024; +static constexpr auto MEM_SIZE = 32 * 1024 * 1024; +static constexpr auto N_WINDOWS = 1; +static constexpr auto WINDOW_SIZE = BLOCK_SIZE * 2; + +const std::string toc[] = { + "partition01=ONE,00001000,00002000,80,", + "partition02=TWO,00002000,00004000,80,", + "partition03=THREE,00004000,00008000,80,", +}; + +int main() +{ + namespace test = openpower::virtual_pnor::test; + namespace vpnor = openpower::virtual_pnor; + + 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); + vpnor::partition::Table table(ctx); + + const struct pnor_partition& part = table.partition("TWO"); + assert(part.data.id == 2); + assert(part.data.base == 2); + assert(part.data.size == 2); + + return 0; +} diff --git a/vpnor/test/toc_missing_file.cpp b/vpnor/test/toc_missing_file.cpp new file mode 100644 index 0000000..821653f --- /dev/null +++ b/vpnor/test/toc_missing_file.cpp @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. +#include <assert.h> +#include <string.h> + +#include "config.h" +#include "vpnor/pnor_partition_table.hpp" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +static constexpr auto BLOCK_SIZE = 0x1000; +static constexpr auto ERASE_SIZE = BLOCK_SIZE; +static constexpr auto PNOR_SIZE = 64 * 1024 * 1024; +static constexpr auto MEM_SIZE = 32 * 1024 * 1024; +static constexpr auto N_WINDOWS = 1; +static constexpr auto WINDOW_SIZE = BLOCK_SIZE * 2; + +const std::string toc[] = { + "partition01=ONE,00001000,00002000,80,", + "partition02=TWO,00002000,00003000,80,", +}; + +int main() +{ + namespace test = openpower::virtual_pnor::test; + namespace fs = std::experimental::filesystem; + namespace vpnor = openpower::virtual_pnor; + + 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); + + fs::remove(root.ro() / "TWO"); + + try + { + vpnor::partition::Table table(ctx); + } + catch (vpnor::InvalidTocEntry& e) + { + return 0; + } + + assert(false); +} diff --git a/vpnor/test/toc_no_end.cpp b/vpnor/test/toc_no_end.cpp new file mode 100644 index 0000000..f9c5187 --- /dev/null +++ b/vpnor/test/toc_no_end.cpp @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include "config.h" +#include <assert.h> + +#include "vpnor/pnor_partition_table.hpp" + +static constexpr auto BLOCK_SIZE = 4 * 1024; + +int main() +{ + namespace vpnor = openpower::virtual_pnor; + + struct pnor_partition part; + std::string line; + + line = "partition01=FOO,00001000,,80,ECC,PRESERVED"; + try + { + openpower::virtual_pnor::parseTocLine(line, BLOCK_SIZE, part); + } + catch (vpnor::MalformedTocEntry& e) + { + return 0; + } + + assert(false); +} diff --git a/vpnor/test/toc_no_name.cpp b/vpnor/test/toc_no_name.cpp new file mode 100644 index 0000000..d62056f --- /dev/null +++ b/vpnor/test/toc_no_name.cpp @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include "config.h" +#include <assert.h> + +#include "vpnor/pnor_partition_table.hpp" + +static constexpr auto BLOCK_SIZE = 4 * 1024; + +int main() +{ + namespace vpnor = openpower::virtual_pnor; + + const std::string line = "partition01=,00000000,00000400,80,ECC,PRESERVED"; + struct pnor_partition part; + + try + { + vpnor::parseTocLine(line, BLOCK_SIZE, part); + } + catch (vpnor::MalformedTocEntry& e) + { + return 0; + } + + assert(false); +} diff --git a/vpnor/test/toc_no_start.cpp b/vpnor/test/toc_no_start.cpp new file mode 100644 index 0000000..1d20a46 --- /dev/null +++ b/vpnor/test/toc_no_start.cpp @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include "config.h" +#include <assert.h> + +#include "vpnor/pnor_partition_table.hpp" + +static constexpr auto BLOCK_SIZE = 4 * 1024; + +int main() +{ + namespace vpnor = openpower::virtual_pnor; + + struct pnor_partition part; + std::string line; + + line = "partition01=FOO,,00001000,80,ECC,PRESERVED"; + try + { + openpower::virtual_pnor::parseTocLine(line, BLOCK_SIZE, part); + } + catch (vpnor::MalformedTocEntry& e) + { + return 0; + } + + assert(false); +} diff --git a/vpnor/test/toc_no_version.cpp b/vpnor/test/toc_no_version.cpp new file mode 100644 index 0000000..68cb057 --- /dev/null +++ b/vpnor/test/toc_no_version.cpp @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include "config.h" +#include <assert.h> + +#include "vpnor/pnor_partition_table.hpp" + +static constexpr auto BLOCK_SIZE = 4 * 1024; + +int main() +{ + namespace vpnor = openpower::virtual_pnor; + + struct pnor_partition part; + std::string line; + + line = "partition01=FOO,00001000,00002000,,ECC,PRESERVED"; + try + { + openpower::virtual_pnor::parseTocLine(line, BLOCK_SIZE, part); + } + catch (vpnor::MalformedTocEntry& e) + { + return 0; + } + + assert(false); +} diff --git a/vpnor/test/toc_overlap.cpp b/vpnor/test/toc_overlap.cpp new file mode 100644 index 0000000..94d071c --- /dev/null +++ b/vpnor/test/toc_overlap.cpp @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. +#include <assert.h> +#include <string.h> + +#include "config.h" +#include "vpnor/pnor_partition_table.hpp" + +extern "C" { +#include "test/mbox.h" +#include "test/system.h" +} + +#include "vpnor/test/tmpd.hpp" + +static constexpr auto BLOCK_SIZE = 0x1000; +static constexpr auto ERASE_SIZE = BLOCK_SIZE; +static constexpr auto PNOR_SIZE = 64 * 1024 * 1024; +static constexpr auto MEM_SIZE = 32 * 1024 * 1024; +static constexpr auto N_WINDOWS = 1; +static constexpr auto WINDOW_SIZE = BLOCK_SIZE * 2; + +const std::string toc[] = { + "partition01=ONE,00001000,00003000,80,", + "partition02=TWO,00002000,00004000,80,", +}; + +int main() +{ + namespace test = openpower::virtual_pnor::test; + namespace vpnor = openpower::virtual_pnor; + + 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); + + try + { + vpnor::partition::Table table(ctx); + } + catch (vpnor::InvalidTocEntry& e) + { + return 0; + } + + assert(false); +} diff --git a/vpnor/test/toc_start_gt_end.cpp b/vpnor/test/toc_start_gt_end.cpp new file mode 100644 index 0000000..69edc63 --- /dev/null +++ b/vpnor/test/toc_start_gt_end.cpp @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include "config.h" +#include <assert.h> + +#include "vpnor/pnor_partition_table.hpp" + +static constexpr auto BLOCK_SIZE = 4 * 1024; + +int main() +{ + namespace vpnor = openpower::virtual_pnor; + + std::string line = "partition01=FOO,00002000,00001000,80,ECC,PRESERVED"; + pnor_partition part; + + try + { + vpnor::parseTocLine(line, BLOCK_SIZE, part); + } + catch (vpnor::InvalidTocEntry& e) + { + return 0; + } + + assert(false); +} diff --git a/vpnor/test/write_patch.cpp b/vpnor/test/write_patch.cpp new file mode 100644 index 0000000..3b2b16a --- /dev/null +++ b/vpnor/test/write_patch.cpp @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include <assert.h> +#include <experimental/filesystem> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/syslog.h> +#include <unistd.h> + +#include "config.h" +#include "common.h" +#include "mbox.h" +#include "mboxd_flash.h" + +#include "vpnor/test/tmpd.hpp" + +static constexpr auto BLOCK_SIZE = 0x1000; +static constexpr auto DATA_SIZE = 8; + +const uint8_t data[DATA_SIZE] = {0xa0, 0xa1, 0xa2, 0xa3, + 0xa4, 0xa5, 0xa6, 0xa7}; + +const std::string toc[] = { + "partition01=TEST1,00001000,00002000,80,ECC,READWRITE", +}; + +int main(void) +{ + namespace fs = std::experimental::filesystem; + namespace test = openpower::virtual_pnor::test; + + struct mbox_context _ctx, *ctx = &_ctx; + char src[DATA_SIZE]{0}; + void *map; + int rc; + int fd; + + /* Setup */ + memset(ctx, 0, sizeof(mbox_context)); + + mbox_vlog = &mbox_log_console; + verbosity = (verbose)2; + + test::VpnorRoot root(ctx, toc, BLOCK_SIZE); + root.write("TEST1", data, sizeof(data)); + /* write_flash 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 = write_flash(ctx, 0x1000, src, sizeof(src)); + assert(rc == 0); + + /* Check that RW file is unmodified after the patch write */ + fd = open((root.rw() / "TEST1").c_str(), O_RDONLY); + map = mmap(NULL, sizeof(src), PROT_READ, MAP_SHARED, fd, 0); + assert(map != MAP_FAILED); + rc = memcmp(data, map, sizeof(src)); + assert(rc == 0); + munmap(map, sizeof(src)); + close(fd); + + /* Check that PATCH is modified with the new data */ + fd = open(patch.c_str(), O_RDONLY); + map = mmap(NULL, sizeof(src), PROT_READ, MAP_SHARED, fd, 0); + assert(map != MAP_FAILED); + rc = memcmp(src, map, sizeof(src)); + assert(rc == 0); + 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 new file mode 100644 index 0000000..8d67683 --- /dev/null +++ b/vpnor/test/write_patch_resize.cpp @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include <assert.h> +#include <experimental/filesystem> +#include <fcntl.h> +#include <stdint.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/syslog.h> +#include <unistd.h> + +#include "config.h" +#include "common.h" +#include "mbox.h" +#include "mboxd_flash.h" + +#include "vpnor/test/tmpd.hpp" + +static constexpr auto BLOCK_SIZE = 0x1000; +static constexpr auto PART_SIZE = BLOCK_SIZE; +static constexpr auto PATCH_SIZE = BLOCK_SIZE / 2; +static constexpr auto UPDATE_SIZE = BLOCK_SIZE; + +const std::string toc[] = { + "partition01=TEST1,00001000,00002000,80,ECC,READWRITE", +}; + +int main(void) +{ + namespace fs = std::experimental::filesystem; + namespace test = openpower::virtual_pnor::test; + + struct mbox_context _ctx, *ctx = &_ctx; + void *map; + int rc; + int fd; + + /* Setup */ + memset(ctx, 0, sizeof(mbox_context)); + + mbox_vlog = &mbox_log_console; + verbosity = (verbose)2; + + test::VpnorRoot root(ctx, toc, BLOCK_SIZE); + std::vector<uint8_t> roContent(PART_SIZE, 0xff); + root.write("TEST1", roContent.data(), roContent.size()); + /* write_flash 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 = write_flash(ctx, 0x1000, update.data(), update.size()); + assert(rc == 0); + + /* Check that PATCH is modified with the new data */ + fs::path patch = root.patch() / "TEST1"; + assert(UPDATE_SIZE == fs::file_size(patch)); + fd = open(patch.c_str(), O_RDONLY); + map = mmap(NULL, UPDATE_SIZE, PROT_READ, MAP_SHARED, fd, 0); + assert(map != MAP_FAILED); + rc = memcmp(update.data(), map, update.size()); + assert(rc == 0); + 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 new file mode 100644 index 0000000..26f1d86 --- /dev/null +++ b/vpnor/test/write_prsv.cpp @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include <assert.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "common.h" +#include "mbox.h" +#include "mboxd_flash.h" + +#include "vpnor/test/tmpd.hpp" + +static constexpr auto BLOCK_SIZE = 0x1000; + +const std::string toc[] = { + "partition01=TEST1,00001000,00002000,80,ECC,PRESERVED", +}; + +namespace test = openpower::virtual_pnor::test; + +int main(void) +{ + namespace fs = std::experimental::filesystem; + + struct mbox_context _ctx, *ctx = &_ctx; + uint8_t src[8]; + void *map; + int fd; + int rc; + + /* Setup */ + memset(ctx, 0, sizeof(mbox_context)); + + mbox_vlog = &mbox_log_console; + verbosity = (verbose)2; + + test::VpnorRoot root(ctx, toc, BLOCK_SIZE); + init_vpnor_from_paths(ctx); + + /* Test */ + memset(src, 0xaa, sizeof(src)); + rc = write_flash(ctx, 0x1000, src, sizeof(src)); + assert(rc == 0); + + /* Verify */ + fd = open((root.prsv() / "TEST1").c_str(), O_RDONLY); + assert(fd >= 0); + map = mmap(NULL, sizeof(src), PROT_READ, MAP_PRIVATE, fd, 0); + assert(map != MAP_FAILED); + + rc = memcmp(src, map, sizeof(src)); + assert(rc == 0); + 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 new file mode 100644 index 0000000..53eeb18 --- /dev/null +++ b/vpnor/test/write_ro.cpp @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include <assert.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "common.h" +#include "mbox.h" +#include "mboxd_flash.h" + +#include "vpnor/test/tmpd.hpp" + +static constexpr auto BLOCK_SIZE = 0x1000; + +const std::string toc[] = { + "partition01=TEST1,00001000,00002000,80,ECC,READONLY", +}; + +int main(void) +{ + namespace fs = std::experimental::filesystem; + namespace test = openpower::virtual_pnor::test; + + struct mbox_context _ctx, *ctx = &_ctx; + uint8_t src[8] = {0}; + int rc; + + /* Setup */ + memset(ctx, 0, sizeof(mbox_context)); + + mbox_vlog = &mbox_log_console; + verbosity = (verbose)2; + + test::VpnorRoot root(ctx, toc, BLOCK_SIZE); + init_vpnor_from_paths(ctx); + + /* Test */ + rc = write_flash(ctx, 0x1000, src, sizeof(src)); + + /* 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 new file mode 100644 index 0000000..1ee5c6c --- /dev/null +++ b/vpnor/test/write_rw.cpp @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2018 IBM Corp. + +#include <assert.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "common.h" +#include "mbox.h" +#include "mboxd_flash.h" + +#include "vpnor/test/tmpd.hpp" + +static constexpr auto BLOCK_SIZE = 0x1000; + +const std::string toc[] = { + "partition01=TEST1,00001000,00002000,80,ECC,READWRITE", +}; + +int main(void) +{ + namespace fs = std::experimental::filesystem; + namespace test = openpower::virtual_pnor::test; + + struct mbox_context _ctx, *ctx = &_ctx; + uint8_t src[8] = {0}; + void *map; + int rc; + int fd; + + /* Setup */ + memset(ctx, 0, sizeof(mbox_context)); + + mbox_vlog = &mbox_log_console; + verbosity = (verbose)2; + + test::VpnorRoot root(ctx, toc, BLOCK_SIZE); + /* write_flash() 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)); + rc = write_flash(ctx, 0x1000, src, sizeof(src)); + assert(rc == 0); + fd = open((root.rw() / "TEST1").c_str(), O_RDONLY); + map = mmap(NULL, sizeof(src), PROT_READ, MAP_PRIVATE, fd, 0); + assert(map != MAP_FAILED); + rc = memcmp(src, map, sizeof(src)); + assert(rc == 0); + + /* Ensure single byte writes function */ + memset(src, 0xcc, sizeof(src)); + rc = write_flash(ctx, 0x1000, src, sizeof(src)); + assert(rc == 0); + rc = memcmp(src, map, sizeof(src)); + assert(rc == 0); + + src[0] = 0xff; + rc = write_flash(ctx, 0x1000, src, 1); + assert(rc == 0); + rc = memcmp(src, map, sizeof(src)); + assert(rc == 0); + + src[1] = 0xff; + rc = write_flash(ctx, 0x1000 + 1, &src[1], 1); + assert(rc == 0); + rc = memcmp(src, map, sizeof(src)); + assert(rc == 0); + + src[2] = 0xff; + rc = write_flash(ctx, 0x1000 + 2, &src[2], 1); + assert(rc == 0); + rc = memcmp(src, map, sizeof(src)); + assert(rc == 0); + + /* Writes past the end of the partition should fail */ + rc = write_flash(ctx, 0x1000 + 0xff9, src, sizeof(src)); + assert(rc < 0); + + /* Check that RW file is unmodified after the bad write */ + fd = open((root.rw() / "TEST1").c_str(), O_RDONLY); + map = mmap(NULL, sizeof(src), PROT_READ, MAP_SHARED, fd, 0); + assert(map != MAP_FAILED); + rc = memcmp(src, map, sizeof(src)); + assert(rc == 0); + + munmap(map, sizeof(src)); + close(fd); + + destroy_vpnor(ctx); + + return 0; +} |