From 7c4536a9af986332eaac8db292b22d59b4977f04 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 10 Jun 2022 18:55:24 +0200 Subject: [PATCH 1/7] boot: Add printf functions --- src/boot/efi/efi-string.c | 491 +++++++++++++++++++++++++++++++++ src/boot/efi/efi-string.h | 26 ++ src/boot/efi/fuzz-efi-printf.c | 76 +++++ src/boot/efi/meson.build | 1 + src/boot/efi/missing_efi.h | 12 + src/boot/efi/test-efi-string.c | 142 ++++++++++ 6 files changed, 748 insertions(+) create mode 100644 src/boot/efi/fuzz-efi-printf.c diff --git a/src/boot/efi/efi-string.c b/src/boot/efi/efi-string.c index 79c296eda3..860dfc00b2 100644 --- a/src/boot/efi/efi-string.c +++ b/src/boot/efi/efi-string.c @@ -2,10 +2,12 @@ #include #include +#include #include "efi-string.h" #if SD_BOOT +# include "missing_efi.h" # include "util.h" #else # include @@ -378,6 +380,495 @@ bool efi_fnmatch(const char16_t *pattern, const char16_t *haystack) { DEFINE_PARSE_NUMBER(char, parse_number8); DEFINE_PARSE_NUMBER(char16_t, parse_number16); +static const char * const warn_table[] = { + [EFI_SUCCESS] = "Success", +#if SD_BOOT + [EFI_WARN_UNKNOWN_GLYPH] = "Unknown glyph", + [EFI_WARN_DELETE_FAILURE] = "Delete failure", + [EFI_WARN_WRITE_FAILURE] = "Write failure", + [EFI_WARN_BUFFER_TOO_SMALL] = "Buffer too small", + [EFI_WARN_STALE_DATA] = "Stale data", + [EFI_WARN_FILE_SYSTEM] = "File system", + [EFI_WARN_RESET_REQUIRED] = "Reset required", +#endif +}; + +/* Errors have MSB set, remove it to keep the table compact. */ +#define NOERR(err) ((err) & ~EFI_ERROR_MASK) + +static const char * const err_table[] = { + [NOERR(EFI_ERROR_MASK)] = "Error", + [NOERR(EFI_LOAD_ERROR)] = "Load error", +#if SD_BOOT + [NOERR(EFI_INVALID_PARAMETER)] = "Invalid parameter", + [NOERR(EFI_UNSUPPORTED)] = "Unsupported", + [NOERR(EFI_BAD_BUFFER_SIZE)] = "Bad buffer size", + [NOERR(EFI_BUFFER_TOO_SMALL)] = "Buffer too small", + [NOERR(EFI_NOT_READY)] = "Not ready", + [NOERR(EFI_DEVICE_ERROR)] = "Device error", + [NOERR(EFI_WRITE_PROTECTED)] = "Write protected", + [NOERR(EFI_OUT_OF_RESOURCES)] = "Out of resources", + [NOERR(EFI_VOLUME_CORRUPTED)] = "Volume corrupt", + [NOERR(EFI_VOLUME_FULL)] = "Volume full", + [NOERR(EFI_NO_MEDIA)] = "No media", + [NOERR(EFI_MEDIA_CHANGED)] = "Media changed", + [NOERR(EFI_NOT_FOUND)] = "Not found", + [NOERR(EFI_ACCESS_DENIED)] = "Access denied", + [NOERR(EFI_NO_RESPONSE)] = "No response", + [NOERR(EFI_NO_MAPPING)] = "No mapping", + [NOERR(EFI_TIMEOUT)] = "Time out", + [NOERR(EFI_NOT_STARTED)] = "Not started", + [NOERR(EFI_ALREADY_STARTED)] = "Already started", + [NOERR(EFI_ABORTED)] = "Aborted", + [NOERR(EFI_ICMP_ERROR)] = "ICMP error", + [NOERR(EFI_TFTP_ERROR)] = "TFTP error", + [NOERR(EFI_PROTOCOL_ERROR)] = "Protocol error", + [NOERR(EFI_INCOMPATIBLE_VERSION)] = "Incompatible version", + [NOERR(EFI_SECURITY_VIOLATION)] = "Security violation", + [NOERR(EFI_CRC_ERROR)] = "CRC error", + [NOERR(EFI_END_OF_MEDIA)] = "End of media", + [29] = "Reserved (29)", + [30] = "Reserved (30)", + [NOERR(EFI_END_OF_FILE)] = "End of file", + [NOERR(EFI_INVALID_LANGUAGE)] = "Invalid language", + [NOERR(EFI_COMPROMISED_DATA)] = "Compromised data", + [NOERR(EFI_IP_ADDRESS_CONFLICT)] = "IP address conflict", + [NOERR(EFI_HTTP_ERROR)] = "HTTP error", +#endif +}; + +static const char *status_to_string(EFI_STATUS status) { + if (status <= ELEMENTSOF(warn_table) - 1) + return warn_table[status]; + if (status >= EFI_ERROR_MASK && status <= ((ELEMENTSOF(err_table) - 1) | EFI_ERROR_MASK)) + return err_table[NOERR(status)]; + return NULL; +} + +typedef struct { + size_t padded_len; /* Field width in printf. */ + size_t len; /* Precision in printf. */ + bool pad_zero; + bool align_left; + bool alternative_form; + bool long_arg; + bool longlong_arg; + bool have_field_width; + + const char *str; + const wchar_t *wstr; + + /* For numbers. */ + bool is_signed; + bool lowercase; + int8_t base; + char sign_pad; /* For + and (space) flags. */ +} SpecifierContext; + +typedef struct { + char16_t stack_buf[128]; /* We use stack_buf first to avoid allocations in most cases. */ + char16_t *dyn_buf; /* Allocated buf or NULL if stack_buf is used. */ + char16_t *buf; /* Points to the current active buf. */ + size_t n_buf; /* Len of buf (in char16_t's, not bytes!). */ + size_t n; /* Used len of buf (in char16_t's). This is always n, need, &need)); + + if (need < ctx->n_buf) + return; + + /* Greedily allocate if we can. */ + if (__builtin_mul_overflow(need, 2, &ctx->n_buf)) + ctx->n_buf = need; + + /* We cannot use realloc here as ctx->buf may be ctx->stack_buf, which we cannot free. */ + char16_t *new_buf = xnew(char16_t, ctx->n_buf); + memcpy(new_buf, ctx->buf, ctx->n * sizeof(*ctx->buf)); + + free(ctx->dyn_buf); + ctx->buf = ctx->dyn_buf = new_buf; +} + +static void push_padding(FormatContext *ctx, char pad, size_t len) { + assert(ctx); + while (len > 0) { + len--; + ctx->buf[ctx->n++] = pad; + } +} + +static bool push_str(FormatContext *ctx, SpecifierContext *sp) { + assert(ctx); + assert(sp); + + sp->padded_len = LESS_BY(sp->padded_len, sp->len); + + grow_buf(ctx, sp->padded_len + sp->len); + + if (!sp->align_left) + push_padding(ctx, ' ', sp->padded_len); + + /* In userspace unit tests we cannot just memcpy() the wide string. */ + if (sp->wstr && sizeof(wchar_t) == sizeof(char16_t)) { + memcpy(ctx->buf + ctx->n, sp->wstr, sp->len * sizeof(*sp->wstr)); + ctx->n += sp->len; + } else + for (size_t i = 0; i < sp->len; i++) + ctx->buf[ctx->n++] = sp->str ? sp->str[i] : sp->wstr[i]; + + if (sp->align_left) + push_padding(ctx, ' ', sp->padded_len); + + assert(ctx->n < ctx->n_buf); + return true; +} + +static bool push_num(FormatContext *ctx, SpecifierContext *sp, uint64_t u) { + const char *digits = sp->lowercase ? "0123456789abcdef" : "0123456789ABCDEF"; + char16_t tmp[32]; + size_t n = 0; + + assert(ctx); + assert(sp); + assert(IN_SET(sp->base, 10, 16)); + + /* "%.0u" prints nothing if value is 0. */ + if (u == 0 && sp->len == 0) + return true; + + if (sp->is_signed && (int64_t) u < 0) { + /* We cannot just do "u = -(int64_t)u" here because -INT64_MIN overflows. */ + + uint64_t rem = -((int64_t) u % sp->base); + u = (int64_t) u / -sp->base; + tmp[n++] = digits[rem]; + sp->sign_pad = '-'; + } + + while (u > 0 || n == 0) { + uint64_t rem = u % sp->base; + u /= sp->base; + tmp[n++] = digits[rem]; + } + + /* Note that numbers never get truncated! */ + size_t prefix = (sp->sign_pad != 0 ? 1 : 0) + (sp->alternative_form ? 2 : 0); + size_t number_len = prefix + MAX(n, sp->len); + grow_buf(ctx, MAX(sp->padded_len, number_len)); + + size_t padding = 0; + if (sp->pad_zero) + /* Leading zeroes go after the sign or 0x prefix. */ + number_len = MAX(number_len, sp->padded_len); + else + padding = LESS_BY(sp->padded_len, number_len); + + if (!sp->align_left) + push_padding(ctx, ' ', padding); + + if (sp->sign_pad != 0) + ctx->buf[ctx->n++] = sp->sign_pad; + if (sp->alternative_form) { + ctx->buf[ctx->n++] = '0'; + ctx->buf[ctx->n++] = sp->lowercase ? 'x' : 'X'; + } + + push_padding(ctx, '0', LESS_BY(number_len, n + prefix)); + + while (n > 0) + ctx->buf[ctx->n++] = tmp[--n]; + + if (sp->align_left) + push_padding(ctx, ' ', padding); + + assert(ctx->n < ctx->n_buf); + return true; +} + +/* This helps unit testing. */ +#if SD_BOOT +# define NULLSTR "(null)" +# define wcsnlen strnlen16 +#else +# define NULLSTR "(nil)" +#endif + +static bool handle_format_specifier(FormatContext *ctx, SpecifierContext *sp) { + /* Parses one item from the format specifier in ctx and put the info into sp. If we are done with + * this specifier returns true, otherwise this function should be called again. */ + + /* This implementation assumes 32bit ints. Also note that all types smaller than int are promoted to + * int in vararg functions, which is why we fetch only ints for any such types. The compiler would + * otherwise warn about fetching smaller types. */ + assert_cc(sizeof(int) == 4); + assert_cc(sizeof(wchar_t) <= sizeof(int)); + assert_cc(sizeof(intmax_t) <= sizeof(long long)); + + assert(ctx); + assert(sp); + + switch (*ctx->format) { + case '#': + sp->alternative_form = true; + return false; + case '.': + sp->have_field_width = true; + return false; + case '-': + sp->align_left = true; + return false; + case '+': + case ' ': + sp->sign_pad = *ctx->format; + return false; + + case '0': + if (!sp->have_field_width) { + sp->pad_zero = true; + return false; + } + + /* If field width has already been provided then 0 is part of precision (%.0s). */ + _fallthrough_; + + case '*': + case '1' ... '9': { + int64_t i; + + if (*ctx->format == '*') + i = va_arg(ctx->ap, int); + else { + uint64_t u; + if (!parse_number8(ctx->format, &u, &ctx->format) || u > INT_MAX) + assert_not_reached(); + ctx->format--; /* Point it back to the last digit. */ + i = u; + } + + if (sp->have_field_width) { + /* Negative precision is ignored. */ + if (i >= 0) + sp->len = (size_t) i; + } else { + /* Negative field width is treated as positive field width with '-' flag. */ + if (i < 0) { + i *= -1; + sp->align_left = true; + } + sp->padded_len = i; + } + + return false; + } + + case 'h': + if (*(ctx->format + 1) == 'h') + ctx->format++; + /* char/short gets promoted to int, nothing to do here. */ + return false; + + case 'l': + if (*(ctx->format + 1) == 'l') { + ctx->format++; + sp->longlong_arg = true; + } else + sp->long_arg = true; + return false; + + case 'z': + sp->long_arg = sizeof(size_t) == sizeof(long); + sp->longlong_arg = !sp->long_arg && sizeof(size_t) == sizeof(long long); + return false; + + case 'j': + sp->long_arg = sizeof(intmax_t) == sizeof(long); + sp->longlong_arg = !sp->long_arg && sizeof(intmax_t) == sizeof(long long); + return false; + + case 't': + sp->long_arg = sizeof(ptrdiff_t) == sizeof(long); + sp->longlong_arg = !sp->long_arg && sizeof(ptrdiff_t) == sizeof(long long); + return false; + + case '%': + sp->str = "%"; + sp->len = 1; + return push_str(ctx, sp); + + case 'c': + sp->wstr = &(wchar_t){ va_arg(ctx->ap, int) }; + sp->len = 1; + return push_str(ctx, sp); + + case 's': + if (sp->long_arg) { + sp->wstr = va_arg(ctx->ap, const wchar_t *) ?: L"(null)"; + sp->len = wcsnlen(sp->wstr, sp->len); + } else { + sp->str = va_arg(ctx->ap, const char *) ?: "(null)"; + sp->len = strnlen8(sp->str, sp->len); + } + return push_str(ctx, sp); + + case 'd': + case 'i': + case 'u': + case 'x': + case 'X': + sp->lowercase = *ctx->format == 'x'; + sp->is_signed = IN_SET(*ctx->format, 'd', 'i'); + sp->base = IN_SET(*ctx->format, 'x', 'X') ? 16 : 10; + if (sp->len == SIZE_MAX) + sp->len = 1; + + uint64_t v; + if (sp->longlong_arg) + v = sp->is_signed ? (uint64_t) va_arg(ctx->ap, long long) : + va_arg(ctx->ap, unsigned long long); + else if (sp->long_arg) + v = sp->is_signed ? (uint64_t) va_arg(ctx->ap, long) : va_arg(ctx->ap, unsigned long); + else + v = sp->is_signed ? (uint64_t) va_arg(ctx->ap, int) : va_arg(ctx->ap, unsigned); + + return push_num(ctx, sp, v); + + case 'p': { + const void *ptr = va_arg(ctx->ap, const void *); + if (!ptr) { + sp->str = NULLSTR; + sp->len = STRLEN(NULLSTR); + return push_str(ctx, sp); + } + + sp->base = 16; + sp->lowercase = true; + sp->alternative_form = true; + sp->len = 0; /* Precision is ignored for %p. */ + return push_num(ctx, sp, (uintptr_t) ptr); + } + + case 'm': { + sp->str = status_to_string(ctx->status); + if (sp->str) { + sp->len = strlen8(sp->str); + return push_str(ctx, sp); + } + + sp->base = 16; + sp->lowercase = true; + sp->alternative_form = true; + sp->len = 0; + return push_num(ctx, sp, ctx->status); + } + + default: + assert_not_reached(); + } +} + +/* printf_internal is largely compatible to userspace vasprintf. Any features omitted should trigger asserts. + * + * Supported: + * - Flags: #, 0, +, -, space + * - Lengths: h, hh, l, ll, z, j, t + * - Specifiers: %, c, s, u, i, d, x, X, p, m + * - Precision and width (inline or as int arg using *) + * + * Notable differences: + * - Passing NULL to %s is permitted and will print "(null)" + * - %p will also use "(null)" + * - The provided EFI_STATUS is used for %m instead of errno + * - "\n" is translated to "\r\n" */ +_printf_(2, 0) static char16_t *printf_internal(EFI_STATUS status, const char *format, va_list ap, bool ret) { + assert(format); + + FormatContext ctx = { + .buf = ctx.stack_buf, + .n_buf = ELEMENTSOF(ctx.stack_buf), + .format = format, + .status = status, + }; + + /* We cannot put this into the struct without making a copy. */ + va_copy(ctx.ap, ap); + + while (*ctx.format != '\0') { + SpecifierContext sp = { .len = SIZE_MAX }; + + switch (*ctx.format) { + case '%': + ctx.format++; + while (!handle_format_specifier(&ctx, &sp)) + ctx.format++; + ctx.format++; + break; + case '\n': + ctx.format++; + sp.str = "\r\n"; + sp.len = 2; + push_str(&ctx, &sp); + break; + default: + sp.str = ctx.format++; + while (!IN_SET(*ctx.format, '%', '\n', '\0')) + ctx.format++; + sp.len = ctx.format - sp.str; + push_str(&ctx, &sp); + } + } + + va_end(ctx.ap); + + assert(ctx.n < ctx.n_buf); + ctx.buf[ctx.n++] = '\0'; + + if (ret) { + if (ctx.dyn_buf) + return TAKE_PTR(ctx.dyn_buf); + + char16_t *ret_buf = xnew(char16_t, ctx.n); + memcpy(ret_buf, ctx.buf, ctx.n * sizeof(*ctx.buf)); + return ret_buf; + } + +#if SD_BOOT + ST->ConOut->OutputString(ST->ConOut, ctx.buf); +#endif + + return mfree(ctx.dyn_buf); +} + +void printf_status(EFI_STATUS status, const char *format, ...) { + va_list ap; + va_start(ap, format); + printf_internal(status, format, ap, false); + va_end(ap); +} + +void vprintf_status(EFI_STATUS status, const char *format, va_list ap) { + printf_internal(status, format, ap, false); +} + +char16_t *xasprintf_status(EFI_STATUS status, const char *format, ...) { + va_list ap; + va_start(ap, format); + char16_t *ret = printf_internal(status, format, ap, true); + va_end(ap); + return ret; +} + +char16_t *xvasprintf_status(EFI_STATUS status, const char *format, va_list ap) { + return printf_internal(status, format, ap, true); +} + #if SD_BOOT /* To provide the actual implementation for these we need to remove the redirection to the builtins. */ # undef memcmp diff --git a/src/boot/efi/efi-string.h b/src/boot/efi/efi-string.h index aaa9b399c8..2a28db3593 100644 --- a/src/boot/efi/efi-string.h +++ b/src/boot/efi/efi-string.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include #include #include #include @@ -109,7 +110,32 @@ bool efi_fnmatch(const char16_t *pattern, const char16_t *haystack); bool parse_number8(const char *s, uint64_t *ret_u, const char **ret_tail); bool parse_number16(const char16_t *s, uint64_t *ret_u, const char16_t **ret_tail); +typedef size_t EFI_STATUS; + +#if !SD_BOOT +/* Provide these for unit testing. */ +enum { + EFI_ERROR_MASK = ((EFI_STATUS) 1 << (sizeof(EFI_STATUS) * CHAR_BIT - 1)), + EFI_SUCCESS = 0, + EFI_LOAD_ERROR = 1 | EFI_ERROR_MASK, +}; +#endif + +#ifdef __clang__ +# define _gnu_printf_(a, b) _printf_(a, b) +#else +# define _gnu_printf_(a, b) __attribute__((format(gnu_printf, a, b))) +#endif + +_gnu_printf_(2, 3) void printf_status(EFI_STATUS status, const char *format, ...); +_gnu_printf_(2, 0) void vprintf_status(EFI_STATUS status, const char *format, va_list ap); +_gnu_printf_(2, 3) _warn_unused_result_ char16_t *xasprintf_status(EFI_STATUS status, const char *format, ...); +_gnu_printf_(2, 0) _warn_unused_result_ char16_t *xvasprintf_status(EFI_STATUS status, const char *format, va_list ap); + #if SD_BOOT +# define printf(...) printf_status(EFI_SUCCESS, __VA_ARGS__) +# define xasprintf(...) xasprintf_status(EFI_SUCCESS, __VA_ARGS__) + /* The compiler normally has knowledge about standard functions such as memcmp, but this is not the case when * compiling with -ffreestanding. By referring to builtins, the compiler can check arguments and do * optimizations again. Note that we still need to provide implementations as the compiler is free to not diff --git a/src/boot/efi/fuzz-efi-printf.c b/src/boot/efi/fuzz-efi-printf.c new file mode 100644 index 0000000000..218a427cef --- /dev/null +++ b/src/boot/efi/fuzz-efi-printf.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "alloc-util.h" +#include "efi-string.h" +#include "fuzz.h" +#include "utf8.h" + +typedef struct { + EFI_STATUS status; + int16_t field_width; + int16_t precision; + const void *ptr; + char c; + unsigned char uchar; + signed char schar; + unsigned short ushort; + signed short sshort; + unsigned int uint; + signed int sint; + unsigned long ulong; + signed long slong; + unsigned long long ulonglong; + signed long long slonglong; + size_t size; + ssize_t ssize; + intmax_t intmax; + uintmax_t uintmax; + ptrdiff_t ptrdiff; + char str[]; +} Input; + +#define PRINTF_ONE(...) \ + ({ \ + _cleanup_free_ char16_t *_ret = xasprintf_status(__VA_ARGS__); \ + DO_NOT_OPTIMIZE(_ret); \ + }) + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (outside_size_range(size, sizeof(Input), 1024 * 1024)) + return 0; + + const Input *i = (const Input *) data; + size_t len = size - offsetof(Input, str); + + PRINTF_ONE(i->status, "%*.*s", i->field_width, (int) len, i->str); + PRINTF_ONE(i->status, "%*.*ls", i->field_width, (int) (len / sizeof(wchar_t)), (const wchar_t *) i->str); + + PRINTF_ONE(i->status, "%% %*.*m", i->field_width, i->precision); + PRINTF_ONE(i->status, "%*p", i->field_width, i->ptr); + PRINTF_ONE(i->status, "%*c %12340c %56789c", i->field_width, i->c, i->c, i->c); + + PRINTF_ONE(i->status, "%*.*hhu", i->field_width, i->precision, i->uchar); + PRINTF_ONE(i->status, "%*.*hhi", i->field_width, i->precision, i->schar); + PRINTF_ONE(i->status, "%*.*hu", i->field_width, i->precision, i->ushort); + PRINTF_ONE(i->status, "%*.*hi", i->field_width, i->precision, i->sshort); + PRINTF_ONE(i->status, "%*.*u", i->field_width, i->precision, i->uint); + PRINTF_ONE(i->status, "%*.*i", i->field_width, i->precision, i->sint); + PRINTF_ONE(i->status, "%*.*lu", i->field_width, i->precision, i->ulong); + PRINTF_ONE(i->status, "%*.*li", i->field_width, i->precision, i->slong); + PRINTF_ONE(i->status, "%*.*llu", i->field_width, i->precision, i->ulonglong); + PRINTF_ONE(i->status, "%*.*lli", i->field_width, i->precision, i->slonglong); + + PRINTF_ONE(i->status, "%+*.*hhi", i->field_width, i->precision, i->schar); + PRINTF_ONE(i->status, "%-*.*hi", i->field_width, i->precision, i->sshort); + PRINTF_ONE(i->status, "% *.*i", i->field_width, i->precision, i->sint); + PRINTF_ONE(i->status, "%0*li", i->field_width, i->slong); + PRINTF_ONE(i->status, "%#*.*llx", i->field_width, i->precision, i->ulonglong); + + PRINTF_ONE(i->status, "%-*.*zx", i->field_width, i->precision, i->size); + PRINTF_ONE(i->status, "% *.*zi", i->field_width, i->precision, i->ssize); + PRINTF_ONE(i->status, "%0*ji", i->field_width, i->intmax); + PRINTF_ONE(i->status, "%#0*jX", i->field_width, i->uintmax); + PRINTF_ONE(i->status, "%*.*ti", i->field_width, i->precision, i->ptrdiff); + + return 0; +} diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index 16342f891e..4b044802d3 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -412,6 +412,7 @@ if efi_arch[1] in ['ia32', 'x86_64', 'arm', 'aarch64'] fuzzers += [ [files('fuzz-bcd.c', 'bcd.c', 'efi-string.c')], [files('fuzz-efi-string.c', 'efi-string.c')], + [files('fuzz-efi-printf.c', 'efi-string.c')], ] endif diff --git a/src/boot/efi/missing_efi.h b/src/boot/efi/missing_efi.h index 250c84c248..b3310ea67e 100644 --- a/src/boot/efi/missing_efi.h +++ b/src/boot/efi/missing_efi.h @@ -398,3 +398,15 @@ typedef struct { void *StdErr; } EFI_SHELL_PARAMETERS_PROTOCOL; #endif + +#ifndef EFI_WARN_UNKNOWN_GLYPH +# define EFI_WARN_UNKNOWN_GLYPH 1 +#endif + +#ifndef EFI_WARN_RESET_REQUIRED +# define EFI_WARN_STALE_DATA 5 +# define EFI_WARN_FILE_SYSTEM 6 +# define EFI_WARN_RESET_REQUIRED 7 +# define EFI_IP_ADDRESS_CONFLICT EFIERR(34) +# define EFI_HTTP_ERROR EFIERR(35) +#endif diff --git a/src/boot/efi/test-efi-string.c b/src/boot/efi/test-efi-string.c index 7b43e1d629..c26973d8bd 100644 --- a/src/boot/efi/test-efi-string.c +++ b/src/boot/efi/test-efi-string.c @@ -468,6 +468,148 @@ TEST(parse_number16) { assert_se(streq16(tail, u"rest")); } +_printf_(1, 2) static void test_printf_one(const char *format, ...) { + va_list ap, ap_efi; + va_start(ap, format); + va_copy(ap_efi, ap); + + _cleanup_free_ char *buf = NULL; + int r = vasprintf(&buf, format, ap); + assert_se(r >= 0); + log_info("/* %s(%s) -> \"%.100s\" */", __func__, format, buf); + + _cleanup_free_ char16_t *buf_efi = xvasprintf_status(0, format, ap_efi); + + bool eq = true; + for (size_t i = 0; i <= (size_t) r; i++) { + if (buf[i] != buf_efi[i]) + eq = false; + buf[i] = buf_efi[i]; + } + + log_info("%.100s", buf); + assert_se(eq); + + va_end(ap); + va_end(ap_efi); +} + +TEST(xvasprintf_status) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-zero-length" + test_printf_one(""); +#pragma GCC diagnostic pop + test_printf_one("string"); + test_printf_one("%%-%%%%"); + + test_printf_one("%p %p %32p %*p %*p", NULL, (void *) 0xF, &errno, 0, &saved_argc, 20, &saved_argv); + test_printf_one("%-10p %-32p %-*p %-*p", NULL, &errno, 0, &saved_argc, 20, &saved_argv); + + test_printf_one("%c %3c %*c %*c %-8c", '1', '!', 0, 'a', 9, '_', '>'); + + test_printf_one("%s %s %s", "012345", "6789", "ab"); + test_printf_one("%.4s %.4s %.4s %.0s", "cdefgh", "ijkl", "mn", "@"); + test_printf_one("%8s %8s %8s", "opqrst", "uvwx", "yz"); + test_printf_one("%8.4s %8.4s %8.4s %8.0s", "ABCDEF", "GHIJ", "KL", "$"); + test_printf_one("%4.8s %4.8s %4.8s", "ABCDEFGHIJ", "ABCDEFGH", "ABCD"); + + test_printf_one("%.*s %.*s %.*s %.*s", 4, "012345", 4, "6789", 4, "ab", 0, "&"); + test_printf_one("%*s %*s %*s", 8, "cdefgh", 8, "ijkl", 8, "mn"); + test_printf_one("%*.*s %*.*s %*.*s %*.*s", 8, 4, "opqrst", 8, 4, "uvwx", 8, 4, "yz", 8, 0, "#"); + test_printf_one("%*.*s %*.*s %*.*s", 3, 8, "OPQRST", 3, 8, "UVWX", 3, 8, "YZ"); + + test_printf_one("%ls %ls %ls", L"012345", L"6789", L"ab"); + test_printf_one("%.4ls %.4ls %.4ls %.0ls", L"cdefgh", L"ijkl", L"mn", L"@"); + test_printf_one("%8ls %8ls %8ls", L"opqrst", L"uvwx", L"yz"); + test_printf_one("%8.4ls %8.4ls %8.4ls %8.0ls", L"ABCDEF", L"GHIJ", L"KL", L"$"); + test_printf_one("%4.8ls %4.8ls %4.8ls", L"ABCDEFGHIJ", L"ABCDEFGH", L"ABCD"); + + test_printf_one("%.*ls %.*ls %.*ls %.*ls", 4, L"012345", 4, L"6789", 4, L"ab", 0, L"&"); + test_printf_one("%*ls %*ls %*ls", 8, L"cdefgh", 8, L"ijkl", 8, L"mn"); + test_printf_one("%*.*ls %*.*ls %*.*ls %*.*ls", 8, 4, L"opqrst", 8, 4, L"uvwx", 8, 4, L"yz", 8, 0, L"#"); + test_printf_one("%*.*ls %*.*ls %*.*ls", 3, 8, L"OPQRST", 3, 8, L"UVWX", 3, 8, L"YZ"); + + test_printf_one("%-14s %-10.0s %-10.3s", "left", "", "chopped"); + test_printf_one("%-14ls %-10.0ls %-10.3ls", L"left", L"", L"chopped"); + + test_printf_one("%.6s", (char[]){ 'n', 'o', ' ', 'n', 'u', 'l' }); + test_printf_one("%.6ls", (wchar_t[]){ 'n', 'o', ' ', 'n', 'u', 'l' }); + + test_printf_one("%u %u %u", 0U, 42U, 1234567890U); + test_printf_one("%i %i %i", 0, -42, -1234567890); + test_printf_one("%x %x %x", 0x0U, 0x42U, 0x123ABCU); + test_printf_one("%X %X %X", 0x1U, 0x43U, 0x234BCDU); + test_printf_one("%#x %#x %#x", 0x2U, 0x44U, 0x345CDEU); + test_printf_one("%#X %#X %#X", 0x3U, 0x45U, 0x456FEDU); + + test_printf_one("%u %lu %llu %zu", UINT_MAX, ULONG_MAX, ULLONG_MAX, SIZE_MAX); + test_printf_one("%i %i %zi", INT_MIN, INT_MAX, SSIZE_MAX); + test_printf_one("%li %li %lli %lli", LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX); + test_printf_one("%x %#lx %llx %#zx", UINT_MAX, ULONG_MAX, ULLONG_MAX, SIZE_MAX); + test_printf_one("%X %#lX %llX %#zX", UINT_MAX, ULONG_MAX, ULLONG_MAX, SIZE_MAX); + test_printf_one("%ju %ji %ji", UINTMAX_MAX, INTMAX_MIN, INTMAX_MAX); + test_printf_one("%ti %ti", PTRDIFF_MIN, PTRDIFF_MAX); + + test_printf_one("%" PRIu32 " %" PRIi32 " %" PRIi32, UINT32_MAX, INT32_MIN, INT32_MAX); + test_printf_one("%" PRIx32 " %" PRIX32, UINT32_MAX, UINT32_MAX); + test_printf_one("%#" PRIx32 " %#" PRIX32, UINT32_MAX, UINT32_MAX); + + test_printf_one("%" PRIu64 " %" PRIi64 " %" PRIi64, UINT64_MAX, INT64_MIN, INT64_MAX); + test_printf_one("%" PRIx64 " %" PRIX64, UINT64_MAX, UINT64_MAX); + test_printf_one("%#" PRIx64 " %#" PRIX64, UINT64_MAX, UINT64_MAX); + + test_printf_one("%.11u %.11i %.11x %.11X %#.11x %#.11X", 1U, -2, 3U, 0xA1U, 0xB2U, 0xC3U); + test_printf_one("%13u %13i %13x %13X %#13x %#13X", 4U, -5, 6U, 0xD4U, 0xE5U, 0xF6U); + test_printf_one("%9.5u %9.5i %9.5x %9.5X %#9.5x %#9.5X", 7U, -8, 9U, 0xA9U, 0xB8U, 0xC7U); + test_printf_one("%09u %09i %09x %09X %#09x %#09X", 4U, -5, 6U, 0xD6U, 0xE5U, 0xF4U); + + test_printf_one("%*u %.*u %*i %.*i", 15, 42U, 15, 43U, 15, -42, 15, -43); + test_printf_one("%*.*u %*.*i", 14, 10, 13U, 14, 10, -14); + test_printf_one("%*x %*X %.*x %.*X", 15, 0x1AU, 15, 0x2BU, 15, 0x3CU, 15, 0x4DU); + test_printf_one("%#*x %#*X %#.*x %#.*X", 15, 0xA1U, 15, 0xB2U, 15, 0xC3U, 15, 0xD4U); + test_printf_one("%*.*x %*.*X", 14, 10, 0x1AU, 14, 10, 0x2BU); + test_printf_one("%#*.*x %#*.*X", 14, 10, 0x3CU, 14, 10, 0x4DU); + + test_printf_one("%+.5i %+.5i % .7i % .7i", -15, 51, -15, 51); + test_printf_one("%+5.i %+5.i % 7.i % 7.i", -15, 51, -15, 51); + + test_printf_one("%-10u %-10i %-10x %#-10X %- 10i", 1u, -2, 0xA2D2u, 0XB3F4u, -512); + test_printf_one("%-10.6u %-10.6i %-10.6x %#-10.6X %- 10.6i", 1u, -2, 0xA2D2u, 0XB3F4u, -512); + test_printf_one("%-6.10u %-6.10i %-6.10x %#-6.10X %- 6.10i", 3u, -4, 0x2A2Du, 0X3B4Fu, -215); + test_printf_one("%*.u %.*i %.*i", -4, 9u, -4, 8, -4, -6); + + test_printf_one("%.0u %.0i %.0x %.0X", 0u, 0, 0u, 0u); + test_printf_one("%.*u %.*i %.*x %.*X", 0, 0u, 0, 0, 0, 0u, 0, 0u); + test_printf_one("%*u %*i %*x %*X", -1, 0u, -1, 0, -1, 0u, -1, 0u); + + test_printf_one("%*s%*s%*s", 256, "", 256, "", 4096, ""); /* Test buf growing. */ + test_printf_one("%0*i%0*i%0*i", 256, 0, 256, 0, 4096, 0); /* Test buf growing. */ + test_printf_one("%0*i", INT16_MAX, 0); /* Poor programmer's memzero. */ + + /* Non printf-compatible behavior tests below. */ + char16_t *s; + + assert_se(s = xasprintf_status(0, "\n \r \r\n")); + assert_se(streq16(s, u"\r\n \r \r\r\n")); + s = mfree(s); + + assert_se(s = xasprintf_status(EFI_SUCCESS, "%m")); + assert_se(streq16(s, u"Success")); + s = mfree(s); + + assert_se(s = xasprintf_status(EFI_SUCCESS, "%15m")); + assert_se(streq16(s, u" Success")); + s = mfree(s); + + assert_se(s = xasprintf_status(EFI_LOAD_ERROR, "%m")); + assert_se(streq16(s, u"Load error")); + s = mfree(s); + + assert_se(s = xasprintf_status(0x42, "%m")); + assert_se(streq16(s, u"0x42")); + s = mfree(s); +} + TEST(efi_memcmp) { assert_se(efi_memcmp(NULL, NULL, 0) == 0); assert_se(efi_memcmp(NULL, NULL, 1) == 0); From c2c6203556f842820ca09e0653c123305f2ba6d2 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 10 Jun 2022 19:06:57 +0200 Subject: [PATCH 2/7] boot: Use printf for error logging This also drops the _stall suffix in anticipation of the next commit. --- src/boot/efi/assert.c | 12 --------- src/boot/efi/boot.c | 54 +++++++++++++++++++------------------- src/boot/efi/console.c | 6 ++--- src/boot/efi/cpio.c | 35 +++++++++++------------- src/boot/efi/devicetree.c | 3 +-- src/boot/efi/drivers.c | 16 +++++------ src/boot/efi/linux.c | 10 +++---- src/boot/efi/linux_x86.c | 15 +++++------ src/boot/efi/log.c | 34 ++++++++++++++++++++++++ src/boot/efi/log.h | 9 +++++++ src/boot/efi/measure.c | 7 +++-- src/boot/efi/meson.build | 3 ++- src/boot/efi/pe.c | 2 +- src/boot/efi/random-seed.c | 44 +++++++++++++++---------------- src/boot/efi/secure-boot.c | 11 ++++---- src/boot/efi/stub.c | 6 ++--- src/boot/efi/util.c | 30 +-------------------- src/boot/efi/util.h | 12 +-------- 18 files changed, 148 insertions(+), 161 deletions(-) delete mode 100644 src/boot/efi/assert.c create mode 100644 src/boot/efi/log.c create mode 100644 src/boot/efi/log.h diff --git a/src/boot/efi/assert.c b/src/boot/efi/assert.c deleted file mode 100644 index bb16d2bf93..0000000000 --- a/src/boot/efi/assert.c +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include -#include - -#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 (;;) - BS->Stall(60 * 1000 * 1000); -} diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 29996b8826..7d0bc2ef11 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -597,14 +597,14 @@ static EFI_STATUS reboot_into_firmware(void) { EFI_STATUS err; if (!FLAGS_SET(get_os_indications_supported(), EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) - return log_error_status_stall(EFI_UNSUPPORTED, L"Reboot to firmware interface not supported."); + return log_error_status(EFI_UNSUPPORTED, "Reboot to firmware interface not supported."); (void) efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", &osind); osind |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI; err = efivar_set_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", osind, EFI_VARIABLE_NON_VOLATILE); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error setting OsIndications: %r", err); + return log_error_status(err, "Error setting OsIndications: %m"); RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); assert_not_reached(); @@ -646,7 +646,7 @@ static bool menu_run( config->console_mode_efivar : config->console_mode); if (err != EFI_SUCCESS) { clear_screen(COLOR_NORMAL); - log_error_stall(L"Error switching console mode: %r", err); + log_error_status(err, "Error switching console mode: %m"); } UINTN line_width = 0, entry_padding = 3; @@ -1189,7 +1189,7 @@ static void config_defaults_load_from_file(Config *config, char *content) { else { uint64_t u; if (!parse_number8(value, &u, NULL) || u > TIMEOUT_TYPE_MAX) { - log_error_stall(L"Error parsing 'timeout' config option: %a", value); + log_error("Error parsing 'timeout' config option: %s", value); continue; } config->timeout_sec_config = u; @@ -1200,7 +1200,7 @@ static void config_defaults_load_from_file(Config *config, char *content) { if (streq8(key, "default")) { if (value[0] == '@' && !strcaseeq8(value, "@saved")) { - log_error_stall(L"Unsupported special entry identifier: %a", value); + log_error("Unsupported special entry identifier: %s", value); continue; } free(config->entry_default_config); @@ -1211,35 +1211,35 @@ static void config_defaults_load_from_file(Config *config, char *content) { if (streq8(key, "editor")) { err = parse_boolean(value, &config->editor); if (err != EFI_SUCCESS) - log_error_stall(L"Error parsing 'editor' config option: %a", value); + log_error("Error parsing 'editor' config option: %s", value); continue; } if (streq8(key, "auto-entries")) { err = parse_boolean(value, &config->auto_entries); if (err != EFI_SUCCESS) - log_error_stall(L"Error parsing 'auto-entries' config option: %a", value); + log_error("Error parsing 'auto-entries' config option: %s", value); continue; } if (streq8(key, "auto-firmware")) { err = parse_boolean(value, &config->auto_firmware); if (err != EFI_SUCCESS) - log_error_stall(L"Error parsing 'auto-firmware' config option: %a", value); + log_error("Error parsing 'auto-firmware' config option: %s", value); continue; } if (streq8(key, "beep")) { err = parse_boolean(value, &config->beep); if (err != EFI_SUCCESS) - log_error_stall(L"Error parsing 'beep' config option: %a", value); + log_error("Error parsing 'beep' config option: %s", value); continue; } if (streq8(key, "reboot-for-bitlocker")) { err = parse_boolean(value, &config->reboot_for_bitlocker); if (err != EFI_SUCCESS) - log_error_stall(L"Error parsing 'reboot-for-bitlocker' config option: %a", value); + log_error("Error parsing 'reboot-for-bitlocker' config option: %s", value); } if (streq8(key, "secure-boot-enroll")) { @@ -1250,7 +1250,7 @@ static void config_defaults_load_from_file(Config *config, char *content) { else if (streq8(value, "off")) config->secure_boot_enroll = ENROLL_OFF; else - log_error_stall(L"Error parsing 'secure-boot-enroll' config option: %a", value); + log_error("Error parsing 'secure-boot-enroll' config option: %s", value); continue; } @@ -1264,7 +1264,7 @@ static void config_defaults_load_from_file(Config *config, char *content) { else { uint64_t u; if (!parse_number8(value, &u, NULL) || u > CONSOLE_MODE_RANGE_MAX) { - log_error_stall(L"Error parsing 'console-mode' config option: %a", value); + log_error("Error parsing 'console-mode' config option: %s", value); continue; } config->console_mode = u; @@ -1368,7 +1368,7 @@ static void config_entry_bump_counters(ConfigEntry *entry, EFI_FILE *root_dir) { strcpy16(file_info->FileName, entry->next_name); err = handle->SetInfo(handle, &GenericFileInfo, file_info_size, file_info); if (err != EFI_SUCCESS) { - log_error_stall(L"Failed to rename '%s' to '%s', ignoring: %r", old_path, entry->next_name, err); + log_error_status(err, "Failed to rename '%ls' to '%ls', ignoring: %m", old_path, entry->next_name); return; } @@ -1576,7 +1576,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) { if (err == EFI_SUCCESS) config->timeout_sec = config->timeout_sec_efivar; else if (err != EFI_NOT_FOUND) - log_error_stall(u"Error reading LoaderConfigTimeout EFI variable: %r", err); + log_error_status(err, "Error reading LoaderConfigTimeout EFI variable: %m"); err = efivar_get_timeout(u"LoaderConfigTimeoutOneShot", &config->timeout_sec); if (err == EFI_SUCCESS) { @@ -1585,7 +1585,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) { config->force_menu = true; /* force the menu when this is set */ } else if (err != EFI_NOT_FOUND) - log_error_stall(u"Error reading LoaderConfigTimeoutOneShot EFI variable: %r", err); + log_error_status(err, "Error reading LoaderConfigTimeoutOneShot EFI variable: %m"); err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigConsoleMode", &value); if (err == EFI_SUCCESS) @@ -2341,38 +2341,38 @@ static EFI_STATUS image_start( _cleanup_(file_closep) EFI_FILE *image_root = NULL; err = open_volume(entry->device, &image_root); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error opening root path: %r", err); + return log_error_status(err, "Error opening root path: %m"); err = make_file_device_path(entry->device, entry->loader, &path); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error making file device path: %r", err); + return log_error_status(err, "Error making file device path: %m"); UINTN initrd_size = 0; _cleanup_free_ void *initrd = NULL; _cleanup_free_ char16_t *options_initrd = NULL; err = initrd_prepare(image_root, entry, &options_initrd, &initrd, &initrd_size); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error preparing initrd: %r", err); + return log_error_status(err, "Error preparing initrd: %m"); err = shim_load_image(parent_image, path, &image); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error loading %s: %r", entry->loader, err); + return log_error_status(err, "Error loading %ls: %m", entry->loader); if (entry->devicetree) { err = devicetree_install(&dtstate, image_root, entry->devicetree); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error loading %s: %r", entry->devicetree, err); + return log_error_status(err, "Error loading %ls: %m", entry->devicetree); } _cleanup_(cleanup_initrd) EFI_HANDLE initrd_handle = NULL; err = initrd_register(initrd, initrd_size, &initrd_handle); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error registering initrd: %r", err); + return log_error_status(err, "Error registering initrd: %m"); EFI_LOADED_IMAGE_PROTOCOL *loaded_image; err = BS->HandleProtocol(image, &LoadedImageProtocol, (void **) &loaded_image); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error getting LoadedImageProtocol handle: %r", err); + return log_error_status(err, "Error getting LoadedImageProtocol handle: %m"); char16_t *options = options_initrd ?: entry->options; if (options) { @@ -2396,7 +2396,7 @@ static EFI_STATUS image_start( err = pe_kernel_info(loaded_image->ImageBase, &compat_address); if (err != EFI_SUCCESS) { if (err != EFI_UNSUPPORTED) - return log_error_status_stall(err, L"Error finding kernel compat entry address: %r", err); + return log_error_status(err, "Error finding kernel compat entry address: %m"); } else if (compat_address > 0) { EFI_IMAGE_ENTRY_POINT kernel_entry = (EFI_IMAGE_ENTRY_POINT) ((uint8_t *) loaded_image->ImageBase + compat_address); @@ -2409,7 +2409,7 @@ static EFI_STATUS image_start( err = EFI_UNSUPPORTED; } - return log_error_status_stall(err, L"Failed to execute %s (%s): %r", entry->title_show, entry->loader, err); + return log_error_status(err, "Failed to execute %ls (%ls): %m", entry->title_show, entry->loader); } static void config_free(Config *config) { @@ -2648,7 +2648,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err); + return log_error_status(err, "Error getting a LoadedImageProtocol handle: %m"); (void) device_path_to_str(loaded_image->FilePath, &loaded_image_path); @@ -2656,14 +2656,14 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { err = discover_root_dir(loaded_image, &root_dir); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Unable to open root directory: %r", err); + return log_error_status(err, "Unable to open root directory: %m"); (void) load_drivers(image, loaded_image, root_dir); config_load_all_entries(&config, loaded_image, loaded_image_path, root_dir); if (config.entry_count == 0) { - log_error_stall(L"No loader found. Configuration files in \\loader\\entries\\*.conf are needed."); + log_error("No loader found. Configuration files in \\loader\\entries\\*.conf are needed."); goto out; } diff --git a/src/boot/efi/console.c b/src/boot/efi/console.c index 14c0008afb..6d77d13ca4 100644 --- a/src/boot/efi/console.c +++ b/src/boot/efi/console.c @@ -67,7 +67,7 @@ EFI_STATUS console_key_read(uint64_t *key, uint64_t timeout_usec) { err = BS->CreateEvent(EVT_TIMER, 0, NULL, NULL, &timer); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error creating timer event: %r", err); + return log_error_status(err, "Error creating timer event: %m"); EFI_EVENT events[] = { timer, @@ -88,14 +88,14 @@ EFI_STATUS console_key_read(uint64_t *key, uint64_t timeout_usec) { TimerRelative, MIN(timeout_usec, watchdog_ping_usec) * 10); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error arming timer event: %r", err); + return log_error_status(err, "Error arming timer event: %m"); (void) BS->SetWatchdogTimer(watchdog_timeout_sec, 0x10000, 0, NULL); err = BS->WaitForEvent(n_events, events, &index); (void) BS->SetWatchdogTimer(watchdog_timeout_sec, 0x10000, 0, NULL); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error waiting for events: %r", err); + return log_error_status(err, "Error waiting for events: %m"); /* We have keyboard input, process it after this loop. */ if (timer != events[index]) diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c index 7f123fa376..7c29beb759 100644 --- a/src/boot/efi/cpio.c +++ b/src/boot/efi/cpio.c @@ -357,8 +357,7 @@ EFI_STATUS pack_cpio( * its file handles. */ goto nothing; if (err != EFI_SUCCESS) - return log_error_status_stall( - err, L"Unable to open root directory: %r", err); + return log_error_status(err, "Unable to open root directory: %m"); if (!dropin_dir) dropin_dir = rel_dropin_dir = get_dropin_dir(loaded_image->FilePath); @@ -368,14 +367,14 @@ EFI_STATUS pack_cpio( /* No extra subdir, that's totally OK */ goto nothing; if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to open extra directory of loaded image: %r", err); + return log_error_status(err, "Failed to open extra directory of loaded image: %m"); for (;;) { _cleanup_free_ char16_t *d = NULL; err = readdir_harder(extra_dir, &dirent, &dirent_size); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to read extra directory of loaded image: %r", err); + return log_error_status(err, "Failed to read extra directory of loaded image: %m"); if (!dirent) /* End of directory */ break; @@ -420,7 +419,7 @@ EFI_STATUS pack_cpio( * archive. Otherwise the cpio archive cannot be unpacked, since the leading dirs won't exist. */ err = pack_cpio_prefix(target_dir_prefix, dir_mode, &inode, &buffer, &buffer_size); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to pack cpio prefix: %r", err); + return log_error_status(err, "Failed to pack cpio prefix: %m"); for (UINTN i = 0; i < n_items; i++) { _cleanup_free_ char *content = NULL; @@ -428,7 +427,7 @@ EFI_STATUS pack_cpio( err = file_read(extra_dir, items[i], 0, 0, &content, &contentsize); if (err != EFI_SUCCESS) { - log_error_status_stall(err, L"Failed to read %s, ignoring: %r", items[i], err); + log_error_status(err, "Failed to read %ls, ignoring: %m", items[i]); continue; } @@ -440,22 +439,21 @@ EFI_STATUS pack_cpio( &inode, &buffer, &buffer_size); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to pack cpio file %s: %r", dirent->FileName, err); + return log_error_status(err, "Failed to pack cpio file %ls: %m", dirent->FileName); } err = pack_cpio_trailer(&buffer, &buffer_size); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to pack cpio trailer: %r"); + return log_error_status(err, "Failed to pack cpio trailer: %m"); err = tpm_log_event( tpm_pcr, POINTER_TO_PHYSICAL_ADDRESS(buffer), buffer_size, tpm_description, ret_measured); if (err != EFI_SUCCESS) - return log_error_status_stall( + return log_error_status( err, - L"Unable to add cpio TPM measurement for PCR %u (%s), ignoring: %r", + "Unable to add cpio TPM measurement for PCR %u (%ls), ignoring: %m", tpm_pcr, - tpm_description, - err); + tpm_description); *ret_buffer = TAKE_PTR(buffer); *ret_buffer_size = buffer_size; @@ -501,7 +499,7 @@ EFI_STATUS pack_cpio_literal( err = pack_cpio_prefix(target_dir_prefix, dir_mode, &inode, &buffer, &buffer_size); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to pack cpio prefix: %r", err); + return log_error_status(err, "Failed to pack cpio prefix: %m"); err = pack_cpio_one( target_filename, @@ -511,21 +509,20 @@ EFI_STATUS pack_cpio_literal( &inode, &buffer, &buffer_size); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to pack cpio file %s: %r", target_filename, err); + return log_error_status(err, "Failed to pack cpio file %ls: %m", target_filename); err = pack_cpio_trailer(&buffer, &buffer_size); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to pack cpio trailer: %r"); + return log_error_status(err, "Failed to pack cpio trailer: %m"); err = tpm_log_event( tpm_pcr, POINTER_TO_PHYSICAL_ADDRESS(buffer), buffer_size, tpm_description, ret_measured); if (err != EFI_SUCCESS) - return log_error_status_stall( + return log_error_status( err, - L"Unable to add cpio TPM measurement for PCR %u (%s), ignoring: %r", + "Unable to add cpio TPM measurement for PCR %u (%ls), ignoring: %m", tpm_pcr, - tpm_description, - err); + tpm_description); *ret_buffer = TAKE_PTR(buffer); *ret_buffer_size = buffer_size; diff --git a/src/boot/efi/devicetree.c b/src/boot/efi/devicetree.c index 12015fce6b..0007bb8fe0 100644 --- a/src/boot/efi/devicetree.c +++ b/src/boot/efi/devicetree.c @@ -36,8 +36,7 @@ static EFI_STATUS devicetree_fixup(struct devicetree_state *state, UINTN len) { err = BS->LocateProtocol(&EfiDtFixupProtocol, NULL, (void **) &fixup); if (err != EFI_SUCCESS) - return log_error_status_stall(EFI_SUCCESS, - L"Could not locate device tree fixup protocol, skipping."); + return log_error_status(EFI_SUCCESS, "Could not locate device tree fixup protocol, skipping."); size = devicetree_allocated(state); err = fixup->Fixup(fixup, PHYSICAL_ADDRESS_TO_POINTER(state->addr), &size, diff --git a/src/boot/efi/drivers.c b/src/boot/efi/drivers.c index 7f2057f5a1..ab360f201c 100644 --- a/src/boot/efi/drivers.c +++ b/src/boot/efi/drivers.c @@ -23,26 +23,26 @@ static EFI_STATUS load_one_driver( spath = xpool_print(L"\\EFI\\systemd\\drivers\\%s", fname); err = make_file_device_path(loaded_image->DeviceHandle, spath, &path); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error making file device path: %r", err); + return log_error_status(err, "Error making file device path: %m"); err = BS->LoadImage(false, parent_image, path, NULL, 0, &image); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to load image %s: %r", fname, err); + return log_error_status(err, "Failed to load image %ls: %m", fname); err = BS->HandleProtocol(image, &LoadedImageProtocol, (void **)&loaded_image); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to find protocol in driver image %s: %r", fname, err); + return log_error_status(err, "Failed to find protocol in driver image %ls: %m", fname); if (loaded_image->ImageCodeType != EfiBootServicesCode && loaded_image->ImageCodeType != EfiRuntimeServicesCode) - return log_error_status_stall(EFI_INVALID_PARAMETER, L"Image %s is not a driver, refusing.", fname); + return log_error("Image %ls is not a driver, refusing.", fname); err = BS->StartImage(image, NULL, NULL); if (err != EFI_SUCCESS) { /* EFI_ABORTED signals an initializing driver. It uses this error code on success * so that it is unloaded after. */ if (err != EFI_ABORTED) - log_error_stall(L"Failed to start image %s: %r", fname, err); + log_error_status(err, "Failed to start image %ls: %m", fname); return err; } @@ -59,7 +59,7 @@ EFI_STATUS reconnect_all_drivers(void) { err = BS->LocateHandleBuffer(AllHandles, NULL, NULL, &n_handles, &handles); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to get list of handles: %r", err); + return log_error_status(err, "Failed to get list of handles: %m"); for (size_t i = 0; i < n_handles; i++) /* Some firmware gives us some bogus handles (or they might become bad due to @@ -87,12 +87,12 @@ EFI_STATUS load_drivers( if (err == EFI_NOT_FOUND) return EFI_SUCCESS; if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to open \\EFI\\systemd\\drivers: %r", err); + return log_error_status(err, "Failed to open \\EFI\\systemd\\drivers: %m"); for (;;) { err = readdir_harder(drivers_dir, &dirent, &dirent_size); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to read extra directory of loaded image: %r", err); + return log_error_status(err, "Failed to read extra directory of loaded image: %m"); if (!dirent) /* End of directory */ break; diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c index 48801f9dd8..2ae68ec295 100644 --- a/src/boot/efi/linux.c +++ b/src/boot/efi/linux.c @@ -120,17 +120,17 @@ EFI_STATUS linux_exec( initrd_length); #endif if (err != EFI_SUCCESS) - return log_error_status_stall(err, u"Bad kernel image: %r", err); + return log_error_status(err, "Bad kernel image: %m"); _cleanup_(unload_imagep) EFI_HANDLE kernel_image = NULL; err = load_image(parent, linux_buffer, linux_length, &kernel_image); if (err != EFI_SUCCESS) - return log_error_status_stall(err, u"Error loading kernel image: %r", err); + return log_error_status(err, "Error loading kernel image: %m"); EFI_LOADED_IMAGE_PROTOCOL *loaded_image; err = BS->HandleProtocol(kernel_image, &LoadedImageProtocol, (void **) &loaded_image); if (err != EFI_SUCCESS) - return log_error_status_stall(err, u"Error getting kernel loaded image protocol: %r", err); + return log_error_status(err, "Error getting kernel loaded image protocol: %m"); if (cmdline) { loaded_image->LoadOptions = (void *) cmdline; @@ -140,7 +140,7 @@ EFI_STATUS linux_exec( _cleanup_(cleanup_initrd) EFI_HANDLE initrd_handle = NULL; err = initrd_register(initrd_buffer, initrd_length, &initrd_handle); if (err != EFI_SUCCESS) - return log_error_status_stall(err, u"Error registering initrd: %r", err); + return log_error_status(err, "Error registering initrd: %m"); err = BS->StartImage(kernel_image, NULL, NULL); @@ -151,5 +151,5 @@ EFI_STATUS linux_exec( err = compat_entry(kernel_image, ST); } - return log_error_status_stall(err, u"Error starting kernel image: %r", err); + return log_error_status(err, "Error starting kernel image: %m"); } diff --git a/src/boot/efi/linux_x86.c b/src/boot/efi/linux_x86.c index 6a5e431107..cbd92201b6 100644 --- a/src/boot/efi/linux_x86.c +++ b/src/boot/efi/linux_x86.c @@ -141,28 +141,27 @@ EFI_STATUS linux_exec_efi_handover( const BootParams *image_params = (const BootParams *) linux_buffer; if (image_params->hdr.header != SETUP_MAGIC || image_params->hdr.boot_flag != BOOT_FLAG_MAGIC) - return log_error_status_stall(EFI_UNSUPPORTED, u"Unsupported kernel image."); + return log_error_status(EFI_UNSUPPORTED, "Unsupported kernel image."); if (image_params->hdr.version < SETUP_VERSION_2_11) - return log_error_status_stall(EFI_UNSUPPORTED, u"Kernel too old."); + return log_error_status(EFI_UNSUPPORTED, "Kernel too old."); if (!image_params->hdr.relocatable_kernel) - return log_error_status_stall(EFI_UNSUPPORTED, u"Kernel is not relocatable."); + return log_error_status(EFI_UNSUPPORTED, "Kernel is not relocatable."); /* The xloadflags were added in version 2.12+ of the boot protocol but the handover support predates * that, so we cannot safety-check this for 2.11. */ if (image_params->hdr.version >= SETUP_VERSION_2_12 && !FLAGS_SET(image_params->hdr.xloadflags, XLF_EFI_HANDOVER)) - return log_error_status_stall(EFI_UNSUPPORTED, u"Kernel does not support EFI handover protocol."); + return log_error_status(EFI_UNSUPPORTED, "Kernel does not support EFI handover protocol."); bool can_4g = image_params->hdr.version >= SETUP_VERSION_2_12 && FLAGS_SET(image_params->hdr.xloadflags, XLF_CAN_BE_LOADED_ABOVE_4G); if (!can_4g && POINTER_TO_PHYSICAL_ADDRESS(linux_buffer) + linux_length > UINT32_MAX) - return log_error_status_stall( + return log_error_status( EFI_UNSUPPORTED, - u"Unified kernel image was loaded above 4G, but kernel lacks support."); + "Unified kernel image was loaded above 4G, but kernel lacks support."); if (!can_4g && POINTER_TO_PHYSICAL_ADDRESS(initrd_buffer) + initrd_length > UINT32_MAX) - return log_error_status_stall( - EFI_UNSUPPORTED, u"Initrd is above 4G, but kernel lacks support."); + return log_error_status(EFI_UNSUPPORTED, "Initrd is above 4G, but kernel lacks support."); _cleanup_pages_ Pages boot_params_page = xmalloc_pages( can_4g ? AllocateAnyPages : AllocateMaxAddress, diff --git a/src/boot/efi/log.c b/src/boot/efi/log.c new file mode 100644 index 0000000000..38e7c5a8a8 --- /dev/null +++ b/src/boot/efi/log.c @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include + +#include "log.h" + +void efi_assert(const char *expr, const char *file, unsigned line, const char *function) { + log_error("systemd-boot assertion '%s' failed at %s:%u@%s. Halting.", expr, file, line, function); + for (;;) + BS->Stall(60 * 1000 * 1000); +} + +EFI_STATUS log_internal(EFI_STATUS status, const char *format, ...) { + assert(format); + + int32_t attr = ST->ConOut->Mode->Attribute; + + if (ST->ConOut->Mode->CursorColumn > 0) + ST->ConOut->OutputString(ST->ConOut, (char16_t *) u"\r\n"); + ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTRED | EFI_BACKGROUND_BLACK); + + va_list ap; + va_start(ap, format); + vprintf_status(status, format, ap); + va_end(ap); + + ST->ConOut->OutputString(ST->ConOut, (char16_t *) u"\r\n"); + ST->ConOut->SetAttribute(ST->ConOut, attr); + + /* Give the user a chance to see the message. */ + BS->Stall(3 * 1000 * 1000); + return status; +} diff --git a/src/boot/efi/log.h b/src/boot/efi/log.h new file mode 100644 index 0000000000..c6e8d626ce --- /dev/null +++ b/src/boot/efi/log.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "efi-string.h" + +_gnu_printf_(2, 3) EFI_STATUS log_internal(EFI_STATUS status, const char *format, ...); +#define log_error_status(status, ...) log_internal(status, __VA_ARGS__) +#define log_error(...) log_internal(EFI_INVALID_PARAMETER, __VA_ARGS__) +#define log_oom() log_internal(EFI_OUT_OF_RESOURCES, "Out of memory.") diff --git a/src/boot/efi/measure.c b/src/boot/efi/measure.c index dc3bd064db..141e8c6042 100644 --- a/src/boot/efi/measure.c +++ b/src/boot/efi/measure.c @@ -205,11 +205,10 @@ EFI_STATUS tpm_log_load_options(const char16_t *load_options, bool *ret_measured load_options, &measured); if (err != EFI_SUCCESS) - return log_error_status_stall( + return log_error_status( err, - L"Unable to add load options (i.e. kernel command) line measurement to PCR %u: %r", - TPM_PCR_INDEX_KERNEL_PARAMETERS, - err); + "Unable to add load options (i.e. kernel command) line measurement to PCR %u: %m", + TPM_PCR_INDEX_KERNEL_PARAMETERS); if (ret_measured) *ret_measured = measured; diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index 4b044802d3..deb328eb4e 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -348,6 +348,7 @@ efi_headers = files( 'graphics.h', 'initrd.h', 'linux.h', + 'log.h', 'measure.h', 'missing_efi.h', 'part-discovery.h', @@ -361,7 +362,6 @@ efi_headers = files( ) common_sources = files( - 'assert.c', 'console.c', 'devicetree.c', 'drivers.c', @@ -369,6 +369,7 @@ common_sources = files( 'efi-string.c', 'graphics.c', 'initrd.c', + 'log.c', 'measure.c', 'part-discovery.c', 'pe.c', diff --git a/src/boot/efi/pe.c b/src/boot/efi/pe.c index 3d5da14d10..7ba63b1b5a 100644 --- a/src/boot/efi/pe.c +++ b/src/boot/efi/pe.c @@ -158,7 +158,7 @@ static void locate_sections( if (in_memory) { if (prev_section_addr > sect->VirtualAddress) - log_error_stall(u"Overlapping PE sections detected. Boot may fail due to image memory corruption!"); + log_error("Overlapping PE sections detected. Boot may fail due to image memory corruption!"); prev_section_addr = sect->VirtualAddress + sect->VirtualSize; } diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c index 332f537d91..f445ac0067 100644 --- a/src/boot/efi/random-seed.c +++ b/src/boot/efi/random-seed.c @@ -48,7 +48,7 @@ static EFI_STATUS acquire_rng(void *ret, UINTN size) { err = rng->GetRNG(rng, NULL, size, ret); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to acquire RNG data: %r", err); + return log_error_status(err, "Failed to acquire RNG data: %m"); return EFI_SUCCESS; } @@ -63,12 +63,12 @@ static EFI_STATUS acquire_system_token(void **ret, UINTN *ret_size) { err = efivar_get_raw(LOADER_GUID, L"LoaderSystemToken", &data, &size); if (err != EFI_SUCCESS) { if (err != EFI_NOT_FOUND) - log_error_stall(L"Failed to read LoaderSystemToken EFI variable: %r", err); + log_error_status(err, "Failed to read LoaderSystemToken EFI variable: %m"); return err; } if (size <= 0) - return log_error_status_stall(EFI_NOT_FOUND, L"System token too short, ignoring."); + return log_error_status(EFI_NOT_FOUND, "System token too short, ignoring."); *ret = TAKE_PTR(data); *ret_size = size; @@ -201,29 +201,29 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) { 0); if (err != EFI_SUCCESS) { if (err != EFI_NOT_FOUND && err != EFI_WRITE_PROTECTED) - log_error_stall(L"Failed to open random seed file: %r", err); + log_error_status(err, "Failed to open random seed file: %m"); return err; } err = get_file_info_harder(handle, &info, NULL); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to get file info for random seed: %r", err); + return log_error_status(err, "Failed to get file info for random seed: %m"); size = info->FileSize; if (size < RANDOM_MAX_SIZE_MIN) - return log_error_status_stall(EFI_INVALID_PARAMETER, L"Random seed file is too short."); + return log_error("Random seed file is too short."); if (size > RANDOM_MAX_SIZE_MAX) - return log_error_status_stall(EFI_INVALID_PARAMETER, L"Random seed file is too large."); + return log_error("Random seed file is too large."); seed = xmalloc(size); rsize = size; err = handle->Read(handle, &rsize, seed); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to read random seed file: %r", err); + return log_error_status(err, "Failed to read random seed file: %m"); if (rsize != size) { explicit_bzero_safe(seed, rsize); - return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short read on random seed file."); + return log_error_status(EFI_PROTOCOL_ERROR, "Short read on random seed file."); } sha256_process_bytes(&size, sizeof(size), &hash); @@ -232,14 +232,14 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) { err = handle->SetPosition(handle, 0); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to seek to beginning of random seed file: %r", err); + return log_error_status(err, "Failed to seek to beginning of random seed file: %m"); /* Let's also include the UEFI monotonic counter (which is supposedly increasing on every single * boot) in the hash, so that even if the changes to the ESP for some reason should not be * persistent, the random seed we generate will still be different on every single boot. */ err = BS->GetNextMonotonicCount(&uefi_monotonic_counter); if (err != EFI_SUCCESS && !seeded_by_efi) - return log_error_status_stall(err, L"Failed to acquire UEFI monotonic counter: %r", err); + return log_error_status(err, "Failed to acquire UEFI monotonic counter: %m"); size = sizeof(uefi_monotonic_counter); sha256_process_bytes(&size, sizeof(size), &hash); sha256_process_bytes(&uefi_monotonic_counter, size, &hash); @@ -264,26 +264,26 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) { if (size < info->FileSize) { err = handle->SetPosition(handle, size); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to seek to offset of random seed file: %r", err); + return log_error_status(err, "Failed to seek to offset of random seed file: %m"); wsize = info->FileSize - size; err = handle->Write(handle, &wsize, seed /* All zeros now */); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to write random seed file: %r", err); + return log_error_status(err, "Failed to write random seed file: %m"); if (wsize != info->FileSize - size) - return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short write on random seed file."); + return log_error_status(EFI_PROTOCOL_ERROR, "Short write on random seed file."); err = handle->Flush(handle); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to flush random seed file: %r", err); + return log_error_status(err, "Failed to flush random seed file: %m"); err = handle->SetPosition(handle, 0); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to seek to beginning of random seed file: %r", err); + return log_error_status(err, "Failed to seek to beginning of random seed file: %m"); /* We could truncate the file here with something like: * * info->FileSize = size; * err = handle->SetInfo(handle, &GenericFileInfo, info->Size, info); * if (err != EFI_SUCCESS) - * return log_error_status_stall(err, L"Failed to truncate random seed file: %r", err); + * return log_error_status(err, "Failed to truncate random seed file: %u"); * * But this is considered slightly risky, because EFI filesystem drivers are a little bit * flimsy. So instead we rely on userspace eventually truncating this when it writes a new @@ -293,18 +293,18 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) { wsize = size; err = handle->Write(handle, &wsize, random_bytes); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to write random seed file: %r", err); + return log_error_status(err, "Failed to write random seed file: %m"); if (wsize != size) - return log_error_status_stall(EFI_PROTOCOL_ERROR, L"Short write on random seed file."); + return log_error_status(EFI_PROTOCOL_ERROR, "Short write on random seed file."); err = handle->Flush(handle); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to flush random seed file: %r", err); + return log_error_status(err, "Failed to flush random seed file: %m"); err = BS->AllocatePool(EfiACPIReclaimMemory, offsetof(struct linux_efi_random_seed, seed) + DESIRED_SEED_SIZE, (void **) &new_seed_table); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to allocate EFI table for random seed: %r", err); + return log_error_status(err, "Failed to allocate EFI table for random seed: %m"); new_seed_table->size = DESIRED_SEED_SIZE; /* hash = hash_key || 1 */ @@ -316,7 +316,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir) { err = BS->InstallConfigurationTable(&(EFI_GUID)LINUX_EFI_RANDOM_SEED_TABLE_GUID, new_seed_table); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed to install EFI table for random seed: %r", err); + return log_error_status(err, "Failed to install EFI table for random seed: %m"); TAKE_PTR(new_seed_table); if (previous_seed_table) { diff --git a/src/boot/efi/secure-boot.c b/src/boot/efi/secure-boot.c index 571c3c3612..71c3f13161 100644 --- a/src/boot/efi/secure-boot.c +++ b/src/boot/efi/secure-boot.c @@ -66,10 +66,9 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) { continue; } if (err != EFI_SUCCESS) - return log_error_status_stall( + return log_error_status( err, - L"Error waiting for user input to enroll Secure Boot keys: %r", - err); + "Error waiting for user input to enroll Secure Boot keys: %m"); /* user aborted, returning EFI_SUCCESS here allows the user to go back to the menu */ return EFI_SUCCESS; @@ -80,7 +79,7 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) { err = open_directory(root_dir, path, &dir); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Failed opening keys directory %s: %r", path, err); + return log_error_status(err, "Failed opening keys directory %ls: %m", path); struct { const char16_t *name; @@ -98,7 +97,7 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) { for (size_t i = 0; i < ELEMENTSOF(sb_vars); i++) { err = file_read(dir, sb_vars[i].filename, 0, 0, &sb_vars[i].buffer, &sb_vars[i].size); if (err != EFI_SUCCESS) { - log_error_stall(L"Failed reading file %s\\%s: %r", path, sb_vars[i].filename, err); + log_error_status(err, "Failed reading file %ls\\%ls: %m", path, sb_vars[i].filename); goto out_deallocate; } } @@ -112,7 +111,7 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) { err = efivar_set_raw(&sb_vars[i].vendor, sb_vars[i].name, sb_vars[i].buffer, sb_vars[i].size, sb_vars_opts); if (err != EFI_SUCCESS) { - log_error_stall(L"Failed to write %s secure boot variable: %r", sb_vars[i].name, err); + log_error_status(err, "Failed to write %ls secure boot variable: %m", sb_vars[i].name); goto out_deallocate; } } diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index aa83b34166..4f627e9a66 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -207,7 +207,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (err != EFI_SUCCESS) - return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err); + return log_error_status(err, "Error getting a LoadedImageProtocol handle: %m"); if (efivar_get_uint64_le(LOADER_GUID, L"LoaderFeatures", &loader_features) != EFI_SUCCESS || !FLAGS_SET(loader_features, EFI_LOADER_FEATURE_RANDOM_SEED)) { @@ -222,7 +222,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { if (err != EFI_SUCCESS || szs[UNIFIED_SECTION_LINUX] == 0) { if (err == EFI_SUCCESS) err = EFI_NOT_FOUND; - return log_error_status_stall(err, L"Unable to locate embedded .linux section: %r", err); + return log_error_status(err, "Unable to locate embedded .linux section: %m"); } /* Measure all "payload" of this PE image into a separate PCR (i.e. where nothing else is written @@ -412,7 +412,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { err = devicetree_install_from_memory( &dt_state, PHYSICAL_ADDRESS_TO_POINTER(dt_base), dt_size); if (err != EFI_SUCCESS) - log_error_stall(L"Error loading embedded devicetree: %r", err); + log_error_status(err, "Error loading embedded devicetree: %m"); } err = linux_exec(image, cmdline, diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c index 202332c2d8..e9267be575 100644 --- a/src/boot/efi/util.c +++ b/src/boot/efi/util.c @@ -339,34 +339,6 @@ EFI_STATUS file_read(EFI_FILE *dir, const char16_t *name, UINTN off, UINTN size, return err; } -void log_error_stall(const char16_t *fmt, ...) { - va_list args; - - assert(fmt); - - int32_t attr = ST->ConOut->Mode->Attribute; - ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTRED|EFI_BACKGROUND_BLACK); - - if (ST->ConOut->Mode->CursorColumn > 0) - Print(L"\n"); - - va_start(args, fmt); - VPrint(fmt, args); - va_end(args); - - Print(L"\n"); - - ST->ConOut->SetAttribute(ST->ConOut, attr); - - /* Give the user a chance to see the message. */ - BS->Stall(3 * 1000 * 1000); -} - -EFI_STATUS log_oom(void) { - log_error_stall(L"Out of memory."); - return EFI_OUT_OF_RESOURCES; -} - void print_at(UINTN x, UINTN y, UINTN attr, const char16_t *str) { assert(str); ST->ConOut->SetCursorPosition(ST->ConOut, x, y); @@ -586,7 +558,7 @@ void hexdump(const char16_t *prefix, const void *data, UINTN size) { buf[size*2] = 0; - log_error_stall(L"%s[%" PRIuN "]: %s", prefix, size, buf); + log_error("%ls[%zu]: %ls", prefix, size, buf); } #endif diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h index 32ecea7d6a..101eee1718 100644 --- a/src/boot/efi/util.h +++ b/src/boot/efi/util.h @@ -5,6 +5,7 @@ #include #include +#include "log.h" #include "string-util-fundamental.h" #define UINTN_MAX (~(UINTN)0) @@ -139,17 +140,6 @@ static inline void unload_imagep(EFI_HANDLE *image) { &(const EFI_GUID) { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } } #define EFI_GLOBAL_GUID &(const EFI_GUID) EFI_GLOBAL_VARIABLE -void log_error_stall(const char16_t *fmt, ...); -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; \ - }) - void print_at(UINTN x, UINTN y, UINTN attr, const char16_t *str); void clear_screen(UINTN attr); From 6ac54809deefddccc7861b5a2cfa4d766cf1aa3b Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 5 Jun 2022 13:19:21 +0200 Subject: [PATCH 3/7] boot: Introduce log_wait Instead of stalling for every log message as it appears we now wait for several messages at strategic locations. --- src/boot/efi/boot.c | 18 +++++++++++++----- src/boot/efi/console.c | 1 + src/boot/efi/graphics.c | 7 ++++--- src/boot/efi/linux.c | 1 + src/boot/efi/linux_x86.c | 1 + src/boot/efi/log.c | 13 +++++++++++-- src/boot/efi/log.h | 1 + src/boot/efi/stub.c | 19 +++++++++++++------ src/boot/efi/util.c | 1 + 9 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 7d0bc2ef11..98c49e96ce 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -2626,7 +2626,7 @@ static EFI_STATUS discover_root_dir(EFI_LOADED_IMAGE_PROTOCOL *loaded_image, EFI return open_volume(loaded_image->DeviceHandle, ret_dir); } -EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { +static EFI_STATUS real_main(EFI_HANDLE image) { EFI_LOADED_IMAGE_PROTOCOL *loaded_image; _cleanup_(file_closep) EFI_FILE *root_dir = NULL; _cleanup_(config_free) Config config = {}; @@ -2635,11 +2635,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { uint64_t init_usec; bool menu = false; - InitializeLib(image, sys_table); init_usec = time_usec(); - debug_hook(L"systemd-boot"); - /* Uncomment the next line if you need to wait for debugger. */ - // debug_break(); err = BS->OpenProtocol(image, &LoadedImageProtocol, @@ -2728,3 +2724,15 @@ out: BS->CloseProtocol(image, &LoadedImageProtocol, image, NULL); return err; } + +EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + InitializeLib(image, sys_table); + + debug_hook(L"systemd-boot"); + /* Uncomment the next line if you need to wait for debugger. */ + // debug_break(); + + EFI_STATUS err = real_main(image); + log_wait(); + return err; +} diff --git a/src/boot/efi/console.c b/src/boot/efi/console.c index 6d77d13ca4..2e5c857b04 100644 --- a/src/boot/efi/console.c +++ b/src/boot/efi/console.c @@ -172,6 +172,7 @@ static EFI_STATUS change_mode(int64_t mode) { mode = CLAMP(mode, CONSOLE_MODE_RANGE_MIN, CONSOLE_MODE_RANGE_MAX); old_mode = MAX(CONSOLE_MODE_RANGE_MIN, ST->ConOut->Mode->Mode); + log_wait(); err = ST->ConOut->SetMode(ST->ConOut, mode); if (err == EFI_SUCCESS) return EFI_SUCCESS; diff --git a/src/boot/efi/graphics.c b/src/boot/efi/graphics.c index dc646bce1f..350d1bc434 100644 --- a/src/boot/efi/graphics.c +++ b/src/boot/efi/graphics.c @@ -25,16 +25,17 @@ EFI_STATUS graphics_mode(bool on) { return err == EFI_NOT_FOUND ? EFI_SUCCESS : err; /* check current mode */ - err =ConsoleControl->GetMode(ConsoleControl, ¤t, &uga_exists, &stdin_locked); + err = ConsoleControl->GetMode(ConsoleControl, ¤t, &uga_exists, &stdin_locked); if (err != EFI_SUCCESS) return err; /* do not touch the mode */ - new = on ? EfiConsoleControlScreenGraphics : EfiConsoleControlScreenText; + new = on ? EfiConsoleControlScreenGraphics : EfiConsoleControlScreenText; if (new == current) return EFI_SUCCESS; - err =ConsoleControl->SetMode(ConsoleControl, new); + log_wait(); + err = ConsoleControl->SetMode(ConsoleControl, new); /* some firmware enables the cursor when switching modes */ ST->ConOut->EnableCursor(ST->ConOut, false); diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c index 2ae68ec295..727e507101 100644 --- a/src/boot/efi/linux.c +++ b/src/boot/efi/linux.c @@ -142,6 +142,7 @@ EFI_STATUS linux_exec( if (err != EFI_SUCCESS) return log_error_status(err, "Error registering initrd: %m"); + log_wait(); err = BS->StartImage(kernel_image, NULL, NULL); /* Try calling the kernel compat entry point if one exists. */ diff --git a/src/boot/efi/linux_x86.c b/src/boot/efi/linux_x86.c index cbd92201b6..eaae988d97 100644 --- a/src/boot/efi/linux_x86.c +++ b/src/boot/efi/linux_x86.c @@ -209,6 +209,7 @@ EFI_STATUS linux_exec_efi_handover( boot_params->hdr.ramdisk_size = initrd_length; boot_params->ext_ramdisk_size = ((uint64_t) initrd_length) >> 32; + log_wait(); linux_efi_handover(parent, (uintptr_t) linux_buffer, boot_params); return EFI_LOAD_ERROR; } diff --git a/src/boot/efi/log.c b/src/boot/efi/log.c index 38e7c5a8a8..b1a613e4e5 100644 --- a/src/boot/efi/log.c +++ b/src/boot/efi/log.c @@ -5,6 +5,8 @@ #include "log.h" +static unsigned log_count = 0; + void efi_assert(const char *expr, const char *file, unsigned line, const char *function) { log_error("systemd-boot assertion '%s' failed at %s:%u@%s. Halting.", expr, file, line, function); for (;;) @@ -28,7 +30,14 @@ EFI_STATUS log_internal(EFI_STATUS status, const char *format, ...) { ST->ConOut->OutputString(ST->ConOut, (char16_t *) u"\r\n"); ST->ConOut->SetAttribute(ST->ConOut, attr); - /* Give the user a chance to see the message. */ - BS->Stall(3 * 1000 * 1000); + log_count++; return status; } + +void log_wait(void) { + if (log_count == 0) + return; + + BS->Stall(MIN(4u, log_count) * 2500 * 1000); + log_count = 0; +} diff --git a/src/boot/efi/log.h b/src/boot/efi/log.h index c6e8d626ce..f24034fd78 100644 --- a/src/boot/efi/log.h +++ b/src/boot/efi/log.h @@ -3,6 +3,7 @@ #include "efi-string.h" +void log_wait(void); _gnu_printf_(2, 3) EFI_STATUS log_internal(EFI_STATUS status, const char *format, ...); #define log_error_status(status, ...) log_internal(status, __VA_ARGS__) #define log_error(...) log_internal(EFI_INVALID_PARAMETER, __VA_ARGS__) diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 4f627e9a66..bb647f1d78 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -180,7 +180,7 @@ static bool use_load_options( return true; } -EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { +static EFI_STATUS real_main(EFI_HANDLE image) { _cleanup_free_ void *credential_initrd = NULL, *global_credential_initrd = NULL, *sysext_initrd = NULL, *pcrsig_initrd = NULL, *pcrpkey_initrd = NULL; size_t credential_initrd_size = 0, global_credential_initrd_size = 0, sysext_initrd_size = 0, pcrsig_initrd_size = 0, pcrpkey_initrd_size = 0; size_t linux_size, initrd_size, dt_size; @@ -194,11 +194,6 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { uint64_t loader_features = 0; EFI_STATUS err; - InitializeLib(image, sys_table); - debug_hook(L"systemd-stub"); - /* Uncomment the next line if you need to wait for debugger. */ - // debug_break(); - err = BS->OpenProtocol( image, &LoadedImageProtocol, @@ -421,3 +416,15 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { graphics_mode(false); return err; } + +EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + InitializeLib(image, sys_table); + + debug_hook(L"systemd-stub"); + /* Uncomment the next line if you need to wait for debugger. */ + // debug_break(); + + EFI_STATUS err = real_main(image); + log_wait(); + return err; +} diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c index e9267be575..86bc9cb543 100644 --- a/src/boot/efi/util.c +++ b/src/boot/efi/util.c @@ -347,6 +347,7 @@ void print_at(UINTN x, UINTN y, UINTN attr, const char16_t *str) { } void clear_screen(UINTN attr) { + log_wait(); ST->ConOut->SetAttribute(ST->ConOut, attr); ST->ConOut->ClearScreen(ST->ConOut); } From 5966c54df4668abc17ae12c40fb0c30d31e80998 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 18 Aug 2022 13:41:49 +0200 Subject: [PATCH 4/7] boot: Add log_trace debugging helper --- src/boot/efi/log.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/boot/efi/log.h b/src/boot/efi/log.h index f24034fd78..9bdcfad923 100644 --- a/src/boot/efi/log.h +++ b/src/boot/efi/log.h @@ -8,3 +8,4 @@ _gnu_printf_(2, 3) EFI_STATUS log_internal(EFI_STATUS status, const char *format #define log_error_status(status, ...) log_internal(status, __VA_ARGS__) #define log_error(...) log_internal(EFI_INVALID_PARAMETER, __VA_ARGS__) #define log_oom() log_internal(EFI_OUT_OF_RESOURCES, "Out of memory.") +#define log_trace() log_internal(EFI_SUCCESS, "%s:%i@%s", __FILE__, __LINE__, __func__) From 5a9b91576630f82ca72a932b5195654dbb04d67e Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 18 Aug 2022 13:43:19 +0200 Subject: [PATCH 5/7] tree-wide: Use __func__ in asserts clang puts the whole function signature in __PRETTY_FUNCTION__, which is a bit excessive for something that can already be figured out by using the line number. --- src/basic/macro.h | 6 +++--- src/fundamental/macro-fundamental.h | 6 +++--- src/journal/test-journal-interleaving.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/basic/macro.h b/src/basic/macro.h index a00d60824d..0d032866cf 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -175,12 +175,12 @@ static inline int __coverity_check_and_return__(int condition) { #define assert_message_se(expr, message) \ do { \ if (_unlikely_(!(expr))) \ - log_assert_failed(message, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__); \ + log_assert_failed(message, PROJECT_FILE, __LINE__, __func__); \ } while (false) #define assert_log(expr, message) ((_likely_(expr)) \ ? (true) \ - : (log_assert_failed_return(message, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__), false)) + : (log_assert_failed_return(message, PROJECT_FILE, __LINE__, __func__), false)) #endif /* __COVERITY__ */ @@ -195,7 +195,7 @@ static inline int __coverity_check_and_return__(int condition) { #endif #define assert_not_reached() \ - log_assert_failed_unreachable(PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__) + log_assert_failed_unreachable(PROJECT_FILE, __LINE__, __func__) #define assert_return(expr, r) \ do { \ diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h index 71c6283e10..b2bc435bd3 100644 --- a/src/fundamental/macro-fundamental.h +++ b/src/fundamental/macro-fundamental.h @@ -74,11 +74,11 @@ #define assert(expr) #define assert_not_reached() __builtin_unreachable() #else - #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__) + #define assert(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __func__); }) + #define assert_not_reached() efi_assert("Code should not be reached", __FILE__, __LINE__, __func__) #endif #define static_assert _Static_assert - #define assert_se(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); }) + #define assert_se(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __func__); }) #endif /* This passes the argument through after (if asserts are enabled) checking that it is not null. */ diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c index 379a0c8caf..67552de8fe 100644 --- a/src/journal/test-journal-interleaving.c +++ b/src/journal/test-journal-interleaving.c @@ -30,7 +30,7 @@ _noreturn_ static void log_assert_errno(const char *text, int error, const char do { \ int _r_ = (expr); \ if (_unlikely_(_r_ < 0)) \ - log_assert_errno(#expr, -_r_, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__); \ + log_assert_errno(#expr, -_r_, PROJECT_FILE, __LINE__, __func__); \ } while (false) static ManagedJournalFile *test_open(const char *name) { From 2f3c3b0bee5534f2338439f04b0aa517479f8b76 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 5 Jun 2022 15:08:07 +0200 Subject: [PATCH 6/7] boot: Drop use of xpool_print/SPrint --- src/boot/efi/boot.c | 73 +++++++++++++++++++++--------------------- src/boot/efi/cpio.c | 2 +- src/boot/efi/drivers.c | 2 +- src/boot/efi/stub.c | 6 ++-- src/boot/efi/util.h | 1 - src/boot/efi/vmm.c | 3 +- 6 files changed, 43 insertions(+), 44 deletions(-) diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 98c49e96ce..4dc3921990 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "bcd.h" #include "bootspec-fundamental.h" @@ -427,7 +428,7 @@ static char16_t *update_timeout_efivar(uint32_t *t, bool inc) { case TIMEOUT_MENU_HIDDEN: return xstrdup16(u"Menu disabled. Hold down key at bootup to show menu."); default: - return xpool_print(L"Menu timeout set to %u s.", *t); + return xasprintf("Menu timeout set to %u s.", *t); } } @@ -761,7 +762,7 @@ static bool menu_run( if (timeout_remain > 0) { free(status); - status = xpool_print(L"Boot in %u s.", timeout_remain); + status = xasprintf("Boot in %u s.", timeout_remain); } if (status) { @@ -940,9 +941,9 @@ static bool menu_run( break; case KEYPRESS(0, 0, 'v'): - status = xpool_print( - L"systemd-boot " GIT_VERSION L" (" EFI_MACHINE_TYPE_NAME L"), " - L"UEFI Specification %u.%02u, Vendor %s %u.%02u", + status = xasprintf( + "systemd-boot " GIT_VERSION " (" EFI_MACHINE_TYPE_NAME "), " + "UEFI Specification %u.%02u, Vendor %ls %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff, ST->FirmwareVendor, @@ -964,10 +965,12 @@ static bool menu_run( case KEYPRESS(0, 0, 'r'): err = console_set_mode(CONSOLE_MODE_NEXT); if (err != EFI_SUCCESS) - status = xpool_print(L"Error changing console mode: %r", err); + status = xasprintf_status(err, "Error changing console mode: %m"); else { config->console_mode_efivar = ST->ConOut->Mode->Mode; - status = xpool_print(L"Console mode changed to %ld.", config->console_mode_efivar); + status = xasprintf( + "Console mode changed to %" PRIi64 ".", + config->console_mode_efivar); } new_mode = true; break; @@ -977,10 +980,13 @@ static bool menu_run( err = console_set_mode(config->console_mode == CONSOLE_MODE_KEEP ? console_mode_initial : config->console_mode); if (err != EFI_SUCCESS) - status = xpool_print(L"Error resetting console mode: %r", err); + status = xasprintf_status(err, "Error resetting console mode: %m"); else - status = xpool_print(L"Console mode reset to %s default.", - config->console_mode == CONSOLE_MODE_KEEP ? L"firmware" : L"configuration file"); + status = xasprintf( + "Console mode reset to %s default.", + config->console_mode == CONSOLE_MODE_KEEP ? + "firmware" : + "configuration file"); new_mode = true; break; @@ -993,9 +999,9 @@ static bool menu_run( if (FLAGS_SET(get_os_indications_supported(), EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) { firmware_setup = true; /* Let's make sure the user really wants to do this. */ - status = xpool_print(L"Press Enter to reboot into firmware interface."); + status = xstrdup16(u"Press Enter to reboot into firmware interface."); } else - status = xpool_print(L"Reboot into firmware interface not supported."); + status = xstrdup16(u"Reboot into firmware interface not supported."); break; default: @@ -1329,9 +1335,9 @@ static void config_entry_parse_tries( entry->tries_done = tries_done; entry->path = xstrdup16(path); entry->current_name = xstrdup16(file); - entry->next_name = xpool_print( - L"%.*s%u-%u%s", - prefix_len, + entry->next_name = xasprintf( + "%.*ls%" PRIu64 "-%" PRIu64 "%ls", + (int) prefix_len, file, LESS_BY(tries_left, 1u), MIN(tries_done + 1, (uint64_t) INT_MAX), @@ -1354,7 +1360,7 @@ static void config_entry_bump_counters(ConfigEntry *entry, EFI_FILE *root_dir) { if (!entry->path || !entry->current_name || !entry->next_name) return; - old_path = xpool_print(L"%s\\%s", entry->path, entry->current_name); + old_path = xasprintf("%ls\\%ls", entry->path, entry->current_name); err = root_dir->Open(root_dir, &handle, old_path, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0ULL); if (err != EFI_SUCCESS) @@ -1377,7 +1383,7 @@ static void config_entry_bump_counters(ConfigEntry *entry, EFI_FILE *root_dir) { /* Let's tell the OS that we renamed this file, so that it knows what to rename to the counter-less name on * success */ - new_path = xpool_print(L"%s\\%s", entry->path, entry->next_name); + new_path = xasprintf("%ls\\%ls", entry->path, entry->next_name); efivar_set(LOADER_GUID, L"LoaderBootCountPath", new_path, 0); /* If the file we just renamed is the loader path, then let's update that. */ @@ -1491,7 +1497,7 @@ static void config_entry_add_type1( new = xstr8_to_16(value); if (entry->options) { - char16_t *s = xpool_print(L"%s %s", entry->options, new); + char16_t *s = xasprintf("%ls %ls", entry->options, new); free(entry->options); entry->options = s; } else @@ -1808,7 +1814,7 @@ static void config_title_generate(Config *config) { continue; _cleanup_free_ char16_t *t = config->entries[i]->title_show; - config->entries[i]->title_show = xpool_print(L"%s (%s)", t, config->entries[i]->version); + config->entries[i]->title_show = xasprintf("%ls (%ls)", t, config->entries[i]->version); } if (entries_unique(config->entries, unique, config->entry_count)) @@ -1825,11 +1831,7 @@ static void config_title_generate(Config *config) { continue; _cleanup_free_ char16_t *t = config->entries[i]->title_show; - config->entries[i]->title_show = xpool_print( - L"%s (%.*s)", - t, - strnlen16(config->entries[i]->machine_id, 8), - config->entries[i]->machine_id); + config->entries[i]->title_show = xasprintf("%ls (%.8ls)", t, config->entries[i]->machine_id); } if (entries_unique(config->entries, unique, config->entry_count)) @@ -1841,7 +1843,7 @@ static void config_title_generate(Config *config) { continue; _cleanup_free_ char16_t *t = config->entries[i]->title_show; - config->entries[i]->title_show = xpool_print(L"%s (%s)", t, config->entries[i]->id); + config->entries[i]->title_show = xasprintf("%ls (%ls)", t, config->entries[i]->id); } } @@ -2006,10 +2008,9 @@ static EFI_STATUS boot_windows_bitlocker(void) { for (UINTN i = 0; i < boot_order_size / sizeof(uint16_t); i++) { _cleanup_free_ char *buf = NULL; - char16_t name[sizeof(L"Boot0000")]; UINTN buf_size; - SPrint(name, sizeof(name), L"Boot%04x", (uint32_t) boot_order[i]); + _cleanup_free_ char16_t *name = xasprintf("Boot%04x", boot_order[i]); err = efivar_get_raw(EFI_GLOBAL_GUID, name, &buf, &buf_size); if (err != EFI_SUCCESS) continue; @@ -2202,7 +2203,7 @@ static void config_entry_add_unified( .title = xstrdup16(good_name), .version = xstrdup16(good_version), .device = device, - .loader = xpool_print(L"\\EFI\\Linux\\%s", f->FileName), + .loader = xasprintf("\\EFI\\Linux\\%ls", f->FileName), .sort_key = xstrdup16(good_sort_key), .key = 'l', .tries_done = -1, @@ -2281,9 +2282,9 @@ static EFI_STATUS initrd_prepare( STRV_FOREACH(i, entry->initrd) { _cleanup_free_ char16_t *o = options; if (o) - options = xpool_print(L"%s initrd=%s", o, *i); + options = xasprintf("%ls initrd=%ls", o, *i); else - options = xpool_print(L"initrd=%s", *i); + options = xasprintf("initrd=%ls", *i); _cleanup_(file_closep) EFI_FILE *handle = NULL; err = root->Open(root, &handle, *i, EFI_FILE_MODE_READ, 0); @@ -2314,7 +2315,7 @@ static EFI_STATUS initrd_prepare( if (entry->options) { _cleanup_free_ char16_t *o = options; - options = xpool_print(L"%s %s", o, entry->options); + options = xasprintf("%ls %ls", o, entry->options); } *ret_options = TAKE_PTR(options); @@ -2496,9 +2497,9 @@ static EFI_STATUS secure_boot_discover_keys(Config *config, EFI_FILE *root_dir) entry = xnew(ConfigEntry, 1); *entry = (ConfigEntry) { - .id = xpool_print(L"secure-boot-keys-%s", dirent->FileName), - .title = xpool_print(L"Enroll Secure Boot keys: %s", dirent->FileName), - .path = xpool_print(L"\\loader\\keys\\%s", dirent->FileName), + .id = xasprintf("secure-boot-keys-%ls", dirent->FileName), + .title = xasprintf("Enroll Secure Boot keys: %ls", dirent->FileName), + .path = xasprintf("\\loader\\keys\\%ls", dirent->FileName), .type = LOADER_SECURE_BOOT_KEYS, .tries_done = -1, .tries_left = -1, @@ -2541,10 +2542,10 @@ static void export_variables( efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec); efivar_set(LOADER_GUID, L"LoaderInfo", L"systemd-boot " GIT_VERSION, 0); - infostr = xpool_print(L"%s %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); + infostr = xasprintf("%ls %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", infostr, 0); - typestr = xpool_print(L"UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); + typestr = xasprintf("UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); efivar_set(LOADER_GUID, L"LoaderFirmwareType", typestr, 0); (void) efivar_set_uint64_le(LOADER_GUID, L"LoaderFeatures", loader_features, 0); diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c index 7c29beb759..9c33e33e9c 100644 --- a/src/boot/efi/cpio.c +++ b/src/boot/efi/cpio.c @@ -318,7 +318,7 @@ static char16_t *get_dropin_dir(const EFI_DEVICE_PATH *file_path) { return NULL; convert_efi_path(file_path_str); - return xpool_print(u"%s.extra.d", file_path_str); + return xasprintf("%ls.extra.d", file_path_str); } EFI_STATUS pack_cpio( diff --git a/src/boot/efi/drivers.c b/src/boot/efi/drivers.c index ab360f201c..5962b48366 100644 --- a/src/boot/efi/drivers.c +++ b/src/boot/efi/drivers.c @@ -20,7 +20,7 @@ static EFI_STATUS load_one_driver( assert(loaded_image); assert(fname); - spath = xpool_print(L"\\EFI\\systemd\\drivers\\%s", fname); + spath = xasprintf("\\EFI\\systemd\\drivers\\%ls", fname); err = make_file_device_path(loaded_image->DeviceHandle, spath, &path); if (err != EFI_SUCCESS) return log_error_status(err, "Error making file device path: %m"); diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index bb647f1d78..675878f478 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -114,14 +114,14 @@ static void export_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) { /* if LoaderFirmwareInfo is not set, let's set it */ if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) { _cleanup_free_ char16_t *s = NULL; - s = xpool_print(L"%s %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); + s = xasprintf("%ls %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", s, 0); } /* ditto for LoaderFirmwareType */ if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) { _cleanup_free_ char16_t *s = NULL; - s = xpool_print(L"UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); + s = xasprintf("UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); efivar_set(LOADER_GUID, L"LoaderFirmwareType", s, 0); } @@ -173,7 +173,7 @@ static bool use_load_options( *ret = xstrdup16(shell->Argv[1]); for (size_t i = 2; i < shell->Argc; i++) { _cleanup_free_ char16_t *old = *ret; - *ret = xpool_print(u"%s %s", old, shell->Argv[i]); + *ret = xasprintf("%ls %ls", old, shell->Argv[i]); } mangle_stub_cmdline(*ret); diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h index 101eee1718..a8652e6d8e 100644 --- a/src/boot/efi/util.h +++ b/src/boot/efi/util.h @@ -68,7 +68,6 @@ static inline void *xrealloc(void *p, size_t old_size, size_t new_size) { return t; } -#define xpool_print(fmt, ...) ((char16_t *) ASSERT_SE_PTR(PoolPrint((fmt), ##__VA_ARGS__))) #define xnew(type, n) ((type *) xmalloc_multiply(sizeof(type), (n))) typedef struct { diff --git a/src/boot/efi/vmm.c b/src/boot/efi/vmm.c index 3dfa92b58d..b24d556700 100644 --- a/src/boot/efi/vmm.c +++ b/src/boot/efi/vmm.c @@ -97,9 +97,8 @@ EFI_STATUS vmm_open(EFI_HANDLE *ret_vmm_dev, EFI_FILE **ret_vmm_dir) { for (size_t order = 0;; order++) { _cleanup_free_ EFI_DEVICE_PATH *dp = NULL; - char16_t order_str[STRLEN("VMMBootOrder") + 4 + 1]; - SPrint(order_str, sizeof(order_str), u"VMMBootOrder%04x", order); + _cleanup_free_ char16_t *order_str = xasprintf("VMMBootOrder%04zx", order); dp_err = efivar_get_raw(&(EFI_GUID)VMM_BOOT_ORDER_GUID, order_str, (char**)&dp, NULL); for (size_t i = 0; i < n_handles; i++) { From 9220b2c46bfbdf759b5a777a8bb3109a4d873039 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Tue, 23 Aug 2022 10:51:36 +0200 Subject: [PATCH 7/7] boot: Drop use of Print The custom print helpers have been replaced with explicit checks at the call site to keep this in line with the way it is done in userspace. Any calls where the check has been ommited should not need them as the value is expected to alawys be around. --- src/boot/efi/boot.c | 170 ++++++++++++++++++++----------------- src/boot/efi/secure-boot.c | 6 +- src/boot/efi/stub.c | 2 +- src/boot/efi/util.h | 16 +--- 4 files changed, 99 insertions(+), 95 deletions(-) diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 4dc3921990..af05859a7e 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -443,22 +443,9 @@ static bool unicode_supported(void) { return cache; } -static void ps_string(const char16_t *fmt, const void *value) { - assert(fmt); - if (value) - Print(fmt, value); -} - -static void ps_bool(const char16_t *fmt, bool value) { - assert(fmt); - Print(fmt, yes_no(value)); -} - static bool ps_continue(void) { - if (unicode_supported()) - Print(L"\n─── Press any key to continue, ESC or q to quit. ───\n\n"); - else - Print(L"\n--- Press any key to continue, ESC or q to quit. ---\n\n"); + const char16_t *sep = unicode_supported() ? u"───" : u"---"; + printf("\n%ls Press any key to continue, ESC or q to quit. %ls\n\n", sep, sep); uint64_t key; return console_key_read(&key, UINT64_MAX) == EFI_SUCCESS && @@ -480,112 +467,143 @@ static void print_status(Config *config, char16_t *loaded_image_path) { secure = secure_boot_mode(); (void) efivar_get(LOADER_GUID, L"LoaderDevicePartUUID", &device_part_uuid); - /* We employ some unusual indentation here for readability. */ - - ps_string(L" systemd-boot version: %a\n", GIT_VERSION); - ps_string(L" loaded image: %s\n", loaded_image_path); - ps_string(L" loader partition UUID: %s\n", device_part_uuid); - ps_string(L" architecture: %a\n", EFI_MACHINE_TYPE_NAME); - Print(L" UEFI specification: %u.%02u\n", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); - ps_string(L" firmware vendor: %s\n", ST->FirmwareVendor); - Print(L" firmware version: %u.%02u\n", ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); - Print(L" OS indications: %lu\n", get_os_indications_supported()); - Print(L" secure boot: %s (%s)\n", yes_no(IN_SET(secure, SECURE_BOOT_USER, SECURE_BOOT_DEPLOYED)), secure_boot_mode_to_string(secure)); - ps_bool(L" shim: %s\n", shim_loaded()); - ps_bool(L" TPM: %s\n", tpm_present()); - Print(L" console mode: %d/%ld (%" PRIuN L"x%" PRIuN L" @%ux%u)\n", ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - INT64_C(1), x_max, y_max, screen_width, screen_height); + printf(" systemd-boot version: " GIT_VERSION "\n"); + if (loaded_image_path) + printf(" loaded image: %ls\n", loaded_image_path); + if (device_part_uuid) + printf(" loader partition UUID: %ls\n", device_part_uuid); + printf(" architecture: " EFI_MACHINE_TYPE_NAME "\n"); + printf(" UEFI specification: %u.%02u\n", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); + printf(" firmware vendor: %ls\n", ST->FirmwareVendor); + printf(" firmware version: %u.%02u\n", ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); + printf(" OS indications: %#" PRIx64 "\n", get_os_indications_supported()); + printf(" secure boot: %ls (%ls)\n", + yes_no(IN_SET(secure, SECURE_BOOT_USER, SECURE_BOOT_DEPLOYED)), + secure_boot_mode_to_string(secure)); + printf(" shim: %ls\n", yes_no(shim_loaded())); + printf(" TPM: %ls\n", yes_no(tpm_present())); + printf(" console mode: %i/%" PRIi64 " (%zux%zu @%ux%u)\n", + ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - INT64_C(1), + x_max, y_max, screen_width, screen_height); if (!ps_continue()) return; switch (config->timeout_sec_config) { case TIMEOUT_UNSET: - break; + break; case TIMEOUT_MENU_FORCE: - Print(L" timeout (config): menu-force\n"); break; + printf(" timeout (config): menu-force\n"); + break; case TIMEOUT_MENU_HIDDEN: - Print(L" timeout (config): menu-hidden\n"); break; + printf(" timeout (config): menu-hidden\n"); + break; default: - Print(L" timeout (config): %u s\n", config->timeout_sec_config); + printf(" timeout (config): %u s\n", config->timeout_sec_config); } switch (config->timeout_sec_efivar) { case TIMEOUT_UNSET: - break; + break; case TIMEOUT_MENU_FORCE: - Print(L" timeout (EFI var): menu-force\n"); break; + printf(" timeout (EFI var): menu-force\n"); + break; case TIMEOUT_MENU_HIDDEN: - Print(L" timeout (EFI var): menu-hidden\n"); break; + printf(" timeout (EFI var): menu-hidden\n"); + break; default: - Print(L" timeout (EFI var): %u s\n", config->timeout_sec_efivar); + printf(" timeout (EFI var): %u s\n", config->timeout_sec_efivar); } - ps_string(L" default (config): %s\n", config->entry_default_config); - ps_string(L" default (EFI var): %s\n", config->entry_default_efivar); - ps_string(L" default (one-shot): %s\n", config->entry_oneshot); - ps_string(L" saved entry: %s\n", config->entry_saved); - ps_bool(L" editor: %s\n", config->editor); - ps_bool(L" auto-entries: %s\n", config->auto_entries); - ps_bool(L" auto-firmware: %s\n", config->auto_firmware); - ps_bool(L" beep: %s\n", config->beep); - ps_bool(L" reboot-for-bitlocker: %s\n", config->reboot_for_bitlocker); + if (config->entry_default_config) + printf(" default (config): %ls\n", config->entry_default_config); + if (config->entry_default_efivar) + printf(" default (EFI var): %ls\n", config->entry_default_efivar); + if (config->entry_oneshot) + printf(" default (one-shot): %ls\n", config->entry_oneshot); + if (config->entry_saved) + printf(" saved entry: %ls\n", config->entry_saved); + printf(" editor: %ls\n", yes_no(config->editor)); + printf(" auto-entries: %ls\n", yes_no(config->auto_entries)); + printf(" auto-firmware: %ls\n", yes_no(config->auto_firmware)); + printf(" beep: %ls\n", yes_no(config->beep)); + printf(" reboot-for-bitlocker: %ls\n", yes_no(config->reboot_for_bitlocker)); switch (config->secure_boot_enroll) { case ENROLL_OFF: - Print(L" secure-boot-enroll: off\n"); break; + printf(" secure-boot-enroll: off\n"); + break; case ENROLL_MANUAL: - Print(L" secure-boot-enroll: manual\n"); break; + printf(" secure-boot-enroll: manual\n"); + break; case ENROLL_FORCE: - Print(L" secure-boot-enroll: force\n"); break; + printf(" secure-boot-enroll: force\n"); + break; default: assert_not_reached(); } switch (config->console_mode) { case CONSOLE_MODE_AUTO: - Print(L" console-mode (config): %s\n", L"auto"); break; + printf(" console-mode (config): auto\n"); + break; case CONSOLE_MODE_KEEP: - Print(L" console-mode (config): %s\n", L"keep"); break; + printf(" console-mode (config): keep\n"); + break; case CONSOLE_MODE_FIRMWARE_MAX: - Print(L" console-mode (config): %s\n", L"max"); break; + printf(" console-mode (config): max\n"); + break; default: - Print(L" console-mode (config): %ld\n", config->console_mode); break; + printf(" console-mode (config): %" PRIi64 "\n", config->console_mode); + break; } /* EFI var console mode is always a concrete value or unset. */ if (config->console_mode_efivar != CONSOLE_MODE_KEEP) - Print(L"console-mode (EFI var): %ld\n", config->console_mode_efivar); + printf("console-mode (EFI var): %" PRIi64 "\n", config->console_mode_efivar); if (!ps_continue()) return; for (UINTN i = 0; i < config->entry_count; i++) { ConfigEntry *entry = config->entries[i]; + EFI_DEVICE_PATH *dp = NULL; + _cleanup_free_ char16_t *dp_str = NULL; - _cleanup_free_ char16_t *dp = NULL; - if (entry->device) - (void) device_path_to_str(DevicePathFromHandle(entry->device), &dp); + if (entry->device && + BS->HandleProtocol(entry->device, &(EFI_GUID) EFI_DEVICE_PATH_PROTOCOL_GUID, (void **) &dp) == + EFI_SUCCESS) + (void) device_path_to_str(dp, &dp_str); - Print(L" config entry: %" PRIuN L"/%" PRIuN L"\n", i + 1, config->entry_count); - ps_string(L" id: %s\n", entry->id); - ps_string(L" title: %s\n", entry->title); - ps_string(L" title show: %s\n", streq16(entry->title, entry->title_show) ? NULL : entry->title_show); - ps_string(L" sort key: %s\n", entry->sort_key); - ps_string(L" version: %s\n", entry->version); - ps_string(L" machine-id: %s\n", entry->machine_id); - ps_string(L" device: %s\n", dp); - ps_string(L" loader: %s\n", entry->loader); + printf(" config entry: %zu/%zu\n", i + 1, config->entry_count); + printf(" id: %ls\n", entry->id); + if (entry->title) + printf(" title: %ls\n", entry->title); + if (entry->title_show && !streq16(entry->title, entry->title_show)) + printf(" title show: %ls\n", entry->title_show); + if (entry->sort_key) + printf(" sort key: %ls\n", entry->sort_key); + if (entry->version) + printf(" version: %ls\n", entry->version); + if (entry->machine_id) + printf(" machine-id: %ls\n", entry->machine_id); + if (dp_str) + printf(" device: %ls\n", dp_str); + if (entry->loader) + printf(" loader: %ls\n", entry->loader); STRV_FOREACH(initrd, entry->initrd) - Print(L" initrd: %s\n", *initrd); - ps_string(L" devicetree: %s\n", entry->devicetree); - ps_string(L" options: %s\n", entry->options); - ps_bool(L" internal call: %s\n", !!entry->call); + printf(" initrd: %ls\n", *initrd); + if (entry->devicetree) + printf(" devicetree: %ls\n", entry->devicetree); + if (entry->options) + printf(" options: %ls\n", entry->options); + printf(" internal call: %ls\n", yes_no(!!entry->call)); - ps_bool(L"counting boots: %s\n", entry->tries_left >= 0); + printf("counting boots: %ls\n", yes_no(entry->tries_left >= 0)); if (entry->tries_left >= 0) { - Print(L" tries: %u left, %u done\n", entry->tries_left, entry->tries_done); - Print(L" current path: %s\\%s\n", entry->path, entry->current_name); - Print(L" next path: %s\\%s\n", entry->path, entry->next_name); + printf(" tries: %i left, %i done\n", entry->tries_left, entry->tries_done); + printf(" current path: %ls\\%ls\n", entry->path, entry->current_name); + printf(" next path: %ls\\%ls\n", entry->path, entry->next_name); } if (!ps_continue()) @@ -641,7 +659,7 @@ static bool menu_run( ST->ConOut->EnableCursor(ST->ConOut, false); /* draw a single character to make ClearScreen work on some firmware */ - Print(L" "); + ST->ConOut->OutputString(ST->ConOut, (char16_t *) u" "); err = console_set_mode(config->console_mode_efivar != CONSOLE_MODE_KEEP ? config->console_mode_efivar : config->console_mode); @@ -2729,7 +2747,7 @@ out: EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { InitializeLib(image, sys_table); - debug_hook(L"systemd-boot"); + debug_hook("systemd-boot"); /* Uncomment the next line if you need to wait for debugger. */ // debug_break(); diff --git a/src/boot/efi/secure-boot.c b/src/boot/efi/secure-boot.c index 71c3f13161..2594c8798f 100644 --- a/src/boot/efi/secure-boot.c +++ b/src/boot/efi/secure-boot.c @@ -44,16 +44,16 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) { clear_screen(COLOR_NORMAL); - Print(u"Enrolling secure boot keys from directory: %s\n", path); + printf("Enrolling secure boot keys from directory: %ls\n", path); /* Enrolling secure boot keys is safe to do in virtualized environments as there is nothing * we can brick there. */ if (!in_hypervisor()) { - Print(u"Warning: Enrolling custom Secure Boot keys might soft-brick your machine!\n"); + printf("Warning: Enrolling custom Secure Boot keys might soft-brick your machine!\n"); unsigned timeout_sec = 15; for (;;) { - Print(u"\rEnrolling in %2u s, press any key to abort.", timeout_sec); + printf("\rEnrolling in %2u s, press any key to abort.", timeout_sec); uint64_t key; err = console_key_read(&key, 1000 * 1000); diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 675878f478..be186635ba 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -420,7 +420,7 @@ static EFI_STATUS real_main(EFI_HANDLE image) { EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { InitializeLib(image, sys_table); - debug_hook(L"systemd-stub"); + debug_hook("systemd-stub"); /* Uncomment the next line if you need to wait for debugger. */ // debug_break(); diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h index a8652e6d8e..bbc772d854 100644 --- a/src/boot/efi/util.h +++ b/src/boot/efi/util.h @@ -11,20 +11,6 @@ #define UINTN_MAX (~(UINTN)0) #define INTN_MAX ((INTN)(UINTN_MAX>>1)) -/* gnu-efi format specifiers for integers are fixed to either 64bit with 'l' and 32bit without a size prefix. - * We rely on %u/%d/%x to format regular ints, so ensure the size is what we expect. At the same time, we also - * need specifiers for (U)INTN which are native (pointer) sized. */ -assert_cc(sizeof(int) == sizeof(uint32_t)); -#if __SIZEOF_POINTER__ == 4 -# define PRIuN L"u" -# define PRIiN L"d" -#elif __SIZEOF_POINTER__ == 8 -# define PRIuN L"lu" -# define PRIiN L"ld" -#else -# error "Unexpected pointer size" -#endif - static inline void free(void *p) { if (!p) return; @@ -180,7 +166,7 @@ void debug_break(void); extern uint8_t _text, _data; /* Report the relocated position of text and data sections so that a debugger * can attach to us. See debug-sd-boot.sh for how this can be done. */ -# define debug_hook(identity) Print(identity L"@0x%lx,0x%lx\n", POINTER_TO_PHYSICAL_ADDRESS(&_text), POINTER_TO_PHYSICAL_ADDRESS(&_data)) +# define debug_hook(identity) printf(identity "@%p,%p\n", &_text, &_data) #else # define debug_hook(identity) #endif