1
0
mirror of https://github.com/systemd/systemd synced 2026-03-25 16:25:04 +01:00

Compare commits

..

No commits in common. "8908ceb7a855eabf5739dc15932ee1d41a0bc93c" and "ced10d48380369c5a3b43037bc00e54ac7fe27b5" have entirely different histories.

46 changed files with 418 additions and 870 deletions

View File

@ -41,8 +41,8 @@
a comment line. Empty and comment lines are ignored.</para> a comment line. Empty and comment lines are ignored.</para>
<para>Boolean arguments may be written as <para>Boolean arguments may be written as
<literal>yes</literal>/<literal>y</literal>/<literal>true</literal>/<literal>t</literal>/<literal>on</literal>/<literal>1</literal> or <literal>yes</literal>/<literal>y</literal>/<literal>true</literal>/<literal>1</literal> or
<literal>no</literal>/<literal>n</literal>/<literal>false</literal>/<literal>f</literal>/<literal>off</literal>/<literal>0</literal>. <literal>no</literal>/<literal>n</literal>/<literal>false</literal>/<literal>0</literal>.
</para> </para>
</refsect1> </refsect1>

View File

@ -744,18 +744,6 @@ Service b@0.service not loaded, b.socket cannot be started.
generators enabled will generally result in some warnings.</para></listitem> generators enabled will generally result in some warnings.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--recursive-errors=<replaceable>MODE</replaceable></option></term>
<listitem><para>Control verification of units and their dependencies and whether
<command>systemd-analyze verify</command> exits with a non-zero process exit status or not. With
<command>yes</command>, return a non-zero process exit status when warnings arise during verification
of either the specified unit or any of its associated dependencies. This is the default. With
<command>no</command>, return a non-zero process exit status when warnings arise during verification
of only the specified unit. With <command>one</command>, return a non-zero process exit status when
warnings arise during verification of either the specified unit or its immediate dependencies. </para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--root=<replaceable>PATH</replaceable></option></term> <term><option>--root=<replaceable>PATH</replaceable></option></term>

View File

@ -345,7 +345,6 @@ possible_common_cc_flags = [
'-Werror=shift-count-overflow', '-Werror=shift-count-overflow',
'-Werror=shift-overflow=2', '-Werror=shift-overflow=2',
'-Werror=undef', '-Werror=undef',
'-Werror=unused-function',
'-Wfloat-equal', '-Wfloat-equal',
'-Wimplicit-fallthrough=5', '-Wimplicit-fallthrough=5',
'-Winit-self', '-Winit-self',

View File

@ -125,7 +125,7 @@ _systemd_analyze() {
elif __contains_word "$verb" ${VERBS[VERIFY]}; then elif __contains_word "$verb" ${VERBS[VERIFY]}; then
if [[ $cur = -* ]]; then if [[ $cur = -* ]]; then
comps='--help --version --system --user --global --man=no --generators=yes --root --image --recursive-errors=no --recursive-errors=yes --recursive-errors=one' comps='--help --version --system --user --global --man=no --generators=yes --root --image'
else else
comps=$( compgen -A file -- "$cur" ) comps=$( compgen -A file -- "$cur" )
compopt -o filenames compopt -o filenames

View File

@ -89,7 +89,6 @@ _arguments \
'--global[Show global user instance config]' \ '--global[Show global user instance config]' \
'--root=[Add support for root argument]:PATH' \ '--root=[Add support for root argument]:PATH' \
'--image=[Add support for discrete images]:PATH' \ '--image=[Add support for discrete images]:PATH' \
'--recursive-errors=[When verifying a unit, control dependency verification]:MODE' \
'--no-pager[Do not pipe output into a pager]' \ '--no-pager[Do not pipe output into a pager]' \
'--man=[Do (not) check for existence of man pages]:boolean:(1 0)' \ '--man=[Do (not) check for existence of man pages]:boolean:(1 0)' \
'--order[When generating graph for dot, show only order]' \ '--order[When generating graph for dot, show only order]' \

View File

@ -11,28 +11,10 @@
#include "manager.h" #include "manager.h"
#include "pager.h" #include "pager.h"
#include "path-util.h" #include "path-util.h"
#include "string-table.h"
#include "strv.h" #include "strv.h"
#include "unit-name.h" #include "unit-name.h"
#include "unit-serialize.h" #include "unit-serialize.h"
static void log_syntax_callback(const char *unit, int level, void *userdata) {
Set **s = userdata;
int r;
assert(userdata);
assert(unit);
if (level > LOG_WARNING)
return;
r = set_put_strdup(s, unit);
if (r < 0) {
set_free_free(*s);
*s = POINTER_MAX;
}
}
static int prepare_filename(const char *filename, char **ret) { static int prepare_filename(const char *filename, char **ret) {
int r; int r;
const char *name; const char *name;
@ -236,22 +218,13 @@ static int verify_unit(Unit *u, bool check_man, const char *root) {
return r; return r;
} }
static void set_destroy_ignore_pointer_max(Set** s) { int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators, const char *root) {
if (*s == POINTER_MAX)
return;
set_free_free(*s);
}
int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators, RecursiveErrors recursive_errors, const char *root) {
const ManagerTestRunFlags flags = const ManagerTestRunFlags flags =
MANAGER_TEST_RUN_MINIMAL | MANAGER_TEST_RUN_MINIMAL |
MANAGER_TEST_RUN_ENV_GENERATORS | MANAGER_TEST_RUN_ENV_GENERATORS |
(recursive_errors == RECURSIVE_ERRORS_NO) * MANAGER_TEST_RUN_IGNORE_DEPENDENCIES |
run_generators * MANAGER_TEST_RUN_GENERATORS; run_generators * MANAGER_TEST_RUN_GENERATORS;
_cleanup_(manager_freep) Manager *m = NULL; _cleanup_(manager_freep) Manager *m = NULL;
_cleanup_(set_destroy_ignore_pointer_max) Set *s = NULL;
_unused_ _cleanup_(clear_log_syntax_callback) dummy_t dummy;
Unit *units[strv_length(filenames)]; Unit *units[strv_length(filenames)];
_cleanup_free_ char *var = NULL; _cleanup_free_ char *var = NULL;
int r, k, i, count = 0; int r, k, i, count = 0;
@ -260,11 +233,6 @@ int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run
if (strv_isempty(filenames)) if (strv_isempty(filenames))
return 0; return 0;
/* Allow systemd-analyze to hook in a callback function so that it can get
* all the required log data from the function itself without having to rely
* on a global set variable for the same */
set_log_syntax_callback(log_syntax_callback, &s);
/* set the path */ /* set the path */
r = generate_path(&var, filenames); r = generate_path(&var, filenames);
if (r < 0) if (r < 0)
@ -315,34 +283,5 @@ int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run
r = k; r = k;
} }
if (s == POINTER_MAX)
return log_oom();
if (set_isempty(s) || r != 0)
return r; return r;
/* If all previous verifications succeeded, then either the recursive parsing of all the
* associated dependencies with RECURSIVE_ERRORS_YES or the parsing of the specified unit file
* with RECURSIVE_ERRORS_NO must have yielded a syntax warning and hence, a non-empty set. */
if (IN_SET(recursive_errors, RECURSIVE_ERRORS_YES, RECURSIVE_ERRORS_NO))
return -ENOTRECOVERABLE;
/* If all previous verifications succeeded, then the non-empty set could have resulted from
* a syntax warning encountered during the recursive parsing of the specified unit file and
* its direct dependencies. Hence, search for any of the filenames in the set and if found,
* return a non-zero process exit status. */
if (recursive_errors == RECURSIVE_ERRORS_ONE)
STRV_FOREACH(filename, filenames)
if (set_contains(s, basename(*filename)))
return -ENOTRECOVERABLE;
return 0;
} }
static const char* const recursive_errors_table[_RECURSIVE_ERRORS_MAX] = {
[RECURSIVE_ERRORS_NO] = "no",
[RECURSIVE_ERRORS_YES] = "yes",
[RECURSIVE_ERRORS_ONE] = "one",
};
DEFINE_STRING_TABLE_LOOKUP(recursive_errors, RecursiveErrors);

View File

@ -6,16 +6,5 @@
#include "execute.h" #include "execute.h"
#include "path-lookup.h" #include "path-lookup.h"
typedef enum RecursiveErrors {
RECURSIVE_ERRORS_YES, /* Look for errors in all associated units */
RECURSIVE_ERRORS_NO, /* Don't look for errors in any but the selected unit */
RECURSIVE_ERRORS_ONE, /* Look for errors in the selected unit and its direct dependencies */
_RECURSIVE_ERRORS_MAX,
_RECURSIVE_ERRORS_INVALID = -EINVAL,
} RecursiveErrors;
int verify_executable(Unit *u, const ExecCommand *exec, const char *root); int verify_executable(Unit *u, const ExecCommand *exec, const char *root);
int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators, RecursiveErrors recursive_errors, const char *root); int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators, const char *root);
const char* recursive_errors_to_string(RecursiveErrors i) _const_;
RecursiveErrors recursive_errors_from_string(const char *s) _pure_;

View File

@ -46,7 +46,6 @@
#endif #endif
#include "sort-util.h" #include "sort-util.h"
#include "special.h" #include "special.h"
#include "string-table.h"
#include "strv.h" #include "strv.h"
#include "strxcpyx.h" #include "strxcpyx.h"
#include "terminal-util.h" #include "terminal-util.h"
@ -86,7 +85,6 @@ static PagerFlags arg_pager_flags = 0;
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
static const char *arg_host = NULL; static const char *arg_host = NULL;
static UnitFileScope arg_scope = UNIT_FILE_SYSTEM; static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
static RecursiveErrors arg_recursive_errors = RECURSIVE_ERRORS_YES;
static bool arg_man = true; static bool arg_man = true;
static bool arg_generators = false; static bool arg_generators = false;
static char *arg_root = NULL; static char *arg_root = NULL;
@ -2147,7 +2145,7 @@ static int do_condition(int argc, char *argv[], void *userdata) {
} }
static int do_verify(int argc, char *argv[], void *userdata) { static int do_verify(int argc, char *argv[], void *userdata) {
return verify_units(strv_skip(argv, 1), arg_scope, arg_man, arg_generators, arg_recursive_errors, arg_root); return verify_units(strv_skip(argv, 1), arg_scope, arg_man, arg_generators, arg_root);
} }
static int do_security(int argc, char *argv[], void *userdata) { static int do_security(int argc, char *argv[], void *userdata) {
@ -2182,32 +2180,25 @@ static int help(int argc, char *argv[], void *userdata) {
"%sProfile systemd, show unit dependencies, check unit files.%s\n" "%sProfile systemd, show unit dependencies, check unit files.%s\n"
"\nCommands:\n" "\nCommands:\n"
" [time] Print time required to boot the machine\n" " [time] Print time required to boot the machine\n"
" blame Print list of running units ordered by\n" " blame Print list of running units ordered by time to init\n"
" time to init\n" " critical-chain [UNIT...] Print a tree of the time critical chain of units\n"
" critical-chain [UNIT...] Print a tree of the time critical chain\n" " plot Output SVG graphic showing service initialization\n"
" of units\n"
" plot Output SVG graphic showing service\n"
" initialization\n"
" dot [UNIT...] Output dependency graph in %s format\n" " dot [UNIT...] Output dependency graph in %s format\n"
" dump Output state serialization of service\n" " dump Output state serialization of service manager\n"
" manager\n"
" cat-config Show configuration file and drop-ins\n" " cat-config Show configuration file and drop-ins\n"
" unit-files List files and symlinks for units\n" " unit-files List files and symlinks for units\n"
" unit-paths List load directories for units\n" " unit-paths List load directories for units\n"
" exit-status [STATUS...] List exit status definitions\n" " exit-status [STATUS...] List exit status definitions\n"
" capability [CAP...] List capability definitions\n" " capability [CAP...] List capability definitions\n"
" syscall-filter [NAME...] Print list of syscalls in seccomp\n" " syscall-filter [NAME...] Print list of syscalls in seccomp filter\n"
" filter\n"
" condition CONDITION... Evaluate conditions and asserts\n" " condition CONDITION... Evaluate conditions and asserts\n"
" verify FILE... Check unit files for correctness\n" " verify FILE... Check unit files for correctness\n"
" calendar SPEC... Validate repetitive calendar time\n" " calendar SPEC... Validate repetitive calendar time events\n"
" events\n"
" timestamp TIMESTAMP... Validate a timestamp\n" " timestamp TIMESTAMP... Validate a timestamp\n"
" timespan SPAN... Validate a time span\n" " timespan SPAN... Validate a time span\n"
" security [UNIT...] Analyze security of unit\n" " security [UNIT...] Analyze security of unit\n"
"\nOptions:\n" "\nOptions:\n"
" -h --help Show this help\n" " -h --help Show this help\n"
" --recursive-errors=MODE Control which units are verified\n"
" --version Show package version\n" " --version Show package version\n"
" --no-pager Do not pipe output into a pager\n" " --no-pager Do not pipe output into a pager\n"
" --system Operate on system systemd instance\n" " --system Operate on system systemd instance\n"
@ -2219,14 +2210,12 @@ static int help(int argc, char *argv[], void *userdata) {
" --require Show only requirement in the graph\n" " --require Show only requirement in the graph\n"
" --from-pattern=GLOB Show only origins in the graph\n" " --from-pattern=GLOB Show only origins in the graph\n"
" --to-pattern=GLOB Show only destinations in the graph\n" " --to-pattern=GLOB Show only destinations in the graph\n"
" --fuzz=SECONDS Also print services which finished SECONDS\n" " --fuzz=SECONDS Also print services which finished SECONDS earlier\n"
" earlier than the latest in the branch\n" " than the latest in the branch\n"
" --man[=BOOL] Do [not] check for existence of man pages\n" " --man[=BOOL] Do [not] check for existence of man pages\n"
" --generators[=BOOL] Do [not] run unit generators\n" " --generators[=BOOL] Do [not] run unit generators (requires privileges)\n"
" (requires privileges)\n"
" --iterations=N Show the specified number of iterations\n" " --iterations=N Show the specified number of iterations\n"
" --base-time=TIMESTAMP Calculate calendar times relative to\n" " --base-time=TIMESTAMP Calculate calendar times relative to specified time\n"
" specified time\n"
"\nSee the %s for details.\n", "\nSee the %s for details.\n",
program_invocation_short_name, program_invocation_short_name,
ansi_highlight(), ansi_highlight(),
@ -2258,7 +2247,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_GENERATORS, ARG_GENERATORS,
ARG_ITERATIONS, ARG_ITERATIONS,
ARG_BASE_TIME, ARG_BASE_TIME,
ARG_RECURSIVE_ERRORS,
}; };
static const struct option options[] = { static const struct option options[] = {
@ -2268,7 +2256,6 @@ static int parse_argv(int argc, char *argv[]) {
{ "require", no_argument, NULL, ARG_REQUIRE }, { "require", no_argument, NULL, ARG_REQUIRE },
{ "root", required_argument, NULL, ARG_ROOT }, { "root", required_argument, NULL, ARG_ROOT },
{ "image", required_argument, NULL, ARG_IMAGE }, { "image", required_argument, NULL, ARG_IMAGE },
{ "recursive-errors", required_argument, NULL, ARG_RECURSIVE_ERRORS },
{ "system", no_argument, NULL, ARG_SYSTEM }, { "system", no_argument, NULL, ARG_SYSTEM },
{ "user", no_argument, NULL, ARG_USER }, { "user", no_argument, NULL, ARG_USER },
{ "global", no_argument, NULL, ARG_GLOBAL }, { "global", no_argument, NULL, ARG_GLOBAL },
@ -2296,18 +2283,6 @@ static int parse_argv(int argc, char *argv[]) {
case 'h': case 'h':
return help(0, NULL, NULL); return help(0, NULL, NULL);
case ARG_RECURSIVE_ERRORS:
if (streq(optarg, "help")) {
DUMP_STRING_TABLE(recursive_errors, RecursiveErrors, _RECURSIVE_ERRORS_MAX);
return 0;
}
r = recursive_errors_from_string(optarg);
if (r < 0)
return log_error_errno(r, "Unknown mode passed to --recursive-errors='%s'.", optarg);
arg_recursive_errors = r;
break;
case ARG_VERSION: case ARG_VERSION:
return version(); return version();

View File

@ -39,9 +39,6 @@
#define SNDBUF_SIZE (8*1024*1024) #define SNDBUF_SIZE (8*1024*1024)
static log_syntax_callback_t log_syntax_callback = NULL;
static void *log_syntax_callback_userdata = NULL;
static LogTarget log_target = LOG_TARGET_CONSOLE; static LogTarget log_target = LOG_TARGET_CONSOLE;
static int log_max_level = LOG_INFO; static int log_max_level = LOG_INFO;
static int log_facility = LOG_DAEMON; static int log_facility = LOG_DAEMON;
@ -1344,14 +1341,6 @@ void log_received_signal(int level, const struct signalfd_siginfo *si) {
signal_to_string(si->ssi_signo)); signal_to_string(si->ssi_signo));
} }
void set_log_syntax_callback(log_syntax_callback_t cb, void *userdata) {
assert(!log_syntax_callback || !cb);
assert(!log_syntax_callback_userdata || !userdata);
log_syntax_callback = cb;
log_syntax_callback_userdata = userdata;
}
int log_syntax_internal( int log_syntax_internal(
const char *unit, const char *unit,
int level, int level,
@ -1363,9 +1352,6 @@ int log_syntax_internal(
const char *func, const char *func,
const char *format, ...) { const char *format, ...) {
if (log_syntax_callback)
log_syntax_callback(unit, level, log_syntax_callback_userdata);
PROTECT_ERRNO; PROTECT_ERRNO;
char buffer[LINE_MAX]; char buffer[LINE_MAX];
va_list ap; va_list ap;

View File

@ -32,15 +32,6 @@ typedef enum LogTarget{
#define IS_SYNTHETIC_ERRNO(val) ((val) >> 30 & 1) #define IS_SYNTHETIC_ERRNO(val) ((val) >> 30 & 1)
#define ERRNO_VALUE(val) (abs(val) & 255) #define ERRNO_VALUE(val) (abs(val) & 255)
/* The callback function to be invoked when syntax warnings are seen
* in the unit files. */
typedef void (*log_syntax_callback_t)(const char *unit, int level, void *userdata);
void set_log_syntax_callback(log_syntax_callback_t cb, void *userdata);
static inline void clear_log_syntax_callback(dummy_t *dummy) {
set_log_syntax_callback(/* cb= */ NULL, /* userdata= */ NULL);
}
const char *log_target_to_string(LogTarget target) _const_; const char *log_target_to_string(LogTarget target) _const_;
LogTarget log_target_from_string(const char *s) _pure_; LogTarget log_target_from_string(const char *s) _pure_;
void log_set_target(LogTarget target); void log_set_target(LogTarget target);

View File

@ -23,12 +23,28 @@
#define _packed_ __attribute__((__packed__)) #define _packed_ __attribute__((__packed__))
#define _malloc_ __attribute__((__malloc__)) #define _malloc_ __attribute__((__malloc__))
#define _weak_ __attribute__((__weak__)) #define _weak_ __attribute__((__weak__))
#define _likely_(x) (__builtin_expect(!!(x), 1))
#define _unlikely_(x) (__builtin_expect(!!(x), 0))
#define _public_ __attribute__((__visibility__("default"))) #define _public_ __attribute__((__visibility__("default")))
#define _hidden_ __attribute__((__visibility__("hidden"))) #define _hidden_ __attribute__((__visibility__("hidden")))
#define _weakref_(x) __attribute__((__weakref__(#x))) #define _weakref_(x) __attribute__((__weakref__(#x)))
#define _alignas_(x) __attribute__((__aligned__(__alignof(x)))) #define _alignas_(x) __attribute__((__aligned__(__alignof(x))))
#define _alignptr_ __attribute__((__aligned__(sizeof(void*)))) #define _alignptr_ __attribute__((__aligned__(sizeof(void*))))
#define _warn_unused_result_ __attribute__((__warn_unused_result__)) #define _warn_unused_result_ __attribute__((__warn_unused_result__))
#if __GNUC__ >= 7
#define _fallthrough_ __attribute__((__fallthrough__))
#else
#define _fallthrough_
#endif
/* Define C11 noreturn without <stdnoreturn.h> and even on older gcc
* compiler versions */
#ifndef _noreturn_
#if __STDC_VERSION__ >= 201112L
#define _noreturn_ _Noreturn
#else
#define _noreturn_ __attribute__((__noreturn__))
#endif
#endif
#if !defined(HAS_FEATURE_MEMORY_SANITIZER) #if !defined(HAS_FEATURE_MEMORY_SANITIZER)
# if defined(__has_feature) # if defined(__has_feature)
@ -193,6 +209,13 @@ static inline size_t GREEDY_ALLOC_ROUND_UP(size_t l) {
return m; return m;
} }
/*
* STRLEN - return the length of a string literal, minus the trailing NUL byte.
* Contrary to strlen(), this is a constant expression.
* @x: a string literal.
*/
#define STRLEN(x) (sizeof(""x"") - 1U)
/* /*
* container_of - cast a member of a structure out to the containing structure * container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member. * @ptr: the pointer to the member.
@ -460,10 +483,4 @@ static inline size_t size_add(size_t x, size_t y) {
return y >= SIZE_MAX - x ? SIZE_MAX : x + y; return y >= SIZE_MAX - x ? SIZE_MAX : x + y;
} }
typedef struct {
int _empty[0];
} dummy_t;
assert_cc(sizeof(dummy_t) == 0);
#include "log.h" #include "log.h"

View File

@ -1,15 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#ifndef NDEBUG
#include <efi.h>
#include <efilib.h>
#include "util.h"
void efi_assert(const char *expr, const char *file, unsigned line, const char *function) {
log_error_stall(L"systemd-boot assertion '%a' failed at %a:%u, function %a(). Halting.", expr, file, line, function);
for (;;)
uefi_call_wrapper(BS->Stall, 1, 60 * 1000 * 1000);
}
#endif

View File

@ -72,9 +72,6 @@ typedef struct {
} Config; } Config;
static VOID cursor_left(UINTN *cursor, UINTN *first) { static VOID cursor_left(UINTN *cursor, UINTN *first) {
assert(cursor);
assert(first);
if ((*cursor) > 0) if ((*cursor) > 0)
(*cursor)--; (*cursor)--;
else if ((*first) > 0) else if ((*first) > 0)
@ -87,9 +84,6 @@ static VOID cursor_right(
UINTN x_max, UINTN x_max,
UINTN len) { UINTN len) {
assert(cursor);
assert(first);
if ((*cursor)+1 < x_max) if ((*cursor)+1 < x_max)
(*cursor)++; (*cursor)++;
else if ((*first) + (*cursor) < len) else if ((*first) + (*cursor) < len)
@ -106,8 +100,6 @@ static BOOLEAN line_edit(
UINTN size, len, first, cursor, clear; UINTN size, len, first, cursor, clear;
BOOLEAN exit, enter; BOOLEAN exit, enter;
assert(line_out);
if (!line_in) if (!line_in)
line_in = L""; line_in = L"";
size = StrLen(line_in) + 1024; size = StrLen(line_in) + 1024;
@ -142,7 +134,7 @@ static BOOLEAN line_edit(
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, print); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, print);
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos);
err = console_key_read(&key, 0); err = console_key_read(&key, TRUE);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
continue; continue;
@ -340,8 +332,6 @@ static BOOLEAN line_edit(
} }
static UINTN entry_lookup_key(Config *config, UINTN start, CHAR16 key) { static UINTN entry_lookup_key(Config *config, UINTN start, CHAR16 key) {
assert(config);
if (key == 0) if (key == 0)
return -1; return -1;
@ -372,9 +362,6 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
_cleanup_freepool_ CHAR16 *partstr = NULL, *defaultstr = NULL; _cleanup_freepool_ CHAR16 *partstr = NULL, *defaultstr = NULL;
UINTN x, y; UINTN x, y;
assert(config);
assert(loaded_image_path);
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
@ -400,7 +387,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
Print(L"OsIndicationsSupported: %d\n", indvar); Print(L"OsIndicationsSupported: %d\n", indvar);
Print(L"\n--- press key ---\n\n"); Print(L"\n--- press key ---\n\n");
console_key_read(&key, 0); console_key_read(&key, TRUE);
Print(L"timeout: %u\n", config->timeout_sec); Print(L"timeout: %u\n", config->timeout_sec);
if (config->timeout_sec_efivar >= 0) if (config->timeout_sec_efivar >= 0)
@ -445,7 +432,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
Print(L"LoaderEntryDefault: %s\n", defaultstr); Print(L"LoaderEntryDefault: %s\n", defaultstr);
Print(L"\n--- press key ---\n\n"); Print(L"\n--- press key ---\n\n");
console_key_read(&key, 0); console_key_read(&key, TRUE);
for (UINTN i = 0; i < config->entry_count; i++) { for (UINTN i = 0; i < config->entry_count; i++) {
ConfigEntry *entry; ConfigEntry *entry;
@ -495,7 +482,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
entry->path, entry->next_name); entry->path, entry->next_name);
Print(L"\n--- press key ---\n\n"); Print(L"\n--- press key ---\n\n");
console_key_read(&key, 0); console_key_read(&key, TRUE);
} }
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
@ -506,10 +493,6 @@ static BOOLEAN menu_run(
ConfigEntry **chosen_entry, ConfigEntry **chosen_entry,
CHAR16 *loaded_image_path) { CHAR16 *loaded_image_path) {
assert(config);
assert(chosen_entry);
assert(loaded_image_path);
EFI_STATUS err; EFI_STATUS err;
UINTN visible_max; UINTN visible_max;
UINTN idx_highlight; UINTN idx_highlight;
@ -526,10 +509,11 @@ static BOOLEAN menu_run(
UINTN y_max; UINTN y_max;
CHAR16 *status; CHAR16 *status;
CHAR16 *clearline; CHAR16 *clearline;
UINTN timeout_remain = config->timeout_sec; INTN timeout_remain;
INT16 idx; INT16 idx;
BOOLEAN exit = FALSE; BOOLEAN exit = FALSE;
BOOLEAN run = TRUE; BOOLEAN run = TRUE;
BOOLEAN wait = FALSE;
graphics_mode(FALSE); graphics_mode(FALSE);
uefi_call_wrapper(ST->ConIn->Reset, 2, ST->ConIn, FALSE); uefi_call_wrapper(ST->ConIn->Reset, 2, ST->ConIn, FALSE);
@ -543,7 +527,7 @@ static BOOLEAN menu_run(
err = console_set_mode(&config->console_mode, config->console_mode_change); err = console_set_mode(&config->console_mode, config->console_mode_change);
if (EFI_ERROR(err)) { if (EFI_ERROR(err)) {
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
log_error_stall(L"Error switching console mode to %lu: %r", (UINT64)config->console_mode, err); Print(L"Error switching console mode to %ld: %r.\r", (UINT64)config->console_mode, err);
} }
} else } else
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
@ -554,6 +538,12 @@ static BOOLEAN menu_run(
y_max = 25; y_max = 25;
} }
/* we check 10 times per second for a keystroke */
if (config->timeout_sec > 0)
timeout_remain = config->timeout_sec * 10;
else
timeout_remain = -1;
idx_highlight = config->idx_default; idx_highlight = config->idx_default;
idx_highlight_prev = 0; idx_highlight_prev = 0;
@ -653,7 +643,7 @@ static BOOLEAN menu_run(
if (timeout_remain > 0) { if (timeout_remain > 0) {
FreePool(status); FreePool(status);
status = PoolPrint(L"Boot in %d s.", timeout_remain); status = PoolPrint(L"Boot in %d sec.", (timeout_remain + 5) / 10);
} }
/* print status at last line of screen */ /* print status at last line of screen */
@ -674,18 +664,27 @@ static BOOLEAN menu_run(
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1 + x + len); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1 + x + len);
} }
err = console_key_read(&key, timeout_remain > 0 ? 1000 * 1000 : 0); err = console_key_read(&key, wait);
if (err == EFI_TIMEOUT) { if (EFI_ERROR(err)) {
timeout_remain--; /* timeout reached */
if (timeout_remain == 0) { if (timeout_remain == 0) {
exit = TRUE; exit = TRUE;
break; break;
} }
/* update status */ /* sleep and update status */
if (timeout_remain > 0) {
uefi_call_wrapper(BS->Stall, 1, 100 * 1000);
timeout_remain--;
continue; continue;
} else }
timeout_remain = 0;
/* timeout disabled, wait for next key */
wait = TRUE;
continue;
}
timeout_remain = -1;
/* clear status after keystroke */ /* clear status after keystroke */
if (status) { if (status) {
@ -788,7 +787,7 @@ static BOOLEAN menu_run(
config->timeout_sec_efivar, config->timeout_sec_efivar,
EFI_VARIABLE_NON_VOLATILE); EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_efivar > 0) if (config->timeout_sec_efivar > 0)
status = PoolPrint(L"Menu timeout set to %d s.", config->timeout_sec_efivar); status = PoolPrint(L"Menu timeout set to %d sec.", config->timeout_sec_efivar);
else else
status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu."); status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
} else if (config->timeout_sec_efivar <= 0){ } else if (config->timeout_sec_efivar <= 0){
@ -796,7 +795,7 @@ static BOOLEAN menu_run(
efivar_set( efivar_set(
LOADER_GUID, L"LoaderConfigTimeout", NULL, EFI_VARIABLE_NON_VOLATILE); LOADER_GUID, L"LoaderConfigTimeout", NULL, EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_config > 0) if (config->timeout_sec_config > 0)
status = PoolPrint(L"Menu timeout of %d s is defined by configuration file.", status = PoolPrint(L"Menu timeout of %d sec is defined by configuration file.",
config->timeout_sec_config); config->timeout_sec_config);
else else
status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu."); status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
@ -814,7 +813,7 @@ static BOOLEAN menu_run(
config->timeout_sec_efivar, config->timeout_sec_efivar,
EFI_VARIABLE_NON_VOLATILE); EFI_VARIABLE_NON_VOLATILE);
if (config->timeout_sec_efivar > 0) if (config->timeout_sec_efivar > 0)
status = PoolPrint(L"Menu timeout set to %d s.", status = PoolPrint(L"Menu timeout set to %d sec.",
config->timeout_sec_efivar); config->timeout_sec_efivar);
else else
status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu."); status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
@ -885,9 +884,6 @@ static BOOLEAN menu_run(
} }
static VOID config_add_entry(Config *config, ConfigEntry *entry) { static VOID config_add_entry(Config *config, ConfigEntry *entry) {
assert(config);
assert(entry);
if ((config->entry_count & 15) == 0) { if ((config->entry_count & 15) == 0) {
UINTN i; UINTN i;
@ -928,12 +924,6 @@ static CHAR8 *line_get_key_value(
CHAR8 *line, *value; CHAR8 *line, *value;
UINTN linelen; UINTN linelen;
assert(content);
assert(sep);
assert(pos);
assert(key_ret);
assert(value_ret);
skip: skip:
line = content + *pos; line = content + *pos;
if (*line == '\0') if (*line == '\0')
@ -995,10 +985,6 @@ static VOID config_defaults_load_from_file(Config *config, CHAR8 *content) {
CHAR8 *line; CHAR8 *line;
UINTN pos = 0; UINTN pos = 0;
CHAR8 *key, *value; CHAR8 *key, *value;
EFI_STATUS err;
assert(config);
assert(content);
while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) { while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) {
if (strcmpa((CHAR8 *)"timeout", key) == 0) { if (strcmpa((CHAR8 *)"timeout", key) == 0) {
@ -1018,23 +1004,32 @@ static VOID config_defaults_load_from_file(Config *config, CHAR8 *content) {
} }
if (strcmpa((CHAR8 *)"editor", key) == 0) { if (strcmpa((CHAR8 *)"editor", key) == 0) {
err = parse_boolean(value, &config->editor); BOOLEAN on;
if (EFI_ERROR(err))
log_error_stall(L"Error parsing 'editor' config option: %a", value); if (EFI_ERROR(parse_boolean(value, &on)))
continue;
config->editor = on;
continue; continue;
} }
if (strcmpa((CHAR8 *)"auto-entries", key) == 0) { if (strcmpa((CHAR8 *)"auto-entries", key) == 0) {
err = parse_boolean(value, &config->auto_entries); BOOLEAN on;
if (EFI_ERROR(err))
log_error_stall(L"Error parsing 'auto-entries' config option: %a", value); if (EFI_ERROR(parse_boolean(value, &on)))
continue;
config->auto_entries = on;
continue; continue;
} }
if (strcmpa((CHAR8 *)"auto-firmware", key) == 0) { if (strcmpa((CHAR8 *)"auto-firmware", key) == 0) {
err = parse_boolean(value, &config->auto_firmware); BOOLEAN on;
if (EFI_ERROR(err))
log_error_stall(L"Error parsing 'auto-firmware' config option: %a", value); if (EFI_ERROR(parse_boolean(value, &on)))
continue;
config->auto_firmware = on;
continue; continue;
} }
@ -1066,11 +1061,8 @@ static VOID config_defaults_load_from_file(Config *config, CHAR8 *content) {
else { else {
BOOLEAN on; BOOLEAN on;
err = parse_boolean(value, &on); if (EFI_ERROR(parse_boolean(value, &on)))
if (EFI_ERROR(err)) {
log_error_stall(L"Error parsing 'random-seed-mode' config option: %a", value);
continue; continue;
}
config->random_seed_mode = on ? RANDOM_SEED_ALWAYS : RANDOM_SEED_OFF; config->random_seed_mode = on ? RANDOM_SEED_ALWAYS : RANDOM_SEED_OFF;
} }
@ -1087,10 +1079,6 @@ static VOID config_entry_parse_tries(
UINTN left = UINTN_MAX, done = UINTN_MAX, factor = 1, i, next_left, next_done; UINTN left = UINTN_MAX, done = UINTN_MAX, factor = 1, i, next_left, next_done;
_cleanup_freepool_ CHAR16 *prefix = NULL; _cleanup_freepool_ CHAR16 *prefix = NULL;
assert(entry);
assert(path);
assert(file);
/* /*
* Parses a suffix of two counters (one going down, one going up) in the form "+LEFT-DONE" from the end of the * Parses a suffix of two counters (one going down, one going up) in the form "+LEFT-DONE" from the end of the
* filename (but before the .efi/.conf suffix), where the "-DONE" part is optional and may be left out (in * filename (but before the .efi/.conf suffix), where the "-DONE" part is optional and may be left out (in
@ -1208,9 +1196,6 @@ static VOID config_entry_bump_counters(
UINTN file_info_size, a, b; UINTN file_info_size, a, b;
EFI_STATUS r; EFI_STATUS r;
assert(entry);
assert(root_dir);
if (entry->tries_left == UINTN_MAX) if (entry->tries_left == UINTN_MAX)
return; return;
@ -1236,7 +1221,8 @@ static VOID config_entry_bump_counters(
break; break;
if (r != EFI_BUFFER_TOO_SMALL || file_info_size * 2 < file_info_size) { if (r != EFI_BUFFER_TOO_SMALL || file_info_size * 2 < file_info_size) {
log_error_stall(L"Failed to get file info for '%s': %r", old_path, r); Print(L"\nFailed to get file info for '%s': %r\n", old_path, r);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return; return;
} }
@ -1248,7 +1234,8 @@ static VOID config_entry_bump_counters(
StrCpy(file_info->FileName, entry->next_name); StrCpy(file_info->FileName, entry->next_name);
r = uefi_call_wrapper(handle->SetInfo, 4, handle, &EfiFileInfoGuid, file_info_size, file_info); r = uefi_call_wrapper(handle->SetInfo, 4, handle, &EfiFileInfoGuid, file_info_size, file_info);
if (EFI_ERROR(r)) { if (EFI_ERROR(r)) {
log_error_stall(L"Failed to rename '%s' to '%s', ignoring: %r", old_path, entry->next_name, r); Print(L"\nFailed to rename '%s' to '%s', ignoring: %r\n", old_path, entry->next_name, r);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return; return;
} }
@ -1284,14 +1271,6 @@ static VOID config_entry_add_from_file(
EFI_FILE_HANDLE handle; EFI_FILE_HANDLE handle;
_cleanup_freepool_ CHAR16 *initrd = NULL; _cleanup_freepool_ CHAR16 *initrd = NULL;
assert(config);
assert(device);
assert(root_dir);
assert(path);
assert(file);
assert(content);
assert(loaded_image_path);
entry = AllocatePool(sizeof(ConfigEntry)); entry = AllocatePool(sizeof(ConfigEntry));
*entry = (ConfigEntry) { *entry = (ConfigEntry) {
@ -1420,8 +1399,6 @@ static VOID config_load_defaults(Config *config, EFI_FILE *root_dir) {
UINTN sec; UINTN sec;
EFI_STATUS err; EFI_STATUS err;
assert(root_dir);
*config = (Config) { *config = (Config) {
.editor = TRUE, .editor = TRUE,
.auto_entries = TRUE, .auto_entries = TRUE,
@ -1459,11 +1436,6 @@ static VOID config_load_entries(
EFI_FILE_HANDLE entries_dir; EFI_FILE_HANDLE entries_dir;
EFI_STATUS err; EFI_STATUS err;
assert(config);
assert(device);
assert(root_dir);
assert(loaded_image_path);
err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &entries_dir, (CHAR16*) L"\\loader\\entries", EFI_FILE_MODE_READ, 0ULL); err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &entries_dir, (CHAR16*) L"\\loader\\entries", EFI_FILE_MODE_READ, 0ULL);
if (!EFI_ERROR(err)) { if (!EFI_ERROR(err)) {
for (;;) { for (;;) {
@ -1499,9 +1471,6 @@ static VOID config_load_entries(
static INTN config_entry_compare(ConfigEntry *a, ConfigEntry *b) { static INTN config_entry_compare(ConfigEntry *a, ConfigEntry *b) {
INTN r; INTN r;
assert(a);
assert(b);
/* Order entries that have no tries left to the beginning of the list */ /* Order entries that have no tries left to the beginning of the list */
if (a->tries_left != 0 && b->tries_left == 0) if (a->tries_left != 0 && b->tries_left == 0)
return 1; return 1;
@ -1532,8 +1501,6 @@ static INTN config_entry_compare(ConfigEntry *a, ConfigEntry *b) {
} }
static VOID config_sort_entries(Config *config) { static VOID config_sort_entries(Config *config) {
assert(config);
for (UINTN i = 1; i < config->entry_count; i++) { for (UINTN i = 1; i < config->entry_count; i++) {
BOOLEAN more; BOOLEAN more;
@ -1555,9 +1522,6 @@ static VOID config_sort_entries(Config *config) {
} }
static INTN config_entry_find(Config *config, CHAR16 *id) { static INTN config_entry_find(Config *config, CHAR16 *id) {
assert(config);
assert(id);
for (UINTN i = 0; i < config->entry_count; i++) for (UINTN i = 0; i < config->entry_count; i++)
if (StrCmp(config->entries[i]->id, id) == 0) if (StrCmp(config->entries[i]->id, id) == 0)
return (INTN) i; return (INTN) i;
@ -1570,8 +1534,6 @@ static VOID config_default_entry_select(Config *config) {
EFI_STATUS err; EFI_STATUS err;
INTN i; INTN i;
assert(config);
/* /*
* The EFI variable to specify a boot entry for the next, and only the * The EFI variable to specify a boot entry for the next, and only the
* next reboot. The variable is always cleared directly after it is read. * next reboot. The variable is always cleared directly after it is read.
@ -1642,8 +1604,6 @@ static VOID config_default_entry_select(Config *config) {
static BOOLEAN find_nonunique(ConfigEntry **entries, UINTN entry_count) { static BOOLEAN find_nonunique(ConfigEntry **entries, UINTN entry_count) {
BOOLEAN non_unique = FALSE; BOOLEAN non_unique = FALSE;
assert(entries);
for (UINTN i = 0; i < entry_count; i++) for (UINTN i = 0; i < entry_count; i++)
entries[i]->non_unique = FALSE; entries[i]->non_unique = FALSE;
@ -1662,8 +1622,6 @@ static BOOLEAN find_nonunique(ConfigEntry **entries, UINTN entry_count) {
/* generate a unique title, avoiding non-distinguishable menu entries */ /* generate a unique title, avoiding non-distinguishable menu entries */
static VOID config_title_generate(Config *config) { static VOID config_title_generate(Config *config) {
assert(config);
/* set title */ /* set title */
for (UINTN i = 0; i < config->entry_count; i++) { for (UINTN i = 0; i < config->entry_count; i++) {
CHAR16 *title; CHAR16 *title;
@ -1736,11 +1694,6 @@ static BOOLEAN config_entry_add_call(
ConfigEntry *entry; ConfigEntry *entry;
assert(config);
assert(id);
assert(title);
assert(call);
entry = AllocatePool(sizeof(ConfigEntry)); entry = AllocatePool(sizeof(ConfigEntry));
*entry = (ConfigEntry) { *entry = (ConfigEntry) {
.id = StrDuplicate(id), .id = StrDuplicate(id),
@ -1767,17 +1720,11 @@ static ConfigEntry *config_entry_add_loader(
ConfigEntry *entry; ConfigEntry *entry;
assert(config);
assert(device);
assert(id);
assert(title);
assert(loader);
entry = AllocatePool(sizeof(ConfigEntry)); entry = AllocatePool(sizeof(ConfigEntry));
*entry = (ConfigEntry) { *entry = (ConfigEntry) {
.type = type, .type = type,
.title = StrDuplicate(title), .title = StrDuplicate(title),
.version = version ? StrDuplicate(version) : NULL, .version = StrDuplicate(version),
.device = device, .device = device,
.loader = StrDuplicate(loader), .loader = StrDuplicate(loader),
.id = StrDuplicate(id), .id = StrDuplicate(id),
@ -1806,13 +1753,6 @@ static BOOLEAN config_entry_add_loader_auto(
ConfigEntry *entry; ConfigEntry *entry;
EFI_STATUS err; EFI_STATUS err;
assert(config);
assert(device);
assert(root_dir);
assert(id);
assert(title);
assert(loader);
if (!config->auto_entries) if (!config->auto_entries)
return FALSE; return FALSE;
@ -1853,8 +1793,6 @@ static VOID config_entry_add_osx(Config *config) {
UINTN handle_count = 0; UINTN handle_count = 0;
_cleanup_freepool_ EFI_HANDLE *handles = NULL; _cleanup_freepool_ EFI_HANDLE *handles = NULL;
assert(config);
if (!config->auto_entries) if (!config->auto_entries)
return; return;
@ -1885,10 +1823,6 @@ static VOID config_entry_add_linux(
EFI_STATUS err; EFI_STATUS err;
ConfigEntry *entry; ConfigEntry *entry;
assert(config);
assert(device);
assert(root_dir);
err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &linux_dir, (CHAR16*) L"\\EFI\\Linux", EFI_FILE_MODE_READ, 0ULL); err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &linux_dir, (CHAR16*) L"\\EFI\\Linux", EFI_FILE_MODE_READ, 0ULL);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return; return;
@ -2023,9 +1957,6 @@ static EFI_DEVICE_PATH *path_parent(EFI_DEVICE_PATH *path, EFI_DEVICE_PATH *node
EFI_DEVICE_PATH *parent; EFI_DEVICE_PATH *parent;
UINTN len; UINTN len;
assert(path);
assert(node);
len = (UINT8*) NextDevicePathNode(node) - (UINT8*) path; len = (UINT8*) NextDevicePathNode(node) - (UINT8*) path;
parent = (EFI_DEVICE_PATH*) AllocatePool(len + sizeof(EFI_DEVICE_PATH)); parent = (EFI_DEVICE_PATH*) AllocatePool(len + sizeof(EFI_DEVICE_PATH));
CopyMem(parent, path, len); CopyMem(parent, path, len);
@ -2047,9 +1978,6 @@ static VOID config_load_xbootldr(
EFI_FILE *root_dir; EFI_FILE *root_dir;
EFI_STATUS r; EFI_STATUS r;
assert(config);
assert(device);
partition_path = DevicePathFromHandle(device); partition_path = DevicePathFromHandle(device);
if (!partition_path) if (!partition_path)
return; return;
@ -2236,16 +2164,19 @@ static EFI_STATUS image_start(
CHAR16 *options; CHAR16 *options;
EFI_STATUS err; EFI_STATUS err;
assert(config);
assert(entry);
path = FileDevicePath(entry->device, entry->loader); path = FileDevicePath(entry->device, entry->loader);
if (!path) if (!path) {
return log_error_status_stall(EFI_INVALID_PARAMETER, L"Error getting device path."); Print(L"Error getting device path.");
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return EFI_INVALID_PARAMETER;
}
err = uefi_call_wrapper(BS->LoadImage, 6, FALSE, parent_image, path, NULL, 0, &image); err = uefi_call_wrapper(BS->LoadImage, 6, FALSE, parent_image, path, NULL, 0, &image);
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
return log_error_status_stall(err, L"Error loading %s: %r", entry->loader, err); Print(L"Error loading %s: %r", entry->loader, err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
if (config->options_edit) if (config->options_edit)
options = config->options_edit; options = config->options_edit;
@ -2259,19 +2190,22 @@ static EFI_STATUS image_start(
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image, err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(err)) { if (EFI_ERROR(err)) {
log_error_stall(L"Error getting LoadedImageProtocol handle: %r", err); Print(L"Error getting LoadedImageProtocol handle: %r", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
goto out_unload; goto out_unload;
} }
loaded_image->LoadOptions = options; loaded_image->LoadOptions = options;
loaded_image->LoadOptionsSize = StrSize(loaded_image->LoadOptions); loaded_image->LoadOptionsSize = (StrLen(loaded_image->LoadOptions)+1) * sizeof(CHAR16);
#if ENABLE_TPM #if ENABLE_TPM
/* Try to log any options to the TPM, especially to catch manually edited options */ /* Try to log any options to the TPM, especially to catch manually edited options */
err = tpm_log_event(SD_TPM_PCR, err = tpm_log_event(SD_TPM_PCR,
(EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions, (EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions,
loaded_image->LoadOptionsSize, loaded_image->LoadOptions); loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
log_error_stall(L"Unable to add image options measurement: %r", err); Print(L"Unable to add image options measurement: %r", err);
uefi_call_wrapper(BS->Stall, 1, 200 * 1000);
}
#endif #endif
} }
@ -2297,11 +2231,12 @@ static EFI_STATUS reboot_into_firmware(VOID) {
return err; return err;
err = uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, EFI_SUCCESS, 0, NULL); err = uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, EFI_SUCCESS, 0, NULL);
return log_error_status_stall(err, L"Error calling ResetSystem: %r", err); Print(L"Error calling ResetSystem: %r", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
} }
static VOID config_free(Config *config) { static VOID config_free(Config *config) {
assert(config);
for (UINTN i = 0; i < config->entry_count; i++) for (UINTN i = 0; i < config->entry_count; i++)
config_entry_free(config->entries[i]); config_entry_free(config->entries[i]);
FreePool(config->entries); FreePool(config->entries);
@ -2311,30 +2246,26 @@ static VOID config_free(Config *config) {
} }
static VOID config_write_entries_to_variable(Config *config) { static VOID config_write_entries_to_variable(Config *config) {
_cleanup_freepool_ CHAR8 *buffer = NULL; _cleanup_freepool_ CHAR16 *buffer = NULL;
UINTN sz = 0; UINTN sz = 0;
CHAR8 *p; CHAR16 *p;
assert(config);
for (UINTN i = 0; i < config->entry_count; i++) for (UINTN i = 0; i < config->entry_count; i++)
sz += StrSize(config->entries[i]->id); sz += StrLen(config->entries[i]->id) + 1;
p = buffer = AllocatePool(sz); p = buffer = AllocatePool(sz * sizeof(CHAR16));
for (UINTN i = 0; i < config->entry_count; i++) { for (UINTN i = 0; i < config->entry_count; i++) {
UINTN l; UINTN l;
l = StrSize(config->entries[i]->id); l = StrLen(config->entries[i]->id) + 1;
CopyMem(p, config->entries[i]->id, l); CopyMem(p, config->entries[i]->id, l * sizeof(CHAR16));
p += l; p += l;
} }
assert(p == buffer + sz);
/* Store the full list of discovered entries. */ /* Store the full list of discovered entries. */
(void) efivar_set_raw(LOADER_GUID, L"LoaderEntries", buffer, sz, 0); (void) efivar_set_raw(LOADER_GUID, L"LoaderEntries", buffer, (UINT8 *) p - (UINT8 *) buffer, 0);
} }
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
@ -2374,21 +2305,30 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image, err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err); Print(L"Error getting a LoadedImageProtocol handle: %r", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
/* export the device path this image is started from */ /* export the device path this image is started from */
if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, 0); efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, 0);
root_dir = LibOpenRoot(loaded_image->DeviceHandle); root_dir = LibOpenRoot(loaded_image->DeviceHandle);
if (!root_dir) if (!root_dir) {
return log_error_status_stall(EFI_LOAD_ERROR, L"Unable to open root directory.", EFI_LOAD_ERROR); Print(L"Unable to open root directory.");
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return EFI_LOAD_ERROR;
}
if (secure_boot_enabled() && shim_loaded()) { if (secure_boot_enabled() && shim_loaded()) {
err = security_policy_install(); err = security_policy_install();
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
return log_error_status_stall(err, L"Error installing security policy: %r", err); Print(L"Error installing security policy: %r ", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
} }
/* the filesystem path to this image, to prevent adding ourselves to the menu */ /* the filesystem path to this image, to prevent adding ourselves to the menu */
@ -2427,7 +2367,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
} }
if (config.entry_count == 0) { if (config.entry_count == 0) {
log_error_stall(L"No loader found. Configuration files in \\loader\\entries\\*.conf are needed."); Print(L"No loader found. Configuration files in \\loader\\entries\\*.conf are needed.");
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
goto out; goto out;
} }
@ -2451,8 +2392,13 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
else { else {
UINT64 key; UINT64 key;
/* Block up to 100ms to give firmware time to get input working. */ err = console_key_read(&key, FALSE);
err = console_key_read(&key, 100 * 1000);
if (err == EFI_NOT_READY) {
uefi_call_wrapper(BS->Stall, 1, 100 * 1000);
err = console_key_read(&key, FALSE);
}
if (!EFI_ERROR(err)) { if (!EFI_ERROR(err)) {
INT16 idx; INT16 idx;
@ -2494,7 +2440,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = image_start(image, &config, entry); err = image_start(image, &config, entry);
if (EFI_ERROR(err)) { if (EFI_ERROR(err)) {
graphics_mode(FALSE); graphics_mode(FALSE);
log_error_stall(L"Failed to execute %s (%s): %r", entry->title, entry->loader, err); Print(L"\nFailed to execute %s (%s): %r\n", entry->title, entry->loader, err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
goto out; goto out;
} }

View File

@ -11,82 +11,32 @@
#define EFI_SIMPLE_TEXT_INPUT_EX_GUID &(EFI_GUID) EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID #define EFI_SIMPLE_TEXT_INPUT_EX_GUID &(EFI_GUID) EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID
static inline void EventClosep(EFI_EVENT *event) { EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) {
if (!*event)
return;
uefi_call_wrapper(BS->CloseEvent, 1, *event);
}
/*
* Reading input from the console sounds like an easy task to do, but thanks to broken
* firmware it is actually a nightmare.
*
* There is a ConIn and TextInputEx API for this. Ideally we want to use TextInputEx,
* because that gives us Ctrl/Alt/Shift key state information. Unfortunately, it is not
* always available and sometimes just non-functional.
*
* On the other hand we have ConIn, where some firmware likes to just freeze on us
* if we call ReadKeyStroke on it.
*
* Therefore, we use WaitForEvent on both ConIn and TextInputEx (if available) along
* with a timer event. The timer ensures there is no need to call into functions
* that might freeze on us, while still allowing us to show a timeout counter.
*/
EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec) {
static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx; static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
static BOOLEAN checked; static BOOLEAN checked;
UINTN index; UINTN index;
EFI_INPUT_KEY k; EFI_INPUT_KEY k;
EFI_STATUS err; EFI_STATUS err;
_cleanup_(EventClosep) EFI_EVENT timer = NULL;
EFI_EVENT events[3] = { ST->ConIn->WaitForKey };
UINTN n_events = 1;
assert(key);
if (!checked) { if (!checked) {
err = LibLocateProtocol(EFI_SIMPLE_TEXT_INPUT_EX_GUID, (VOID **)&TextInputEx); err = LibLocateProtocol(EFI_SIMPLE_TEXT_INPUT_EX_GUID, (VOID **)&TextInputEx);
if (EFI_ERROR(err) || if (EFI_ERROR(err))
uefi_call_wrapper(BS->CheckEvent, 1, TextInputEx->WaitForKeyEx) == EFI_INVALID_PARAMETER)
/* If WaitForKeyEx fails here, the firmware pretends it talks this
* protocol, but it really doesn't. */
TextInputEx = NULL; TextInputEx = NULL;
else
events[n_events++] = TextInputEx->WaitForKeyEx;
checked = TRUE; checked = TRUE;
} }
if (timeout_usec > 0) { /* wait until key is pressed */
err = uefi_call_wrapper(BS->CreateEvent, 5, EVT_TIMER, 0, NULL, NULL, &timer); if (wait)
if (EFI_ERROR(err)) uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
return log_error_status_stall(err, L"Error creating timer event: %r", err);
/* SetTimer expects 100ns units for some reason. */ if (TextInputEx) {
err = uefi_call_wrapper(BS->SetTimer, 3, timer, TimerRelative, timeout_usec * 10);
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Error arming timer event: %r", err);
events[n_events++] = timer;
}
err = uefi_call_wrapper(BS->WaitForEvent, 3, n_events, events, &index);
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Error waiting for events: %r", err);
if (timeout_usec > 0 && timer == events[index])
return EFI_TIMEOUT;
/* TextInputEx might be ready too even if ConIn got to signal first. */
if (TextInputEx && !EFI_ERROR(uefi_call_wrapper(BS->CheckEvent, 1, TextInputEx->WaitForKeyEx))) {
EFI_KEY_DATA keydata; EFI_KEY_DATA keydata;
UINT64 keypress; UINT64 keypress;
UINT32 shift = 0;
err = uefi_call_wrapper(TextInputEx->ReadKeyStrokeEx, 2, TextInputEx, &keydata); err = uefi_call_wrapper(TextInputEx->ReadKeyStrokeEx, 2, TextInputEx, &keydata);
if (EFI_ERROR(err)) if (!EFI_ERROR(err)) {
return err; UINT32 shift = 0;
/* do not distinguish between left and right keys */ /* do not distinguish between left and right keys */
if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) { if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) {
@ -100,18 +50,22 @@ EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec) {
keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar); keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
if (keypress > 0) { if (keypress > 0) {
*key = keypress; *key = keypress;
return EFI_SUCCESS; return 0;
} }
}
return EFI_NOT_READY;
} }
/* fallback for firmware which does not support SimpleTextInputExProtocol
*
* This is also called in case ReadKeyStrokeEx did not return a key, because
* some broken firmwares offer SimpleTextInputExProtocol, but never actually
* handle any key. */
err = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &k); err = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &k);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return err; return err;
*key = KEYPRESS(0, k.ScanCode, k.UnicodeChar); *key = KEYPRESS(0, k.ScanCode, k.UnicodeChar);
return EFI_SUCCESS; return 0;
} }
static EFI_STATUS change_mode(UINTN mode) { static EFI_STATUS change_mode(UINTN mode) {
@ -154,8 +108,6 @@ static EFI_STATUS mode_auto(UINTN *mode) {
EFI_STATUS err; EFI_STATUS err;
BOOLEAN keep = FALSE; BOOLEAN keep = FALSE;
assert(mode);
err = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput); err = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
if (!EFI_ERROR(err) && GraphicsOutput->Mode && GraphicsOutput->Mode->Info) { if (!EFI_ERROR(err) && GraphicsOutput->Mode && GraphicsOutput->Mode->Info) {
Info = GraphicsOutput->Mode->Info; Info = GraphicsOutput->Mode->Info;
@ -204,8 +156,6 @@ static EFI_STATUS mode_auto(UINTN *mode) {
} }
EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how) { EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how) {
assert(mode);
if (how == CONSOLE_MODE_AUTO) if (how == CONSOLE_MODE_AUTO)
return mode_auto(mode); return mode_auto(mode);

View File

@ -16,5 +16,5 @@ enum console_mode_change_type {
CONSOLE_MODE_MAX, CONSOLE_MODE_MAX,
}; };
EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec); EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait);
EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how); EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how);

View File

@ -42,7 +42,6 @@
*/ */
#include "crc32.h" #include "crc32.h"
#include "macro-fundamental.h"
static const UINT32 crc32_tab[] = { static const UINT32 crc32_tab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
@ -112,8 +111,6 @@ UINT32 crc32(UINT32 seed, const VOID *buf, UINTN len) {
const UINT8 *p = buf; const UINT8 *p = buf;
UINT32 crc = seed; UINT32 crc = seed;
assert(buf);
while (len > 0) { while (len > 0) {
crc = crc32_add_char(crc, *p++); crc = crc32_add_char(crc, *p++);
len--; len--;
@ -132,8 +129,6 @@ UINT32 crc32_exclude_offset(
const UINT8 *p = buf; const UINT8 *p = buf;
UINT32 crc = seed; UINT32 crc = seed;
assert(buf);
for (UINTN i = 0; i < len; i++) { for (UINTN i = 0; i < len; i++) {
UINT8 x = *p++; UINT8 x = *p++;

View File

@ -9,8 +9,6 @@
EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[static 37]) { EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[static 37]) {
EFI_DEVICE_PATH *device_path; EFI_DEVICE_PATH *device_path;
assert(handle);
/* export the device path this image is started from */ /* export the device path this image is started from */
device_path = DevicePathFromHandle(handle); device_path = DevicePathFromHandle(handle);
if (device_path) { if (device_path) {

View File

@ -17,8 +17,6 @@ static VOID linux_efi_handover(EFI_HANDLE image, struct boot_params *params) {
handover_f handover; handover_f handover;
UINTN start = (UINTN)params->hdr.code32_start; UINTN start = (UINTN)params->hdr.code32_start;
assert(params);
#ifdef __x86_64__ #ifdef __x86_64__
asm volatile ("cli"); asm volatile ("cli");
start += 512; start += 512;
@ -37,9 +35,6 @@ EFI_STATUS linux_exec(EFI_HANDLE *image,
EFI_PHYSICAL_ADDRESS addr; EFI_PHYSICAL_ADDRESS addr;
EFI_STATUS err; EFI_STATUS err;
assert(image);
assert(cmdline);
image_params = (struct boot_params *) linux_addr; image_params = (struct boot_params *) linux_addr;
if (image_params->hdr.boot_flag != 0xAA55 || if (image_params->hdr.boot_flag != 0xAA55 ||

View File

@ -5,7 +5,6 @@
#include <efi.h> #include <efi.h>
#include <efilib.h> #include <efilib.h>
#include "macro-fundamental.h"
#include "measure.h" #include "measure.h"
#define EFI_TCG_GUID \ #define EFI_TCG_GUID \
@ -185,10 +184,8 @@ static EFI_STATUS tpm1_measure_to_pcr_and_event_log(const EFI_TCG *tcg, UINT32 p
EFI_PHYSICAL_ADDRESS event_log_last; EFI_PHYSICAL_ADDRESS event_log_last;
UINTN desc_len; UINTN desc_len;
assert(tcg); desc_len = (StrLen(description) + 1) * sizeof(CHAR16);
assert(description);
desc_len = StrSize(description);
tcg_event = AllocateZeroPool(desc_len + sizeof(TCG_PCR_EVENT)); tcg_event = AllocateZeroPool(desc_len + sizeof(TCG_PCR_EVENT));
if (!tcg_event) if (!tcg_event)
@ -218,16 +215,14 @@ static EFI_STATUS tpm2_measure_to_pcr_and_event_log(const EFI_TCG2 *tcg, UINT32
EFI_TCG2_EVENT *tcg_event; EFI_TCG2_EVENT *tcg_event;
UINTN desc_len; UINTN desc_len;
assert(tcg); desc_len = StrLen(description) * sizeof(CHAR16);
assert(description);
desc_len = StrSize(description); tcg_event = AllocateZeroPool(sizeof(*tcg_event) - sizeof(tcg_event->Event) + desc_len + 1);
tcg_event = AllocateZeroPool(sizeof(*tcg_event) - sizeof(tcg_event->Event) + desc_len);
if (!tcg_event) if (!tcg_event)
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;
tcg_event->Size = sizeof(*tcg_event) - sizeof(tcg_event->Event) + desc_len; tcg_event->Size = sizeof(*tcg_event) - sizeof(tcg_event->Event) + desc_len + 1;
tcg_event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER); tcg_event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER);
tcg_event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION; tcg_event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
tcg_event->Header.PCRIndex = pcrindex; tcg_event->Header.PCRIndex = pcrindex;
@ -307,8 +302,6 @@ EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UIN
EFI_TCG *tpm1; EFI_TCG *tpm1;
EFI_TCG2 *tpm2; EFI_TCG2 *tpm2;
assert(description);
tpm2 = tcg2_interface_check(); tpm2 = tcg2_interface_check();
if (tpm2) if (tpm2)
return tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description); return tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description);

View File

@ -17,7 +17,6 @@ efi_headers = files('''
'''.split()) '''.split())
common_sources = ''' common_sources = '''
assert.c
disk.c disk.c
graphics.c graphics.c
measure.c measure.c
@ -220,16 +219,12 @@ if have_gnu_efi
compile_args += ['-Werror'] compile_args += ['-Werror']
endif endif
if get_option('buildtype') == 'debug' if get_option('buildtype') == 'debug'
compile_args += ['-ggdb', '-O0', '-DEFI_DEBUG'] compile_args += ['-ggdb', '-O0']
elif get_option('buildtype') == 'debugoptimized' elif get_option('buildtype') == 'debugoptimized'
compile_args += ['-ggdb', '-Og', '-DEFI_DEBUG'] compile_args += ['-ggdb', '-Og']
else else
compile_args += ['-O2'] compile_args += ['-O2']
endif endif
if get_option('b_ndebug') == 'true' or (
get_option('b_ndebug') == 'if-release' and ['plain', 'release'].contains(get_option('buildtype')))
compile_args += ['-DNDEBUG']
endif
efi_ldflags = ['-T', efi_lds, efi_ldflags = ['-T', efi_lds,
'-shared', '-shared',

View File

@ -66,9 +66,6 @@ EFI_STATUS pe_memory_locate_sections(CHAR8 *base, CHAR8 **sections, UINTN *addrs
struct PeHeader *pe; struct PeHeader *pe;
UINTN offset; UINTN offset;
assert(base);
assert(sections);
dos = (struct DosFileHeader *)base; dos = (struct DosFileHeader *)base;
if (CompareMem(dos->Magic, "MZ", 2) != 0) if (CompareMem(dos->Magic, "MZ", 2) != 0)
@ -121,9 +118,6 @@ EFI_STATUS pe_file_locate_sections(EFI_FILE *dir, CHAR16 *path, CHAR8 **sections
EFI_STATUS err; EFI_STATUS err;
_cleanup_freepool_ CHAR8 *header = NULL; _cleanup_freepool_ CHAR8 *header = NULL;
assert(dir);
assert(path);
err = uefi_call_wrapper(dir->Open, 5, dir, &handle, path, EFI_FILE_MODE_READ, 0ULL); err = uefi_call_wrapper(dir->Open, 5, dir, &handle, path, EFI_FILE_MODE_READ, 0ULL);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return err; return err;

View File

@ -22,8 +22,6 @@ static EFI_STATUS acquire_rng(UINTN size, VOID **ret) {
EFI_RNG_PROTOCOL *rng; EFI_RNG_PROTOCOL *rng;
EFI_STATUS err; EFI_STATUS err;
assert(ret);
/* Try to acquire the specified number of bytes from the UEFI RNG */ /* Try to acquire the specified number of bytes from the UEFI RNG */
err = LibLocateProtocol(EFI_RNG_GUID, (VOID**) &rng); err = LibLocateProtocol(EFI_RNG_GUID, (VOID**) &rng);
@ -37,8 +35,10 @@ static EFI_STATUS acquire_rng(UINTN size, VOID **ret) {
return log_oom(); return log_oom();
err = uefi_call_wrapper(rng->GetRNG, 3, rng, NULL, size, data); err = uefi_call_wrapper(rng->GetRNG, 3, rng, NULL, size, data);
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
return log_error_status_stall(err, L"Failed to acquire RNG data: %r", err); Print(L"Failed to acquire RNG data: %r\n", err);
return err;
}
*ret = TAKE_PTR(data); *ret = TAKE_PTR(data);
return EFI_SUCCESS; return EFI_SUCCESS;
@ -65,10 +65,6 @@ static VOID hash_once(
struct sha256_ctx hash; struct sha256_ctx hash;
assert(old_seed);
assert(rng);
assert(system_token);
sha256_init_ctx(&hash); sha256_init_ctx(&hash);
sha256_process_bytes(old_seed, size, &hash); sha256_process_bytes(old_seed, size, &hash);
if (rng) if (rng)
@ -91,11 +87,6 @@ static EFI_STATUS hash_many(
_cleanup_freepool_ VOID *output = NULL; _cleanup_freepool_ VOID *output = NULL;
assert(old_seed);
assert(rng);
assert(system_token);
assert(ret);
/* Hashes the specified parameters in counter mode, generating n hash values, with the counter in the /* Hashes the specified parameters in counter mode, generating n hash values, with the counter in the
* range counter_startcounter_start+n-1. */ * range counter_startcounter_start+n-1. */
@ -126,12 +117,6 @@ static EFI_STATUS mangle_random_seed(
EFI_STATUS err; EFI_STATUS err;
UINTN n; UINTN n;
assert(old_seed);
assert(rng);
assert(system_token);
assert(ret_new_seed);
assert(ret_for_kernel);
/* This takes the old seed file contents, an (optional) random number acquired from the UEFI RNG, an /* This takes the old seed file contents, an (optional) random number acquired from the UEFI RNG, an
* (optional) system 'token' installed once by the OS installer in an EFI variable, and hashes them * (optional) system 'token' installed once by the OS installer in an EFI variable, and hashes them
* together in counter mode, generating a new seed (to replace the file on disk) and the seed for the * together in counter mode, generating a new seed (to replace the file on disk) and the seed for the
@ -161,18 +146,17 @@ static EFI_STATUS acquire_system_token(VOID **ret, UINTN *ret_size) {
EFI_STATUS err; EFI_STATUS err;
UINTN size; UINTN size;
assert(ret);
assert(ret_size);
err = efivar_get_raw(LOADER_GUID, L"LoaderSystemToken", &data, &size); err = efivar_get_raw(LOADER_GUID, L"LoaderSystemToken", &data, &size);
if (EFI_ERROR(err)) { if (EFI_ERROR(err)) {
if (err != EFI_NOT_FOUND) if (err != EFI_NOT_FOUND)
log_error_stall(L"Failed to read LoaderSystemToken EFI variable: %r", err); Print(L"Failed to read LoaderSystemToken EFI variable: %r", err);
return err; return err;
} }
if (size <= 0) if (size <= 0) {
return log_error_status_stall(EFI_NOT_FOUND, L"System token too short, ignoring."); Print(L"System token too short, ignoring.");
return EFI_NOT_FOUND;
}
*ret = TAKE_PTR(data); *ret = TAKE_PTR(data);
*ret_size = size; *ret_size = size;
@ -182,7 +166,7 @@ static EFI_STATUS acquire_system_token(VOID **ret, UINTN *ret_size) {
static VOID validate_sha256(void) { static VOID validate_sha256(void) {
#ifdef EFI_DEBUG #ifndef __OPTIMIZE__
/* Let's validate our SHA256 implementation. We stole it from glibc, and converted it to UEFI /* Let's validate our SHA256 implementation. We stole it from glibc, and converted it to UEFI
* style. We better check whether it does the right stuff. We use the simpler test vectors from the * style. We better check whether it does the right stuff. We use the simpler test vectors from the
* SHA spec. Note that we strip this out in optimization builds. */ * SHA spec. Note that we strip this out in optimization builds. */
@ -224,9 +208,14 @@ static VOID validate_sha256(void) {
sha256_process_bytes(array[i].string, strlena((const CHAR8*) array[i].string), &hash); sha256_process_bytes(array[i].string, strlena((const CHAR8*) array[i].string), &hash);
sha256_finish_ctx(&hash, result); sha256_finish_ctx(&hash, result);
assert(CompareMem(result, array[i].hash, HASH_VALUE_SIZE) == 0); if (CompareMem(result, array[i].hash, HASH_VALUE_SIZE) != 0) {
Print(L"SHA256 failed validation.\n");
uefi_call_wrapper(BS->Stall, 1, 120 * 1000 * 1000);
return;
}
} }
Print(L"SHA256 validated\n");
#endif #endif
} }
@ -237,8 +226,6 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
_cleanup_freepool_ EFI_FILE_INFO *info = NULL; _cleanup_freepool_ EFI_FILE_INFO *info = NULL;
EFI_STATUS err; EFI_STATUS err;
assert(root_dir);
validate_sha256(); validate_sha256();
if (mode == RANDOM_SEED_OFF) if (mode == RANDOM_SEED_OFF)
@ -259,7 +246,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, (CHAR16*) L"\\loader\\random-seed", EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0ULL); err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, (CHAR16*) L"\\loader\\random-seed", EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0ULL);
if (EFI_ERROR(err)) { if (EFI_ERROR(err)) {
if (err != EFI_NOT_FOUND && err != EFI_WRITE_PROTECTED) if (err != EFI_NOT_FOUND && err != EFI_WRITE_PROTECTED)
log_error_stall(L"Failed to open random seed file: %r", err); Print(L"Failed to open random seed file: %r\n", err);
return err; return err;
} }
@ -268,11 +255,15 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
return log_oom(); return log_oom();
size = info->FileSize; size = info->FileSize;
if (size < RANDOM_MAX_SIZE_MIN) if (size < RANDOM_MAX_SIZE_MIN) {
return log_error_status_stall(EFI_INVALID_PARAMETER, L"Random seed file is too short."); Print(L"Random seed file is too short?\n");
return EFI_INVALID_PARAMETER;
}
if (size > RANDOM_MAX_SIZE_MAX) if (size > RANDOM_MAX_SIZE_MAX) {
return log_error_status_stall(EFI_INVALID_PARAMETER, L"Random seed file is too large."); Print(L"Random seed file is too large?\n");
return EFI_INVALID_PARAMETER;
}
seed = AllocatePool(size); seed = AllocatePool(size);
if (!seed) if (!seed)
@ -280,14 +271,20 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
rsize = size; rsize = size;
err = uefi_call_wrapper(handle->Read, 3, handle, &rsize, seed); err = uefi_call_wrapper(handle->Read, 3, handle, &rsize, seed);
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
return log_error_status_stall(err, L"Failed to read random seed file: %r", err); Print(L"Failed to read random seed file: %r\n", err);
if (rsize != size) return err;
return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short read on random seed file."); }
if (rsize != size) {
Print(L"Short read on random seed file\n");
return EFI_PROTOCOL_ERROR;
}
err = uefi_call_wrapper(handle->SetPosition, 2, handle, 0); err = uefi_call_wrapper(handle->SetPosition, 2, handle, 0);
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
return log_error_status_stall(err, L"Failed to seek to beginning of random seed file: %r", err); Print(L"Failed to seek to beginning of random seed file: %r\n", err);
return err;
}
/* Request some random data from the UEFI RNG. We don't need this to work safely, but it's a good /* Request some random data from the UEFI RNG. We don't need this to work safely, but it's a good
* idea to use it because it helps us for cases where users mistakenly include a random seed in * idea to use it because it helps us for cases where users mistakenly include a random seed in
@ -302,19 +299,27 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
/* Update the random seed on disk before we use it */ /* Update the random seed on disk before we use it */
wsize = size; wsize = size;
err = uefi_call_wrapper(handle->Write, 3, handle, &wsize, new_seed); err = uefi_call_wrapper(handle->Write, 3, handle, &wsize, new_seed);
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
return log_error_status_stall(err, L"Failed to write random seed file: %r", err); Print(L"Failed to write random seed file: %r\n", err);
if (wsize != size) return err;
return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short write on random seed file."); }
if (wsize != size) {
Print(L"Short write on random seed file\n");
return EFI_PROTOCOL_ERROR;
}
err = uefi_call_wrapper(handle->Flush, 1, handle); err = uefi_call_wrapper(handle->Flush, 1, handle);
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
return log_error_status_stall(err, L"Failed to flush random seed file: %r", err); Print(L"Failed to flush random seed file: %r\n");
return err;
}
/* We are good to go */ /* We are good to go */
err = efivar_set_raw(LOADER_GUID, L"LoaderRandomSeed", for_kernel, size, 0); err = efivar_set_raw(LOADER_GUID, L"LoaderRandomSeed", for_kernel, size, 0);
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
return log_error_status_stall(err, L"Failed to write random seed to EFI variable: %r", err); Print(L"Failed to write random seed to EFI variable: %r\n", err);
return err;
}
return EFI_SUCCESS; return EFI_SUCCESS;
} }

View File

@ -23,7 +23,6 @@
/* Written by Ulrich Drepper <drepper@redhat.com>, 2007. */ /* Written by Ulrich Drepper <drepper@redhat.com>, 2007. */
#include "macro-fundamental.h"
#include "sha256.h" #include "sha256.h"
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
@ -74,8 +73,6 @@ static void sha256_process_block(const void *, UINTN, struct sha256_ctx *);
/* Initialize structure containing state of computation. /* Initialize structure containing state of computation.
(FIPS 180-2:5.3.2) */ (FIPS 180-2:5.3.2) */
void sha256_init_ctx(struct sha256_ctx *ctx) { void sha256_init_ctx(struct sha256_ctx *ctx) {
assert(ctx);
ctx->H[0] = 0x6a09e667; ctx->H[0] = 0x6a09e667;
ctx->H[1] = 0xbb67ae85; ctx->H[1] = 0xbb67ae85;
ctx->H[2] = 0x3c6ef372; ctx->H[2] = 0x3c6ef372;
@ -99,9 +96,6 @@ void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
UINT32 bytes = ctx->buflen; UINT32 bytes = ctx->buflen;
UINTN pad; UINTN pad;
assert(ctx);
assert(resbuf);
/* Now count remaining bytes. */ /* Now count remaining bytes. */
ctx->total64 += bytes; ctx->total64 += bytes;
@ -124,9 +118,6 @@ void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
} }
void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx) { void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx) {
assert(buffer);
assert(ctx);
/* When we already have some bits in our internal buffer concatenate /* When we already have some bits in our internal buffer concatenate
both inputs first. */ both inputs first. */
@ -200,10 +191,6 @@ void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx)
static void sha256_process_block(const void *buffer, UINTN len, struct sha256_ctx *ctx) { static void sha256_process_block(const void *buffer, UINTN len, struct sha256_ctx *ctx) {
const UINT32 *words = buffer; const UINT32 *words = buffer;
UINTN nwords = len / sizeof (UINT32); UINTN nwords = len / sizeof (UINT32);
assert(buffer);
assert(ctx);
UINT32 a = ctx->H[0]; UINT32 a = ctx->H[0];
UINT32 b = ctx->H[1]; UINT32 b = ctx->H[1];
UINT32 c = ctx->H[2]; UINT32 c = ctx->H[2];

View File

@ -111,10 +111,6 @@ static EFIAPI EFI_STATUS security2_policy_authentication (const EFI_SECURITY2_PR
VOID *file_buffer, UINTN file_size, BOOLEAN boot_policy) { VOID *file_buffer, UINTN file_size, BOOLEAN boot_policy) {
EFI_STATUS status; EFI_STATUS status;
assert(this);
assert(device_path);
assert(file_buffer);
/* Chain original security policy */ /* Chain original security policy */
status = uefi_call_wrapper(es2fa, 5, this, device_path, file_buffer, file_size, boot_policy); status = uefi_call_wrapper(es2fa, 5, this, device_path, file_buffer, file_size, boot_policy);
@ -147,9 +143,6 @@ static EFIAPI EFI_STATUS security_policy_authentication (const EFI_SECURITY_PROT
_cleanup_freepool_ CHAR8 *file_buffer = NULL; _cleanup_freepool_ CHAR8 *file_buffer = NULL;
UINTN file_size; UINTN file_size;
assert(this);
assert(device_path_const);
if (!device_path_const) if (!device_path_const)
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;

View File

@ -44,11 +44,6 @@ static EFI_STATUS bmp_parse_header(UINT8 *bmp, UINTN size, struct bmp_dib **ret_
struct bmp_map *map; struct bmp_map *map;
UINTN row_size; UINTN row_size;
assert(bmp);
assert(ret_dib);
assert(ret_map);
assert(pixmap);
if (size < sizeof(struct bmp_file) + sizeof(struct bmp_dib)) if (size < sizeof(struct bmp_file) + sizeof(struct bmp_dib))
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
@ -133,8 +128,6 @@ static EFI_STATUS bmp_parse_header(UINT8 *bmp, UINTN size, struct bmp_dib **ret_
static VOID pixel_blend(UINT32 *dst, const UINT32 source) { static VOID pixel_blend(UINT32 *dst, const UINT32 source) {
UINT32 alpha, src, src_rb, src_g, dst_rb, dst_g, rb, g; UINT32 alpha, src, src_rb, src_g, dst_rb, dst_g, rb, g;
assert(dst);
alpha = (source & 0xff); alpha = (source & 0xff);
/* convert src from RGBA to XRGB */ /* convert src from RGBA to XRGB */
@ -159,11 +152,6 @@ static EFI_STATUS bmp_to_blt(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *buf,
UINT8 *pixmap) { UINT8 *pixmap) {
UINT8 *in; UINT8 *in;
assert(buf);
assert(dib);
assert(map);
assert(pixmap);
/* transform and copy pixels */ /* transform and copy pixels */
in = pixmap; in = pixmap;
for (UINTN y = 0; y < dib->y; y++) { for (UINTN y = 0; y < dib->y; y++) {
@ -259,8 +247,6 @@ EFI_STATUS graphics_splash(UINT8 *content, UINTN len, const EFI_GRAPHICS_OUTPUT_
UINTN y_pos = 0; UINTN y_pos = 0;
EFI_STATUS err; EFI_STATUS err;
assert(content);
if (!background) { if (!background) {
if (StriCmp(L"Apple", ST->FirmwareVendor) == 0) { if (StriCmp(L"Apple", ST->FirmwareVendor) == 0) {
pixel.Red = 0xc0; pixel.Red = 0xc0;

View File

@ -36,12 +36,18 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image, err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err); Print(L"Error getting a LoadedImageProtocol handle: %r ", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs); err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs);
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
return log_error_status_stall(err, L"Unable to locate embedded .linux section: %r", err); Print(L"Unable to locate embedded .linux section: %r ", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
if (szs[0] > 0) if (szs[0] > 0)
cmdline = (CHAR8 *)(loaded_image->ImageBase) + addrs[0]; cmdline = (CHAR8 *)(loaded_image->ImageBase) + addrs[0];
@ -66,8 +72,10 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = tpm_log_event(SD_TPM_PCR, err = tpm_log_event(SD_TPM_PCR,
(EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions, (EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions,
loaded_image->LoadOptionsSize, loaded_image->LoadOptions); loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
if (EFI_ERROR(err)) if (EFI_ERROR(err)) {
log_error_stall(L"Unable to add image options measurement: %r", err); Print(L"Unable to add image options measurement: %r", err);
uefi_call_wrapper(BS->Stall, 1, 200 * 1000);
}
#endif #endif
} }
@ -118,5 +126,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
(UINTN)loaded_image->ImageBase + addrs[2], szs[2]); (UINTN)loaded_image->ImageBase + addrs[2], szs[2]);
graphics_mode(FALSE); graphics_mode(FALSE);
return log_error_status_stall(err, L"Execution of embedded linux image failed: %r", err); Print(L"Execution of embedded linux image failed: %r\n", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
} }

View File

@ -67,17 +67,13 @@ UINT64 time_usec(VOID) {
} }
EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b) { EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b) {
assert(b);
if (!v) if (!v)
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
if (strcmpa(v, (CHAR8 *)"1") == 0 || if (strcmpa(v, (CHAR8 *)"1") == 0 ||
strcmpa(v, (CHAR8 *)"yes") == 0 || strcmpa(v, (CHAR8 *)"yes") == 0 ||
strcmpa(v, (CHAR8 *)"y") == 0 || strcmpa(v, (CHAR8 *)"y") == 0 ||
strcmpa(v, (CHAR8 *)"true") == 0 || strcmpa(v, (CHAR8 *)"true") == 0) {
strcmpa(v, (CHAR8 *)"t") == 0 ||
strcmpa(v, (CHAR8 *)"on") == 0) {
*b = TRUE; *b = TRUE;
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -85,9 +81,7 @@ EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b) {
if (strcmpa(v, (CHAR8 *)"0") == 0 || if (strcmpa(v, (CHAR8 *)"0") == 0 ||
strcmpa(v, (CHAR8 *)"no") == 0 || strcmpa(v, (CHAR8 *)"no") == 0 ||
strcmpa(v, (CHAR8 *)"n") == 0 || strcmpa(v, (CHAR8 *)"n") == 0 ||
strcmpa(v, (CHAR8 *)"false") == 0 || strcmpa(v, (CHAR8 *)"false") == 0) {
strcmpa(v, (CHAR8 *)"f") == 0 ||
strcmpa(v, (CHAR8 *)"off") == 0) {
*b = FALSE; *b = FALSE;
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -96,37 +90,24 @@ EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b) {
} }
EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, UINT32 flags) { EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, UINT32 flags) {
assert(vendor);
assert(name);
assert(buf || size == 0);
flags |= EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; flags |= EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
return uefi_call_wrapper(RT->SetVariable, 5, (CHAR16*) name, (EFI_GUID *)vendor, flags, size, (VOID*) buf); return uefi_call_wrapper(RT->SetVariable, 5, (CHAR16*) name, (EFI_GUID *)vendor, flags, size, (VOID*) buf);
} }
EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, UINT32 flags) { EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, UINT32 flags) {
assert(vendor); return efivar_set_raw(vendor, name, value, value ? (StrLen(value) + 1) * sizeof(CHAR16) : 0, flags);
assert(name);
return efivar_set_raw(vendor, name, value, value ? StrSize(value) : 0, flags);
} }
EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN i, UINT32 flags) { EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN i, UINT32 flags) {
CHAR16 str[32]; CHAR16 str[32];
assert(vendor); SPrint(str, 32, L"%u", i);
assert(name);
SPrint(str, ELEMENTSOF(str), L"%u", i);
return efivar_set(vendor, name, str, flags); return efivar_set(vendor, name, str, flags);
} }
EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT32 value, UINT32 flags) { EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT32 value, UINT32 flags) {
UINT8 buf[4]; UINT8 buf[4];
assert(vendor);
assert(name);
buf[0] = (UINT8)(value >> 0U & 0xFF); buf[0] = (UINT8)(value >> 0U & 0xFF);
buf[1] = (UINT8)(value >> 8U & 0xFF); buf[1] = (UINT8)(value >> 8U & 0xFF);
buf[2] = (UINT8)(value >> 16U & 0xFF); buf[2] = (UINT8)(value >> 16U & 0xFF);
@ -138,9 +119,6 @@ EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT
EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 value, UINT32 flags) { EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 value, UINT32 flags) {
UINT8 buf[8]; UINT8 buf[8];
assert(vendor);
assert(name);
buf[0] = (UINT8)(value >> 0U & 0xFF); buf[0] = (UINT8)(value >> 0U & 0xFF);
buf[1] = (UINT8)(value >> 8U & 0xFF); buf[1] = (UINT8)(value >> 8U & 0xFF);
buf[2] = (UINT8)(value >> 16U & 0xFF); buf[2] = (UINT8)(value >> 16U & 0xFF);
@ -154,38 +132,35 @@ EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT
} }
EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value) { EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value) {
_cleanup_freepool_ CHAR16 *buf = NULL; _cleanup_freepool_ CHAR8 *buf = NULL;
EFI_STATUS err; EFI_STATUS err;
CHAR16 *val; CHAR16 *val;
UINTN size; UINTN size;
assert(vendor); err = efivar_get_raw(vendor, name, &buf, &size);
assert(name);
err = efivar_get_raw(vendor, name, (CHAR8**)&buf, &size);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return err; return err;
/* Make sure there are no incomplete characters in the buffer */ /* Make sure there are no incomplete characters in the buffer */
if ((size % sizeof(CHAR16)) != 0) if ((size % 2) != 0)
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
if (!value) if (!value)
return EFI_SUCCESS; return EFI_SUCCESS;
/* Return buffer directly if it happens to be NUL terminated already */ /* Return buffer directly if it happens to be NUL terminated already */
if (size >= sizeof(CHAR16) && buf[size/sizeof(CHAR16)] == 0) { if (size >= 2 && buf[size-2] == 0 && buf[size-1] == 0) {
*value = TAKE_PTR(buf); *value = (CHAR16*) TAKE_PTR(buf);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
/* Make sure a terminating NUL is available at the end */ /* Make sure a terminating NUL is available at the end */
val = AllocatePool(size + sizeof(CHAR16)); val = AllocatePool(size + 2);
if (!val) if (!val)
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;
CopyMem(val, buf, size); CopyMem(val, buf, size);
val[size / sizeof(CHAR16)] = 0; /* NUL terminate */ val[size/2] = 0; /* NUL terminate */
*value = val; *value = val;
return EFI_SUCCESS; return EFI_SUCCESS;
@ -195,12 +170,8 @@ EFI_STATUS efivar_get_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UI
_cleanup_freepool_ CHAR16 *val = NULL; _cleanup_freepool_ CHAR16 *val = NULL;
EFI_STATUS err; EFI_STATUS err;
assert(vendor);
assert(name);
assert(i);
err = efivar_get(vendor, name, &val); err = efivar_get(vendor, name, &val);
if (!EFI_ERROR(err)) if (!EFI_ERROR(err) && i)
*i = Atoi(val); *i = Atoi(val);
return err; return err;
@ -211,9 +182,6 @@ EFI_STATUS efivar_get_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT
UINTN size; UINTN size;
EFI_STATUS err; EFI_STATUS err;
assert(vendor);
assert(name);
err = efivar_get_raw(vendor, name, &buf, &size); err = efivar_get_raw(vendor, name, &buf, &size);
if (!EFI_ERROR(err) && ret) { if (!EFI_ERROR(err) && ret) {
if (size != sizeof(UINT32)) if (size != sizeof(UINT32))
@ -231,9 +199,6 @@ EFI_STATUS efivar_get_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT
UINTN size; UINTN size;
EFI_STATUS err; EFI_STATUS err;
assert(vendor);
assert(name);
err = efivar_get_raw(vendor, name, &buf, &size); err = efivar_get_raw(vendor, name, &buf, &size);
if (!EFI_ERROR(err) && ret) { if (!EFI_ERROR(err) && ret) {
if (size != sizeof(UINT64)) if (size != sizeof(UINT64))
@ -252,9 +217,6 @@ EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **bu
UINTN l; UINTN l;
EFI_STATUS err; EFI_STATUS err;
assert(vendor);
assert(name);
l = sizeof(CHAR16 *) * EFI_MAXIMUM_VARIABLE_SIZE; l = sizeof(CHAR16 *) * EFI_MAXIMUM_VARIABLE_SIZE;
buf = AllocatePool(l); buf = AllocatePool(l);
if (!buf) if (!buf)
@ -278,10 +240,6 @@ EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const CHAR16 *name, BOO
UINTN size; UINTN size;
EFI_STATUS err; EFI_STATUS err;
assert(vendor);
assert(name);
assert(ret);
err = efivar_get_raw(vendor, name, &b, &size); err = efivar_get_raw(vendor, name, &b, &size);
if (!EFI_ERROR(err)) if (!EFI_ERROR(err))
*ret = *b > 0; *ret = *b > 0;
@ -292,15 +250,12 @@ EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const CHAR16 *name, BOO
VOID efivar_set_time_usec(const EFI_GUID *vendor, const CHAR16 *name, UINT64 usec) { VOID efivar_set_time_usec(const EFI_GUID *vendor, const CHAR16 *name, UINT64 usec) {
CHAR16 str[32]; CHAR16 str[32];
assert(vendor);
assert(name);
if (usec == 0) if (usec == 0)
usec = time_usec(); usec = time_usec();
if (usec == 0) if (usec == 0)
return; return;
SPrint(str, ELEMENTSOF(str), L"%ld", usec); SPrint(str, 32, L"%ld", usec);
efivar_set(vendor, name, str, 0); efivar_set(vendor, name, str, 0);
} }
@ -308,9 +263,6 @@ static INTN utf8_to_16(const CHAR8 *stra, CHAR16 *c) {
CHAR16 unichar; CHAR16 unichar;
UINTN len; UINTN len;
assert(stra);
assert(c);
if (!(stra[0] & 0x80)) if (!(stra[0] & 0x80))
len = 1; len = 1;
else if ((stra[0] & 0xe0) == 0xc0) else if ((stra[0] & 0xe0) == 0xc0)
@ -364,8 +316,6 @@ CHAR16 *stra_to_str(const CHAR8 *stra) {
UINTN i; UINTN i;
CHAR16 *str; CHAR16 *str;
assert(stra);
len = strlena(stra); len = strlena(stra);
str = AllocatePool((len + 1) * sizeof(CHAR16)); str = AllocatePool((len + 1) * sizeof(CHAR16));
@ -394,8 +344,6 @@ CHAR16 *stra_to_path(const CHAR8 *stra) {
UINTN len; UINTN len;
UINTN i; UINTN i;
assert(stra);
len = strlena(stra); len = strlena(stra);
str = AllocatePool((len + 2) * sizeof(CHAR16)); str = AllocatePool((len + 2) * sizeof(CHAR16));
@ -428,7 +376,6 @@ CHAR16 *stra_to_path(const CHAR8 *stra) {
} }
CHAR8 *strchra(const CHAR8 *s, CHAR8 c) { CHAR8 *strchra(const CHAR8 *s, CHAR8 c) {
assert(s);
do { do {
if (*s == c) if (*s == c)
return (CHAR8*) s; return (CHAR8*) s;
@ -441,9 +388,6 @@ EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN s
_cleanup_freepool_ CHAR8 *buf = NULL; _cleanup_freepool_ CHAR8 *buf = NULL;
EFI_STATUS err; EFI_STATUS err;
assert(name);
assert(ret);
err = uefi_call_wrapper(dir->Open, 5, dir, &handle, (CHAR16*) name, EFI_FILE_MODE_READ, 0ULL); err = uefi_call_wrapper(dir->Open, 5, dir, &handle, (CHAR16*) name, EFI_FILE_MODE_READ, 0ULL);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return err; return err;
@ -481,23 +425,8 @@ EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN s
return err; return err;
} }
VOID log_error_stall(const CHAR16 *fmt, ...) {
va_list args;
assert(fmt);
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTRED|EFI_BACKGROUND_BLACK);
Print(L"\n");
va_start(args, fmt);
VPrint(fmt, args);
va_end(args);
Print(L"\n");
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
}
EFI_STATUS log_oom(void) { EFI_STATUS log_oom(void) {
log_error_stall(L"Out of memory."); Print(L"Out of memory.");
(void) uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;
} }

View File

@ -74,13 +74,4 @@ static inline void FileHandleClosep(EFI_FILE_HANDLE *handle) {
#define UINT64_MAX ((UINT64) -1) #define UINT64_MAX ((UINT64) -1)
#endif #endif
VOID log_error_stall(const CHAR16 *fmt, ...);
EFI_STATUS log_oom(void); EFI_STATUS log_oom(void);
/* This works just like log_error_errno() from userspace, but requires you
* to provide err a second time if you want to use %r in the message! */
#define log_error_status_stall(err, fmt, ...) \
({ \
log_error_stall(fmt, ##__VA_ARGS__); \
err; \
})

View File

@ -1541,7 +1541,7 @@ Manager* manager_free(Manager *m) {
static void manager_enumerate_perpetual(Manager *m) { static void manager_enumerate_perpetual(Manager *m) {
assert(m); assert(m);
if (FLAGS_SET(m->test_run_flags, MANAGER_TEST_RUN_MINIMAL)) if (m->test_run_flags == MANAGER_TEST_RUN_MINIMAL)
return; return;
/* Let's ask every type to load all units from disk/kernel that it might know */ /* Let's ask every type to load all units from disk/kernel that it might know */
@ -1559,7 +1559,7 @@ static void manager_enumerate_perpetual(Manager *m) {
static void manager_enumerate(Manager *m) { static void manager_enumerate(Manager *m) {
assert(m); assert(m);
if (FLAGS_SET(m->test_run_flags, MANAGER_TEST_RUN_MINIMAL)) if (m->test_run_flags == MANAGER_TEST_RUN_MINIMAL)
return; return;
/* Let's ask every type to load all units from disk/kernel that it might know */ /* Let's ask every type to load all units from disk/kernel that it might know */

View File

@ -133,7 +133,6 @@ typedef enum ManagerTestRunFlags {
MANAGER_TEST_RUN_BASIC = 1 << 1, /* interact with the environment */ MANAGER_TEST_RUN_BASIC = 1 << 1, /* interact with the environment */
MANAGER_TEST_RUN_ENV_GENERATORS = 1 << 2, /* also run env generators */ MANAGER_TEST_RUN_ENV_GENERATORS = 1 << 2, /* also run env generators */
MANAGER_TEST_RUN_GENERATORS = 1 << 3, /* also run unit generators */ MANAGER_TEST_RUN_GENERATORS = 1 << 3, /* also run unit generators */
MANAGER_TEST_RUN_IGNORE_DEPENDENCIES = 1 << 4, /* run while ignoring dependencies */
MANAGER_TEST_FULL = MANAGER_TEST_RUN_BASIC | MANAGER_TEST_RUN_ENV_GENERATORS | MANAGER_TEST_RUN_GENERATORS, MANAGER_TEST_FULL = MANAGER_TEST_RUN_BASIC | MANAGER_TEST_RUN_ENV_GENERATORS | MANAGER_TEST_RUN_GENERATORS,
} ManagerTestRunFlags; } ManagerTestRunFlags;

View File

@ -3053,9 +3053,6 @@ int unit_add_dependency(
return 0; return 0;
} }
if (u->manager && FLAGS_SET(u->manager->test_run_flags, MANAGER_TEST_RUN_IGNORE_DEPENDENCIES))
return 0;
/* Note that ordering a device unit after a unit is permitted since it allows to start its job /* Note that ordering a device unit after a unit is permitted since it allows to start its job
* running timeout at a specific time. */ * running timeout at a specific time. */
if (FLAGS_SET(a, UNIT_ATOM_BEFORE) && other->type == UNIT_DEVICE) { if (FLAGS_SET(a, UNIT_ATOM_BEFORE) && other->type == UNIT_DEVICE) {
@ -3179,9 +3176,6 @@ int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, boo
if (r < 0) if (r < 0)
return r; return r;
if (u->manager && FLAGS_SET(u->manager->test_run_flags, MANAGER_TEST_RUN_IGNORE_DEPENDENCIES))
return 0;
r = manager_load_unit(u->manager, name, NULL, NULL, &other); r = manager_load_unit(u->manager, name, NULL, NULL, &other);
if (r < 0) if (r < 0)
return r; return r;
@ -3201,9 +3195,6 @@ int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency
if (r < 0) if (r < 0)
return r; return r;
if (u->manager && FLAGS_SET(u->manager->test_run_flags, MANAGER_TEST_RUN_IGNORE_DEPENDENCIES))
return 0;
r = manager_load_unit(u->manager, name, NULL, NULL, &other); r = manager_load_unit(u->manager, name, NULL, NULL, &other);
if (r < 0) if (r < 0)
return r; return r;
@ -3321,9 +3312,6 @@ int unit_set_default_slice(Unit *u) {
assert(u); assert(u);
if (u->manager && FLAGS_SET(u->manager->test_run_flags, MANAGER_TEST_RUN_IGNORE_DEPENDENCIES))
return 0;
if (UNIT_GET_SLICE(u)) if (UNIT_GET_SLICE(u))
return 0; return 0;

View File

@ -14,22 +14,6 @@
#define _used_ __attribute__((__used__)) #define _used_ __attribute__((__used__))
#define _unused_ __attribute__((__unused__)) #define _unused_ __attribute__((__unused__))
#define _cleanup_(x) __attribute__((__cleanup__(x))) #define _cleanup_(x) __attribute__((__cleanup__(x)))
#define _likely_(x) (__builtin_expect(!!(x), 1))
#define _unlikely_(x) (__builtin_expect(!!(x), 0))
#if __GNUC__ >= 7
#define _fallthrough_ __attribute__((__fallthrough__))
#else
#define _fallthrough_
#endif
/* Define C11 noreturn without <stdnoreturn.h> and even on older gcc
* compiler versions */
#ifndef _noreturn_
#if __STDC_VERSION__ >= 201112L
#define _noreturn_ _Noreturn
#else
#define _noreturn_ __attribute__((__noreturn__))
#endif
#endif
#define XSTRINGIFY(x) #x #define XSTRINGIFY(x) #x
#define STRINGIFY(x) XSTRINGIFY(x) #define STRINGIFY(x) XSTRINGIFY(x)
@ -50,14 +34,7 @@
#define CONCATENATE(x, y) XCONCATENATE(x, y) #define CONCATENATE(x, y) XCONCATENATE(x, y)
#ifdef SD_BOOT #ifdef SD_BOOT
#ifdef NDEBUG #define assert(expr) do {} while (false)
#define assert(expr)
#define assert_not_reached() __builtin_unreachable()
#else
void efi_assert(const char *expr, const char *file, unsigned line, const char *function) _noreturn_;
#define assert(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); })
#define assert_not_reached() efi_assert("Code should not be reached", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#endif
#endif #endif
#if defined(static_assert) #if defined(static_assert)
@ -256,10 +233,3 @@
(ptr) = NULL; \ (ptr) = NULL; \
_ptr_; \ _ptr_; \
}) })
/*
* STRLEN - return the length of a string literal, minus the trailing NUL byte.
* Contrary to strlen(), this is a constant expression.
* @x: a string literal.
*/
#define STRLEN(x) (sizeof(""x"") - sizeof(typeof(x[0])))

View File

@ -29,7 +29,7 @@ static int bare_udp_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *
log_netdev_info(netdev, "BareUDP netdev exists, using existing without changing its parameters."); log_netdev_info(netdev, "BareUDP netdev exists, using existing without changing its parameters.");
else if (r < 0) { else if (r < 0) {
log_netdev_warning_errno(netdev, r, "BareUDP netdev could not be created: %m"); log_netdev_warning_errno(netdev, r, "BareUDP netdev could not be created: %m");
netdev_enter_failed(netdev); netdev_drop(netdev);
return 1; return 1;
} }

View File

@ -108,7 +108,7 @@ static int fou_tunnel_create_handler(sd_netlink *rtnl, sd_netlink_message *m, Ne
log_netdev_info(netdev, "netdev exists, using existing without changing its parameters"); log_netdev_info(netdev, "netdev exists, using existing without changing its parameters");
else if (r < 0) { else if (r < 0) {
log_netdev_warning_errno(netdev, r, "netdev could not be created: %m"); log_netdev_warning_errno(netdev, r, "netdev could not be created: %m");
netdev_enter_failed(netdev); netdev_drop(netdev);
return 1; return 1;
} }

View File

@ -37,7 +37,7 @@ static int geneve_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m,
log_netdev_info(netdev, "Geneve netdev exists, using existing without changing its parameters"); log_netdev_info(netdev, "Geneve netdev exists, using existing without changing its parameters");
else if (r < 0) { else if (r < 0) {
log_netdev_warning_errno(netdev, r, "Geneve netdev could not be created: %m"); log_netdev_warning_errno(netdev, r, "Geneve netdev could not be created: %m");
netdev_enter_failed(netdev); netdev_drop(netdev);
return 1; return 1;
} }

View File

@ -355,7 +355,7 @@ static int l2tp_create_tunnel_handler(sd_netlink *rtnl, sd_netlink_message *m, N
log_netdev_info(netdev, "netdev exists, using existing without changing its parameters"); log_netdev_info(netdev, "netdev exists, using existing without changing its parameters");
else if (r < 0) { else if (r < 0) {
log_netdev_warning_errno(netdev, r, "netdev could not be created: %m"); log_netdev_warning_errno(netdev, r, "netdev could not be created: %m");
netdev_enter_failed(netdev); netdev_drop(netdev);
return 1; return 1;
} }

View File

@ -317,7 +317,7 @@ static int macsec_receive_association_handler(sd_netlink *rtnl, sd_netlink_messa
else if (r < 0) { else if (r < 0) {
log_netdev_warning_errno(netdev, r, log_netdev_warning_errno(netdev, r,
"Failed to add receive secure association: %m"); "Failed to add receive secure association: %m");
netdev_enter_failed(netdev); netdev_drop(netdev);
return 1; return 1;
} }
@ -375,7 +375,7 @@ static int macsec_receive_channel_handler(sd_netlink *rtnl, sd_netlink_message *
else if (r < 0) { else if (r < 0) {
log_netdev_warning_errno(netdev, r, log_netdev_warning_errno(netdev, r,
"Failed to add receive secure channel: %m"); "Failed to add receive secure channel: %m");
netdev_enter_failed(netdev); netdev_drop(netdev);
return 1; return 1;
} }
@ -387,7 +387,7 @@ static int macsec_receive_channel_handler(sd_netlink *rtnl, sd_netlink_message *
if (r < 0) { if (r < 0) {
log_netdev_warning_errno(netdev, r, log_netdev_warning_errno(netdev, r,
"Failed to configure receive security association: %m"); "Failed to configure receive security association: %m");
netdev_enter_failed(netdev); netdev_drop(netdev);
return 1; return 1;
} }
} }
@ -441,7 +441,7 @@ static int macsec_transmit_association_handler(sd_netlink *rtnl, sd_netlink_mess
else if (r < 0) { else if (r < 0) {
log_netdev_warning_errno(netdev, r, log_netdev_warning_errno(netdev, r,
"Failed to add transmit secure association: %m"); "Failed to add transmit secure association: %m");
netdev_enter_failed(netdev); netdev_drop(netdev);
return 1; return 1;
} }

View File

@ -167,54 +167,6 @@ bool netdev_is_managed(NetDev *netdev) {
return hashmap_get(netdev->manager->netdevs, netdev->ifname) == netdev; return hashmap_get(netdev->manager->netdevs, netdev->ifname) == netdev;
} }
static bool netdev_is_stacked_and_independent(NetDev *netdev) {
assert(netdev);
if (!IN_SET(netdev_get_create_type(netdev), NETDEV_CREATE_STACKED, NETDEV_CREATE_AFTER_CONFIGURED))
return false;
switch (netdev->kind) {
case NETDEV_KIND_ERSPAN:
return ERSPAN(netdev)->independent;
case NETDEV_KIND_GRE:
return GRE(netdev)->independent;
case NETDEV_KIND_GRETAP:
return GRETAP(netdev)->independent;
case NETDEV_KIND_IP6GRE:
return IP6GRE(netdev)->independent;
case NETDEV_KIND_IP6GRETAP:
return IP6GRETAP(netdev)->independent;
case NETDEV_KIND_IP6TNL:
return IP6TNL(netdev)->independent;
case NETDEV_KIND_IPIP:
return IPIP(netdev)->independent;
case NETDEV_KIND_SIT:
return SIT(netdev)->independent;
case NETDEV_KIND_VTI:
return VTI(netdev)->independent;
case NETDEV_KIND_VTI6:
return VTI6(netdev)->independent;
case NETDEV_KIND_VXLAN:
return VXLAN(netdev)->independent;
case NETDEV_KIND_XFRM:
return XFRM(netdev)->independent;
default:
return false;
}
}
static bool netdev_is_stacked(NetDev *netdev) {
assert(netdev);
if (!IN_SET(netdev_get_create_type(netdev), NETDEV_CREATE_STACKED, NETDEV_CREATE_AFTER_CONFIGURED))
return false;
if (netdev_is_stacked_and_independent(netdev))
return false;
return true;
}
static void netdev_detach_from_manager(NetDev *netdev) { static void netdev_detach_from_manager(NetDev *netdev) {
if (netdev->ifname && netdev->manager) if (netdev->ifname && netdev->manager)
hashmap_remove(netdev->manager->netdevs, netdev->ifname); hashmap_remove(netdev->manager->netdevs, netdev->ifname);
@ -250,19 +202,9 @@ static NetDev *netdev_free(NetDev *netdev) {
DEFINE_TRIVIAL_REF_UNREF_FUNC(NetDev, netdev, netdev_free); DEFINE_TRIVIAL_REF_UNREF_FUNC(NetDev, netdev, netdev_free);
void netdev_drop(NetDev *netdev) { void netdev_drop(NetDev *netdev) {
if (!netdev) if (!netdev || netdev->state == NETDEV_STATE_LINGER)
return; return;
if (netdev_is_stacked(netdev)) {
/* The netdev may be removed due to the underlying device removal, and the device may
* be re-added later. */
netdev->state = NETDEV_STATE_LOADING;
netdev->ifindex = 0;
log_netdev_debug(netdev, "netdev removed");
return;
}
netdev->state = NETDEV_STATE_LINGER; netdev->state = NETDEV_STATE_LINGER;
log_netdev_debug(netdev, "netdev removed"); log_netdev_debug(netdev, "netdev removed");
@ -290,8 +232,9 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) {
return 0; return 0;
} }
void netdev_enter_failed(NetDev *netdev) { static int netdev_enter_failed(NetDev *netdev) {
netdev->state = NETDEV_STATE_FAILED; netdev->state = NETDEV_STATE_FAILED;
return 0;
} }
static int netdev_enter_ready(NetDev *netdev) { static int netdev_enter_ready(NetDev *netdev) {
@ -323,7 +266,7 @@ static int netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev
log_netdev_info(netdev, "netdev exists, using existing without changing its parameters"); log_netdev_info(netdev, "netdev exists, using existing without changing its parameters");
else if (r < 0) { else if (r < 0) {
log_netdev_warning_errno(netdev, r, "netdev could not be created: %m"); log_netdev_warning_errno(netdev, r, "netdev could not be created: %m");
netdev_enter_failed(netdev); netdev_drop(netdev);
return 1; return 1;
} }
@ -617,12 +560,12 @@ static bool netdev_is_ready_to_create(NetDev *netdev, Link *link) {
return true; return true;
} }
int request_process_stacked_netdev(Request *req) { int request_process_create_stacked_netdev(Request *req) {
int r; int r;
assert(req); assert(req);
assert(req->link); assert(req->link);
assert(req->type == REQUEST_TYPE_STACKED_NETDEV); assert(req->type == REQUEST_TYPE_CREATE_STACKED_NETDEV);
assert(req->netdev); assert(req->netdev);
assert(req->netlink_handler); assert(req->netlink_handler);
@ -689,42 +632,46 @@ static int link_create_stacked_netdev_after_configured_handler(sd_netlink *rtnl,
return 0; return 0;
} }
int link_request_stacked_netdev(Link *link, NetDev *netdev) { int link_request_to_crate_stacked_netdev(Link *link, NetDev *netdev) {
NetDevCreateType create_type;
int r; int r;
assert(link); assert(link);
assert(netdev); assert(netdev);
if (!netdev_is_stacked(netdev)) create_type = netdev_get_create_type(netdev);
if (!IN_SET(create_type, NETDEV_CREATE_STACKED, NETDEV_CREATE_AFTER_CONFIGURED))
return -EINVAL; return -EINVAL;
if (!IN_SET(netdev->state, NETDEV_STATE_LOADING, NETDEV_STATE_FAILED) || netdev->ifindex > 0) if (netdev->state != NETDEV_STATE_LOADING || netdev->ifindex > 0)
return 0; /* Already created. */ /* Already created (or removed?) */
return 0;
if (netdev_get_create_type(netdev) == NETDEV_CREATE_STACKED) { if (create_type == NETDEV_CREATE_STACKED) {
link->stacked_netdevs_created = false; link->stacked_netdevs_created = false;
r = link_queue_request(link, REQUEST_TYPE_STACKED_NETDEV, netdev, false, r = link_queue_request(link, REQUEST_TYPE_CREATE_STACKED_NETDEV, netdev, false,
&link->create_stacked_netdev_messages, &link->create_stacked_netdev_messages,
link_create_stacked_netdev_handler, link_create_stacked_netdev_handler,
NULL); NULL);
} else { } else {
link->stacked_netdevs_after_configured_created = false; link->stacked_netdevs_after_configured_created = false;
r = link_queue_request(link, REQUEST_TYPE_STACKED_NETDEV, netdev, false, r = link_queue_request(link, REQUEST_TYPE_CREATE_STACKED_NETDEV, netdev, false,
&link->create_stacked_netdev_after_configured_messages, &link->create_stacked_netdev_after_configured_messages,
link_create_stacked_netdev_after_configured_handler, link_create_stacked_netdev_after_configured_handler,
NULL); NULL);
} }
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to request stacked netdev '%s': %m", return log_link_error_errno(link, r, "Failed to request to create stacked netdev '%s': %m",
netdev->ifname); netdev->ifname);
log_link_debug(link, "Requested stacked netdev '%s'", netdev->ifname); log_link_debug(link, "Requested to create stacked netdev '%s'", netdev->ifname);
return 0; return 0;
} }
int netdev_load_one(Manager *manager, const char *filename) { int netdev_load_one(Manager *manager, const char *filename) {
_cleanup_(netdev_unrefp) NetDev *netdev_raw = NULL, *netdev = NULL; _cleanup_(netdev_unrefp) NetDev *netdev_raw = NULL, *netdev = NULL;
const char *dropin_dirname; const char *dropin_dirname;
bool independent = false;
int r; int r;
assert(manager); assert(manager);
@ -845,7 +792,48 @@ int netdev_load_one(Manager *manager, const char *filename) {
return r; return r;
} }
if (netdev_is_stacked_and_independent(netdev)) { switch (netdev->kind) {
case NETDEV_KIND_IPIP:
independent = IPIP(netdev)->independent;
break;
case NETDEV_KIND_GRE:
independent = GRE(netdev)->independent;
break;
case NETDEV_KIND_GRETAP:
independent = GRETAP(netdev)->independent;
break;
case NETDEV_KIND_IP6GRE:
independent = IP6GRE(netdev)->independent;
break;
case NETDEV_KIND_IP6GRETAP:
independent = IP6GRETAP(netdev)->independent;
break;
case NETDEV_KIND_SIT:
independent = SIT(netdev)->independent;
break;
case NETDEV_KIND_VTI:
independent = VTI(netdev)->independent;
break;
case NETDEV_KIND_VTI6:
independent = VTI6(netdev)->independent;
break;
case NETDEV_KIND_IP6TNL:
independent = IP6TNL(netdev)->independent;
break;
case NETDEV_KIND_ERSPAN:
independent = ERSPAN(netdev)->independent;
break;
case NETDEV_KIND_XFRM:
independent = XFRM(netdev)->independent;
break;
case NETDEV_KIND_VXLAN:
independent = VXLAN(netdev)->independent;
break;
default:
break;
}
if (independent) {
r = netdev_create(netdev, NULL, NULL); r = netdev_create(netdev, NULL, NULL);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -184,7 +184,6 @@ extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX];
int netdev_load(Manager *manager, bool reload); int netdev_load(Manager *manager, bool reload);
int netdev_load_one(Manager *manager, const char *filename); int netdev_load_one(Manager *manager, const char *filename);
void netdev_drop(NetDev *netdev); void netdev_drop(NetDev *netdev);
void netdev_enter_failed(NetDev *netdev);
NetDev *netdev_unref(NetDev *netdev); NetDev *netdev_unref(NetDev *netdev);
NetDev *netdev_ref(NetDev *netdev); NetDev *netdev_ref(NetDev *netdev);
@ -197,8 +196,8 @@ int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink);
int netdev_get_mac(const char *ifname, struct ether_addr **ret); int netdev_get_mac(const char *ifname, struct ether_addr **ret);
int netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t cb); int netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t cb);
int request_process_stacked_netdev(Request *req); int request_process_create_stacked_netdev(Request *req);
int link_request_stacked_netdev(Link *link, NetDev *netdev); int link_request_to_crate_stacked_netdev(Link *link, NetDev *netdev);
const char *netdev_kind_to_string(NetDevKind d) _const_; const char *netdev_kind_to_string(NetDevKind d) _const_;
NetDevKind netdev_kind_from_string(const char *d) _pure_; NetDevKind netdev_kind_from_string(const char *d) _pure_;

View File

@ -594,7 +594,7 @@ static int link_request_stacked_netdevs(Link *link) {
link->stacked_netdevs_after_configured_created = false; link->stacked_netdevs_after_configured_created = false;
HASHMAP_FOREACH(netdev, link->network->stacked_netdevs) { HASHMAP_FOREACH(netdev, link->network->stacked_netdevs) {
r = link_request_stacked_netdev(link, netdev); r = link_request_to_crate_stacked_netdev(link, netdev);
if (r < 0) if (r < 0)
return r; return r;
} }

View File

@ -32,6 +32,8 @@ static void request_free_object(RequestType type, void *object) {
case REQUEST_TYPE_BRIDGE_MDB: case REQUEST_TYPE_BRIDGE_MDB:
bridge_mdb_free(object); bridge_mdb_free(object);
break; break;
case REQUEST_TYPE_CREATE_STACKED_NETDEV:
break;
case REQUEST_TYPE_DHCP_SERVER: case REQUEST_TYPE_DHCP_SERVER:
case REQUEST_TYPE_DHCP4_CLIENT: case REQUEST_TYPE_DHCP4_CLIENT:
case REQUEST_TYPE_DHCP6_CLIENT: case REQUEST_TYPE_DHCP6_CLIENT:
@ -54,7 +56,6 @@ static void request_free_object(RequestType type, void *object) {
routing_policy_rule_free(object); routing_policy_rule_free(object);
break; break;
case REQUEST_TYPE_SET_LINK: case REQUEST_TYPE_SET_LINK:
case REQUEST_TYPE_STACKED_NETDEV:
case REQUEST_TYPE_UP_DOWN: case REQUEST_TYPE_UP_DOWN:
break; break;
default: default:
@ -109,7 +110,7 @@ static void request_hash_func(const Request *req, struct siphash *state) {
case REQUEST_TYPE_ADDRESS_LABEL: case REQUEST_TYPE_ADDRESS_LABEL:
case REQUEST_TYPE_BRIDGE_FDB: case REQUEST_TYPE_BRIDGE_FDB:
case REQUEST_TYPE_BRIDGE_MDB: case REQUEST_TYPE_BRIDGE_MDB:
case REQUEST_TYPE_STACKED_NETDEV: case REQUEST_TYPE_CREATE_STACKED_NETDEV:
/* TODO: Currently, these types do not have any specific hash and compare functions. /* TODO: Currently, these types do not have any specific hash and compare functions.
* Fortunately, all these objects are 'static', thus we can use the trivial functions. */ * Fortunately, all these objects are 'static', thus we can use the trivial functions. */
trivial_hash_func(req->object, state); trivial_hash_func(req->object, state);
@ -172,7 +173,7 @@ static int request_compare_func(const struct Request *a, const struct Request *b
case REQUEST_TYPE_ADDRESS_LABEL: case REQUEST_TYPE_ADDRESS_LABEL:
case REQUEST_TYPE_BRIDGE_FDB: case REQUEST_TYPE_BRIDGE_FDB:
case REQUEST_TYPE_BRIDGE_MDB: case REQUEST_TYPE_BRIDGE_MDB:
case REQUEST_TYPE_STACKED_NETDEV: case REQUEST_TYPE_CREATE_STACKED_NETDEV:
return trivial_compare_func(a->object, b->object); return trivial_compare_func(a->object, b->object);
case REQUEST_TYPE_DHCP_SERVER: case REQUEST_TYPE_DHCP_SERVER:
case REQUEST_TYPE_DHCP4_CLIENT: case REQUEST_TYPE_DHCP4_CLIENT:
@ -305,6 +306,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
case REQUEST_TYPE_BRIDGE_MDB: case REQUEST_TYPE_BRIDGE_MDB:
r = request_process_bridge_mdb(req); r = request_process_bridge_mdb(req);
break; break;
case REQUEST_TYPE_CREATE_STACKED_NETDEV:
r = request_process_create_stacked_netdev(req);
break;
case REQUEST_TYPE_DHCP_SERVER: case REQUEST_TYPE_DHCP_SERVER:
r = request_process_dhcp_server(req); r = request_process_dhcp_server(req);
break; break;
@ -335,9 +339,6 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
case REQUEST_TYPE_SET_LINK: case REQUEST_TYPE_SET_LINK:
r = request_process_set_link(req); r = request_process_set_link(req);
break; break;
case REQUEST_TYPE_STACKED_NETDEV:
r = request_process_stacked_netdev(req);
break;
case REQUEST_TYPE_UP_DOWN: case REQUEST_TYPE_UP_DOWN:
r = request_process_link_up_or_down(req); r = request_process_link_up_or_down(req);
break; break;

View File

@ -26,6 +26,7 @@ typedef enum RequestType {
REQUEST_TYPE_ADDRESS_LABEL, REQUEST_TYPE_ADDRESS_LABEL,
REQUEST_TYPE_BRIDGE_FDB, REQUEST_TYPE_BRIDGE_FDB,
REQUEST_TYPE_BRIDGE_MDB, REQUEST_TYPE_BRIDGE_MDB,
REQUEST_TYPE_CREATE_STACKED_NETDEV,
REQUEST_TYPE_DHCP_SERVER, REQUEST_TYPE_DHCP_SERVER,
REQUEST_TYPE_DHCP4_CLIENT, REQUEST_TYPE_DHCP4_CLIENT,
REQUEST_TYPE_DHCP6_CLIENT, REQUEST_TYPE_DHCP6_CLIENT,
@ -36,7 +37,6 @@ typedef enum RequestType {
REQUEST_TYPE_ROUTE, REQUEST_TYPE_ROUTE,
REQUEST_TYPE_ROUTING_POLICY_RULE, REQUEST_TYPE_ROUTING_POLICY_RULE,
REQUEST_TYPE_SET_LINK, REQUEST_TYPE_SET_LINK,
REQUEST_TYPE_STACKED_NETDEV,
REQUEST_TYPE_UP_DOWN, REQUEST_TYPE_UP_DOWN,
_REQUEST_TYPE_MAX, _REQUEST_TYPE_MAX,
_REQUEST_TYPE_INVALID = -EINVAL, _REQUEST_TYPE_INVALID = -EINVAL,

View File

@ -362,8 +362,9 @@ void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level
if (s->possible_feature_level > level) { if (s->possible_feature_level > level) {
s->possible_feature_level = level; s->possible_feature_level = level;
dns_server_reset_counters(s); dns_server_reset_counters(s);
log_debug("Downgrading transaction feature level fixed an RCODE error, downgrading server %s too.", strna(dns_server_string_full(s)));
} }
log_debug("Downgrading transaction feature level fixed an RCODE error, downgrading server %s too.", strna(dns_server_string_full(s)));
} }
void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level) { void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level) {

View File

@ -1142,18 +1142,6 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
break; break;
} }
/* SERVFAIL can happen for many reasons and may be transient.
* To avoid unnecessary downgrades retry once with the initial level.
* Check for clamp_feature_level_servfail having an invalid value as a sign that this is the
* first attempt to downgrade. If so, clamp to the current value so that the transaction
* is retried without actually downgrading. If the next try also fails we will downgrade by
* hitting the else branch below. */
if (DNS_PACKET_RCODE(p) == DNS_RCODE_SERVFAIL &&
t->clamp_feature_level_servfail < 0) {
t->clamp_feature_level_servfail = t->current_feature_level;
log_debug("Server returned error %s, retrying transaction.",
dns_rcode_to_string(DNS_PACKET_RCODE(p)));
} else {
/* Reduce this feature level by one and try again. */ /* Reduce this feature level by one and try again. */
switch (t->current_feature_level) { switch (t->current_feature_level) {
case DNS_SERVER_FEATURE_LEVEL_TLS_DO: case DNS_SERVER_FEATURE_LEVEL_TLS_DO:
@ -1170,7 +1158,6 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
log_debug("Server returned error %s, retrying transaction with reduced feature level %s.", log_debug("Server returned error %s, retrying transaction with reduced feature level %s.",
dns_rcode_to_string(DNS_PACKET_RCODE(p)), dns_rcode_to_string(DNS_PACKET_RCODE(p)),
dns_server_feature_level_to_string(t->clamp_feature_level_servfail)); dns_server_feature_level_to_string(t->clamp_feature_level_servfail));
}
dns_transaction_retry(t, false /* use the same server */); dns_transaction_retry(t, false /* use the same server */);
return; return;

View File

@ -7,8 +7,6 @@
/* Do some basic checks on STRLEN() and DECIMAL_STR_MAX() */ /* Do some basic checks on STRLEN() and DECIMAL_STR_MAX() */
assert_cc(STRLEN("xxx") == 3); assert_cc(STRLEN("xxx") == 3);
assert_cc(STRLEN("") == 0); assert_cc(STRLEN("") == 0);
assert_cc(STRLEN(L"xxx") == 3 * sizeof(wchar_t));
assert_cc(STRLEN(L"") == 0);
assert_cc(DECIMAL_STR_MAX(uint8_t) == 5); assert_cc(DECIMAL_STR_MAX(uint8_t) == 5);
assert_cc(DECIMAL_STR_MAX(int8_t) == 5); assert_cc(DECIMAL_STR_MAX(int8_t) == 5);
assert_cc(DECIMAL_STR_MAX(uint64_t) == 22); assert_cc(DECIMAL_STR_MAX(uint64_t) == 22);

View File

@ -1183,25 +1183,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.assertRegex(output, ' mtu 2000 ') self.assertRegex(output, ' mtu 2000 ')
self.assertRegex(output, 'macvlan mode ' + mode + ' ') self.assertRegex(output, 'macvlan mode ' + mode + ' ')
rc = call("ip link del test1")
self.assertEqual(rc, 0)
time.sleep(1)
rc = call("ip link add test1 type dummy")
self.assertEqual(rc, 0)
time.sleep(1)
self.wait_online(['macvlan99:degraded', 'test1:degraded'])
output = check_output('ip -d link show test1')
print(output)
self.assertRegex(output, ' mtu 2000 ')
output = check_output('ip -d link show macvlan99')
print(output)
self.assertRegex(output, ' mtu 2000 ')
self.assertRegex(output, 'macvlan mode ' + mode + ' ')
@expectedFailureIfModuleIsNotAvailable('ipvlan') @expectedFailureIfModuleIsNotAvailable('ipvlan')
def test_ipvlan(self): def test_ipvlan(self):
for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]: for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]: