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