Commit 2e6fa86f authored by Ard Biesheuvel's avatar Ard Biesheuvel
Browse files

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: default avatarArd Biesheuvel <ardb@kernel.org>
parent 52dce39c
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -22,8 +22,6 @@ PROVIDE(__efistub_primary_entry_offset = primary_entry - _text);
 * position independent manner
 */
PROVIDE(__efistub_memchr		= __pi_memchr);
PROVIDE(__efistub_strlen		= __pi_strlen);
PROVIDE(__efistub_strnlen		= __pi_strnlen);
PROVIDE(__efistub_strcmp		= __pi_strcmp);
PROVIDE(__efistub_strrchr		= __pi_strrchr);
PROVIDE(__efistub_dcache_clean_poc	= __pi_dcache_clean_poc);
+0 −2
Original line number Diff line number Diff line
@@ -10,10 +10,8 @@
__efistub_memchr		= memchr;
__efistub_strcat		= strcat;
__efistub_strcmp		= strcmp;
__efistub_strlen		= strlen;
__efistub_strncat		= strncat;
__efistub_strnstr		= strnstr;
__efistub_strnlen		= strnlen;
__efistub_strrchr		= strrchr;
__efistub_kernel_entry		= kernel_entry;
__efistub_kernel_asize		= kernel_asize;
+0 −2
Original line number Diff line number Diff line
@@ -24,8 +24,6 @@
 * position independent manner
 */
__efistub_memchr		= memchr;
__efistub_strlen		= strlen;
__efistub_strnlen		= strnlen;
__efistub_strcmp		= strcmp;
__efistub_strrchr		= strrchr;

+3 −2
Original line number Diff line number Diff line
@@ -24,7 +24,8 @@ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \
# disable the stackleak plugin
cflags-$(CONFIG_ARM64)		+= -fpie $(DISABLE_STACKLEAK_PLUGIN) \
				   $(call cc-option,-mbranch-protection=none)
cflags-$(CONFIG_ARM)		+= -fno-builtin -fpic \
cflags-$(CONFIG_ARM)		+= -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \
				   -fno-builtin -fpic \
				   $(call cc-option,-mno-single-pic-base)
cflags-$(CONFIG_RISCV)		+= -fpic
cflags-$(CONFIG_LOONGARCH)	+= -fpie
@@ -68,7 +69,7 @@ KCOV_INSTRUMENT := n
lib-y				:= efi-stub-helper.o gop.o secureboot.o tpm.o \
				   file.o mem.o random.o randomalloc.o pci.o \
				   skip_spaces.o lib-cmdline.o lib-ctype.o \
				   alignedmem.o relocate.o vsprintf.o
				   alignedmem.o relocate.o printk.o vsprintf.o

# include the stub's libfdt dependencies from lib/ when needed
libfdt-deps			:= fdt_rw.c fdt_ro.c fdt_wip.c fdt.c \
+0 −143
Original line number Diff line number Diff line
@@ -9,10 +9,8 @@

#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>

@@ -20,7 +18,6 @@

bool efi_nochunk;
bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE);
int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
bool efi_novamap;

static bool efi_noinitrd;
@@ -32,146 +29,6 @@ bool __pure __efi_soft_reserve_enabled(void)
	return !efi_nosoftreserve;
}

/**
 * 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;
}

/**
 * efi_parse_options() - Parse EFI command line options
 * @cmdline:	kernel command line
Loading