}
}
+#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:
}
#if SD_BOOT
- ST->ConOut->OutputString(ST->ConOut, ctx.buf);
+ output_string_safe(ST->ConOut, ctx.buf);
#endif
return mfree(ctx.dyn_buf);
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);
}
#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);