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