|
@@ -56,13 +56,6 @@
|
|
|
|
|
|
#define EFI_DEBUG
|
|
|
|
|
|
-#define EFI_MIN_RESERVE 5120
|
|
|
-
|
|
|
-#define EFI_DUMMY_GUID \
|
|
|
- EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9)
|
|
|
-
|
|
|
-static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 };
|
|
|
-
|
|
|
struct efi_memory_map memmap;
|
|
|
|
|
|
static struct efi efi_phys __initdata;
|
|
@@ -95,15 +88,6 @@ static int __init setup_add_efi_memmap(char *arg)
|
|
|
}
|
|
|
early_param("add_efi_memmap", setup_add_efi_memmap);
|
|
|
|
|
|
-static bool efi_no_storage_paranoia;
|
|
|
-
|
|
|
-static int __init setup_storage_paranoia(char *arg)
|
|
|
-{
|
|
|
- efi_no_storage_paranoia = true;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-early_param("efi_no_storage_paranoia", setup_storage_paranoia);
|
|
|
-
|
|
|
static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
|
|
|
{
|
|
|
unsigned long flags;
|
|
@@ -392,37 +376,6 @@ static void __init print_efi_memmap(void)
|
|
|
#endif /* EFI_DEBUG */
|
|
|
}
|
|
|
|
|
|
-void __init efi_reserve_boot_services(void)
|
|
|
-{
|
|
|
- void *p;
|
|
|
-
|
|
|
- for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
|
|
- efi_memory_desc_t *md = p;
|
|
|
- u64 start = md->phys_addr;
|
|
|
- u64 size = md->num_pages << EFI_PAGE_SHIFT;
|
|
|
-
|
|
|
- if (md->type != EFI_BOOT_SERVICES_CODE &&
|
|
|
- md->type != EFI_BOOT_SERVICES_DATA)
|
|
|
- continue;
|
|
|
- /* Only reserve where possible:
|
|
|
- * - Not within any already allocated areas
|
|
|
- * - Not over any memory area (really needed, if above?)
|
|
|
- * - Not within any part of the kernel
|
|
|
- * - Not the bios reserved area
|
|
|
- */
|
|
|
- if ((start + size > __pa_symbol(_text)
|
|
|
- && start <= __pa_symbol(_end)) ||
|
|
|
- !e820_all_mapped(start, start+size, E820_RAM) ||
|
|
|
- memblock_is_region_reserved(start, size)) {
|
|
|
- /* Could not reserve, skip it */
|
|
|
- md->num_pages = 0;
|
|
|
- memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n",
|
|
|
- start, start+size-1);
|
|
|
- } else
|
|
|
- memblock_reserve(start, size);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
void __init efi_unmap_memmap(void)
|
|
|
{
|
|
|
clear_bit(EFI_MEMMAP, &efi.flags);
|
|
@@ -432,29 +385,6 @@ void __init efi_unmap_memmap(void)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void __init efi_free_boot_services(void)
|
|
|
-{
|
|
|
- void *p;
|
|
|
-
|
|
|
- for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
|
|
- efi_memory_desc_t *md = p;
|
|
|
- unsigned long long start = md->phys_addr;
|
|
|
- unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
|
|
|
-
|
|
|
- if (md->type != EFI_BOOT_SERVICES_CODE &&
|
|
|
- md->type != EFI_BOOT_SERVICES_DATA)
|
|
|
- continue;
|
|
|
-
|
|
|
- /* Could not reserve boot area */
|
|
|
- if (!size)
|
|
|
- continue;
|
|
|
-
|
|
|
- free_bootmem_late(start, size);
|
|
|
- }
|
|
|
-
|
|
|
- efi_unmap_memmap();
|
|
|
-}
|
|
|
-
|
|
|
static int __init efi_systab_init(void *phys)
|
|
|
{
|
|
|
if (efi_enabled(EFI_64BIT)) {
|
|
@@ -649,62 +579,6 @@ static int __init efi_memmap_init(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * A number of config table entries get remapped to virtual addresses
|
|
|
- * after entering EFI virtual mode. However, the kexec kernel requires
|
|
|
- * their physical addresses therefore we pass them via setup_data and
|
|
|
- * correct those entries to their respective physical addresses here.
|
|
|
- *
|
|
|
- * Currently only handles smbios which is necessary for some firmware
|
|
|
- * implementation.
|
|
|
- */
|
|
|
-static int __init efi_reuse_config(u64 tables, int nr_tables)
|
|
|
-{
|
|
|
- int i, sz, ret = 0;
|
|
|
- void *p, *tablep;
|
|
|
- struct efi_setup_data *data;
|
|
|
-
|
|
|
- if (!efi_setup)
|
|
|
- return 0;
|
|
|
-
|
|
|
- if (!efi_enabled(EFI_64BIT))
|
|
|
- return 0;
|
|
|
-
|
|
|
- data = early_memremap(efi_setup, sizeof(*data));
|
|
|
- if (!data) {
|
|
|
- ret = -ENOMEM;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- if (!data->smbios)
|
|
|
- goto out_memremap;
|
|
|
-
|
|
|
- sz = sizeof(efi_config_table_64_t);
|
|
|
-
|
|
|
- p = tablep = early_memremap(tables, nr_tables * sz);
|
|
|
- if (!p) {
|
|
|
- pr_err("Could not map Configuration table!\n");
|
|
|
- ret = -ENOMEM;
|
|
|
- goto out_memremap;
|
|
|
- }
|
|
|
-
|
|
|
- for (i = 0; i < efi.systab->nr_tables; i++) {
|
|
|
- efi_guid_t guid;
|
|
|
-
|
|
|
- guid = ((efi_config_table_64_t *)p)->guid;
|
|
|
-
|
|
|
- if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
|
|
|
- ((efi_config_table_64_t *)p)->table = data->smbios;
|
|
|
- p += sz;
|
|
|
- }
|
|
|
- early_iounmap(tablep, nr_tables * sz);
|
|
|
-
|
|
|
-out_memremap:
|
|
|
- early_iounmap(data, sizeof(*data));
|
|
|
-out:
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
void __init efi_init(void)
|
|
|
{
|
|
|
efi_char16_t *c16;
|
|
@@ -1057,11 +931,7 @@ static void __init kexec_enter_virtual_mode(void)
|
|
|
runtime_code_page_mkexec();
|
|
|
|
|
|
/* clean DUMMY object */
|
|
|
- efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
|
|
|
- EFI_VARIABLE_NON_VOLATILE |
|
|
|
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
|
|
- EFI_VARIABLE_RUNTIME_ACCESS,
|
|
|
- 0, NULL);
|
|
|
+ efi_delete_dummy_variable();
|
|
|
#endif
|
|
|
}
|
|
|
|
|
@@ -1179,11 +1049,7 @@ static void __init __efi_enter_virtual_mode(void)
|
|
|
free_pages((unsigned long)new_memmap, pg_shift);
|
|
|
|
|
|
/* clean DUMMY object */
|
|
|
- efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
|
|
|
- EFI_VARIABLE_NON_VOLATILE |
|
|
|
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
|
|
- EFI_VARIABLE_RUNTIME_ACCESS,
|
|
|
- 0, NULL);
|
|
|
+ efi_delete_dummy_variable();
|
|
|
}
|
|
|
|
|
|
void __init efi_enter_virtual_mode(void)
|
|
@@ -1230,86 +1096,6 @@ u64 efi_mem_attributes(unsigned long phys_addr)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Some firmware implementations refuse to boot if there's insufficient space
|
|
|
- * in the variable store. Ensure that we never use more than a safe limit.
|
|
|
- *
|
|
|
- * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
|
|
|
- * store.
|
|
|
- */
|
|
|
-efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
|
|
|
-{
|
|
|
- efi_status_t status;
|
|
|
- u64 storage_size, remaining_size, max_size;
|
|
|
-
|
|
|
- if (!(attributes & EFI_VARIABLE_NON_VOLATILE))
|
|
|
- return 0;
|
|
|
-
|
|
|
- status = efi.query_variable_info(attributes, &storage_size,
|
|
|
- &remaining_size, &max_size);
|
|
|
- if (status != EFI_SUCCESS)
|
|
|
- return status;
|
|
|
-
|
|
|
- /*
|
|
|
- * We account for that by refusing the write if permitting it would
|
|
|
- * reduce the available space to under 5KB. This figure was provided by
|
|
|
- * Samsung, so should be safe.
|
|
|
- */
|
|
|
- if ((remaining_size - size < EFI_MIN_RESERVE) &&
|
|
|
- !efi_no_storage_paranoia) {
|
|
|
-
|
|
|
- /*
|
|
|
- * Triggering garbage collection may require that the firmware
|
|
|
- * generate a real EFI_OUT_OF_RESOURCES error. We can force
|
|
|
- * that by attempting to use more space than is available.
|
|
|
- */
|
|
|
- unsigned long dummy_size = remaining_size + 1024;
|
|
|
- void *dummy = kzalloc(dummy_size, GFP_ATOMIC);
|
|
|
-
|
|
|
- if (!dummy)
|
|
|
- return EFI_OUT_OF_RESOURCES;
|
|
|
-
|
|
|
- status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
|
|
|
- EFI_VARIABLE_NON_VOLATILE |
|
|
|
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
|
|
- EFI_VARIABLE_RUNTIME_ACCESS,
|
|
|
- dummy_size, dummy);
|
|
|
-
|
|
|
- if (status == EFI_SUCCESS) {
|
|
|
- /*
|
|
|
- * This should have failed, so if it didn't make sure
|
|
|
- * that we delete it...
|
|
|
- */
|
|
|
- efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
|
|
|
- EFI_VARIABLE_NON_VOLATILE |
|
|
|
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
|
|
- EFI_VARIABLE_RUNTIME_ACCESS,
|
|
|
- 0, dummy);
|
|
|
- }
|
|
|
-
|
|
|
- kfree(dummy);
|
|
|
-
|
|
|
- /*
|
|
|
- * The runtime code may now have triggered a garbage collection
|
|
|
- * run, so check the variable info again
|
|
|
- */
|
|
|
- status = efi.query_variable_info(attributes, &storage_size,
|
|
|
- &remaining_size, &max_size);
|
|
|
-
|
|
|
- if (status != EFI_SUCCESS)
|
|
|
- return status;
|
|
|
-
|
|
|
- /*
|
|
|
- * There still isn't enough room, so return an error
|
|
|
- */
|
|
|
- if (remaining_size - size < EFI_MIN_RESERVE)
|
|
|
- return EFI_OUT_OF_RESOURCES;
|
|
|
- }
|
|
|
-
|
|
|
- return EFI_SUCCESS;
|
|
|
-}
|
|
|
-EXPORT_SYMBOL_GPL(efi_query_variable_store);
|
|
|
-
|
|
|
static int __init parse_efi_cmdline(char *str)
|
|
|
{
|
|
|
if (*str == '=')
|
|
@@ -1321,22 +1107,3 @@ static int __init parse_efi_cmdline(char *str)
|
|
|
return 0;
|
|
|
}
|
|
|
early_param("efi", parse_efi_cmdline);
|
|
|
-
|
|
|
-void __init efi_apply_memmap_quirks(void)
|
|
|
-{
|
|
|
- /*
|
|
|
- * Once setup is done earlier, unmap the EFI memory map on mismatched
|
|
|
- * firmware/kernel architectures since there is no support for runtime
|
|
|
- * services.
|
|
|
- */
|
|
|
- if (!efi_runtime_supported()) {
|
|
|
- pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
|
|
|
- efi_unmap_memmap();
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * UV doesn't support the new EFI pagetable mapping yet.
|
|
|
- */
|
|
|
- if (is_uv_system())
|
|
|
- set_bit(EFI_OLD_MEMMAP, &efi.flags);
|
|
|
-}
|