1204431Sraj/* 2204431Sraj * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 3204431Sraj * 4204431Sraj * 5204431Sraj * This program is free software; you can redistribute it and/or 6204431Sraj * modify it under the terms of the GNU General Public License as 7204431Sraj * published by the Free Software Foundation; either version 2 of the 8204431Sraj * License, or (at your option) any later version. 9204431Sraj * 10204431Sraj * This program is distributed in the hope that it will be useful, 11204431Sraj * but WITHOUT ANY WARRANTY; without even the implied warranty of 12204431Sraj * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13204431Sraj * General Public License for more details. 14204431Sraj * 15204431Sraj * You should have received a copy of the GNU General Public License 16204431Sraj * along with this program; if not, write to the Free Software 17204431Sraj * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 18204431Sraj * USA 19204431Sraj */ 20204431Sraj 21204431Sraj#include "dtc.h" 22204431Sraj 23204431Srajvoid data_free(struct data d) 24204431Sraj{ 25204431Sraj struct marker *m, *nm; 26204431Sraj 27204431Sraj m = d.markers; 28204431Sraj while (m) { 29204431Sraj nm = m->next; 30204431Sraj free(m->ref); 31204431Sraj free(m); 32204431Sraj m = nm; 33204431Sraj } 34204431Sraj 35204431Sraj if (d.val) 36204431Sraj free(d.val); 37204431Sraj} 38204431Sraj 39204431Srajstruct data data_grow_for(struct data d, int xlen) 40204431Sraj{ 41204431Sraj struct data nd; 42204431Sraj int newsize; 43204431Sraj 44204431Sraj if (xlen == 0) 45204431Sraj return d; 46204431Sraj 47204431Sraj nd = d; 48204431Sraj 49204431Sraj newsize = xlen; 50204431Sraj 51204431Sraj while ((d.len + xlen) > newsize) 52204431Sraj newsize *= 2; 53204431Sraj 54204431Sraj nd.val = xrealloc(d.val, newsize); 55204431Sraj 56204431Sraj return nd; 57204431Sraj} 58204431Sraj 59204431Srajstruct data data_copy_mem(const char *mem, int len) 60204431Sraj{ 61204431Sraj struct data d; 62204431Sraj 63204431Sraj d = data_grow_for(empty_data, len); 64204431Sraj 65204431Sraj d.len = len; 66204431Sraj memcpy(d.val, mem, len); 67204431Sraj 68204431Sraj return d; 69204431Sraj} 70204431Sraj 71204431Srajstruct data data_copy_escape_string(const char *s, int len) 72204431Sraj{ 73204431Sraj int i = 0; 74204431Sraj struct data d; 75204431Sraj char *q; 76204431Sraj 77318102Sgonzo d = data_grow_for(empty_data, len + 1); 78204431Sraj 79204431Sraj q = d.val; 80204431Sraj while (i < len) { 81204431Sraj char c = s[i++]; 82204431Sraj 83238742Simp if (c == '\\') 84238742Simp c = get_escape_char(s, &i); 85204431Sraj 86238742Simp q[d.len++] = c; 87204431Sraj } 88204431Sraj 89204431Sraj q[d.len++] = '\0'; 90204431Sraj return d; 91204431Sraj} 92204431Sraj 93204431Srajstruct data data_copy_file(FILE *f, size_t maxlen) 94204431Sraj{ 95204431Sraj struct data d = empty_data; 96204431Sraj 97204431Sraj while (!feof(f) && (d.len < maxlen)) { 98204431Sraj size_t chunksize, ret; 99204431Sraj 100204431Sraj if (maxlen == -1) 101204431Sraj chunksize = 4096; 102204431Sraj else 103204431Sraj chunksize = maxlen - d.len; 104204431Sraj 105204431Sraj d = data_grow_for(d, chunksize); 106204431Sraj ret = fread(d.val + d.len, 1, chunksize, f); 107204431Sraj 108204431Sraj if (ferror(f)) 109204431Sraj die("Error reading file into data: %s", strerror(errno)); 110204431Sraj 111204431Sraj if (d.len + ret < d.len) 112204431Sraj die("Overflow reading file into data\n"); 113204431Sraj 114204431Sraj d.len += ret; 115204431Sraj } 116204431Sraj 117204431Sraj return d; 118204431Sraj} 119204431Sraj 120204431Srajstruct data data_append_data(struct data d, const void *p, int len) 121204431Sraj{ 122204431Sraj d = data_grow_for(d, len); 123204431Sraj memcpy(d.val + d.len, p, len); 124204431Sraj d.len += len; 125204431Sraj return d; 126204431Sraj} 127204431Sraj 128204431Srajstruct data data_insert_at_marker(struct data d, struct marker *m, 129204431Sraj const void *p, int len) 130204431Sraj{ 131204431Sraj d = data_grow_for(d, len); 132204431Sraj memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset); 133204431Sraj memcpy(d.val + m->offset, p, len); 134204431Sraj d.len += len; 135204431Sraj 136204431Sraj /* Adjust all markers after the one we're inserting at */ 137204431Sraj m = m->next; 138204431Sraj for_each_marker(m) 139204431Sraj m->offset += len; 140204431Sraj return d; 141204431Sraj} 142204431Sraj 143204433Srajstatic struct data data_append_markers(struct data d, struct marker *m) 144204431Sraj{ 145204431Sraj struct marker **mp = &d.markers; 146204431Sraj 147204431Sraj /* Find the end of the markerlist */ 148204431Sraj while (*mp) 149204431Sraj mp = &((*mp)->next); 150204431Sraj *mp = m; 151204431Sraj return d; 152204431Sraj} 153204431Sraj 154204431Srajstruct data data_merge(struct data d1, struct data d2) 155204431Sraj{ 156204431Sraj struct data d; 157204431Sraj struct marker *m2 = d2.markers; 158204431Sraj 159204431Sraj d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2); 160204431Sraj 161204431Sraj /* Adjust for the length of d1 */ 162204431Sraj for_each_marker(m2) 163204431Sraj m2->offset += d1.len; 164204431Sraj 165204431Sraj d2.markers = NULL; /* So data_free() doesn't clobber them */ 166204431Sraj data_free(d2); 167204431Sraj 168204431Sraj return d; 169204431Sraj} 170204431Sraj 171238742Simpstruct data data_append_integer(struct data d, uint64_t value, int bits) 172204431Sraj{ 173238742Simp uint8_t value_8; 174238742Simp uint16_t value_16; 175238742Simp uint32_t value_32; 176238742Simp uint64_t value_64; 177204431Sraj 178238742Simp switch (bits) { 179238742Simp case 8: 180238742Simp value_8 = value; 181238742Simp return data_append_data(d, &value_8, 1); 182238742Simp 183238742Simp case 16: 184238742Simp value_16 = cpu_to_fdt16(value); 185238742Simp return data_append_data(d, &value_16, 2); 186238742Simp 187238742Simp case 32: 188238742Simp value_32 = cpu_to_fdt32(value); 189238742Simp return data_append_data(d, &value_32, 4); 190238742Simp 191238742Simp case 64: 192238742Simp value_64 = cpu_to_fdt64(value); 193238742Simp return data_append_data(d, &value_64, 8); 194238742Simp 195238742Simp default: 196238742Simp die("Invalid literal size (%d)\n", bits); 197238742Simp } 198204431Sraj} 199204431Sraj 200204431Srajstruct data data_append_re(struct data d, const struct fdt_reserve_entry *re) 201204431Sraj{ 202204431Sraj struct fdt_reserve_entry bere; 203204431Sraj 204204431Sraj bere.address = cpu_to_fdt64(re->address); 205204431Sraj bere.size = cpu_to_fdt64(re->size); 206204431Sraj 207204431Sraj return data_append_data(d, &bere, sizeof(bere)); 208204431Sraj} 209204431Sraj 210238742Simpstruct data data_append_cell(struct data d, cell_t word) 211238742Simp{ 212238742Simp return data_append_integer(d, word, sizeof(word) * 8); 213238742Simp} 214238742Simp 215204431Srajstruct data data_append_addr(struct data d, uint64_t addr) 216204431Sraj{ 217238742Simp return data_append_integer(d, addr, sizeof(addr) * 8); 218204431Sraj} 219204431Sraj 220204431Srajstruct data data_append_byte(struct data d, uint8_t byte) 221204431Sraj{ 222204431Sraj return data_append_data(d, &byte, 1); 223204431Sraj} 224204431Sraj 225204431Srajstruct data data_append_zeroes(struct data d, int len) 226204431Sraj{ 227204431Sraj d = data_grow_for(d, len); 228204431Sraj 229204431Sraj memset(d.val + d.len, 0, len); 230204431Sraj d.len += len; 231204431Sraj return d; 232204431Sraj} 233204431Sraj 234204431Srajstruct data data_append_align(struct data d, int align) 235204431Sraj{ 236204431Sraj int newlen = ALIGN(d.len, align); 237204431Sraj return data_append_zeroes(d, newlen - d.len); 238204431Sraj} 239204431Sraj 240204431Srajstruct data data_add_marker(struct data d, enum markertype type, char *ref) 241204431Sraj{ 242204431Sraj struct marker *m; 243204431Sraj 244204431Sraj m = xmalloc(sizeof(*m)); 245204431Sraj m->offset = d.len; 246204431Sraj m->type = type; 247204431Sraj m->ref = ref; 248204431Sraj m->next = NULL; 249204431Sraj 250204431Sraj return data_append_markers(d, m); 251204431Sraj} 252204431Sraj 253261215Simpbool data_is_one_string(struct data d) 254204431Sraj{ 255204431Sraj int i; 256204431Sraj int len = d.len; 257204431Sraj 258204431Sraj if (len == 0) 259261215Simp return false; 260204431Sraj 261204431Sraj for (i = 0; i < len-1; i++) 262204431Sraj if (d.val[i] == '\0') 263261215Simp return false; 264204431Sraj 265204431Sraj if (d.val[len-1] != '\0') 266261215Simp return false; 267204431Sraj 268261215Simp return true; 269204431Sraj} 270