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