2 * Copyright (c) 2016 NextThing Co
3 * Copyright (c) 2016 Free Electrons
5 * SPDX-License-Identifier: GPL-2.0+
13 #include <linux/sizes.h>
16 #include <test/overlay.h>
17 #include <test/suites.h>
19 /* 4k ought to be enough for anybody */
20 #define FDT_COPY_SIZE (4 * SZ_1K)
22 extern u32 __dtb_test_fdt_base_begin;
23 extern u32 __dtb_test_fdt_overlay_begin;
24 extern u32 __dtb_test_fdt_overlay_stacked_begin;
26 static int ut_fdt_getprop_u32_by_index(void *fdt, const char *path,
27 const char *name, int index,
34 node_off = fdt_path_offset(fdt, path);
38 val = fdt_getprop(fdt, node_off, name, &len);
39 if (!val || (len < (sizeof(uint32_t) * (index + 1))))
40 return -FDT_ERR_NOTFOUND;
42 *out = fdt32_to_cpu(*(val + index));
47 static int ut_fdt_getprop_u32(void *fdt, const char *path, const char *name,
50 return ut_fdt_getprop_u32_by_index(fdt, path, name, 0, out);
53 static int fdt_getprop_str(void *fdt, const char *path, const char *name,
59 node_off = fdt_path_offset(fdt, path);
63 *out = fdt_stringlist_get(fdt, node_off, name, 0, &len);
65 return len < 0 ? len : 0;
68 static int fdt_overlay_change_int_property(struct unit_test_state *uts)
70 void *fdt = uts->priv;
73 ut_assertok(ut_fdt_getprop_u32(fdt, "/test-node", "test-int-property",
77 return CMD_RET_SUCCESS;
79 OVERLAY_TEST(fdt_overlay_change_int_property, 0);
81 static int fdt_overlay_change_str_property(struct unit_test_state *uts)
83 void *fdt = uts->priv;
84 const char *val = NULL;
86 ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property",
88 ut_asserteq_str("foobar", val);
90 return CMD_RET_SUCCESS;
92 OVERLAY_TEST(fdt_overlay_change_str_property, 0);
94 static int fdt_overlay_add_str_property(struct unit_test_state *uts)
96 void *fdt = uts->priv;
97 const char *val = NULL;
99 ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property-2",
101 ut_asserteq_str("foobar2", val);
103 return CMD_RET_SUCCESS;
105 OVERLAY_TEST(fdt_overlay_add_str_property, 0);
107 static int fdt_overlay_add_node_by_phandle(struct unit_test_state *uts)
109 void *fdt = uts->priv;
112 off = fdt_path_offset(fdt, "/test-node/new-node");
115 ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
117 return CMD_RET_SUCCESS;
119 OVERLAY_TEST(fdt_overlay_add_node_by_phandle, 0);
121 static int fdt_overlay_add_node_by_path(struct unit_test_state *uts)
123 void *fdt = uts->priv;
126 off = fdt_path_offset(fdt, "/new-node");
129 ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
131 return CMD_RET_SUCCESS;
133 OVERLAY_TEST(fdt_overlay_add_node_by_path, 0);
135 static int fdt_overlay_add_subnode_property(struct unit_test_state *uts)
137 void *fdt = uts->priv;
140 off = fdt_path_offset(fdt, "/test-node/sub-test-node");
143 ut_assertnonnull(fdt_getprop(fdt, off, "sub-test-property", NULL));
144 ut_assertnonnull(fdt_getprop(fdt, off, "new-sub-test-property", NULL));
146 return CMD_RET_SUCCESS;
148 OVERLAY_TEST(fdt_overlay_add_subnode_property, 0);
150 static int fdt_overlay_local_phandle(struct unit_test_state *uts)
152 uint32_t local_phandle;
153 void *fdt = uts->priv;
157 off = fdt_path_offset(fdt, "/new-local-node");
160 local_phandle = fdt_get_phandle(fdt, off);
161 ut_assert(local_phandle);
163 ut_assertok(ut_fdt_getprop_u32_by_index(fdt, "/", "test-several-phandle",
165 ut_asserteq(local_phandle, val);
167 ut_assertok(ut_fdt_getprop_u32_by_index(fdt, "/", "test-several-phandle",
169 ut_asserteq(local_phandle, val);
171 return CMD_RET_SUCCESS;
173 OVERLAY_TEST(fdt_overlay_local_phandle, 0);
175 static int fdt_overlay_local_phandles(struct unit_test_state *uts)
177 uint32_t local_phandle, test_phandle;
178 void *fdt = uts->priv;
182 off = fdt_path_offset(fdt, "/new-local-node");
185 local_phandle = fdt_get_phandle(fdt, off);
186 ut_assert(local_phandle);
188 off = fdt_path_offset(fdt, "/test-node");
191 test_phandle = fdt_get_phandle(fdt, off);
192 ut_assert(test_phandle);
194 ut_assertok(ut_fdt_getprop_u32_by_index(fdt, "/", "test-phandle", 0,
196 ut_asserteq(test_phandle, val);
198 ut_assertok(ut_fdt_getprop_u32_by_index(fdt, "/", "test-phandle", 1,
200 ut_asserteq(local_phandle, val);
202 return CMD_RET_SUCCESS;
204 OVERLAY_TEST(fdt_overlay_local_phandles, 0);
206 static int fdt_overlay_stacked(struct unit_test_state *uts)
208 void *fdt = uts->priv;
211 ut_assertok(ut_fdt_getprop_u32(fdt, "/new-local-node",
212 "stacked-test-int-property", &val));
213 ut_asserteq(43, val);
215 return CMD_RET_SUCCESS;
217 OVERLAY_TEST(fdt_overlay_stacked, 0);
219 int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
221 struct unit_test *tests = ll_entry_start(struct unit_test,
223 const int n_ents = ll_entry_count(struct unit_test, overlay_test);
224 struct unit_test_state *uts;
225 void *fdt_base = &__dtb_test_fdt_base_begin;
226 void *fdt_overlay = &__dtb_test_fdt_overlay_begin;
227 void *fdt_overlay_stacked = &__dtb_test_fdt_overlay_stacked_begin;
228 void *fdt_base_copy, *fdt_overlay_copy, *fdt_overlay_stacked_copy;
231 uts = calloc(1, sizeof(*uts));
235 ut_assertok(fdt_check_header(fdt_base));
236 ut_assertok(fdt_check_header(fdt_overlay));
238 fdt_base_copy = malloc(FDT_COPY_SIZE);
241 uts->priv = fdt_base_copy;
243 fdt_overlay_copy = malloc(FDT_COPY_SIZE);
244 if (!fdt_overlay_copy)
247 fdt_overlay_stacked_copy = malloc(FDT_COPY_SIZE);
248 if (!fdt_overlay_stacked_copy)
252 * Resize the FDT to 4k so that we have room to operate on
254 * (and relocate it since the memory might be mapped
257 ut_assertok(fdt_open_into(fdt_base, fdt_base_copy, FDT_COPY_SIZE));
260 * Resize the overlay to 4k so that we have room to operate on
262 * (and relocate it since the memory might be mapped
265 ut_assertok(fdt_open_into(fdt_overlay, fdt_overlay_copy,
269 * Resize the stacked overlay to 4k so that we have room to operate on
271 * (and relocate it since the memory might be mapped
274 ut_assertok(fdt_open_into(fdt_overlay_stacked, fdt_overlay_stacked_copy,
277 /* Apply the overlay */
278 ut_assertok(fdt_overlay_apply(fdt_base_copy, fdt_overlay_copy));
280 /* Apply the stacked overlay */
281 ut_assertok(fdt_overlay_apply(fdt_base_copy, fdt_overlay_stacked_copy));
283 ret = cmd_ut_category("overlay", tests, n_ents, argc, argv);
285 free(fdt_overlay_stacked_copy);
287 free(fdt_overlay_copy);