xref: /openbmc/linux/scripts/dtc/util.h (revision ea3723a5)
112869ecdSRob Herring /* SPDX-License-Identifier: GPL-2.0-or-later */
29130ba88SRob Herring #ifndef UTIL_H
39130ba88SRob Herring #define UTIL_H
4658f29a5SJohn Bonesio 
56e9c9686SRob Herring #include <stdlib.h>
6cd296721SStephen Warren #include <stdarg.h>
747605971SRob Herring #include <stdbool.h>
873ab39b1SGrant Likely #include <getopt.h>
9cd296721SStephen Warren 
10658f29a5SJohn Bonesio /*
11cd296721SStephen Warren  * Copyright 2011 The Chromium Authors, All Rights Reserved.
12658f29a5SJohn Bonesio  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
13658f29a5SJohn Bonesio  */
14658f29a5SJohn Bonesio 
1589d12310SRob Herring #ifdef __GNUC__
16a77725a9SRob Herring #if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
170cec114eSRob Herring #define PRINTF(i, j)	__attribute__((format (gnu_printf, i, j)))
18a77725a9SRob Herring #else
19a77725a9SRob Herring #define PRINTF(i, j)	__attribute__((format (printf, i, j)))
200cec114eSRob Herring #endif
2189d12310SRob Herring #define NORETURN	__attribute__((noreturn))
2289d12310SRob Herring #else
2389d12310SRob Herring #define PRINTF(i, j)
2489d12310SRob Herring #define NORETURN
2589d12310SRob Herring #endif
2689d12310SRob Herring 
2773ab39b1SGrant Likely #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
2873ab39b1SGrant Likely 
299130ba88SRob Herring #define stringify(s)	stringify_(s)
309130ba88SRob Herring #define stringify_(s)	#s
319130ba88SRob Herring 
die(const char * str,...)3289d12310SRob Herring static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
33658f29a5SJohn Bonesio {
34658f29a5SJohn Bonesio 	va_list ap;
35658f29a5SJohn Bonesio 
36658f29a5SJohn Bonesio 	va_start(ap, str);
37658f29a5SJohn Bonesio 	fprintf(stderr, "FATAL ERROR: ");
38658f29a5SJohn Bonesio 	vfprintf(stderr, str, ap);
3947605971SRob Herring 	va_end(ap);
40658f29a5SJohn Bonesio 	exit(1);
41658f29a5SJohn Bonesio }
42658f29a5SJohn Bonesio 
xmalloc(size_t len)43658f29a5SJohn Bonesio static inline void *xmalloc(size_t len)
44658f29a5SJohn Bonesio {
45658f29a5SJohn Bonesio 	void *new = malloc(len);
46658f29a5SJohn Bonesio 
47658f29a5SJohn Bonesio 	if (!new)
48658f29a5SJohn Bonesio 		die("malloc() failed\n");
49658f29a5SJohn Bonesio 
50658f29a5SJohn Bonesio 	return new;
51658f29a5SJohn Bonesio }
52658f29a5SJohn Bonesio 
xrealloc(void * p,size_t len)53658f29a5SJohn Bonesio static inline void *xrealloc(void *p, size_t len)
54658f29a5SJohn Bonesio {
55658f29a5SJohn Bonesio 	void *new = realloc(p, len);
56658f29a5SJohn Bonesio 
57658f29a5SJohn Bonesio 	if (!new)
5889d12310SRob Herring 		die("realloc() failed (len=%zd)\n", len);
59658f29a5SJohn Bonesio 
60658f29a5SJohn Bonesio 	return new;
61658f29a5SJohn Bonesio }
62658f29a5SJohn Bonesio 
63658f29a5SJohn Bonesio extern char *xstrdup(const char *s);
64*ea3723a5SRob Herring extern char *xstrndup(const char *s, size_t len);
6589d12310SRob Herring 
6689d12310SRob Herring extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
67c2e7075cSRob Herring extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...);
68c2e7075cSRob Herring extern int xavsprintf_append(char **strp, const char *fmt, va_list ap);
69658f29a5SJohn Bonesio extern char *join_path(const char *path, const char *name);
70658f29a5SJohn Bonesio 
71cd296721SStephen Warren /**
7273ab39b1SGrant Likely  * Check a property of a given length to see if it is all printable and
7373ab39b1SGrant Likely  * has a valid terminator. The property can contain either a single string,
7473ab39b1SGrant Likely  * or multiple strings each of non-zero length.
75cd296721SStephen Warren  *
76cd296721SStephen Warren  * @param data	The string to check
77cd296721SStephen Warren  * @param len	The string length including terminator
7873ab39b1SGrant Likely  * @return 1 if a valid printable string, 0 if not
7973ab39b1SGrant Likely  */
8047605971SRob Herring bool util_is_printable_string(const void *data, int len);
81cd296721SStephen Warren 
82cd296721SStephen Warren /*
83cd296721SStephen Warren  * Parse an escaped character starting at index i in string s.  The resulting
84cd296721SStephen Warren  * character will be returned and the index i will be updated to point at the
85cd296721SStephen Warren  * character directly after the end of the encoding, this may be the '\0'
86cd296721SStephen Warren  * terminator of the string.
87cd296721SStephen Warren  */
88cd296721SStephen Warren char get_escape_char(const char *s, int *i);
89cd296721SStephen Warren 
90cd296721SStephen Warren /**
91cd296721SStephen Warren  * Read a device tree file into a buffer. This will report any errors on
92cd296721SStephen Warren  * stderr.
93cd296721SStephen Warren  *
94cd296721SStephen Warren  * @param filename	The filename to read, or - for stdin
95f858927fSRob Herring  * @param len		If non-NULL, the amount of data we managed to read
96cd296721SStephen Warren  * @return Pointer to allocated buffer containing fdt, or NULL on error
97cd296721SStephen Warren  */
98f858927fSRob Herring char *utilfdt_read(const char *filename, size_t *len);
9973ab39b1SGrant Likely 
10073ab39b1SGrant Likely /**
101cd296721SStephen Warren  * Read a device tree file into a buffer. Does not report errors, but only
102cd296721SStephen Warren  * returns them. The value returned can be passed to strerror() to obtain
103cd296721SStephen Warren  * an error message for the user.
104cd296721SStephen Warren  *
105cd296721SStephen Warren  * @param filename	The filename to read, or - for stdin
106cd296721SStephen Warren  * @param buffp		Returns pointer to buffer containing fdt
107f858927fSRob Herring  * @param len		If non-NULL, the amount of data we managed to read
108cd296721SStephen Warren  * @return 0 if ok, else an errno value representing the error
109cd296721SStephen Warren  */
110f858927fSRob Herring int utilfdt_read_err(const char *filename, char **buffp, size_t *len);
111cd296721SStephen Warren 
112cd296721SStephen Warren /**
113cd296721SStephen Warren  * Write a device tree buffer to a file. This will report any errors on
114cd296721SStephen Warren  * stderr.
115cd296721SStephen Warren  *
116cd296721SStephen Warren  * @param filename	The filename to write, or - for stdout
1179bb9c6a1SRob Herring  * @param blob		Pointer to buffer containing fdt
118cd296721SStephen Warren  * @return 0 if ok, -1 on error
119cd296721SStephen Warren  */
120cd296721SStephen Warren int utilfdt_write(const char *filename, const void *blob);
121cd296721SStephen Warren 
122cd296721SStephen Warren /**
123cd296721SStephen Warren  * Write a device tree buffer to a file. Does not report errors, but only
124cd296721SStephen Warren  * returns them. The value returned can be passed to strerror() to obtain
125cd296721SStephen Warren  * an error message for the user.
126cd296721SStephen Warren  *
127cd296721SStephen Warren  * @param filename	The filename to write, or - for stdout
1289bb9c6a1SRob Herring  * @param blob		Pointer to buffer containing fdt
129cd296721SStephen Warren  * @return 0 if ok, else an errno value representing the error
130cd296721SStephen Warren  */
131cd296721SStephen Warren int utilfdt_write_err(const char *filename, const void *blob);
132cd296721SStephen Warren 
133cd296721SStephen Warren /**
134cd296721SStephen Warren  * Decode a data type string. The purpose of this string
135cd296721SStephen Warren  *
136cd296721SStephen Warren  * The string consists of an optional character followed by the type:
137cd296721SStephen Warren  *	Modifier characters:
138cd296721SStephen Warren  *		hh or b	1 byte
139cd296721SStephen Warren  *		h	2 byte
140cd296721SStephen Warren  *		l	4 byte, default
141cd296721SStephen Warren  *
142cd296721SStephen Warren  *	Type character:
143cd296721SStephen Warren  *		s	string
144cd296721SStephen Warren  *		i	signed integer
145cd296721SStephen Warren  *		u	unsigned integer
146cd296721SStephen Warren  *		x	hex
147*ea3723a5SRob Herring  *		r	raw
148cd296721SStephen Warren  *
149cd296721SStephen Warren  * TODO: Implement ll modifier (8 bytes)
150cd296721SStephen Warren  * TODO: Implement o type (octal)
151cd296721SStephen Warren  *
152cd296721SStephen Warren  * @param fmt		Format string to process
153cd296721SStephen Warren  * @param type		Returns type found(s/d/u/x), or 0 if none
154cd296721SStephen Warren  * @param size		Returns size found(1,2,4,8) or 4 if none
155cd296721SStephen Warren  * @return 0 if ok, -1 on error (no type given, or other invalid format)
156cd296721SStephen Warren  */
157cd296721SStephen Warren int utilfdt_decode_type(const char *fmt, int *type, int *size);
158cd296721SStephen Warren 
159cd296721SStephen Warren /*
160cd296721SStephen Warren  * This is a usage message fragment for the -t option. It is the format
161cd296721SStephen Warren  * supported by utilfdt_decode_type.
162cd296721SStephen Warren  */
163cd296721SStephen Warren 
164cd296721SStephen Warren #define USAGE_TYPE_MSG \
165*ea3723a5SRob Herring 	"<type>\ts=string, i=int, u=unsigned, x=hex, r=raw\n" \
166cd296721SStephen Warren 	"\tOptional modifier prefix:\n" \
16773ab39b1SGrant Likely 	"\t\thh or b=byte, h=2 byte, l=4 byte (default)";
16873ab39b1SGrant Likely 
16973ab39b1SGrant Likely /**
17073ab39b1SGrant Likely  * Print property data in a readable format to stdout
17173ab39b1SGrant Likely  *
17273ab39b1SGrant Likely  * Properties that look like strings will be printed as strings. Otherwise
17373ab39b1SGrant Likely  * the data will be displayed either as cells (if len is a multiple of 4
17473ab39b1SGrant Likely  * bytes) or bytes.
17573ab39b1SGrant Likely  *
17673ab39b1SGrant Likely  * If len is 0 then this function does nothing.
17773ab39b1SGrant Likely  *
17873ab39b1SGrant Likely  * @param data	Pointers to property data
17973ab39b1SGrant Likely  * @param len	Length of property data
18073ab39b1SGrant Likely  */
18173ab39b1SGrant Likely void utilfdt_print_data(const char *data, int len);
18273ab39b1SGrant Likely 
18373ab39b1SGrant Likely /**
18473ab39b1SGrant Likely  * Show source version and exit
18573ab39b1SGrant Likely  */
18689d12310SRob Herring void NORETURN util_version(void);
18773ab39b1SGrant Likely 
18873ab39b1SGrant Likely /**
18973ab39b1SGrant Likely  * Show usage and exit
19073ab39b1SGrant Likely  *
19173ab39b1SGrant Likely  * This helps standardize the output of various utils.  You most likely want
19273ab39b1SGrant Likely  * to use the usage() helper below rather than call this.
19373ab39b1SGrant Likely  *
19473ab39b1SGrant Likely  * @param errmsg	If non-NULL, an error message to display
19573ab39b1SGrant Likely  * @param synopsis	The initial example usage text (and possible examples)
19673ab39b1SGrant Likely  * @param short_opts	The string of short options
19773ab39b1SGrant Likely  * @param long_opts	The structure of long options
19873ab39b1SGrant Likely  * @param opts_help	An array of help strings (should align with long_opts)
19973ab39b1SGrant Likely  */
20089d12310SRob Herring void NORETURN util_usage(const char *errmsg, const char *synopsis,
20189d12310SRob Herring 			 const char *short_opts,
20289d12310SRob Herring 			 struct option const long_opts[],
20389d12310SRob Herring 			 const char * const opts_help[]);
20473ab39b1SGrant Likely 
20573ab39b1SGrant Likely /**
20673ab39b1SGrant Likely  * Show usage and exit
20773ab39b1SGrant Likely  *
20873ab39b1SGrant Likely  * If you name all your usage variables with usage_xxx, then you can call this
20973ab39b1SGrant Likely  * help macro rather than expanding all arguments yourself.
21073ab39b1SGrant Likely  *
21173ab39b1SGrant Likely  * @param errmsg	If non-NULL, an error message to display
21273ab39b1SGrant Likely  */
21373ab39b1SGrant Likely #define usage(errmsg) \
21473ab39b1SGrant Likely 	util_usage(errmsg, usage_synopsis, usage_short_opts, \
21573ab39b1SGrant Likely 		   usage_long_opts, usage_opts_help)
21673ab39b1SGrant Likely 
21773ab39b1SGrant Likely /**
21873ab39b1SGrant Likely  * Call getopt_long() with standard options
21973ab39b1SGrant Likely  *
22073ab39b1SGrant Likely  * Since all util code runs getopt in the same way, provide a helper.
22173ab39b1SGrant Likely  */
22273ab39b1SGrant Likely #define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
22373ab39b1SGrant Likely 				       usage_long_opts, NULL)
22473ab39b1SGrant Likely 
22573ab39b1SGrant Likely /* Helper for aligning long_opts array */
22673ab39b1SGrant Likely #define a_argument required_argument
22773ab39b1SGrant Likely 
22873ab39b1SGrant Likely /* Helper for usage_short_opts string constant */
22973ab39b1SGrant Likely #define USAGE_COMMON_SHORT_OPTS "hV"
23073ab39b1SGrant Likely 
23173ab39b1SGrant Likely /* Helper for usage_long_opts option array */
23273ab39b1SGrant Likely #define USAGE_COMMON_LONG_OPTS \
23373ab39b1SGrant Likely 	{"help",      no_argument, NULL, 'h'}, \
23473ab39b1SGrant Likely 	{"version",   no_argument, NULL, 'V'}, \
23573ab39b1SGrant Likely 	{NULL,        no_argument, NULL, 0x0}
23673ab39b1SGrant Likely 
23773ab39b1SGrant Likely /* Helper for usage_opts_help array */
23873ab39b1SGrant Likely #define USAGE_COMMON_OPTS_HELP \
23973ab39b1SGrant Likely 	"Print this help and exit", \
24073ab39b1SGrant Likely 	"Print version and exit", \
24173ab39b1SGrant Likely 	NULL
24273ab39b1SGrant Likely 
24373ab39b1SGrant Likely /* Helper for getopt case statements */
24473ab39b1SGrant Likely #define case_USAGE_COMMON_FLAGS \
24573ab39b1SGrant Likely 	case 'h': usage(NULL); \
24673ab39b1SGrant Likely 	case 'V': util_version(); \
24773ab39b1SGrant Likely 	case '?': usage("unknown option");
248cd296721SStephen Warren 
2499130ba88SRob Herring #endif /* UTIL_H */
250