|
@@ -18,7 +18,27 @@
|
|
|
|
|
|
|
|
#include "efistub.h"
|
|
#include "efistub.h"
|
|
|
|
|
|
|
|
-bool __nokaslr;
|
|
|
|
|
|
|
+/*
|
|
|
|
|
+ * This is the base address at which to start allocating virtual memory ranges
|
|
|
|
|
+ * for UEFI Runtime Services. This is in the low TTBR0 range so that we can use
|
|
|
|
|
+ * any allocation we choose, and eliminate the risk of a conflict after kexec.
|
|
|
|
|
+ * The value chosen is the largest non-zero power of 2 suitable for this purpose
|
|
|
|
|
+ * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can
|
|
|
|
|
+ * be mapped efficiently.
|
|
|
|
|
+ * Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split,
|
|
|
|
|
+ * map everything below 1 GB. (512 MB is a reasonable upper bound for the
|
|
|
|
|
+ * entire footprint of the UEFI runtime services memory regions)
|
|
|
|
|
+ */
|
|
|
|
|
+#define EFI_RT_VIRTUAL_BASE SZ_512M
|
|
|
|
|
+#define EFI_RT_VIRTUAL_SIZE SZ_512M
|
|
|
|
|
+
|
|
|
|
|
+#ifdef CONFIG_ARM64
|
|
|
|
|
+# define EFI_RT_VIRTUAL_LIMIT TASK_SIZE_64
|
|
|
|
|
+#else
|
|
|
|
|
+# define EFI_RT_VIRTUAL_LIMIT TASK_SIZE
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
|
|
|
|
|
|
|
|
efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
|
|
efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
|
|
|
void *__image, void **__fh)
|
|
void *__image, void **__fh)
|
|
@@ -118,8 +138,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
|
|
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
|
|
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
|
|
|
goto fail;
|
|
goto fail;
|
|
|
|
|
|
|
|
- pr_efi(sys_table, "Booting Linux Kernel...\n");
|
|
|
|
|
-
|
|
|
|
|
status = check_platform_features(sys_table);
|
|
status = check_platform_features(sys_table);
|
|
|
if (status != EFI_SUCCESS)
|
|
if (status != EFI_SUCCESS)
|
|
|
goto fail;
|
|
goto fail;
|
|
@@ -153,17 +171,15 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
|
|
goto fail;
|
|
goto fail;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /* check whether 'nokaslr' was passed on the command line */
|
|
|
|
|
- if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
|
|
|
|
|
- static const u8 default_cmdline[] = CONFIG_CMDLINE;
|
|
|
|
|
- const u8 *str, *cmdline = cmdline_ptr;
|
|
|
|
|
|
|
+ if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
|
|
|
|
|
+ IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
|
|
|
|
|
+ cmdline_size == 0)
|
|
|
|
|
+ efi_parse_options(CONFIG_CMDLINE);
|
|
|
|
|
|
|
|
- if (IS_ENABLED(CONFIG_CMDLINE_FORCE))
|
|
|
|
|
- cmdline = default_cmdline;
|
|
|
|
|
- str = strstr(cmdline, "nokaslr");
|
|
|
|
|
- if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
|
|
|
|
|
- __nokaslr = true;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
|
|
|
|
|
+ efi_parse_options(cmdline_ptr);
|
|
|
|
|
+
|
|
|
|
|
+ pr_efi(sys_table, "Booting Linux Kernel...\n");
|
|
|
|
|
|
|
|
si = setup_graphics(sys_table);
|
|
si = setup_graphics(sys_table);
|
|
|
|
|
|
|
@@ -176,10 +192,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
|
|
goto fail_free_cmdline;
|
|
goto fail_free_cmdline;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- status = efi_parse_options(cmdline_ptr);
|
|
|
|
|
- if (status != EFI_SUCCESS)
|
|
|
|
|
- pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n");
|
|
|
|
|
-
|
|
|
|
|
secure_boot = efi_get_secureboot(sys_table);
|
|
secure_boot = efi_get_secureboot(sys_table);
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -213,8 +225,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
|
|
if (!fdt_addr)
|
|
if (!fdt_addr)
|
|
|
pr_efi(sys_table, "Generating empty DTB\n");
|
|
pr_efi(sys_table, "Generating empty DTB\n");
|
|
|
|
|
|
|
|
- status = handle_cmdline_files(sys_table, image, cmdline_ptr,
|
|
|
|
|
- "initrd=", dram_base + SZ_512M,
|
|
|
|
|
|
|
+ status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
|
|
|
|
|
+ efi_get_max_initrd_addr(dram_base,
|
|
|
|
|
+ *image_addr),
|
|
|
(unsigned long *)&initrd_addr,
|
|
(unsigned long *)&initrd_addr,
|
|
|
(unsigned long *)&initrd_size);
|
|
(unsigned long *)&initrd_size);
|
|
|
if (status != EFI_SUCCESS)
|
|
if (status != EFI_SUCCESS)
|
|
@@ -222,9 +235,29 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
|
|
|
|
|
|
|
efi_random_get_seed(sys_table);
|
|
efi_random_get_seed(sys_table);
|
|
|
|
|
|
|
|
|
|
+ if (!nokaslr()) {
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Randomize the base of the UEFI runtime services region.
|
|
|
|
|
+ * Preserve the 2 MB alignment of the region by taking a
|
|
|
|
|
+ * shift of 21 bit positions into account when scaling
|
|
|
|
|
+ * the headroom value using a 32-bit random value.
|
|
|
|
|
+ */
|
|
|
|
|
+ static const u64 headroom = EFI_RT_VIRTUAL_LIMIT -
|
|
|
|
|
+ EFI_RT_VIRTUAL_BASE -
|
|
|
|
|
+ EFI_RT_VIRTUAL_SIZE;
|
|
|
|
|
+ u32 rnd;
|
|
|
|
|
+
|
|
|
|
|
+ status = efi_get_random_bytes(sys_table, sizeof(rnd),
|
|
|
|
|
+ (u8 *)&rnd);
|
|
|
|
|
+ if (status == EFI_SUCCESS) {
|
|
|
|
|
+ virtmap_base = EFI_RT_VIRTUAL_BASE +
|
|
|
|
|
+ (((headroom >> 21) * rnd) >> (32 - 21));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
new_fdt_addr = fdt_addr;
|
|
new_fdt_addr = fdt_addr;
|
|
|
status = allocate_new_fdt_and_exit_boot(sys_table, handle,
|
|
status = allocate_new_fdt_and_exit_boot(sys_table, handle,
|
|
|
- &new_fdt_addr, dram_base + MAX_FDT_OFFSET,
|
|
|
|
|
|
|
+ &new_fdt_addr, efi_get_max_fdt_addr(dram_base),
|
|
|
initrd_addr, initrd_size, cmdline_ptr,
|
|
initrd_addr, initrd_size, cmdline_ptr,
|
|
|
fdt_addr, fdt_size);
|
|
fdt_addr, fdt_size);
|
|
|
|
|
|
|
@@ -251,18 +284,6 @@ fail:
|
|
|
return EFI_ERROR;
|
|
return EFI_ERROR;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * This is the base address at which to start allocating virtual memory ranges
|
|
|
|
|
- * for UEFI Runtime Services. This is in the low TTBR0 range so that we can use
|
|
|
|
|
- * any allocation we choose, and eliminate the risk of a conflict after kexec.
|
|
|
|
|
- * The value chosen is the largest non-zero power of 2 suitable for this purpose
|
|
|
|
|
- * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can
|
|
|
|
|
- * be mapped efficiently.
|
|
|
|
|
- * Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split,
|
|
|
|
|
- * map everything below 1 GB.
|
|
|
|
|
- */
|
|
|
|
|
-#define EFI_RT_VIRTUAL_BASE SZ_512M
|
|
|
|
|
-
|
|
|
|
|
static int cmp_mem_desc(const void *l, const void *r)
|
|
static int cmp_mem_desc(const void *l, const void *r)
|
|
|
{
|
|
{
|
|
|
const efi_memory_desc_t *left = l, *right = r;
|
|
const efi_memory_desc_t *left = l, *right = r;
|
|
@@ -312,7 +333,7 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
|
|
|
unsigned long desc_size, efi_memory_desc_t *runtime_map,
|
|
unsigned long desc_size, efi_memory_desc_t *runtime_map,
|
|
|
int *count)
|
|
int *count)
|
|
|
{
|
|
{
|
|
|
- u64 efi_virt_base = EFI_RT_VIRTUAL_BASE;
|
|
|
|
|
|
|
+ u64 efi_virt_base = virtmap_base;
|
|
|
efi_memory_desc_t *in, *prev = NULL, *out = runtime_map;
|
|
efi_memory_desc_t *in, *prev = NULL, *out = runtime_map;
|
|
|
int l;
|
|
int l;
|
|
|
|
|
|