mirror of
https://github.com/systemd/systemd
synced 2026-03-28 01:34:52 +01:00
Compare commits
23 Commits
adbd80f510
...
73bf0f2ace
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73bf0f2ace | ||
|
|
28078aa5cc | ||
|
|
46ebc0a6f5 | ||
|
|
3d7e273dba | ||
|
|
a51f6dba60 | ||
|
|
e6e6ca8251 | ||
|
|
533f11c529 | ||
|
|
3448711b7e | ||
|
|
89edc243e4 | ||
|
|
20240b071b | ||
|
|
d1469b7095 | ||
|
|
f9755203b9 | ||
|
|
6aebfec3a5 | ||
|
|
1b965abc66 | ||
|
|
13239c86e0 | ||
|
|
be991d7678 | ||
|
|
7ab7547a40 | ||
|
|
84b5e291e2 | ||
|
|
a4588af942 | ||
|
|
2ea7eb003c | ||
|
|
d7ac09520b | ||
|
|
134144abc8 | ||
|
|
bd8ea741a4 |
2
.github/workflows/build_test.yml
vendored
2
.github/workflows/build_test.yml
vendored
@ -20,9 +20,9 @@ jobs:
|
||||
env:
|
||||
- { COMPILER: "gcc", COMPILER_VERSION: "10" }
|
||||
- { COMPILER: "gcc", COMPILER_VERSION: "11" }
|
||||
- { COMPILER: "clang", COMPILER_VERSION: "10" }
|
||||
- { COMPILER: "clang", COMPILER_VERSION: "11" }
|
||||
- { COMPILER: "clang", COMPILER_VERSION: "12" }
|
||||
- { COMPILER: "clang", COMPILER_VERSION: "13" }
|
||||
env: ${{ matrix.env }}
|
||||
steps:
|
||||
- name: Repository checkout
|
||||
|
||||
@ -151,6 +151,16 @@
|
||||
<listitem><para>Decrease the timeout</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><keycap>r</keycap></term>
|
||||
<listitem><para>Change screen resolution, skipping any unsupported modes.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><keycap>R</keycap></term>
|
||||
<listitem><para>Reset screen resolution to firmware or configuration file default.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><keycap>p</keycap></term>
|
||||
<listitem><para>Print status</para></listitem>
|
||||
|
||||
@ -30,14 +30,16 @@
|
||||
/* The maximum size of the file we'll read in one go in read_full_file() (64M). */
|
||||
#define READ_FULL_BYTES_MAX (64U*1024U*1024U - 1U)
|
||||
|
||||
/* The maximum size of virtual files we'll read in one go in read_virtual_file() (4M). Note that this limit
|
||||
* is different (and much lower) than the READ_FULL_BYTES_MAX limit. This reflects the fact that we use
|
||||
* different strategies for reading virtual and regular files: virtual files are generally size constrained:
|
||||
* there we allocate the full buffer size in advance. Regular files OTOH can be much larger, and here we grow
|
||||
* the allocations exponentially in a loop. In glibc large allocations are immediately backed by mmap()
|
||||
* making them relatively slow (measurably so). Thus, when allocating the full buffer in advance the large
|
||||
* limit is a problem. When allocating piecemeal it's not. Hence pick two distinct limits. */
|
||||
#define READ_VIRTUAL_BYTES_MAX (4U*1024U*1024U - 1U)
|
||||
/* The maximum size of virtual files (i.e. procfs, sysfs, and other virtual "API" files) we'll read in one go
|
||||
* in read_virtual_file(). Note that this limit is different (and much lower) than the READ_FULL_BYTES_MAX
|
||||
* limit. This reflects the fact that we use different strategies for reading virtual and regular files:
|
||||
* virtual files we generally have to read in a single read() syscall since the kernel doesn't support
|
||||
* continuation read()s for them. Thankfully they are somewhat size constrained. Thus we can allocate the
|
||||
* full potential buffer in advance. Regular files OTOH can be much larger, and there we grow the allocations
|
||||
* exponentially in a loop. We use a size limit of 4M-2 because 4M-1 is the maximum buffer that /proc/sys/
|
||||
* allows us to read() (larger reads will fail with ENOMEM), and we want to read one extra byte so that we
|
||||
* can detect EOFs. */
|
||||
#define READ_VIRTUAL_BYTES_MAX (4U*1024U*1024U - 2U)
|
||||
|
||||
int fopen_unlocked(const char *path, const char *options, FILE **ret) {
|
||||
assert(ret);
|
||||
@ -393,7 +395,7 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
|
||||
* contents* may be returned. (Though the read is still done using one syscall.) Returns 0 on
|
||||
* partial success, 1 if untruncated contents were read. */
|
||||
|
||||
fd = open(filename, O_RDONLY|O_CLOEXEC);
|
||||
fd = open(filename, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
|
||||
@ -3,15 +3,15 @@
|
||||
#include "nulstr-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
bool nulstr_contains(const char *nulstr, const char *needle) {
|
||||
const char* nulstr_get(const char *nulstr, const char *needle) {
|
||||
const char *i;
|
||||
|
||||
if (!nulstr)
|
||||
return false;
|
||||
return NULL;
|
||||
|
||||
NULSTR_FOREACH(i, nulstr)
|
||||
if (streq(i, needle))
|
||||
return true;
|
||||
return i;
|
||||
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -10,4 +10,8 @@
|
||||
#define NULSTR_FOREACH_PAIR(i, j, l) \
|
||||
for ((i) = (l), (j) = strchr((i), 0)+1; (i) && *(i); (i) = strchr((j), 0)+1, (j) = *(i) ? strchr((i), 0)+1 : (i))
|
||||
|
||||
bool nulstr_contains(const char *nulstr, const char *needle);
|
||||
const char* nulstr_get(const char *nulstr, const char *needle);
|
||||
|
||||
static inline bool nulstr_contains(const char *nulstr, const char *needle) {
|
||||
return nulstr_get(nulstr, needle);
|
||||
}
|
||||
|
||||
@ -1254,7 +1254,7 @@ int safe_fork_full(
|
||||
|
||||
pid_t original_pid, pid;
|
||||
sigset_t saved_ss, ss;
|
||||
_cleanup_(restore_sigsetp) sigset_t *saved_ssp = NULL;
|
||||
_unused_ _cleanup_(restore_sigsetp) sigset_t *saved_ssp = NULL;
|
||||
bool block_signals = false, block_all = false;
|
||||
int prio, r;
|
||||
|
||||
|
||||
@ -793,7 +793,7 @@ bool ifname_valid_full(const char *p, IfnameValidFlags flags) {
|
||||
|
||||
/* Let's refuse "all" and "default" as interface name, to avoid collisions with the special sysctl
|
||||
* directories /proc/sys/net/{ipv4,ipv6}/conf/{all,default} */
|
||||
if (STR_IN_SET(p, "all", "default"))
|
||||
if (!FLAGS_SET(flags, IFNAME_VALID_SPECIAL) && STR_IN_SET(p, "all", "default"))
|
||||
return false;
|
||||
|
||||
for (const char *t = p; *t; t++) {
|
||||
|
||||
@ -135,9 +135,10 @@ int ip_tos_to_string_alloc(int i, char **s);
|
||||
int ip_tos_from_string(const char *s);
|
||||
|
||||
typedef enum {
|
||||
IFNAME_VALID_ALTERNATIVE = 1 << 0,
|
||||
IFNAME_VALID_NUMERIC = 1 << 1,
|
||||
_IFNAME_VALID_ALL = IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC,
|
||||
IFNAME_VALID_ALTERNATIVE = 1 << 0, /* Allow "altnames" too */
|
||||
IFNAME_VALID_NUMERIC = 1 << 1, /* Allow decimal formatted ifindexes too */
|
||||
IFNAME_VALID_SPECIAL = 1 << 2, /* Allow the special names "all" and "default" */
|
||||
_IFNAME_VALID_ALL = IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC | IFNAME_VALID_SPECIAL,
|
||||
} IfnameValidFlags;
|
||||
bool ifname_valid_char(char a);
|
||||
bool ifname_valid_full(const char *p, IfnameValidFlags flags);
|
||||
|
||||
@ -5,11 +5,13 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "af-list.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "path-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "sysctl-util.h"
|
||||
|
||||
@ -36,7 +38,7 @@ char *sysctl_normalize(char *s) {
|
||||
path_simplify(s);
|
||||
|
||||
/* Kill the leading slash, but keep the first character of the string in the same place. */
|
||||
if (*s == '/' && *(s+1))
|
||||
if (s[0] == '/' && s[1] != 0)
|
||||
memmove(s, s+1, strlen(s));
|
||||
|
||||
return s;
|
||||
@ -44,25 +46,19 @@ char *sysctl_normalize(char *s) {
|
||||
|
||||
int sysctl_write(const char *property, const char *value) {
|
||||
char *p;
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
assert(property);
|
||||
assert(value);
|
||||
|
||||
log_debug("Setting '%s' to '%.*s'.", property, (int) strcspn(value, NEWLINE), value);
|
||||
|
||||
p = strjoina("/proc/sys/", property);
|
||||
fd = open(p, O_WRONLY|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
if (!endswith(value, "\n"))
|
||||
value = strjoina(value, "\n");
|
||||
path_simplify(p);
|
||||
if (!path_is_normalized(p))
|
||||
return -EINVAL;
|
||||
|
||||
if (write(fd, value, strlen(value)) < 0)
|
||||
return -errno;
|
||||
log_debug("Setting '%s' to '%s'", p, value);
|
||||
|
||||
return 0;
|
||||
return write_string_file(p, value, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
|
||||
}
|
||||
|
||||
int sysctl_writef(const char *property, const char *format, ...) {
|
||||
@ -83,48 +79,59 @@ int sysctl_writef(const char *property, const char *format, ...) {
|
||||
int sysctl_write_ip_property(int af, const char *ifname, const char *property, const char *value) {
|
||||
const char *p;
|
||||
|
||||
assert(IN_SET(af, AF_INET, AF_INET6));
|
||||
assert(property);
|
||||
assert(value);
|
||||
|
||||
p = strjoina("/proc/sys/net/ipv", af == AF_INET ? "4" : "6",
|
||||
ifname ? "/conf/" : "", strempty(ifname),
|
||||
property[0] == '/' ? "" : "/", property);
|
||||
if (!IN_SET(af, AF_INET, AF_INET6))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
log_debug("Setting '%s' to '%s'", p, value);
|
||||
if (ifname) {
|
||||
if (!ifname_valid_full(ifname, IFNAME_VALID_SPECIAL))
|
||||
return -EINVAL;
|
||||
|
||||
return write_string_file(p, value, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
|
||||
p = strjoina("net/", af_to_ipv4_ipv6(af), "/conf/", ifname, "/", property);
|
||||
} else
|
||||
p = strjoina("net/", af_to_ipv4_ipv6(af), "/", property);
|
||||
|
||||
return sysctl_write(p, value);
|
||||
}
|
||||
|
||||
int sysctl_read(const char *property, char **ret) {
|
||||
char *p;
|
||||
|
||||
assert(property);
|
||||
assert(ret);
|
||||
|
||||
p = strjoina("/proc/sys/", property);
|
||||
return read_full_virtual_file(p, ret, NULL);
|
||||
}
|
||||
|
||||
int sysctl_read_ip_property(int af, const char *ifname, const char *property, char **ret) {
|
||||
_cleanup_free_ char *value = NULL;
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(IN_SET(af, AF_INET, AF_INET6));
|
||||
assert(property);
|
||||
|
||||
p = strjoina("/proc/sys/net/ipv", af == AF_INET ? "4" : "6",
|
||||
ifname ? "/conf/" : "", strempty(ifname),
|
||||
property[0] == '/' ? "" : "/", property);
|
||||
p = strjoina("/proc/sys/", property);
|
||||
|
||||
r = read_full_virtual_file(p, &value, NULL);
|
||||
path_simplify(p);
|
||||
if (!path_is_normalized(p)) /* Filter out attempts to write to /proc/sys/../../…, just in case */
|
||||
return -EINVAL;
|
||||
|
||||
r = read_full_virtual_file(p, ret, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
truncate_nl(value);
|
||||
if (ret)
|
||||
*ret = TAKE_PTR(value);
|
||||
delete_trailing_chars(*ret, NEWLINE);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int sysctl_read_ip_property(int af, const char *ifname, const char *property, char **ret) {
|
||||
const char *p;
|
||||
|
||||
assert(property);
|
||||
|
||||
if (!IN_SET(af, AF_INET, AF_INET6))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
if (ifname) {
|
||||
if (!ifname_valid_full(ifname, IFNAME_VALID_SPECIAL))
|
||||
return -EINVAL;
|
||||
|
||||
p = strjoina("net/", af_to_ipv4_ipv6(af), "/conf/", ifname, "/", property);
|
||||
} else
|
||||
p = strjoina("net/", af_to_ipv4_ipv6(af), "/", property);
|
||||
|
||||
return sysctl_read(p, ret);
|
||||
}
|
||||
|
||||
@ -286,7 +286,8 @@ int unit_file_build_name_map(
|
||||
|
||||
FOREACH_DIRENT(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) {
|
||||
char *filename;
|
||||
_cleanup_free_ char *_filename_free = NULL, *simplified = NULL;
|
||||
_unused_ _cleanup_free_ char *_filename_free = NULL;
|
||||
_cleanup_free_ char *simplified = NULL;
|
||||
const char *suffix, *dst = NULL;
|
||||
bool valid_unit_name;
|
||||
|
||||
|
||||
@ -69,8 +69,8 @@ typedef struct {
|
||||
BOOLEAN auto_entries;
|
||||
BOOLEAN auto_firmware;
|
||||
BOOLEAN force_menu;
|
||||
UINTN console_mode;
|
||||
enum console_mode_change_type console_mode_change;
|
||||
INT64 console_mode;
|
||||
INT64 console_mode_efivar;
|
||||
RandomSeedMode random_seed_mode;
|
||||
} Config;
|
||||
|
||||
@ -370,13 +370,13 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
|
||||
UINTN timeout;
|
||||
BOOLEAN modevar;
|
||||
_cleanup_freepool_ CHAR16 *partstr = NULL, *defaultstr = NULL;
|
||||
UINTN x, y;
|
||||
UINTN x_max, y_max;
|
||||
|
||||
assert(config);
|
||||
assert(loaded_image_path);
|
||||
|
||||
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, COLOR_NORMAL);
|
||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||
clear_screen(COLOR_NORMAL);
|
||||
console_query_mode(&x_max, &y_max);
|
||||
|
||||
Print(L"systemd-boot version: " GIT_VERSION "\n");
|
||||
Print(L"architecture: " EFI_MACHINE_TYPE_NAME "\n");
|
||||
@ -384,10 +384,8 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
|
||||
Print(L"UEFI specification: %d.%02d\n", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
|
||||
Print(L"firmware vendor: %s\n", ST->FirmwareVendor);
|
||||
Print(L"firmware version: %d.%02d\n", ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
|
||||
|
||||
if (uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x, &y) == EFI_SUCCESS)
|
||||
Print(L"console size: %d x %d\n", x, y);
|
||||
|
||||
Print(L"console mode: %d/%ld\n", ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - 1LL);
|
||||
Print(L"console size: %d x %d\n", x_max, y_max);
|
||||
Print(L"SecureBoot: %s\n", yes_no(secure_boot_enabled()));
|
||||
|
||||
if (efivar_get_boolean_u8(EFI_GLOBAL_GUID, L"SetupMode", &modevar) == EFI_SUCCESS)
|
||||
@ -499,8 +497,6 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
|
||||
Print(L"\n--- press key ---\n\n");
|
||||
console_key_read(&key, 0);
|
||||
}
|
||||
|
||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||
}
|
||||
|
||||
static BOOLEAN menu_run(
|
||||
@ -513,107 +509,115 @@ static BOOLEAN menu_run(
|
||||
assert(loaded_image_path);
|
||||
|
||||
EFI_STATUS err;
|
||||
UINTN visible_max;
|
||||
UINTN visible_max = 0;
|
||||
UINTN idx_highlight = config->idx_default;
|
||||
UINTN idx_highlight_prev = 0;
|
||||
UINTN idx_first;
|
||||
UINTN idx_last;
|
||||
BOOLEAN refresh = TRUE;
|
||||
BOOLEAN highlight = FALSE;
|
||||
UINTN line_width = 0;
|
||||
UINTN entry_padding = 3;
|
||||
CHAR16 **lines;
|
||||
UINTN x_start;
|
||||
UINTN y_start;
|
||||
UINTN x_max;
|
||||
UINTN y_max;
|
||||
CHAR16 *status = NULL;
|
||||
CHAR16 *clearline;
|
||||
UINTN idx_first = 0, idx_last = 0;
|
||||
BOOLEAN new_mode = TRUE, clear = TRUE;
|
||||
BOOLEAN refresh = TRUE, highlight = FALSE;
|
||||
UINTN x_start = 0, y_start = 0, y_status = 0;
|
||||
UINTN x_max, y_max;
|
||||
CHAR16 **lines = NULL, *status = NULL, *clearline = NULL;
|
||||
UINTN timeout_remain = config->timeout_sec;
|
||||
INT16 idx;
|
||||
BOOLEAN exit = FALSE;
|
||||
BOOLEAN run = TRUE;
|
||||
BOOLEAN exit = FALSE, run = TRUE;
|
||||
INT64 console_mode_initial = ST->ConOut->Mode->Mode, console_mode_efivar_saved = config->console_mode_efivar;
|
||||
|
||||
graphics_mode(FALSE);
|
||||
uefi_call_wrapper(ST->ConIn->Reset, 2, ST->ConIn, FALSE);
|
||||
uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE);
|
||||
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, COLOR_NORMAL);
|
||||
|
||||
/* draw a single character to make ClearScreen work on some firmware */
|
||||
Print(L" ");
|
||||
|
||||
if (config->console_mode_change != CONSOLE_MODE_KEEP) {
|
||||
err = console_set_mode(&config->console_mode, config->console_mode_change);
|
||||
if (EFI_ERROR(err)) {
|
||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||
log_error_stall(L"Error switching console mode to %lu: %r", (UINT64)config->console_mode, err);
|
||||
}
|
||||
} else
|
||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||
|
||||
err = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x_max, &y_max);
|
||||
err = console_set_mode(config->console_mode_efivar != CONSOLE_MODE_KEEP ?
|
||||
config->console_mode_efivar : config->console_mode);
|
||||
if (EFI_ERROR(err)) {
|
||||
x_max = 80;
|
||||
y_max = 25;
|
||||
clear_screen(COLOR_NORMAL);
|
||||
log_error_stall(L"Error switching console mode: %r", err);
|
||||
}
|
||||
|
||||
visible_max = y_max - 2;
|
||||
|
||||
/* Drawing entries starts at idx_first until idx_last. We want to make
|
||||
* sure that idx_highlight is centered, but not if we are close to the
|
||||
* beginning/end of the entry list. Otherwise we would have a half-empty
|
||||
* screen. */
|
||||
if (config->entry_count <= visible_max || idx_highlight <= visible_max / 2)
|
||||
idx_first = 0;
|
||||
else if (idx_highlight >= config->entry_count - (visible_max / 2))
|
||||
idx_first = config->entry_count - visible_max;
|
||||
else
|
||||
idx_first = idx_highlight - (visible_max / 2);
|
||||
idx_last = idx_first + visible_max - 1;
|
||||
|
||||
/* length of the longest entry */
|
||||
for (UINTN i = 0; i < config->entry_count; i++)
|
||||
line_width = MAX(line_width, StrLen(config->entries[i]->title_show));
|
||||
line_width = MIN(line_width + 2 * entry_padding, x_max);
|
||||
|
||||
/* offsets to center the entries on the screen */
|
||||
x_start = (x_max - (line_width)) / 2;
|
||||
if (config->entry_count < visible_max)
|
||||
y_start = ((visible_max - config->entry_count) / 2) + 1;
|
||||
else
|
||||
y_start = 0;
|
||||
|
||||
/* menu entries title lines */
|
||||
lines = AllocatePool(sizeof(CHAR16 *) * config->entry_count);
|
||||
for (UINTN i = 0; i < config->entry_count; i++) {
|
||||
UINTN j;
|
||||
|
||||
lines[i] = AllocatePool(((line_width + 1) * sizeof(CHAR16)));
|
||||
UINTN padding = (line_width - MIN(StrLen(config->entries[i]->title_show), line_width)) / 2;
|
||||
|
||||
for (j = 0; j < padding; j++)
|
||||
lines[i][j] = ' ';
|
||||
|
||||
for (UINTN k = 0; config->entries[i]->title_show[k] != '\0' && j < line_width; j++, k++)
|
||||
lines[i][j] = config->entries[i]->title_show[k];
|
||||
|
||||
for (; j < line_width; j++)
|
||||
lines[i][j] = ' ';
|
||||
lines[i][line_width] = '\0';
|
||||
}
|
||||
|
||||
clearline = AllocatePool((x_max+1) * sizeof(CHAR16));
|
||||
for (UINTN i = 0; i < x_max; i++)
|
||||
clearline[i] = ' ';
|
||||
clearline[x_max] = 0;
|
||||
|
||||
while (!exit) {
|
||||
UINT64 key;
|
||||
|
||||
if (refresh) {
|
||||
if (new_mode) {
|
||||
UINTN line_width = 0, entry_padding = 3;
|
||||
|
||||
console_query_mode(&x_max, &y_max);
|
||||
|
||||
/* account for padding+status */
|
||||
visible_max = y_max - 2;
|
||||
|
||||
/* Drawing entries starts at idx_first until idx_last. We want to make
|
||||
* sure that idx_highlight is centered, but not if we are close to the
|
||||
* beginning/end of the entry list. Otherwise we would have a half-empty
|
||||
* screen. */
|
||||
if (config->entry_count <= visible_max || idx_highlight <= visible_max / 2)
|
||||
idx_first = 0;
|
||||
else if (idx_highlight >= config->entry_count - (visible_max / 2))
|
||||
idx_first = config->entry_count - visible_max;
|
||||
else
|
||||
idx_first = idx_highlight - (visible_max / 2);
|
||||
idx_last = idx_first + visible_max - 1;
|
||||
|
||||
/* length of the longest entry */
|
||||
for (UINTN i = 0; i < config->entry_count; i++)
|
||||
line_width = MAX(line_width, StrLen(config->entries[i]->title_show));
|
||||
line_width = MIN(line_width + 2 * entry_padding, x_max);
|
||||
|
||||
/* offsets to center the entries on the screen */
|
||||
x_start = (x_max - (line_width)) / 2;
|
||||
if (config->entry_count < visible_max)
|
||||
y_start = ((visible_max - config->entry_count) / 2) + 1;
|
||||
else
|
||||
y_start = 0;
|
||||
|
||||
/* Put status line after the entry list, but give it some breathing room. */
|
||||
y_status = MIN(y_start + MIN(visible_max, config->entry_count) + 4, y_max - 1);
|
||||
|
||||
if (lines) {
|
||||
for (UINTN i = 0; i < config->entry_count; i++)
|
||||
FreePool(lines[i]);
|
||||
FreePool(lines);
|
||||
FreePool(clearline);
|
||||
}
|
||||
|
||||
/* menu entries title lines */
|
||||
lines = AllocatePool(sizeof(CHAR16 *) * config->entry_count);
|
||||
for (UINTN i = 0; i < config->entry_count; i++) {
|
||||
if (i < idx_first || i > idx_last)
|
||||
continue;
|
||||
UINTN j, padding;
|
||||
|
||||
lines[i] = AllocatePool(((line_width + 1) * sizeof(CHAR16)));
|
||||
padding = (line_width - MIN(StrLen(config->entries[i]->title_show), line_width)) / 2;
|
||||
|
||||
for (j = 0; j < padding; j++)
|
||||
lines[i][j] = ' ';
|
||||
|
||||
for (UINTN k = 0; config->entries[i]->title_show[k] != '\0' && j < line_width; j++, k++)
|
||||
lines[i][j] = config->entries[i]->title_show[k];
|
||||
|
||||
for (; j < line_width; j++)
|
||||
lines[i][j] = ' ';
|
||||
lines[i][line_width] = '\0';
|
||||
}
|
||||
|
||||
clearline = AllocatePool((x_max+1) * sizeof(CHAR16));
|
||||
for (UINTN i = 0; i < x_max; i++)
|
||||
clearline[i] = ' ';
|
||||
clearline[x_max] = 0;
|
||||
|
||||
new_mode = FALSE;
|
||||
clear = TRUE;
|
||||
}
|
||||
|
||||
if (clear) {
|
||||
clear_screen(COLOR_NORMAL);
|
||||
clear = FALSE;
|
||||
refresh = TRUE;
|
||||
}
|
||||
|
||||
if (refresh) {
|
||||
for (UINTN i = idx_first; i <= idx_last && i < config->entry_count; i++) {
|
||||
print_at(x_start, y_start + i - idx_first,
|
||||
(i == idx_highlight) ? COLOR_HIGHLIGHT : COLOR_ENTRY,
|
||||
lines[i]);
|
||||
@ -649,7 +653,7 @@ static BOOLEAN menu_run(
|
||||
x = (x_max - len) / 2;
|
||||
else
|
||||
x = 0;
|
||||
print_at(0, y_max - 1, COLOR_NORMAL, clearline + (x_max - x));
|
||||
print_at(0, y_status, COLOR_NORMAL, clearline + (x_max - x));
|
||||
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, status);
|
||||
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1 + x + len);
|
||||
}
|
||||
@ -671,7 +675,7 @@ static BOOLEAN menu_run(
|
||||
if (status) {
|
||||
FreePool(status);
|
||||
status = NULL;
|
||||
print_at(0, y_max - 1, COLOR_NORMAL, clearline + 1);
|
||||
print_at(0, y_status, COLOR_NORMAL, clearline + 1);
|
||||
}
|
||||
|
||||
idx_highlight_prev = idx_highlight;
|
||||
@ -733,7 +737,7 @@ static BOOLEAN menu_run(
|
||||
case KEYPRESS(0, 0, 'H'):
|
||||
case KEYPRESS(0, 0, '?'):
|
||||
/* This must stay below 80 characters! Q/v/Ctrl+l deliberately not advertised. */
|
||||
status = StrDuplicate(L"(d)efault (t/T)timeout (e)dit (p)rint (h)elp");
|
||||
status = StrDuplicate(L"(d)efault (t/T)timeout (e)dit (r/R)resolution (p)rint (h)elp");
|
||||
break;
|
||||
|
||||
case KEYPRESS(0, 0, 'Q'):
|
||||
@ -813,9 +817,9 @@ static BOOLEAN menu_run(
|
||||
* causing a scroll to happen that screws with our beautiful boot loader output.
|
||||
* Since we cannot paint the last character of the edit line, we simply start
|
||||
* at x-offset 1 for symmetry. */
|
||||
print_at(1, y_max - 1, COLOR_EDIT, clearline + 2);
|
||||
exit = line_edit(config->entries[idx_highlight]->options, &config->options_edit, x_max-2, y_max-1);
|
||||
print_at(1, y_max - 1, COLOR_NORMAL, clearline + 2);
|
||||
print_at(1, y_status, COLOR_EDIT, clearline + 2);
|
||||
exit = line_edit(config->entries[idx_highlight]->options, &config->options_edit, x_max - 2, y_status);
|
||||
print_at(1, y_status, COLOR_NORMAL, clearline + 2);
|
||||
break;
|
||||
|
||||
case KEYPRESS(0, 0, 'v'):
|
||||
@ -827,12 +831,35 @@ static BOOLEAN menu_run(
|
||||
case KEYPRESS(0, 0, 'p'):
|
||||
case KEYPRESS(0, 0, 'P'):
|
||||
print_status(config, loaded_image_path);
|
||||
refresh = TRUE;
|
||||
clear = TRUE;
|
||||
break;
|
||||
|
||||
case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'l'):
|
||||
case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('l')):
|
||||
refresh = TRUE;
|
||||
clear = TRUE;
|
||||
break;
|
||||
|
||||
case KEYPRESS(0, 0, 'r'):
|
||||
err = console_set_mode(CONSOLE_MODE_NEXT);
|
||||
if (EFI_ERROR(err))
|
||||
status = PoolPrint(L"Error changing console mode: %r", err);
|
||||
else {
|
||||
config->console_mode_efivar = ST->ConOut->Mode->Mode;
|
||||
status = PoolPrint(L"Console mode changed to %ld.", config->console_mode_efivar);
|
||||
}
|
||||
new_mode = TRUE;
|
||||
break;
|
||||
|
||||
case KEYPRESS(0, 0, 'R'):
|
||||
config->console_mode_efivar = CONSOLE_MODE_KEEP;
|
||||
err = console_set_mode(config->console_mode == CONSOLE_MODE_KEEP ?
|
||||
console_mode_initial : config->console_mode);
|
||||
if (EFI_ERROR(err))
|
||||
status = PoolPrint(L"Error resetting console mode: %r", err);
|
||||
else
|
||||
status = PoolPrint(L"Console mode reset to %s default.",
|
||||
config->console_mode == CONSOLE_MODE_KEEP ? L"firmware" : L"configuration file");
|
||||
new_mode = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -860,13 +887,23 @@ static BOOLEAN menu_run(
|
||||
|
||||
*chosen_entry = config->entries[idx_highlight];
|
||||
|
||||
/* The user is likely to cycle through several modes before
|
||||
* deciding to keep one. Therefore, we update the EFI var after
|
||||
* we left the menu to reduce nvram writes. */
|
||||
if (console_mode_efivar_saved != config->console_mode_efivar) {
|
||||
if (config->console_mode_efivar == CONSOLE_MODE_KEEP)
|
||||
efivar_set(LOADER_GUID, L"LoaderConfigConsoleMode", NULL, EFI_VARIABLE_NON_VOLATILE);
|
||||
else
|
||||
efivar_set_uint_string(LOADER_GUID, L"LoaderConfigConsoleMode",
|
||||
config->console_mode_efivar, EFI_VARIABLE_NON_VOLATILE);
|
||||
}
|
||||
|
||||
for (UINTN i = 0; i < config->entry_count; i++)
|
||||
FreePool(lines[i]);
|
||||
FreePool(lines);
|
||||
FreePool(clearline);
|
||||
|
||||
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, COLOR_NORMAL);
|
||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||
clear_screen(COLOR_NORMAL);
|
||||
return run;
|
||||
}
|
||||
|
||||
@ -1027,17 +1064,16 @@ static VOID config_defaults_load_from_file(Config *config, CHAR8 *content) {
|
||||
|
||||
if (strcmpa((CHAR8 *)"console-mode", key) == 0) {
|
||||
if (strcmpa((CHAR8 *)"auto", value) == 0)
|
||||
config->console_mode_change = CONSOLE_MODE_AUTO;
|
||||
config->console_mode = CONSOLE_MODE_AUTO;
|
||||
else if (strcmpa((CHAR8 *)"max", value) == 0)
|
||||
config->console_mode_change = CONSOLE_MODE_MAX;
|
||||
config->console_mode = CONSOLE_MODE_FIRMWARE_MAX;
|
||||
else if (strcmpa((CHAR8 *)"keep", value) == 0)
|
||||
config->console_mode_change = CONSOLE_MODE_KEEP;
|
||||
config->console_mode = CONSOLE_MODE_KEEP;
|
||||
else {
|
||||
_cleanup_freepool_ CHAR16 *s = NULL;
|
||||
|
||||
s = stra_to_str(value);
|
||||
config->console_mode = Atoi(s);
|
||||
config->console_mode_change = CONSOLE_MODE_SET;
|
||||
config->console_mode = MIN(Atoi(s), (UINTN)CONSOLE_MODE_RANGE_MAX);
|
||||
}
|
||||
|
||||
continue;
|
||||
@ -1410,7 +1446,7 @@ static VOID config_entry_add_from_file(
|
||||
|
||||
static VOID config_load_defaults(Config *config, EFI_FILE *root_dir) {
|
||||
_cleanup_freepool_ CHAR8 *content = NULL;
|
||||
UINTN sec;
|
||||
UINTN value;
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(root_dir);
|
||||
@ -1421,27 +1457,33 @@ static VOID config_load_defaults(Config *config, EFI_FILE *root_dir) {
|
||||
.auto_firmware = TRUE,
|
||||
.random_seed_mode = RANDOM_SEED_WITH_SYSTEM_TOKEN,
|
||||
.idx_default_efivar = -1,
|
||||
.console_mode = CONSOLE_MODE_KEEP,
|
||||
.console_mode_efivar = CONSOLE_MODE_KEEP,
|
||||
};
|
||||
|
||||
err = file_read(root_dir, L"\\loader\\loader.conf", 0, 0, &content, NULL);
|
||||
if (!EFI_ERROR(err))
|
||||
config_defaults_load_from_file(config, content);
|
||||
|
||||
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeout", &sec);
|
||||
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeout", &value);
|
||||
if (!EFI_ERROR(err)) {
|
||||
config->timeout_sec_efivar = sec > INTN_MAX ? INTN_MAX : sec;
|
||||
config->timeout_sec = sec;
|
||||
config->timeout_sec_efivar = value > INTN_MAX ? INTN_MAX : value;
|
||||
config->timeout_sec = value;
|
||||
} else
|
||||
config->timeout_sec_efivar = -1;
|
||||
|
||||
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeoutOneShot", &sec);
|
||||
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeoutOneShot", &value);
|
||||
if (!EFI_ERROR(err)) {
|
||||
/* Unset variable now, after all it's "one shot". */
|
||||
(void) efivar_set(LOADER_GUID, L"LoaderConfigTimeoutOneShot", NULL, EFI_VARIABLE_NON_VOLATILE);
|
||||
|
||||
config->timeout_sec = sec;
|
||||
config->timeout_sec = value;
|
||||
config->force_menu = TRUE; /* force the menu when this is set */
|
||||
}
|
||||
|
||||
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigConsoleMode", &value);
|
||||
if (!EFI_ERROR(err))
|
||||
config->console_mode_efivar = value;
|
||||
}
|
||||
|
||||
static VOID config_load_entries(
|
||||
|
||||
@ -8,6 +8,9 @@
|
||||
|
||||
#define SYSTEM_FONT_WIDTH 8
|
||||
#define SYSTEM_FONT_HEIGHT 19
|
||||
#define HORIZONTAL_MAX_OK 1920
|
||||
#define VERTICAL_MAX_OK 1080
|
||||
#define VIEWPORT_RATIO 10
|
||||
|
||||
#define EFI_SIMPLE_TEXT_INPUT_EX_GUID \
|
||||
&(const EFI_GUID) EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID
|
||||
@ -115,51 +118,36 @@ EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFI_STATUS change_mode(UINTN mode) {
|
||||
static EFI_STATUS change_mode(INT64 mode) {
|
||||
EFI_STATUS err;
|
||||
INT32 old_mode;
|
||||
|
||||
/* SetMode expects a UINTN, so make sure these values are sane. */
|
||||
mode = CLAMP(mode, CONSOLE_MODE_RANGE_MIN, CONSOLE_MODE_RANGE_MAX);
|
||||
old_mode = MAX(CONSOLE_MODE_RANGE_MIN, ST->ConOut->Mode->Mode);
|
||||
|
||||
err = uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, mode);
|
||||
if (!EFI_ERROR(err))
|
||||
return EFI_SUCCESS;
|
||||
|
||||
/* Special case mode 1: when using OVMF and qemu, setting it returns error
|
||||
* and breaks console output. */
|
||||
if (EFI_ERROR(err) && mode == 1)
|
||||
uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, (UINTN)0);
|
||||
/* Something went wrong. Output is probably borked, so try to revert to previous mode. */
|
||||
if (!EFI_ERROR(uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, old_mode)))
|
||||
return err;
|
||||
|
||||
/* Maybe the device is on fire? */
|
||||
uefi_call_wrapper(ST->ConOut->Reset, 2, ST->ConOut, TRUE);
|
||||
uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, CONSOLE_MODE_RANGE_MIN);
|
||||
return err;
|
||||
}
|
||||
|
||||
static UINT64 text_area_from_font_size(void) {
|
||||
EFI_STATUS err;
|
||||
UINT64 text_area;
|
||||
UINTN rows, columns;
|
||||
|
||||
err = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &columns, &rows);
|
||||
if (EFI_ERROR(err)) {
|
||||
columns = 80;
|
||||
rows = 25;
|
||||
}
|
||||
|
||||
text_area = SYSTEM_FONT_WIDTH * SYSTEM_FONT_HEIGHT * (UINT64)rows * (UINT64)columns;
|
||||
|
||||
return text_area;
|
||||
}
|
||||
|
||||
static EFI_STATUS mode_auto(UINTN *mode) {
|
||||
const UINT32 HORIZONTAL_MAX_OK = 1920;
|
||||
const UINT32 VERTICAL_MAX_OK = 1080;
|
||||
const UINT64 VIEWPORT_RATIO = 10;
|
||||
UINT64 screen_area, text_area;
|
||||
static const EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
static INT64 get_auto_mode(void) {
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
|
||||
EFI_STATUS err;
|
||||
BOOLEAN keep = FALSE;
|
||||
|
||||
assert(mode);
|
||||
|
||||
err = LibLocateProtocol((EFI_GUID*) &GraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
|
||||
err = LibLocateProtocol(&GraphicsOutputProtocol, (VOID **)&GraphicsOutput);
|
||||
if (!EFI_ERROR(err) && GraphicsOutput->Mode && GraphicsOutput->Mode->Info) {
|
||||
Info = GraphicsOutput->Mode->Info;
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info = GraphicsOutput->Mode->Info;
|
||||
BOOLEAN keep = FALSE;
|
||||
|
||||
/* Start verifying if we are in a resolution larger than Full HD
|
||||
* (1920x1080). If we're not, assume we're in a good mode and do not
|
||||
@ -170,19 +158,19 @@ static EFI_STATUS mode_auto(UINTN *mode) {
|
||||
* area to the text viewport area. If it's less than 10 times bigger,
|
||||
* then assume the text is readable and keep the text mode. */
|
||||
else {
|
||||
screen_area = (UINT64)Info->HorizontalResolution * (UINT64)Info->VerticalResolution;
|
||||
text_area = text_area_from_font_size();
|
||||
UINT64 text_area;
|
||||
UINTN x_max, y_max;
|
||||
UINT64 screen_area = (UINT64)Info->HorizontalResolution * (UINT64)Info->VerticalResolution;
|
||||
|
||||
console_query_mode(&x_max, &y_max);
|
||||
text_area = SYSTEM_FONT_WIDTH * SYSTEM_FONT_HEIGHT * (UINT64)x_max * (UINT64)y_max;
|
||||
|
||||
if (text_area != 0 && screen_area/text_area < VIEWPORT_RATIO)
|
||||
keep = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (keep) {
|
||||
/* Just clear the screen instead of changing the mode and return. */
|
||||
*mode = ST->ConOut->Mode->Mode;
|
||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||
return EFI_SUCCESS;
|
||||
if (keep)
|
||||
return ST->ConOut->Mode->Mode;
|
||||
}
|
||||
|
||||
/* If we reached here, then we have a high resolution screen and the text
|
||||
@ -191,32 +179,72 @@ static EFI_STATUS mode_auto(UINTN *mode) {
|
||||
* standard mode, which is provided by the device manufacturer, so it should
|
||||
* be a good mode.
|
||||
* Note: MaxMode is the number of modes, not the last mode. */
|
||||
if (ST->ConOut->Mode->MaxMode > 2)
|
||||
*mode = 2;
|
||||
if (ST->ConOut->Mode->MaxMode > CONSOLE_MODE_FIRMWARE_FIRST)
|
||||
return CONSOLE_MODE_FIRMWARE_FIRST;
|
||||
|
||||
/* Try again with mode different than zero (assume user requests
|
||||
* auto mode due to some problem with mode zero). */
|
||||
else if (ST->ConOut->Mode->MaxMode == 2)
|
||||
*mode = 1;
|
||||
/* Else force mode change to zero. */
|
||||
else
|
||||
*mode = 0;
|
||||
if (ST->ConOut->Mode->MaxMode > CONSOLE_MODE_80_50)
|
||||
return CONSOLE_MODE_80_50;
|
||||
|
||||
return change_mode(*mode);
|
||||
return CONSOLE_MODE_80_25;
|
||||
}
|
||||
|
||||
EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how) {
|
||||
assert(mode);
|
||||
EFI_STATUS console_set_mode(INT64 mode) {
|
||||
switch (mode) {
|
||||
case CONSOLE_MODE_KEEP:
|
||||
/* If the firmware indicates the current mode is invalid, change it anyway. */
|
||||
if (ST->ConOut->Mode->Mode < CONSOLE_MODE_RANGE_MIN)
|
||||
return change_mode(CONSOLE_MODE_RANGE_MIN);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
if (how == CONSOLE_MODE_AUTO)
|
||||
return mode_auto(mode);
|
||||
case CONSOLE_MODE_NEXT:
|
||||
if (ST->ConOut->Mode->MaxMode <= CONSOLE_MODE_RANGE_MIN)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
if (how == CONSOLE_MODE_MAX) {
|
||||
mode = MAX(CONSOLE_MODE_RANGE_MIN, ST->ConOut->Mode->Mode);
|
||||
do {
|
||||
mode = (mode + 1) % ST->ConOut->Mode->MaxMode;
|
||||
if (!EFI_ERROR(change_mode(mode)))
|
||||
break;
|
||||
/* If this mode is broken/unsupported, try the next.
|
||||
* If mode is 0, we wrapped around and should stop. */
|
||||
} while (mode > CONSOLE_MODE_RANGE_MIN);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
case CONSOLE_MODE_AUTO:
|
||||
return change_mode(get_auto_mode());
|
||||
|
||||
case CONSOLE_MODE_FIRMWARE_MAX:
|
||||
/* Note: MaxMode is the number of modes, not the last mode. */
|
||||
if (ST->ConOut->Mode->MaxMode > 0)
|
||||
*mode = ST->ConOut->Mode->MaxMode-1;
|
||||
else
|
||||
*mode = 0;
|
||||
return change_mode(ST->ConOut->Mode->MaxMode - 1LL);
|
||||
|
||||
default:
|
||||
return change_mode(mode);
|
||||
}
|
||||
}
|
||||
|
||||
EFI_STATUS console_query_mode(UINTN *x_max, UINTN *y_max) {
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(x_max);
|
||||
assert(y_max);
|
||||
|
||||
err = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, x_max, y_max);
|
||||
if (EFI_ERROR(err)) {
|
||||
/* Fallback values mandated by UEFI spec. */
|
||||
switch (ST->ConOut->Mode->Mode) {
|
||||
case CONSOLE_MODE_80_50:
|
||||
*x_max = 80;
|
||||
*y_max = 50;
|
||||
break;
|
||||
case CONSOLE_MODE_80_25:
|
||||
default:
|
||||
*x_max = 80;
|
||||
*y_max = 25;
|
||||
}
|
||||
}
|
||||
|
||||
return change_mode(*mode);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -9,12 +9,23 @@
|
||||
#define KEYCHAR(k) ((k) & 0xffff)
|
||||
#define CHAR_CTRL(c) ((c) - 'a' + 1)
|
||||
|
||||
enum console_mode_change_type {
|
||||
CONSOLE_MODE_KEEP = 0,
|
||||
CONSOLE_MODE_SET,
|
||||
enum {
|
||||
/* Console mode is a INT32 in EFI. We use INT64 to make room for our special values. */
|
||||
CONSOLE_MODE_RANGE_MIN = 0,
|
||||
CONSOLE_MODE_RANGE_MAX = INT32_MAX, /* This is just the theoretical limit. */
|
||||
CONSOLE_MODE_INVALID = -1, /* UEFI uses -1 if the device is not in a valid text mode. */
|
||||
|
||||
CONSOLE_MODE_80_25 = 0, /* 80x25 is required by UEFI spec. */
|
||||
CONSOLE_MODE_80_50 = 1, /* 80x50 may be supported. */
|
||||
CONSOLE_MODE_FIRMWARE_FIRST = 2, /* First custom mode, if supported. */
|
||||
|
||||
/* These are our own mode values that map to concrete values at runtime. */
|
||||
CONSOLE_MODE_KEEP = CONSOLE_MODE_RANGE_MAX + 1LL,
|
||||
CONSOLE_MODE_NEXT,
|
||||
CONSOLE_MODE_AUTO,
|
||||
CONSOLE_MODE_MAX,
|
||||
CONSOLE_MODE_FIRMWARE_MAX, /* 'max' in config. */
|
||||
};
|
||||
|
||||
EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec);
|
||||
EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how);
|
||||
EFI_STATUS console_set_mode(INT64 mode);
|
||||
EFI_STATUS console_query_mode(UINTN *x_max, UINTN *y_max);
|
||||
|
||||
@ -522,3 +522,8 @@ VOID print_at(UINTN x, UINTN y, UINTN attr, const CHAR16 *str) {
|
||||
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, attr);
|
||||
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, (CHAR16*)str);
|
||||
}
|
||||
|
||||
VOID clear_screen(UINTN attr) {
|
||||
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, attr);
|
||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||
}
|
||||
|
||||
@ -93,3 +93,4 @@ static inline VOID *mempmem_safe(const VOID *haystack, UINTN haystack_len, const
|
||||
}
|
||||
|
||||
VOID print_at(UINTN x, UINTN y, UINTN attr, const CHAR16 *str);
|
||||
VOID clear_screen(UINTN attr);
|
||||
|
||||
@ -1758,7 +1758,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *roo
|
||||
|
||||
{
|
||||
/* This block is (optionally) done with the reloading counter bumped */
|
||||
_cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
|
||||
_unused_ _cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
|
||||
|
||||
/* If we will deserialize make sure that during enumeration this is already known, so we increase the
|
||||
* counter here already */
|
||||
@ -3237,7 +3237,7 @@ int manager_override_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
|
||||
}
|
||||
|
||||
int manager_reload(Manager *m) {
|
||||
_cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
|
||||
_unused_ _cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
|
||||
_cleanup_fdset_free_ FDSet *fds = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int r;
|
||||
|
||||
@ -853,7 +853,7 @@ static int mount_private_dev(MountEntry *m) {
|
||||
char temporary_mount[] = "/tmp/namespace-dev-XXXXXX";
|
||||
const char *d, *dev = NULL, *devpts = NULL, *devshm = NULL, *devhugepages = NULL, *devmqueue = NULL, *devlog = NULL, *devptmx = NULL;
|
||||
bool can_mknod = true;
|
||||
_cleanup_umask_ mode_t u;
|
||||
_unused_ _cleanup_umask_ mode_t u;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
@ -1674,7 +1674,7 @@ static int run(int argc, char *argv[]) {
|
||||
verb = argv[1];
|
||||
|
||||
if (streq(verb, "attach")) {
|
||||
_cleanup_(remove_and_erasep) const char *destroy_key_file = NULL;
|
||||
_unused_ _cleanup_(remove_and_erasep) const char *destroy_key_file = NULL;
|
||||
_cleanup_(erase_and_freep) void *key_data = NULL;
|
||||
const char *volume, *source, *key_file, *options;
|
||||
crypt_status_info status;
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
int r;
|
||||
|
||||
log_setup();
|
||||
|
||||
@ -166,10 +166,10 @@ static void context_read_os_release(Context *c) {
|
||||
c->etc_os_release_stat = current_stat;
|
||||
}
|
||||
|
||||
static bool valid_chassis(const char *chassis) {
|
||||
static const char* valid_chassis(const char *chassis) {
|
||||
assert(chassis);
|
||||
|
||||
return nulstr_contains(
|
||||
return nulstr_get(
|
||||
"vm\0"
|
||||
"container\0"
|
||||
"desktop\0"
|
||||
@ -190,6 +190,7 @@ static bool valid_deployment(const char *deployment) {
|
||||
}
|
||||
|
||||
static const char* fallback_chassis(void) {
|
||||
const char *chassis;
|
||||
char *type;
|
||||
unsigned t;
|
||||
int v, r;
|
||||
@ -261,14 +262,14 @@ try_acpi:
|
||||
r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed read ACPI PM profile, ignoring: %m");
|
||||
return NULL;
|
||||
goto try_devicetree;
|
||||
}
|
||||
|
||||
r = safe_atou(type, &t);
|
||||
free(type);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed parse ACPI PM profile, ignoring: %m");
|
||||
return NULL;
|
||||
goto try_devicetree;
|
||||
}
|
||||
|
||||
/* We only list the really obvious cases here as the ACPI data is not really super reliable.
|
||||
@ -300,7 +301,24 @@ try_acpi:
|
||||
log_debug("Unhandled ACPI PM profile 0x%02x, ignoring.", t);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
try_devicetree:
|
||||
r = read_one_line_file("/sys/firmware/devicetree/base/chassis-type", &type);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read device-tree chassis type, ignoring: %m");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Note that the Devicetree specification uses the very same vocabulary
|
||||
* of chassis types as we do, hence we do not need to translate these types:
|
||||
*
|
||||
* https://github.com/devicetree-org/devicetree-specification/blob/master/source/chapter3-devicenodes.rst */
|
||||
chassis = valid_chassis(type);
|
||||
if (!chassis)
|
||||
log_debug("Invalid device-tree chassis type '%s', ignoring.", type);
|
||||
|
||||
free(type);
|
||||
|
||||
return chassis;
|
||||
}
|
||||
|
||||
static char* context_fallback_icon_name(Context *c) {
|
||||
|
||||
@ -311,7 +311,7 @@ static int process_event(Server *s, struct epoll_event *ev) {
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(server_done) Server server = { .epoll_fd = -1 };
|
||||
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
int r, n;
|
||||
|
||||
if (argc > 1)
|
||||
|
||||
@ -1099,7 +1099,7 @@ static int load_certificates(char **key, char **cert, char **trust) {
|
||||
|
||||
static int run(int argc, char **argv) {
|
||||
_cleanup_(journal_remote_server_destroy) RemoteServer s = {};
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_cleanup_(erase_and_freep) char *key = NULL;
|
||||
_cleanup_free_ char *cert = NULL, *trust = NULL;
|
||||
int r;
|
||||
|
||||
@ -272,7 +272,7 @@ int journal_remote_add_source(RemoteServer *s, int fd, char* name, bool own_name
|
||||
|
||||
int journal_remote_add_raw_socket(RemoteServer *s, int fd) {
|
||||
int r;
|
||||
_cleanup_close_ int fd_ = fd;
|
||||
_unused_ _cleanup_close_ int fd_ = fd;
|
||||
char name[STRLEN("raw-socket-") + DECIMAL_STR_MAX(int) + 1];
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
@ -820,7 +820,7 @@ static int open_journal(sd_journal **j) {
|
||||
|
||||
static int run(int argc, char **argv) {
|
||||
_cleanup_(destroy_uploader) Uploader u = {};
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
bool use_journal;
|
||||
int r;
|
||||
|
||||
|
||||
@ -903,7 +903,7 @@ static void dispatch_message_real(
|
||||
pid_t object_pid) {
|
||||
|
||||
char source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)];
|
||||
_cleanup_free_ char *cmdline1 = NULL, *cmdline2 = NULL;
|
||||
_unused_ _cleanup_free_ char *cmdline1 = NULL, *cmdline2 = NULL;
|
||||
uid_t journal_uid;
|
||||
ClientContext *o;
|
||||
|
||||
|
||||
@ -94,7 +94,8 @@ int device_add_property_aux(sd_device *device, const char *key, const char *valu
|
||||
properties = &device->properties;
|
||||
|
||||
if (value) {
|
||||
_cleanup_free_ char *new_key = NULL, *new_value = NULL, *old_key = NULL, *old_value = NULL;
|
||||
_unused_ _cleanup_free_ char *old_value = NULL;
|
||||
_cleanup_free_ char *new_key = NULL, *new_value = NULL, *old_key = NULL;
|
||||
int r;
|
||||
|
||||
r = ordered_hashmap_ensure_allocated(properties, &string_hash_ops_free_free);
|
||||
@ -119,7 +120,8 @@ int device_add_property_aux(sd_device *device, const char *key, const char *valu
|
||||
TAKE_PTR(new_key);
|
||||
TAKE_PTR(new_value);
|
||||
} else {
|
||||
_cleanup_free_ char *old_key = NULL, *old_value = NULL;
|
||||
_unused_ _cleanup_free_ char *old_value = NULL;
|
||||
_cleanup_free_ char *old_key = NULL;
|
||||
|
||||
old_value = ordered_hashmap_remove2(*properties, key, (void**) &old_key);
|
||||
}
|
||||
@ -1939,7 +1941,8 @@ _public_ int sd_device_get_trigger_uuid(sd_device *device, sd_id128_t *ret) {
|
||||
}
|
||||
|
||||
static int device_cache_sysattr_value(sd_device *device, const char *key, char *value) {
|
||||
_cleanup_free_ char *new_key = NULL, *old_value = NULL;
|
||||
_unused_ _cleanup_free_ char *old_value = NULL;
|
||||
_cleanup_free_ char *new_key = NULL;
|
||||
int r;
|
||||
|
||||
assert(device);
|
||||
|
||||
@ -53,7 +53,7 @@ static void test_catalog_import_invalid(void) {
|
||||
}
|
||||
|
||||
static void test_catalog_import_badid(void) {
|
||||
_cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL;
|
||||
_unused_ _cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL;
|
||||
const char *input =
|
||||
"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededede\n" \
|
||||
"Subject: message\n" \
|
||||
|
||||
@ -703,7 +703,7 @@ bool manager_all_buttons_ignored(Manager *m) {
|
||||
int manager_read_utmp(Manager *m) {
|
||||
#if ENABLE_UTMP
|
||||
int r;
|
||||
_cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
_unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
|
||||
assert(m);
|
||||
|
||||
|
||||
@ -1323,7 +1323,7 @@ bool session_is_controller(Session *s, const char *sender) {
|
||||
}
|
||||
|
||||
static void session_release_controller(Session *s, bool notify) {
|
||||
_cleanup_free_ char *name = NULL;
|
||||
_unused_ _cleanup_free_ char *name = NULL;
|
||||
SessionDevice *sd;
|
||||
|
||||
if (!s->controller)
|
||||
|
||||
@ -1157,7 +1157,7 @@ static int manager_run(Manager *m) {
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(manager_unrefp) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
int r;
|
||||
|
||||
log_set_facility(LOG_AUTH);
|
||||
|
||||
@ -702,8 +702,10 @@ int config_parse_dhcp_send_option(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *opt4 = NULL, *old4 = NULL;
|
||||
_cleanup_(sd_dhcp6_option_unrefp) sd_dhcp6_option *opt6 = NULL, *old6 = NULL;
|
||||
_cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *opt4 = NULL;
|
||||
_cleanup_(sd_dhcp6_option_unrefp) sd_dhcp6_option *opt6 = NULL;
|
||||
_unused_ _cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *old4 = NULL;
|
||||
_unused_ _cleanup_(sd_dhcp6_option_unrefp) sd_dhcp6_option *old6 = NULL;
|
||||
uint32_t uint32_data, enterprise_identifier = 0;
|
||||
_cleanup_free_ char *word = NULL, *q = NULL;
|
||||
OrderedHashmap **options = data;
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
int r;
|
||||
|
||||
log_setup();
|
||||
|
||||
@ -195,7 +195,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
int r;
|
||||
|
||||
log_setup();
|
||||
|
||||
@ -2196,7 +2196,7 @@ static int copy_devnodes(const char *dest) {
|
||||
"tty\0"
|
||||
"net/tun\0";
|
||||
|
||||
_cleanup_umask_ mode_t u;
|
||||
_unused_ _cleanup_umask_ mode_t u;
|
||||
const char *d;
|
||||
int r = 0;
|
||||
|
||||
@ -2279,7 +2279,7 @@ static int copy_devnodes(const char *dest) {
|
||||
}
|
||||
|
||||
static int make_extra_nodes(const char *dest) {
|
||||
_cleanup_umask_ mode_t u;
|
||||
_unused_ _cleanup_umask_ mode_t u;
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
@ -2480,7 +2480,7 @@ static int setup_kmsg(int kmsg_socket) {
|
||||
_cleanup_(unlink_and_freep) char *from = NULL;
|
||||
_cleanup_free_ char *fifo = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
_cleanup_umask_ mode_t u;
|
||||
_unused_ _cleanup_umask_ mode_t u;
|
||||
int r;
|
||||
|
||||
assert(kmsg_socket >= 0);
|
||||
|
||||
@ -303,7 +303,7 @@ enum nss_status userdb_getgrnam(
|
||||
}
|
||||
|
||||
if (!g) {
|
||||
_cleanup_(_nss_systemd_unblockp) bool blocked = false;
|
||||
_unused_ _cleanup_(_nss_systemd_unblockp) bool blocked = false;
|
||||
|
||||
if (strv_isempty(members))
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
@ -365,7 +365,7 @@ enum nss_status userdb_getgrgid(
|
||||
}
|
||||
|
||||
if (!g) {
|
||||
_cleanup_(_nss_systemd_unblockp) bool blocked = false;
|
||||
_unused_ _cleanup_(_nss_systemd_unblockp) bool blocked = false;
|
||||
|
||||
/* So, quite possibly we have to extend an existing group record with additional members. But
|
||||
* to do this we need to know the group name first. The group didn't exist via non-NSS
|
||||
|
||||
@ -387,7 +387,7 @@ static void clear_candidate_hashmapp(Manager **m) {
|
||||
static int monitor_memory_pressure_contexts_handler(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
/* Don't want to use stale candidate data. Setting this will clear the candidate hashmap on return unless we
|
||||
* update the candidate data (in which case clear_candidates will be NULL). */
|
||||
_cleanup_(clear_candidate_hashmapp) Manager *clear_candidates = userdata;
|
||||
_unused_ _cleanup_(clear_candidate_hashmapp) Manager *clear_candidates = userdata;
|
||||
_cleanup_set_free_ Set *targets = NULL;
|
||||
bool in_post_action_delay = false;
|
||||
Manager *m = userdata;
|
||||
|
||||
@ -116,7 +116,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(notify_on_cleanup) const char *notify_msg = NULL;
|
||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_msg = NULL;
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_free_ char *swap = NULL;
|
||||
unsigned long long s = 0;
|
||||
|
||||
@ -904,7 +904,8 @@ static void context_place_partitions(Context *context) {
|
||||
|
||||
for (size_t i = 0; i < context->n_free_areas; i++) {
|
||||
FreeArea *a = context->free_areas[i];
|
||||
uint64_t start, left;
|
||||
_unused_ uint64_t left;
|
||||
uint64_t start;
|
||||
|
||||
if (a->after) {
|
||||
assert(a->after->offset != UINT64_MAX);
|
||||
|
||||
@ -274,7 +274,7 @@ static int dns_cache_link_item(DnsCache *c, DnsCacheItem *i) {
|
||||
|
||||
first = hashmap_get(c->by_key, i->key);
|
||||
if (first) {
|
||||
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL;
|
||||
_unused_ _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL;
|
||||
|
||||
/* Keep a reference to the original key, while we manipulate the list. */
|
||||
k = dns_resource_key_ref(first->key);
|
||||
|
||||
@ -165,7 +165,7 @@ static int dns_query_candidate_add_transaction(
|
||||
}
|
||||
|
||||
static int dns_query_candidate_go(DnsQueryCandidate *c) {
|
||||
_cleanup_(dns_query_candidate_unrefp) DnsQueryCandidate *keep_c = NULL;
|
||||
_unused_ _cleanup_(dns_query_candidate_unrefp) DnsQueryCandidate *keep_c = NULL;
|
||||
DnsTransaction *t;
|
||||
int r;
|
||||
unsigned n = 0;
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
int r;
|
||||
|
||||
log_setup();
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
* Returns: 0 on success, negative error code on failure.
|
||||
*/
|
||||
int barrier_create(Barrier *b) {
|
||||
_cleanup_(barrier_destroyp) Barrier *staging = b;
|
||||
_unused_ _cleanup_(barrier_destroyp) Barrier *staging = b;
|
||||
int r;
|
||||
|
||||
assert(b);
|
||||
|
||||
@ -81,7 +81,7 @@ int make_inaccessible_nodes(
|
||||
{ "inaccessible/blk", S_IFBLK | 0000 },
|
||||
};
|
||||
|
||||
_cleanup_umask_ mode_t u;
|
||||
_unused_ _cleanup_umask_ mode_t u;
|
||||
int r;
|
||||
|
||||
if (!parent_dir)
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
#include "utmp-wtmp.h"
|
||||
|
||||
int utmp_get_runlevel(int *runlevel, int *previous) {
|
||||
_cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
_unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
struct utmpx *found, lookup = { .ut_type = RUN_LVL };
|
||||
const char *e;
|
||||
|
||||
@ -87,7 +87,7 @@ static void init_entry(struct utmpx *store, usec_t t) {
|
||||
}
|
||||
|
||||
static int write_entry_utmp(const struct utmpx *store) {
|
||||
_cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
_unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
|
||||
assert(store);
|
||||
|
||||
@ -215,7 +215,7 @@ int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line
|
||||
}
|
||||
|
||||
int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
|
||||
_cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
_unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
struct utmpx lookup = {
|
||||
.ut_type = INIT_PROCESS /* looks for DEAD_PROCESS, LOGIN_PROCESS, USER_PROCESS, too */
|
||||
}, store, store_wtmp, *found;
|
||||
@ -340,7 +340,7 @@ int utmp_wall(
|
||||
bool (*match_tty)(const char *tty, void *userdata),
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
_unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
_cleanup_free_ char *text = NULL, *hn = NULL, *un = NULL, *stdin_tty = NULL;
|
||||
struct utmpx *u;
|
||||
int r;
|
||||
|
||||
@ -30,7 +30,7 @@ static int update_timeout(void) {
|
||||
|
||||
flags = WDIOS_DISABLECARD;
|
||||
if (ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags) < 0)
|
||||
return log_warning_errno(errno, "Failed to disable hardware watchdog: %m");
|
||||
return log_warning_errno(errno, "Failed to disable hardware watchdog, ignoring: %m");
|
||||
} else {
|
||||
int sec, flags;
|
||||
usec_t t;
|
||||
@ -38,7 +38,7 @@ static int update_timeout(void) {
|
||||
t = DIV_ROUND_UP(watchdog_timeout, USEC_PER_SEC);
|
||||
sec = MIN(t, (usec_t) INT_MAX); /* Saturate */
|
||||
if (ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &sec) < 0)
|
||||
return log_warning_errno(errno, "Failed to set timeout to %is: %m", sec);
|
||||
return log_warning_errno(errno, "Failed to set timeout to %is, ignoring: %m", sec);
|
||||
|
||||
/* Just in case the driver is buggy */
|
||||
assert(sec > 0);
|
||||
@ -50,14 +50,14 @@ static int update_timeout(void) {
|
||||
flags = WDIOS_ENABLECARD;
|
||||
if (ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags) < 0) {
|
||||
/* ENOTTY means the watchdog is always enabled so we're fine */
|
||||
log_full(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING,
|
||||
"Failed to enable hardware watchdog: %m");
|
||||
log_full_errno(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING, errno,
|
||||
"Failed to enable hardware watchdog, ignoring: %m");
|
||||
if (!ERRNO_IS_NOT_SUPPORTED(errno))
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0) < 0)
|
||||
return log_warning_errno(errno, "Failed to ping hardware watchdog: %m");
|
||||
return log_warning_errno(errno, "Failed to ping hardware watchdog, ignoring: %m");
|
||||
|
||||
watchdog_last_ping = now(clock_boottime_or_monotonic());
|
||||
}
|
||||
@ -75,10 +75,10 @@ static int open_watchdog(void) {
|
||||
fn = watchdog_device ?: "/dev/watchdog";
|
||||
watchdog_fd = open(fn, O_WRONLY|O_CLOEXEC);
|
||||
if (watchdog_fd < 0)
|
||||
return log_debug_errno(errno, "Failed to open watchdog device %s: %m", fn);
|
||||
return log_debug_errno(errno, "Failed to open watchdog device %s, ignoring: %m", fn);
|
||||
|
||||
if (ioctl(watchdog_fd, WDIOC_GETSUPPORT, &ident) < 0)
|
||||
log_debug_errno(errno, "Hardware watchdog %s does not support WDIOC_GETSUPPORT ioctl: %m", fn);
|
||||
log_debug_errno(errno, "Hardware watchdog %s does not support WDIOC_GETSUPPORT ioctl, ignoring: %m", fn);
|
||||
else
|
||||
log_info("Using hardware watchdog '%s', version %x, device %s",
|
||||
ident.identity,
|
||||
@ -156,7 +156,7 @@ int watchdog_ping(void) {
|
||||
}
|
||||
|
||||
if (ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0) < 0)
|
||||
return log_warning_errno(errno, "Failed to ping hardware watchdog: %m");
|
||||
return log_warning_errno(errno, "Failed to ping hardware watchdog, ignoring: %m");
|
||||
|
||||
watchdog_last_ping = ntime;
|
||||
return 0;
|
||||
@ -172,7 +172,7 @@ void watchdog_close(bool disarm) {
|
||||
/* Explicitly disarm it */
|
||||
flags = WDIOS_DISABLECARD;
|
||||
if (ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags) < 0)
|
||||
log_warning_errno(errno, "Failed to disable hardware watchdog: %m");
|
||||
log_warning_errno(errno, "Failed to disable hardware watchdog, ignoring: %m");
|
||||
|
||||
/* To be sure, use magic close logic, too */
|
||||
for (;;) {
|
||||
@ -182,7 +182,7 @@ void watchdog_close(bool disarm) {
|
||||
break;
|
||||
|
||||
if (errno != EINTR) {
|
||||
log_error_errno(errno, "Failed to disarm watchdog timer: %m");
|
||||
log_warning_errno(errno, "Failed to disarm watchdog timer, ignoring: %m");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "errno-util.h"
|
||||
#include "hostname-util.h"
|
||||
#include "strv.h"
|
||||
#include "sysctl-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
static const char* cases[] = {
|
||||
static const char* const cases[] = {
|
||||
"a.b.c", "a/b/c",
|
||||
"a/b/c", "a/b/c",
|
||||
"a/b.c/d", "a/b.c/d",
|
||||
@ -24,7 +28,7 @@ static void test_sysctl_normalize(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
const char **s, **expected;
|
||||
STRV_FOREACH_PAIR(s, expected, cases) {
|
||||
STRV_FOREACH_PAIR(s, expected, (const char**) cases) {
|
||||
_cleanup_free_ char *t;
|
||||
|
||||
assert_se(t = strdup(*s));
|
||||
@ -35,10 +39,44 @@ static void test_sysctl_normalize(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void test_sysctl_read(void) {
|
||||
_cleanup_free_ char *s = NULL, *h = NULL;
|
||||
sd_id128_t a, b;
|
||||
int r;
|
||||
|
||||
assert_se(sysctl_read("kernel/random/boot_id", &s) >= 0);
|
||||
assert_se(sd_id128_from_string(s, &a) >= 0);
|
||||
assert_se(sd_id128_get_boot(&b) >= 0);
|
||||
assert_se(sd_id128_equal(a, b));
|
||||
s = mfree(s);
|
||||
|
||||
assert_se(sysctl_read_ip_property(AF_INET, "lo", "forwarding", &s));
|
||||
assert_se(STR_IN_SET(s, "0", "1"));
|
||||
|
||||
r = sysctl_write_ip_property(AF_INET, "lo", "forwarding", s);
|
||||
assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r) || r == -EROFS);
|
||||
s = mfree(s);
|
||||
|
||||
assert_se(sysctl_read_ip_property(AF_INET, NULL, "ip_forward", &s));
|
||||
assert_se(STR_IN_SET(s, "0", "1"));
|
||||
|
||||
r = sysctl_write_ip_property(AF_INET, NULL, "ip_forward", s);
|
||||
assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r) || r == -EROFS);
|
||||
s = mfree(s);
|
||||
|
||||
assert_se(sysctl_read("kernel/hostname", &s) >= 0);
|
||||
assert_se(gethostname_full(GET_HOSTNAME_ALLOW_NONE|GET_HOSTNAME_ALLOW_LOCALHOST, &h) >= 0);
|
||||
assert_se(streq(s, h));
|
||||
|
||||
r = sysctl_write("kernel/hostname", s);
|
||||
assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r) || r == -EROFS);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
test_setup_logging(LOG_INFO);
|
||||
|
||||
test_sysctl_normalize();
|
||||
test_sysctl_read();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -87,7 +87,7 @@ settime:
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
const char *user = "systemd-timesync";
|
||||
uid_t uid, uid_current;
|
||||
gid_t gid;
|
||||
|
||||
@ -338,7 +338,8 @@ static int process_and_watch_password_files(bool watch) {
|
||||
_FD_MAX
|
||||
};
|
||||
|
||||
_cleanup_close_ int notify = -1, signal_fd = -1, tty_block_fd = -1;
|
||||
_unused_ _cleanup_close_ int tty_block_fd = -1;
|
||||
_cleanup_close_ int notify = -1, signal_fd = -1;
|
||||
struct pollfd pollfd[_FD_MAX];
|
||||
sigset_t mask;
|
||||
int r;
|
||||
|
||||
@ -1136,7 +1136,8 @@ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrl
|
||||
manager_reload(manager);
|
||||
break;
|
||||
case UDEV_CTRL_SET_ENV: {
|
||||
_cleanup_free_ char *key = NULL, *val = NULL, *old_key = NULL, *old_val = NULL;
|
||||
_unused_ _cleanup_free_ char *old_val = NULL;
|
||||
_cleanup_free_ char *key = NULL, *val = NULL, *old_key = NULL;
|
||||
const char *eq;
|
||||
|
||||
eq = strchr(value->buf, '=');
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
int r;
|
||||
|
||||
log_setup();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user