blob: b081fa83854f6aa12992e40cf9f7273eb7a5429f [file] [log] [blame]
Jon Loeliger879e4d22008-10-03 11:12:33 -05001/*
Simon Glass36204fd2011-09-22 10:11:02 -07002 * Copyright 2011 The Chromium Authors, All Rights Reserved.
Jon Loeliger879e4d22008-10-03 11:12:33 -05003 * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
4 *
Simon Glass492f9d52011-07-05 12:02:49 -07005 * util_is_printable_string contributed by
6 * Pantelis Antoniou <pantelis.antoniou AT gmail.com>
7 *
Jon Loeliger879e4d22008-10-03 11:12:33 -05008 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 */
23
Simon Glass492f9d52011-07-05 12:02:49 -070024#include <ctype.h>
David Gibson87658742010-03-03 16:38:01 +110025#include <stdio.h>
26#include <stdlib.h>
27#include <stdarg.h>
28#include <string.h>
Anton Staafb43335a2011-09-09 12:16:29 -070029#include <assert.h>
David Gibson87658742010-03-03 16:38:01 +110030
Simon Glass36204fd2011-09-22 10:11:02 -070031#include <errno.h>
32#include <fcntl.h>
33#include <unistd.h>
34
35#include "libfdt.h"
David Gibson87658742010-03-03 16:38:01 +110036#include "util.h"
Jon Loeliger879e4d22008-10-03 11:12:33 -050037
38char *xstrdup(const char *s)
39{
40 int len = strlen(s) + 1;
41 char *dup = xmalloc(len);
42
43 memcpy(dup, s, len);
44
45 return dup;
46}
David Gibsond68cb362009-12-08 14:24:42 +110047
48char *join_path(const char *path, const char *name)
49{
50 int lenp = strlen(path);
51 int lenn = strlen(name);
52 int len;
53 int needslash = 1;
54 char *str;
55
56 len = lenp + lenn + 2;
57 if ((lenp > 0) && (path[lenp-1] == '/')) {
58 needslash = 0;
59 len--;
60 }
61
62 str = xmalloc(len);
63 memcpy(str, path, lenp);
64 if (needslash) {
65 str[lenp] = '/';
66 lenp++;
67 }
68 memcpy(str+lenp, name, lenn+1);
69 return str;
70}
Simon Glass492f9d52011-07-05 12:02:49 -070071
72int util_is_printable_string(const void *data, int len)
73{
74 const char *s = data;
Pantelis Antoniou1c1efd62013-01-04 21:12:58 +020075 const char *ss, *se;
Simon Glass492f9d52011-07-05 12:02:49 -070076
77 /* zero length is not */
78 if (len == 0)
79 return 0;
80
81 /* must terminate with zero */
82 if (s[len - 1] != '\0')
83 return 0;
84
Pantelis Antoniou1c1efd62013-01-04 21:12:58 +020085 se = s + len;
Simon Glass492f9d52011-07-05 12:02:49 -070086
Pantelis Antoniou1c1efd62013-01-04 21:12:58 +020087 while (s < se) {
88 ss = s;
89 while (s < se && *s && isprint(*s))
90 s++;
91
92 /* not zero, or not done yet */
93 if (*s != '\0' || s == ss)
94 return 0;
95
96 s++;
97 }
Simon Glass492f9d52011-07-05 12:02:49 -070098
99 return 1;
100}
Anton Staafb43335a2011-09-09 12:16:29 -0700101
102/*
103 * Parse a octal encoded character starting at index i in string s. The
104 * resulting character will be returned and the index i will be updated to
105 * point at the character directly after the end of the encoding, this may be
106 * the '\0' terminator of the string.
107 */
108static char get_oct_char(const char *s, int *i)
109{
110 char x[4];
111 char *endx;
112 long val;
113
114 x[3] = '\0';
115 strncpy(x, s + *i, 3);
116
117 val = strtol(x, &endx, 8);
118
119 assert(endx > x);
120
121 (*i) += endx - x;
122 return val;
123}
124
125/*
126 * Parse a hexadecimal encoded character starting at index i in string s. The
127 * resulting character will be returned and the index i will be updated to
128 * point at the character directly after the end of the encoding, this may be
129 * the '\0' terminator of the string.
130 */
131static char get_hex_char(const char *s, int *i)
132{
133 char x[3];
134 char *endx;
135 long val;
136
137 x[2] = '\0';
138 strncpy(x, s + *i, 2);
139
140 val = strtol(x, &endx, 16);
141 if (!(endx > x))
142 die("\\x used with no following hex digits\n");
143
144 (*i) += endx - x;
145 return val;
146}
147
148char get_escape_char(const char *s, int *i)
149{
150 char c = s[*i];
151 int j = *i + 1;
152 char val;
153
154 assert(c);
155 switch (c) {
156 case 'a':
157 val = '\a';
158 break;
159 case 'b':
160 val = '\b';
161 break;
162 case 't':
163 val = '\t';
164 break;
165 case 'n':
166 val = '\n';
167 break;
168 case 'v':
169 val = '\v';
170 break;
171 case 'f':
172 val = '\f';
173 break;
174 case 'r':
175 val = '\r';
176 break;
177 case '0':
178 case '1':
179 case '2':
180 case '3':
181 case '4':
182 case '5':
183 case '6':
184 case '7':
185 j--; /* need to re-read the first digit as
186 * part of the octal value */
187 val = get_oct_char(s, &j);
188 break;
189 case 'x':
190 val = get_hex_char(s, &j);
191 break;
192 default:
193 val = c;
194 }
195
196 (*i) = j;
197 return val;
198}
Simon Glass36204fd2011-09-22 10:11:02 -0700199
200int utilfdt_read_err(const char *filename, char **buffp)
201{
202 int fd = 0; /* assume stdin */
203 char *buf = NULL;
204 off_t bufsize = 1024, offset = 0;
205 int ret = 0;
206
207 *buffp = NULL;
208 if (strcmp(filename, "-") != 0) {
209 fd = open(filename, O_RDONLY);
210 if (fd < 0)
211 return errno;
212 }
213
214 /* Loop until we have read everything */
215 buf = malloc(bufsize);
216 do {
217 /* Expand the buffer to hold the next chunk */
218 if (offset == bufsize) {
219 bufsize *= 2;
220 buf = realloc(buf, bufsize);
221 if (!buf) {
222 ret = ENOMEM;
223 break;
224 }
225 }
226
227 ret = read(fd, &buf[offset], bufsize - offset);
228 if (ret < 0) {
229 ret = errno;
230 break;
231 }
232 offset += ret;
233 } while (ret != 0);
234
235 /* Clean up, including closing stdin; return errno on error */
236 close(fd);
237 if (ret)
238 free(buf);
239 else
240 *buffp = buf;
241 return ret;
242}
243
244char *utilfdt_read(const char *filename)
245{
246 char *buff;
247 int ret = utilfdt_read_err(filename, &buff);
248
249 if (ret) {
250 fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
251 strerror(ret));
252 return NULL;
253 }
254 /* Successful read */
255 return buff;
256}
257
258int utilfdt_write_err(const char *filename, const void *blob)
259{
260 int fd = 1; /* assume stdout */
261 int totalsize;
262 int offset;
263 int ret = 0;
264 const char *ptr = blob;
265
266 if (strcmp(filename, "-") != 0) {
267 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
268 if (fd < 0)
269 return errno;
270 }
271
272 totalsize = fdt_totalsize(blob);
273 offset = 0;
274
275 while (offset < totalsize) {
276 ret = write(fd, ptr + offset, totalsize - offset);
277 if (ret < 0) {
278 ret = -errno;
279 break;
280 }
281 offset += ret;
282 }
283 /* Close the file/stdin; return errno on error */
284 if (fd != 1)
285 close(fd);
286 return ret < 0 ? -ret : 0;
287}
288
289
290int utilfdt_write(const char *filename, const void *blob)
291{
292 int ret = utilfdt_write_err(filename, blob);
293
294 if (ret) {
295 fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename,
296 strerror(ret));
297 }
298 return ret ? -1 : 0;
299}
300
301int utilfdt_decode_type(const char *fmt, int *type, int *size)
302{
303 int qualifier = 0;
304
David Gibsone2804422012-02-03 17:06:12 +1100305 if (!*fmt)
306 return -1;
307
Simon Glass36204fd2011-09-22 10:11:02 -0700308 /* get the conversion qualifier */
309 *size = -1;
310 if (strchr("hlLb", *fmt)) {
311 qualifier = *fmt++;
312 if (qualifier == *fmt) {
313 switch (*fmt++) {
314/* TODO: case 'l': qualifier = 'L'; break;*/
315 case 'h':
316 qualifier = 'b';
317 break;
318 }
319 }
320 }
321
322 /* we should now have a type */
David Gibsone2804422012-02-03 17:06:12 +1100323 if ((*fmt == '\0') || !strchr("iuxs", *fmt))
Simon Glass36204fd2011-09-22 10:11:02 -0700324 return -1;
325
326 /* convert qualifier (bhL) to byte size */
327 if (*fmt != 's')
328 *size = qualifier == 'b' ? 1 :
329 qualifier == 'h' ? 2 :
330 qualifier == 'l' ? 4 : -1;
331 *type = *fmt++;
332
333 /* that should be it! */
334 if (*fmt)
335 return -1;
336 return 0;
337}
Simon Glassd20391d2013-01-21 12:59:16 -0800338
339void utilfdt_print_data(const char *data, int len)
340{
341 int i;
342 const char *p = data;
343 const char *s;
344
345 /* no data, don't print */
346 if (len == 0)
347 return;
348
349 if (util_is_printable_string(data, len)) {
350 printf(" = ");
351
352 s = data;
353 do {
354 printf("\"%s\"", s);
355 s += strlen(s) + 1;
356 if (s < data + len)
357 printf(", ");
358 } while (s < data + len);
359
360 } else if ((len % 4) == 0) {
361 const uint32_t *cell = (const uint32_t *)data;
362
363 printf(" = <");
364 for (i = 0; i < len; i += 4)
365 printf("0x%08x%s", fdt32_to_cpu(cell[i]),
366 i < (len - 4) ? " " : "");
367 printf(">");
368 } else {
369 printf(" = [");
370 for (i = 0; i < len; i++)
371 printf("%02x%s", *p++, i < len - 1 ? " " : "");
372 printf("]");
373 }
374}