1 /* $NetBSD: dtbs_equal_ordered.c,v 1.1.1.3 2019/12/22 12:34:06 skrll Exp $ */ 2 3 // SPDX-License-Identifier: LGPL-2.1-or-later 4 /* 5 * libfdt - Flat Device Tree manipulation 6 * Tests if two given dtbs are structurally equal (including order) 7 * Copyright (C) 2007 David Gibson, IBM Corporation. 8 */ 9 10 #include <stdlib.h> 11 #include <stdio.h> 12 #include <string.h> 13 #include <stdint.h> 14 15 #include <libfdt.h> 16 17 #include "tests.h" 18 #include "testdata.h" 19 20 static int notequal; /* = 0 */ 21 22 #define MISMATCH(fmt, ...) \ 23 do { \ 24 if (notequal) \ 25 PASS(); \ 26 else \ 27 FAIL(fmt, ##__VA_ARGS__); \ 28 } while (0) 29 30 #define MATCH() \ 31 do { \ 32 if (!notequal) \ 33 PASS(); \ 34 else \ 35 FAIL("Trees match which shouldn't"); \ 36 } while (0) 37 38 #define CHECK(code) \ 39 { \ 40 err = (code); \ 41 if (err) \ 42 FAIL(#code ": %s", fdt_strerror(err)); \ 43 } 44 45 static void compare_mem_rsv(const void *fdt1, const void *fdt2) 46 { 47 int i; 48 uint64_t addr1, size1, addr2, size2; 49 int err; 50 51 if (fdt_num_mem_rsv(fdt1) != fdt_num_mem_rsv(fdt2)) 52 MISMATCH("Trees have different number of reserve entries"); 53 for (i = 0; i < fdt_num_mem_rsv(fdt1); i++) { 54 CHECK(fdt_get_mem_rsv(fdt1, i, &addr1, &size1)); 55 CHECK(fdt_get_mem_rsv(fdt2, i, &addr2, &size2)); 56 57 if ((addr1 != addr2) || (size1 != size2)) 58 MISMATCH("Mismatch in reserve entry %d: " 59 "(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i, 60 (unsigned long long)addr1, 61 (unsigned long long)size1, 62 (unsigned long long)addr2, 63 (unsigned long long)size2); 64 } 65 } 66 67 static void compare_structure(const void *fdt1, const void *fdt2) 68 { 69 int nextoffset1 = 0, nextoffset2 = 0; 70 int offset1, offset2; 71 uint32_t tag1, tag2; 72 const char *name1, *name2; 73 int err; 74 const struct fdt_property *prop1, *prop2; 75 int len1, len2; 76 77 while (1) { 78 do { 79 offset1 = nextoffset1; 80 tag1 = fdt_next_tag(fdt1, offset1, &nextoffset1); 81 } while (tag1 == FDT_NOP); 82 do { 83 offset2 = nextoffset2; 84 tag2 = fdt_next_tag(fdt2, offset2, &nextoffset2); 85 } while (tag2 == FDT_NOP); 86 87 if (tag1 != tag2) 88 MISMATCH("Tag mismatch (%d != %d) at (%d, %d)", 89 tag1, tag2, offset1, offset2); 90 91 switch (tag1) { 92 case FDT_BEGIN_NODE: 93 name1 = fdt_get_name(fdt1, offset1, &err); 94 if (!name1) 95 FAIL("fdt_get_name(fdt1, %d, ..): %s", 96 offset1, fdt_strerror(err)); 97 name2 = fdt_get_name(fdt2, offset2, NULL); 98 if (!name2) 99 FAIL("fdt_get_name(fdt2, %d, ..): %s", 100 offset2, fdt_strerror(err)); 101 102 if (!streq(name1, name2)) 103 MISMATCH("Name mismatch (\"%s\" != \"%s\") at (%d, %d)", 104 name1, name2, offset1, offset2); 105 break; 106 107 case FDT_PROP: 108 prop1 = fdt_offset_ptr(fdt1, offset1, sizeof(*prop1)); 109 if (!prop1) 110 FAIL("Could get fdt1 property at %d", offset1); 111 prop2 = fdt_offset_ptr(fdt2, offset2, sizeof(*prop2)); 112 if (!prop2) 113 FAIL("Could get fdt2 property at %d", offset2); 114 115 name1 = fdt_string(fdt1, fdt32_to_cpu(prop1->nameoff)); 116 name2 = fdt_string(fdt2, fdt32_to_cpu(prop2->nameoff)); 117 if (!streq(name1, name2)) 118 MISMATCH("Property name mismatch \"%s\" != \"%s\" " 119 "at (%d, %d)", name1, name2, offset1, offset2); 120 len1 = fdt32_to_cpu(prop1->len); 121 len2 = fdt32_to_cpu(prop2->len); 122 if (len1 != len2) 123 MISMATCH("Property length mismatch %u != %u " 124 "at (%d, %d)", len1, len2, offset1, offset2); 125 126 if (memcmp(prop1->data, prop2->data, len1) != 0) 127 MISMATCH("Property value mismatch at (%d, %d)", 128 offset1, offset2); 129 break; 130 131 case FDT_END: 132 return; 133 } 134 } 135 } 136 137 int main(int argc, char *argv[]) 138 { 139 void *fdt1, *fdt2; 140 uint32_t cpuid1, cpuid2; 141 142 test_init(argc, argv); 143 if ((argc != 3) 144 && ((argc != 4) || !streq(argv[1], "-n"))) 145 CONFIG("Usage: %s [-n] <dtb file> <dtb file>", argv[0]); 146 if (argc == 4) 147 notequal = 1; 148 149 fdt1 = load_blob(argv[argc-2]); 150 fdt2 = load_blob(argv[argc-1]); 151 152 compare_mem_rsv(fdt1, fdt2); 153 compare_structure(fdt1, fdt2); 154 155 cpuid1 = fdt_boot_cpuid_phys(fdt1); 156 cpuid2 = fdt_boot_cpuid_phys(fdt2); 157 if (cpuid1 != cpuid2) 158 MISMATCH("boot_cpuid_phys mismatch 0x%x != 0x%x", 159 cpuid1, cpuid2); 160 161 MATCH(); 162 } 163