1c0e032e0STom Rini /* 2c0e032e0STom Rini * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 3c0e032e0STom Rini * 4c0e032e0STom Rini * 5c0e032e0STom Rini * This program is free software; you can redistribute it and/or 6c0e032e0STom Rini * modify it under the terms of the GNU General Public License as 7c0e032e0STom Rini * published by the Free Software Foundation; either version 2 of the 8c0e032e0STom Rini * License, or (at your option) any later version. 9c0e032e0STom Rini * 10c0e032e0STom Rini * This program is distributed in the hope that it will be useful, 11c0e032e0STom Rini * but WITHOUT ANY WARRANTY; without even the implied warranty of 12c0e032e0STom Rini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13c0e032e0STom Rini * General Public License for more details. 14c0e032e0STom Rini * 15c0e032e0STom Rini * You should have received a copy of the GNU General Public License 16c0e032e0STom Rini * along with this program; if not, write to the Free Software 17c0e032e0STom Rini * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 18c0e032e0STom Rini * USA 19c0e032e0STom Rini */ 20c0e032e0STom Rini 21c0e032e0STom Rini #include "dtc.h" 22c0e032e0STom Rini 23c0e032e0STom Rini void data_free(struct data d) 24c0e032e0STom Rini { 25c0e032e0STom Rini struct marker *m, *nm; 26c0e032e0STom Rini 27c0e032e0STom Rini m = d.markers; 28c0e032e0STom Rini while (m) { 29c0e032e0STom Rini nm = m->next; 30c0e032e0STom Rini free(m->ref); 31c0e032e0STom Rini free(m); 32c0e032e0STom Rini m = nm; 33c0e032e0STom Rini } 34c0e032e0STom Rini 35c0e032e0STom Rini if (d.val) 36c0e032e0STom Rini free(d.val); 37c0e032e0STom Rini } 38c0e032e0STom Rini 39c0e032e0STom Rini struct data data_grow_for(struct data d, int xlen) 40c0e032e0STom Rini { 41c0e032e0STom Rini struct data nd; 42c0e032e0STom Rini int newsize; 43c0e032e0STom Rini 44c0e032e0STom Rini if (xlen == 0) 45c0e032e0STom Rini return d; 46c0e032e0STom Rini 47c0e032e0STom Rini nd = d; 48c0e032e0STom Rini 49c0e032e0STom Rini newsize = xlen; 50c0e032e0STom Rini 51c0e032e0STom Rini while ((d.len + xlen) > newsize) 52c0e032e0STom Rini newsize *= 2; 53c0e032e0STom Rini 54c0e032e0STom Rini nd.val = xrealloc(d.val, newsize); 55c0e032e0STom Rini 56c0e032e0STom Rini return nd; 57c0e032e0STom Rini } 58c0e032e0STom Rini 59c0e032e0STom Rini struct data data_copy_mem(const char *mem, int len) 60c0e032e0STom Rini { 61c0e032e0STom Rini struct data d; 62c0e032e0STom Rini 63c0e032e0STom Rini d = data_grow_for(empty_data, len); 64c0e032e0STom Rini 65c0e032e0STom Rini d.len = len; 66c0e032e0STom Rini memcpy(d.val, mem, len); 67c0e032e0STom Rini 68c0e032e0STom Rini return d; 69c0e032e0STom Rini } 70c0e032e0STom Rini 71c0e032e0STom Rini struct data data_copy_escape_string(const char *s, int len) 72c0e032e0STom Rini { 73c0e032e0STom Rini int i = 0; 74c0e032e0STom Rini struct data d; 75c0e032e0STom Rini char *q; 76c0e032e0STom Rini 77c0e032e0STom Rini d = data_grow_for(empty_data, len + 1); 78c0e032e0STom Rini 79c0e032e0STom Rini q = d.val; 80c0e032e0STom Rini while (i < len) { 81c0e032e0STom Rini char c = s[i++]; 82c0e032e0STom Rini 83c0e032e0STom Rini if (c == '\\') 84c0e032e0STom Rini c = get_escape_char(s, &i); 85c0e032e0STom Rini 86c0e032e0STom Rini q[d.len++] = c; 87c0e032e0STom Rini } 88c0e032e0STom Rini 89c0e032e0STom Rini q[d.len++] = '\0'; 90c0e032e0STom Rini return d; 91c0e032e0STom Rini } 92c0e032e0STom Rini 93c0e032e0STom Rini struct data data_copy_file(FILE *f, size_t maxlen) 94c0e032e0STom Rini { 95c0e032e0STom Rini struct data d = empty_data; 96c0e032e0STom Rini 97c0e032e0STom Rini while (!feof(f) && (d.len < maxlen)) { 98c0e032e0STom Rini size_t chunksize, ret; 99c0e032e0STom Rini 100c0e032e0STom Rini if (maxlen == -1) 101c0e032e0STom Rini chunksize = 4096; 102c0e032e0STom Rini else 103c0e032e0STom Rini chunksize = maxlen - d.len; 104c0e032e0STom Rini 105c0e032e0STom Rini d = data_grow_for(d, chunksize); 106c0e032e0STom Rini ret = fread(d.val + d.len, 1, chunksize, f); 107c0e032e0STom Rini 108c0e032e0STom Rini if (ferror(f)) 109c0e032e0STom Rini die("Error reading file into data: %s", strerror(errno)); 110c0e032e0STom Rini 111c0e032e0STom Rini if (d.len + ret < d.len) 112c0e032e0STom Rini die("Overflow reading file into data\n"); 113c0e032e0STom Rini 114c0e032e0STom Rini d.len += ret; 115c0e032e0STom Rini } 116c0e032e0STom Rini 117c0e032e0STom Rini return d; 118c0e032e0STom Rini } 119c0e032e0STom Rini 120c0e032e0STom Rini struct data data_append_data(struct data d, const void *p, int len) 121c0e032e0STom Rini { 122c0e032e0STom Rini d = data_grow_for(d, len); 123c0e032e0STom Rini memcpy(d.val + d.len, p, len); 124c0e032e0STom Rini d.len += len; 125c0e032e0STom Rini return d; 126c0e032e0STom Rini } 127c0e032e0STom Rini 128c0e032e0STom Rini struct data data_insert_at_marker(struct data d, struct marker *m, 129c0e032e0STom Rini const void *p, int len) 130c0e032e0STom Rini { 131c0e032e0STom Rini d = data_grow_for(d, len); 132c0e032e0STom Rini memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset); 133c0e032e0STom Rini memcpy(d.val + m->offset, p, len); 134c0e032e0STom Rini d.len += len; 135c0e032e0STom Rini 136c0e032e0STom Rini /* Adjust all markers after the one we're inserting at */ 137c0e032e0STom Rini m = m->next; 138c0e032e0STom Rini for_each_marker(m) 139c0e032e0STom Rini m->offset += len; 140c0e032e0STom Rini return d; 141c0e032e0STom Rini } 142c0e032e0STom Rini 143c0e032e0STom Rini static struct data data_append_markers(struct data d, struct marker *m) 144c0e032e0STom Rini { 145c0e032e0STom Rini struct marker **mp = &d.markers; 146c0e032e0STom Rini 147c0e032e0STom Rini /* Find the end of the markerlist */ 148c0e032e0STom Rini while (*mp) 149c0e032e0STom Rini mp = &((*mp)->next); 150c0e032e0STom Rini *mp = m; 151c0e032e0STom Rini return d; 152c0e032e0STom Rini } 153c0e032e0STom Rini 154c0e032e0STom Rini struct data data_merge(struct data d1, struct data d2) 155c0e032e0STom Rini { 156c0e032e0STom Rini struct data d; 157c0e032e0STom Rini struct marker *m2 = d2.markers; 158c0e032e0STom Rini 159c0e032e0STom Rini d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2); 160c0e032e0STom Rini 161c0e032e0STom Rini /* Adjust for the length of d1 */ 162c0e032e0STom Rini for_each_marker(m2) 163c0e032e0STom Rini m2->offset += d1.len; 164c0e032e0STom Rini 165c0e032e0STom Rini d2.markers = NULL; /* So data_free() doesn't clobber them */ 166c0e032e0STom Rini data_free(d2); 167c0e032e0STom Rini 168c0e032e0STom Rini return d; 169c0e032e0STom Rini } 170c0e032e0STom Rini 171c0e032e0STom Rini struct data data_append_integer(struct data d, uint64_t value, int bits) 172c0e032e0STom Rini { 173c0e032e0STom Rini uint8_t value_8; 174*d6fc90ceSTom Rini fdt16_t value_16; 175*d6fc90ceSTom Rini fdt32_t value_32; 176*d6fc90ceSTom Rini fdt64_t value_64; 177c0e032e0STom Rini 178c0e032e0STom Rini switch (bits) { 179c0e032e0STom Rini case 8: 180c0e032e0STom Rini value_8 = value; 181c0e032e0STom Rini return data_append_data(d, &value_8, 1); 182c0e032e0STom Rini 183c0e032e0STom Rini case 16: 184c0e032e0STom Rini value_16 = cpu_to_fdt16(value); 185c0e032e0STom Rini return data_append_data(d, &value_16, 2); 186c0e032e0STom Rini 187c0e032e0STom Rini case 32: 188c0e032e0STom Rini value_32 = cpu_to_fdt32(value); 189c0e032e0STom Rini return data_append_data(d, &value_32, 4); 190c0e032e0STom Rini 191c0e032e0STom Rini case 64: 192c0e032e0STom Rini value_64 = cpu_to_fdt64(value); 193c0e032e0STom Rini return data_append_data(d, &value_64, 8); 194c0e032e0STom Rini 195c0e032e0STom Rini default: 196c0e032e0STom Rini die("Invalid literal size (%d)\n", bits); 197c0e032e0STom Rini } 198c0e032e0STom Rini } 199c0e032e0STom Rini 200*d6fc90ceSTom Rini struct data data_append_re(struct data d, uint64_t address, uint64_t size) 201c0e032e0STom Rini { 202*d6fc90ceSTom Rini struct fdt_reserve_entry re; 203c0e032e0STom Rini 204*d6fc90ceSTom Rini re.address = cpu_to_fdt64(address); 205*d6fc90ceSTom Rini re.size = cpu_to_fdt64(size); 206c0e032e0STom Rini 207*d6fc90ceSTom Rini return data_append_data(d, &re, sizeof(re)); 208c0e032e0STom Rini } 209c0e032e0STom Rini 210c0e032e0STom Rini struct data data_append_cell(struct data d, cell_t word) 211c0e032e0STom Rini { 212c0e032e0STom Rini return data_append_integer(d, word, sizeof(word) * 8); 213c0e032e0STom Rini } 214c0e032e0STom Rini 215c0e032e0STom Rini struct data data_append_addr(struct data d, uint64_t addr) 216c0e032e0STom Rini { 217c0e032e0STom Rini return data_append_integer(d, addr, sizeof(addr) * 8); 218c0e032e0STom Rini } 219c0e032e0STom Rini 220c0e032e0STom Rini struct data data_append_byte(struct data d, uint8_t byte) 221c0e032e0STom Rini { 222c0e032e0STom Rini return data_append_data(d, &byte, 1); 223c0e032e0STom Rini } 224c0e032e0STom Rini 225c0e032e0STom Rini struct data data_append_zeroes(struct data d, int len) 226c0e032e0STom Rini { 227c0e032e0STom Rini d = data_grow_for(d, len); 228c0e032e0STom Rini 229c0e032e0STom Rini memset(d.val + d.len, 0, len); 230c0e032e0STom Rini d.len += len; 231c0e032e0STom Rini return d; 232c0e032e0STom Rini } 233c0e032e0STom Rini 234c0e032e0STom Rini struct data data_append_align(struct data d, int align) 235c0e032e0STom Rini { 236c0e032e0STom Rini int newlen = ALIGN(d.len, align); 237c0e032e0STom Rini return data_append_zeroes(d, newlen - d.len); 238c0e032e0STom Rini } 239c0e032e0STom Rini 240c0e032e0STom Rini struct data data_add_marker(struct data d, enum markertype type, char *ref) 241c0e032e0STom Rini { 242c0e032e0STom Rini struct marker *m; 243c0e032e0STom Rini 244c0e032e0STom Rini m = xmalloc(sizeof(*m)); 245c0e032e0STom Rini m->offset = d.len; 246c0e032e0STom Rini m->type = type; 247c0e032e0STom Rini m->ref = ref; 248c0e032e0STom Rini m->next = NULL; 249c0e032e0STom Rini 250c0e032e0STom Rini return data_append_markers(d, m); 251c0e032e0STom Rini } 252c0e032e0STom Rini 253c0e032e0STom Rini bool data_is_one_string(struct data d) 254c0e032e0STom Rini { 255c0e032e0STom Rini int i; 256c0e032e0STom Rini int len = d.len; 257c0e032e0STom Rini 258c0e032e0STom Rini if (len == 0) 259c0e032e0STom Rini return false; 260c0e032e0STom Rini 261c0e032e0STom Rini for (i = 0; i < len-1; i++) 262c0e032e0STom Rini if (d.val[i] == '\0') 263c0e032e0STom Rini return false; 264c0e032e0STom Rini 265c0e032e0STom Rini if (d.val[len-1] != '\0') 266c0e032e0STom Rini return false; 267c0e032e0STom Rini 268c0e032e0STom Rini return true; 269c0e032e0STom Rini } 270