#include "efistub.h"
 
+/*
+ * 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
+
+static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
+
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
                             void *__image, void **__fh)
 {
 
        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.
+                */
+               u64 headroom = TASK_SIZE - 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;
        status = allocate_new_fdt_and_exit_boot(sys_table, handle,
                                &new_fdt_addr, efi_get_max_fdt_addr(dram_base),
        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)
 {
        const efi_memory_desc_t *left = l, *right = r;
                     unsigned long desc_size, efi_memory_desc_t *runtime_map,
                     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;
        int l;