screen_info.o efi-stub-entry.o
 
 lib-$(CONFIG_ARM)              += arm32-stub.o
-lib-$(CONFIG_ARM64)            += arm64-stub.o arm64-entry.o
+lib-$(CONFIG_ARM64)            += arm64.o arm64-stub.o arm64-entry.o
 lib-$(CONFIG_X86)              += x86-stub.o
 lib-$(CONFIG_RISCV)            += riscv.o riscv-stub.o
 lib-$(CONFIG_LOONGARCH)                += loongarch-stub.o
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
+       /*
+        * The entrypoint of a arm64 bare metal image is at offset #0 of the
+        * image, so this is a reasonable default for primary_entry_offset.
+        * Only when the EFI stub is integrated into the core kernel, it is not
+        * guaranteed that the PE/COFF header has been copied to memory too, so
+        * in this case, primary_entry_offset should be overridden by the
+        * linker and point to primary_entry() directly.
+        */
+       .weak   primary_entry_offset
+
 SYM_CODE_START(efi_enter_kernel)
        /*
         * efi_pe_entry() will have copied the kernel image if necessary and we
 
 #include <asm/efi.h>
 #include <asm/memory.h>
 #include <asm/sections.h>
-#include <asm/sysreg.h>
 
 #include "efistub.h"
 
-efi_status_t check_platform_features(void)
-{
-       u64 tg;
-
-       /*
-        * If we have 48 bits of VA space for TTBR0 mappings, we can map the
-        * UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is
-        * unnecessary.
-        */
-       if (VA_BITS_MIN >= 48)
-               efi_novamap = true;
-
-       /* UEFI mandates support for 4 KB granularity, no need to check */
-       if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
-               return EFI_SUCCESS;
-
-       tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_EL1_TGRAN_SHIFT) & 0xf;
-       if (tg < ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN || tg > ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX) {
-               if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
-                       efi_err("This 64 KB granular kernel is not supported by your CPU\n");
-               else
-                       efi_err("This 16 KB granular kernel is not supported by your CPU\n");
-               return EFI_UNSUPPORTED;
-       }
-       return EFI_SUCCESS;
-}
-
 /*
  * Distro versions of GRUB may ignore the BSS allocation entirely (i.e., fail
  * to provide space, and fail to zero it). Check for this condition by double
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2013, 2014 Linaro Ltd;  <roy.franz@linaro.org>
+ *
+ * This file implements the EFI boot stub for the arm64 kernel.
+ * Adapted from ARM version by Mark Salter <msalter@redhat.com>
+ */
+
+
+#include <linux/efi.h>
+#include <asm/efi.h>
+#include <asm/memory.h>
+#include <asm/sysreg.h>
+
+#include "efistub.h"
+
+efi_status_t check_platform_features(void)
+{
+       u64 tg;
+
+       /*
+        * If we have 48 bits of VA space for TTBR0 mappings, we can map the
+        * UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is
+        * unnecessary.
+        */
+       if (VA_BITS_MIN >= 48)
+               efi_novamap = true;
+
+       /* UEFI mandates support for 4 KB granularity, no need to check */
+       if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
+               return EFI_SUCCESS;
+
+       tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_EL1_TGRAN_SHIFT) & 0xf;
+       if (tg < ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN || tg > ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX) {
+               if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
+                       efi_err("This 64 KB granular kernel is not supported by your CPU\n");
+               else
+                       efi_err("This 16 KB granular kernel is not supported by your CPU\n");
+               return EFI_UNSUPPORTED;
+       }
+       return EFI_SUCCESS;
+}
+
+void efi_cache_sync_image(unsigned long image_base,
+                         unsigned long alloc_size,
+                         unsigned long code_size)
+{
+       u32 ctr = read_cpuid_effective_cachetype();
+       u64 lsize = 4 << cpuid_feature_extract_unsigned_field(ctr,
+                                               CTR_EL0_DminLine_SHIFT);
+
+       do {
+               asm("dc civac, %0" :: "r"(image_base));
+               image_base += lsize;
+               alloc_size -= lsize;
+       } while (alloc_size >= lsize);
+
+       asm("ic ialluis");
+       dsb(ish);
+       isb();
+}
 
 struct screen_info *alloc_screen_info(void);
 void free_screen_info(struct screen_info *si);
 
+void efi_cache_sync_image(unsigned long image_base,
+                         unsigned long alloc_size,
+                         unsigned long code_size);
+
 #endif