2 * Copyright 2011-2014 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License as
7 * published by the Free Software Foundation; either version 2.1 of the
8 * License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see
17 * <http://www.gnu.org/licenses/>.
19 * Author(s): Peter Jones <pjones@redhat.com>
22 #define EFIVAR_UTIL_H 1
36 #include <sys/ioctl.h>
37 #include <sys/mount.h>
39 #include <sys/types.h>
43 #define UNUSED __attribute__((__unused__))
44 #define HIDDEN __attribute__((__visibility__ ("hidden")))
45 #define PUBLIC __attribute__((__visibility__ ("default")))
46 #define DESTRUCTOR __attribute__((destructor))
47 #define CONSTRUCTOR __attribute__((constructor))
48 #define ALIAS(x) __attribute__((weak, alias (#x)))
49 #define NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
50 #define PRINTF(...) __attribute__((__format__(printf, __VA_ARGS__)))
51 #define FLATTEN __attribute__((__flatten__))
52 #define PACKED __attribute__((__packed__))
53 #define VERSION(sym, ver) __asm__(".symver " # sym "," # ver)
55 #define __branch_check__(x, expect, is_constant) \
56 __builtin_expect(!!(x), expect)
58 #define likely(x) (__branch_check__(x, 1, __builtin_constant_p(x)))
61 #define unlikely(x) (__branch_check__(x, 0, __builtin_constant_p(x)))
65 * I'm not actually sure when these appear, but they're present in the
66 * version in front of me.
68 #if defined(__GNUC__) && defined(__GNUC_MINOR__)
69 #if __GNUC__ >= 5 && __GNUC_MINOR__ >= 1
70 #define int_add(a, b, c) __builtin_add_overflow(a, b, c)
71 #define long_add(a, b, c) __builtin_add_overflow(a, b, c)
72 #define long_mult(a, b, c) __builtin_mul_overflow(a, b, c)
73 #define ulong_add(a, b, c) __builtin_add_overflow(a, b, c)
74 #define ulong_mult(a, b, c) __builtin_mul_overflow(a, b, c)
78 #define int_add(a, b, c) ({ \
79 const int _limit = INT_MAX; \
81 _ret = _limit - ((unsigned long long)a) > \
82 ((unsigned long long)b); \
89 #define long_add(a, b, c) ({ \
90 const long _limit = LONG_MAX; \
92 _ret = _limit - ((unsigned long long)a) > \
93 ((unsigned long long)b); \
100 #define long_mult(a, b, c) ({ \
101 const long _limit = LONG_MAX; \
103 if ((a) == 0 || (b) == 0) \
106 _ret = _limit / (a) < (b); \
108 *(c) = ((a) * (b)); \
113 #define ulong_add(a, b, c) ({ \
114 const unsigned long _limit = ULONG_MAX; \
116 _ret = _limit - ((unsigned long long)a) > \
117 ((unsigned long long)b); \
119 *(c) = ((a) + (b)); \
124 #define ulong_mult(a, b, c) ({ \
125 const unsigned long _limit = ULONG_MAX; \
127 if ((a) == 0 || (b) == 0) \
130 _ret = _limit / (a) < (b); \
132 *(c) = ((a) * (b)); \
137 #if defined(__GNUC__) && defined(__GNUC_MINOR__)
138 #if __GNUC__ >= 5 && __GNUC_MINOR__ >= 1
139 #define add(a, b, c) _Generic((c), \
140 int *: int_add(a,b,c), \
141 long *: long_add(a,b,c), \
142 unsigned long *: ulong_add(a,b,c))
143 #define mult(a, b, c) _Generic((c), \
144 long *: long_mult(a,b,c), \
145 unsigned long *: ulong_mult(a,b,c))
150 #define add(a, b, c) ({ \
151 (*(c)) = ((a) + (b)); \
155 #define mult(a, b, c) ({ \
156 (*(c)) = ((a) * (b)); \
160 static inline int UNUSED
161 read_file(int fd, uint8_t **result, size_t *bufsize)
167 uint8_t *buf, *newbuf;
169 if (!(newbuf = calloc(size, sizeof (uint8_t)))) {
170 efi_error("could not allocate memory");
171 *result = buf = NULL;
179 /* size - filesize shouldn't exceed SSIZE_MAX because we're
180 * only allocating 4096 bytes at a time and we're checking that
181 * before doing so. */
182 s = read(fd, p, size - filesize);
183 if (s < 0 && errno == EAGAIN) {
185 * if we got EAGAIN, there's a good chance we've hit
186 * the kernel rate limiter. Doing more reads is just
187 * going to make it worse, so instead, give it a rest.
192 int saved_errno = errno;
194 *result = buf = NULL;
197 efi_error("could not read from file");
201 /* only exit for empty reads */
204 if (filesize >= size) {
205 /* See if we're going to overrun and return an error
207 if (size > (size_t)-1 - 4096) {
209 *result = buf = NULL;
212 efi_error("could not read from file");
215 newbuf = realloc(buf, size + 4096);
216 if (newbuf == NULL) {
217 int saved_errno = errno;
219 *result = buf = NULL;
222 efi_error("could not allocate memory");
226 memset(buf + size, '\0', 4096);
231 newbuf = realloc(buf, filesize+1);
234 *result = buf = NULL;
235 efi_error("could not allocate memory");
238 newbuf[filesize] = '\0';
240 *bufsize = filesize+1;
244 static inline uint64_t UNUSED
245 lcm(uint64_t x, uint64_t y)
247 uint64_t m = x, n = y, o;
248 while ((o = m % n)) {
256 #define strndupa(s, l) \
258 const char *__in = (s); \
259 size_t __len = strnlen (__in, (l)); \
260 char *__out = (char *) alloca (__len + 1); \
261 strncpy(__out, __in, __len); \
262 __out[__len] = '\0'; \
267 #define asprintfa(str, fmt, args...) \
272 _rc = asprintf((str), (fmt), ## args); \
274 _tmp = strdupa(*(str)); \
287 #define vasprintfa(str, fmt, ap) \
292 _rc = vasprintf((str), (fmt), (ap)); \
294 _tmp = strdupa(*(str)); \
307 static inline ssize_t
308 get_file(uint8_t **result, const char * const fmt, ...)
318 if (result == NULL) {
319 efi_error("invalid parameter 'result'");
324 rc = vasprintfa(&path, fmt, ap);
327 efi_error("could not allocate memory");
331 fd = open(path, O_RDONLY);
333 efi_error("could not open file \"%s\" for reading",
338 rc = read_file(fd, &buf, &bufsize);
343 if (rc < 0 || bufsize < 1) {
345 * I don't think this can happen, but I can't convince
351 efi_error("could not read file \"%s\"", path);
359 static inline void UNUSED
360 swizzle_guid_to_uuid(efi_guid_t *guid)
365 u32 = (uint32_t *)guid;
366 u32[0] = __builtin_bswap32(u32[0]);
367 u16 = (uint16_t *)&u32[1];
368 u16[0] = __builtin_bswap16(u16[0]);
369 u16[1] = __builtin_bswap16(u16[1]);
372 #define log_(file, line, func, level, fmt, args...) \
374 if (efi_get_verbose() >= level) { \
375 FILE *logfile_ = efi_get_logfile(); \
376 int len_ = strlen(fmt); \
377 fprintf(logfile_, "%s:%d %s(): ", \
379 fprintf(logfile_, fmt, ## args); \
380 if (!len_ || fmt[len_ - 1] != '\n') \
381 fprintf(logfile_, "\n"); \
385 #define LOG_VERBOSE 0
390 #define log(level, fmt, args...) log_(__FILE__, __LINE__, __func__, level, fmt, ## args)
391 #define arrow(l,b,o,p,n,m) ({if(n==m){char c_=b[p+1]; b[o]='^'; b[p+o]='^';b[p+o+1]='\0';log(l,"%s",b);b[o]=' ';b[p+o]=' ';b[p+o+1]=c_;}})
392 #define debug(fmt, args...) log(LOG_DEBUG, fmt, ## args)
394 #endif /* EFIVAR_UTIL_H */