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