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