mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 02:05:33 +00:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git
This commit is contained in:
commit
ec454ce37f
@ -250,6 +250,9 @@ static inline u32 efi64_convert_status(efi_status_t status)
|
||||
#define __efi64_argmap_allocate_pool(type, size, buffer) \
|
||||
((type), (size), efi64_zero_upper(buffer))
|
||||
|
||||
#define __efi64_argmap_locate_handle_buffer(type, proto, key, num, buf) \
|
||||
((type), (proto), (key), efi64_zero_upper(num), efi64_zero_upper(buf))
|
||||
|
||||
#define __efi64_argmap_create_event(type, tpl, f, c, event) \
|
||||
((type), (tpl), (f), (c), efi64_zero_upper(event))
|
||||
|
||||
|
@ -54,13 +54,11 @@
|
||||
#include <asm/uv/uv.h>
|
||||
|
||||
static unsigned long efi_systab_phys __initdata;
|
||||
static unsigned long uga_phys = EFI_INVALID_TABLE_ADDR;
|
||||
static unsigned long efi_runtime, efi_nr_tables;
|
||||
|
||||
unsigned long efi_fw_vendor, efi_config_table;
|
||||
|
||||
static const efi_config_table_type_t arch_tables[] __initconst = {
|
||||
{UGA_IO_PROTOCOL_GUID, &uga_phys, "UGA" },
|
||||
#ifdef CONFIG_X86_UV
|
||||
{UV_SYSTEM_TABLE_GUID, &uv_systab_phys, "UVsystab" },
|
||||
#endif
|
||||
@ -72,7 +70,6 @@ static const unsigned long * const efi_tables[] = {
|
||||
&efi.acpi20,
|
||||
&efi.smbios,
|
||||
&efi.smbios3,
|
||||
&uga_phys,
|
||||
#ifdef CONFIG_X86_UV
|
||||
&uv_systab_phys,
|
||||
#endif
|
||||
@ -891,13 +888,6 @@ bool efi_is_table_address(unsigned long phys_addr)
|
||||
return false;
|
||||
}
|
||||
|
||||
char *efi_systab_show_arch(char *str)
|
||||
{
|
||||
if (uga_phys != EFI_INVALID_TABLE_ADDR)
|
||||
str += sprintf(str, "UGA=0x%lx\n", uga_phys);
|
||||
return str;
|
||||
}
|
||||
|
||||
#define EFI_FIELD(var) efi_ ## var
|
||||
|
||||
#define EFI_ATTR_SHOW(name) \
|
||||
|
@ -148,9 +148,6 @@ static ssize_t systab_show(struct kobject *kobj,
|
||||
if (efi.smbios != EFI_INVALID_TABLE_ADDR)
|
||||
str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86))
|
||||
str = efi_systab_show_arch(str);
|
||||
|
||||
return str - buf;
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,12 @@ lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o
|
||||
|
||||
CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
|
||||
|
||||
zboot-obj-$(CONFIG_RISCV) := lib-clz_ctz.o lib-ashldi3.o
|
||||
zboot-obj-y := zboot-decompress-gzip.o
|
||||
CFLAGS_zboot-decompress-gzip.o += -I$(srctree)/lib/zlib_inflate
|
||||
zboot-obj-$(CONFIG_KERNEL_ZSTD) := zboot-decompress-zstd.o lib-xxhash.o
|
||||
CFLAGS_zboot-decompress-zstd.o += -I$(srctree)/lib/zstd
|
||||
|
||||
zboot-obj-$(CONFIG_RISCV) += lib-clz_ctz.o lib-ashldi3.o
|
||||
lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y)
|
||||
|
||||
lib-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o bitmap.o find.o
|
||||
|
@ -47,9 +47,10 @@ bool __pure __efi_soft_reserve_enabled(void)
|
||||
*/
|
||||
efi_status_t efi_parse_options(char const *cmdline)
|
||||
{
|
||||
size_t len;
|
||||
char *buf __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
char *str, *buf;
|
||||
size_t len;
|
||||
char *str;
|
||||
|
||||
if (!cmdline)
|
||||
return EFI_SUCCESS;
|
||||
@ -102,7 +103,6 @@ efi_status_t efi_parse_options(char const *cmdline)
|
||||
efi_parse_option_graphics(val + strlen("efifb:"));
|
||||
}
|
||||
}
|
||||
efi_bs_call(free_pool, buf);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ static efi_status_t efi_measure_tagged_event(unsigned long load_addr,
|
||||
u64, const union efistub_event *);
|
||||
struct { u32 hash_log_extend_event; } mixed_mode;
|
||||
} method;
|
||||
struct efistub_measured_event *evt;
|
||||
struct efistub_measured_event *evt __free(efi_pool) = NULL;
|
||||
int size = struct_size(evt, tagged_event.tagged_event_data,
|
||||
events[event].event_data_len);
|
||||
efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
|
||||
@ -312,7 +312,6 @@ static efi_status_t efi_measure_tagged_event(unsigned long load_addr,
|
||||
|
||||
status = efi_fn_call(&method, hash_log_extend_event, protocol, 0,
|
||||
load_addr, load_size, &evt->event_data);
|
||||
efi_bs_call(free_pool, evt);
|
||||
|
||||
if (status == EFI_SUCCESS)
|
||||
return EFI_SUCCESS;
|
||||
|
@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "efistub.h"
|
||||
@ -53,25 +54,16 @@ void __weak free_screen_info(struct screen_info *si)
|
||||
|
||||
static struct screen_info *setup_graphics(void)
|
||||
{
|
||||
efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
efi_status_t status;
|
||||
unsigned long size;
|
||||
void **gop_handle = NULL;
|
||||
struct screen_info *si = NULL;
|
||||
struct screen_info *si, tmp = {};
|
||||
|
||||
size = 0;
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
|
||||
&gop_proto, NULL, &size, gop_handle);
|
||||
if (status == EFI_BUFFER_TOO_SMALL) {
|
||||
si = alloc_screen_info();
|
||||
if (!si)
|
||||
return NULL;
|
||||
status = efi_setup_gop(si, &gop_proto, size);
|
||||
if (status != EFI_SUCCESS) {
|
||||
free_screen_info(si);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (efi_setup_gop(&tmp) != EFI_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
si = alloc_screen_info();
|
||||
if (!si)
|
||||
return NULL;
|
||||
|
||||
*si = tmp;
|
||||
return si;
|
||||
}
|
||||
|
||||
@ -112,8 +104,8 @@ static u32 get_supported_rt_services(void)
|
||||
|
||||
efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
|
||||
{
|
||||
char *cmdline __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
char *cmdline;
|
||||
|
||||
/*
|
||||
* Get the command line from EFI, using the LOADED_IMAGE
|
||||
@ -128,25 +120,24 @@ efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
|
||||
|
||||
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
|
||||
status = efi_parse_options(cmdline);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail_free_cmdline;
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to parse EFI load options\n");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
|
||||
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
|
||||
cmdline[0] == 0) {
|
||||
status = efi_parse_options(CONFIG_CMDLINE);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail_free_cmdline;
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to parse built-in command line\n");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
*cmdline_ptr = cmdline;
|
||||
*cmdline_ptr = no_free_ptr(cmdline);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
fail_free_cmdline:
|
||||
efi_err("Failed to parse options\n");
|
||||
efi_bs_call(free_pool, cmdline);
|
||||
return status;
|
||||
}
|
||||
|
||||
efi_status_t efi_stub_common(efi_handle_t handle,
|
||||
|
@ -4,6 +4,7 @@
|
||||
#define _DRIVERS_FIRMWARE_EFI_EFISTUB_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kern_levels.h>
|
||||
@ -122,11 +123,10 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
#define efi_get_handle_num(size) \
|
||||
((size) / (efi_is_native() ? sizeof(efi_handle_t) : sizeof(u32)))
|
||||
|
||||
#define for_each_efi_handle(handle, array, size, i) \
|
||||
for (i = 0; \
|
||||
i < efi_get_handle_num(size) && \
|
||||
((handle = efi_get_handle_at((array), i)) || true); \
|
||||
i++)
|
||||
#define for_each_efi_handle(handle, array, num) \
|
||||
for (int __i = 0; __i < (num) && \
|
||||
((handle = efi_get_handle_at((array), __i)) || true); \
|
||||
__i++)
|
||||
|
||||
static inline
|
||||
void efi_set_u64_split(u64 data, u32 *lo, u32 *hi)
|
||||
@ -171,7 +171,7 @@ void efi_set_u64_split(u64 data, u32 *lo, u32 *hi)
|
||||
* the EFI memory map. Other related structures, e.g. x86 e820ext, need
|
||||
* to factor in this headroom requirement as well.
|
||||
*/
|
||||
#define EFI_MMAP_NR_SLACK_SLOTS 8
|
||||
#define EFI_MMAP_NR_SLACK_SLOTS 32
|
||||
|
||||
typedef struct efi_generic_dev_path efi_device_path_protocol_t;
|
||||
|
||||
@ -314,7 +314,9 @@ union efi_boot_services {
|
||||
void *close_protocol;
|
||||
void *open_protocol_information;
|
||||
void *protocols_per_handle;
|
||||
void *locate_handle_buffer;
|
||||
efi_status_t (__efiapi *locate_handle_buffer)(int, efi_guid_t *,
|
||||
void *, unsigned long *,
|
||||
efi_handle_t **);
|
||||
efi_status_t (__efiapi *locate_protocol)(efi_guid_t *, void *,
|
||||
void **);
|
||||
efi_status_t (__efiapi *install_multiple_protocol_interfaces)(efi_handle_t *, ...);
|
||||
@ -1053,6 +1055,7 @@ void efi_puts(const char *str);
|
||||
__printf(1, 2) int efi_printk(char const *fmt, ...);
|
||||
|
||||
void efi_free(unsigned long size, unsigned long addr);
|
||||
DEFINE_FREE(efi_pool, void *, if (_T) efi_bs_call(free_pool, _T));
|
||||
|
||||
void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_size);
|
||||
|
||||
@ -1082,8 +1085,7 @@ efi_status_t efi_parse_options(char const *cmdline);
|
||||
|
||||
void efi_parse_option_graphics(char *option);
|
||||
|
||||
efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
|
||||
unsigned long size);
|
||||
efi_status_t efi_setup_gop(struct screen_info *si);
|
||||
|
||||
efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
|
||||
const efi_char16_t *optstr,
|
||||
@ -1232,4 +1234,7 @@ void process_unaccepted_memory(u64 start, u64 end);
|
||||
void accept_memory(phys_addr_t start, unsigned long size);
|
||||
void arch_accept_memory(phys_addr_t start, phys_addr_t end);
|
||||
|
||||
efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size);
|
||||
efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen);
|
||||
|
||||
#endif
|
||||
|
@ -133,13 +133,11 @@ void efi_parse_option_graphics(char *option)
|
||||
|
||||
static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
|
||||
{
|
||||
efi_status_t status;
|
||||
|
||||
efi_graphics_output_mode_info_t *info __free(efi_pool) = NULL;
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
unsigned long info_size;
|
||||
|
||||
u32 max_mode, cur_mode;
|
||||
efi_status_t status;
|
||||
int pf;
|
||||
|
||||
mode = efi_table_attr(gop, mode);
|
||||
@ -154,17 +152,13 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
|
||||
return cur_mode;
|
||||
}
|
||||
|
||||
status = efi_call_proto(gop, query_mode, cmdline.mode,
|
||||
&info_size, &info);
|
||||
status = efi_call_proto(gop, query_mode, cmdline.mode, &info_size, &info);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Couldn't get mode information\n");
|
||||
return cur_mode;
|
||||
}
|
||||
|
||||
pf = info->pixel_format;
|
||||
|
||||
efi_bs_call(free_pool, info);
|
||||
|
||||
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) {
|
||||
efi_err("Invalid PixelFormat\n");
|
||||
return cur_mode;
|
||||
@ -173,6 +167,28 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
|
||||
return cmdline.mode;
|
||||
}
|
||||
|
||||
static u32 choose_mode(efi_graphics_output_protocol_t *gop,
|
||||
bool (*match)(const efi_graphics_output_mode_info_t *, u32, void *),
|
||||
void *ctx)
|
||||
{
|
||||
efi_graphics_output_protocol_mode_t *mode = efi_table_attr(gop, mode);
|
||||
u32 max_mode = efi_table_attr(mode, max_mode);
|
||||
|
||||
for (u32 m = 0; m < max_mode; m++) {
|
||||
efi_graphics_output_mode_info_t *info __free(efi_pool) = NULL;
|
||||
unsigned long info_size;
|
||||
efi_status_t status;
|
||||
|
||||
status = efi_call_proto(gop, query_mode, m, &info_size, &info);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (match(info, m, ctx))
|
||||
return m;
|
||||
}
|
||||
return (unsigned long)ctx;
|
||||
}
|
||||
|
||||
static u8 pixel_bpp(int pixel_format, efi_pixel_bitmask_t pixel_info)
|
||||
{
|
||||
if (pixel_format == PIXEL_BIT_MASK) {
|
||||
@ -185,192 +201,117 @@ static u8 pixel_bpp(int pixel_format, efi_pixel_bitmask_t pixel_info)
|
||||
return 32;
|
||||
}
|
||||
|
||||
static bool match_res(const efi_graphics_output_mode_info_t *info, u32 mode, void *ctx)
|
||||
{
|
||||
efi_pixel_bitmask_t pi = info->pixel_information;
|
||||
int pf = info->pixel_format;
|
||||
|
||||
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
|
||||
return false;
|
||||
|
||||
return cmdline.res.width == info->horizontal_resolution &&
|
||||
cmdline.res.height == info->vertical_resolution &&
|
||||
(cmdline.res.format < 0 || cmdline.res.format == pf) &&
|
||||
(!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi));
|
||||
}
|
||||
|
||||
static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
|
||||
{
|
||||
efi_status_t status;
|
||||
efi_graphics_output_protocol_mode_t *mode = efi_table_attr(gop, mode);
|
||||
unsigned long cur_mode = efi_table_attr(mode, mode);
|
||||
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
unsigned long info_size;
|
||||
|
||||
u32 max_mode, cur_mode;
|
||||
int pf;
|
||||
efi_pixel_bitmask_t pi;
|
||||
u32 m, w, h;
|
||||
|
||||
mode = efi_table_attr(gop, mode);
|
||||
|
||||
cur_mode = efi_table_attr(mode, mode);
|
||||
info = efi_table_attr(mode, info);
|
||||
pf = info->pixel_format;
|
||||
pi = info->pixel_information;
|
||||
w = info->horizontal_resolution;
|
||||
h = info->vertical_resolution;
|
||||
|
||||
if (w == cmdline.res.width && h == cmdline.res.height &&
|
||||
(cmdline.res.format < 0 || cmdline.res.format == pf) &&
|
||||
(!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi)))
|
||||
if (match_res(efi_table_attr(mode, info), cur_mode, NULL))
|
||||
return cur_mode;
|
||||
|
||||
max_mode = efi_table_attr(mode, max_mode);
|
||||
return choose_mode(gop, match_res, (void *)cur_mode);
|
||||
}
|
||||
|
||||
for (m = 0; m < max_mode; m++) {
|
||||
if (m == cur_mode)
|
||||
continue;
|
||||
struct match {
|
||||
u32 mode;
|
||||
u32 area;
|
||||
u8 depth;
|
||||
};
|
||||
|
||||
status = efi_call_proto(gop, query_mode, m,
|
||||
&info_size, &info);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
static bool match_auto(const efi_graphics_output_mode_info_t *info, u32 mode, void *ctx)
|
||||
{
|
||||
u32 area = info->horizontal_resolution * info->vertical_resolution;
|
||||
efi_pixel_bitmask_t pi = info->pixel_information;
|
||||
int pf = info->pixel_format;
|
||||
u8 depth = pixel_bpp(pf, pi);
|
||||
struct match *m = ctx;
|
||||
|
||||
pf = info->pixel_format;
|
||||
pi = info->pixel_information;
|
||||
w = info->horizontal_resolution;
|
||||
h = info->vertical_resolution;
|
||||
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
|
||||
return false;
|
||||
|
||||
efi_bs_call(free_pool, info);
|
||||
if (area > m->area || (area == m->area && depth > m->depth))
|
||||
*m = (struct match){ mode, area, depth };
|
||||
|
||||
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
|
||||
continue;
|
||||
if (w == cmdline.res.width && h == cmdline.res.height &&
|
||||
(cmdline.res.format < 0 || cmdline.res.format == pf) &&
|
||||
(!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi)))
|
||||
return m;
|
||||
}
|
||||
|
||||
efi_err("Couldn't find requested mode\n");
|
||||
|
||||
return cur_mode;
|
||||
return false;
|
||||
}
|
||||
|
||||
static u32 choose_mode_auto(efi_graphics_output_protocol_t *gop)
|
||||
{
|
||||
efi_status_t status;
|
||||
struct match match = {};
|
||||
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
unsigned long info_size;
|
||||
choose_mode(gop, match_auto, &match);
|
||||
|
||||
u32 max_mode, cur_mode, best_mode, area;
|
||||
u8 depth;
|
||||
int pf;
|
||||
efi_pixel_bitmask_t pi;
|
||||
u32 m, w, h, a;
|
||||
u8 d;
|
||||
return match.mode;
|
||||
}
|
||||
|
||||
mode = efi_table_attr(gop, mode);
|
||||
static bool match_list(const efi_graphics_output_mode_info_t *info, u32 mode, void *ctx)
|
||||
{
|
||||
efi_pixel_bitmask_t pi = info->pixel_information;
|
||||
u32 cur_mode = (unsigned long)ctx;
|
||||
int pf = info->pixel_format;
|
||||
const char *dstr;
|
||||
u8 depth = 0;
|
||||
bool valid;
|
||||
|
||||
cur_mode = efi_table_attr(mode, mode);
|
||||
max_mode = efi_table_attr(mode, max_mode);
|
||||
valid = !(pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX);
|
||||
|
||||
info = efi_table_attr(mode, info);
|
||||
|
||||
pf = info->pixel_format;
|
||||
pi = info->pixel_information;
|
||||
w = info->horizontal_resolution;
|
||||
h = info->vertical_resolution;
|
||||
|
||||
best_mode = cur_mode;
|
||||
area = w * h;
|
||||
depth = pixel_bpp(pf, pi);
|
||||
|
||||
for (m = 0; m < max_mode; m++) {
|
||||
if (m == cur_mode)
|
||||
continue;
|
||||
|
||||
status = efi_call_proto(gop, query_mode, m,
|
||||
&info_size, &info);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
pf = info->pixel_format;
|
||||
pi = info->pixel_information;
|
||||
w = info->horizontal_resolution;
|
||||
h = info->vertical_resolution;
|
||||
|
||||
efi_bs_call(free_pool, info);
|
||||
|
||||
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
|
||||
continue;
|
||||
a = w * h;
|
||||
if (a < area)
|
||||
continue;
|
||||
d = pixel_bpp(pf, pi);
|
||||
if (a > area || d > depth) {
|
||||
best_mode = m;
|
||||
area = a;
|
||||
depth = d;
|
||||
}
|
||||
switch (pf) {
|
||||
case PIXEL_RGB_RESERVED_8BIT_PER_COLOR:
|
||||
dstr = "rgb";
|
||||
break;
|
||||
case PIXEL_BGR_RESERVED_8BIT_PER_COLOR:
|
||||
dstr = "bgr";
|
||||
break;
|
||||
case PIXEL_BIT_MASK:
|
||||
dstr = "";
|
||||
depth = pixel_bpp(pf, pi);
|
||||
break;
|
||||
case PIXEL_BLT_ONLY:
|
||||
dstr = "blt";
|
||||
break;
|
||||
default:
|
||||
dstr = "xxx";
|
||||
break;
|
||||
}
|
||||
|
||||
return best_mode;
|
||||
efi_printk("Mode %3u %c%c: Resolution %ux%u-%s%.0hhu\n",
|
||||
mode,
|
||||
(mode == cur_mode) ? '*' : ' ',
|
||||
!valid ? '-' : ' ',
|
||||
info->horizontal_resolution,
|
||||
info->vertical_resolution,
|
||||
dstr, depth);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static u32 choose_mode_list(efi_graphics_output_protocol_t *gop)
|
||||
{
|
||||
efi_status_t status;
|
||||
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
unsigned long info_size;
|
||||
|
||||
u32 max_mode, cur_mode;
|
||||
int pf;
|
||||
efi_pixel_bitmask_t pi;
|
||||
u32 m, w, h;
|
||||
u8 d;
|
||||
const char *dstr;
|
||||
bool valid;
|
||||
efi_graphics_output_protocol_mode_t *mode = efi_table_attr(gop, mode);
|
||||
unsigned long cur_mode = efi_table_attr(mode, mode);
|
||||
u32 max_mode = efi_table_attr(mode, max_mode);
|
||||
efi_input_key_t key;
|
||||
|
||||
mode = efi_table_attr(gop, mode);
|
||||
|
||||
cur_mode = efi_table_attr(mode, mode);
|
||||
max_mode = efi_table_attr(mode, max_mode);
|
||||
efi_status_t status;
|
||||
|
||||
efi_printk("Available graphics modes are 0-%u\n", max_mode-1);
|
||||
efi_puts(" * = current mode\n"
|
||||
" - = unusable mode\n");
|
||||
for (m = 0; m < max_mode; m++) {
|
||||
status = efi_call_proto(gop, query_mode, m,
|
||||
&info_size, &info);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
pf = info->pixel_format;
|
||||
pi = info->pixel_information;
|
||||
w = info->horizontal_resolution;
|
||||
h = info->vertical_resolution;
|
||||
|
||||
efi_bs_call(free_pool, info);
|
||||
|
||||
valid = !(pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX);
|
||||
d = 0;
|
||||
switch (pf) {
|
||||
case PIXEL_RGB_RESERVED_8BIT_PER_COLOR:
|
||||
dstr = "rgb";
|
||||
break;
|
||||
case PIXEL_BGR_RESERVED_8BIT_PER_COLOR:
|
||||
dstr = "bgr";
|
||||
break;
|
||||
case PIXEL_BIT_MASK:
|
||||
dstr = "";
|
||||
d = pixel_bpp(pf, pi);
|
||||
break;
|
||||
case PIXEL_BLT_ONLY:
|
||||
dstr = "blt";
|
||||
break;
|
||||
default:
|
||||
dstr = "xxx";
|
||||
break;
|
||||
}
|
||||
|
||||
efi_printk("Mode %3u %c%c: Resolution %ux%u-%s%.0hhu\n",
|
||||
m,
|
||||
m == cur_mode ? '*' : ' ',
|
||||
!valid ? '-' : ' ',
|
||||
w, h, dstr, d);
|
||||
}
|
||||
choose_mode(gop, match_list, (void *)cur_mode);
|
||||
|
||||
efi_puts("\nPress any key to continue (or wait 10 seconds)\n");
|
||||
status = efi_wait_for_key(10 * EFI_USEC_PER_SEC, &key);
|
||||
@ -461,26 +402,25 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
|
||||
}
|
||||
}
|
||||
|
||||
static efi_graphics_output_protocol_t *
|
||||
find_gop(efi_guid_t *proto, unsigned long size, void **handles)
|
||||
static efi_graphics_output_protocol_t *find_gop(unsigned long num,
|
||||
const efi_handle_t handles[])
|
||||
{
|
||||
efi_graphics_output_protocol_t *first_gop;
|
||||
efi_handle_t h;
|
||||
int i;
|
||||
|
||||
first_gop = NULL;
|
||||
|
||||
for_each_efi_handle(h, handles, size, i) {
|
||||
for_each_efi_handle(h, handles, num) {
|
||||
efi_status_t status;
|
||||
|
||||
efi_graphics_output_protocol_t *gop;
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
|
||||
efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
|
||||
void *dummy = NULL;
|
||||
|
||||
status = efi_bs_call(handle_protocol, h, proto, (void **)&gop);
|
||||
status = efi_bs_call(handle_protocol, h,
|
||||
&EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID,
|
||||
(void **)&gop);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
@ -500,7 +440,8 @@ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
|
||||
* Once we've found a GOP supporting ConOut,
|
||||
* don't bother looking any further.
|
||||
*/
|
||||
status = efi_bs_call(handle_protocol, h, &conout_proto, &dummy);
|
||||
status = efi_bs_call(handle_protocol, h,
|
||||
&EFI_CONSOLE_OUT_DEVICE_GUID, &dummy);
|
||||
if (status == EFI_SUCCESS)
|
||||
return gop;
|
||||
|
||||
@ -511,16 +452,22 @@ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
|
||||
return first_gop;
|
||||
}
|
||||
|
||||
static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
|
||||
unsigned long size, void **handles)
|
||||
efi_status_t efi_setup_gop(struct screen_info *si)
|
||||
{
|
||||
efi_graphics_output_protocol_t *gop;
|
||||
efi_handle_t *handles __free(efi_pool) = NULL;
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
efi_graphics_output_protocol_t *gop;
|
||||
efi_status_t status;
|
||||
unsigned long num;
|
||||
|
||||
gop = find_gop(proto, size, handles);
|
||||
status = efi_bs_call(locate_handle_buffer, EFI_LOCATE_BY_PROTOCOL,
|
||||
&EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, NULL, &num,
|
||||
&handles);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* Did we find any GOPs? */
|
||||
gop = find_gop(num, handles);
|
||||
if (!gop)
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
@ -552,29 +499,3 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we have Graphics Output Protocol
|
||||
*/
|
||||
efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
|
||||
unsigned long size)
|
||||
{
|
||||
efi_status_t status;
|
||||
void **gop_handle = NULL;
|
||||
|
||||
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
|
||||
(void **)&gop_handle);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, proto, NULL,
|
||||
&size, gop_handle);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_handle;
|
||||
|
||||
status = setup_gop(si, proto, size, gop_handle);
|
||||
|
||||
free_handle:
|
||||
efi_bs_call(free_pool, gop_handle);
|
||||
return status;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ u32 efi_kaslr_get_phys_seed(efi_handle_t image_handle)
|
||||
*/
|
||||
static bool check_image_region(u64 base, u64 size)
|
||||
{
|
||||
struct efi_boot_memmap *map;
|
||||
struct efi_boot_memmap *map __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
bool ret = false;
|
||||
int map_offset;
|
||||
@ -80,8 +80,6 @@ static bool check_image_region(u64 base, u64 size)
|
||||
}
|
||||
}
|
||||
|
||||
efi_bs_call(free_pool, map);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -20,10 +20,10 @@
|
||||
efi_status_t efi_get_memory_map(struct efi_boot_memmap **map,
|
||||
bool install_cfg_tbl)
|
||||
{
|
||||
struct efi_boot_memmap tmp, *m __free(efi_pool) = NULL;
|
||||
int memtype = install_cfg_tbl ? EFI_ACPI_RECLAIM_MEMORY
|
||||
: EFI_LOADER_DATA;
|
||||
efi_guid_t tbl_guid = LINUX_EFI_BOOT_MEMMAP_GUID;
|
||||
struct efi_boot_memmap *m, tmp;
|
||||
efi_status_t status;
|
||||
unsigned long size;
|
||||
|
||||
@ -48,24 +48,20 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap **map,
|
||||
*/
|
||||
status = efi_bs_call(install_configuration_table, &tbl_guid, m);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_map;
|
||||
return status;
|
||||
}
|
||||
|
||||
m->buff_size = m->map_size = size;
|
||||
status = efi_bs_call(get_memory_map, &m->map_size, m->map, &m->map_key,
|
||||
&m->desc_size, &m->desc_ver);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto uninstall_table;
|
||||
if (status != EFI_SUCCESS) {
|
||||
if (install_cfg_tbl)
|
||||
efi_bs_call(install_configuration_table, &tbl_guid, NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
*map = m;
|
||||
*map = no_free_ptr(m);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
uninstall_table:
|
||||
if (install_cfg_tbl)
|
||||
efi_bs_call(install_configuration_table, &tbl_guid, NULL);
|
||||
free_map:
|
||||
efi_bs_call(free_pool, m);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,37 +16,20 @@
|
||||
void efi_pci_disable_bridge_busmaster(void)
|
||||
{
|
||||
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
|
||||
unsigned long pci_handle_size = 0;
|
||||
efi_handle_t *pci_handle = NULL;
|
||||
efi_handle_t *pci_handle __free(efi_pool) = NULL;
|
||||
unsigned long pci_handle_num;
|
||||
efi_handle_t handle;
|
||||
efi_status_t status;
|
||||
u16 class, command;
|
||||
int i;
|
||||
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto,
|
||||
NULL, &pci_handle_size, NULL);
|
||||
|
||||
if (status != EFI_BUFFER_TOO_SMALL) {
|
||||
if (status != EFI_SUCCESS && status != EFI_NOT_FOUND)
|
||||
efi_err("Failed to locate PCI I/O handles'\n");
|
||||
status = efi_bs_call(locate_handle_buffer, EFI_LOCATE_BY_PROTOCOL,
|
||||
&pci_proto, NULL, &pci_handle_num, &pci_handle);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to locate PCI I/O handles\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, pci_handle_size,
|
||||
(void **)&pci_handle);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to allocate memory for 'pci_handle'\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto,
|
||||
NULL, &pci_handle_size, pci_handle);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to locate PCI I/O handles'\n");
|
||||
goto free_handle;
|
||||
}
|
||||
|
||||
for_each_efi_handle(handle, pci_handle, pci_handle_size, i) {
|
||||
for_each_efi_handle(handle, pci_handle, pci_handle_num) {
|
||||
efi_pci_io_protocol_t *pci;
|
||||
unsigned long segment_nr, bus_nr, device_nr, func_nr;
|
||||
|
||||
@ -82,7 +65,7 @@ void efi_pci_disable_bridge_busmaster(void)
|
||||
efi_bs_call(disconnect_controller, handle, NULL, NULL);
|
||||
}
|
||||
|
||||
for_each_efi_handle(handle, pci_handle, pci_handle_size, i) {
|
||||
for_each_efi_handle(handle, pci_handle, pci_handle_num) {
|
||||
efi_pci_io_protocol_t *pci;
|
||||
|
||||
status = efi_bs_call(handle_protocol, handle, &pci_proto,
|
||||
@ -108,7 +91,4 @@ void efi_pci_disable_bridge_busmaster(void)
|
||||
if (status != EFI_SUCCESS)
|
||||
efi_err("Failed to disable PCI busmastering\n");
|
||||
}
|
||||
|
||||
free_handle:
|
||||
efi_bs_call(free_pool, pci_handle);
|
||||
}
|
||||
|
@ -59,9 +59,9 @@ efi_status_t efi_random_alloc(unsigned long size,
|
||||
unsigned long alloc_min,
|
||||
unsigned long alloc_max)
|
||||
{
|
||||
struct efi_boot_memmap *map __free(efi_pool) = NULL;
|
||||
unsigned long total_slots = 0, target_slot;
|
||||
unsigned long total_mirrored_slots = 0;
|
||||
struct efi_boot_memmap *map;
|
||||
efi_status_t status;
|
||||
int map_offset;
|
||||
|
||||
@ -130,7 +130,5 @@ efi_status_t efi_random_alloc(unsigned long size,
|
||||
break;
|
||||
}
|
||||
|
||||
efi_bs_call(free_pool, map);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -23,14 +23,14 @@
|
||||
efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
|
||||
unsigned long *addr, unsigned long min)
|
||||
{
|
||||
struct efi_boot_memmap *map;
|
||||
struct efi_boot_memmap *map __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
unsigned long nr_pages;
|
||||
int i;
|
||||
|
||||
status = efi_get_memory_map(&map, false);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail;
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Enforce minimum alignment that EFI or Linux requires when
|
||||
@ -79,11 +79,9 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
|
||||
}
|
||||
|
||||
if (i == map->map_size / map->desc_size)
|
||||
status = EFI_NOT_FOUND;
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
efi_bs_call(free_pool, map);
|
||||
fail:
|
||||
return status;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,7 +42,7 @@ union sev_memory_acceptance_protocol {
|
||||
static efi_status_t
|
||||
preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
|
||||
{
|
||||
struct pci_setup_rom *rom = NULL;
|
||||
struct pci_setup_rom *rom __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
unsigned long size;
|
||||
uint64_t romsize;
|
||||
@ -75,14 +75,13 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
|
||||
rom->data.len = size - sizeof(struct setup_data);
|
||||
rom->data.next = 0;
|
||||
rom->pcilen = romsize;
|
||||
*__rom = rom;
|
||||
|
||||
status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
|
||||
PCI_VENDOR_ID, 1, &rom->vendor);
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to read rom->vendor\n");
|
||||
goto free_struct;
|
||||
return status;
|
||||
}
|
||||
|
||||
status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
|
||||
@ -90,21 +89,18 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to read rom->devid\n");
|
||||
goto free_struct;
|
||||
return status;
|
||||
}
|
||||
|
||||
status = efi_call_proto(pci, get_location, &rom->segment, &rom->bus,
|
||||
&rom->device, &rom->function);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_struct;
|
||||
return status;
|
||||
|
||||
memcpy(rom->romdata, romimage, romsize);
|
||||
return status;
|
||||
|
||||
free_struct:
|
||||
efi_bs_call(free_pool, rom);
|
||||
return status;
|
||||
*__rom = no_free_ptr(rom);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -119,38 +115,23 @@ free_struct:
|
||||
static void setup_efi_pci(struct boot_params *params)
|
||||
{
|
||||
efi_status_t status;
|
||||
void **pci_handle = NULL;
|
||||
efi_handle_t *pci_handle __free(efi_pool) = NULL;
|
||||
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
|
||||
unsigned long size = 0;
|
||||
struct setup_data *data;
|
||||
unsigned long num;
|
||||
efi_handle_t h;
|
||||
int i;
|
||||
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
|
||||
&pci_proto, NULL, &size, pci_handle);
|
||||
|
||||
if (status == EFI_BUFFER_TOO_SMALL) {
|
||||
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
|
||||
(void **)&pci_handle);
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to allocate memory for 'pci_handle'\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
|
||||
&pci_proto, NULL, &size, pci_handle);
|
||||
}
|
||||
|
||||
status = efi_bs_call(locate_handle_buffer, EFI_LOCATE_BY_PROTOCOL,
|
||||
&pci_proto, NULL, &num, &pci_handle);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_handle;
|
||||
return;
|
||||
|
||||
data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
|
||||
|
||||
while (data && data->next)
|
||||
data = (struct setup_data *)(unsigned long)data->next;
|
||||
|
||||
for_each_efi_handle(h, pci_handle, size, i) {
|
||||
for_each_efi_handle(h, pci_handle, num) {
|
||||
efi_pci_io_protocol_t *pci = NULL;
|
||||
struct pci_setup_rom *rom;
|
||||
|
||||
@ -170,9 +151,6 @@ static void setup_efi_pci(struct boot_params *params)
|
||||
|
||||
data = (struct setup_data *)rom;
|
||||
}
|
||||
|
||||
free_handle:
|
||||
efi_bs_call(free_pool, pci_handle);
|
||||
}
|
||||
|
||||
static void retrieve_apple_device_properties(struct boot_params *boot_params)
|
||||
@ -405,116 +383,13 @@ static void setup_quirks(struct boot_params *boot_params)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we have Universal Graphics Adapter (UGA) protocol
|
||||
*/
|
||||
static efi_status_t
|
||||
setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size)
|
||||
{
|
||||
efi_status_t status;
|
||||
u32 width, height;
|
||||
void **uga_handle = NULL;
|
||||
efi_uga_draw_protocol_t *uga = NULL, *first_uga;
|
||||
efi_handle_t handle;
|
||||
int i;
|
||||
|
||||
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
|
||||
(void **)&uga_handle);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
|
||||
uga_proto, NULL, &size, uga_handle);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_handle;
|
||||
|
||||
height = 0;
|
||||
width = 0;
|
||||
|
||||
first_uga = NULL;
|
||||
for_each_efi_handle(handle, uga_handle, size, i) {
|
||||
efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
|
||||
u32 w, h, depth, refresh;
|
||||
void *pciio;
|
||||
|
||||
status = efi_bs_call(handle_protocol, handle, uga_proto,
|
||||
(void **)&uga);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
pciio = NULL;
|
||||
efi_bs_call(handle_protocol, handle, &pciio_proto, &pciio);
|
||||
|
||||
status = efi_call_proto(uga, get_mode, &w, &h, &depth, &refresh);
|
||||
if (status == EFI_SUCCESS && (!first_uga || pciio)) {
|
||||
width = w;
|
||||
height = h;
|
||||
|
||||
/*
|
||||
* Once we've found a UGA supporting PCIIO,
|
||||
* don't bother looking any further.
|
||||
*/
|
||||
if (pciio)
|
||||
break;
|
||||
|
||||
first_uga = uga;
|
||||
}
|
||||
}
|
||||
|
||||
if (!width && !height)
|
||||
goto free_handle;
|
||||
|
||||
/* EFI framebuffer */
|
||||
si->orig_video_isVGA = VIDEO_TYPE_EFI;
|
||||
|
||||
si->lfb_depth = 32;
|
||||
si->lfb_width = width;
|
||||
si->lfb_height = height;
|
||||
|
||||
si->red_size = 8;
|
||||
si->red_pos = 16;
|
||||
si->green_size = 8;
|
||||
si->green_pos = 8;
|
||||
si->blue_size = 8;
|
||||
si->blue_pos = 0;
|
||||
si->rsvd_size = 8;
|
||||
si->rsvd_pos = 24;
|
||||
|
||||
free_handle:
|
||||
efi_bs_call(free_pool, uga_handle);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void setup_graphics(struct boot_params *boot_params)
|
||||
{
|
||||
efi_guid_t graphics_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
struct screen_info *si;
|
||||
efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
|
||||
efi_status_t status;
|
||||
unsigned long size;
|
||||
void **gop_handle = NULL;
|
||||
void **uga_handle = NULL;
|
||||
struct screen_info *si = memset(&boot_params->screen_info, 0, sizeof(*si));
|
||||
|
||||
si = &boot_params->screen_info;
|
||||
memset(si, 0, sizeof(*si));
|
||||
|
||||
size = 0;
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
|
||||
&graphics_proto, NULL, &size, gop_handle);
|
||||
if (status == EFI_BUFFER_TOO_SMALL)
|
||||
status = efi_setup_gop(si, &graphics_proto, size);
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
size = 0;
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
|
||||
&uga_proto, NULL, &size, uga_handle);
|
||||
if (status == EFI_BUFFER_TOO_SMALL)
|
||||
setup_uga(si, &uga_proto, size);
|
||||
}
|
||||
efi_setup_gop(si);
|
||||
}
|
||||
|
||||
|
||||
static void __noreturn efi_exit(efi_handle_t handle, efi_status_t status)
|
||||
{
|
||||
efi_bs_call(exit, handle, status, 0, NULL);
|
||||
@ -737,7 +612,7 @@ static efi_status_t allocate_e820(struct boot_params *params,
|
||||
struct setup_data **e820ext,
|
||||
u32 *e820ext_size)
|
||||
{
|
||||
struct efi_boot_memmap *map;
|
||||
struct efi_boot_memmap *map __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
__u32 nr_desc;
|
||||
|
||||
@ -751,13 +626,14 @@ static efi_status_t allocate_e820(struct boot_params *params,
|
||||
EFI_MMAP_NR_SLACK_SLOTS;
|
||||
|
||||
status = alloc_e820ext(nr_e820ext, e820ext, e820ext_size);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_UNACCEPTED_MEMORY) && status == EFI_SUCCESS)
|
||||
status = allocate_unaccepted_bitmap(nr_desc, map);
|
||||
if (IS_ENABLED(CONFIG_UNACCEPTED_MEMORY))
|
||||
return allocate_unaccepted_bitmap(nr_desc, map);
|
||||
|
||||
efi_bs_call(free_pool, map);
|
||||
return status;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
struct exit_boot_struct {
|
||||
|
68
drivers/firmware/efi/libstub/zboot-decompress-gzip.c
Normal file
68
drivers/firmware/efi/libstub/zboot-decompress-gzip.c
Normal file
@ -0,0 +1,68 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/zlib.h>
|
||||
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
#include "inftrees.c"
|
||||
#include "inffast.c"
|
||||
#include "inflate.c"
|
||||
|
||||
extern unsigned char _gzdata_start[], _gzdata_end[];
|
||||
extern u32 __aligned(1) payload_size;
|
||||
|
||||
static struct z_stream_s stream;
|
||||
|
||||
efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size)
|
||||
{
|
||||
efi_status_t status;
|
||||
int rc;
|
||||
|
||||
/* skip the 10 byte header, assume no recorded filename */
|
||||
stream.next_in = _gzdata_start + 10;
|
||||
stream.avail_in = _gzdata_end - stream.next_in;
|
||||
|
||||
status = efi_allocate_pages(zlib_inflate_workspacesize(),
|
||||
(unsigned long *)&stream.workspace,
|
||||
ULONG_MAX);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
rc = zlib_inflateInit2(&stream, -MAX_WBITS);
|
||||
if (rc != Z_OK) {
|
||||
efi_err("failed to initialize GZIP decompressor: %d\n", rc);
|
||||
status = EFI_LOAD_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*alloc_size = payload_size;
|
||||
return EFI_SUCCESS;
|
||||
out:
|
||||
efi_free(zlib_inflate_workspacesize(), (unsigned long)stream.workspace);
|
||||
return status;
|
||||
}
|
||||
|
||||
efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen)
|
||||
{
|
||||
int rc;
|
||||
|
||||
stream.next_out = out;
|
||||
stream.avail_out = outlen;
|
||||
|
||||
rc = zlib_inflate(&stream, 0);
|
||||
zlib_inflateEnd(&stream);
|
||||
|
||||
efi_free(zlib_inflate_workspacesize(), (unsigned long)stream.workspace);
|
||||
|
||||
if (rc != Z_STREAM_END) {
|
||||
efi_err("GZIP decompression failed with status %d\n", rc);
|
||||
return EFI_LOAD_ERROR;
|
||||
}
|
||||
|
||||
efi_cache_sync_image((unsigned long)out, outlen);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
83
drivers/firmware/efi/libstub/zboot-decompress-zstd.c
Normal file
83
drivers/firmware/efi/libstub/zboot-decompress-zstd.c
Normal file
@ -0,0 +1,83 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/zstd.h>
|
||||
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "decompress_sources.h"
|
||||
#include "efistub.h"
|
||||
|
||||
extern unsigned char _gzdata_start[], _gzdata_end[];
|
||||
extern u32 __aligned(1) payload_size;
|
||||
|
||||
static ZSTD_inBuffer zstd_buf;
|
||||
static ZSTD_DStream *dstream;
|
||||
static size_t wksp_size;
|
||||
static void *wksp;
|
||||
|
||||
efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size)
|
||||
{
|
||||
zstd_frame_header header;
|
||||
efi_status_t status;
|
||||
size_t ret;
|
||||
|
||||
zstd_buf.src = _gzdata_start;
|
||||
zstd_buf.pos = 0;
|
||||
zstd_buf.size = _gzdata_end - _gzdata_start;
|
||||
|
||||
ret = zstd_get_frame_header(&header, zstd_buf.src, zstd_buf.size);
|
||||
if (ret != 0) {
|
||||
efi_err("ZSTD-compressed data has an incomplete frame header\n");
|
||||
status = EFI_LOAD_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (header.windowSize > (1 << ZSTD_WINDOWLOG_MAX)) {
|
||||
efi_err("ZSTD-compressed data has too large a window size\n");
|
||||
status = EFI_LOAD_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
wksp_size = zstd_dstream_workspace_bound(header.windowSize);
|
||||
status = efi_allocate_pages(wksp_size, (unsigned long *)&wksp, ULONG_MAX);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto out;
|
||||
|
||||
dstream = zstd_init_dstream(header.windowSize, wksp, wksp_size);
|
||||
if (!dstream) {
|
||||
efi_err("Can't initialize ZSTD stream\n");
|
||||
status = EFI_OUT_OF_RESOURCES;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*alloc_size = payload_size;
|
||||
return EFI_SUCCESS;
|
||||
out:
|
||||
efi_free(wksp_size, (unsigned long)wksp);
|
||||
return status;
|
||||
}
|
||||
|
||||
efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen)
|
||||
{
|
||||
ZSTD_outBuffer zstd_dec;
|
||||
size_t ret;
|
||||
int retval;
|
||||
|
||||
zstd_dec.dst = out;
|
||||
zstd_dec.pos = 0;
|
||||
zstd_dec.size = outlen;
|
||||
|
||||
ret = zstd_decompress_stream(dstream, &zstd_dec, &zstd_buf);
|
||||
efi_free(wksp_size, (unsigned long)wksp);
|
||||
|
||||
retval = zstd_get_error_code(ret);
|
||||
if (retval) {
|
||||
efi_err("ZSTD-decompression failed with status %d\n", retval);
|
||||
return EFI_LOAD_ERROR;
|
||||
}
|
||||
|
||||
efi_cache_sync_image((unsigned long)out, outlen);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
@ -7,36 +7,6 @@
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
static unsigned char zboot_heap[SZ_256K] __aligned(64);
|
||||
static unsigned long free_mem_ptr, free_mem_end_ptr;
|
||||
|
||||
#define STATIC static
|
||||
#if defined(CONFIG_KERNEL_GZIP)
|
||||
#include "../../../../lib/decompress_inflate.c"
|
||||
#elif defined(CONFIG_KERNEL_LZ4)
|
||||
#include "../../../../lib/decompress_unlz4.c"
|
||||
#elif defined(CONFIG_KERNEL_LZMA)
|
||||
#include "../../../../lib/decompress_unlzma.c"
|
||||
#elif defined(CONFIG_KERNEL_LZO)
|
||||
#include "../../../../lib/decompress_unlzo.c"
|
||||
#elif defined(CONFIG_KERNEL_XZ)
|
||||
#undef memcpy
|
||||
#define memcpy memcpy
|
||||
#undef memmove
|
||||
#define memmove memmove
|
||||
#include "../../../../lib/decompress_unxz.c"
|
||||
#elif defined(CONFIG_KERNEL_ZSTD)
|
||||
#include "../../../../lib/decompress_unzstd.c"
|
||||
#endif
|
||||
|
||||
extern char efi_zboot_header[];
|
||||
extern char _gzdata_start[], _gzdata_end[];
|
||||
|
||||
static void error(char *x)
|
||||
{
|
||||
efi_err("EFI decompressor: %s\n", x);
|
||||
}
|
||||
|
||||
static unsigned long alloc_preferred_address(unsigned long alloc_size)
|
||||
{
|
||||
#ifdef EFI_KIMG_PREFERRED_ADDRESS
|
||||
@ -64,22 +34,17 @@ struct screen_info *alloc_screen_info(void)
|
||||
asmlinkage efi_status_t __efiapi
|
||||
efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
|
||||
{
|
||||
unsigned long compressed_size = _gzdata_end - _gzdata_start;
|
||||
char *cmdline_ptr __free(efi_pool) = NULL;
|
||||
unsigned long image_base, alloc_size;
|
||||
efi_loaded_image_t *image;
|
||||
efi_status_t status;
|
||||
char *cmdline_ptr;
|
||||
int ret;
|
||||
|
||||
WRITE_ONCE(efi_system_table, systab);
|
||||
|
||||
free_mem_ptr = (unsigned long)&zboot_heap;
|
||||
free_mem_end_ptr = free_mem_ptr + sizeof(zboot_heap);
|
||||
|
||||
status = efi_bs_call(handle_protocol, handle,
|
||||
&LOADED_IMAGE_PROTOCOL_GUID, (void **)&image);
|
||||
if (status != EFI_SUCCESS) {
|
||||
error("Failed to locate parent's loaded image protocol");
|
||||
efi_err("Failed to locate parent's loaded image protocol\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -89,9 +54,9 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
|
||||
|
||||
efi_info("Decompressing Linux Kernel...\n");
|
||||
|
||||
// SizeOfImage from the compressee's PE/COFF header
|
||||
alloc_size = round_up(get_unaligned_le32(_gzdata_end - 4),
|
||||
EFI_ALLOC_ALIGN);
|
||||
status = efi_zboot_decompress_init(&alloc_size);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
// If the architecture has a preferred address for the image,
|
||||
// try that first.
|
||||
@ -122,26 +87,14 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
|
||||
seed, EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to allocate memory\n");
|
||||
goto free_cmdline;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
// Decompress the payload into the newly allocated buffer.
|
||||
ret = __decompress(_gzdata_start, compressed_size, NULL, NULL,
|
||||
(void *)image_base, alloc_size, NULL, error);
|
||||
if (ret < 0) {
|
||||
error("Decompression failed");
|
||||
status = EFI_DEVICE_ERROR;
|
||||
goto free_image;
|
||||
}
|
||||
// Decompress the payload into the newly allocated buffer
|
||||
status = efi_zboot_decompress((void *)image_base, alloc_size) ?:
|
||||
efi_stub_common(handle, image, image_base, cmdline_ptr);
|
||||
|
||||
efi_cache_sync_image(image_base, alloc_size);
|
||||
|
||||
status = efi_stub_common(handle, image, image_base, cmdline_ptr);
|
||||
|
||||
free_image:
|
||||
efi_free(alloc_size, image_base);
|
||||
free_cmdline:
|
||||
efi_bs_call(free_pool, cmdline_ptr);
|
||||
return status;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ SECTIONS
|
||||
.rodata : ALIGN(8) {
|
||||
__efistub__gzdata_start = .;
|
||||
*(.gzdata)
|
||||
__efistub_payload_size = . - 4;
|
||||
__efistub__gzdata_end = .;
|
||||
*(.rodata* .init.rodata* .srodata*)
|
||||
|
||||
|
@ -91,6 +91,7 @@ void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
|
||||
_ret_; \
|
||||
})
|
||||
|
||||
#ifdef CONFIG_EFI
|
||||
static int __init efifb_set_system(const struct dmi_system_id *id)
|
||||
{
|
||||
struct efifb_dmi_info *info = id->driver_data;
|
||||
@ -346,7 +347,6 @@ static const struct fwnode_operations efifb_fwnode_ops = {
|
||||
.add_links = efifb_add_links,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_EFI
|
||||
static struct fwnode_handle efifb_fwnode;
|
||||
|
||||
__init void sysfb_apply_efi_quirks(void)
|
||||
|
@ -36,28 +36,41 @@ static ssize_t efivarfs_file_write(struct file *file,
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
inode_lock(inode);
|
||||
if (d_unhashed(file->f_path.dentry)) {
|
||||
/*
|
||||
* file got removed; don't allow a set. Caused by an
|
||||
* unsuccessful create or successful delete write
|
||||
* racing with us.
|
||||
*/
|
||||
bytes = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bytes = efivar_entry_set_get_size(var, attributes, &datasize,
|
||||
data, &set);
|
||||
if (!set && bytes) {
|
||||
if (!set) {
|
||||
if (bytes == -ENOENT)
|
||||
bytes = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bytes == -ENOENT) {
|
||||
drop_nlink(inode);
|
||||
d_delete(file->f_path.dentry);
|
||||
dput(file->f_path.dentry);
|
||||
/*
|
||||
* zero size signals to release that the write deleted
|
||||
* the variable
|
||||
*/
|
||||
i_size_write(inode, 0);
|
||||
} else {
|
||||
inode_lock(inode);
|
||||
i_size_write(inode, datasize + sizeof(attributes));
|
||||
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
||||
inode_unlock(inode);
|
||||
}
|
||||
|
||||
bytes = count;
|
||||
|
||||
out:
|
||||
inode_unlock(inode);
|
||||
|
||||
kfree(data);
|
||||
|
||||
return bytes;
|
||||
@ -106,8 +119,37 @@ out_free:
|
||||
return size;
|
||||
}
|
||||
|
||||
static int efivarfs_file_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
bool release;
|
||||
struct efivar_entry *var = inode->i_private;
|
||||
|
||||
inode_lock(inode);
|
||||
release = (--var->open_count == 0 && i_size_read(inode) == 0);
|
||||
inode_unlock(inode);
|
||||
|
||||
if (release)
|
||||
simple_recursive_removal(file->f_path.dentry, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int efivarfs_file_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct efivar_entry *entry = inode->i_private;
|
||||
|
||||
file->private_data = entry;
|
||||
|
||||
inode_lock(inode);
|
||||
entry->open_count++;
|
||||
inode_unlock(inode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct file_operations efivarfs_file_operations = {
|
||||
.open = simple_open,
|
||||
.read = efivarfs_file_read,
|
||||
.write = efivarfs_file_write,
|
||||
.open = efivarfs_file_open,
|
||||
.read = efivarfs_file_read,
|
||||
.write = efivarfs_file_write,
|
||||
.release = efivarfs_file_release,
|
||||
};
|
||||
|
@ -77,7 +77,6 @@ static bool efivarfs_valid_name(const char *str, int len)
|
||||
static int efivarfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl)
|
||||
{
|
||||
struct efivarfs_fs_info *info = dir->i_sb->s_fs_info;
|
||||
struct inode *inode = NULL;
|
||||
struct efivar_entry *var;
|
||||
int namelen, i = 0, err = 0;
|
||||
@ -119,10 +118,6 @@ static int efivarfs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
inode->i_private = var;
|
||||
kmemleak_ignore(var);
|
||||
|
||||
err = efivar_entry_add(var, &info->efivarfs_list);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
d_instantiate(dentry, inode);
|
||||
dget(dentry);
|
||||
out:
|
||||
|
@ -6,7 +6,6 @@
|
||||
#ifndef EFIVAR_FS_INTERNAL_H
|
||||
#define EFIVAR_FS_INTERNAL_H
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/efi.h>
|
||||
|
||||
struct efivarfs_mount_opts {
|
||||
@ -16,30 +15,24 @@ struct efivarfs_mount_opts {
|
||||
|
||||
struct efivarfs_fs_info {
|
||||
struct efivarfs_mount_opts mount_opts;
|
||||
struct list_head efivarfs_list;
|
||||
struct super_block *sb;
|
||||
struct notifier_block nb;
|
||||
struct notifier_block pm_nb;
|
||||
};
|
||||
|
||||
struct efi_variable {
|
||||
efi_char16_t VariableName[EFI_VAR_NAME_LEN/sizeof(efi_char16_t)];
|
||||
efi_guid_t VendorGuid;
|
||||
__u32 Attributes;
|
||||
};
|
||||
|
||||
struct efivar_entry {
|
||||
struct efi_variable var;
|
||||
struct list_head list;
|
||||
struct kobject kobj;
|
||||
unsigned long open_count;
|
||||
};
|
||||
|
||||
int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *,
|
||||
struct list_head *),
|
||||
void *data, struct list_head *head);
|
||||
int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),
|
||||
void *data, bool duplicate_check);
|
||||
|
||||
int efivar_entry_add(struct efivar_entry *entry, struct list_head *head);
|
||||
void __efivar_entry_add(struct efivar_entry *entry, struct list_head *head);
|
||||
void efivar_entry_remove(struct efivar_entry *entry);
|
||||
int efivar_entry_delete(struct efivar_entry *entry);
|
||||
|
||||
int efivar_entry_size(struct efivar_entry *entry, unsigned long *size);
|
||||
@ -50,13 +43,14 @@ int efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
|
||||
int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
|
||||
unsigned long *size, void *data, bool *set);
|
||||
|
||||
int efivar_entry_iter(int (*func)(struct efivar_entry *, void *),
|
||||
struct list_head *head, void *data);
|
||||
|
||||
bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
|
||||
unsigned long data_size);
|
||||
bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
|
||||
size_t len);
|
||||
char *efivar_get_utf8name(const efi_char16_t *name16, efi_guid_t *vendor);
|
||||
bool efivarfs_variable_is_present(efi_char16_t *variable_name,
|
||||
efi_guid_t *vendor, void *data);
|
||||
|
||||
extern const struct file_operations efivarfs_file_operations;
|
||||
extern const struct inode_operations efivarfs_dir_inode_operations;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/ucs2_string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/statfs.h>
|
||||
#include <linux/notifier.h>
|
||||
@ -41,6 +42,9 @@ static int efivarfs_ops_notifier(struct notifier_block *nb, unsigned long event,
|
||||
|
||||
static void efivarfs_evict_inode(struct inode *inode)
|
||||
{
|
||||
struct efivar_entry *entry = inode->i_private;
|
||||
|
||||
kfree(entry);
|
||||
clear_inode(inode);
|
||||
}
|
||||
|
||||
@ -181,51 +185,60 @@ static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
|
||||
unsigned long name_size, void *data,
|
||||
struct list_head *list)
|
||||
bool efivarfs_variable_is_present(efi_char16_t *variable_name,
|
||||
efi_guid_t *vendor, void *data)
|
||||
{
|
||||
char *name = efivar_get_utf8name(variable_name, vendor);
|
||||
struct super_block *sb = data;
|
||||
struct dentry *dentry;
|
||||
struct qstr qstr;
|
||||
|
||||
if (!name)
|
||||
/*
|
||||
* If the allocation failed there'll already be an
|
||||
* error in the log (and likely a huge and growing
|
||||
* number of them since they system will be under
|
||||
* extreme memory pressure), so simply assume
|
||||
* collision for safety but don't add to the log
|
||||
* flood.
|
||||
*/
|
||||
return true;
|
||||
|
||||
qstr.name = name;
|
||||
qstr.len = strlen(name);
|
||||
dentry = d_hash_and_lookup(sb->s_root, &qstr);
|
||||
kfree(name);
|
||||
if (!IS_ERR_OR_NULL(dentry))
|
||||
dput(dentry);
|
||||
|
||||
return dentry != NULL;
|
||||
}
|
||||
|
||||
static int efivarfs_create_dentry(struct super_block *sb, efi_char16_t *name16,
|
||||
unsigned long name_size, efi_guid_t *vendor,
|
||||
char *name)
|
||||
{
|
||||
struct super_block *sb = (struct super_block *)data;
|
||||
struct efivar_entry *entry;
|
||||
struct inode *inode = NULL;
|
||||
struct inode *inode;
|
||||
struct dentry *dentry, *root = sb->s_root;
|
||||
unsigned long size = 0;
|
||||
char *name;
|
||||
int len;
|
||||
int err = -ENOMEM;
|
||||
bool is_removable = false;
|
||||
|
||||
if (guid_equal(&vendor, &LINUX_EFI_RANDOM_SEED_TABLE_GUID))
|
||||
return 0;
|
||||
|
||||
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
|
||||
if (!entry)
|
||||
return err;
|
||||
|
||||
memcpy(entry->var.VariableName, name16, name_size);
|
||||
memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
|
||||
memcpy(&(entry->var.VendorGuid), vendor, sizeof(efi_guid_t));
|
||||
|
||||
len = ucs2_utf8size(entry->var.VariableName);
|
||||
|
||||
/* name, plus '-', plus GUID, plus NUL*/
|
||||
name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL);
|
||||
if (!name)
|
||||
goto fail;
|
||||
|
||||
ucs2_as_utf8(name, entry->var.VariableName, len);
|
||||
/* length of the variable name itself: remove GUID and separator */
|
||||
len = strlen(name) - EFI_VARIABLE_GUID_LEN - 1;
|
||||
|
||||
if (efivar_variable_is_removable(entry->var.VendorGuid, name, len))
|
||||
is_removable = true;
|
||||
|
||||
name[len] = '-';
|
||||
|
||||
efi_guid_to_str(&entry->var.VendorGuid, name + len + 1);
|
||||
|
||||
name[len + EFI_VARIABLE_GUID_LEN+1] = '\0';
|
||||
|
||||
/* replace invalid slashes like kobject_set_name_vargs does for /sys/firmware/efi/vars. */
|
||||
strreplace(name, '/', '!');
|
||||
|
||||
inode = efivarfs_get_inode(sb, d_inode(root), S_IFREG | 0644, 0,
|
||||
is_removable);
|
||||
if (!inode)
|
||||
@ -238,14 +251,13 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
|
||||
}
|
||||
|
||||
__efivar_entry_get(entry, NULL, &size, NULL);
|
||||
__efivar_entry_add(entry, list);
|
||||
|
||||
/* copied by the above to local storage in the dentry. */
|
||||
kfree(name);
|
||||
|
||||
inode_lock(inode);
|
||||
inode->i_private = entry;
|
||||
i_size_write(inode, size + sizeof(entry->var.Attributes));
|
||||
i_size_write(inode, size + sizeof(__u32)); /* attributes + data */
|
||||
inode_unlock(inode);
|
||||
d_add(dentry, inode);
|
||||
|
||||
@ -255,16 +267,25 @@ fail_inode:
|
||||
iput(inode);
|
||||
fail_name:
|
||||
kfree(name);
|
||||
fail:
|
||||
kfree(entry);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int efivarfs_destroy(struct efivar_entry *entry, void *data)
|
||||
static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
|
||||
unsigned long name_size, void *data)
|
||||
{
|
||||
efivar_entry_remove(entry);
|
||||
kfree(entry);
|
||||
return 0;
|
||||
struct super_block *sb = (struct super_block *)data;
|
||||
char *name;
|
||||
|
||||
if (guid_equal(&vendor, &LINUX_EFI_RANDOM_SEED_TABLE_GUID))
|
||||
return 0;
|
||||
|
||||
name = efivar_get_utf8name(name16, &vendor);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
return efivarfs_create_dentry(sb, name16, name_size, &vendor, name);
|
||||
}
|
||||
|
||||
enum {
|
||||
@ -336,7 +357,7 @@ static int efivarfs_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return efivar_init(efivarfs_callback, sb, &sfi->efivarfs_list);
|
||||
return efivar_init(efivarfs_callback, sb, true);
|
||||
}
|
||||
|
||||
static int efivarfs_get_tree(struct fs_context *fc)
|
||||
@ -360,6 +381,148 @@ static const struct fs_context_operations efivarfs_context_ops = {
|
||||
.reconfigure = efivarfs_reconfigure,
|
||||
};
|
||||
|
||||
struct efivarfs_ctx {
|
||||
struct dir_context ctx;
|
||||
struct super_block *sb;
|
||||
struct dentry *dentry;
|
||||
};
|
||||
|
||||
static bool efivarfs_actor(struct dir_context *ctx, const char *name, int len,
|
||||
loff_t offset, u64 ino, unsigned mode)
|
||||
{
|
||||
unsigned long size;
|
||||
struct efivarfs_ctx *ectx = container_of(ctx, struct efivarfs_ctx, ctx);
|
||||
struct qstr qstr = { .name = name, .len = len };
|
||||
struct dentry *dentry = d_hash_and_lookup(ectx->sb->s_root, &qstr);
|
||||
struct inode *inode;
|
||||
struct efivar_entry *entry;
|
||||
int err;
|
||||
|
||||
if (IS_ERR_OR_NULL(dentry))
|
||||
return true;
|
||||
|
||||
inode = d_inode(dentry);
|
||||
entry = inode->i_private;
|
||||
|
||||
err = efivar_entry_size(entry, &size);
|
||||
size += sizeof(__u32); /* attributes */
|
||||
if (err)
|
||||
size = 0;
|
||||
|
||||
inode_lock(inode);
|
||||
i_size_write(inode, size);
|
||||
inode_unlock(inode);
|
||||
|
||||
if (!size) {
|
||||
ectx->dentry = dentry;
|
||||
return false;
|
||||
}
|
||||
|
||||
dput(dentry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int efivarfs_check_missing(efi_char16_t *name16, efi_guid_t vendor,
|
||||
unsigned long name_size, void *data)
|
||||
{
|
||||
char *name;
|
||||
struct super_block *sb = data;
|
||||
struct dentry *dentry;
|
||||
struct qstr qstr;
|
||||
int err;
|
||||
|
||||
if (guid_equal(&vendor, &LINUX_EFI_RANDOM_SEED_TABLE_GUID))
|
||||
return 0;
|
||||
|
||||
name = efivar_get_utf8name(name16, &vendor);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
qstr.name = name;
|
||||
qstr.len = strlen(name);
|
||||
dentry = d_hash_and_lookup(sb->s_root, &qstr);
|
||||
if (IS_ERR(dentry)) {
|
||||
err = PTR_ERR(dentry);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!dentry) {
|
||||
/* found missing entry */
|
||||
pr_info("efivarfs: creating variable %s\n", name);
|
||||
return efivarfs_create_dentry(sb, name16, name_size, &vendor, name);
|
||||
}
|
||||
|
||||
dput(dentry);
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
kfree(name);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int efivarfs_pm_notify(struct notifier_block *nb, unsigned long action,
|
||||
void *ptr)
|
||||
{
|
||||
struct efivarfs_fs_info *sfi = container_of(nb, struct efivarfs_fs_info,
|
||||
pm_nb);
|
||||
struct path path = { .mnt = NULL, .dentry = sfi->sb->s_root, };
|
||||
struct efivarfs_ctx ectx = {
|
||||
.ctx = {
|
||||
.actor = efivarfs_actor,
|
||||
},
|
||||
.sb = sfi->sb,
|
||||
};
|
||||
struct file *file;
|
||||
static bool rescan_done = true;
|
||||
|
||||
if (action == PM_HIBERNATION_PREPARE) {
|
||||
rescan_done = false;
|
||||
return NOTIFY_OK;
|
||||
} else if (action != PM_POST_HIBERNATION) {
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
if (rescan_done)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
pr_info("efivarfs: resyncing variable state\n");
|
||||
|
||||
/* O_NOATIME is required to prevent oops on NULL mnt */
|
||||
file = kernel_file_open(&path, O_RDONLY | O_DIRECTORY | O_NOATIME,
|
||||
current_cred());
|
||||
if (IS_ERR(file))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
rescan_done = true;
|
||||
|
||||
/*
|
||||
* First loop over the directory and verify each entry exists,
|
||||
* removing it if it doesn't
|
||||
*/
|
||||
file->f_pos = 2; /* skip . and .. */
|
||||
do {
|
||||
ectx.dentry = NULL;
|
||||
iterate_dir(file, &ectx.ctx);
|
||||
if (ectx.dentry) {
|
||||
pr_info("efivarfs: removing variable %pd\n",
|
||||
ectx.dentry);
|
||||
simple_recursive_removal(ectx.dentry, NULL);
|
||||
dput(ectx.dentry);
|
||||
}
|
||||
} while (ectx.dentry);
|
||||
fput(file);
|
||||
|
||||
/*
|
||||
* then loop over variables, creating them if there's no matching
|
||||
* dentry
|
||||
*/
|
||||
efivar_init(efivarfs_check_missing, sfi->sb, false);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int efivarfs_init_fs_context(struct fs_context *fc)
|
||||
{
|
||||
struct efivarfs_fs_info *sfi;
|
||||
@ -371,13 +534,16 @@ static int efivarfs_init_fs_context(struct fs_context *fc)
|
||||
if (!sfi)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&sfi->efivarfs_list);
|
||||
|
||||
sfi->mount_opts.uid = GLOBAL_ROOT_UID;
|
||||
sfi->mount_opts.gid = GLOBAL_ROOT_GID;
|
||||
|
||||
fc->s_fs_info = sfi;
|
||||
fc->ops = &efivarfs_context_ops;
|
||||
|
||||
sfi->pm_nb.notifier_call = efivarfs_pm_notify;
|
||||
sfi->pm_nb.priority = 0;
|
||||
register_pm_notifier(&sfi->pm_nb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -387,9 +553,8 @@ static void efivarfs_kill_sb(struct super_block *sb)
|
||||
|
||||
blocking_notifier_chain_unregister(&efivar_ops_nh, &sfi->nb);
|
||||
kill_litter_super(sb);
|
||||
unregister_pm_notifier(&sfi->pm_nb);
|
||||
|
||||
/* Remove all entries and destroy */
|
||||
efivar_entry_iter(efivarfs_destroy, &sfi->efivarfs_list, NULL);
|
||||
kfree(sfi);
|
||||
}
|
||||
|
||||
|
@ -225,6 +225,31 @@ variable_matches(const char *var_name, size_t len, const char *match_name,
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
efivar_get_utf8name(const efi_char16_t *name16, efi_guid_t *vendor)
|
||||
{
|
||||
int len = ucs2_utf8size(name16);
|
||||
char *name;
|
||||
|
||||
/* name, plus '-', plus GUID, plus NUL*/
|
||||
name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL);
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
ucs2_as_utf8(name, name16, len);
|
||||
|
||||
name[len] = '-';
|
||||
|
||||
efi_guid_to_str(vendor, name + len + 1);
|
||||
|
||||
name[len + EFI_VARIABLE_GUID_LEN+1] = '\0';
|
||||
|
||||
/* replace invalid slashes like kobject_set_name_vargs does for /sys/firmware/efi/vars. */
|
||||
strreplace(name, '/', '!');
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
bool
|
||||
efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
|
||||
unsigned long data_size)
|
||||
@ -288,28 +313,6 @@ efivar_variable_is_removable(efi_guid_t vendor, const char *var_name,
|
||||
return found;
|
||||
}
|
||||
|
||||
static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct efivar_entry *entry, *n;
|
||||
unsigned long strsize1, strsize2;
|
||||
bool found = false;
|
||||
|
||||
strsize1 = ucs2_strsize(variable_name, EFI_VAR_NAME_LEN);
|
||||
list_for_each_entry_safe(entry, n, head, list) {
|
||||
strsize2 = ucs2_strsize(entry->var.VariableName, EFI_VAR_NAME_LEN);
|
||||
if (strsize1 == strsize2 &&
|
||||
!memcmp(variable_name, &(entry->var.VariableName),
|
||||
strsize2) &&
|
||||
!efi_guidcmp(entry->var.VendorGuid,
|
||||
*vendor)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the size of variable_name, in bytes, including the
|
||||
* terminating NULL character, or variable_name_size if no NULL
|
||||
@ -361,16 +364,15 @@ static void dup_variable_bug(efi_char16_t *str16, efi_guid_t *vendor_guid,
|
||||
* efivar_init - build the initial list of EFI variables
|
||||
* @func: callback function to invoke for every variable
|
||||
* @data: function-specific data to pass to @func
|
||||
* @head: initialised head of variable list
|
||||
* @duplicate_check: fail if a duplicate variable is found
|
||||
*
|
||||
* Get every EFI variable from the firmware and invoke @func. @func
|
||||
* should call efivar_entry_add() to build the list of variables.
|
||||
* should populate the initial dentry and inode tree.
|
||||
*
|
||||
* Returns 0 on success, or a kernel error code on failure.
|
||||
*/
|
||||
int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *,
|
||||
struct list_head *),
|
||||
void *data, struct list_head *head)
|
||||
int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),
|
||||
void *data, bool duplicate_check)
|
||||
{
|
||||
unsigned long variable_name_size = 512;
|
||||
efi_char16_t *variable_name;
|
||||
@ -414,14 +416,15 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *,
|
||||
* we'll ever see a different variable name,
|
||||
* and may end up looping here forever.
|
||||
*/
|
||||
if (variable_is_present(variable_name, &vendor_guid,
|
||||
head)) {
|
||||
if (duplicate_check &&
|
||||
efivarfs_variable_is_present(variable_name,
|
||||
&vendor_guid, data)) {
|
||||
dup_variable_bug(variable_name, &vendor_guid,
|
||||
variable_name_size);
|
||||
status = EFI_NOT_FOUND;
|
||||
} else {
|
||||
err = func(variable_name, vendor_guid,
|
||||
variable_name_size, data, head);
|
||||
variable_name_size, data);
|
||||
if (err)
|
||||
status = EFI_NOT_FOUND;
|
||||
}
|
||||
@ -453,70 +456,12 @@ free:
|
||||
}
|
||||
|
||||
/**
|
||||
* efivar_entry_add - add entry to variable list
|
||||
* @entry: entry to add to list
|
||||
* @head: list head
|
||||
*
|
||||
* Returns 0 on success, or a kernel error code on failure.
|
||||
*/
|
||||
int efivar_entry_add(struct efivar_entry *entry, struct list_head *head)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = efivar_lock();
|
||||
if (err)
|
||||
return err;
|
||||
list_add(&entry->list, head);
|
||||
efivar_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* __efivar_entry_add - add entry to variable list
|
||||
* @entry: entry to add to list
|
||||
* @head: list head
|
||||
*/
|
||||
void __efivar_entry_add(struct efivar_entry *entry, struct list_head *head)
|
||||
{
|
||||
list_add(&entry->list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* efivar_entry_remove - remove entry from variable list
|
||||
* @entry: entry to remove from list
|
||||
*
|
||||
* Returns 0 on success, or a kernel error code on failure.
|
||||
*/
|
||||
void efivar_entry_remove(struct efivar_entry *entry)
|
||||
{
|
||||
list_del(&entry->list);
|
||||
}
|
||||
|
||||
/*
|
||||
* efivar_entry_list_del_unlock - remove entry from variable list
|
||||
* @entry: entry to remove
|
||||
*
|
||||
* Remove @entry from the variable list and release the list lock.
|
||||
*
|
||||
* NOTE: slightly weird locking semantics here - we expect to be
|
||||
* called with the efivars lock already held, and we release it before
|
||||
* returning. This is because this function is usually called after
|
||||
* set_variable() while the lock is still held.
|
||||
*/
|
||||
static void efivar_entry_list_del_unlock(struct efivar_entry *entry)
|
||||
{
|
||||
list_del(&entry->list);
|
||||
efivar_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* efivar_entry_delete - delete variable and remove entry from list
|
||||
* efivar_entry_delete - delete variable
|
||||
* @entry: entry containing variable to delete
|
||||
*
|
||||
* Delete the variable from the firmware and remove @entry from the
|
||||
* variable list. It is the caller's responsibility to free @entry
|
||||
* once we return.
|
||||
* Delete the variable from the firmware. It is the caller's
|
||||
* responsibility to free @entry (by deleting the dentry/inode) once
|
||||
* we return.
|
||||
*
|
||||
* Returns 0 on success, -EINTR if we can't grab the semaphore,
|
||||
* converted EFI status code if set_variable() fails.
|
||||
@ -533,12 +478,10 @@ int efivar_entry_delete(struct efivar_entry *entry)
|
||||
status = efivar_set_variable_locked(entry->var.VariableName,
|
||||
&entry->var.VendorGuid,
|
||||
0, 0, NULL, false);
|
||||
if (!(status == EFI_SUCCESS || status == EFI_NOT_FOUND)) {
|
||||
efivar_unlock();
|
||||
efivar_unlock();
|
||||
if (!(status == EFI_SUCCESS || status == EFI_NOT_FOUND))
|
||||
return efi_status_to_err(status);
|
||||
}
|
||||
|
||||
efivar_entry_list_del_unlock(entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -632,7 +575,7 @@ int efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
|
||||
* get_variable() fail.
|
||||
*
|
||||
* If the EFI variable does not exist when calling set_variable()
|
||||
* (EFI_NOT_FOUND), @entry is removed from the variable list.
|
||||
* (EFI_NOT_FOUND).
|
||||
*/
|
||||
int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
|
||||
unsigned long *size, void *data, bool *set)
|
||||
@ -648,9 +591,8 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* The lock here protects the get_variable call, the conditional
|
||||
* set_variable call, and removal of the variable from the efivars
|
||||
* list (in the case of an authenticated delete).
|
||||
* The lock here protects the get_variable call and the
|
||||
* conditional set_variable call
|
||||
*/
|
||||
err = efivar_lock();
|
||||
if (err)
|
||||
@ -676,10 +618,7 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
|
||||
&entry->var.VendorGuid,
|
||||
NULL, size, NULL);
|
||||
|
||||
if (status == EFI_NOT_FOUND)
|
||||
efivar_entry_list_del_unlock(entry);
|
||||
else
|
||||
efivar_unlock();
|
||||
efivar_unlock();
|
||||
|
||||
if (status && status != EFI_BUFFER_TOO_SMALL)
|
||||
return efi_status_to_err(status);
|
||||
@ -691,37 +630,3 @@ out:
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* efivar_entry_iter - iterate over variable list
|
||||
* @func: callback function
|
||||
* @head: head of variable list
|
||||
* @data: function-specific data to pass to callback
|
||||
*
|
||||
* Iterate over the list of EFI variables and call @func with every
|
||||
* entry on the list. It is safe for @func to remove entries in the
|
||||
* list via efivar_entry_delete() while iterating.
|
||||
*
|
||||
* Some notes for the callback function:
|
||||
* - a non-zero return value indicates an error and terminates the loop
|
||||
* - @func is called from atomic context
|
||||
*/
|
||||
int efivar_entry_iter(int (*func)(struct efivar_entry *, void *),
|
||||
struct list_head *head, void *data)
|
||||
{
|
||||
struct efivar_entry *entry, *n;
|
||||
int err = 0;
|
||||
|
||||
err = efivar_lock();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
list_for_each_entry_safe(entry, n, head, list) {
|
||||
err = func(entry, data);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
efivar_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -363,7 +363,6 @@ void efi_native_runtime_setup(void);
|
||||
#define ACPI_20_TABLE_GUID EFI_GUID(0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81)
|
||||
#define SMBIOS_TABLE_GUID EFI_GUID(0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
|
||||
#define SMBIOS3_TABLE_GUID EFI_GUID(0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94)
|
||||
#define UGA_IO_PROTOCOL_GUID EFI_GUID(0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0x0b, 0x07, 0xa2)
|
||||
#define EFI_GLOBAL_VARIABLE_GUID EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c)
|
||||
#define UV_SYSTEM_TABLE_GUID EFI_GUID(0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93)
|
||||
#define LINUX_EFI_CRASH_GUID EFI_GUID(0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0)
|
||||
@ -373,7 +372,6 @@ void efi_native_runtime_setup(void);
|
||||
#define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID EFI_GUID(0x8b843e20, 0x8132, 0x4852, 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c)
|
||||
#define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID EFI_GUID(0x05c99a21, 0xc70f, 0x4ad2, 0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e)
|
||||
#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID EFI_GUID(0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a)
|
||||
#define EFI_UGA_PROTOCOL_GUID EFI_GUID(0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39)
|
||||
#define EFI_PCI_IO_PROTOCOL_GUID EFI_GUID(0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x02, 0x9a)
|
||||
#define EFI_FILE_INFO_ID EFI_GUID(0x09576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
|
||||
#define EFI_SYSTEM_RESOURCE_TABLE_GUID EFI_GUID(0xb122a263, 0x3661, 0x4f68, 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80)
|
||||
@ -1286,8 +1284,6 @@ struct linux_efi_memreserve {
|
||||
|
||||
void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size);
|
||||
|
||||
char *efi_systab_show_arch(char *str);
|
||||
|
||||
/*
|
||||
* The LINUX_EFI_MOK_VARIABLE_TABLE_GUID config table can be provided
|
||||
* to the kernel by an EFI boot loader. The table contains a packed
|
||||
|
Loading…
x
Reference in New Issue
Block a user