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