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__
16*12d638f4SRob Herring (Arm) #ifdef __MINGW_PRINTF_FORMAT
17*12d638f4SRob Herring (Arm) #define PRINTF(i, j) __attribute__((format (__MINGW_PRINTF_FORMAT, i, j)))
18*12d638f4SRob Herring (Arm) #elif __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
190cec114eSRob Herring #define PRINTF(i, j) __attribute__((format (gnu_printf, i, j)))
20a77725a9SRob Herring #else
21a77725a9SRob Herring #define PRINTF(i, j) __attribute__((format (printf, i, j)))
220cec114eSRob Herring #endif
2389d12310SRob Herring #define NORETURN __attribute__((noreturn))
2489d12310SRob Herring #else
2589d12310SRob Herring #define PRINTF(i, j)
2689d12310SRob Herring #define NORETURN
2789d12310SRob Herring #endif
2889d12310SRob Herring
2973ab39b1SGrant Likely #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
3073ab39b1SGrant Likely
319130ba88SRob Herring #define stringify(s) stringify_(s)
329130ba88SRob Herring #define stringify_(s) #s
339130ba88SRob Herring
die(const char * str,...)3489d12310SRob Herring static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
35658f29a5SJohn Bonesio {
36658f29a5SJohn Bonesio va_list ap;
37658f29a5SJohn Bonesio
38658f29a5SJohn Bonesio va_start(ap, str);
39658f29a5SJohn Bonesio fprintf(stderr, "FATAL ERROR: ");
40658f29a5SJohn Bonesio vfprintf(stderr, str, ap);
4147605971SRob Herring va_end(ap);
42658f29a5SJohn Bonesio exit(1);
43658f29a5SJohn Bonesio }
44658f29a5SJohn Bonesio
xmalloc(size_t len)45658f29a5SJohn Bonesio static inline void *xmalloc(size_t len)
46658f29a5SJohn Bonesio {
47658f29a5SJohn Bonesio void *new = malloc(len);
48658f29a5SJohn Bonesio
49658f29a5SJohn Bonesio if (!new)
50658f29a5SJohn Bonesio die("malloc() failed\n");
51658f29a5SJohn Bonesio
52658f29a5SJohn Bonesio return new;
53658f29a5SJohn Bonesio }
54658f29a5SJohn Bonesio
xrealloc(void * p,size_t len)55658f29a5SJohn Bonesio static inline void *xrealloc(void *p, size_t len)
56658f29a5SJohn Bonesio {
57658f29a5SJohn Bonesio void *new = realloc(p, len);
58658f29a5SJohn Bonesio
59658f29a5SJohn Bonesio if (!new)
6089d12310SRob Herring die("realloc() failed (len=%zd)\n", len);
61658f29a5SJohn Bonesio
62658f29a5SJohn Bonesio return new;
63658f29a5SJohn Bonesio }
64658f29a5SJohn Bonesio
65658f29a5SJohn Bonesio extern char *xstrdup(const char *s);
66ea3723a5SRob Herring extern char *xstrndup(const char *s, size_t len);
6789d12310SRob Herring
6889d12310SRob Herring extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
69c2e7075cSRob Herring extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...);
70*12d638f4SRob Herring (Arm) extern int PRINTF(2, 0) xavsprintf_append(char **strp, const char *fmt, va_list ap);
71658f29a5SJohn Bonesio extern char *join_path(const char *path, const char *name);
72658f29a5SJohn Bonesio
73cd296721SStephen Warren /**
7473ab39b1SGrant Likely * Check a property of a given length to see if it is all printable and
7573ab39b1SGrant Likely * has a valid terminator. The property can contain either a single string,
7673ab39b1SGrant Likely * or multiple strings each of non-zero length.
77cd296721SStephen Warren *
78cd296721SStephen Warren * @param data The string to check
79cd296721SStephen Warren * @param len The string length including terminator
8073ab39b1SGrant Likely * @return 1 if a valid printable string, 0 if not
8173ab39b1SGrant Likely */
8247605971SRob Herring bool util_is_printable_string(const void *data, int len);
83cd296721SStephen Warren
84cd296721SStephen Warren /*
85cd296721SStephen Warren * Parse an escaped character starting at index i in string s. The resulting
86cd296721SStephen Warren * character will be returned and the index i will be updated to point at the
87cd296721SStephen Warren * character directly after the end of the encoding, this may be the '\0'
88cd296721SStephen Warren * terminator of the string.
89cd296721SStephen Warren */
90cd296721SStephen Warren char get_escape_char(const char *s, int *i);
91cd296721SStephen Warren
92cd296721SStephen Warren /**
93cd296721SStephen Warren * Read a device tree file into a buffer. This will report any errors on
94cd296721SStephen Warren * stderr.
95cd296721SStephen Warren *
96cd296721SStephen Warren * @param filename The filename to read, or - for stdin
97f858927fSRob Herring * @param len If non-NULL, the amount of data we managed to read
98cd296721SStephen Warren * @return Pointer to allocated buffer containing fdt, or NULL on error
99cd296721SStephen Warren */
100f858927fSRob Herring char *utilfdt_read(const char *filename, size_t *len);
10173ab39b1SGrant Likely
10273ab39b1SGrant Likely /**
103cd296721SStephen Warren * Read a device tree file into a buffer. Does not report errors, but only
104cd296721SStephen Warren * returns them. The value returned can be passed to strerror() to obtain
105cd296721SStephen Warren * an error message for the user.
106cd296721SStephen Warren *
107cd296721SStephen Warren * @param filename The filename to read, or - for stdin
108cd296721SStephen Warren * @param buffp Returns pointer to buffer containing fdt
109f858927fSRob Herring * @param len If non-NULL, the amount of data we managed to read
110cd296721SStephen Warren * @return 0 if ok, else an errno value representing the error
111cd296721SStephen Warren */
112f858927fSRob Herring int utilfdt_read_err(const char *filename, char **buffp, size_t *len);
113cd296721SStephen Warren
114cd296721SStephen Warren /**
115cd296721SStephen Warren * Write a device tree buffer to a file. This will report any errors on
116cd296721SStephen Warren * stderr.
117cd296721SStephen Warren *
118cd296721SStephen Warren * @param filename The filename to write, or - for stdout
1199bb9c6a1SRob Herring * @param blob Pointer to buffer containing fdt
120cd296721SStephen Warren * @return 0 if ok, -1 on error
121cd296721SStephen Warren */
122cd296721SStephen Warren int utilfdt_write(const char *filename, const void *blob);
123cd296721SStephen Warren
124cd296721SStephen Warren /**
125cd296721SStephen Warren * Write a device tree buffer to a file. Does not report errors, but only
126cd296721SStephen Warren * returns them. The value returned can be passed to strerror() to obtain
127cd296721SStephen Warren * an error message for the user.
128cd296721SStephen Warren *
129cd296721SStephen Warren * @param filename The filename to write, or - for stdout
1309bb9c6a1SRob Herring * @param blob Pointer to buffer containing fdt
131cd296721SStephen Warren * @return 0 if ok, else an errno value representing the error
132cd296721SStephen Warren */
133cd296721SStephen Warren int utilfdt_write_err(const char *filename, const void *blob);
134cd296721SStephen Warren
135cd296721SStephen Warren /**
136cd296721SStephen Warren * Decode a data type string. The purpose of this string
137cd296721SStephen Warren *
138cd296721SStephen Warren * The string consists of an optional character followed by the type:
139cd296721SStephen Warren * Modifier characters:
140cd296721SStephen Warren * hh or b 1 byte
141cd296721SStephen Warren * h 2 byte
142cd296721SStephen Warren * l 4 byte, default
143cd296721SStephen Warren *
144cd296721SStephen Warren * Type character:
145cd296721SStephen Warren * s string
146cd296721SStephen Warren * i signed integer
147cd296721SStephen Warren * u unsigned integer
148cd296721SStephen Warren * x hex
149ea3723a5SRob Herring * r raw
150cd296721SStephen Warren *
151cd296721SStephen Warren * TODO: Implement ll modifier (8 bytes)
152cd296721SStephen Warren * TODO: Implement o type (octal)
153cd296721SStephen Warren *
154cd296721SStephen Warren * @param fmt Format string to process
155cd296721SStephen Warren * @param type Returns type found(s/d/u/x), or 0 if none
156cd296721SStephen Warren * @param size Returns size found(1,2,4,8) or 4 if none
157cd296721SStephen Warren * @return 0 if ok, -1 on error (no type given, or other invalid format)
158cd296721SStephen Warren */
159cd296721SStephen Warren int utilfdt_decode_type(const char *fmt, int *type, int *size);
160cd296721SStephen Warren
161cd296721SStephen Warren /*
162cd296721SStephen Warren * This is a usage message fragment for the -t option. It is the format
163cd296721SStephen Warren * supported by utilfdt_decode_type.
164cd296721SStephen Warren */
165cd296721SStephen Warren
166cd296721SStephen Warren #define USAGE_TYPE_MSG \
167ea3723a5SRob Herring "<type>\ts=string, i=int, u=unsigned, x=hex, r=raw\n" \
168cd296721SStephen Warren "\tOptional modifier prefix:\n" \
16973ab39b1SGrant Likely "\t\thh or b=byte, h=2 byte, l=4 byte (default)";
17073ab39b1SGrant Likely
17173ab39b1SGrant Likely /**
17273ab39b1SGrant Likely * Print property data in a readable format to stdout
17373ab39b1SGrant Likely *
17473ab39b1SGrant Likely * Properties that look like strings will be printed as strings. Otherwise
17573ab39b1SGrant Likely * the data will be displayed either as cells (if len is a multiple of 4
17673ab39b1SGrant Likely * bytes) or bytes.
17773ab39b1SGrant Likely *
17873ab39b1SGrant Likely * If len is 0 then this function does nothing.
17973ab39b1SGrant Likely *
18073ab39b1SGrant Likely * @param data Pointers to property data
18173ab39b1SGrant Likely * @param len Length of property data
18273ab39b1SGrant Likely */
18373ab39b1SGrant Likely void utilfdt_print_data(const char *data, int len);
18473ab39b1SGrant Likely
18573ab39b1SGrant Likely /**
18673ab39b1SGrant Likely * Show source version and exit
18773ab39b1SGrant Likely */
18889d12310SRob Herring void NORETURN util_version(void);
18973ab39b1SGrant Likely
19073ab39b1SGrant Likely /**
19173ab39b1SGrant Likely * Show usage and exit
19273ab39b1SGrant Likely *
19373ab39b1SGrant Likely * This helps standardize the output of various utils. You most likely want
19473ab39b1SGrant Likely * to use the usage() helper below rather than call this.
19573ab39b1SGrant Likely *
19673ab39b1SGrant Likely * @param errmsg If non-NULL, an error message to display
19773ab39b1SGrant Likely * @param synopsis The initial example usage text (and possible examples)
19873ab39b1SGrant Likely * @param short_opts The string of short options
19973ab39b1SGrant Likely * @param long_opts The structure of long options
20073ab39b1SGrant Likely * @param opts_help An array of help strings (should align with long_opts)
20173ab39b1SGrant Likely */
20289d12310SRob Herring void NORETURN util_usage(const char *errmsg, const char *synopsis,
20389d12310SRob Herring const char *short_opts,
20489d12310SRob Herring struct option const long_opts[],
20589d12310SRob Herring const char * const opts_help[]);
20673ab39b1SGrant Likely
20773ab39b1SGrant Likely /**
20873ab39b1SGrant Likely * Show usage and exit
20973ab39b1SGrant Likely *
21073ab39b1SGrant Likely * If you name all your usage variables with usage_xxx, then you can call this
21173ab39b1SGrant Likely * help macro rather than expanding all arguments yourself.
21273ab39b1SGrant Likely *
21373ab39b1SGrant Likely * @param errmsg If non-NULL, an error message to display
21473ab39b1SGrant Likely */
21573ab39b1SGrant Likely #define usage(errmsg) \
21673ab39b1SGrant Likely util_usage(errmsg, usage_synopsis, usage_short_opts, \
21773ab39b1SGrant Likely usage_long_opts, usage_opts_help)
21873ab39b1SGrant Likely
21973ab39b1SGrant Likely /**
22073ab39b1SGrant Likely * Call getopt_long() with standard options
22173ab39b1SGrant Likely *
22273ab39b1SGrant Likely * Since all util code runs getopt in the same way, provide a helper.
22373ab39b1SGrant Likely */
22473ab39b1SGrant Likely #define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
22573ab39b1SGrant Likely usage_long_opts, NULL)
22673ab39b1SGrant Likely
22773ab39b1SGrant Likely /* Helper for aligning long_opts array */
22873ab39b1SGrant Likely #define a_argument required_argument
22973ab39b1SGrant Likely
23073ab39b1SGrant Likely /* Helper for usage_short_opts string constant */
23173ab39b1SGrant Likely #define USAGE_COMMON_SHORT_OPTS "hV"
23273ab39b1SGrant Likely
23373ab39b1SGrant Likely /* Helper for usage_long_opts option array */
23473ab39b1SGrant Likely #define USAGE_COMMON_LONG_OPTS \
23573ab39b1SGrant Likely {"help", no_argument, NULL, 'h'}, \
23673ab39b1SGrant Likely {"version", no_argument, NULL, 'V'}, \
23773ab39b1SGrant Likely {NULL, no_argument, NULL, 0x0}
23873ab39b1SGrant Likely
23973ab39b1SGrant Likely /* Helper for usage_opts_help array */
24073ab39b1SGrant Likely #define USAGE_COMMON_OPTS_HELP \
24173ab39b1SGrant Likely "Print this help and exit", \
24273ab39b1SGrant Likely "Print version and exit", \
24373ab39b1SGrant Likely NULL
24473ab39b1SGrant Likely
24573ab39b1SGrant Likely /* Helper for getopt case statements */
24673ab39b1SGrant Likely #define case_USAGE_COMMON_FLAGS \
24773ab39b1SGrant Likely case 'h': usage(NULL); \
24873ab39b1SGrant Likely case 'V': util_version(); \
24973ab39b1SGrant Likely case '?': usage("unknown option");
250cd296721SStephen Warren
2519130ba88SRob Herring #endif /* UTIL_H */
252