diff --git a/arch/arm/config.mk b/arch/arm/config.mk
index 38c49c877c4..c8b5bcda8e4 100644
--- a/arch/arm/config.mk
+++ b/arch/arm/config.mk
@@ -146,9 +146,6 @@ OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .hash \
 		-j .binman_sym_table -j .text_rest
 endif
 
-OBJCOPYFLAGS_EFI += $(OBJCOPYFLAGS) -j .dynamic -j .rela -j .reloc \
-	-j .embedded_dtb
-
 # if a dtb section exists we always have to include it
 # there are only two cases where it is generated
 # 1) OF_EMBEDED is turned on
@@ -178,13 +175,6 @@ endif
 endif
 endif
 
-ifdef CONFIG_ARM64
-EFI_LDS := elf_aarch64_efi.lds
-EFI_CRT0 := crt0_aarch64_efi.o
-EFI_RELOC := reloc_aarch64_efi.o
-EFI_TARGET := --target=efi-app-aarch64
-else
 EFI_LDS := elf_arm_efi.lds
 EFI_CRT0 := crt0_arm_efi.o
 EFI_RELOC := reloc_arm_efi.o
-endif
diff --git a/arch/arm/cpu/armv8/config.mk b/arch/arm/cpu/armv8/config.mk
index 61ba3143969..0316af306c4 100644
--- a/arch/arm/cpu/armv8/config.mk
+++ b/arch/arm/cpu/armv8/config.mk
@@ -13,7 +13,7 @@ EFI_RELOC := reloc_aarch64_efi.o
 
 LDSCRIPT_EFI := $(srctree)/arch/arm/lib/elf_aarch64_efi.lds
 EFISTUB := crt0_aarch64_efi.o reloc_aarch64_efi.o
-OBJCOPYFLAGS_EFI += -O binary --target=efi-app-aarch64
+OBJCOPYFLAGS_EFI += --target=pei-aarch64-little
 EFIPAYLOAD_BFDTARGET := pei-aarch64-little
 EFIPAYLOAD_BFDARCH := aarch64
 LDFLAGS_EFI_PAYLOAD := -Bsymbolic -Bsymbolic-functions -shared --no-undefined \
@@ -21,3 +21,7 @@ LDFLAGS_EFI_PAYLOAD := -Bsymbolic -Bsymbolic-functions -shared --no-undefined \
 
 CPPFLAGS_REMOVE_crt0-efi-aarch64.o += $(CFLAGS_NON_EFI)
 CPPFLAGS_crt0-efi-aarch64.o += $(CFLAGS_EFI)
+
+ifeq ($(CONFIG_EFI_APP),y)
+PLATFORM_CPPFLAGS += $(CFLAGS_EFI)
+endif
diff --git a/arch/arm/lib/crt0_aarch64_efi.S b/arch/arm/lib/crt0_aarch64_efi.S
index 88f8449bb03..c1030e5392a 100644
--- a/arch/arm/lib/crt0_aarch64_efi.S
+++ b/arch/arm/lib/crt0_aarch64_efi.S
@@ -10,11 +10,140 @@
 
 #include <asm-generic/pe.h>
 
-	.text
-	.align		12
+	.section	.text.head
+
+	/*
+	 * Magic "MZ" signature for PE/COFF
+	 */
+	.globl	image_base
+image_base:
+	.short	IMAGE_DOS_SIGNATURE		/* 'MZ' */
+	.skip	54				/* 'MZ' + pad + offset == 64 */
+	.long   LINUX_ARM64_MAGIC		/* For GRUB's linux command */
+	.long	pe_header - image_base		/* Offset to the PE header */
+pe_header:
+	.long	IMAGE_NT_SIGNATURE		/* 'PE' */
+coff_header:
+	.short	IMAGE_FILE_MACHINE_ARM64	/* AArch64 */
+	.short	3				/* nr_sections */
+	.long	0				/* TimeDateStamp */
+	.long	0				/* PointerToSymbolTable */
+	.long	0				/* NumberOfSymbols */
+	.short	section_table - optional_header	/* SizeOfOptionalHeader */
+	/* Characteristics */
+	.short	(IMAGE_FILE_EXECUTABLE_IMAGE | \
+		 IMAGE_FILE_LINE_NUMS_STRIPPED | \
+		 IMAGE_FILE_LOCAL_SYMS_STRIPPED | \
+		 IMAGE_FILE_LARGE_ADDRESS_AWARE | \
+		 IMAGE_FILE_DEBUG_STRIPPED)
+optional_header:
+	.short	IMAGE_NT_OPTIONAL_HDR64_MAGIC	/* PE32+ format */
+	.byte	0x02				/* MajorLinkerVersion */
+	.byte	0x14				/* MinorLinkerVersion */
+	.long	_etext - _start			/* SizeOfCode */
+	.long	0				/* SizeOfInitializedData */
+	.long	0				/* SizeOfUninitializedData */
+	.long	_start - image_base		/* AddressOfEntryPoint */
+	.long	_start - image_base		/* BaseOfCode */
+
+extra_header_fields:
+	.quad	0				/* image_base */
+	.long	0x1000				/* SectionAlignment */
+	.long	0x200				/* FileAlignment */
+	.short	0				/* MajorOperatingSystemVersion */
+	.short	0				/* MinorOperatingSystemVersion */
+	.short	0				/* MajorImageVersion */
+	.short	0				/* MinorImageVersion */
+	.short	0				/* MajorSubsystemVersion */
+	.short	0				/* MinorSubsystemVersion */
+	.long	0				/* Win32VersionValue */
+
+	.long	_edata - image_base		/* SizeOfImage */
+
+	/*
+	 * Everything before the kernel image is considered part of the header
+	 */
+	.long	_start - image_base		/* SizeOfHeaders */
+	.long	0				/* CheckSum */
+	.short	IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */
+#if CONFIG_ARCH_EFI
+	.short	0				/* DllCharacteristics */
+#else
+	.short	IMAGE_DLLCHARACTERISTICS_NX_COMPAT
+#endif
+	.quad	0				/* SizeOfStackReserve */
+	.quad	0				/* SizeOfStackCommit */
+	.quad	0				/* SizeOfHeapReserve */
+	.quad	0				/* SizeOfHeapCommit */
+	.long	0				/* LoaderFlags */
+	.long	0x6				/* NumberOfRvaAndSizes */
+
+	.quad	0				/* ExportTable */
+	.quad	0				/* ImportTable */
+	.quad	0				/* ResourceTable */
+	.quad	0				/* ExceptionTable */
+	.quad	0				/* CertificationTable */
+	.quad	0				/* BaseRelocationTable */
 
-	.globl _start
-	.type _start,%function
+	/* Section table */
+section_table:
+
+	/*
+	 * The EFI application loader requires a relocation section
+	 * because EFI applications must be relocatable.  This is a
+	 * dummy section as far as we are concerned.
+	 */
+	.ascii	".reloc"
+	.byte	0
+	.byte	0			/* end of 0 padding of section name */
+	.long	0
+	.long	0
+	.long	0			/* SizeOfRawData */
+	.long	0			/* PointerToRawData */
+	.long	0			/* PointerToRelocations */
+	.long	0			/* PointerToLineNumbers */
+	.short	0			/* NumberOfRelocations */
+	.short	0			/* NumberOfLineNumbers */
+	/* Characteristics (section flags) */
+	.long	(IMAGE_SCN_MEM_READ | \
+		 IMAGE_SCN_MEM_DISCARDABLE | \
+		 IMAGE_SCN_CNT_INITIALIZED_DATA)
+
+	.ascii	".text"
+	.byte	0
+	.byte	0
+	.byte	0			/* end of 0 padding of section name */
+	.long	_etext - _start		/* VirtualSize */
+	.long	_start - image_base	/* VirtualAddress */
+	.long	_etext - _start		/* SizeOfRawData */
+	.long	_start - image_base	/* PointerToRawData */
+	.long	0			/* PointerToRelocations */
+	.long	0			/* PointerToLineNumbers */
+	.short	0			/* NumberOfRelocations */
+	.short	0			/* NumberOfLineNumbers */
+	/* Characteristics (section flags) */
+	.long	(IMAGE_SCN_MEM_READ | \
+		 IMAGE_SCN_MEM_EXECUTE | \
+		 IMAGE_SCN_CNT_CODE)
+
+	.ascii	".data"
+	.byte	0
+	.byte	0
+	.byte	0			/* end of 0 padding of section name */
+	.long	_data_size		/* VirtualSize */
+	.long	_data - image_base	/* VirtualAddress */
+	.long	_data_size		/* SizeOfRawData */
+	.long	_data - image_base	/* PointerToRawData */
+	.long	0			/* PointerToRelocations */
+	.long	0			/* PointerToLineNumbers */
+	.short	0			/* NumberOfRelocations */
+	.short	0			/* NumberOfLineNumbers */
+	/* Characteristics (section flags) */
+	.long	(IMAGE_SCN_MEM_WRITE | \
+		 IMAGE_SCN_MEM_READ | \
+		 IMAGE_SCN_CNT_INITIALIZED_DATA)
+
+	.align		12
 _start:
 	stp		x29, x30, [sp, #-32]!
 	mov		x29, sp
@@ -31,22 +160,3 @@ _start:
 
 0:	ldp		x29, x30, [sp], #32
 	ret
-
-	/*
-	 * hand-craft a dummy .reloc section so EFI knows it's a relocatable
-	 * executable:
-	*/
-	.data
-dummy:	.4byte	0
-
-#define IMAGE_REL_ABSOLUTE	0
-	.section .reloc, "a"
-label1:
-	.4byte	dummy-label1			// Page RVA
-	.4byte	12				// Block Size (2*4+2*2), must be aligned by 32 Bits
-	.2byte	(IMAGE_REL_ABSOLUTE<<12) +  0	// reloc for dummy
-	.2byte	(IMAGE_REL_ABSOLUTE<<12) +  0	// reloc for dummy
-
-#if defined(__ELF__) && defined(__linux__)
-	.section .note.GNU-stack,"",%progbits
-#endif
diff --git a/arch/arm/lib/elf_aarch64_efi.lds b/arch/arm/lib/elf_aarch64_efi.lds
index cb7081abef5..f872624dd42 100644
--- a/arch/arm/lib/elf_aarch64_efi.lds
+++ b/arch/arm/lib/elf_aarch64_efi.lds
@@ -7,19 +7,18 @@
 
 OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
 OUTPUT_ARCH(aarch64)
+
+PHDRS
+{
+	data PT_LOAD FLAGS(3); /* SHF_WRITE | SHF_ALLOC */
+}
+
 ENTRY(_start)
 SECTIONS
 {
-	. = 0;
-	image_base = .;
-	/* .hash and/or .gnu.hash MUST come first! */
-	.hash : { *(.hash) }
-	.gnu.hash : { *(.gnu.hash) }
-	. = ALIGN(4096);
-	.eh_frame : { *(.eh_frame) }
-	. = ALIGN(4096);
-	.text : {
+	.text 0x0 : {
 		_text = .;
+		*(.text.head)
 		*(.text)
 		*(.text.*)
 		*(.gnu.linkonce.t.*)
@@ -29,12 +28,12 @@ SECTIONS
 		*(.dynamic);
 		. = ALIGN(512);
 	}
+	.rela.dyn : { *(.rela.dyn) }
+	.rela.plt : { *(.rela.plt) }
+	.rela.got : { *(.rela.got) }
+	.rela.data : { *(.rela.data) *(.rela.data*) }
 	_etext = .;
 	_text_size = . - _text;
-	. = ALIGN(65536);
-	.reloc : {
-		KEEP (*(.reloc))
-	}
 	. = ALIGN(4096);
 	.data : {
 		_data = .;
@@ -64,24 +63,9 @@ SECTIONS
 		. = ALIGN(512);
 		_bss_end = .;
 		_edata = .;
-		_end = .;
-	}
+	} :data
 	_data_size = _edata - _data;
 
-	. = ALIGN(4096);
-	.rela : {
-		*(.rela.text*)
-		*(.rela.data*)
-		*(.rela.got)
-		*(.rela.dyn)
-		*(.rela.stab)
-		*(.rela.init_array*)
-		*(.rela.fini_array*)
-		*(.rela.ctors*)
-		*(.rela.dtors*)
-		*(.rela__u_boot_list*)
-	}
-
 	. = ALIGN(4096);
 	.dynsym   : { *(.dynsym) }
 	. = ALIGN(4096);
@@ -93,8 +77,5 @@ SECTIONS
 		*(.eh_frame)
 		*(.note.GNU-stack)
 	}
-	.embedded_dtb : {
-		*(.embedded_dtb)
-	}
 	.comment 0 : { *(.comment) }
 }
diff --git a/board/efi/efi-arm_app/config.mk b/board/efi/efi-arm_app/config.mk
deleted file mode 100644
index a576a1da539..00000000000
--- a/board/efi/efi-arm_app/config.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0+
-
-BUILD_CFLAGS += -shared
-PLATFORM_CPPFLAGS += $(CFLAGS_EFI)
