1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/stdarg.h>
5 #include <linux/ctype.h>
7 #include <linux/kernel.h>
8 #include <linux/printk.h> /* For CONSOLE_LOGLEVEL_* */
10 #include <asm/setup.h>
14 int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
17 * efi_char16_puts() - Write a UCS-2 encoded string to the console
18 * @str: UCS-2 encoded string
20 void efi_char16_puts(efi_char16_t *str)
22 efi_call_proto(efi_table_attr(efi_system_table, con_out),
27 u32 utf8_to_utf32(const u8 **s8)
35 * The position of the most-significant 0 bit gives us the length of
36 * a multi-octet encoding.
38 for (clen = 0; cx & 0x80; ++clen)
41 * If the 0 bit is in position 8, this is a valid single-octet
42 * encoding. If the 0 bit is in position 7 or positions 1-3, the
43 * encoding is invalid.
44 * In either case, we just return the first octet.
46 if (clen < 2 || clen > 4)
48 /* Get the bits from the first octet. */
50 for (i = 0; i < clen; ++i) {
51 /* Trailing octets must have 10 in most significant bits. */
55 c32 = (c32 << 6) | cx;
59 * - The character must be in the Unicode range.
60 * - It must not be a surrogate.
61 * - It must be encoded using the correct number of octets.
64 (c32 & 0xf800) == 0xd800 ||
65 clen != (c32 >= 0x80) + (c32 >= 0x800) + (c32 >= 0x10000))
72 * efi_puts() - Write a UTF-8 encoded string to the console
73 * @str: UTF-8 encoded string
75 void efi_puts(const char *str)
77 efi_char16_t buf[128];
78 size_t pos = 0, lim = ARRAY_SIZE(buf);
79 const u8 *s8 = (const u8 *)str;
85 c32 = utf8_to_utf32(&s8);
87 /* Characters in plane 0 use a single word. */
91 * Characters in other planes encode into a surrogate
94 buf[pos++] = (0xd800 - (0x10000 >> 10)) + (c32 >> 10);
95 buf[pos++] = 0xdc00 + (c32 & 0x3ff);
97 if (*s8 == '\0' || pos >= lim - 2) {
106 * efi_printk() - Print a kernel message
107 * @fmt: format string
109 * The first letter of the format string is used to determine the logging level
110 * of the message. If the level is less then the current EFI logging level, the
111 * message is suppressed. The message will be truncated to 255 bytes.
113 * Return: number of printed characters
115 int efi_printk(const char *fmt, ...)
117 char printf_buf[256];
120 int loglevel = printk_get_level(fmt);
128 * Use loglevel -1 for cases where we just want to print to
135 if (loglevel >= efi_loglevel)
139 efi_puts("EFI stub: ");
141 fmt = printk_skip_level(fmt);
144 printed = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args);
147 efi_puts(printf_buf);
148 if (printed >= sizeof(printf_buf)) {
149 efi_puts("[Message truncated]\n");