1 1.1.1.2 skrll /* $NetBSD: dtbs_equal_unordered.c,v 1.1.1.3 2019/12/22 12:34:06 skrll Exp $ */ 2 1.1.1.2 skrll 3 1.1.1.3 skrll // SPDX-License-Identifier: LGPL-2.1-or-later 4 1.1 macallan /* 5 1.1 macallan * libfdt - Flat Device Tree manipulation 6 1.1 macallan * Tests if two given dtbs are structurally equal (including order) 7 1.1 macallan * Copyright (C) 2007 David Gibson, IBM Corporation. 8 1.1 macallan */ 9 1.1 macallan 10 1.1 macallan #include <stdlib.h> 11 1.1 macallan #include <stdio.h> 12 1.1 macallan #include <string.h> 13 1.1 macallan #include <stdint.h> 14 1.1 macallan #include <limits.h> 15 1.1 macallan 16 1.1 macallan #include <libfdt.h> 17 1.1 macallan 18 1.1 macallan #include "tests.h" 19 1.1 macallan #include "testdata.h" 20 1.1 macallan 21 1.1.1.2 skrll static int notequal; /* = 0 */ 22 1.1.1.3 skrll static int ignore_memrsv; /* = 0 */ 23 1.1 macallan 24 1.1 macallan #define MISMATCH(fmt, ...) \ 25 1.1 macallan do { \ 26 1.1 macallan if (notequal) \ 27 1.1 macallan PASS(); \ 28 1.1 macallan else \ 29 1.1 macallan FAIL(fmt, ##__VA_ARGS__); \ 30 1.1 macallan } while (0) 31 1.1 macallan 32 1.1 macallan #define MATCH() \ 33 1.1 macallan do { \ 34 1.1 macallan if (!notequal) \ 35 1.1 macallan PASS(); \ 36 1.1 macallan else \ 37 1.1 macallan FAIL("Trees match which shouldn't"); \ 38 1.1 macallan } while (0) 39 1.1 macallan 40 1.1 macallan #define CHECK(code) \ 41 1.1 macallan { \ 42 1.1 macallan err = (code); \ 43 1.1 macallan if (err) \ 44 1.1 macallan FAIL(#code ": %s", fdt_strerror(err)); \ 45 1.1 macallan } 46 1.1 macallan 47 1.1 macallan static int mem_rsv_cmp(const void *p1, const void *p2) 48 1.1 macallan { 49 1.1 macallan const struct fdt_reserve_entry *re1 = p1; 50 1.1 macallan const struct fdt_reserve_entry *re2 = p2; 51 1.1 macallan 52 1.1.1.2 skrll if (fdt64_to_cpu(re1->address) < fdt64_to_cpu(re2->address)) 53 1.1 macallan return -1; 54 1.1.1.2 skrll else if (fdt64_to_cpu(re1->address) > fdt64_to_cpu(re2->address)) 55 1.1 macallan return 1; 56 1.1 macallan 57 1.1.1.2 skrll if (fdt64_to_cpu(re1->size) < fdt64_to_cpu(re2->size)) 58 1.1 macallan return -1; 59 1.1.1.2 skrll else if (fdt64_to_cpu(re1->size) > fdt64_to_cpu(re2->size)) 60 1.1 macallan return 1; 61 1.1 macallan 62 1.1 macallan return 0; 63 1.1 macallan } 64 1.1 macallan 65 1.1 macallan static void compare_mem_rsv(void *fdt1, void *fdt2) 66 1.1 macallan { 67 1.1 macallan int i; 68 1.1 macallan uint64_t addr1, size1, addr2, size2; 69 1.1 macallan int err; 70 1.1 macallan 71 1.1 macallan if (fdt_num_mem_rsv(fdt1) != fdt_num_mem_rsv(fdt2)) 72 1.1 macallan MISMATCH("Trees have different number of reserve entries"); 73 1.1 macallan 74 1.1 macallan qsort((char *)fdt1 + fdt_off_mem_rsvmap(fdt1), fdt_num_mem_rsv(fdt1), 75 1.1 macallan sizeof(struct fdt_reserve_entry), mem_rsv_cmp); 76 1.1 macallan qsort((char *)fdt2 + fdt_off_mem_rsvmap(fdt2), fdt_num_mem_rsv(fdt2), 77 1.1 macallan sizeof(struct fdt_reserve_entry), mem_rsv_cmp); 78 1.1 macallan 79 1.1 macallan for (i = 0; i < fdt_num_mem_rsv(fdt1); i++) { 80 1.1 macallan CHECK(fdt_get_mem_rsv(fdt1, i, &addr1, &size1)); 81 1.1 macallan CHECK(fdt_get_mem_rsv(fdt2, i, &addr2, &size2)); 82 1.1 macallan 83 1.1 macallan if ((addr1 != addr2) || (size1 != size2)) 84 1.1 macallan MISMATCH("Mismatch in reserve entry %d: " 85 1.1 macallan "(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i, 86 1.1 macallan (unsigned long long)addr1, 87 1.1 macallan (unsigned long long)size1, 88 1.1 macallan (unsigned long long)addr2, 89 1.1 macallan (unsigned long long)size2); 90 1.1 macallan } 91 1.1 macallan } 92 1.1 macallan 93 1.1 macallan static void compare_properties(const void *fdt1, int offset1, 94 1.1 macallan const void *fdt2, int offset2) 95 1.1 macallan { 96 1.1 macallan int offset = offset1; 97 1.1 macallan 98 1.1 macallan /* Check the properties */ 99 1.1 macallan for (offset = fdt_first_property_offset(fdt1, offset1); 100 1.1 macallan offset >= 0; 101 1.1 macallan offset = fdt_next_property_offset(fdt1, offset)) { 102 1.1 macallan const char *name; 103 1.1 macallan int len1, len2; 104 1.1 macallan const void *data1, *data2; 105 1.1 macallan int i; 106 1.1 macallan 107 1.1 macallan data1 = fdt_getprop_by_offset(fdt1, offset, &name, &len1); 108 1.1 macallan if (!data1) 109 1.1 macallan FAIL("fdt_getprop_by_offset(): %s\n", 110 1.1 macallan fdt_strerror(len1)); 111 1.1 macallan 112 1.1 macallan verbose_printf("Property '%s'\n", name); 113 1.1 macallan 114 1.1 macallan data2 = fdt_getprop(fdt2, offset2, name, &len2); 115 1.1 macallan if (!data2) { 116 1.1 macallan if (len2 == -FDT_ERR_NOTFOUND) 117 1.1 macallan MISMATCH("Property '%s' missing\n", name); 118 1.1 macallan else 119 1.1 macallan FAIL("fdt_get_property(): %s\n", 120 1.1 macallan fdt_strerror(len2)); 121 1.1 macallan } 122 1.1 macallan 123 1.1 macallan verbose_printf("len1=%d data1=", len1); 124 1.1 macallan for (i = 0; i < len1; i++) 125 1.1 macallan verbose_printf(" %02x", ((const char *)data1)[i]); 126 1.1 macallan verbose_printf("\nlen2=%d data2=", len2); 127 1.1 macallan for (i = 0; i < len1; i++) 128 1.1 macallan verbose_printf(" %02x", ((const char *)data2)[i]); 129 1.1 macallan verbose_printf("\n"); 130 1.1 macallan 131 1.1 macallan if (len1 != len2) 132 1.1 macallan MISMATCH("Property '%s' mismatched length %d vs. %d\n", 133 1.1 macallan name, len1, len2); 134 1.1 macallan else if (memcmp(data1, data2, len1) != 0) 135 1.1 macallan MISMATCH("Property '%s' mismatched value\n", name); 136 1.1 macallan } 137 1.1 macallan } 138 1.1 macallan 139 1.1 macallan static void compare_node(const void *fdt1, int offset1, 140 1.1 macallan const void *fdt2, int offset2); 141 1.1 macallan 142 1.1 macallan static void compare_subnodes(const void *fdt1, int offset1, 143 1.1 macallan const void *fdt2, int offset2, 144 1.1 macallan int recurse) 145 1.1 macallan { 146 1.1 macallan int coffset1, coffset2, depth; 147 1.1 macallan 148 1.1 macallan for (depth = 0, coffset1 = offset1; 149 1.1 macallan (coffset1 >= 0) && (depth >= 0); 150 1.1 macallan coffset1 = fdt_next_node(fdt1, coffset1, &depth)) 151 1.1 macallan if (depth == 1) { 152 1.1 macallan const char *name = fdt_get_name(fdt1, coffset1, NULL); 153 1.1 macallan 154 1.1 macallan verbose_printf("Subnode %s\n", name); 155 1.1 macallan coffset2 = fdt_subnode_offset(fdt2, offset2, name); 156 1.1 macallan if (coffset2 == -FDT_ERR_NOTFOUND) 157 1.1 macallan MISMATCH("Subnode %s missing\n", name); 158 1.1 macallan else if (coffset2 < 0) 159 1.1 macallan FAIL("fdt_subnode_offset(): %s\n", 160 1.1 macallan fdt_strerror(coffset2)); 161 1.1 macallan 162 1.1 macallan if (recurse) 163 1.1 macallan compare_node(fdt1, coffset1, fdt2, coffset2); 164 1.1 macallan } 165 1.1 macallan } 166 1.1 macallan 167 1.1 macallan static void compare_node(const void *fdt1, int offset1, 168 1.1 macallan const void *fdt2, int offset2) 169 1.1 macallan { 170 1.1 macallan int err; 171 1.1 macallan char path1[PATH_MAX], path2[PATH_MAX]; 172 1.1 macallan 173 1.1 macallan CHECK(fdt_get_path(fdt1, offset1, path1, sizeof(path1))); 174 1.1 macallan CHECK(fdt_get_path(fdt2, offset2, path2, sizeof(path2))); 175 1.1 macallan 176 1.1 macallan if (!streq(path1, path2)) 177 1.1 macallan TEST_BUG("Path mismatch %s vs. %s\n", path1, path2); 178 1.1 macallan 179 1.1 macallan verbose_printf("Checking %s\n", path1); 180 1.1 macallan 181 1.1 macallan compare_properties(fdt1, offset1, fdt2, offset2); 182 1.1 macallan compare_properties(fdt2, offset2, fdt1, offset1); 183 1.1 macallan 184 1.1 macallan compare_subnodes(fdt1, offset1, fdt2, offset2, 1); 185 1.1 macallan compare_subnodes(fdt2, offset2, fdt1, offset1, 0); 186 1.1 macallan } 187 1.1 macallan 188 1.1.1.3 skrll static void badargs(char **argv) 189 1.1.1.3 skrll { 190 1.1.1.3 skrll CONFIG("Usage: %s [-n] [-m] <dtb file> <dtb file>", argv[0]); 191 1.1.1.3 skrll } 192 1.1.1.3 skrll 193 1.1 macallan int main(int argc, char *argv[]) 194 1.1 macallan { 195 1.1 macallan void *fdt1, *fdt2; 196 1.1 macallan uint32_t cpuid1, cpuid2; 197 1.1.1.3 skrll char **args; 198 1.1.1.3 skrll int argsleft; 199 1.1 macallan 200 1.1 macallan test_init(argc, argv); 201 1.1 macallan 202 1.1.1.3 skrll args = &argv[1]; 203 1.1.1.3 skrll argsleft = argc - 1; 204 1.1.1.3 skrll 205 1.1.1.3 skrll while (argsleft > 2) { 206 1.1.1.3 skrll if (streq(args[0], "-n")) 207 1.1.1.3 skrll notequal = 1; 208 1.1.1.3 skrll else if (streq(args[0], "-m")) 209 1.1.1.3 skrll ignore_memrsv = 1; 210 1.1.1.3 skrll else 211 1.1.1.3 skrll badargs(argv); 212 1.1.1.3 skrll args++; 213 1.1.1.3 skrll argsleft--; 214 1.1.1.3 skrll } 215 1.1.1.3 skrll if (argsleft != 2) 216 1.1.1.3 skrll badargs(argv); 217 1.1.1.3 skrll 218 1.1.1.3 skrll fdt1 = load_blob(args[0]); 219 1.1.1.3 skrll fdt2 = load_blob(args[1]); 220 1.1 macallan 221 1.1.1.3 skrll if (!ignore_memrsv) 222 1.1.1.3 skrll compare_mem_rsv(fdt1, fdt2); 223 1.1 macallan compare_node(fdt1, 0, fdt2, 0); 224 1.1 macallan 225 1.1 macallan cpuid1 = fdt_boot_cpuid_phys(fdt1); 226 1.1 macallan cpuid2 = fdt_boot_cpuid_phys(fdt2); 227 1.1 macallan if (cpuid1 != cpuid2) 228 1.1 macallan MISMATCH("boot_cpuid_phys mismatch 0x%x != 0x%x", 229 1.1 macallan cpuid1, cpuid2); 230 1.1 macallan 231 1.1 macallan MATCH(); 232 1.1 macallan } 233