data.c revision 261215
175295Sdes/*
275295Sdes * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
375295Sdes *
475295Sdes *
575295Sdes * This program is free software; you can redistribute it and/or
675295Sdes * modify it under the terms of the GNU General Public License as
775295Sdes * published by the Free Software Foundation; either version 2 of the
875295Sdes * License, or (at your option) any later version.
975295Sdes *
1075295Sdes *  This program is distributed in the hope that it will be useful,
1175295Sdes *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1275295Sdes *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1375295Sdes *  General Public License for more details.
1475295Sdes *
1575295Sdes *  You should have received a copy of the GNU General Public License
1675295Sdes *  along with this program; if not, write to the Free Software
1775295Sdes *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
1875295Sdes *                                                                   USA
1975295Sdes */
2075295Sdes
2175295Sdes#include "dtc.h"
2275295Sdes
2375295Sdesvoid data_free(struct data d)
2475295Sdes{
2575295Sdes	struct marker *m, *nm;
2675295Sdes
2775295Sdes	m = d.markers;
2875295Sdes	while (m) {
29143592Sdes		nm = m->next;
30143592Sdes		free(m->ref);
31143592Sdes		free(m);
32143592Sdes		m = nm;
33143592Sdes	}
3475295Sdes
3575295Sdes	if (d.val)
3675295Sdes		free(d.val);
37112564Sjhb}
3878073Sdes
3975295Sdesstruct data data_grow_for(struct data d, int xlen)
4077965Sdes{
4184246Sdes	struct data nd;
4275295Sdes	int newsize;
4375295Sdes
4475295Sdes	if (xlen == 0)
4575295Sdes		return d;
4675295Sdes
4775295Sdes	nd = d;
4877998Sdes
4975295Sdes	newsize = xlen;
5075295Sdes
5189071Smsmith	while ((d.len + xlen) > newsize)
52112564Sjhb		newsize *= 2;
53112564Sjhb
5475295Sdes	nd.val = xrealloc(d.val, newsize);
5575295Sdes
5675295Sdes	return nd;
5775295Sdes}
5884246Sdes
5984246Sdesstruct data data_copy_mem(const char *mem, int len)
6084246Sdes{
6184246Sdes	struct data d;
6284246Sdes
6384246Sdes	d = data_grow_for(empty_data, len);
6484246Sdes
6584246Sdes	d.len = len;
6684246Sdes	memcpy(d.val, mem, len);
6784246Sdes
6875295Sdes	return d;
6984246Sdes}
7084246Sdes
7175295Sdesstruct data data_copy_escape_string(const char *s, int len)
7275295Sdes{
7375295Sdes	int i = 0;
7484246Sdes	struct data d;
7584246Sdes	char *q;
7675295Sdes
7775295Sdes	d = data_grow_for(empty_data, strlen(s)+1);
78138290Sphk
7975295Sdes	q = d.val;
8075295Sdes	while (i < len) {
8175295Sdes		char c = s[i++];
8275295Sdes
8375295Sdes		if (c == '\\')
8475295Sdes			c = get_escape_char(s, &i);
8575295Sdes
86133776Sdes		q[d.len++] = c;
87112564Sjhb	}
88112564Sjhb
8975295Sdes	q[d.len++] = '\0';
9075295Sdes	return d;
9175295Sdes}
9275295Sdes
9375295Sdesstruct data data_copy_file(FILE *f, size_t maxlen)
9475295Sdes{
9575295Sdes	struct data d = empty_data;
9675295Sdes
97112564Sjhb	while (!feof(f) && (d.len < maxlen)) {
9884386Sdes		size_t chunksize, ret;
9984386Sdes
10084386Sdes		if (maxlen == -1)
10175295Sdes			chunksize = 4096;
10275295Sdes		else
10375295Sdes			chunksize = maxlen - d.len;
10475295Sdes
10575295Sdes		d = data_grow_for(d, chunksize);
10675295Sdes		ret = fread(d.val + d.len, 1, chunksize, f);
10775295Sdes
10877998Sdes		if (ferror(f))
10977998Sdes			die("Error reading file into data: %s", strerror(errno));
11075295Sdes
11177998Sdes		if (d.len + ret < d.len)
11275295Sdes			die("Overflow reading file into data\n");
11388234Sdillon
11488234Sdillon		d.len += ret;
11597940Sdes	}
11688234Sdillon
11788234Sdillon	return d;
11875295Sdes}
11984246Sdes
120109969Stjrstruct data data_append_data(struct data d, const void *p, int len)
121109969Stjr{
12284246Sdes	d = data_grow_for(d, len);
12375295Sdes	memcpy(d.val + d.len, p, len);
12484246Sdes	d.len += len;
12575295Sdes	return d;
12688234Sdillon}
12788234Sdillon
12899566Sjeffstruct data data_insert_at_marker(struct data d, struct marker *m,
12999566Sjeff				  const void *p, int len)
13075295Sdes{
13175295Sdes	d = data_grow_for(d, len);
13277998Sdes	memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset);
13377998Sdes	memcpy(d.val + m->offset, p, len);
13477998Sdes	d.len += len;
13577998Sdes
13677998Sdes	/* Adjust all markers after the one we're inserting at */
13775295Sdes	m = m->next;
13875295Sdes	for_each_marker(m)
13975295Sdes		m->offset += len;
140111119Simp	return d;
14184246Sdes}
14284246Sdes
143138290Sphkstatic struct data data_append_markers(struct data d, struct marker *m)
144105165Sphk{
145105165Sphk	struct marker **mp = &d.markers;
14675295Sdes
147105165Sphk	/* Find the end of the markerlist */
14877998Sdes	while (*mp)
14977998Sdes		mp = &((*mp)->next);
15077998Sdes	*mp = m;
15175295Sdes	return d;
15275295Sdes}
153101308Sjeff
15475295Sdesstruct data data_merge(struct data d1, struct data d2)
15575295Sdes{
15675295Sdes	struct data d;
15784246Sdes	struct marker *m2 = d2.markers;
15875295Sdes
15975295Sdes	d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2);
16075295Sdes
16177998Sdes	/* Adjust for the length of d1 */
16275295Sdes	for_each_marker(m2)
16375295Sdes		m2->offset += d1.len;
16475295Sdes
16575295Sdes	d2.markers = NULL; /* So data_free() doesn't clobber them */
16675295Sdes	data_free(d2);
16775295Sdes
16875295Sdes	return d;
16975295Sdes}
17077998Sdes
17177998Sdesstruct data data_append_integer(struct data d, uint64_t value, int bits)
17275295Sdes{
17375295Sdes	uint8_t value_8;
17475295Sdes	uint16_t value_16;
175103314Snjl	uint32_t value_32;
176103314Snjl	uint64_t value_64;
177103314Snjl
178103314Snjl	switch (bits) {
179103314Snjl	case 8:
180103314Snjl		value_8 = value;
18184246Sdes		return data_append_data(d, &value_8, 1);
18277998Sdes
18384246Sdes	case 16:
18484246Sdes		value_16 = cpu_to_fdt16(value);
18584246Sdes		return data_append_data(d, &value_16, 2);
18684246Sdes
18784246Sdes	case 32:
18875295Sdes		value_32 = cpu_to_fdt32(value);
189105077Smckusick		return data_append_data(d, &value_32, 4);
19099566Sjeff
19175295Sdes	case 64:
19275295Sdes		value_64 = cpu_to_fdt64(value);
19375295Sdes		return data_append_data(d, &value_64, 8);
19475295Sdes
19575295Sdes	default:
19675295Sdes		die("Invalid literal size (%d)\n", bits);
19775295Sdes	}
19875295Sdes}
19975295Sdes
20077998Sdesstruct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
20188234Sdillon{
20275295Sdes	struct fdt_reserve_entry bere;
20384246Sdes
20484246Sdes	bere.address = cpu_to_fdt64(re->address);
20584246Sdes	bere.size = cpu_to_fdt64(re->size);
20684246Sdes
20784246Sdes	return data_append_data(d, &bere, sizeof(bere));
20884246Sdes}
20977998Sdes
21084246Sdesstruct data data_append_cell(struct data d, cell_t word)
21177998Sdes{
21284246Sdes	return data_append_integer(d, word, sizeof(word) * 8);
21384246Sdes}
21477998Sdes
21575295Sdesstruct data data_append_addr(struct data d, uint64_t addr)
21675295Sdes{
21775295Sdes	return data_append_integer(d, addr, sizeof(addr) * 8);
21884246Sdes}
21984246Sdes
22084246Sdesstruct data data_append_byte(struct data d, uint8_t byte)
221139896Srwatson{
222139896Srwatson	return data_append_data(d, &byte, 1);
223139896Srwatson}
224139896Srwatson
22584246Sdesstruct data data_append_zeroes(struct data d, int len)
22684246Sdes{
227112564Sjhb	d = data_grow_for(d, len);
22884246Sdes
229133776Sdes	memset(d.val + d.len, 0, len);
230133776Sdes	d.len += len;
23184246Sdes	return d;
232142907Sphk}
233142907Sphk
234126975Sgreenstruct data data_append_align(struct data d, int align)
23584246Sdes{
236133776Sdes	int newlen = ALIGN(d.len, align);
237133776Sdes	return data_append_zeroes(d, newlen - d.len);
238133776Sdes}
239133776Sdes
240133776Sdesstruct data data_add_marker(struct data d, enum markertype type, char *ref)
241133776Sdes{
242133776Sdes	struct marker *m;
243133776Sdes
244133776Sdes	m = xmalloc(sizeof(*m));
245133776Sdes	m->offset = d.len;
246133776Sdes	m->type = type;
24784246Sdes	m->ref = ref;
248133776Sdes	m->next = NULL;
249133776Sdes
250133776Sdes	return data_append_markers(d, m);
251133776Sdes}
252133776Sdes
253147809Sjeffbool data_is_one_string(struct data d)
254133776Sdes{
255143513Sjeff	int i;
256133776Sdes	int len = d.len;
257143513Sjeff
258147809Sjeff	if (len == 0)
259133776Sdes		return false;
260133776Sdes
261133776Sdes	for (i = 0; i < len-1; i++)
262133776Sdes		if (d.val[i] == '\0')
26384246Sdes			return false;
26484246Sdes
26584246Sdes	if (d.val[len-1] != '\0')
266126975Sgreen		return false;
26784246Sdes
26884386Sdes	return true;
26984386Sdes}
27084386Sdes