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