mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-12 08:09:56 +00:00
Merge branch 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI fixes from Ingo Molnar: "Three fixes to EFI mixed boot mode, mostly related to x86-64 vmap stacks activated years ago, bug-fixed recently for EFI, which had knock-on effects of various 1:1 mapping assumptions in mixed mode. There's also a READ_ONCE() fix for reading an mmap-ed EFI firmware data field only once, out of caution" * 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: efi: READ_ONCE rng seed size before munmap efi/x86: Handle by-ref arguments covering multiple pages in mixed mode efi/x86: Remove support for EFI time and counter services in mixed mode efi/x86: Align GUIDs to their size in the mixed mode runtime wrapper
This commit is contained in:
commit
e130a920f6
@ -180,7 +180,7 @@ void efi_sync_low_kernel_mappings(void)
|
|||||||
static inline phys_addr_t
|
static inline phys_addr_t
|
||||||
virt_to_phys_or_null_size(void *va, unsigned long size)
|
virt_to_phys_or_null_size(void *va, unsigned long size)
|
||||||
{
|
{
|
||||||
bool bad_size;
|
phys_addr_t pa;
|
||||||
|
|
||||||
if (!va)
|
if (!va)
|
||||||
return 0;
|
return 0;
|
||||||
@ -188,16 +188,13 @@ virt_to_phys_or_null_size(void *va, unsigned long size)
|
|||||||
if (virt_addr_valid(va))
|
if (virt_addr_valid(va))
|
||||||
return virt_to_phys(va);
|
return virt_to_phys(va);
|
||||||
|
|
||||||
/*
|
pa = slow_virt_to_phys(va);
|
||||||
* A fully aligned variable on the stack is guaranteed not to
|
|
||||||
* cross a page bounary. Try to catch strings on the stack by
|
|
||||||
* checking that 'size' is a power of two.
|
|
||||||
*/
|
|
||||||
bad_size = size > PAGE_SIZE || !is_power_of_2(size);
|
|
||||||
|
|
||||||
WARN_ON(!IS_ALIGNED((unsigned long)va, size) || bad_size);
|
/* check if the object crosses a page boundary */
|
||||||
|
if (WARN_ON((pa ^ (pa + size - 1)) & PAGE_MASK))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return slow_virt_to_phys(va);
|
return pa;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define virt_to_phys_or_null(addr) \
|
#define virt_to_phys_or_null(addr) \
|
||||||
@ -568,85 +565,25 @@ efi_thunk_set_virtual_address_map(unsigned long memory_map_size,
|
|||||||
|
|
||||||
static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc)
|
static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc)
|
||||||
{
|
{
|
||||||
efi_status_t status;
|
return EFI_UNSUPPORTED;
|
||||||
u32 phys_tm, phys_tc;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock(&rtc_lock);
|
|
||||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
|
||||||
|
|
||||||
phys_tm = virt_to_phys_or_null(tm);
|
|
||||||
phys_tc = virt_to_phys_or_null(tc);
|
|
||||||
|
|
||||||
status = efi_thunk(get_time, phys_tm, phys_tc);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
|
||||||
spin_unlock(&rtc_lock);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static efi_status_t efi_thunk_set_time(efi_time_t *tm)
|
static efi_status_t efi_thunk_set_time(efi_time_t *tm)
|
||||||
{
|
{
|
||||||
efi_status_t status;
|
return EFI_UNSUPPORTED;
|
||||||
u32 phys_tm;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock(&rtc_lock);
|
|
||||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
|
||||||
|
|
||||||
phys_tm = virt_to_phys_or_null(tm);
|
|
||||||
|
|
||||||
status = efi_thunk(set_time, phys_tm);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
|
||||||
spin_unlock(&rtc_lock);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static efi_status_t
|
static efi_status_t
|
||||||
efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
|
efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
|
||||||
efi_time_t *tm)
|
efi_time_t *tm)
|
||||||
{
|
{
|
||||||
efi_status_t status;
|
return EFI_UNSUPPORTED;
|
||||||
u32 phys_enabled, phys_pending, phys_tm;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock(&rtc_lock);
|
|
||||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
|
||||||
|
|
||||||
phys_enabled = virt_to_phys_or_null(enabled);
|
|
||||||
phys_pending = virt_to_phys_or_null(pending);
|
|
||||||
phys_tm = virt_to_phys_or_null(tm);
|
|
||||||
|
|
||||||
status = efi_thunk(get_wakeup_time, phys_enabled,
|
|
||||||
phys_pending, phys_tm);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
|
||||||
spin_unlock(&rtc_lock);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static efi_status_t
|
static efi_status_t
|
||||||
efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
|
efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
|
||||||
{
|
{
|
||||||
efi_status_t status;
|
return EFI_UNSUPPORTED;
|
||||||
u32 phys_tm;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock(&rtc_lock);
|
|
||||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
|
||||||
|
|
||||||
phys_tm = virt_to_phys_or_null(tm);
|
|
||||||
|
|
||||||
status = efi_thunk(set_wakeup_time, enabled, phys_tm);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
|
||||||
spin_unlock(&rtc_lock);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long efi_name_size(efi_char16_t *name)
|
static unsigned long efi_name_size(efi_char16_t *name)
|
||||||
@ -658,6 +595,8 @@ static efi_status_t
|
|||||||
efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
|
efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
|
||||||
u32 *attr, unsigned long *data_size, void *data)
|
u32 *attr, unsigned long *data_size, void *data)
|
||||||
{
|
{
|
||||||
|
u8 buf[24] __aligned(8);
|
||||||
|
efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
|
||||||
efi_status_t status;
|
efi_status_t status;
|
||||||
u32 phys_name, phys_vendor, phys_attr;
|
u32 phys_name, phys_vendor, phys_attr;
|
||||||
u32 phys_data_size, phys_data;
|
u32 phys_data_size, phys_data;
|
||||||
@ -665,14 +604,19 @@ efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
|
|||||||
|
|
||||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
spin_lock_irqsave(&efi_runtime_lock, flags);
|
||||||
|
|
||||||
|
*vnd = *vendor;
|
||||||
|
|
||||||
phys_data_size = virt_to_phys_or_null(data_size);
|
phys_data_size = virt_to_phys_or_null(data_size);
|
||||||
phys_vendor = virt_to_phys_or_null(vendor);
|
phys_vendor = virt_to_phys_or_null(vnd);
|
||||||
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
|
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
|
||||||
phys_attr = virt_to_phys_or_null(attr);
|
phys_attr = virt_to_phys_or_null(attr);
|
||||||
phys_data = virt_to_phys_or_null_size(data, *data_size);
|
phys_data = virt_to_phys_or_null_size(data, *data_size);
|
||||||
|
|
||||||
status = efi_thunk(get_variable, phys_name, phys_vendor,
|
if (!phys_name || (data && !phys_data))
|
||||||
phys_attr, phys_data_size, phys_data);
|
status = EFI_INVALID_PARAMETER;
|
||||||
|
else
|
||||||
|
status = efi_thunk(get_variable, phys_name, phys_vendor,
|
||||||
|
phys_attr, phys_data_size, phys_data);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||||
|
|
||||||
@ -683,19 +627,25 @@ static efi_status_t
|
|||||||
efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
|
efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
|
||||||
u32 attr, unsigned long data_size, void *data)
|
u32 attr, unsigned long data_size, void *data)
|
||||||
{
|
{
|
||||||
|
u8 buf[24] __aligned(8);
|
||||||
|
efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
|
||||||
u32 phys_name, phys_vendor, phys_data;
|
u32 phys_name, phys_vendor, phys_data;
|
||||||
efi_status_t status;
|
efi_status_t status;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
spin_lock_irqsave(&efi_runtime_lock, flags);
|
||||||
|
|
||||||
|
*vnd = *vendor;
|
||||||
|
|
||||||
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
|
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
|
||||||
phys_vendor = virt_to_phys_or_null(vendor);
|
phys_vendor = virt_to_phys_or_null(vnd);
|
||||||
phys_data = virt_to_phys_or_null_size(data, data_size);
|
phys_data = virt_to_phys_or_null_size(data, data_size);
|
||||||
|
|
||||||
/* If data_size is > sizeof(u32) we've got problems */
|
if (!phys_name || !phys_data)
|
||||||
status = efi_thunk(set_variable, phys_name, phys_vendor,
|
status = EFI_INVALID_PARAMETER;
|
||||||
attr, data_size, phys_data);
|
else
|
||||||
|
status = efi_thunk(set_variable, phys_name, phys_vendor,
|
||||||
|
attr, data_size, phys_data);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||||
|
|
||||||
@ -707,6 +657,8 @@ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
|
|||||||
u32 attr, unsigned long data_size,
|
u32 attr, unsigned long data_size,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
|
u8 buf[24] __aligned(8);
|
||||||
|
efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
|
||||||
u32 phys_name, phys_vendor, phys_data;
|
u32 phys_name, phys_vendor, phys_data;
|
||||||
efi_status_t status;
|
efi_status_t status;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -714,13 +666,17 @@ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
|
|||||||
if (!spin_trylock_irqsave(&efi_runtime_lock, flags))
|
if (!spin_trylock_irqsave(&efi_runtime_lock, flags))
|
||||||
return EFI_NOT_READY;
|
return EFI_NOT_READY;
|
||||||
|
|
||||||
|
*vnd = *vendor;
|
||||||
|
|
||||||
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
|
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
|
||||||
phys_vendor = virt_to_phys_or_null(vendor);
|
phys_vendor = virt_to_phys_or_null(vnd);
|
||||||
phys_data = virt_to_phys_or_null_size(data, data_size);
|
phys_data = virt_to_phys_or_null_size(data, data_size);
|
||||||
|
|
||||||
/* If data_size is > sizeof(u32) we've got problems */
|
if (!phys_name || !phys_data)
|
||||||
status = efi_thunk(set_variable, phys_name, phys_vendor,
|
status = EFI_INVALID_PARAMETER;
|
||||||
attr, data_size, phys_data);
|
else
|
||||||
|
status = efi_thunk(set_variable, phys_name, phys_vendor,
|
||||||
|
attr, data_size, phys_data);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||||
|
|
||||||
@ -732,39 +688,36 @@ efi_thunk_get_next_variable(unsigned long *name_size,
|
|||||||
efi_char16_t *name,
|
efi_char16_t *name,
|
||||||
efi_guid_t *vendor)
|
efi_guid_t *vendor)
|
||||||
{
|
{
|
||||||
|
u8 buf[24] __aligned(8);
|
||||||
|
efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
|
||||||
efi_status_t status;
|
efi_status_t status;
|
||||||
u32 phys_name_size, phys_name, phys_vendor;
|
u32 phys_name_size, phys_name, phys_vendor;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
spin_lock_irqsave(&efi_runtime_lock, flags);
|
||||||
|
|
||||||
|
*vnd = *vendor;
|
||||||
|
|
||||||
phys_name_size = virt_to_phys_or_null(name_size);
|
phys_name_size = virt_to_phys_or_null(name_size);
|
||||||
phys_vendor = virt_to_phys_or_null(vendor);
|
phys_vendor = virt_to_phys_or_null(vnd);
|
||||||
phys_name = virt_to_phys_or_null_size(name, *name_size);
|
phys_name = virt_to_phys_or_null_size(name, *name_size);
|
||||||
|
|
||||||
status = efi_thunk(get_next_variable, phys_name_size,
|
if (!phys_name)
|
||||||
phys_name, phys_vendor);
|
status = EFI_INVALID_PARAMETER;
|
||||||
|
else
|
||||||
|
status = efi_thunk(get_next_variable, phys_name_size,
|
||||||
|
phys_name, phys_vendor);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
||||||
|
|
||||||
|
*vendor = *vnd;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static efi_status_t
|
static efi_status_t
|
||||||
efi_thunk_get_next_high_mono_count(u32 *count)
|
efi_thunk_get_next_high_mono_count(u32 *count)
|
||||||
{
|
{
|
||||||
efi_status_t status;
|
return EFI_UNSUPPORTED;
|
||||||
u32 phys_count;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&efi_runtime_lock, flags);
|
|
||||||
|
|
||||||
phys_count = virt_to_phys_or_null(count);
|
|
||||||
status = efi_thunk(get_next_high_mono_count, phys_count);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&efi_runtime_lock, flags);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -552,7 +552,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
|
|||||||
|
|
||||||
seed = early_memremap(efi.rng_seed, sizeof(*seed));
|
seed = early_memremap(efi.rng_seed, sizeof(*seed));
|
||||||
if (seed != NULL) {
|
if (seed != NULL) {
|
||||||
size = seed->size;
|
size = READ_ONCE(seed->size);
|
||||||
early_memunmap(seed, sizeof(*seed));
|
early_memunmap(seed, sizeof(*seed));
|
||||||
} else {
|
} else {
|
||||||
pr_err("Could not map UEFI random seed!\n");
|
pr_err("Could not map UEFI random seed!\n");
|
||||||
@ -562,7 +562,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
|
|||||||
sizeof(*seed) + size);
|
sizeof(*seed) + size);
|
||||||
if (seed != NULL) {
|
if (seed != NULL) {
|
||||||
pr_notice("seeding entropy pool\n");
|
pr_notice("seeding entropy pool\n");
|
||||||
add_bootloader_randomness(seed->bits, seed->size);
|
add_bootloader_randomness(seed->bits, size);
|
||||||
early_memunmap(seed, sizeof(*seed) + size);
|
early_memunmap(seed, sizeof(*seed) + size);
|
||||||
} else {
|
} else {
|
||||||
pr_err("Could not map UEFI random seed!\n");
|
pr_err("Could not map UEFI random seed!\n");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user