efi_loader: ARM: run EFI payloads non-secure
authorMark Kettenis <kettenis@openbsd.org>
Fri, 15 Jun 2018 21:47:12 +0000 (23:47 +0200)
committerAlexander Graf <agraf@suse.de>
Wed, 25 Jul 2018 12:57:43 +0000 (14:57 +0200)
If desired (and possible) switch into HYP mode or non-secure SVC mode
before calling the entry point of an EFI application.  This allows
U-Boot to provide a usable PSCI implementation and makes it possible
to boot kernels into hypervisor mode using an EFI bootloader.

Based on diffs from Heinrich Schuchardt and Alexander Graf.

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
[agraf: Fix indentation]
Signed-off-by: Alexander Graf <agraf@suse.de>
cmd/bootefi.c

index cd755b6bf44441a9d25ff0356a9d10066f9e4c56..c8c2564512244ab29b4c2739fdf8db00a64a382c 100644 (file)
 #include <asm-generic/unaligned.h>
 #include <linux/linkage.h>
 
+#ifdef CONFIG_ARMV7_NONSEC
+#include <asm/armv7.h>
+#include <asm/secure.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #define OBJ_LIST_NOT_INITIALIZED 1
@@ -194,6 +199,18 @@ static efi_status_t efi_run_in_el2(EFIAPI efi_status_t (*entry)(
 }
 #endif
 
+#ifdef CONFIG_ARMV7_NONSEC
+static efi_status_t efi_run_in_hyp(EFIAPI efi_status_t (*entry)(
+                       efi_handle_t image_handle, struct efi_system_table *st),
+                       efi_handle_t image_handle, struct efi_system_table *st)
+{
+       /* Enable caches again */
+       dcache_enable();
+
+       return efi_do_enter(image_handle, st, entry);
+}
+#endif
+
 /* Carve out DT reserved memory ranges */
 static efi_status_t efi_carve_out_dt_rsv(void *fdt)
 {
@@ -350,6 +367,22 @@ static efi_status_t do_bootefi_exec(void *efi,
        }
 #endif
 
+#ifdef CONFIG_ARMV7_NONSEC
+       if (armv7_boot_nonsec()) {
+               dcache_disable();       /* flush cache before switch to HYP */
+
+               armv7_init_nonsec();
+               secure_ram_addr(_do_nonsec_entry)(
+                                       efi_run_in_hyp,
+                                       (uintptr_t)entry,
+                                       (uintptr_t)loaded_image_info_obj.handle,
+                                       (uintptr_t)&systab);
+
+               /* Should never reach here, efi exits with longjmp */
+               while (1) { }
+       }
+#endif
+
        ret = efi_do_enter(loaded_image_info_obj.handle, &systab, entry);
 
 exit: