+ -D_GNU_SOURCE
*efivar_cpp_options:
- -Werror -Wall -std=gnu11 -Wextra
+ -Werror -Wall -std=gnu11 -Wextra -Wno-nonnull-compare
*cpp_options:
+ %(efivar_cpp_options)
LIBEFIBOOT_SOURCES = crc32.c creator.c disk.c gpt.c linux.c loadopt.c
LIBEFIBOOT_OBJECTS = $(patsubst %.c,%.o,$(LIBEFIBOOT_SOURCES))
LIBEFIVAR_SOURCES = dp.c dp-acpi.c dp-hw.c dp-media.c dp-message.c \
- efivarfs.c export.c guid.c guids.S guid-symbols.c \
+ efivarfs.c error.c export.c guid.c guids.S guid-symbols.c \
lib.c vars.c
LIBEFIVAR_OBJECTS = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(LIBEFIVAR_SOURCES)))
EFIVAR_SOURCES = efivar.c
--- /dev/null
+/*
+ * libefiboot - library for the manipulation of EFI boot variables
+ * Copyright 2012-2015 Red Hat, Inc.
+ * Copyright (C) 2000-2001 Dell Computer Corporation <Matt_Domsch@dell.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+typedef struct {
+ int error;
+ char *filename;
+ char *function;
+ int line;
+ char *message;
+} error_table_entry;
+
+static error_table_entry *error_table;
+static unsigned int current;
+
+int
+__attribute__((__visibility__ ("default")))
+__attribute__((__nonnull__ (2, 3, 4, 5, 6)))
+efi_error_get(unsigned int n,
+ char ** const filename,
+ char ** const function,
+ int *line,
+ char ** const message,
+ int *error
+ )
+{
+ if (!filename || !function || !line || !message || !error) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (n >= current)
+ return 0;
+
+ *filename = error_table[n].filename;
+ *function = error_table[n].function;
+ *line = error_table[n].line;
+ *message = error_table[n].message;
+ *error = error_table[n].error;
+
+ return 1;
+}
+
+int
+__attribute__((__visibility__ ("default")))
+__attribute__((__nonnull__ (1, 2, 5)))
+__attribute__((__format__ (printf, 5, 6)))
+efi_error_set(const char *filename,
+ const char *function,
+ int line,
+ int error,
+ const char *fmt, ...)
+{
+ error_table_entry et = { 0, };
+ error_table_entry *table;
+ char *tmp;
+
+ table = realloc(error_table, sizeof(et) * (current +1));
+ if (!table)
+ goto err;
+ error_table = table;
+
+ et.error = error;
+ et.line = line;
+ tmp = filename ? strdup(filename) : NULL;
+ if (!tmp)
+ goto err;
+ et.filename = tmp;
+
+ tmp = function ? strdup(function) : NULL;
+ if (!tmp)
+ goto err;
+ et.function = tmp;
+
+ if (fmt) {
+ int rc;
+ int saved_errno;
+ va_list ap;
+
+ tmp = NULL;
+ va_start(ap, fmt);
+ rc = vasprintf(&tmp, fmt, ap);
+ saved_errno = errno;
+ va_end(ap);
+ errno = saved_errno;
+ if (rc < 0)
+ goto err;
+ et.message = tmp;
+ }
+
+ memcpy(&error_table[current], &et, sizeof(et));
+ current += 1;
+ return current;
+err:
+ if (et.filename)
+ free(et.filename);
+ if (et.function)
+ free(et.function);
+ if (et.message)
+ free(et.message);
+ errno = ENOMEM;
+ return -1;
+}
+
+void
+__attribute__((__visibility__ ("default")))
+__attribute__((destructor))
+efi_error_clear(void)
+{
+ if (error_table) {
+ for (unsigned int i = 0; i < current; i++) {
+ error_table_entry *et = &error_table[i];
+
+ if (et->filename)
+ free(et->filename);
+ if (et->function)
+ free(et->function);
+ if (et->message)
+ free(et->message);
+
+ memset(et, '\0', sizeof(*et));
+ }
+ free(error_table);
+ }
+ error_table = NULL;
+ current = 0;
+}
extern int efi_variable_realize(efi_variable_t *var)
__attribute__((__nonnull__ (1)));
+#ifndef EFIVAR_BUILD_ENVIRONMENT
+extern int efi_error_get(unsigned int n,
+ char ** const filename,
+ char ** const function,
+ int *line,
+ char ** const message,
+ int *error)
+ __attribute__((__nonnull__ (2, 3, 4, 5, 6)));
+extern int efi_error_set(const char *filename,
+ const char *function,
+ int line,
+ int error,
+ const char *fmt, ...)
+ __attribute__((__visibility__ ("default")))
+ __attribute__((__nonnull__ (1, 2, 5)))
+ __attribute__((__format__ (printf, 5, 6)));
+extern void efi_error_clear(void);
+#else
+static inline int
+__attribute__((__nonnull__ (2, 3, 4, 5, 6)))
+efi_error_get(unsigned int n __attribute__((__unused__)),
+ char ** const filename __attribute__((__unused__)),
+ char ** const function __attribute__((__unused__)),
+ int *line __attribute__((__unused__)),
+ char ** const message __attribute__((__unused__)),
+ int *error __attribute__((__unused__)))
+{
+ return 0;
+}
+
+static inline int
+__attribute__((__nonnull__ (1, 2, 5)))
+__attribute__((__format__ (printf, 5, 6)))
+efi_error_set(const char *filename __attribute__((__unused__)),
+ const char *function __attribute__((__unused__)),
+ int line __attribute__((__unused__)),
+ int error __attribute__((__unused__)),
+ const char *fmt __attribute__((__unused__)),
+ ...)
+{
+ return 0;
+}
+
+static inline void
+efi_error_clear(void)
+{
+ return;
+}
+#endif
+
+#define efi_error_real__(errval, file, function, line, fmt, args...) \
+ efi_error_set(file, function, line, errval, (fmt), ## args)
+
+#define efi_error(fmt, args...) \
+ efi_error_real__(errno, __FILE__, __func__, __LINE__, (fmt), ## args)
+#define efi_error_val(errval, msg, args...) \
+ efi_error_real__(errval, __FILE__, __func__, __LINE__, (fmt), ## args)
+
#include <efivar-dp.h>
#endif /* EFIVAR_H */
} LIBEFIVAR_0.0;
LIBEFIVAR_@@VERSION@@ {
+ global: efi_error_set;
+ efi_error_get;
+ efi_error_clear;
};