|
1 /* |
|
2 * libfdt - Flat Device Tree manipulation |
|
3 * Tests if two given dtbs are structurally equal (including order) |
|
4 * Copyright (C) 2007 David Gibson, IBM Corporation. |
|
5 * |
|
6 * This library is free software; you can redistribute it and/or |
|
7 * modify it under the terms of the GNU Lesser General Public License |
|
8 * as published by the Free Software Foundation; either version 2.1 of |
|
9 * the License, or (at your option) any later version. |
|
10 * |
|
11 * This library is distributed in the hope that it will be useful, but |
|
12 * WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 * Lesser General Public License for more details. |
|
15 * |
|
16 * You should have received a copy of the GNU Lesser General Public |
|
17 * License along with this library; if not, write to the Free Software |
|
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|
19 */ |
|
20 |
|
21 #include <stdlib.h> |
|
22 #include <stdio.h> |
|
23 #include <string.h> |
|
24 #include <stdint.h> |
|
25 |
|
26 #include <fdt.h> |
|
27 #include <libfdt.h> |
|
28 |
|
29 #include "tests.h" |
|
30 #include "testdata.h" |
|
31 |
|
32 void compare_mem_rsv(const void *fdt1, const void *fdt2) |
|
33 { |
|
34 int i; |
|
35 uint64_t addr1, size1, addr2, size2; |
|
36 int err; |
|
37 |
|
38 if (fdt_num_mem_rsv(fdt1) != fdt_num_mem_rsv(fdt2)) |
|
39 FAIL("Trees have different number of reserve entries"); |
|
40 for (i = 0; i < fdt_num_mem_rsv(fdt1); i++) { |
|
41 err = fdt_get_mem_rsv(fdt1, i, &addr1, &size1); |
|
42 if (err) |
|
43 FAIL("fdt_get_mem_rsv(fdt1, %d, ...): %s", i, |
|
44 fdt_strerror(err)); |
|
45 err = fdt_get_mem_rsv(fdt2, i, &addr2, &size2); |
|
46 if (err) |
|
47 FAIL("fdt_get_mem_rsv(fdt2, %d, ...): %s", i, |
|
48 fdt_strerror(err)); |
|
49 if ((addr1 != addr2) || (size1 != size2)) |
|
50 FAIL("Mismatch in reserve entry %d: " |
|
51 "(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i, |
|
52 (unsigned long long)addr1, |
|
53 (unsigned long long)size1, |
|
54 (unsigned long long)addr2, |
|
55 (unsigned long long)size2); |
|
56 } |
|
57 } |
|
58 |
|
59 void compare_structure(const void *fdt1, const void *fdt2) |
|
60 { |
|
61 int nextoffset1 = 0, nextoffset2 = 0; |
|
62 int offset1, offset2; |
|
63 uint32_t tag1, tag2; |
|
64 const char *name1, *name2; |
|
65 int err; |
|
66 const struct fdt_property *prop1, *prop2; |
|
67 int len1, len2; |
|
68 |
|
69 while (1) { |
|
70 do { |
|
71 offset1 = nextoffset1; |
|
72 tag1 = fdt_next_tag(fdt1, offset1, &nextoffset1); |
|
73 } while (tag1 == FDT_NOP); |
|
74 do { |
|
75 offset2 = nextoffset2; |
|
76 tag2 = fdt_next_tag(fdt2, offset2, &nextoffset2); |
|
77 } while (tag2 == FDT_NOP); |
|
78 |
|
79 if (tag1 != tag2) |
|
80 FAIL("Tag mismatch (%d != %d) at (%d, %d)", |
|
81 tag1, tag2, offset1, offset2); |
|
82 |
|
83 switch (tag1) { |
|
84 case FDT_BEGIN_NODE: |
|
85 name1 = fdt_get_name(fdt1, offset1, &err); |
|
86 if (!name1) |
|
87 FAIL("fdt_get_name(fdt1, %d, ..): %s", |
|
88 offset1, fdt_strerror(err)); |
|
89 name2 = fdt_get_name(fdt2, offset2, NULL); |
|
90 if (!name2) |
|
91 FAIL("fdt_get_name(fdt2, %d, ..): %s", |
|
92 offset2, fdt_strerror(err)); |
|
93 if (!streq(name1, name2)) |
|
94 FAIL("Name mismatch (\"%s\" != \"%s\") at (%d, %d)", |
|
95 name1, name2, offset1, offset2); |
|
96 break; |
|
97 |
|
98 case FDT_PROP: |
|
99 prop1 = fdt_offset_ptr(fdt1, offset1, sizeof(*prop1)); |
|
100 if (!prop1) |
|
101 FAIL("Could get fdt1 property at %d", offset1); |
|
102 prop2 = fdt_offset_ptr(fdt2, offset2, sizeof(*prop2)); |
|
103 if (!prop2) |
|
104 FAIL("Could get fdt2 property at %d", offset2); |
|
105 |
|
106 name1 = fdt_string(fdt1, fdt32_to_cpu(prop1->nameoff)); |
|
107 name2 = fdt_string(fdt2, fdt32_to_cpu(prop2->nameoff)); |
|
108 if (!streq(name1, name2)) |
|
109 FAIL("Property name mismatch \"%s\" != \"%s\" " |
|
110 "at (%d, %d)", name1, name2, offset1, offset2); |
|
111 len1 = fdt32_to_cpu(prop1->len); |
|
112 len2 = fdt32_to_cpu(prop2->len); |
|
113 if (len1 != len2) |
|
114 FAIL("Property length mismatch %u != %u " |
|
115 "at (%d, %d)", len1, len2, offset1, offset2); |
|
116 |
|
117 if (memcmp(prop1->data, prop2->data, len1) != 0) |
|
118 FAIL("Property value mismatch at (%d, %d)", |
|
119 offset1, offset2); |
|
120 break; |
|
121 |
|
122 case FDT_END: |
|
123 return; |
|
124 } |
|
125 } |
|
126 } |
|
127 |
|
128 int main(int argc, char *argv[]) |
|
129 { |
|
130 void *fdt1, *fdt2; |
|
131 uint32_t cpuid1, cpuid2; |
|
132 |
|
133 test_init(argc, argv); |
|
134 if (argc != 3) |
|
135 CONFIG("Usage: %s <dtb file> <dtb file>", argv[0]); |
|
136 fdt1 = load_blob(argv[1]); |
|
137 fdt2 = load_blob(argv[2]); |
|
138 |
|
139 compare_mem_rsv(fdt1, fdt2); |
|
140 compare_structure(fdt1, fdt2); |
|
141 |
|
142 cpuid1 = fdt_boot_cpuid_phys(fdt1); |
|
143 cpuid2 = fdt_boot_cpuid_phys(fdt2); |
|
144 if (cpuid1 != cpuid2) |
|
145 FAIL("boot_cpuid_phys mismatch 0x%x != 0x%x", |
|
146 cpuid1, cpuid2); |
|
147 |
|
148 PASS(); |
|
149 } |