Test: Add BL2 tests
Change-Id: Ie230b3e8caaeb35676be06e4ca9db45b04f64e97
Signed-off-by: Raef Coles <raef.coles@arm.com>
diff --git a/test/bl2/mcuboot/CMakeLists.txt b/test/bl2/mcuboot/CMakeLists.txt
new file mode 100644
index 0000000..89df0f5
--- /dev/null
+++ b/test/bl2/mcuboot/CMakeLists.txt
@@ -0,0 +1,33 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+add_subdirectory(suites/integration)
+
+add_library(mcuboot_tests STATIC)
+
+target_sources(mcuboot_tests
+ PRIVATE
+ ./mcuboot_suites.c
+)
+
+target_include_directories(mcuboot_tests
+ PUBLIC
+ .
+)
+
+target_link_libraries(mcuboot_tests
+ PUBLIC
+ tfm_test_framework_common
+ PRIVATE
+ platform_bl2
+ mcuboot_test_suite_integration
+)
+
+target_compile_definitions(mcuboot_tests
+ PUBLIC
+ DOMAIN_NS=1
+)
diff --git a/test/bl2/mcuboot/mcuboot_suites.c b/test/bl2/mcuboot/mcuboot_suites.c
new file mode 100644
index 0000000..e7188fd
--- /dev/null
+++ b/test/bl2/mcuboot/mcuboot_suites.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "test_framework_integ_test.h"
+#include "test_framework_integ_test_helper.h"
+#include "test_framework.h"
+
+#include "mcuboot_integration_tests.h"
+
+static struct test_suite_t test_suites[] = {
+ {®ister_testsuite_mcuboot_integration, 0, 0, 0},
+
+ /* End of test suites */
+ {0, 0, 0, 0}
+};
+
+enum test_suite_err_t run_mcuboot_testsuite(void)
+{
+ return integ_test("MCUBOOT", test_suites);
+}
diff --git a/test/bl2/mcuboot/mcuboot_suites.h b/test/bl2/mcuboot/mcuboot_suites.h
new file mode 100644
index 0000000..73737aa
--- /dev/null
+++ b/test/bl2/mcuboot/mcuboot_suites.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef MCUBOOT_SUITES_H
+#define MCUBOOT_SUITES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "test_framework_error_codes.h"
+
+enum test_suite_err_t run_mcuboot_testsuite(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MCUBOOT_SUITES_H */
diff --git a/test/bl2/mcuboot/suites/integration/CMakeLists.txt b/test/bl2/mcuboot/suites/integration/CMakeLists.txt
new file mode 100644
index 0000000..df4aaa1
--- /dev/null
+++ b/test/bl2/mcuboot/suites/integration/CMakeLists.txt
@@ -0,0 +1,34 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+add_library(mcuboot_test_suite_integration)
+
+target_sources(mcuboot_test_suite_integration
+ PRIVATE
+ ./mcuboot_integration_tests.c
+)
+
+target_include_directories(mcuboot_test_suite_integration
+ PUBLIC
+ .
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/bl2/ext/mcuboot/include
+ ${MCUBOOT_PATH}/boot/bootutil/src
+)
+
+target_link_libraries(mcuboot_test_suite_integration
+ PUBLIC
+ tfm_test_framework_common
+ bootutil
+ tfm_log
+ platform_bl2
+)
+
+target_compile_definitions(mcuboot_test_suite_integration
+ PUBLIC
+ DOMAIN_NS=1
+)
diff --git a/test/bl2/mcuboot/suites/integration/mcuboot_integration_tests.c b/test/bl2/mcuboot/suites/integration/mcuboot_integration_tests.c
new file mode 100644
index 0000000..decbbf4
--- /dev/null
+++ b/test/bl2/mcuboot/suites/integration/mcuboot_integration_tests.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "mcuboot_integration_tests.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "bootutil/image.h"
+#include "region_defs.h"
+#include "flash_map/flash_map.h"
+#include "flash_map_backend/flash_map_backend.h"
+#include "bootutil/bootutil.h"
+#include "bootutil/boot_status.h"
+#include "bootutil_priv.h"
+#include "test_framework_helpers.h"
+
+#define MCUBOOT_INTEG_TEST_BLOCK_SIZE 256
+
+static int read_image_header(int idx, struct image_header *hdr)
+{
+ int rc;
+ const struct flash_area *fap;
+
+ rc = flash_area_open(flash_area_id_from_image_slot(idx), &fap);
+ if (rc) {
+ return rc;
+ }
+
+ rc = flash_area_read(fap, 0, hdr, sizeof(struct image_header));
+
+ flash_area_close(fap);
+
+ return rc;
+}
+
+static int write_image_header(int idx, struct image_header *hdr)
+{
+ int rc;
+ const struct flash_area *fap;
+
+ rc = flash_area_open(flash_area_id_from_image_slot(idx), &fap);
+ if (rc) {
+ return rc;
+ }
+
+ rc = flash_area_write(fap, 0, hdr, sizeof(struct image_header));
+ if (rc) {
+ return rc;
+ }
+
+ flash_area_close(fap);
+
+ return 0;
+}
+
+static int copy_image_to_slot(int source_idx, int dest_idx)
+{
+ int rc;
+ const struct flash_area *source_fap;
+ const struct flash_area *dest_fap;
+ size_t idx;
+ size_t copy_size;
+ uint8_t block[MCUBOOT_INTEG_TEST_BLOCK_SIZE];
+
+ rc = flash_area_open(flash_area_id_from_image_slot(source_idx), &source_fap);
+ if (rc) {
+ return rc;
+ }
+
+ rc = flash_area_open(flash_area_id_from_image_slot(dest_idx), &dest_fap);
+ if (rc) {
+ flash_area_close(source_fap);
+ return rc;
+ }
+
+ rc = flash_area_erase(dest_fap, 0, dest_fap->fa_size);
+ if (rc) {
+ goto out;
+ }
+
+ copy_size = source_fap->fa_size > dest_fap->fa_size ?
+ dest_fap->fa_size :
+ source_fap->fa_size;
+
+ /* Note that this copy leaves the header erased, so it can be set by the
+ * test without doing any more flash erasing.
+ */
+ for (idx = sizeof(struct image_header); idx < (copy_size - sizeof(block));
+ idx += sizeof(block)) {
+ rc = flash_area_read(source_fap, idx, block, sizeof(block));
+ if (rc) {
+ goto out;
+ }
+
+ rc = flash_area_write(dest_fap, idx, block, sizeof(block));
+ if (rc) {
+ goto out;
+ }
+ }
+
+ rc = flash_area_read(source_fap, idx, block, copy_size - idx);
+ if (rc) {
+ goto out;
+ }
+
+ rc = flash_area_write(dest_fap, idx, block, copy_size - idx);
+ if (rc) {
+ goto out;
+ }
+
+out:
+ flash_area_close(source_fap);
+ flash_area_close(dest_fap);
+
+ return rc;
+}
+
+static int test_setup(int *original_image_idx)
+{
+ int rc;
+ struct image_header hdr;
+
+ rc = read_image_header(0, &hdr);
+ if (rc) {
+ return rc;
+ }
+
+ /* If there's a valid image in slot 0 copy that to slot 1 */
+ if (hdr.ih_magic == IMAGE_MAGIC) {
+ *original_image_idx = 0;
+ return copy_image_to_slot(0, 1);
+ } else {
+ /* Else copy slot 1 to slot 0. We assume that one of the slots has a
+ * valid image.
+ */
+ *original_image_idx = 1;
+ return copy_image_to_slot(1, 0);
+ }
+}
+
+static void reset_shared_area()
+{
+ struct shared_data_tlv_header *header =
+ (struct shared_data_tlv_header*)MCUBOOT_SHARED_DATA_BASE;
+
+ memset((uint8_t*)MCUBOOT_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE, 0,
+ MCUBOOT_SHARED_DATA_SIZE - SHARED_DATA_HEADER_SIZE);
+
+ header->tlv_tot_len = SHARED_DATA_HEADER_SIZE;
+}
+
+static int test_teardown(int original_image_idx)
+{
+ int rc;
+ int test_image_idx;
+ const struct flash_area *fap;
+
+ /* Erase the test image */
+ test_image_idx = original_image_idx == 0 ? 1 : 0;
+ rc = flash_area_open(flash_area_id_from_image_slot(test_image_idx), &fap);
+ if (rc) {
+ return rc;
+ }
+
+ rc = flash_area_erase(fap, 0, fap->fa_size);
+ flash_area_close(fap);
+
+ reset_shared_area();
+
+ return rc;
+}
+
+static void tfm_mcuboot_integration_test_0001(struct test_result_t *ret)
+{
+ int rc;
+ int original_image_idx = 0;
+ struct image_header hdr;
+ struct boot_rsp rsp;
+
+ rc = test_setup(&original_image_idx);
+ if (rc) {
+ TEST_FAIL("Failed to setup test");
+ goto out;
+ }
+
+ rc = read_image_header(0, &hdr);
+ if (rc) {
+ TEST_FAIL("Failed to read image header");
+ goto out;
+ }
+
+ /* Increasing the version both causes the image to boot preferentially and
+ * also invalidates the signature
+ */
+ hdr.ih_ver.iv_major += 1;
+
+ rc = write_image_header(1, &hdr);
+ if (rc) {
+ TEST_FAIL("Failed to write image header");
+ goto out;
+ }
+
+ rc = fih_int_decode(boot_go(&rsp));
+ if (memcmp(rsp.br_hdr, &hdr, sizeof(struct image_header)) == 0) {
+ TEST_FAIL("Invalid image boot succeeded");
+ goto out;
+ }
+
+ ret->val = TEST_PASSED;
+
+out:
+ rc = test_teardown(original_image_idx);
+ if (rc) {
+ TEST_FAIL("Failed to teardown test");
+ }
+}
+
+static struct test_t integration_tests[] = {
+ {&tfm_mcuboot_integration_test_0001, "TFM_MCUBOOT_INTEGRATION_TEST_0001",
+ "Integration invalid image signature test", {TEST_PASSED} },
+};
+
+void register_testsuite_mcuboot_integration(struct test_suite_t *p_test_suite)
+{
+ uint32_t list_size = (sizeof(integration_tests) / sizeof(integration_tests[0]));
+
+ set_testsuite("MCUboot Integration test (TFM_MCUBOOT_INTEGRATION_TEST_0XXX)",
+ integration_tests, list_size, p_test_suite);
+}
diff --git a/test/bl2/mcuboot/suites/integration/mcuboot_integration_tests.h b/test/bl2/mcuboot/suites/integration/mcuboot_integration_tests.h
new file mode 100644
index 0000000..6d758a1
--- /dev/null
+++ b/test/bl2/mcuboot/suites/integration/mcuboot_integration_tests.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef MCUBOOT_INTEGRATION_TESTS_H
+#define MCUBOOT_INTEGRATION_TESTS_H
+
+#include "test_framework.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void register_testsuite_mcuboot_integration(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MCUBOOT_INTEGRATION_TESTS_H */