| // SPDX-License-Identifier: LGPL-2.1-or-later |
| /* |
| * libfdt - Flat Device Tree manipulation |
| * Tests if two given dtbs are structurally equal (including order) |
| * Copyright (C) 2010 David Gibson, IBM Corporation. |
| */ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdint.h> |
| #include <limits.h> |
| |
| #include <libfdt.h> |
| |
| #include "tests.h" |
| #include "testdata.h" |
| |
| #define CHECK(code) \ |
| { \ |
| err = (code); \ |
| if (err) \ |
| FAIL(#code ": %s", fdt_strerror(err)); \ |
| } |
| |
| static void reverse_reservemap(void *in, void *out, int n) |
| { |
| int err; |
| uint64_t addr, size; |
| |
| verbose_printf("reverse_reservemap(): %d/%d\n", |
| n, fdt_num_mem_rsv(in)); |
| |
| if (n < (fdt_num_mem_rsv(in)-1)) |
| reverse_reservemap(in, out, n+1); |
| |
| CHECK(fdt_get_mem_rsv(in, n, &addr, &size)); |
| CHECK(fdt_add_reservemap_entry(out, addr, size)); |
| verbose_printf("Added entry 0x%llx 0x%llx\n", |
| (unsigned long long)addr, (unsigned long long)size); |
| } |
| |
| static void reverse_properties(void *in, void *out, int offset) |
| { |
| int err; |
| int len; |
| const char *name; |
| const void *data; |
| |
| data = fdt_getprop_by_offset(in, offset, &name, &len); |
| if (!data) |
| FAIL("fdt_getprop_by_offset(): %s\n", fdt_strerror(len)); |
| |
| verbose_printf("reverse_properties(): offset=%d name=%s\n", |
| offset, name); |
| |
| offset = fdt_next_property_offset(in, offset); |
| if (offset >= 0) |
| reverse_properties(in, out, offset); |
| else if (offset != -FDT_ERR_NOTFOUND) |
| FAIL("fdt_next_property_offset(): %s\n", fdt_strerror(offset)); |
| |
| CHECK(fdt_property(out, name, data, len)); |
| verbose_printf(" -> output property %s\n", name); |
| } |
| |
| static void reverse_node(void *in, void *out, int nodeoffset); |
| |
| static void reverse_children(void *in, void *out, int offset) |
| { |
| int err; |
| int nextoffset = offset; |
| int depth = 1; |
| |
| do { |
| char path[PATH_MAX]; |
| |
| CHECK(fdt_get_path(in, nextoffset, path, sizeof(path))); |
| verbose_printf("reverse_children() offset=%d nextoffset=%d [%s]" |
| " depth=%d\n", offset, nextoffset, path, depth); |
| |
| nextoffset = fdt_next_node(in, nextoffset, &depth); |
| } while ((depth >= 0) && (depth != 1)); |
| |
| if (depth == 1) |
| reverse_children(in, out, nextoffset); |
| |
| reverse_node(in, out, offset); |
| } |
| |
| static void reverse_node(void *in, void *out, int nodeoffset) |
| { |
| const char *name = fdt_get_name(in, nodeoffset, NULL); |
| char path[PATH_MAX]; |
| int err; |
| int offset; |
| int depth = 0; |
| |
| CHECK(fdt_get_path(in, nodeoffset, path, sizeof(path))); |
| verbose_printf("reverse_node(): nodeoffset=%d [%s]\n", |
| nodeoffset, path); |
| |
| CHECK(fdt_begin_node(out, name)); |
| |
| offset = fdt_first_property_offset(in, nodeoffset); |
| if (offset >= 0) |
| reverse_properties(in, out, offset); |
| else if (offset != -FDT_ERR_NOTFOUND) |
| FAIL("fdt_first_property(): %s\n", fdt_strerror(offset)); |
| |
| offset = fdt_next_node(in, nodeoffset, &depth); |
| |
| if (depth == 1) |
| reverse_children(in, out, offset); |
| |
| CHECK(fdt_end_node(out)); |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| void *in, *out; |
| char outname[PATH_MAX]; |
| int bufsize; |
| int err; |
| |
| test_init(argc, argv); |
| if (argc != 2) |
| CONFIG("Usage: %s <dtb file>", argv[0]); |
| |
| in = load_blob(argv[1]); |
| sprintf(outname, "%s.reversed.test.dtb", argv[1]); |
| |
| bufsize = fdt_totalsize(in); |
| out = xmalloc(bufsize); |
| |
| CHECK(fdt_create(out, bufsize)); |
| |
| fdt_set_boot_cpuid_phys(out, fdt_boot_cpuid_phys(in)); |
| |
| reverse_reservemap(in, out, 0); |
| CHECK(fdt_finish_reservemap(out)); |
| |
| reverse_node(in, out, 0); |
| |
| CHECK(fdt_finish(out)); |
| |
| save_blob(outname, out); |
| |
| PASS(); |
| } |