summaryrefslogtreecommitdiff
path: root/drivers/firmware/efi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/efi')
-rw-r--r--drivers/firmware/efi/efi-pstore.c8
-rw-r--r--drivers/firmware/efi/libstub/Makefile2
-rw-r--r--drivers/firmware/efi/libstub/arm64-stub.c13
-rw-r--r--drivers/firmware/efi/libstub/arm64.c3
-rw-r--r--drivers/firmware/efi/libstub/efistub.h9
-rw-r--r--drivers/firmware/efi/libstub/kaslr.c20
-rw-r--r--drivers/firmware/efi/libstub/loongarch.c2
-rw-r--r--drivers/firmware/efi/libstub/relocate.c2
-rw-r--r--drivers/firmware/efi/libstub/smbios.c43
-rw-r--r--drivers/firmware/efi/libstub/unaccepted_memory.c2
-rw-r--r--drivers/firmware/efi/libstub/x86-stub.c83
-rw-r--r--drivers/firmware/efi/libstub/zboot.lds1
-rw-r--r--drivers/firmware/efi/memattr.c2
-rw-r--r--drivers/firmware/efi/memmap.c9
-rw-r--r--drivers/firmware/efi/runtime-wrappers.c13
15 files changed, 132 insertions, 80 deletions
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index 5b9dc26e6bcb..552c78f5f059 100644
--- a/drivers/firmware/efi/efi-pstore.c
+++ b/drivers/firmware/efi/efi-pstore.c
@@ -136,7 +136,7 @@ static int efi_pstore_read_func(struct pstore_record *record,
&size, record->buf);
if (status != EFI_SUCCESS) {
kfree(record->buf);
- return -EIO;
+ return efi_status_to_err(status);
}
/*
@@ -189,7 +189,7 @@ static ssize_t efi_pstore_read(struct pstore_record *record)
return 0;
if (status != EFI_SUCCESS)
- return -EIO;
+ return efi_status_to_err(status);
/* skip variables that don't concern us */
if (efi_guidcmp(guid, LINUX_EFI_CRASH_GUID))
@@ -227,7 +227,7 @@ static int efi_pstore_write(struct pstore_record *record)
record->size, record->psi->buf,
true);
efivar_unlock();
- return status == EFI_SUCCESS ? 0 : -EIO;
+ return efi_status_to_err(status);
};
static int efi_pstore_erase(struct pstore_record *record)
@@ -238,7 +238,7 @@ static int efi_pstore_erase(struct pstore_record *record)
PSTORE_EFI_ATTRIBUTES, 0, NULL);
if (status != EFI_SUCCESS && status != EFI_NOT_FOUND)
- return -EIO;
+ return efi_status_to_err(status);
return 0;
}
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 06f0428a723c..1f32d6cf98d6 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -76,7 +76,7 @@ lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \
lib-$(CONFIG_ARM) += arm32-stub.o
lib-$(CONFIG_ARM64) += kaslr.o arm64.o arm64-stub.o smbios.o
-lib-$(CONFIG_X86) += x86-stub.o
+lib-$(CONFIG_X86) += x86-stub.o smbios.o
lib-$(CONFIG_X86_64) += x86-5lvl.o
lib-$(CONFIG_RISCV) += kaslr.o riscv.o riscv-stub.o
lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index 452b7ccd330e..2c3869356147 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -21,7 +21,6 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
efi_loaded_image_t *image,
efi_handle_t image_handle)
{
- efi_status_t status;
unsigned long kernel_size, kernel_codesize, kernel_memsize;
if (image->image_base != _text) {
@@ -39,15 +38,9 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
*reserve_size = kernel_memsize;
*image_addr = (unsigned long)_text;
- status = efi_kaslr_relocate_kernel(image_addr,
- reserve_addr, reserve_size,
- kernel_size, kernel_codesize,
- kernel_memsize,
- efi_kaslr_get_phys_seed(image_handle));
- if (status != EFI_SUCCESS)
- return status;
-
- return EFI_SUCCESS;
+ return efi_kaslr_relocate_kernel(image_addr, reserve_addr, reserve_size,
+ kernel_size, kernel_codesize, kernel_memsize,
+ efi_kaslr_get_phys_seed(image_handle));
}
asmlinkage void primary_entry(void);
diff --git a/drivers/firmware/efi/libstub/arm64.c b/drivers/firmware/efi/libstub/arm64.c
index 446e35eaf3d9..e57cd3de0a00 100644
--- a/drivers/firmware/efi/libstub/arm64.c
+++ b/drivers/firmware/efi/libstub/arm64.c
@@ -39,8 +39,7 @@ static bool system_needs_vamap(void)
static char const emag[] = "eMAG";
default:
- version = efi_get_smbios_string(&record->header, 4,
- processor_version);
+ version = efi_get_smbios_string(record, processor_version);
if (!version || (strncmp(version, altra, sizeof(altra) - 1) &&
strncmp(version, emag, sizeof(emag) - 1)))
break;
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 27abb4ce0291..d33ccbc4a2c6 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -1204,14 +1204,13 @@ struct efi_smbios_type4_record {
u16 thread_enabled;
};
-#define efi_get_smbios_string(__record, __type, __name) ({ \
- int off = offsetof(struct efi_smbios_type ## __type ## _record, \
- __name); \
- __efi_get_smbios_string((__record), __type, off); \
+#define efi_get_smbios_string(__record, __field) ({ \
+ __typeof__(__record) __rec = __record; \
+ __efi_get_smbios_string(&__rec->header, &__rec->__field); \
})
const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
- u8 type, int offset);
+ const u8 *offset);
void efi_remap_image(unsigned long image_base, unsigned alloc_size,
unsigned long code_size);
diff --git a/drivers/firmware/efi/libstub/kaslr.c b/drivers/firmware/efi/libstub/kaslr.c
index 1a9808012abd..6318c40bda38 100644
--- a/drivers/firmware/efi/libstub/kaslr.c
+++ b/drivers/firmware/efi/libstub/kaslr.c
@@ -18,8 +18,6 @@
*/
u32 efi_kaslr_get_phys_seed(efi_handle_t image_handle)
{
- efi_status_t status;
- u32 phys_seed;
efi_guid_t li_fixed_proto = LINUX_EFI_LOADED_IMAGE_FIXED_GUID;
void *p;
@@ -32,18 +30,20 @@ u32 efi_kaslr_get_phys_seed(efi_handle_t image_handle)
&li_fixed_proto, &p) == EFI_SUCCESS) {
efi_info("Image placement fixed by loader\n");
} else {
+ efi_status_t status;
+ u32 phys_seed;
+
status = efi_get_random_bytes(sizeof(phys_seed),
(u8 *)&phys_seed);
- if (status == EFI_SUCCESS) {
+ if (status == EFI_SUCCESS)
return phys_seed;
- } else if (status == EFI_NOT_FOUND) {
+
+ if (status == EFI_NOT_FOUND)
efi_info("EFI_RNG_PROTOCOL unavailable\n");
- efi_nokaslr = true;
- } else if (status != EFI_SUCCESS) {
- efi_err("efi_get_random_bytes() failed (0x%lx)\n",
- status);
- efi_nokaslr = true;
- }
+ else
+ efi_err("efi_get_random_bytes() failed (0x%lx)\n", status);
+
+ efi_nokaslr = true;
}
return 0;
diff --git a/drivers/firmware/efi/libstub/loongarch.c b/drivers/firmware/efi/libstub/loongarch.c
index 684c9354637c..d0ef93551c44 100644
--- a/drivers/firmware/efi/libstub/loongarch.c
+++ b/drivers/firmware/efi/libstub/loongarch.c
@@ -41,7 +41,7 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
unsigned long __weak kernel_entry_address(unsigned long kernel_addr,
efi_loaded_image_t *image)
{
- return *(unsigned long *)(kernel_addr + 8) - VMLINUX_LOAD_ADDRESS + kernel_addr;
+ return *(unsigned long *)(kernel_addr + 8) - PHYSADDR(VMLINUX_LOAD_ADDRESS) + kernel_addr;
}
efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
diff --git a/drivers/firmware/efi/libstub/relocate.c b/drivers/firmware/efi/libstub/relocate.c
index bf6fbd5d22a1..d694bcfa1074 100644
--- a/drivers/firmware/efi/libstub/relocate.c
+++ b/drivers/firmware/efi/libstub/relocate.c
@@ -48,7 +48,7 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
unsigned long m = (unsigned long)map->map;
u64 start, end;
- desc = efi_early_memdesc_ptr(m, map->desc_size, i);
+ desc = efi_memdesc_ptr(m, map->desc_size, i);
if (desc->type != EFI_CONVENTIONAL_MEMORY)
continue;
diff --git a/drivers/firmware/efi/libstub/smbios.c b/drivers/firmware/efi/libstub/smbios.c
index c217de2cc8d5..f31410d7e7e1 100644
--- a/drivers/firmware/efi/libstub/smbios.c
+++ b/drivers/firmware/efi/libstub/smbios.c
@@ -6,20 +6,31 @@
#include "efistub.h"
-typedef struct efi_smbios_protocol efi_smbios_protocol_t;
-
-struct efi_smbios_protocol {
- efi_status_t (__efiapi *add)(efi_smbios_protocol_t *, efi_handle_t,
- u16 *, struct efi_smbios_record *);
- efi_status_t (__efiapi *update_string)(efi_smbios_protocol_t *, u16 *,
- unsigned long *, u8 *);
- efi_status_t (__efiapi *remove)(efi_smbios_protocol_t *, u16);
- efi_status_t (__efiapi *get_next)(efi_smbios_protocol_t *, u16 *, u8 *,
- struct efi_smbios_record **,
- efi_handle_t *);
-
- u8 major_version;
- u8 minor_version;
+typedef union efi_smbios_protocol efi_smbios_protocol_t;
+
+union efi_smbios_protocol {
+ struct {
+ efi_status_t (__efiapi *add)(efi_smbios_protocol_t *, efi_handle_t,
+ u16 *, struct efi_smbios_record *);
+ efi_status_t (__efiapi *update_string)(efi_smbios_protocol_t *, u16 *,
+ unsigned long *, u8 *);
+ efi_status_t (__efiapi *remove)(efi_smbios_protocol_t *, u16);
+ efi_status_t (__efiapi *get_next)(efi_smbios_protocol_t *, u16 *, u8 *,
+ struct efi_smbios_record **,
+ efi_handle_t *);
+
+ u8 major_version;
+ u8 minor_version;
+ };
+ struct {
+ u32 add;
+ u32 update_string;
+ u32 remove;
+ u32 get_next;
+
+ u8 major_version;
+ u8 minor_version;
+ } mixed_mode;
};
const struct efi_smbios_record *efi_get_smbios_record(u8 type)
@@ -38,7 +49,7 @@ const struct efi_smbios_record *efi_get_smbios_record(u8 type)
}
const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
- u8 type, int offset)
+ const u8 *offset)
{
const u8 *strtable;
@@ -46,7 +57,7 @@ const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
return NULL;
strtable = (u8 *)record + record->length;
- for (int i = 1; i < ((u8 *)record)[offset]; i++) {
+ for (int i = 1; i < *offset; i++) {
int len = strlen(strtable);
if (!len)
diff --git a/drivers/firmware/efi/libstub/unaccepted_memory.c b/drivers/firmware/efi/libstub/unaccepted_memory.c
index 9a655f30ba47..c295ea3a6efc 100644
--- a/drivers/firmware/efi/libstub/unaccepted_memory.c
+++ b/drivers/firmware/efi/libstub/unaccepted_memory.c
@@ -29,7 +29,7 @@ efi_status_t allocate_unaccepted_bitmap(__u32 nr_desc,
efi_memory_desc_t *d;
unsigned long m = (unsigned long)map->map;
- d = efi_early_memdesc_ptr(m, map->desc_size, i);
+ d = efi_memdesc_ptr(m, map->desc_size, i);
if (d->type != EFI_UNACCEPTED_MEMORY)
continue;
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index 1983fd3bf392..078055b054e3 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -225,6 +225,68 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
}
}
+static bool apple_match_product_name(void)
+{
+ static const char type1_product_matches[][15] = {
+ "MacBookPro11,3",
+ "MacBookPro11,5",
+ "MacBookPro13,3",
+ "MacBookPro14,3",
+ "MacBookPro15,1",
+ "MacBookPro15,3",
+ "MacBookPro16,1",
+ "MacBookPro16,4",
+ };
+ const struct efi_smbios_type1_record *record;
+ const u8 *product;
+
+ record = (struct efi_smbios_type1_record *)efi_get_smbios_record(1);
+ if (!record)
+ return false;
+
+ product = efi_get_smbios_string(record, product_name);
+ if (!product)
+ return false;
+
+ for (int i = 0; i < ARRAY_SIZE(type1_product_matches); i++) {
+ if (!strcmp(product, type1_product_matches[i]))
+ return true;
+ }
+
+ return false;
+}
+
+static void apple_set_os(void)
+{
+ struct {
+ unsigned long version;
+ efi_status_t (__efiapi *set_os_version)(const char *);
+ efi_status_t (__efiapi *set_os_vendor)(const char *);
+ } *set_os;
+ efi_status_t status;
+
+ if (!efi_is_64bit() || !apple_match_product_name())
+ return;
+
+ status = efi_bs_call(locate_protocol, &APPLE_SET_OS_PROTOCOL_GUID, NULL,
+ (void **)&set_os);
+ if (status != EFI_SUCCESS)
+ return;
+
+ if (set_os->version >= 2) {
+ status = set_os->set_os_vendor("Apple Inc.");
+ if (status != EFI_SUCCESS)
+ efi_err("Failed to set OS vendor via apple_set_os\n");
+ }
+
+ if (set_os->version > 0) {
+ /* The version being set doesn't seem to matter */
+ status = set_os->set_os_version("Mac OS X 10.9");
+ if (status != EFI_SUCCESS)
+ efi_err("Failed to set OS version via apple_set_os\n");
+ }
+}
+
efi_status_t efi_adjust_memory_range_protection(unsigned long start,
unsigned long size)
{
@@ -335,9 +397,12 @@ static const efi_char16_t apple[] = L"Apple";
static void setup_quirks(struct boot_params *boot_params)
{
- if (IS_ENABLED(CONFIG_APPLE_PROPERTIES) &&
- !memcmp(efistub_fw_vendor(), apple, sizeof(apple)))
- retrieve_apple_device_properties(boot_params);
+ if (!memcmp(efistub_fw_vendor(), apple, sizeof(apple))) {
+ if (IS_ENABLED(CONFIG_APPLE_PROPERTIES))
+ retrieve_apple_device_properties(boot_params);
+
+ apple_set_os();
+ }
}
/*
@@ -476,9 +541,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_status_t status;
char *cmdline_ptr;
- if (efi_is_native())
- memset(_bss, 0, _ebss - _bss);
-
efi_system_table = sys_table_arg;
/* Check if we were booted by the EFI firmware */
@@ -501,16 +563,13 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
/* Convert unicode cmdline to ascii */
cmdline_ptr = efi_convert_cmdline(image, &options_size);
if (!cmdline_ptr)
- goto fail;
+ efi_exit(handle, EFI_OUT_OF_RESOURCES);
efi_set_u64_split((unsigned long)cmdline_ptr, &hdr->cmd_line_ptr,
&boot_params.ext_cmd_line_ptr);
efi_stub_entry(handle, sys_table_arg, &boot_params);
/* not reached */
-
-fail:
- efi_exit(handle, status);
}
static void add_e820ext(struct boot_params *params,
@@ -555,7 +614,7 @@ setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_s
m |= (u64)efi->efi_memmap_hi << 32;
#endif
- d = efi_early_memdesc_ptr(m, efi->efi_memdesc_size, i);
+ d = efi_memdesc_ptr(m, efi->efi_memdesc_size, i);
switch (d->type) {
case EFI_RESERVED_TYPE:
case EFI_RUNTIME_SERVICES_CODE:
@@ -781,7 +840,7 @@ static const char *cmdline_memmap_override;
static efi_status_t parse_options(const char *cmdline)
{
static const char opts[][14] = {
- "mem=", "memmap=", "efi_fake_mem=", "hugepages="
+ "mem=", "memmap=", "hugepages="
};
for (int i = 0; i < ARRAY_SIZE(opts); i++) {
diff --git a/drivers/firmware/efi/libstub/zboot.lds b/drivers/firmware/efi/libstub/zboot.lds
index ac8c0ef85158..af2c82f7bd90 100644
--- a/drivers/firmware/efi/libstub/zboot.lds
+++ b/drivers/firmware/efi/libstub/zboot.lds
@@ -41,6 +41,7 @@ SECTIONS
}
/DISCARD/ : {
+ *(.discard .discard.*)
*(.modinfo .init.modinfo)
}
}
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
index ab85bf8e165a..164203429fa7 100644
--- a/drivers/firmware/efi/memattr.c
+++ b/drivers/firmware/efi/memattr.c
@@ -164,7 +164,7 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm,
bool valid;
char buf[64];
- valid = entry_is_valid((void *)tbl->entry + i * tbl->desc_size,
+ valid = entry_is_valid(efi_memdesc_ptr(tbl->entry, tbl->desc_size, i),
&md);
size = md.num_pages << EFI_PAGE_SHIFT;
if (efi_enabled(EFI_DBG) || !valid)
diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c
index 3365944f7965..34109fd86c55 100644
--- a/drivers/firmware/efi/memmap.c
+++ b/drivers/firmware/efi/memmap.c
@@ -15,10 +15,6 @@
#include <asm/early_ioremap.h>
#include <asm/efi.h>
-#ifndef __efi_memmap_free
-#define __efi_memmap_free(phys, size, flags) do { } while (0)
-#endif
-
/**
* __efi_memmap_init - Common code for mapping the EFI memory map
* @data: EFI memory map data
@@ -51,11 +47,6 @@ int __init __efi_memmap_init(struct efi_memory_map_data *data)
return -ENOMEM;
}
- if (efi.memmap.flags & (EFI_MEMMAP_MEMBLOCK | EFI_MEMMAP_SLAB))
- __efi_memmap_free(efi.memmap.phys_map,
- efi.memmap.desc_size * efi.memmap.nr_map,
- efi.memmap.flags);
-
map.phys_map = data->phys_map;
map.nr_map = data->size / data->desc_size;
map.map_end = map.map + data->size;
diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
index 5d56bc40a79d..708b777857d3 100644
--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -213,7 +213,7 @@ extern struct semaphore __efi_uv_runtime_lock __alias(efi_runtime_lock);
* Calls the appropriate efi_runtime_service() with the appropriate
* arguments.
*/
-static void efi_call_rts(struct work_struct *work)
+static void __nocfi efi_call_rts(struct work_struct *work)
{
const union efi_rts_args *args = efi_rts_work.args;
efi_status_t status = EFI_NOT_FOUND;
@@ -435,7 +435,7 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
return status;
}
-static efi_status_t
+static efi_status_t __nocfi
virt_efi_set_variable_nb(efi_char16_t *name, efi_guid_t *vendor, u32 attr,
unsigned long data_size, void *data)
{
@@ -469,7 +469,7 @@ static efi_status_t virt_efi_query_variable_info(u32 attr,
return status;
}
-static efi_status_t
+static efi_status_t __nocfi
virt_efi_query_variable_info_nb(u32 attr, u64 *storage_space,
u64 *remaining_space, u64 *max_variable_size)
{
@@ -499,10 +499,9 @@ static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
return status;
}
-static void virt_efi_reset_system(int reset_type,
- efi_status_t status,
- unsigned long data_size,
- efi_char16_t *data)
+static void __nocfi
+virt_efi_reset_system(int reset_type, efi_status_t status,
+ unsigned long data_size, efi_char16_t *data)
{
if (down_trylock(&efi_runtime_lock)) {
pr_warn("failed to invoke the reset_system() runtime service:\n"