1/* 2 * libfdt - Flat Device Tree manipulation 3 * Tests if two given dtbs are structurally equal (including order) 4 * Copyright (C) 2010 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#include <limits.h> 26 27#include <libfdt.h> 28 29#include "tests.h" 30#include "testdata.h" 31 32#define CHECK(code) \ 33 { \ 34 err = (code); \ 35 if (err) \ 36 FAIL(#code ": %s", fdt_strerror(err)); \ 37 } 38 39static void reverse_reservemap(void *in, void *out, int n) 40{ 41 int err; 42 uint64_t addr, size; 43 44 verbose_printf("reverse_reservemap(): %d/%d\n", 45 n, fdt_num_mem_rsv(in)); 46 47 if (n < (fdt_num_mem_rsv(in)-1)) 48 reverse_reservemap(in, out, n+1); 49 50 CHECK(fdt_get_mem_rsv(in, n, &addr, &size)); 51 CHECK(fdt_add_reservemap_entry(out, addr, size)); 52 verbose_printf("Added entry 0x%llx 0x%llx\n", 53 (unsigned long long)addr, (unsigned long long)size); 54} 55 56static void reverse_properties(void *in, void *out, int offset) 57{ 58 int err; 59 int len; 60 const char *name; 61 const void *data; 62 63 data = fdt_getprop_by_offset(in, offset, &name, &len); 64 if (!data) 65 FAIL("fdt_getprop_by_offset(): %s\n", fdt_strerror(len)); 66 67 verbose_printf("reverse_properties(): offset=%d name=%s\n", 68 offset, name); 69 70 offset = fdt_next_property_offset(in, offset); 71 if (offset >= 0) 72 reverse_properties(in, out, offset); 73 else if (offset != -FDT_ERR_NOTFOUND) 74 FAIL("fdt_next_property_offset(): %s\n", fdt_strerror(offset)); 75 76 CHECK(fdt_property(out, name, data, len)); 77 verbose_printf(" -> output property %s\n", name); 78} 79 80static void reverse_node(void *in, void *out, int nodeoffset); 81 82static void reverse_children(void *in, void *out, int offset) 83{ 84 int err; 85 int nextoffset = offset; 86 int depth = 1; 87 88 do { 89 char path[PATH_MAX]; 90 91 CHECK(fdt_get_path(in, nextoffset, path, sizeof(path))); 92 verbose_printf("reverse_children() offset=%d nextoffset=%d [%s]" 93 " depth=%d\n", offset, nextoffset, path, depth); 94 95 nextoffset = fdt_next_node(in, nextoffset, &depth); 96 } while ((depth >= 0) && (depth != 1)); 97 98 if (depth == 1) 99 reverse_children(in, out, nextoffset); 100 101 reverse_node(in, out, offset); 102} 103 104static void reverse_node(void *in, void *out, int nodeoffset) 105{ 106 const char *name = fdt_get_name(in, nodeoffset, NULL); 107 char path[PATH_MAX]; 108 int err; 109 int offset; 110 int depth = 0; 111 112 CHECK(fdt_get_path(in, nodeoffset, path, sizeof(path))); 113 verbose_printf("reverse_node(): nodeoffset=%d [%s]\n", 114 nodeoffset, path); 115 116 CHECK(fdt_begin_node(out, name)); 117 118 offset = fdt_first_property_offset(in, nodeoffset); 119 if (offset >= 0) 120 reverse_properties(in, out, offset); 121 else if (offset != -FDT_ERR_NOTFOUND) 122 FAIL("fdt_first_property(): %s\n", fdt_strerror(offset)); 123 124 offset = fdt_next_node(in, nodeoffset, &depth); 125 126 if (depth == 1) 127 reverse_children(in, out, offset); 128 129 CHECK(fdt_end_node(out)); 130} 131 132int main(int argc, char *argv[]) 133{ 134 void *in, *out; 135 char outname[PATH_MAX]; 136 int bufsize; 137 int err; 138 139 test_init(argc, argv); 140 if (argc != 2) 141 CONFIG("Usage: %s <dtb file>", argv[0]); 142 143 in = load_blob(argv[1]); 144 sprintf(outname, "%s.reversed.test.dtb", argv[1]); 145 146 bufsize = fdt_totalsize(in); 147 out = xmalloc(bufsize); 148 149 CHECK(fdt_create(out, bufsize)); 150 151 fdt_set_boot_cpuid_phys(out, fdt_boot_cpuid_phys(in)); 152 153 reverse_reservemap(in, out, 0); 154 CHECK(fdt_finish_reservemap(out)); 155 156 reverse_node(in, out, 0); 157 158 CHECK(fdt_finish(out)); 159 160 save_blob(outname, out); 161 162 PASS(); 163} 164