1 /*
2 * Copyright (c) 2017 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/storage/flash_map.h>
9 #include <bootutil/bootutil_public.h>
10 #include <zephyr/dfu/mcuboot.h>
11 #include <zephyr/drivers/flash.h>
12
13 #define BOOT_MAGIC_VAL_W0 0xf395c277
14 #define BOOT_MAGIC_VAL_W1 0x7fefd260
15 #define BOOT_MAGIC_VAL_W2 0x0f505235
16 #define BOOT_MAGIC_VAL_W3 0x8079b62c
17 #define BOOT_MAGIC_VALUES {BOOT_MAGIC_VAL_W0, BOOT_MAGIC_VAL_W1,\
18 BOOT_MAGIC_VAL_W2, BOOT_MAGIC_VAL_W3 }
19
erase_image_status_page(const struct flash_area * fa)20 static void erase_image_status_page(const struct flash_area *fa)
21 {
22 int ret;
23 struct flash_pages_info page;
24 const struct device *sf_dev;
25
26 sf_dev = flash_area_get_device(fa);
27
28 /* Erase flash page to which image status belongs. */
29 ret = flash_get_page_info_by_offs(sf_dev, fa->fa_off + fa->fa_size - 1,
30 &page);
31 zassert_true(ret == 0, "can't get the trailer's flash page info.");
32
33 ret = flash_erase(sf_dev, page.start_offset, page.size);
34 zassert_true(ret == 0, "can't erase the trailer flash page.");
35 }
36
_test_request_upgrade_n(uint8_t fa_id,int img_index,int confirmed)37 static void _test_request_upgrade_n(uint8_t fa_id, int img_index, int confirmed)
38 {
39 const struct flash_area *fa;
40 const uint32_t expectation[6] = {
41 0xffffffff,
42 0xffffffff,
43 BOOT_MAGIC_VAL_W0,
44 BOOT_MAGIC_VAL_W1,
45 BOOT_MAGIC_VAL_W2,
46 BOOT_MAGIC_VAL_W3
47 };
48 uint32_t readout[ARRAY_SIZE(expectation)];
49 int ret;
50
51 ret = flash_area_open(fa_id, &fa);
52 zassert_true(ret == 0, "can't open the images's flash area.");
53
54 erase_image_status_page(fa);
55
56 ret = (confirmed) ? BOOT_UPGRADE_PERMANENT : BOOT_UPGRADE_TEST;
57 zassert_true(boot_request_upgrade_multi(img_index, ret) == 0,
58 "Can' request the upgrade of the %d. image.", img_index);
59
60 ret = flash_area_read(fa, fa->fa_size - sizeof(expectation),
61 &readout, sizeof(readout));
62 zassert_true(ret == 0, "Read from flash");
63
64 if (confirmed) {
65 zassert_true(memcmp(&expectation[2], &readout[2],
66 sizeof(expectation) -
67 2 * sizeof(expectation[0])) == 0,
68 "unexpected trailer value");
69
70 zassert_equal(1, readout[0] & 0xff, "confirmation error");
71 } else {
72 zassert_true(memcmp(expectation, readout,
73 sizeof(expectation)) == 0, "unexpected trailer value");
74 }
75 }
76
ZTEST(mcuboot_multi,test_request_upgrade_multi)77 ZTEST(mcuboot_multi, test_request_upgrade_multi)
78 {
79 _test_request_upgrade_n(FIXED_PARTITION_ID(slot1_partition), 0, 0);
80 _test_request_upgrade_n(FIXED_PARTITION_ID(slot3_partition), 1, 1);
81 }
82
_test_write_confirm_n(uint8_t fa_id,int img_index)83 static void _test_write_confirm_n(uint8_t fa_id, int img_index)
84 {
85 const uint32_t img_magic[4] = BOOT_MAGIC_VALUES;
86 uint32_t readout[ARRAY_SIZE(img_magic)];
87 uint8_t flag[BOOT_MAX_ALIGN];
88 const struct flash_area *fa;
89 int ret;
90
91 flag[0] = 0x01;
92 memset(&flag[1], 0xff, sizeof(flag) - 1);
93
94 ret = flash_area_open(fa_id, &fa);
95 zassert_true(ret == 0, "can't open the images's flash area.");
96
97 erase_image_status_page(fa);
98
99 ret = flash_area_read(fa, fa->fa_size - sizeof(img_magic),
100 &readout, sizeof(img_magic));
101 zassert_true(ret == 0, "Read from flash");
102
103 if (memcmp(img_magic, readout, sizeof(img_magic)) != 0) {
104 ret = flash_area_write(fa, fa->fa_size - 16,
105 img_magic, 16);
106 zassert_true(ret == 0, "Write to flash");
107 }
108
109 /* set copy-done flag */
110 ret = flash_area_write(fa, fa->fa_size - 32, &flag, sizeof(flag));
111 zassert_true(ret == 0, "Write to flash");
112
113 ret = boot_write_img_confirmed_multi(img_index);
114 zassert(ret == 0, "pass", "fail (%d)", ret);
115
116 ret = flash_area_read(fa, fa->fa_size - 24, readout,
117 sizeof(readout[0]));
118 zassert_true(ret == 0, "Read from flash");
119
120 zassert_equal(1, readout[0] & 0xff, "confirmation error");
121 }
122
ZTEST(mcuboot_multi,test_write_confirm_multi)123 ZTEST(mcuboot_multi, test_write_confirm_multi)
124 {
125 _test_write_confirm_n(FIXED_PARTITION_ID(slot0_partition), 0);
126 _test_write_confirm_n(FIXED_PARTITION_ID(slot2_partition), 1);
127 }
128
129 ZTEST_SUITE(mcuboot_multi, NULL, NULL, NULL, NULL, NULL);
130