Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Helper functions used by the EFI stub on multiple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * architectures. This should be #included by the EFI stub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * implementation files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Copyright 2011 Intel Corporation; author Matt Fleming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/printk.h> /* For CONSOLE_LOGLEVEL_* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <asm/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "efistub.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) bool efi_nochunk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) bool efi_noinitrd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) bool efi_novamap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static bool efi_nosoftreserve;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) bool __pure __efi_soft_reserve_enabled(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	return !efi_nosoftreserve;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  * efi_char16_puts() - Write a UCS-2 encoded string to the console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  * @str:	UCS-2 encoded string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) void efi_char16_puts(efi_char16_t *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	efi_call_proto(efi_table_attr(efi_system_table, con_out),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		       output_string, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) u32 utf8_to_utf32(const u8 **s8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	u32 c32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	u8 c0, cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	size_t clen, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	c0 = cx = *(*s8)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	 * The position of the most-significant 0 bit gives us the length of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	 * a multi-octet encoding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	for (clen = 0; cx & 0x80; ++clen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		cx <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	 * If the 0 bit is in position 8, this is a valid single-octet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	 * encoding. If the 0 bit is in position 7 or positions 1-3, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	 * encoding is invalid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	 * In either case, we just return the first octet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	if (clen < 2 || clen > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		return c0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	/* Get the bits from the first octet. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	c32 = cx >> clen--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	for (i = 0; i < clen; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		/* Trailing octets must have 10 in most significant bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		cx = (*s8)[i] ^ 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		if (cx & 0xc0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 			return c0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		c32 = (c32 << 6) | cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	 * Check for validity:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	 * - The character must be in the Unicode range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	 * - It must not be a surrogate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	 * - It must be encoded using the correct number of octets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	if (c32 > 0x10ffff ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	    (c32 & 0xf800) == 0xd800 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	    clen != (c32 >= 0x80) + (c32 >= 0x800) + (c32 >= 0x10000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		return c0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	*s8 += clen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	return c32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  * efi_puts() - Write a UTF-8 encoded string to the console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  * @str:	UTF-8 encoded string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) void efi_puts(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	efi_char16_t buf[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	size_t pos = 0, lim = ARRAY_SIZE(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	const u8 *s8 = (const u8 *)str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	u32 c32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	while (*s8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		if (*s8 == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 			buf[pos++] = L'\r';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		c32 = utf8_to_utf32(&s8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		if (c32 < 0x10000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 			/* Characters in plane 0 use a single word. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 			buf[pos++] = c32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			 * Characters in other planes encode into a surrogate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			 * pair.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			buf[pos++] = (0xd800 - (0x10000 >> 10)) + (c32 >> 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 			buf[pos++] = 0xdc00 + (c32 & 0x3ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		if (*s8 == '\0' || pos >= lim - 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			buf[pos] = L'\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 			efi_char16_puts(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  * efi_printk() - Print a kernel message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  * @fmt:	format string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)  * The first letter of the format string is used to determine the logging level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)  * of the message. If the level is less then the current EFI logging level, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)  * message is suppressed. The message will be truncated to 255 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)  * Return:	number of printed characters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int efi_printk(const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	char printf_buf[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	int printed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	int loglevel = printk_get_level(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	switch (loglevel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	case '0' ... '9':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		loglevel -= '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		 * Use loglevel -1 for cases where we just want to print to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		 * the screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		loglevel = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	if (loglevel >= efi_loglevel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	if (loglevel >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		efi_puts("EFI stub: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	fmt = printk_skip_level(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	printed = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	efi_puts(printf_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	if (printed >= sizeof(printf_buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		efi_puts("[Message truncated]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	return printed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)  * efi_parse_options() - Parse EFI command line options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)  * @cmdline:	kernel command line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  * Parse the ASCII string @cmdline for EFI options, denoted by the efi=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  * option, e.g. efi=nochunk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  * It should be noted that efi= is parsed in two very different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  * environments, first in the early boot environment of the EFI boot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * stub, and subsequently during the kernel boot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * Return:	status code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) efi_status_t efi_parse_options(char const *cmdline)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	efi_status_t status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	char *str, *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	if (!cmdline)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		return EFI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	len = strnlen(cmdline, COMMAND_LINE_SIZE - 1) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, len, (void **)&buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	memcpy(buf, cmdline, len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	buf[len - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	str = skip_spaces(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	while (*str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		char *param, *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		str = next_arg(str, &param, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		if (!val && !strcmp(param, "--"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		if (!strcmp(param, "nokaslr")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 			efi_nokaslr = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		} else if (!strcmp(param, "quiet")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			efi_loglevel = CONSOLE_LOGLEVEL_QUIET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		} else if (!strcmp(param, "noinitrd")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 			efi_noinitrd = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		} else if (!strcmp(param, "efi") && val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 			efi_nochunk = parse_option_str(val, "nochunk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 			efi_novamap = parse_option_str(val, "novamap");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 			efi_nosoftreserve = IS_ENABLED(CONFIG_EFI_SOFT_RESERVE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 					    parse_option_str(val, "nosoftreserve");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			if (parse_option_str(val, "disable_early_pci_dma"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 				efi_disable_pci_dma = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 			if (parse_option_str(val, "no_disable_early_pci_dma"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 				efi_disable_pci_dma = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 			if (parse_option_str(val, "debug"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 				efi_loglevel = CONSOLE_LOGLEVEL_DEBUG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		} else if (!strcmp(param, "video") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 			   val && strstarts(val, "efifb:")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			efi_parse_option_graphics(val + strlen("efifb:"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	efi_bs_call(free_pool, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	return EFI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)  * The EFI_LOAD_OPTION descriptor has the following layout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)  *	u32 Attributes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)  *	u16 FilePathListLength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)  *	u16 Description[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)  *	efi_device_path_protocol_t FilePathList[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)  *	u8 OptionalData[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)  * This function validates and unpacks the variable-size data fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) bool efi_load_option_unpack(efi_load_option_unpacked_t *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 			    const efi_load_option_t *src, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	const void *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	u16 c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	efi_device_path_protocol_t header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	const efi_char16_t *description;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	const efi_device_path_protocol_t *file_path_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	if (size < offsetof(efi_load_option_t, variable_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	pos = src->variable_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	size -= offsetof(efi_load_option_t, variable_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	if ((src->attributes & ~EFI_LOAD_OPTION_MASK) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	/* Scan description. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	description = pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		if (size < sizeof(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		c = *(const u16 *)pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		pos += sizeof(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		size -= sizeof(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	} while (c != L'\0');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	/* Scan file_path_list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	file_path_list = pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		if (size < sizeof(header))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		header = *(const efi_device_path_protocol_t *)pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		if (header.length < sizeof(header))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		if (size < header.length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		pos += header.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		size -= header.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	} while ((header.type != EFI_DEV_END_PATH && header.type != EFI_DEV_END_PATH2) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		 (header.sub_type != EFI_DEV_END_ENTIRE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	if (pos != (const void *)file_path_list + src->file_path_list_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	dest->attributes = src->attributes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	dest->file_path_list_length = src->file_path_list_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	dest->description = description;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	dest->file_path_list = file_path_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	dest->optional_data_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	dest->optional_data = size ? pos : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)  * At least some versions of Dell firmware pass the entire contents of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)  * Boot#### variable, i.e. the EFI_LOAD_OPTION descriptor, rather than just the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)  * OptionalData field.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)  * Detect this case and extract OptionalData.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) void efi_apply_loadoptions_quirk(const void **load_options, int *load_options_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	const efi_load_option_t *load_option = *load_options;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	efi_load_option_unpacked_t load_option_unpacked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	if (!IS_ENABLED(CONFIG_X86))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	if (!load_option)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	if (*load_options_size < sizeof(*load_option))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	if ((load_option->attributes & ~EFI_LOAD_OPTION_BOOT_MASK) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	if (!efi_load_option_unpack(&load_option_unpacked, load_option, *load_options_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	efi_warn_once(FW_BUG "LoadOptions is an EFI_LOAD_OPTION descriptor\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	efi_warn_once(FW_BUG "Using OptionalData as a workaround\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	*load_options = load_option_unpacked.optional_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	*load_options_size = load_option_unpacked.optional_data_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)  * Convert the unicode UEFI command line to ASCII to pass to kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)  * Size of memory allocated return in *cmd_line_len.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)  * Returns NULL on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	const u16 *s2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	unsigned long cmdline_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	int options_chars = efi_table_attr(image, load_options_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	const u16 *options = efi_table_attr(image, load_options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	int options_bytes = 0, safe_options_bytes = 0;  /* UTF-8 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	bool in_quote = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	efi_status_t status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	efi_apply_loadoptions_quirk((const void **)&options, &options_chars);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	options_chars /= sizeof(*options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	if (options) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		s2 = options;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		while (options_bytes < COMMAND_LINE_SIZE && options_chars--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 			u16 c = *s2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 			if (c < 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 				if (c == L'\0' || c == L'\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 				if (c == L'"')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 					in_quote = !in_quote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 				else if (!in_quote && isspace((char)c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 					safe_options_bytes = options_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 				options_bytes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 			 * Get the number of UTF-8 bytes corresponding to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 			 * UTF-16 character.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 			 * The first part handles everything in the BMP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 			options_bytes += 2 + (c >= 0x800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 			 * Add one more byte for valid surrogate pairs. Invalid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 			 * surrogates will be replaced with 0xfffd and take up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 			 * only 3 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 			if ((c & 0xfc00) == 0xd800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 				 * If the very last word is a high surrogate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 				 * we must ignore it since we can't access the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 				 * low surrogate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 				if (!options_chars) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 					options_bytes -= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 				} else if ((*s2 & 0xfc00) == 0xdc00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 					options_bytes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 					options_chars--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 					s2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 		if (options_bytes >= COMMAND_LINE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 			options_bytes = safe_options_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 			efi_err("Command line is too long: truncated to %d bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 				options_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	options_bytes++;	/* NUL termination */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, options_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 			     (void **)&cmdline_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	snprintf((char *)cmdline_addr, options_bytes, "%.*ls",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		 options_bytes - 1, options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	*cmd_line_len = options_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	return (char *)cmdline_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)  * efi_exit_boot_services() - Exit boot services
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)  * @handle:	handle of the exiting image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)  * @map:	pointer to receive the memory map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)  * @priv:	argument to be passed to @priv_func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)  * @priv_func:	function to process the memory map before exiting boot services
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)  * Handle calling ExitBootServices according to the requirements set out by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)  * spec.  Obtains the current memory map, and returns that info after calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)  * ExitBootServices.  The client must specify a function to perform any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)  * processing of the memory map data prior to ExitBootServices.  A client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)  * specific structure may be passed to the function via priv.  The client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)  * function may be called multiple times.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)  * Return:	status code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) efi_status_t efi_exit_boot_services(void *handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 				    struct efi_boot_memmap *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 				    void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 				    efi_exit_boot_map_processing priv_func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	efi_status_t status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	status = efi_get_memory_map(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	status = priv_func(map, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		goto free_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	if (efi_disable_pci_dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		efi_pci_disable_bridge_busmaster();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	status = efi_bs_call(exit_boot_services, handle, *map->key_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	if (status == EFI_INVALID_PARAMETER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		 * The memory map changed between efi_get_memory_map() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		 * exit_boot_services().  Per the UEFI Spec v2.6, Section 6.4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		 * EFI_BOOT_SERVICES.ExitBootServices we need to get the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		 * updated map, and try again.  The spec implies one retry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		 * should be sufficent, which is confirmed against the EDK2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		 * implementation.  Per the spec, we can only invoke
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		 * get_memory_map() and exit_boot_services() - we cannot alloc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		 * so efi_get_memory_map() cannot be used, and we must reuse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		 * the buffer.  For all practical purposes, the headroom in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		 * buffer should account for any changes in the map so the call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		 * to get_memory_map() is expected to succeed here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		*map->map_size = *map->buff_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		status = efi_bs_call(get_memory_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 				     map->map_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 				     *map->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 				     map->key_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 				     map->desc_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 				     map->desc_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		/* exit_boot_services() was called, thus cannot free */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		status = priv_func(map, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		/* exit_boot_services() was called, thus cannot free */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		status = efi_bs_call(exit_boot_services, handle, *map->key_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	/* exit_boot_services() was called, thus cannot free */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	return EFI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) free_map:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	efi_bs_call(free_pool, *map->map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)  * get_efi_config_table() - retrieve UEFI configuration table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)  * @guid:	GUID of the configuration table to be retrieved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)  * Return:	pointer to the configuration table or NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) void *get_efi_config_table(efi_guid_t guid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	unsigned long tables = efi_table_attr(efi_system_table, tables);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	int nr_tables = efi_table_attr(efi_system_table, nr_tables);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	for (i = 0; i < nr_tables; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		efi_config_table_t *t = (void *)tables;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		if (efi_guidcmp(t->guid, guid) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 			return efi_table_attr(t, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 		tables += efi_is_native() ? sizeof(efi_config_table_t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 					  : sizeof(efi_config_table_32_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)  * The LINUX_EFI_INITRD_MEDIA_GUID vendor media device path below provides a way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)  * for the firmware or bootloader to expose the initrd data directly to the stub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)  * via the trivial LoadFile2 protocol, which is defined in the UEFI spec, and is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)  * very easy to implement. It is a simple Linux initrd specific conduit between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)  * kernel and firmware, allowing us to put the EFI stub (being part of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)  * kernel) in charge of where and when to load the initrd, while leaving it up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)  * to the firmware to decide whether it needs to expose its filesystem hierarchy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)  * via EFI protocols.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	struct efi_vendor_dev_path	vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	struct efi_generic_dev_path	end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) } __packed initrd_dev_path = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 			EFI_DEV_MEDIA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 			EFI_DEV_MEDIA_VENDOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 			sizeof(struct efi_vendor_dev_path),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		LINUX_EFI_INITRD_MEDIA_GUID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		EFI_DEV_END_PATH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		EFI_DEV_END_ENTIRE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		sizeof(struct efi_generic_dev_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)  * efi_load_initrd_dev_path() - load the initrd from the Linux initrd device path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)  * @load_addr:	pointer to store the address where the initrd was loaded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)  * @load_size:	pointer to store the size of the loaded initrd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)  * @max:	upper limit for the initrd memory allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)  * * %EFI_SUCCESS if the initrd was loaded successfully, in which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)  *   case @load_addr and @load_size are assigned accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)  * * %EFI_NOT_FOUND if no LoadFile2 protocol exists on the initrd device path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)  * * %EFI_INVALID_PARAMETER if load_addr == NULL or load_size == NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)  * * %EFI_OUT_OF_RESOURCES if memory allocation failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)  * * %EFI_LOAD_ERROR in all other cases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 				      unsigned long *load_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 				      unsigned long max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	efi_guid_t lf2_proto_guid = EFI_LOAD_FILE2_PROTOCOL_GUID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	efi_device_path_protocol_t *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	efi_load_file2_protocol_t *lf2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	unsigned long initrd_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	unsigned long initrd_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	efi_handle_t handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	efi_status_t status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	dp = (efi_device_path_protocol_t *)&initrd_dev_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	status = efi_bs_call(locate_device_path, &lf2_proto_guid, &dp, &handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	status = efi_bs_call(handle_protocol, handle, &lf2_proto_guid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 			     (void **)&lf2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	status = efi_call_proto(lf2, load_file, dp, false, &initrd_size, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	if (status != EFI_BUFFER_TOO_SMALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		return EFI_LOAD_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	status = efi_allocate_pages(initrd_size, &initrd_addr, max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	status = efi_call_proto(lf2, load_file, dp, false, &initrd_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 				(void *)initrd_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	if (status != EFI_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 		efi_free(initrd_size, initrd_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 		return EFI_LOAD_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	*load_addr = initrd_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	*load_size = initrd_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	return EFI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 				     unsigned long *load_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 				     unsigned long *load_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 				     unsigned long soft_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 				     unsigned long hard_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	if (!IS_ENABLED(CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	    (IS_ENABLED(CONFIG_X86) && (!efi_is_native() || image == NULL))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 		*load_addr = *load_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 		return EFI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 				    soft_limit, hard_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 				    load_addr, load_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)  * efi_load_initrd() - Load initial RAM disk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)  * @image:	EFI loaded image protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)  * @load_addr:	pointer to loaded initrd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)  * @load_size:	size of loaded initrd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)  * @soft_limit:	preferred size of allocated memory for loading the initrd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)  * @hard_limit:	minimum size of allocated memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)  * Return:	status code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) efi_status_t efi_load_initrd(efi_loaded_image_t *image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 			     unsigned long *load_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 			     unsigned long *load_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 			     unsigned long soft_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 			     unsigned long hard_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	efi_status_t status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	if (!load_addr || !load_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 		return EFI_INVALID_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	status = efi_load_initrd_dev_path(load_addr, load_size, hard_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	if (status == EFI_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 		efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	} else if (status == EFI_NOT_FOUND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 		status = efi_load_initrd_cmdline(image, load_addr, load_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 						 soft_limit, hard_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 		if (status == EFI_SUCCESS && *load_size > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 			efi_info("Loaded initrd from command line option\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)  * efi_wait_for_key() - Wait for key stroke
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)  * @usec:	number of microseconds to wait for key stroke
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)  * @key:	key entered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)  * Wait for up to @usec microseconds for a key stroke.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)  * Return:	status code, EFI_SUCCESS if key received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	efi_event_t events[2], timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	unsigned long index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	efi_simple_text_input_protocol_t *con_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	efi_status_t status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 	con_in = efi_table_attr(efi_system_table, con_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	if (!con_in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 		return EFI_UNSUPPORTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	efi_set_event_at(events, 0, efi_table_attr(con_in, wait_for_key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 	status = efi_bs_call(create_event, EFI_EVT_TIMER, 0, NULL, NULL, &timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	status = efi_bs_call(set_timer, timer, EfiTimerRelative,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 			     EFI_100NSEC_PER_USEC * usec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	efi_set_event_at(events, 1, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	status = efi_bs_call(wait_for_event, 2, events, &index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	if (status == EFI_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 		if (index == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 			status = efi_call_proto(con_in, read_keystroke, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 			status = EFI_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	efi_bs_call(close_event, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }