diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml index 0ef80f9a56..3d83cbba83 100644 --- a/man/kernel-command-line.xml +++ b/man/kernel-command-line.xml @@ -315,11 +315,13 @@ vconsole.font= vconsole.font_map= vconsole.font_unimap= + vconsole.font_scale= Parameters understood by the virtual console setup logic. For details, see vconsole.conf5. + vconsole.font_scale= was added in version 262. diff --git a/man/systemd-vconsole-setup.service.xml b/man/systemd-vconsole-setup.service.xml index 4f018424fb..3ccd82efe6 100644 --- a/man/systemd-vconsole-setup.service.xml +++ b/man/systemd-vconsole-setup.service.xml @@ -85,11 +85,13 @@ vconsole.font vconsole.font_map vconsole.font_unimap + vconsole.font_scale The console font settings to apply. The matching options in vconsole.conf and on the kernel command line take precedence over these credentials. + vconsole.font_scale was added in version 262. diff --git a/man/systemd.system-credentials.xml b/man/systemd.system-credentials.xml index 6541baaf5f..076db27362 100644 --- a/man/systemd.system-credentials.xml +++ b/man/systemd.system-credentials.xml @@ -340,10 +340,12 @@ vconsole.font vconsole.font_map vconsole.font_unimap + vconsole.font_scale Console settings to apply, see systemd-vconsole-setup.service8 for details. + vconsole.font_scale was added in version 262. diff --git a/man/vconsole.conf.xml b/man/vconsole.conf.xml index 20b30d3994..bd1db8590b 100644 --- a/man/vconsole.conf.xml +++ b/man/vconsole.conf.xml @@ -49,7 +49,8 @@ vconsole.keymap_toggle=, vconsole.font=, vconsole.font_map=, - vconsole.font_unimap= may be used + vconsole.font_unimap=, and + vconsole.font_scale= may be used to override the console settings at boot. Depending on the operating system other configuration files @@ -98,6 +99,18 @@ and the unicode font map. + + FONT_SCALE= + + + Specifies a font scaling factor. Takes an unsigned value, optionally suffixed with + %. Specifying 2 or 200% doubles the font + size. Currently, only the scaling factors 100% and 200% are + supported; other values are clamped to the nearest supported value. + + + + @@ -118,15 +131,18 @@ - vconsole.font= vconsole.font_map= vconsole.font_unimap= + vconsole.font_scale= - Overrides FONT=, FONT_MAP=, and - FONT_UNIMAP=. + + Overrides FONT=, FONT_MAP=, + FONT_UNIMAP=, and FONT_SCALE=. - + vconsole.font_scale= was added in version 262. + + diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index f8c5dffd1e..5e0b86df50 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -23,6 +23,8 @@ #include "locale-util.h" #include "log.h" #include "main-func.h" +#include "parse-util.h" +#include "percent-util.h" #include "pidref.h" #include "proc-cmdline.h" #include "process-util.h" @@ -38,8 +40,14 @@ typedef struct Context { char *font; char *font_map; char *font_unimap; + int font_scale; /* in percent, negative values mean unset. */ } Context; +#define CONTEXT_NULL \ + (Context) { \ + .font_scale = -1, \ + } + static void context_done(Context *c) { assert(c); @@ -71,10 +79,30 @@ static void context_merge_config( context_merge(dst, src, src_compat, font); context_merge(dst, src, src_compat, font_map); context_merge(dst, src, src_compat, font_unimap); + + if (src->font_scale >= 0) + dst->font_scale = src->font_scale; +} + +static int parse_font_scale(const char *s) { + assert(s); + + /* This returns the font scaling in percent. */ + + unsigned u; + if (safe_atou(s, &u) >= 0) { + /* Here, we use INT_MAX, as parse_percent_unbounded() is bounded by INT_MAX. */ + if (u > INT_MAX / 100) + return -ERANGE; + + return u * 100; + } + + return parse_percent_unbounded(s); } static int context_read_efi(Context *c) { - _cleanup_(context_done) Context v = {}; + _cleanup_(context_done) Context v = CONTEXT_NULL; int r; assert(c); @@ -92,7 +120,8 @@ static int context_read_efi(Context *c) { } static int context_read_creds(Context *c) { - _cleanup_(context_done) Context v = {}; + _cleanup_(context_done) Context v = CONTEXT_NULL; + _cleanup_free_ char *font_scale = NULL; int r; assert(c); @@ -102,16 +131,26 @@ static int context_read_creds(Context *c) { "vconsole.keymap_toggle", &v.keymap_toggle, "vconsole.font", &v.font, "vconsole.font_map", &v.font_map, - "vconsole.font_unimap", &v.font_unimap); + "vconsole.font_unimap", &v.font_unimap, + "vconsole.font_scale", &font_scale); if (r < 0) log_warning_errno(r, "Failed to import credentials, ignoring: %m"); + if (font_scale) { + r = parse_font_scale(font_scale); + if (r < 0) + log_warning_errno(r, "Failed to parse vconsole.font_scale credential, ignoring: %m"); + else + v.font_scale = r; + } + context_merge_config(c, &v, NULL); return 0; } static int context_read_env(Context *c) { - _cleanup_(context_done) Context v = {}; + _cleanup_(context_done) Context v = CONTEXT_NULL; + _cleanup_free_ char *font_scale = NULL; int r; assert(c); @@ -122,19 +161,29 @@ static int context_read_env(Context *c) { "KEYMAP_TOGGLE", &v.keymap_toggle, "FONT", &v.font, "FONT_MAP", &v.font_map, - "FONT_UNIMAP", &v.font_unimap); + "FONT_UNIMAP", &v.font_unimap, + "FONT_SCALE", &font_scale); if (r < 0) { if (r != -ENOENT) log_warning_errno(r, "Failed to read /etc/vconsole.conf, ignoring: %m"); return r; } + if (font_scale) { + r = parse_font_scale(font_scale); + if (r < 0) + log_warning_errno(r, "Failed to parse FONT_SCALE= in /etc/vconsole.conf, ignoring: %m"); + else + v.font_scale = r; + } + context_merge_config(c, &v, NULL); return 0; } static int context_read_proc_cmdline(Context *c) { - _cleanup_(context_done) Context v = {}, w = {}; + _cleanup_(context_done) Context v = CONTEXT_NULL, w = CONTEXT_NULL; + _cleanup_free_ char *font_scale = NULL; int r; assert(c); @@ -146,6 +195,7 @@ static int context_read_proc_cmdline(Context *c) { "vconsole.font", &v.font, "vconsole.font_map", &v.font_map, "vconsole.font_unimap", &v.font_unimap, + "vconsole.font_scale", &font_scale, /* compatibility with obsolete multiple-dot scheme */ "vconsole.keymap.toggle", &w.keymap_toggle, "vconsole.font.map", &w.font_map, @@ -156,6 +206,14 @@ static int context_read_proc_cmdline(Context *c) { return r; } + if (font_scale) { + r = parse_font_scale(font_scale); + if (r < 0) + log_warning_errno(r, "Failed to parse vconsole.font_scale from /proc/cmdline, ignoring: %m"); + else + v.font_scale = r; + } + context_merge_config(c, &v, &w); return 0; } @@ -354,7 +412,7 @@ static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) { } static int font_load_and_wait(int fd, const char *vc, Context *c) { - const char* args[9]; + const char* args[10]; unsigned i = 0; int r; @@ -366,8 +424,16 @@ static int font_load_and_wait(int fd, const char *vc, Context *c) { *font_map = empty_to_null(c->font_map), *font_unimap = empty_to_null(c->font_unimap); + int font_scale = 100; /* Defaults to 100%, no scaling. */ + if (c->font_scale >= 0) { + /* Clamp to the closest value that setfont supports, Currently, only 100% and 200% are supported. */ + font_scale = c->font_scale < 150 ? 100 : 200; + if (font_scale != c->font_scale) + log_debug("Font scale %i%% is requested, clamped to %i%%", c->font_scale, font_scale); + } + /* Any part can be set independently */ - if (!font && !font_map && !font_unimap) + if (!font && !font_map && !font_unimap && font_scale != 200) return 0; if (access(KBD_SETFONT, X_OK) < 0) { @@ -391,6 +457,8 @@ static int font_load_and_wait(int fd, const char *vc, Context *c) { args[i++] = KBD_SETFONT; args[i++] = "-C"; args[i++] = vc; + if (font_scale == 200) + args[i++] = "-d"; if (font_map) { args[i++] = "-m"; args[i++] = font_map; @@ -653,7 +721,7 @@ static int verify_source_vc(char **ret_path, const char *src_vc) { } static int run(int argc, char **argv) { - _cleanup_(context_done) Context c = {}; + _cleanup_(context_done) Context c = CONTEXT_NULL; _cleanup_free_ char *vc = NULL; _cleanup_close_ int fd = -EBADF, lock_fd = -EBADF; bool utf8;