1*ad6eb39cSmacallan /* 2*ad6eb39cSmacallan * libfdt - Flat Device Tree manipulation 3*ad6eb39cSmacallan * Tests if two given dtbs are structurally equal (including order) 4*ad6eb39cSmacallan * Copyright (C) 2010 David Gibson, IBM Corporation. 5*ad6eb39cSmacallan * 6*ad6eb39cSmacallan * This library is free software; you can redistribute it and/or 7*ad6eb39cSmacallan * modify it under the terms of the GNU Lesser General Public License 8*ad6eb39cSmacallan * as published by the Free Software Foundation; either version 2.1 of 9*ad6eb39cSmacallan * the License, or (at your option) any later version. 10*ad6eb39cSmacallan * 11*ad6eb39cSmacallan * This library is distributed in the hope that it will be useful, but 12*ad6eb39cSmacallan * WITHOUT ANY WARRANTY; without even the implied warranty of 13*ad6eb39cSmacallan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*ad6eb39cSmacallan * Lesser General Public License for more details. 15*ad6eb39cSmacallan * 16*ad6eb39cSmacallan * You should have received a copy of the GNU Lesser General Public 17*ad6eb39cSmacallan * License along with this library; if not, write to the Free Software 18*ad6eb39cSmacallan * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19*ad6eb39cSmacallan */ 20*ad6eb39cSmacallan 21*ad6eb39cSmacallan #include <stdlib.h> 22*ad6eb39cSmacallan #include <stdio.h> 23*ad6eb39cSmacallan #include <string.h> 24*ad6eb39cSmacallan #include <stdint.h> 25*ad6eb39cSmacallan #include <limits.h> 26*ad6eb39cSmacallan 27*ad6eb39cSmacallan #include <libfdt.h> 28*ad6eb39cSmacallan 29*ad6eb39cSmacallan #include "tests.h" 30*ad6eb39cSmacallan #include "testdata.h" 31*ad6eb39cSmacallan 32*ad6eb39cSmacallan #define CHECK(code) \ 33*ad6eb39cSmacallan { \ 34*ad6eb39cSmacallan err = (code); \ 35*ad6eb39cSmacallan if (err) \ 36*ad6eb39cSmacallan FAIL(#code ": %s", fdt_strerror(err)); \ 37*ad6eb39cSmacallan } 38*ad6eb39cSmacallan 39*ad6eb39cSmacallan static void reverse_reservemap(void *in, void *out, int n) 40*ad6eb39cSmacallan { 41*ad6eb39cSmacallan int err; 42*ad6eb39cSmacallan uint64_t addr, size; 43*ad6eb39cSmacallan 44*ad6eb39cSmacallan verbose_printf("reverse_reservemap(): %d/%d\n", 45*ad6eb39cSmacallan n, fdt_num_mem_rsv(in)); 46*ad6eb39cSmacallan 47*ad6eb39cSmacallan if (n < (fdt_num_mem_rsv(in)-1)) 48*ad6eb39cSmacallan reverse_reservemap(in, out, n+1); 49*ad6eb39cSmacallan 50*ad6eb39cSmacallan CHECK(fdt_get_mem_rsv(in, n, &addr, &size)); 51*ad6eb39cSmacallan CHECK(fdt_add_reservemap_entry(out, addr, size)); 52*ad6eb39cSmacallan verbose_printf("Added entry 0x%llx 0x%llx\n", 53*ad6eb39cSmacallan (unsigned long long)addr, (unsigned long long)size); 54*ad6eb39cSmacallan } 55*ad6eb39cSmacallan 56*ad6eb39cSmacallan static void reverse_properties(void *in, void *out, int offset) 57*ad6eb39cSmacallan { 58*ad6eb39cSmacallan int err; 59*ad6eb39cSmacallan int len; 60*ad6eb39cSmacallan const char *name; 61*ad6eb39cSmacallan const void *data; 62*ad6eb39cSmacallan 63*ad6eb39cSmacallan data = fdt_getprop_by_offset(in, offset, &name, &len); 64*ad6eb39cSmacallan if (!data) 65*ad6eb39cSmacallan FAIL("fdt_getprop_by_offset(): %s\n", fdt_strerror(len)); 66*ad6eb39cSmacallan 67*ad6eb39cSmacallan verbose_printf("reverse_properties(): offset=%d name=%s\n", 68*ad6eb39cSmacallan offset, name); 69*ad6eb39cSmacallan 70*ad6eb39cSmacallan offset = fdt_next_property_offset(in, offset); 71*ad6eb39cSmacallan if (offset >= 0) 72*ad6eb39cSmacallan reverse_properties(in, out, offset); 73*ad6eb39cSmacallan else if (offset != -FDT_ERR_NOTFOUND) 74*ad6eb39cSmacallan FAIL("fdt_next_property_offset(): %s\n", fdt_strerror(offset)); 75*ad6eb39cSmacallan 76*ad6eb39cSmacallan CHECK(fdt_property(out, name, data, len)); 77*ad6eb39cSmacallan verbose_printf(" -> output property %s\n", name); 78*ad6eb39cSmacallan } 79*ad6eb39cSmacallan 80*ad6eb39cSmacallan static void reverse_node(void *in, void *out, int nodeoffset); 81*ad6eb39cSmacallan 82*ad6eb39cSmacallan static void reverse_children(void *in, void *out, int offset) 83*ad6eb39cSmacallan { 84*ad6eb39cSmacallan int err; 85*ad6eb39cSmacallan int nextoffset = offset; 86*ad6eb39cSmacallan int depth = 1; 87*ad6eb39cSmacallan 88*ad6eb39cSmacallan do { 89*ad6eb39cSmacallan char path[PATH_MAX]; 90*ad6eb39cSmacallan 91*ad6eb39cSmacallan CHECK(fdt_get_path(in, nextoffset, path, sizeof(path))); 92*ad6eb39cSmacallan verbose_printf("reverse_children() offset=%d nextoffset=%d [%s]" 93*ad6eb39cSmacallan " depth=%d\n", offset, nextoffset, path, depth); 94*ad6eb39cSmacallan 95*ad6eb39cSmacallan nextoffset = fdt_next_node(in, nextoffset, &depth); 96*ad6eb39cSmacallan } while ((depth >= 0) && (depth != 1)); 97*ad6eb39cSmacallan 98*ad6eb39cSmacallan if (depth == 1) 99*ad6eb39cSmacallan reverse_children(in, out, nextoffset); 100*ad6eb39cSmacallan 101*ad6eb39cSmacallan reverse_node(in, out, offset); 102*ad6eb39cSmacallan } 103*ad6eb39cSmacallan 104*ad6eb39cSmacallan static void reverse_node(void *in, void *out, int nodeoffset) 105*ad6eb39cSmacallan { 106*ad6eb39cSmacallan const char *name = fdt_get_name(in, nodeoffset, NULL); 107*ad6eb39cSmacallan char path[PATH_MAX]; 108*ad6eb39cSmacallan int err; 109*ad6eb39cSmacallan int offset; 110*ad6eb39cSmacallan int depth = 0; 111*ad6eb39cSmacallan 112*ad6eb39cSmacallan CHECK(fdt_get_path(in, nodeoffset, path, sizeof(path))); 113*ad6eb39cSmacallan verbose_printf("reverse_node(): nodeoffset=%d [%s]\n", 114*ad6eb39cSmacallan nodeoffset, path); 115*ad6eb39cSmacallan 116*ad6eb39cSmacallan CHECK(fdt_begin_node(out, name)); 117*ad6eb39cSmacallan 118*ad6eb39cSmacallan offset = fdt_first_property_offset(in, nodeoffset); 119*ad6eb39cSmacallan if (offset >= 0) 120*ad6eb39cSmacallan reverse_properties(in, out, offset); 121*ad6eb39cSmacallan else if (offset != -FDT_ERR_NOTFOUND) 122*ad6eb39cSmacallan FAIL("fdt_first_property(): %s\n", fdt_strerror(offset)); 123*ad6eb39cSmacallan 124*ad6eb39cSmacallan offset = fdt_next_node(in, nodeoffset, &depth); 125*ad6eb39cSmacallan 126*ad6eb39cSmacallan if (depth == 1) 127*ad6eb39cSmacallan reverse_children(in, out, offset); 128*ad6eb39cSmacallan 129*ad6eb39cSmacallan CHECK(fdt_end_node(out)); 130*ad6eb39cSmacallan } 131*ad6eb39cSmacallan 132*ad6eb39cSmacallan int main(int argc, char *argv[]) 133*ad6eb39cSmacallan { 134*ad6eb39cSmacallan void *in, *out; 135*ad6eb39cSmacallan char outname[PATH_MAX]; 136*ad6eb39cSmacallan int bufsize; 137*ad6eb39cSmacallan int err; 138*ad6eb39cSmacallan 139*ad6eb39cSmacallan test_init(argc, argv); 140*ad6eb39cSmacallan if (argc != 2) 141*ad6eb39cSmacallan CONFIG("Usage: %s <dtb file>", argv[0]); 142*ad6eb39cSmacallan 143*ad6eb39cSmacallan in = load_blob(argv[1]); 144*ad6eb39cSmacallan sprintf(outname, "%s.reversed.test.dtb", argv[1]); 145*ad6eb39cSmacallan 146*ad6eb39cSmacallan bufsize = fdt_totalsize(in); 147*ad6eb39cSmacallan out = xmalloc(bufsize); 148*ad6eb39cSmacallan 149*ad6eb39cSmacallan CHECK(fdt_create(out, bufsize)); 150*ad6eb39cSmacallan 151*ad6eb39cSmacallan fdt_set_boot_cpuid_phys(out, fdt_boot_cpuid_phys(in)); 152*ad6eb39cSmacallan 153*ad6eb39cSmacallan reverse_reservemap(in, out, 0); 154*ad6eb39cSmacallan CHECK(fdt_finish_reservemap(out)); 155*ad6eb39cSmacallan 156*ad6eb39cSmacallan reverse_node(in, out, 0); 157*ad6eb39cSmacallan 158*ad6eb39cSmacallan CHECK(fdt_finish(out)); 159*ad6eb39cSmacallan 160*ad6eb39cSmacallan save_blob(outname, out); 161*ad6eb39cSmacallan 162*ad6eb39cSmacallan PASS(); 163*ad6eb39cSmacallan } 164