xref: /rk3399_rockchip-uboot/scripts/dtc/util.h (revision d18719a48ffdf6be4a0724f88d8968904df3a0d9)
1*d18719a4STom Rini #ifndef _UTIL_H
2*d18719a4STom Rini #define _UTIL_H
3*d18719a4STom Rini 
4*d18719a4STom Rini #include <stdarg.h>
5*d18719a4STom Rini #include <stdbool.h>
6*d18719a4STom Rini #include <getopt.h>
7*d18719a4STom Rini 
8*d18719a4STom Rini /*
9*d18719a4STom Rini  * Copyright 2011 The Chromium Authors, All Rights Reserved.
10*d18719a4STom Rini  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
11*d18719a4STom Rini  *
12*d18719a4STom Rini  * This program is free software; you can redistribute it and/or
13*d18719a4STom Rini  * modify it under the terms of the GNU General Public License as
14*d18719a4STom Rini  * published by the Free Software Foundation; either version 2 of the
15*d18719a4STom Rini  * License, or (at your option) any later version.
16*d18719a4STom Rini  *
17*d18719a4STom Rini  *  This program is distributed in the hope that it will be useful,
18*d18719a4STom Rini  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19*d18719a4STom Rini  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20*d18719a4STom Rini  *  General Public License for more details.
21*d18719a4STom Rini  *
22*d18719a4STom Rini  *  You should have received a copy of the GNU General Public License
23*d18719a4STom Rini  *  along with this program; if not, write to the Free Software
24*d18719a4STom Rini  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
25*d18719a4STom Rini  *                                                                   USA
26*d18719a4STom Rini  */
27*d18719a4STom Rini 
28*d18719a4STom Rini #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
29*d18719a4STom Rini 
30*d18719a4STom Rini #ifdef __GNUC__
31*d18719a4STom Rini static inline void
32*d18719a4STom Rini __attribute__((noreturn)) __attribute__((format (printf, 1, 2)))
33*d18719a4STom Rini die(const char *str, ...)
34*d18719a4STom Rini #else
35*d18719a4STom Rini static inline void die(const char *str, ...)
36*d18719a4STom Rini #endif
37*d18719a4STom Rini {
38*d18719a4STom Rini 	va_list ap;
39*d18719a4STom Rini 
40*d18719a4STom Rini 	va_start(ap, str);
41*d18719a4STom Rini 	fprintf(stderr, "FATAL ERROR: ");
42*d18719a4STom Rini 	vfprintf(stderr, str, ap);
43*d18719a4STom Rini 	va_end(ap);
44*d18719a4STom Rini 	exit(1);
45*d18719a4STom Rini }
46*d18719a4STom Rini 
47*d18719a4STom Rini static inline void *xmalloc(size_t len)
48*d18719a4STom Rini {
49*d18719a4STom Rini 	void *new = malloc(len);
50*d18719a4STom Rini 
51*d18719a4STom Rini 	if (!new)
52*d18719a4STom Rini 		die("malloc() failed\n");
53*d18719a4STom Rini 
54*d18719a4STom Rini 	return new;
55*d18719a4STom Rini }
56*d18719a4STom Rini 
57*d18719a4STom Rini static inline void *xrealloc(void *p, size_t len)
58*d18719a4STom Rini {
59*d18719a4STom Rini 	void *new = realloc(p, len);
60*d18719a4STom Rini 
61*d18719a4STom Rini 	if (!new)
62*d18719a4STom Rini 		die("realloc() failed (len=%zd)\n", len);
63*d18719a4STom Rini 
64*d18719a4STom Rini 	return new;
65*d18719a4STom Rini }
66*d18719a4STom Rini 
67*d18719a4STom Rini extern char *xstrdup(const char *s);
68*d18719a4STom Rini 
69*d18719a4STom Rini #ifdef __GNUC__
70*d18719a4STom Rini extern int __attribute__((format (printf, 2, 3)))
71*d18719a4STom Rini xasprintf(char **strp, const char *fmt, ...);
72*d18719a4STom Rini #else
73*d18719a4STom Rini extern int xasprintf(char **strp, const char *fmt, ...);
74*d18719a4STom Rini #endif
75*d18719a4STom Rini extern char *join_path(const char *path, const char *name);
76*d18719a4STom Rini 
77*d18719a4STom Rini /**
78*d18719a4STom Rini  * Check a property of a given length to see if it is all printable and
79*d18719a4STom Rini  * has a valid terminator. The property can contain either a single string,
80*d18719a4STom Rini  * or multiple strings each of non-zero length.
81*d18719a4STom Rini  *
82*d18719a4STom Rini  * @param data	The string to check
83*d18719a4STom Rini  * @param len	The string length including terminator
84*d18719a4STom Rini  * @return 1 if a valid printable string, 0 if not
85*d18719a4STom Rini  */
86*d18719a4STom Rini bool util_is_printable_string(const void *data, int len);
87*d18719a4STom Rini 
88*d18719a4STom Rini /*
89*d18719a4STom Rini  * Parse an escaped character starting at index i in string s.  The resulting
90*d18719a4STom Rini  * character will be returned and the index i will be updated to point at the
91*d18719a4STom Rini  * character directly after the end of the encoding, this may be the '\0'
92*d18719a4STom Rini  * terminator of the string.
93*d18719a4STom Rini  */
94*d18719a4STom Rini char get_escape_char(const char *s, int *i);
95*d18719a4STom Rini 
96*d18719a4STom Rini /**
97*d18719a4STom Rini  * Read a device tree file into a buffer. This will report any errors on
98*d18719a4STom Rini  * stderr.
99*d18719a4STom Rini  *
100*d18719a4STom Rini  * @param filename	The filename to read, or - for stdin
101*d18719a4STom Rini  * @return Pointer to allocated buffer containing fdt, or NULL on error
102*d18719a4STom Rini  */
103*d18719a4STom Rini char *utilfdt_read(const char *filename);
104*d18719a4STom Rini 
105*d18719a4STom Rini /**
106*d18719a4STom Rini  * Like utilfdt_read(), but also passes back the size of the file read.
107*d18719a4STom Rini  *
108*d18719a4STom Rini  * @param len		If non-NULL, the amount of data we managed to read
109*d18719a4STom Rini  */
110*d18719a4STom Rini char *utilfdt_read_len(const char *filename, off_t *len);
111*d18719a4STom Rini 
112*d18719a4STom Rini /**
113*d18719a4STom Rini  * Read a device tree file into a buffer. Does not report errors, but only
114*d18719a4STom Rini  * returns them. The value returned can be passed to strerror() to obtain
115*d18719a4STom Rini  * an error message for the user.
116*d18719a4STom Rini  *
117*d18719a4STom Rini  * @param filename	The filename to read, or - for stdin
118*d18719a4STom Rini  * @param buffp		Returns pointer to buffer containing fdt
119*d18719a4STom Rini  * @return 0 if ok, else an errno value representing the error
120*d18719a4STom Rini  */
121*d18719a4STom Rini int utilfdt_read_err(const char *filename, char **buffp);
122*d18719a4STom Rini 
123*d18719a4STom Rini /**
124*d18719a4STom Rini  * Like utilfdt_read_err(), but also passes back the size of the file read.
125*d18719a4STom Rini  *
126*d18719a4STom Rini  * @param len		If non-NULL, the amount of data we managed to read
127*d18719a4STom Rini  */
128*d18719a4STom Rini int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len);
129*d18719a4STom Rini 
130*d18719a4STom Rini /**
131*d18719a4STom Rini  * Write a device tree buffer to a file. This will report any errors on
132*d18719a4STom Rini  * stderr.
133*d18719a4STom Rini  *
134*d18719a4STom Rini  * @param filename	The filename to write, or - for stdout
135*d18719a4STom Rini  * @param blob		Poiner to buffer containing fdt
136*d18719a4STom Rini  * @return 0 if ok, -1 on error
137*d18719a4STom Rini  */
138*d18719a4STom Rini int utilfdt_write(const char *filename, const void *blob);
139*d18719a4STom Rini 
140*d18719a4STom Rini /**
141*d18719a4STom Rini  * Write a device tree buffer to a file. Does not report errors, but only
142*d18719a4STom Rini  * returns them. The value returned can be passed to strerror() to obtain
143*d18719a4STom Rini  * an error message for the user.
144*d18719a4STom Rini  *
145*d18719a4STom Rini  * @param filename	The filename to write, or - for stdout
146*d18719a4STom Rini  * @param blob		Poiner to buffer containing fdt
147*d18719a4STom Rini  * @return 0 if ok, else an errno value representing the error
148*d18719a4STom Rini  */
149*d18719a4STom Rini int utilfdt_write_err(const char *filename, const void *blob);
150*d18719a4STom Rini 
151*d18719a4STom Rini /**
152*d18719a4STom Rini  * Decode a data type string. The purpose of this string
153*d18719a4STom Rini  *
154*d18719a4STom Rini  * The string consists of an optional character followed by the type:
155*d18719a4STom Rini  *	Modifier characters:
156*d18719a4STom Rini  *		hh or b	1 byte
157*d18719a4STom Rini  *		h	2 byte
158*d18719a4STom Rini  *		l	4 byte, default
159*d18719a4STom Rini  *
160*d18719a4STom Rini  *	Type character:
161*d18719a4STom Rini  *		s	string
162*d18719a4STom Rini  *		i	signed integer
163*d18719a4STom Rini  *		u	unsigned integer
164*d18719a4STom Rini  *		x	hex
165*d18719a4STom Rini  *
166*d18719a4STom Rini  * TODO: Implement ll modifier (8 bytes)
167*d18719a4STom Rini  * TODO: Implement o type (octal)
168*d18719a4STom Rini  *
169*d18719a4STom Rini  * @param fmt		Format string to process
170*d18719a4STom Rini  * @param type		Returns type found(s/d/u/x), or 0 if none
171*d18719a4STom Rini  * @param size		Returns size found(1,2,4,8) or 4 if none
172*d18719a4STom Rini  * @return 0 if ok, -1 on error (no type given, or other invalid format)
173*d18719a4STom Rini  */
174*d18719a4STom Rini int utilfdt_decode_type(const char *fmt, int *type, int *size);
175*d18719a4STom Rini 
176*d18719a4STom Rini /*
177*d18719a4STom Rini  * This is a usage message fragment for the -t option. It is the format
178*d18719a4STom Rini  * supported by utilfdt_decode_type.
179*d18719a4STom Rini  */
180*d18719a4STom Rini 
181*d18719a4STom Rini #define USAGE_TYPE_MSG \
182*d18719a4STom Rini 	"<type>\ts=string, i=int, u=unsigned, x=hex\n" \
183*d18719a4STom Rini 	"\tOptional modifier prefix:\n" \
184*d18719a4STom Rini 	"\t\thh or b=byte, h=2 byte, l=4 byte (default)";
185*d18719a4STom Rini 
186*d18719a4STom Rini /**
187*d18719a4STom Rini  * Print property data in a readable format to stdout
188*d18719a4STom Rini  *
189*d18719a4STom Rini  * Properties that look like strings will be printed as strings. Otherwise
190*d18719a4STom Rini  * the data will be displayed either as cells (if len is a multiple of 4
191*d18719a4STom Rini  * bytes) or bytes.
192*d18719a4STom Rini  *
193*d18719a4STom Rini  * If len is 0 then this function does nothing.
194*d18719a4STom Rini  *
195*d18719a4STom Rini  * @param data	Pointers to property data
196*d18719a4STom Rini  * @param len	Length of property data
197*d18719a4STom Rini  */
198*d18719a4STom Rini void utilfdt_print_data(const char *data, int len);
199*d18719a4STom Rini 
200*d18719a4STom Rini /**
201*d18719a4STom Rini  * Show source version and exit
202*d18719a4STom Rini  */
203*d18719a4STom Rini void util_version(void) __attribute__((noreturn));
204*d18719a4STom Rini 
205*d18719a4STom Rini /**
206*d18719a4STom Rini  * Show usage and exit
207*d18719a4STom Rini  *
208*d18719a4STom Rini  * This helps standardize the output of various utils.  You most likely want
209*d18719a4STom Rini  * to use the usage() helper below rather than call this.
210*d18719a4STom Rini  *
211*d18719a4STom Rini  * @param errmsg	If non-NULL, an error message to display
212*d18719a4STom Rini  * @param synopsis	The initial example usage text (and possible examples)
213*d18719a4STom Rini  * @param short_opts	The string of short options
214*d18719a4STom Rini  * @param long_opts	The structure of long options
215*d18719a4STom Rini  * @param opts_help	An array of help strings (should align with long_opts)
216*d18719a4STom Rini  */
217*d18719a4STom Rini void util_usage(const char *errmsg, const char *synopsis,
218*d18719a4STom Rini 		const char *short_opts, struct option const long_opts[],
219*d18719a4STom Rini 		const char * const opts_help[]) __attribute__((noreturn));
220*d18719a4STom Rini 
221*d18719a4STom Rini /**
222*d18719a4STom Rini  * Show usage and exit
223*d18719a4STom Rini  *
224*d18719a4STom Rini  * If you name all your usage variables with usage_xxx, then you can call this
225*d18719a4STom Rini  * help macro rather than expanding all arguments yourself.
226*d18719a4STom Rini  *
227*d18719a4STom Rini  * @param errmsg	If non-NULL, an error message to display
228*d18719a4STom Rini  */
229*d18719a4STom Rini #define usage(errmsg) \
230*d18719a4STom Rini 	util_usage(errmsg, usage_synopsis, usage_short_opts, \
231*d18719a4STom Rini 		   usage_long_opts, usage_opts_help)
232*d18719a4STom Rini 
233*d18719a4STom Rini /**
234*d18719a4STom Rini  * Call getopt_long() with standard options
235*d18719a4STom Rini  *
236*d18719a4STom Rini  * Since all util code runs getopt in the same way, provide a helper.
237*d18719a4STom Rini  */
238*d18719a4STom Rini #define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
239*d18719a4STom Rini 				       usage_long_opts, NULL)
240*d18719a4STom Rini 
241*d18719a4STom Rini /* Helper for aligning long_opts array */
242*d18719a4STom Rini #define a_argument required_argument
243*d18719a4STom Rini 
244*d18719a4STom Rini /* Helper for usage_short_opts string constant */
245*d18719a4STom Rini #define USAGE_COMMON_SHORT_OPTS "hV"
246*d18719a4STom Rini 
247*d18719a4STom Rini /* Helper for usage_long_opts option array */
248*d18719a4STom Rini #define USAGE_COMMON_LONG_OPTS \
249*d18719a4STom Rini 	{"help",      no_argument, NULL, 'h'}, \
250*d18719a4STom Rini 	{"version",   no_argument, NULL, 'V'}, \
251*d18719a4STom Rini 	{NULL,        no_argument, NULL, 0x0}
252*d18719a4STom Rini 
253*d18719a4STom Rini /* Helper for usage_opts_help array */
254*d18719a4STom Rini #define USAGE_COMMON_OPTS_HELP \
255*d18719a4STom Rini 	"Print this help and exit", \
256*d18719a4STom Rini 	"Print version and exit", \
257*d18719a4STom Rini 	NULL
258*d18719a4STom Rini 
259*d18719a4STom Rini /* Helper for getopt case statements */
260*d18719a4STom Rini #define case_USAGE_COMMON_FLAGS \
261*d18719a4STom Rini 	case 'h': usage(NULL); \
262*d18719a4STom Rini 	case 'V': util_version(); \
263*d18719a4STom Rini 	case '?': usage("unknown option");
264*d18719a4STom Rini 
265*d18719a4STom Rini #endif /* _UTIL_H */
266