-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
efi: libstub: Enable efi_printk() in zboot decompressor
Split the efi_printk() routine into its own source file, and provide local implementations of strlen() and strnlen() so that the standalone zboot app can efi_err and efi_info etc. Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
- Loading branch information
Ard Biesheuvel
committed
Nov 9, 2022
1 parent
52dce39
commit 2e6fa86
Showing
8 changed files
with
198 additions
and
173 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
#include <linux/stdarg.h> | ||
|
||
#include <linux/ctype.h> | ||
#include <linux/efi.h> | ||
#include <linux/kernel.h> | ||
#include <linux/printk.h> /* For CONSOLE_LOGLEVEL_* */ | ||
#include <asm/efi.h> | ||
#include <asm/setup.h> | ||
|
||
#include "efistub.h" | ||
|
||
int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT; | ||
|
||
/** | ||
* efi_char16_puts() - Write a UCS-2 encoded string to the console | ||
* @str: UCS-2 encoded string | ||
*/ | ||
void efi_char16_puts(efi_char16_t *str) | ||
{ | ||
efi_call_proto(efi_table_attr(efi_system_table, con_out), | ||
output_string, str); | ||
} | ||
|
||
static | ||
u32 utf8_to_utf32(const u8 **s8) | ||
{ | ||
u32 c32; | ||
u8 c0, cx; | ||
size_t clen, i; | ||
|
||
c0 = cx = *(*s8)++; | ||
/* | ||
* The position of the most-significant 0 bit gives us the length of | ||
* a multi-octet encoding. | ||
*/ | ||
for (clen = 0; cx & 0x80; ++clen) | ||
cx <<= 1; | ||
/* | ||
* If the 0 bit is in position 8, this is a valid single-octet | ||
* encoding. If the 0 bit is in position 7 or positions 1-3, the | ||
* encoding is invalid. | ||
* In either case, we just return the first octet. | ||
*/ | ||
if (clen < 2 || clen > 4) | ||
return c0; | ||
/* Get the bits from the first octet. */ | ||
c32 = cx >> clen--; | ||
for (i = 0; i < clen; ++i) { | ||
/* Trailing octets must have 10 in most significant bits. */ | ||
cx = (*s8)[i] ^ 0x80; | ||
if (cx & 0xc0) | ||
return c0; | ||
c32 = (c32 << 6) | cx; | ||
} | ||
/* | ||
* Check for validity: | ||
* - The character must be in the Unicode range. | ||
* - It must not be a surrogate. | ||
* - It must be encoded using the correct number of octets. | ||
*/ | ||
if (c32 > 0x10ffff || | ||
(c32 & 0xf800) == 0xd800 || | ||
clen != (c32 >= 0x80) + (c32 >= 0x800) + (c32 >= 0x10000)) | ||
return c0; | ||
*s8 += clen; | ||
return c32; | ||
} | ||
|
||
/** | ||
* efi_puts() - Write a UTF-8 encoded string to the console | ||
* @str: UTF-8 encoded string | ||
*/ | ||
void efi_puts(const char *str) | ||
{ | ||
efi_char16_t buf[128]; | ||
size_t pos = 0, lim = ARRAY_SIZE(buf); | ||
const u8 *s8 = (const u8 *)str; | ||
u32 c32; | ||
|
||
while (*s8) { | ||
if (*s8 == '\n') | ||
buf[pos++] = L'\r'; | ||
c32 = utf8_to_utf32(&s8); | ||
if (c32 < 0x10000) { | ||
/* Characters in plane 0 use a single word. */ | ||
buf[pos++] = c32; | ||
} else { | ||
/* | ||
* Characters in other planes encode into a surrogate | ||
* pair. | ||
*/ | ||
buf[pos++] = (0xd800 - (0x10000 >> 10)) + (c32 >> 10); | ||
buf[pos++] = 0xdc00 + (c32 & 0x3ff); | ||
} | ||
if (*s8 == '\0' || pos >= lim - 2) { | ||
buf[pos] = L'\0'; | ||
efi_char16_puts(buf); | ||
pos = 0; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* efi_printk() - Print a kernel message | ||
* @fmt: format string | ||
* | ||
* The first letter of the format string is used to determine the logging level | ||
* of the message. If the level is less then the current EFI logging level, the | ||
* message is suppressed. The message will be truncated to 255 bytes. | ||
* | ||
* Return: number of printed characters | ||
*/ | ||
int efi_printk(const char *fmt, ...) | ||
{ | ||
char printf_buf[256]; | ||
va_list args; | ||
int printed; | ||
int loglevel = printk_get_level(fmt); | ||
|
||
switch (loglevel) { | ||
case '0' ... '9': | ||
loglevel -= '0'; | ||
break; | ||
default: | ||
/* | ||
* Use loglevel -1 for cases where we just want to print to | ||
* the screen. | ||
*/ | ||
loglevel = -1; | ||
break; | ||
} | ||
|
||
if (loglevel >= efi_loglevel) | ||
return 0; | ||
|
||
if (loglevel >= 0) | ||
efi_puts("EFI stub: "); | ||
|
||
fmt = printk_skip_level(fmt); | ||
|
||
va_start(args, fmt); | ||
printed = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args); | ||
va_end(args); | ||
|
||
efi_puts(printf_buf); | ||
if (printed >= sizeof(printf_buf)) { | ||
efi_puts("[Message truncated]\n"); | ||
return -1; | ||
} | ||
|
||
return printed; | ||
} |
Oops, something went wrong.