1 /* $NetBSD: mangle-layout.c,v 1.3 2017/06/08 16:00:40 skrll Exp $ */ 2 3 /* 4 * libfdt - Flat Device Tree manipulation 5 * Testcase/tool for rearranging blocks of a dtb 6 * Copyright (C) 2006 David Gibson, IBM Corporation. 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public License 10 * as published by the Free Software Foundation; either version 2.1 of 11 * the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23 #include <stdlib.h> 24 #include <stdio.h> 25 #include <string.h> 26 #include <limits.h> 27 #include <stdint.h> 28 29 #include <libfdt.h> 30 31 #include "tests.h" 32 #include "testdata.h" 33 34 struct bufstate { 35 char *buf; 36 int size; 37 }; 38 39 static void expand_buf(struct bufstate *buf, int newsize) 40 { 41 buf->buf = realloc(buf->buf, newsize); 42 if (!buf->buf) 43 CONFIG("Allocation failure"); 44 buf->size = newsize; 45 } 46 47 static void new_header(struct bufstate *buf, int version, const void *fdt) 48 { 49 int hdrsize; 50 51 if (version == 16) 52 hdrsize = FDT_V16_SIZE; 53 else if (version == 17) 54 hdrsize = FDT_V17_SIZE; 55 else 56 CONFIG("Bad version %d", version); 57 58 expand_buf(buf, hdrsize); 59 memset(buf->buf, 0, hdrsize); 60 61 fdt_set_magic(buf->buf, FDT_MAGIC); 62 fdt_set_version(buf->buf, version); 63 fdt_set_last_comp_version(buf->buf, 16); 64 fdt_set_boot_cpuid_phys(buf->buf, fdt_boot_cpuid_phys(fdt)); 65 } 66 67 static void add_block(struct bufstate *buf, int version, char block, const void *fdt) 68 { 69 int align, size, oldsize; 70 const void *src; 71 int offset; 72 73 switch (block) { 74 case 'm': 75 /* Memory reserve map */ 76 align = 8; 77 src = (const char *)fdt + fdt_off_mem_rsvmap(fdt); 78 size = (fdt_num_mem_rsv(fdt) + 1) 79 * sizeof(struct fdt_reserve_entry); 80 break; 81 82 case 't': 83 /* Structure block */ 84 align = 4; 85 src = (const char *)fdt + fdt_off_dt_struct(fdt); 86 size = fdt_size_dt_struct(fdt); 87 break; 88 89 case 's': 90 /* Strings block */ 91 align = 1; 92 src = (const char *)fdt + fdt_off_dt_strings(fdt); 93 size = fdt_size_dt_strings(fdt); 94 break; 95 default: 96 CONFIG("Bad block '%c'", block); 97 } 98 99 oldsize = buf->size; 100 offset = FDTALIGN2(oldsize, align); 101 expand_buf(buf, offset+size); 102 memset(buf->buf + oldsize, 0, offset - oldsize); 103 104 memcpy(buf->buf + offset, src, size); 105 106 switch (block) { 107 case 'm': 108 fdt_set_off_mem_rsvmap(buf->buf, offset); 109 break; 110 111 case 't': 112 fdt_set_off_dt_struct(buf->buf, offset); 113 if (version >= 17) 114 fdt_set_size_dt_struct(buf->buf, size); 115 break; 116 117 case 's': 118 fdt_set_off_dt_strings(buf->buf, offset); 119 fdt_set_size_dt_strings(buf->buf, size); 120 break; 121 } 122 } 123 124 int main(int argc, char *argv[]) 125 { 126 void *fdt; 127 int version; 128 const char *blockorder; 129 struct bufstate buf = {NULL, 0}; 130 int err; 131 const char *inname; 132 char outname[PATH_MAX]; 133 134 test_init(argc, argv); 135 if (argc != 4) 136 CONFIG("Usage: %s <dtb file> <version> <block order>", argv[0]); 137 138 inname = argv[1]; 139 fdt = load_blob(argv[1]); 140 version = atoi(argv[2]); 141 blockorder = argv[3]; 142 sprintf(outname, "v%d.%s.%s", version, blockorder, inname); 143 144 if ((version != 16) && (version != 17)) 145 CONFIG("Version must be 16 or 17"); 146 147 if (fdt_version(fdt) < 17) 148 CONFIG("Input tree must be v17"); 149 150 new_header(&buf, version, fdt); 151 152 while (*blockorder) { 153 add_block(&buf, version, *blockorder, fdt); 154 blockorder++; 155 } 156 157 fdt_set_totalsize(buf.buf, buf.size); 158 159 err = fdt_check_header(buf.buf); 160 if (err) 161 FAIL("Output tree fails check: %s", fdt_strerror(err)); 162 163 save_blob(outname, buf.buf); 164 165 PASS(); 166 } 167