1 /* $NetBSD: mangle-layout.c,v 1.4 2019/12/22 12:38:24 skrll Exp $ */ 2 3 // SPDX-License-Identifier: LGPL-2.1-or-later 4 /* 5 * libfdt - Flat Device Tree manipulation 6 * Testcase/tool for rearranging blocks of a dtb 7 * Copyright (C) 2006 David Gibson, IBM Corporation. 8 */ 9 10 #include <stdlib.h> 11 #include <stdio.h> 12 #include <string.h> 13 #include <limits.h> 14 #include <stdint.h> 15 16 #include <libfdt.h> 17 18 #include "tests.h" 19 #include "testdata.h" 20 21 struct bufstate { 22 char *buf; 23 int size; 24 }; 25 26 static void expand_buf(struct bufstate *buf, int newsize) 27 { 28 buf->buf = realloc(buf->buf, newsize); 29 if (!buf->buf) 30 CONFIG("Allocation failure"); 31 buf->size = newsize; 32 } 33 34 static void new_header(struct bufstate *buf, int version, const void *fdt) 35 { 36 int hdrsize = fdt_header_size_(version); 37 38 if ((version != 16) && (version != 17)) 39 CONFIG("Bad version %d", version); 40 41 expand_buf(buf, hdrsize); 42 memset(buf->buf, 0, hdrsize); 43 44 fdt_set_magic(buf->buf, FDT_MAGIC); 45 fdt_set_version(buf->buf, version); 46 fdt_set_last_comp_version(buf->buf, 16); 47 fdt_set_boot_cpuid_phys(buf->buf, fdt_boot_cpuid_phys(fdt)); 48 } 49 50 static void add_block(struct bufstate *buf, int version, char block, const void *fdt) 51 { 52 int align, size, oldsize; 53 const void *src; 54 int offset; 55 56 switch (block) { 57 case 'm': 58 /* Memory reserve map */ 59 align = 8; 60 src = (const char *)fdt + fdt_off_mem_rsvmap(fdt); 61 size = (fdt_num_mem_rsv(fdt) + 1) 62 * sizeof(struct fdt_reserve_entry); 63 break; 64 65 case 't': 66 /* Structure block */ 67 align = 4; 68 src = (const char *)fdt + fdt_off_dt_struct(fdt); 69 size = fdt_size_dt_struct(fdt); 70 break; 71 72 case 's': 73 /* Strings block */ 74 align = 1; 75 src = (const char *)fdt + fdt_off_dt_strings(fdt); 76 size = fdt_size_dt_strings(fdt); 77 break; 78 default: 79 CONFIG("Bad block '%c'", block); 80 } 81 82 oldsize = buf->size; 83 offset = FDTALIGN2(oldsize, align); 84 expand_buf(buf, offset+size); 85 memset(buf->buf + oldsize, 0, offset - oldsize); 86 87 memcpy(buf->buf + offset, src, size); 88 89 switch (block) { 90 case 'm': 91 fdt_set_off_mem_rsvmap(buf->buf, offset); 92 break; 93 94 case 't': 95 fdt_set_off_dt_struct(buf->buf, offset); 96 if (version >= 17) 97 fdt_set_size_dt_struct(buf->buf, size); 98 break; 99 100 case 's': 101 fdt_set_off_dt_strings(buf->buf, offset); 102 fdt_set_size_dt_strings(buf->buf, size); 103 break; 104 } 105 } 106 107 int main(int argc, char *argv[]) 108 { 109 void *fdt; 110 int version; 111 const char *blockorder; 112 struct bufstate buf = {NULL, 0}; 113 int err; 114 const char *inname; 115 char outname[PATH_MAX]; 116 117 test_init(argc, argv); 118 if (argc != 4) 119 CONFIG("Usage: %s <dtb file> <version> <block order>", argv[0]); 120 121 inname = argv[1]; 122 fdt = load_blob(argv[1]); 123 version = atoi(argv[2]); 124 blockorder = argv[3]; 125 sprintf(outname, "v%d.%s.%s", version, blockorder, inname); 126 127 if ((version != 16) && (version != 17)) 128 CONFIG("Version must be 16 or 17"); 129 130 if (fdt_version(fdt) < 17) 131 CONFIG("Input tree must be v17"); 132 133 new_header(&buf, version, fdt); 134 135 while (*blockorder) { 136 add_block(&buf, version, *blockorder, fdt); 137 blockorder++; 138 } 139 140 fdt_set_totalsize(buf.buf, buf.size); 141 142 err = fdt_check_header(buf.buf); 143 if (err) 144 FAIL("Output tree fails check: %s", fdt_strerror(err)); 145 146 save_blob(outname, buf.buf); 147 148 PASS(); 149 } 150