1*cd60bc56SAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*cd60bc56SAndroid Build Coastguard Worker /*
3*cd60bc56SAndroid Build Coastguard Worker * Copyright 2011 The Chromium Authors, All Rights Reserved.
4*cd60bc56SAndroid Build Coastguard Worker * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
5*cd60bc56SAndroid Build Coastguard Worker *
6*cd60bc56SAndroid Build Coastguard Worker * util_is_printable_string contributed by
7*cd60bc56SAndroid Build Coastguard Worker * Pantelis Antoniou <pantelis.antoniou AT gmail.com>
8*cd60bc56SAndroid Build Coastguard Worker */
9*cd60bc56SAndroid Build Coastguard Worker
10*cd60bc56SAndroid Build Coastguard Worker #include <ctype.h>
11*cd60bc56SAndroid Build Coastguard Worker #include <stdio.h>
12*cd60bc56SAndroid Build Coastguard Worker #include <stdlib.h>
13*cd60bc56SAndroid Build Coastguard Worker #include <stdarg.h>
14*cd60bc56SAndroid Build Coastguard Worker #include <string.h>
15*cd60bc56SAndroid Build Coastguard Worker #include <assert.h>
16*cd60bc56SAndroid Build Coastguard Worker #include <inttypes.h>
17*cd60bc56SAndroid Build Coastguard Worker
18*cd60bc56SAndroid Build Coastguard Worker #include <errno.h>
19*cd60bc56SAndroid Build Coastguard Worker #include <fcntl.h>
20*cd60bc56SAndroid Build Coastguard Worker #include <unistd.h>
21*cd60bc56SAndroid Build Coastguard Worker
22*cd60bc56SAndroid Build Coastguard Worker #include "libfdt.h"
23*cd60bc56SAndroid Build Coastguard Worker #include "util.h"
24*cd60bc56SAndroid Build Coastguard Worker #include "version_gen.h"
25*cd60bc56SAndroid Build Coastguard Worker
xstrdup(const char * s)26*cd60bc56SAndroid Build Coastguard Worker char *xstrdup(const char *s)
27*cd60bc56SAndroid Build Coastguard Worker {
28*cd60bc56SAndroid Build Coastguard Worker int len = strlen(s) + 1;
29*cd60bc56SAndroid Build Coastguard Worker char *d = xmalloc(len);
30*cd60bc56SAndroid Build Coastguard Worker
31*cd60bc56SAndroid Build Coastguard Worker memcpy(d, s, len);
32*cd60bc56SAndroid Build Coastguard Worker
33*cd60bc56SAndroid Build Coastguard Worker return d;
34*cd60bc56SAndroid Build Coastguard Worker }
35*cd60bc56SAndroid Build Coastguard Worker
xstrndup(const char * s,size_t n)36*cd60bc56SAndroid Build Coastguard Worker char *xstrndup(const char *s, size_t n)
37*cd60bc56SAndroid Build Coastguard Worker {
38*cd60bc56SAndroid Build Coastguard Worker size_t len = strnlen(s, n) + 1;
39*cd60bc56SAndroid Build Coastguard Worker char *d = xmalloc(len);
40*cd60bc56SAndroid Build Coastguard Worker
41*cd60bc56SAndroid Build Coastguard Worker memcpy(d, s, len - 1);
42*cd60bc56SAndroid Build Coastguard Worker d[len - 1] = '\0';
43*cd60bc56SAndroid Build Coastguard Worker
44*cd60bc56SAndroid Build Coastguard Worker return d;
45*cd60bc56SAndroid Build Coastguard Worker }
46*cd60bc56SAndroid Build Coastguard Worker
xavsprintf_append(char ** strp,const char * fmt,va_list ap)47*cd60bc56SAndroid Build Coastguard Worker int xavsprintf_append(char **strp, const char *fmt, va_list ap)
48*cd60bc56SAndroid Build Coastguard Worker {
49*cd60bc56SAndroid Build Coastguard Worker int n, size = 0; /* start with 128 bytes */
50*cd60bc56SAndroid Build Coastguard Worker char *p;
51*cd60bc56SAndroid Build Coastguard Worker va_list ap_copy;
52*cd60bc56SAndroid Build Coastguard Worker
53*cd60bc56SAndroid Build Coastguard Worker p = *strp;
54*cd60bc56SAndroid Build Coastguard Worker if (p)
55*cd60bc56SAndroid Build Coastguard Worker size = strlen(p);
56*cd60bc56SAndroid Build Coastguard Worker
57*cd60bc56SAndroid Build Coastguard Worker va_copy(ap_copy, ap);
58*cd60bc56SAndroid Build Coastguard Worker n = vsnprintf(NULL, 0, fmt, ap_copy) + 1;
59*cd60bc56SAndroid Build Coastguard Worker va_end(ap_copy);
60*cd60bc56SAndroid Build Coastguard Worker
61*cd60bc56SAndroid Build Coastguard Worker p = xrealloc(p, size + n);
62*cd60bc56SAndroid Build Coastguard Worker
63*cd60bc56SAndroid Build Coastguard Worker n = vsnprintf(p + size, n, fmt, ap);
64*cd60bc56SAndroid Build Coastguard Worker
65*cd60bc56SAndroid Build Coastguard Worker *strp = p;
66*cd60bc56SAndroid Build Coastguard Worker return strlen(p);
67*cd60bc56SAndroid Build Coastguard Worker }
68*cd60bc56SAndroid Build Coastguard Worker
xasprintf_append(char ** strp,const char * fmt,...)69*cd60bc56SAndroid Build Coastguard Worker int xasprintf_append(char **strp, const char *fmt, ...)
70*cd60bc56SAndroid Build Coastguard Worker {
71*cd60bc56SAndroid Build Coastguard Worker int n;
72*cd60bc56SAndroid Build Coastguard Worker va_list ap;
73*cd60bc56SAndroid Build Coastguard Worker
74*cd60bc56SAndroid Build Coastguard Worker va_start(ap, fmt);
75*cd60bc56SAndroid Build Coastguard Worker n = xavsprintf_append(strp, fmt, ap);
76*cd60bc56SAndroid Build Coastguard Worker va_end(ap);
77*cd60bc56SAndroid Build Coastguard Worker
78*cd60bc56SAndroid Build Coastguard Worker return n;
79*cd60bc56SAndroid Build Coastguard Worker }
80*cd60bc56SAndroid Build Coastguard Worker
xasprintf(char ** strp,const char * fmt,...)81*cd60bc56SAndroid Build Coastguard Worker int xasprintf(char **strp, const char *fmt, ...)
82*cd60bc56SAndroid Build Coastguard Worker {
83*cd60bc56SAndroid Build Coastguard Worker int n;
84*cd60bc56SAndroid Build Coastguard Worker va_list ap;
85*cd60bc56SAndroid Build Coastguard Worker
86*cd60bc56SAndroid Build Coastguard Worker *strp = NULL;
87*cd60bc56SAndroid Build Coastguard Worker
88*cd60bc56SAndroid Build Coastguard Worker va_start(ap, fmt);
89*cd60bc56SAndroid Build Coastguard Worker n = xavsprintf_append(strp, fmt, ap);
90*cd60bc56SAndroid Build Coastguard Worker va_end(ap);
91*cd60bc56SAndroid Build Coastguard Worker
92*cd60bc56SAndroid Build Coastguard Worker return n;
93*cd60bc56SAndroid Build Coastguard Worker }
94*cd60bc56SAndroid Build Coastguard Worker
join_path(const char * path,const char * name)95*cd60bc56SAndroid Build Coastguard Worker char *join_path(const char *path, const char *name)
96*cd60bc56SAndroid Build Coastguard Worker {
97*cd60bc56SAndroid Build Coastguard Worker int lenp = strlen(path);
98*cd60bc56SAndroid Build Coastguard Worker int lenn = strlen(name);
99*cd60bc56SAndroid Build Coastguard Worker int len;
100*cd60bc56SAndroid Build Coastguard Worker int needslash = 1;
101*cd60bc56SAndroid Build Coastguard Worker char *str;
102*cd60bc56SAndroid Build Coastguard Worker
103*cd60bc56SAndroid Build Coastguard Worker len = lenp + lenn + 2;
104*cd60bc56SAndroid Build Coastguard Worker if ((lenp > 0) && (path[lenp-1] == '/')) {
105*cd60bc56SAndroid Build Coastguard Worker needslash = 0;
106*cd60bc56SAndroid Build Coastguard Worker len--;
107*cd60bc56SAndroid Build Coastguard Worker }
108*cd60bc56SAndroid Build Coastguard Worker
109*cd60bc56SAndroid Build Coastguard Worker str = xmalloc(len);
110*cd60bc56SAndroid Build Coastguard Worker memcpy(str, path, lenp);
111*cd60bc56SAndroid Build Coastguard Worker if (needslash) {
112*cd60bc56SAndroid Build Coastguard Worker str[lenp] = '/';
113*cd60bc56SAndroid Build Coastguard Worker lenp++;
114*cd60bc56SAndroid Build Coastguard Worker }
115*cd60bc56SAndroid Build Coastguard Worker memcpy(str+lenp, name, lenn+1);
116*cd60bc56SAndroid Build Coastguard Worker return str;
117*cd60bc56SAndroid Build Coastguard Worker }
118*cd60bc56SAndroid Build Coastguard Worker
util_is_printable_string(const void * data,int len)119*cd60bc56SAndroid Build Coastguard Worker bool util_is_printable_string(const void *data, int len)
120*cd60bc56SAndroid Build Coastguard Worker {
121*cd60bc56SAndroid Build Coastguard Worker const char *s = data;
122*cd60bc56SAndroid Build Coastguard Worker const char *ss, *se;
123*cd60bc56SAndroid Build Coastguard Worker
124*cd60bc56SAndroid Build Coastguard Worker /* zero length is not */
125*cd60bc56SAndroid Build Coastguard Worker if (len == 0)
126*cd60bc56SAndroid Build Coastguard Worker return 0;
127*cd60bc56SAndroid Build Coastguard Worker
128*cd60bc56SAndroid Build Coastguard Worker /* must terminate with zero */
129*cd60bc56SAndroid Build Coastguard Worker if (s[len - 1] != '\0')
130*cd60bc56SAndroid Build Coastguard Worker return 0;
131*cd60bc56SAndroid Build Coastguard Worker
132*cd60bc56SAndroid Build Coastguard Worker se = s + len;
133*cd60bc56SAndroid Build Coastguard Worker
134*cd60bc56SAndroid Build Coastguard Worker while (s < se) {
135*cd60bc56SAndroid Build Coastguard Worker ss = s;
136*cd60bc56SAndroid Build Coastguard Worker while (s < se && *s && isprint((unsigned char)*s))
137*cd60bc56SAndroid Build Coastguard Worker s++;
138*cd60bc56SAndroid Build Coastguard Worker
139*cd60bc56SAndroid Build Coastguard Worker /* not zero, or not done yet */
140*cd60bc56SAndroid Build Coastguard Worker if (*s != '\0' || s == ss)
141*cd60bc56SAndroid Build Coastguard Worker return 0;
142*cd60bc56SAndroid Build Coastguard Worker
143*cd60bc56SAndroid Build Coastguard Worker s++;
144*cd60bc56SAndroid Build Coastguard Worker }
145*cd60bc56SAndroid Build Coastguard Worker
146*cd60bc56SAndroid Build Coastguard Worker return 1;
147*cd60bc56SAndroid Build Coastguard Worker }
148*cd60bc56SAndroid Build Coastguard Worker
149*cd60bc56SAndroid Build Coastguard Worker /*
150*cd60bc56SAndroid Build Coastguard Worker * Parse a octal encoded character starting at index i in string s. The
151*cd60bc56SAndroid Build Coastguard Worker * resulting character will be returned and the index i will be updated to
152*cd60bc56SAndroid Build Coastguard Worker * point at the character directly after the end of the encoding, this may be
153*cd60bc56SAndroid Build Coastguard Worker * the '\0' terminator of the string.
154*cd60bc56SAndroid Build Coastguard Worker */
get_oct_char(const char * s,int * i)155*cd60bc56SAndroid Build Coastguard Worker static char get_oct_char(const char *s, int *i)
156*cd60bc56SAndroid Build Coastguard Worker {
157*cd60bc56SAndroid Build Coastguard Worker char x[4];
158*cd60bc56SAndroid Build Coastguard Worker char *endx;
159*cd60bc56SAndroid Build Coastguard Worker long val;
160*cd60bc56SAndroid Build Coastguard Worker
161*cd60bc56SAndroid Build Coastguard Worker x[3] = '\0';
162*cd60bc56SAndroid Build Coastguard Worker strncpy(x, s + *i, 3);
163*cd60bc56SAndroid Build Coastguard Worker
164*cd60bc56SAndroid Build Coastguard Worker val = strtol(x, &endx, 8);
165*cd60bc56SAndroid Build Coastguard Worker
166*cd60bc56SAndroid Build Coastguard Worker assert(endx > x);
167*cd60bc56SAndroid Build Coastguard Worker
168*cd60bc56SAndroid Build Coastguard Worker (*i) += endx - x;
169*cd60bc56SAndroid Build Coastguard Worker return val;
170*cd60bc56SAndroid Build Coastguard Worker }
171*cd60bc56SAndroid Build Coastguard Worker
172*cd60bc56SAndroid Build Coastguard Worker /*
173*cd60bc56SAndroid Build Coastguard Worker * Parse a hexadecimal encoded character starting at index i in string s. The
174*cd60bc56SAndroid Build Coastguard Worker * resulting character will be returned and the index i will be updated to
175*cd60bc56SAndroid Build Coastguard Worker * point at the character directly after the end of the encoding, this may be
176*cd60bc56SAndroid Build Coastguard Worker * the '\0' terminator of the string.
177*cd60bc56SAndroid Build Coastguard Worker */
get_hex_char(const char * s,int * i)178*cd60bc56SAndroid Build Coastguard Worker static char get_hex_char(const char *s, int *i)
179*cd60bc56SAndroid Build Coastguard Worker {
180*cd60bc56SAndroid Build Coastguard Worker char x[3];
181*cd60bc56SAndroid Build Coastguard Worker char *endx;
182*cd60bc56SAndroid Build Coastguard Worker long val;
183*cd60bc56SAndroid Build Coastguard Worker
184*cd60bc56SAndroid Build Coastguard Worker x[2] = '\0';
185*cd60bc56SAndroid Build Coastguard Worker strncpy(x, s + *i, 2);
186*cd60bc56SAndroid Build Coastguard Worker
187*cd60bc56SAndroid Build Coastguard Worker val = strtol(x, &endx, 16);
188*cd60bc56SAndroid Build Coastguard Worker if (!(endx > x))
189*cd60bc56SAndroid Build Coastguard Worker die("\\x used with no following hex digits\n");
190*cd60bc56SAndroid Build Coastguard Worker
191*cd60bc56SAndroid Build Coastguard Worker (*i) += endx - x;
192*cd60bc56SAndroid Build Coastguard Worker return val;
193*cd60bc56SAndroid Build Coastguard Worker }
194*cd60bc56SAndroid Build Coastguard Worker
get_escape_char(const char * s,int * i)195*cd60bc56SAndroid Build Coastguard Worker char get_escape_char(const char *s, int *i)
196*cd60bc56SAndroid Build Coastguard Worker {
197*cd60bc56SAndroid Build Coastguard Worker char c = s[*i];
198*cd60bc56SAndroid Build Coastguard Worker int j = *i + 1;
199*cd60bc56SAndroid Build Coastguard Worker char val;
200*cd60bc56SAndroid Build Coastguard Worker
201*cd60bc56SAndroid Build Coastguard Worker switch (c) {
202*cd60bc56SAndroid Build Coastguard Worker case 'a':
203*cd60bc56SAndroid Build Coastguard Worker val = '\a';
204*cd60bc56SAndroid Build Coastguard Worker break;
205*cd60bc56SAndroid Build Coastguard Worker case 'b':
206*cd60bc56SAndroid Build Coastguard Worker val = '\b';
207*cd60bc56SAndroid Build Coastguard Worker break;
208*cd60bc56SAndroid Build Coastguard Worker case 't':
209*cd60bc56SAndroid Build Coastguard Worker val = '\t';
210*cd60bc56SAndroid Build Coastguard Worker break;
211*cd60bc56SAndroid Build Coastguard Worker case 'n':
212*cd60bc56SAndroid Build Coastguard Worker val = '\n';
213*cd60bc56SAndroid Build Coastguard Worker break;
214*cd60bc56SAndroid Build Coastguard Worker case 'v':
215*cd60bc56SAndroid Build Coastguard Worker val = '\v';
216*cd60bc56SAndroid Build Coastguard Worker break;
217*cd60bc56SAndroid Build Coastguard Worker case 'f':
218*cd60bc56SAndroid Build Coastguard Worker val = '\f';
219*cd60bc56SAndroid Build Coastguard Worker break;
220*cd60bc56SAndroid Build Coastguard Worker case 'r':
221*cd60bc56SAndroid Build Coastguard Worker val = '\r';
222*cd60bc56SAndroid Build Coastguard Worker break;
223*cd60bc56SAndroid Build Coastguard Worker case '0':
224*cd60bc56SAndroid Build Coastguard Worker case '1':
225*cd60bc56SAndroid Build Coastguard Worker case '2':
226*cd60bc56SAndroid Build Coastguard Worker case '3':
227*cd60bc56SAndroid Build Coastguard Worker case '4':
228*cd60bc56SAndroid Build Coastguard Worker case '5':
229*cd60bc56SAndroid Build Coastguard Worker case '6':
230*cd60bc56SAndroid Build Coastguard Worker case '7':
231*cd60bc56SAndroid Build Coastguard Worker j--; /* need to re-read the first digit as
232*cd60bc56SAndroid Build Coastguard Worker * part of the octal value */
233*cd60bc56SAndroid Build Coastguard Worker val = get_oct_char(s, &j);
234*cd60bc56SAndroid Build Coastguard Worker break;
235*cd60bc56SAndroid Build Coastguard Worker case 'x':
236*cd60bc56SAndroid Build Coastguard Worker val = get_hex_char(s, &j);
237*cd60bc56SAndroid Build Coastguard Worker break;
238*cd60bc56SAndroid Build Coastguard Worker default:
239*cd60bc56SAndroid Build Coastguard Worker val = c;
240*cd60bc56SAndroid Build Coastguard Worker }
241*cd60bc56SAndroid Build Coastguard Worker
242*cd60bc56SAndroid Build Coastguard Worker (*i) = j;
243*cd60bc56SAndroid Build Coastguard Worker return val;
244*cd60bc56SAndroid Build Coastguard Worker }
245*cd60bc56SAndroid Build Coastguard Worker
utilfdt_read_err(const char * filename,char ** buffp,size_t * len)246*cd60bc56SAndroid Build Coastguard Worker int utilfdt_read_err(const char *filename, char **buffp, size_t *len)
247*cd60bc56SAndroid Build Coastguard Worker {
248*cd60bc56SAndroid Build Coastguard Worker int fd = 0; /* assume stdin */
249*cd60bc56SAndroid Build Coastguard Worker char *buf = NULL;
250*cd60bc56SAndroid Build Coastguard Worker size_t bufsize = 1024, offset = 0;
251*cd60bc56SAndroid Build Coastguard Worker int ret = 0;
252*cd60bc56SAndroid Build Coastguard Worker
253*cd60bc56SAndroid Build Coastguard Worker *buffp = NULL;
254*cd60bc56SAndroid Build Coastguard Worker if (strcmp(filename, "-") != 0) {
255*cd60bc56SAndroid Build Coastguard Worker fd = open(filename, O_RDONLY);
256*cd60bc56SAndroid Build Coastguard Worker if (fd < 0)
257*cd60bc56SAndroid Build Coastguard Worker return errno;
258*cd60bc56SAndroid Build Coastguard Worker }
259*cd60bc56SAndroid Build Coastguard Worker
260*cd60bc56SAndroid Build Coastguard Worker /* Loop until we have read everything */
261*cd60bc56SAndroid Build Coastguard Worker buf = xmalloc(bufsize);
262*cd60bc56SAndroid Build Coastguard Worker do {
263*cd60bc56SAndroid Build Coastguard Worker /* Expand the buffer to hold the next chunk */
264*cd60bc56SAndroid Build Coastguard Worker if (offset == bufsize) {
265*cd60bc56SAndroid Build Coastguard Worker bufsize *= 2;
266*cd60bc56SAndroid Build Coastguard Worker buf = xrealloc(buf, bufsize);
267*cd60bc56SAndroid Build Coastguard Worker }
268*cd60bc56SAndroid Build Coastguard Worker
269*cd60bc56SAndroid Build Coastguard Worker ret = read(fd, &buf[offset], bufsize - offset);
270*cd60bc56SAndroid Build Coastguard Worker if (ret < 0) {
271*cd60bc56SAndroid Build Coastguard Worker ret = errno;
272*cd60bc56SAndroid Build Coastguard Worker break;
273*cd60bc56SAndroid Build Coastguard Worker }
274*cd60bc56SAndroid Build Coastguard Worker offset += ret;
275*cd60bc56SAndroid Build Coastguard Worker } while (ret != 0);
276*cd60bc56SAndroid Build Coastguard Worker
277*cd60bc56SAndroid Build Coastguard Worker /* Clean up, including closing stdin; return errno on error */
278*cd60bc56SAndroid Build Coastguard Worker close(fd);
279*cd60bc56SAndroid Build Coastguard Worker if (ret)
280*cd60bc56SAndroid Build Coastguard Worker free(buf);
281*cd60bc56SAndroid Build Coastguard Worker else
282*cd60bc56SAndroid Build Coastguard Worker *buffp = buf;
283*cd60bc56SAndroid Build Coastguard Worker if (len)
284*cd60bc56SAndroid Build Coastguard Worker *len = bufsize;
285*cd60bc56SAndroid Build Coastguard Worker return ret;
286*cd60bc56SAndroid Build Coastguard Worker }
287*cd60bc56SAndroid Build Coastguard Worker
utilfdt_read(const char * filename,size_t * len)288*cd60bc56SAndroid Build Coastguard Worker char *utilfdt_read(const char *filename, size_t *len)
289*cd60bc56SAndroid Build Coastguard Worker {
290*cd60bc56SAndroid Build Coastguard Worker char *buff;
291*cd60bc56SAndroid Build Coastguard Worker int ret = utilfdt_read_err(filename, &buff, len);
292*cd60bc56SAndroid Build Coastguard Worker
293*cd60bc56SAndroid Build Coastguard Worker if (ret) {
294*cd60bc56SAndroid Build Coastguard Worker fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
295*cd60bc56SAndroid Build Coastguard Worker strerror(ret));
296*cd60bc56SAndroid Build Coastguard Worker return NULL;
297*cd60bc56SAndroid Build Coastguard Worker }
298*cd60bc56SAndroid Build Coastguard Worker /* Successful read */
299*cd60bc56SAndroid Build Coastguard Worker return buff;
300*cd60bc56SAndroid Build Coastguard Worker }
301*cd60bc56SAndroid Build Coastguard Worker
utilfdt_write_err(const char * filename,const void * blob)302*cd60bc56SAndroid Build Coastguard Worker int utilfdt_write_err(const char *filename, const void *blob)
303*cd60bc56SAndroid Build Coastguard Worker {
304*cd60bc56SAndroid Build Coastguard Worker int fd = 1; /* assume stdout */
305*cd60bc56SAndroid Build Coastguard Worker int totalsize;
306*cd60bc56SAndroid Build Coastguard Worker int offset;
307*cd60bc56SAndroid Build Coastguard Worker int ret = 0;
308*cd60bc56SAndroid Build Coastguard Worker const char *ptr = blob;
309*cd60bc56SAndroid Build Coastguard Worker
310*cd60bc56SAndroid Build Coastguard Worker if (strcmp(filename, "-") != 0) {
311*cd60bc56SAndroid Build Coastguard Worker fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
312*cd60bc56SAndroid Build Coastguard Worker if (fd < 0)
313*cd60bc56SAndroid Build Coastguard Worker return errno;
314*cd60bc56SAndroid Build Coastguard Worker }
315*cd60bc56SAndroid Build Coastguard Worker
316*cd60bc56SAndroid Build Coastguard Worker totalsize = fdt_totalsize(blob);
317*cd60bc56SAndroid Build Coastguard Worker offset = 0;
318*cd60bc56SAndroid Build Coastguard Worker
319*cd60bc56SAndroid Build Coastguard Worker while (offset < totalsize) {
320*cd60bc56SAndroid Build Coastguard Worker ret = write(fd, ptr + offset, totalsize - offset);
321*cd60bc56SAndroid Build Coastguard Worker if (ret < 0) {
322*cd60bc56SAndroid Build Coastguard Worker ret = -errno;
323*cd60bc56SAndroid Build Coastguard Worker break;
324*cd60bc56SAndroid Build Coastguard Worker }
325*cd60bc56SAndroid Build Coastguard Worker offset += ret;
326*cd60bc56SAndroid Build Coastguard Worker }
327*cd60bc56SAndroid Build Coastguard Worker /* Close the file/stdin; return errno on error */
328*cd60bc56SAndroid Build Coastguard Worker if (fd != 1)
329*cd60bc56SAndroid Build Coastguard Worker close(fd);
330*cd60bc56SAndroid Build Coastguard Worker return ret < 0 ? -ret : 0;
331*cd60bc56SAndroid Build Coastguard Worker }
332*cd60bc56SAndroid Build Coastguard Worker
333*cd60bc56SAndroid Build Coastguard Worker
utilfdt_write(const char * filename,const void * blob)334*cd60bc56SAndroid Build Coastguard Worker int utilfdt_write(const char *filename, const void *blob)
335*cd60bc56SAndroid Build Coastguard Worker {
336*cd60bc56SAndroid Build Coastguard Worker int ret = utilfdt_write_err(filename, blob);
337*cd60bc56SAndroid Build Coastguard Worker
338*cd60bc56SAndroid Build Coastguard Worker if (ret) {
339*cd60bc56SAndroid Build Coastguard Worker fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename,
340*cd60bc56SAndroid Build Coastguard Worker strerror(ret));
341*cd60bc56SAndroid Build Coastguard Worker }
342*cd60bc56SAndroid Build Coastguard Worker return ret ? -1 : 0;
343*cd60bc56SAndroid Build Coastguard Worker }
344*cd60bc56SAndroid Build Coastguard Worker
utilfdt_decode_type(const char * fmt,int * type,int * size)345*cd60bc56SAndroid Build Coastguard Worker int utilfdt_decode_type(const char *fmt, int *type, int *size)
346*cd60bc56SAndroid Build Coastguard Worker {
347*cd60bc56SAndroid Build Coastguard Worker int qualifier = 0;
348*cd60bc56SAndroid Build Coastguard Worker
349*cd60bc56SAndroid Build Coastguard Worker if (!*fmt)
350*cd60bc56SAndroid Build Coastguard Worker return -1;
351*cd60bc56SAndroid Build Coastguard Worker
352*cd60bc56SAndroid Build Coastguard Worker /* get the conversion qualifier */
353*cd60bc56SAndroid Build Coastguard Worker *size = -1;
354*cd60bc56SAndroid Build Coastguard Worker if (strchr("hlLb", *fmt)) {
355*cd60bc56SAndroid Build Coastguard Worker qualifier = *fmt++;
356*cd60bc56SAndroid Build Coastguard Worker if (qualifier == *fmt) {
357*cd60bc56SAndroid Build Coastguard Worker switch (*fmt++) {
358*cd60bc56SAndroid Build Coastguard Worker /* TODO: case 'l': qualifier = 'L'; break;*/
359*cd60bc56SAndroid Build Coastguard Worker case 'h':
360*cd60bc56SAndroid Build Coastguard Worker qualifier = 'b';
361*cd60bc56SAndroid Build Coastguard Worker break;
362*cd60bc56SAndroid Build Coastguard Worker }
363*cd60bc56SAndroid Build Coastguard Worker }
364*cd60bc56SAndroid Build Coastguard Worker }
365*cd60bc56SAndroid Build Coastguard Worker
366*cd60bc56SAndroid Build Coastguard Worker /* we should now have a type */
367*cd60bc56SAndroid Build Coastguard Worker if ((*fmt == '\0') || !strchr("iuxsr", *fmt))
368*cd60bc56SAndroid Build Coastguard Worker return -1;
369*cd60bc56SAndroid Build Coastguard Worker
370*cd60bc56SAndroid Build Coastguard Worker /* convert qualifier (bhL) to byte size */
371*cd60bc56SAndroid Build Coastguard Worker if (*fmt != 's' && *fmt != 'r')
372*cd60bc56SAndroid Build Coastguard Worker *size = qualifier == 'b' ? 1 :
373*cd60bc56SAndroid Build Coastguard Worker qualifier == 'h' ? 2 :
374*cd60bc56SAndroid Build Coastguard Worker qualifier == 'l' ? 4 : -1;
375*cd60bc56SAndroid Build Coastguard Worker *type = *fmt++;
376*cd60bc56SAndroid Build Coastguard Worker
377*cd60bc56SAndroid Build Coastguard Worker /* that should be it! */
378*cd60bc56SAndroid Build Coastguard Worker if (*fmt)
379*cd60bc56SAndroid Build Coastguard Worker return -1;
380*cd60bc56SAndroid Build Coastguard Worker return 0;
381*cd60bc56SAndroid Build Coastguard Worker }
382*cd60bc56SAndroid Build Coastguard Worker
utilfdt_print_data(const char * data,int len)383*cd60bc56SAndroid Build Coastguard Worker void utilfdt_print_data(const char *data, int len)
384*cd60bc56SAndroid Build Coastguard Worker {
385*cd60bc56SAndroid Build Coastguard Worker int i;
386*cd60bc56SAndroid Build Coastguard Worker const char *s;
387*cd60bc56SAndroid Build Coastguard Worker
388*cd60bc56SAndroid Build Coastguard Worker /* no data, don't print */
389*cd60bc56SAndroid Build Coastguard Worker if (len == 0)
390*cd60bc56SAndroid Build Coastguard Worker return;
391*cd60bc56SAndroid Build Coastguard Worker
392*cd60bc56SAndroid Build Coastguard Worker if (util_is_printable_string(data, len)) {
393*cd60bc56SAndroid Build Coastguard Worker printf(" = ");
394*cd60bc56SAndroid Build Coastguard Worker
395*cd60bc56SAndroid Build Coastguard Worker s = data;
396*cd60bc56SAndroid Build Coastguard Worker do {
397*cd60bc56SAndroid Build Coastguard Worker printf("\"%s\"", s);
398*cd60bc56SAndroid Build Coastguard Worker s += strlen(s) + 1;
399*cd60bc56SAndroid Build Coastguard Worker if (s < data + len)
400*cd60bc56SAndroid Build Coastguard Worker printf(", ");
401*cd60bc56SAndroid Build Coastguard Worker } while (s < data + len);
402*cd60bc56SAndroid Build Coastguard Worker
403*cd60bc56SAndroid Build Coastguard Worker } else if ((len % 4) == 0) {
404*cd60bc56SAndroid Build Coastguard Worker const fdt32_t *cell = (const fdt32_t *)data;
405*cd60bc56SAndroid Build Coastguard Worker
406*cd60bc56SAndroid Build Coastguard Worker printf(" = <");
407*cd60bc56SAndroid Build Coastguard Worker for (i = 0, len /= 4; i < len; i++)
408*cd60bc56SAndroid Build Coastguard Worker printf("0x%08" PRIx32 "%s", fdt32_to_cpu(cell[i]),
409*cd60bc56SAndroid Build Coastguard Worker i < (len - 1) ? " " : "");
410*cd60bc56SAndroid Build Coastguard Worker printf(">");
411*cd60bc56SAndroid Build Coastguard Worker } else {
412*cd60bc56SAndroid Build Coastguard Worker const unsigned char *p = (const unsigned char *)data;
413*cd60bc56SAndroid Build Coastguard Worker printf(" = [");
414*cd60bc56SAndroid Build Coastguard Worker for (i = 0; i < len; i++)
415*cd60bc56SAndroid Build Coastguard Worker printf("%02x%s", *p++, i < len - 1 ? " " : "");
416*cd60bc56SAndroid Build Coastguard Worker printf("]");
417*cd60bc56SAndroid Build Coastguard Worker }
418*cd60bc56SAndroid Build Coastguard Worker }
419*cd60bc56SAndroid Build Coastguard Worker
util_version(void)420*cd60bc56SAndroid Build Coastguard Worker void NORETURN util_version(void)
421*cd60bc56SAndroid Build Coastguard Worker {
422*cd60bc56SAndroid Build Coastguard Worker printf("Version: %s\n", DTC_VERSION);
423*cd60bc56SAndroid Build Coastguard Worker exit(0);
424*cd60bc56SAndroid Build Coastguard Worker }
425*cd60bc56SAndroid Build Coastguard Worker
util_usage(const char * errmsg,const char * synopsis,const char * short_opts,struct option const long_opts[],const char * const opts_help[])426*cd60bc56SAndroid Build Coastguard Worker void NORETURN util_usage(const char *errmsg, const char *synopsis,
427*cd60bc56SAndroid Build Coastguard Worker const char *short_opts,
428*cd60bc56SAndroid Build Coastguard Worker struct option const long_opts[],
429*cd60bc56SAndroid Build Coastguard Worker const char * const opts_help[])
430*cd60bc56SAndroid Build Coastguard Worker {
431*cd60bc56SAndroid Build Coastguard Worker FILE *fp = errmsg ? stderr : stdout;
432*cd60bc56SAndroid Build Coastguard Worker const char a_arg[] = "<arg>";
433*cd60bc56SAndroid Build Coastguard Worker size_t a_arg_len = strlen(a_arg) + 1;
434*cd60bc56SAndroid Build Coastguard Worker size_t i;
435*cd60bc56SAndroid Build Coastguard Worker int optlen;
436*cd60bc56SAndroid Build Coastguard Worker
437*cd60bc56SAndroid Build Coastguard Worker fprintf(fp,
438*cd60bc56SAndroid Build Coastguard Worker "Usage: %s\n"
439*cd60bc56SAndroid Build Coastguard Worker "\n"
440*cd60bc56SAndroid Build Coastguard Worker "Options: -[%s]\n", synopsis, short_opts);
441*cd60bc56SAndroid Build Coastguard Worker
442*cd60bc56SAndroid Build Coastguard Worker /* prescan the --long opt length to auto-align */
443*cd60bc56SAndroid Build Coastguard Worker optlen = 0;
444*cd60bc56SAndroid Build Coastguard Worker for (i = 0; long_opts[i].name; ++i) {
445*cd60bc56SAndroid Build Coastguard Worker /* +1 is for space between --opt and help text */
446*cd60bc56SAndroid Build Coastguard Worker int l = strlen(long_opts[i].name) + 1;
447*cd60bc56SAndroid Build Coastguard Worker if (long_opts[i].has_arg == a_argument)
448*cd60bc56SAndroid Build Coastguard Worker l += a_arg_len;
449*cd60bc56SAndroid Build Coastguard Worker if (optlen < l)
450*cd60bc56SAndroid Build Coastguard Worker optlen = l;
451*cd60bc56SAndroid Build Coastguard Worker }
452*cd60bc56SAndroid Build Coastguard Worker
453*cd60bc56SAndroid Build Coastguard Worker for (i = 0; long_opts[i].name; ++i) {
454*cd60bc56SAndroid Build Coastguard Worker /* helps when adding new applets or options */
455*cd60bc56SAndroid Build Coastguard Worker assert(opts_help[i] != NULL);
456*cd60bc56SAndroid Build Coastguard Worker
457*cd60bc56SAndroid Build Coastguard Worker /* first output the short flag if it has one */
458*cd60bc56SAndroid Build Coastguard Worker if (long_opts[i].val > '~')
459*cd60bc56SAndroid Build Coastguard Worker fprintf(fp, " ");
460*cd60bc56SAndroid Build Coastguard Worker else
461*cd60bc56SAndroid Build Coastguard Worker fprintf(fp, " -%c, ", long_opts[i].val);
462*cd60bc56SAndroid Build Coastguard Worker
463*cd60bc56SAndroid Build Coastguard Worker /* then the long flag */
464*cd60bc56SAndroid Build Coastguard Worker if (long_opts[i].has_arg == no_argument)
465*cd60bc56SAndroid Build Coastguard Worker fprintf(fp, "--%-*s", optlen, long_opts[i].name);
466*cd60bc56SAndroid Build Coastguard Worker else
467*cd60bc56SAndroid Build Coastguard Worker fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg,
468*cd60bc56SAndroid Build Coastguard Worker (int)(optlen - strlen(long_opts[i].name) - a_arg_len), "");
469*cd60bc56SAndroid Build Coastguard Worker
470*cd60bc56SAndroid Build Coastguard Worker /* finally the help text */
471*cd60bc56SAndroid Build Coastguard Worker fprintf(fp, "%s\n", opts_help[i]);
472*cd60bc56SAndroid Build Coastguard Worker }
473*cd60bc56SAndroid Build Coastguard Worker
474*cd60bc56SAndroid Build Coastguard Worker if (errmsg) {
475*cd60bc56SAndroid Build Coastguard Worker fprintf(fp, "\nError: %s\n", errmsg);
476*cd60bc56SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
477*cd60bc56SAndroid Build Coastguard Worker } else
478*cd60bc56SAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
479*cd60bc56SAndroid Build Coastguard Worker }
480