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