blob: c689ea7ae13e66ccd4d7160ca4789f7bcb42b51e [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
Mike Frysingercc2c1782013-04-10 14:29:07 -0400200int utilfdt_read_err(const char *filename, char **buffp, off_t *len)
Simon Glass36204fd2011-09-22 10:11:02 -0700201{
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 */
Mike Frysingerf8cb5dd2013-04-10 14:29:06 -0400215 buf = xmalloc(bufsize);
Simon Glass36204fd2011-09-22 10:11:02 -0700216 do {
217 /* Expand the buffer to hold the next chunk */
218 if (offset == bufsize) {
219 bufsize *= 2;
Mike Frysingerf8cb5dd2013-04-10 14:29:06 -0400220 buf = xrealloc(buf, bufsize);
Simon Glass36204fd2011-09-22 10:11:02 -0700221 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;
Mike Frysingercc2c1782013-04-10 14:29:07 -0400241 if (len)
242 *len = bufsize;
Simon Glass36204fd2011-09-22 10:11:02 -0700243 return ret;
244}
245
Mike Frysingercc2c1782013-04-10 14:29:07 -0400246char *utilfdt_read(const char *filename, off_t *len)
Simon Glass36204fd2011-09-22 10:11:02 -0700247{
248 char *buff;
Mike Frysingercc2c1782013-04-10 14:29:07 -0400249 int ret = utilfdt_read_err(filename, &buff, len);
Simon Glass36204fd2011-09-22 10:11:02 -0700250
251 if (ret) {
252 fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
253 strerror(ret));
254 return NULL;
255 }
256 /* Successful read */
257 return buff;
258}
259
260int utilfdt_write_err(const char *filename, const void *blob)
261{
262 int fd = 1; /* assume stdout */
263 int totalsize;
264 int offset;
265 int ret = 0;
266 const char *ptr = blob;
267
268 if (strcmp(filename, "-") != 0) {
269 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
270 if (fd < 0)
271 return errno;
272 }
273
274 totalsize = fdt_totalsize(blob);
275 offset = 0;
276
277 while (offset < totalsize) {
278 ret = write(fd, ptr + offset, totalsize - offset);
279 if (ret < 0) {
280 ret = -errno;
281 break;
282 }
283 offset += ret;
284 }
285 /* Close the file/stdin; return errno on error */
286 if (fd != 1)
287 close(fd);
288 return ret < 0 ? -ret : 0;
289}
290
291
292int utilfdt_write(const char *filename, const void *blob)
293{
294 int ret = utilfdt_write_err(filename, blob);
295
296 if (ret) {
297 fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename,
298 strerror(ret));
299 }
300 return ret ? -1 : 0;
301}
302
303int utilfdt_decode_type(const char *fmt, int *type, int *size)
304{
305 int qualifier = 0;
306
David Gibsone2804422012-02-03 17:06:12 +1100307 if (!*fmt)
308 return -1;
309
Simon Glass36204fd2011-09-22 10:11:02 -0700310 /* get the conversion qualifier */
311 *size = -1;
312 if (strchr("hlLb", *fmt)) {
313 qualifier = *fmt++;
314 if (qualifier == *fmt) {
315 switch (*fmt++) {
316/* TODO: case 'l': qualifier = 'L'; break;*/
317 case 'h':
318 qualifier = 'b';
319 break;
320 }
321 }
322 }
323
324 /* we should now have a type */
David Gibsone2804422012-02-03 17:06:12 +1100325 if ((*fmt == '\0') || !strchr("iuxs", *fmt))
Simon Glass36204fd2011-09-22 10:11:02 -0700326 return -1;
327
328 /* convert qualifier (bhL) to byte size */
329 if (*fmt != 's')
330 *size = qualifier == 'b' ? 1 :
331 qualifier == 'h' ? 2 :
332 qualifier == 'l' ? 4 : -1;
333 *type = *fmt++;
334
335 /* that should be it! */
336 if (*fmt)
337 return -1;
338 return 0;
339}
Simon Glassd20391d2013-01-21 12:59:16 -0800340
341void utilfdt_print_data(const char *data, int len)
342{
343 int i;
344 const char *p = data;
345 const char *s;
346
347 /* no data, don't print */
348 if (len == 0)
349 return;
350
351 if (util_is_printable_string(data, len)) {
352 printf(" = ");
353
354 s = data;
355 do {
356 printf("\"%s\"", s);
357 s += strlen(s) + 1;
358 if (s < data + len)
359 printf(", ");
360 } while (s < data + len);
361
362 } else if ((len % 4) == 0) {
363 const uint32_t *cell = (const uint32_t *)data;
364
365 printf(" = <");
366 for (i = 0; i < len; i += 4)
367 printf("0x%08x%s", fdt32_to_cpu(cell[i]),
368 i < (len - 4) ? " " : "");
369 printf(">");
370 } else {
371 printf(" = [");
372 for (i = 0; i < len; i++)
373 printf("%02x%s", *p++, i < len - 1 ? " " : "");
374 printf("]");
375 }
376}