mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 08:56:15 +09:00
sd-boot: terminal handling tweaks (#39026)
Let's make sd-boot's terminal handling a bit cleaner, to the point that uefi's weird handling allows this.
This commit is contained in:
@@ -495,8 +495,9 @@ static bool menu_run(
|
||||
ST->ConIn->Reset(ST->ConIn, false);
|
||||
ST->ConOut->EnableCursor(ST->ConOut, false);
|
||||
|
||||
/* draw a single character to make ClearScreen work on some firmware */
|
||||
ST->ConOut->OutputString(ST->ConOut, (char16_t *) u" ");
|
||||
/* Draw a single character to the beginning of a line, in order to make ClearScreen() work on certain
|
||||
* broken firmware. And let's immediately move back to the beginning of the line. */
|
||||
printf("\r \r");
|
||||
|
||||
err = console_set_mode(config->console_mode_efivar != CONSOLE_MODE_KEEP ?
|
||||
config->console_mode_efivar : config->console_mode);
|
||||
|
||||
@@ -917,6 +917,37 @@ static bool handle_format_specifier(FormatContext *ctx, SpecifierContext *sp) {
|
||||
}
|
||||
}
|
||||
|
||||
#if SD_BOOT
|
||||
static void output_string_safe(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *this, const char16_t *s) {
|
||||
assert(this);
|
||||
assert(s);
|
||||
|
||||
/* This is a color-conscious version of ST->ConOut->OutputString(). Whenever it encounters a newline
|
||||
* character, it will reset the color to our default, because some UEFI implementations/terminals
|
||||
* reset the color in that case, and we want our default color to remain in effect */
|
||||
|
||||
int32_t saved_attribute = ST->ConOut->Mode->Attribute;
|
||||
for (;;) {
|
||||
const char16_t *nl = strchr16(s, '\n');
|
||||
if (!nl) /* No further newline */
|
||||
return (void) ST->ConOut->OutputString(ST->ConOut, (char16_t*) s);
|
||||
|
||||
if (nl[1] == 0) { /* Newline is at the end of the string */
|
||||
(void) ST->ConOut->OutputString(ST->ConOut, (char16_t*) s);
|
||||
set_attribute_safe(saved_attribute);
|
||||
return;
|
||||
}
|
||||
|
||||
/* newline is in the middle of the string */
|
||||
_cleanup_free_ char16_t *x = xstrndup16(s, nl - s + 1);
|
||||
(void) ST->ConOut->OutputString(ST->ConOut, x);
|
||||
set_attribute_safe(saved_attribute);
|
||||
|
||||
s = nl + 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* printf_internal is largely compatible to userspace vasprintf. Any features omitted should trigger asserts.
|
||||
*
|
||||
* Supported:
|
||||
@@ -983,7 +1014,7 @@ _printf_(2, 0) static char16_t *printf_internal(EFI_STATUS status, const char *f
|
||||
}
|
||||
|
||||
#if SD_BOOT
|
||||
ST->ConOut->OutputString(ST->ConOut, ctx.buf);
|
||||
output_string_safe(ST->ConOut, ctx.buf);
|
||||
#endif
|
||||
|
||||
return mfree(ctx.dyn_buf);
|
||||
|
||||
@@ -105,6 +105,9 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool
|
||||
timeout_sec--;
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(
|
||||
err,
|
||||
|
||||
@@ -195,16 +195,27 @@ EFI_STATUS file_read(
|
||||
return file_handle_read(handle, offset, size, ret, ret_size);
|
||||
}
|
||||
|
||||
void set_attribute_safe(size_t attr) {
|
||||
/* Various UEFI implementations suppress color changes from a color to the same color. Often, we want
|
||||
* to force out the color change though, hence change the color here once, and then back. We simply
|
||||
* mark the color as bright for a moment, and then revert that. */
|
||||
|
||||
attr ^= 0x08;
|
||||
ST->ConOut->SetAttribute(ST->ConOut, attr);
|
||||
attr ^= 0x08;
|
||||
ST->ConOut->SetAttribute(ST->ConOut, attr);
|
||||
}
|
||||
|
||||
void print_at(size_t x, size_t y, size_t attr, const char16_t *str) {
|
||||
assert(str);
|
||||
ST->ConOut->SetCursorPosition(ST->ConOut, x, y);
|
||||
ST->ConOut->SetAttribute(ST->ConOut, attr);
|
||||
set_attribute_safe(attr);
|
||||
ST->ConOut->OutputString(ST->ConOut, (char16_t *) str);
|
||||
}
|
||||
|
||||
void clear_screen(size_t attr) {
|
||||
log_wait();
|
||||
ST->ConOut->SetAttribute(ST->ConOut, attr);
|
||||
set_attribute_safe(attr);
|
||||
ST->ConOut->ClearScreen(ST->ConOut);
|
||||
}
|
||||
|
||||
|
||||
@@ -152,6 +152,7 @@ static inline void unload_imagep(EFI_HANDLE *image) {
|
||||
#define GUID_FORMAT_VAL(g) (g).Data1, (g).Data2, (g).Data3, (g).Data4[0], (g).Data4[1], \
|
||||
(g).Data4[2], (g).Data4[3], (g).Data4[4], (g).Data4[5], (g).Data4[6], (g).Data4[7]
|
||||
|
||||
void set_attribute_safe(size_t attr);
|
||||
void print_at(size_t x, size_t y, size_t attr, const char16_t *str);
|
||||
void clear_screen(size_t attr);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user