diff mbox series

[16/16] efi: LoongArch: Implement everything

Message ID 20240522-loongarch-v1-16-1407e0b69678@flygoat.com
State Changes Requested
Delegated to: Tom Rini
Headers show
Series LoongArch initial support | expand

Commit Message

Jiaxun Yang May 22, 2024, 3:34 p.m. UTC
Implement crt, reloc, linker scripts, wire things up in
Makefiles and Kconfig.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/loongarch/config.mk                 |   4 +
 arch/loongarch/lib/Makefile              |  12 ++
 arch/loongarch/lib/crt0_loongarch_efi.S  | 182 +++++++++++++++++++++++++++++++
 arch/loongarch/lib/elf_loongarch_efi.lds |  76 +++++++++++++
 arch/loongarch/lib/reloc_loongarch_efi.c | 107 ++++++++++++++++++
 lib/efi_loader/Kconfig                   |   2 +-
 6 files changed, 382 insertions(+), 1 deletion(-)

Comments

Heinrich Schuchardt May 23, 2024, 4:26 p.m. UTC | #1
On 22.05.24 17:34, Jiaxun Yang wrote:
> Implement crt, reloc, linker scripts, wire things up in
> Makefiles and Kconfig.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>   arch/loongarch/config.mk                 |   4 +
>   arch/loongarch/lib/Makefile              |  12 ++
>   arch/loongarch/lib/crt0_loongarch_efi.S  | 182 +++++++++++++++++++++++++++++++
>   arch/loongarch/lib/elf_loongarch_efi.lds |  76 +++++++++++++
>   arch/loongarch/lib/reloc_loongarch_efi.c | 107 ++++++++++++++++++
>   lib/efi_loader/Kconfig                   |   2 +-
>   6 files changed, 382 insertions(+), 1 deletion(-)
>
> diff --git a/arch/loongarch/config.mk b/arch/loongarch/config.mk
> index 7c247400e361..bae4566e9b62 100644
> --- a/arch/loongarch/config.mk
> +++ b/arch/loongarch/config.mk
> @@ -21,3 +21,7 @@ endif
>   PLATFORM_CPPFLAGS	+= -fpic
>   PLATFORM_RELFLAGS	+= -fno-common -ffunction-sections -fdata-sections
>   LDFLAGS_u-boot		+= --gc-sections -static -pie
> +
> +EFI_LDS				:= elf_loongarch_efi.lds
> +EFI_CRT0			:= crt0_loongarch_efi.o
> +EFI_RELOC			:= reloc_loongarch_efi.o
> diff --git a/arch/loongarch/lib/Makefile b/arch/loongarch/lib/Makefile
> index e65e66357a9b..17d2b1160b41 100644
> --- a/arch/loongarch/lib/Makefile
> +++ b/arch/loongarch/lib/Makefile
> @@ -12,3 +12,15 @@ ifeq ($(CONFIG_$(SPL_)SYSRESET),)
>   obj-y	+= reset.o
>   endif
>   obj-y	+= setjmp.o
> +
> +# For building EFI apps
> +CFLAGS_NON_EFI := -fstack-protector-strong
> +CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI)
> +CFLAGS_REMOVE_$(EFI_CRT0) := $(CFLAGS_NON_EFI)
> +
> +CFLAGS_$(EFI_RELOC) := $(CFLAGS_EFI)
> +CFLAGS_REMOVE_$(EFI_RELOC) := $(CFLAGS_NON_EFI)
> +
> +extra-$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE) += $(EFI_CRT0) $(EFI_RELOC)
> +extra-$(CONFIG_CMD_BOOTEFI_SELFTEST) += $(EFI_CRT0) $(EFI_RELOC)
> +extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC)
> diff --git a/arch/loongarch/lib/crt0_loongarch_efi.S b/arch/loongarch/lib/crt0_loongarch_efi.S
> new file mode 100644
> index 000000000000..5be47045ad8a
> --- /dev/null
> +++ b/arch/loongarch/lib/crt0_loongarch_efi.S
> @@ -0,0 +1,182 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * crt0-efi-loongarch.S - PE/COFF header for LoongArch EFI applications
> + *
> + * Copright (C) 2024 Jiaxun Yang <jiaxun.yang@flygoat.com>
> + */
> +
> +#include <asm-generic/pe.h>
> +#include <asm/asm.h>
> +
> +#ifdef __loongarch64
> +#define PE_MACHINE	IMAGE_FILE_MACHINE_LOONGARCH64
> +#define PE_MAGIC    IMAGE_NT_OPTIONAL_HDR64_MAGIC
> +#define IMG_CHARACTERISTICS \
> +	(IMAGE_FILE_EXECUTABLE_IMAGE | \
> +	 IMAGE_FILE_LINE_NUMS_STRIPPED | \
> +	 IMAGE_FILE_LOCAL_SYMS_STRIPPED | \
> +	 IMAGE_FILE_LARGE_ADDRESS_AWARE | \
> +	 IMAGE_FILE_DEBUG_STRIPPED)
> +#else
> +#define PE_MACHINE	IMAGE_FILE_MACHINE_LOONGARCH32
> +#define PE_MAGIC    IMAGE_NT_OPTIONAL_HDR32_MAGIC
> +#define IMG_CHARACTERISTICS \
> +	(IMAGE_FILE_EXECUTABLE_IMAGE | \
> +	 IMAGE_FILE_LINE_NUMS_STRIPPED | \
> +	 IMAGE_FILE_LOCAL_SYMS_STRIPPED | \
> +	 IMAGE_FILE_DEBUG_STRIPPED)
> +#endif
> +
> +	.section	.text.head
> +
> +	/*
> +	 * Magic "MZ" signature for PE/COFF
> +	 */
> +	.globl	ImageBase
> +ImageBase:
> +	.short	IMAGE_DOS_SIGNATURE		/* 'MZ' */
> +	.skip	58
> +	.long	pe_header - ImageBase		/* Offset to the PE header */
> +pe_header:
> +	.long	IMAGE_NT_SIGNATURE		/* 'PE' */
> +coff_header:
> +	.short	PE_MACHINE			/* LoongArch 64/32-bit */
> +	.short	3				/* nr_sections */
> +	.long	0				/* TimeDateStamp */
> +	.long	0				/* PointerToSymbolTable */
> +	.long	0				/* NumberOfSymbols */
> +	.short	section_table - optional_header	/* SizeOfOptionalHeader */
> +	.short	IMG_CHARACTERISTICS		/* Characteristics */
> +optional_header:
> +	.short	PE_MAGIC			/* PE32(+) format */
> +	.byte	0x02				/* MajorLinkerVersion */
> +	.byte	0x14				/* MinorLinkerVersion */
> +	.long	_edata - _start			/* SizeOfCode */
> +	.long	0				/* SizeOfInitializedData */
> +	.long	0				/* SizeOfUninitializedData */
> +	.long	_start - ImageBase		/* AddressOfEntryPoint */
> +	.long	_start - ImageBase		/* BaseOfCode */
> +#ifndef __loongarch64
> +	.long	0				/* BaseOfData */
> +#endif
> +
> +extra_header_fields:
> +	LONG	0
> +	.long	0x200				/* SectionAlignment */
> +	.long	0x200				/* FileAlignment */
> +	.short	0				/* MajorOperatingSystemVersion */
> +	.short	0				/* MinorOperatingSystemVersion */
> +	.short	1				/* MajorImageVersion */
> +	.short	0				/* MinorImageVersion */
> +	.short	0				/* MajorSubsystemVersion */
> +	.short	0				/* MinorSubsystemVersion */
> +	.long	0				/* Win32VersionValue */
> +
> +	.long	_edata - ImageBase		/* SizeOfImage */
> +
> +	/*
> +	 * Everything before the kernel image is considered part of the header
> +	 */
> +	.long	_start - ImageBase		/* SizeOfHeaders */
> +	.long	0				/* CheckSum */
> +	.short	IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */
> +#if CONFIG_VENDOR_EFI
> +	.short	0				/* DllCharacteristics */
> +#else
> +	.short	IMAGE_DLLCHARACTERISTICS_NX_COMPAT
> +#endif
> +	LONG	0				/* SizeOfStackReserve */
> +	LONG	0				/* SizeOfStackCommit */
> +	LONG	0				/* SizeOfHeapReserve */
> +	LONG	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 */
> +
> +	/* 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 */
> +	.long	0x42100040		/* Characteristics (section flags) */
> +
> +
> +	.ascii	".text"
> +	.byte	0
> +	.byte	0
> +	.byte	0			/* end of 0 padding of section name */
> +	.long	_etext - _start		/* VirtualSize */
> +	.long	_start - ImageBase	/* VirtualAddress */
> +	.long	_etext - _start		/* SizeOfRawData */
> +	.long	_start - ImageBase	/* PointerToRawData */
> +	.long	0			/* PointerToRelocations (0 for executables) */
> +	.long	0			/* PointerToLineNumbers (0 for executables) */
> +	.short	0			/* NumberOfRelocations  (0 for executables) */
> +	.short	0			/* NumberOfLineNumbers  (0 for executables) */
> +	/* 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	_edata - _data		/* VirtualSize */
> +	.long	_data - ImageBase	/* VirtualAddress */
> +	.long	_edata - _data		/* SizeOfRawData */
> +	.long	_data - ImageBase	/* 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
> +	.globl	_start
> +	.type	_start, @function
> +_start:
> +	PTR_ADDI	sp, sp, -(3 * LONGSIZE)
> +	LONG_S		ra, sp, 0
> +	LONG_S		a0, sp, (1 * LONGSIZE)
> +	LONG_S		a1, sp, (2 * LONGSIZE)
> +
> +	move		a2, a0		/* a2: ImageHandle */
> +	move		a3, a1		/* a3: SystemTable */
> +	la.local	a0, ImageBase	/* a0: ImageBase */
> +	la.local	a1, _DYNAMIC	/* a1: DynamicSection */
> +	bl 	  	_relocate
> +	bnez		a0, 0f
> +
> +	LONG_L		a0, sp, (1 * LONGSIZE)
> +	LONG_L		a1, sp, (2 * LONGSIZE)
> +	bl		efi_main
> +
> +0:	LONG_L		ra, sp, 0
> +	PTR_ADDI	sp, sp, (3 * LONGSIZE)
> +	jr			ra
> +	.end	  _start
> diff --git a/arch/loongarch/lib/elf_loongarch_efi.lds b/arch/loongarch/lib/elf_loongarch_efi.lds
> new file mode 100644
> index 000000000000..050e5a52a0b3
> --- /dev/null
> +++ b/arch/loongarch/lib/elf_loongarch_efi.lds
> @@ -0,0 +1,76 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +/*
> + * U-Boot LoongArch
> + *
> + * Modified from arch/riscv/lib/elf_riscv64_efi.lds
> + */
> +
> +OUTPUT_ARCH(loongarch)
> +
> +PHDRS
> +{
> +	data PT_LOAD FLAGS(3); /* SHF_WRITE | SHF_ALLOC */
> +}
> +
> +ENTRY(_start)
> +SECTIONS
> +{
> +	.text 0x0 : {
> +		_text = .;
> +		*(.text.head)
> +		*(.text)
> +		*(.text.*)
> +		*(.gnu.linkonce.t.*)
> +		*(.srodata)
> +		*(.rodata*)
> +		. = ALIGN(16);
> +		*(.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(4096);
> +	.data : {
> +		_data = .;
> +		*(.sdata)
> +		*(.data)
> +		*(.data1)
> +		*(.data.*)
> +		*(.got.plt)
> +		*(.got)
> +
> +		/*
> +		 * The EFI loader doesn't seem to like a .bss section, so we
> +		 * stick it all into .data:
> +		 */
> +		. = ALIGN(16);
> +		_bss = .;
> +		*(.sbss)
> +		*(.scommon)
> +		*(.dynbss)
> +		*(.bss)
> +		*(.bss.*)
> +		*(COMMON)
> +		. = ALIGN(512);
> +		_bss_end = .;
> +		_edata = .;
> +	} :data
> +	_data_size = _edata - _data;
> +
> +	. = ALIGN(4096);
> +	.dynsym   : { *(.dynsym) }
> +	. = ALIGN(4096);
> +	.dynstr   : { *(.dynstr) }
> +	. = ALIGN(4096);
> +	.note.gnu.build-id : { *(.note.gnu.build-id) }
> +	/DISCARD/ : {
> +		*(.rel.reloc)
> +		*(.eh_frame)
> +		*(.note.GNU-stack)
> +	}
> +	.comment 0 : { *(.comment) }
> +}
> diff --git a/arch/loongarch/lib/reloc_loongarch_efi.c b/arch/loongarch/lib/reloc_loongarch_efi.c
> new file mode 100644
> index 000000000000..32a7d792103d
> --- /dev/null
> +++ b/arch/loongarch/lib/reloc_loongarch_efi.c

The code seems to be very similar for all architectures. I wonder if one
implementation could cover them all.

Best regards

Heinrich

> @@ -0,0 +1,107 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/* reloc_loongarch.c - position independent ELF shared object relocator
> +   Copyright (C) 2018 Alexander Graf <agraf@suse.de>
> +   Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
> +   Copyright (C) 1999 Hewlett-Packard Co.
> +	Contributed by David Mosberger <davidm@hpl.hp.com>.
> +
> +    All rights reserved.
> +
> +    Redistribution and use in source and binary forms, with or without
> +    modification, are permitted provided that the following conditions
> +    are met:
> +
> +    * Redistributions of source code must retain the above copyright
> +      notice, this list of conditions and the following disclaimer.
> +    * Redistributions in binary form must reproduce the above
> +      copyright notice, this list of conditions and the following
> +      disclaimer in the documentation and/or other materials
> +      provided with the distribution.
> +    * Neither the name of Hewlett-Packard Co. nor the names of its
> +      contributors may be used to endorse or promote products derived
> +      from this software without specific prior written permission.
> +
> +    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> +    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> +    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> +    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> +    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
> +    BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
> +    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> +    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> +    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> +    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> +    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> +    SUCH DAMAGE.
> +*/
> +
> +#include <efi.h>
> +
> +#include <elf.h>
> +
> +#ifdef __loongarch64
> +#define Elf_Dyn		Elf64_Dyn
> +#define Elf_Rela	Elf64_Rela
> +#define ELF_R_TYPE	ELF64_R_TYPE
> +#else
> +#define Elf_Dyn		Elf32_Dyn
> +#defiggne Elf_Rela	Elf32_Rela
> +#define ELF_R_TYPE	ELF32_R_TYPE
> +#endif
> +
> +efi_status_t EFIAPI _relocate(long ldbase, Elf_Dyn *dyn)
> +{
> +	long relsz = 0, relent = 0;
> +	Elf_Rela *rel = 0;
> +	unsigned long *addr;
> +	int i;
> +
> +	for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
> +		switch (dyn[i].d_tag) {
> +		case DT_RELA:
> +			rel = (Elf_Rela *)
> +				((unsigned long)dyn[i].d_un.d_ptr
> +					+ ldbase);
> +			break;
> +		case DT_RELASZ:
> +			relsz = dyn[i].d_un.d_val;
> +			break;
> +		case DT_RELAENT:
> +			relent = dyn[i].d_un.d_val;
> +			break;
> +		case DT_PLTGOT:
> +			addr = (unsigned long *)
> +				((unsigned long)dyn[i].d_un.d_ptr
> +					+ ldbase);
> +			break;
> +		default:
> +			break;
> +		}
> +	}
> +
> +	if (!rel && relent == 0)
> +		return EFI_SUCCESS;
> +
> +	if (!rel || relent == 0)
> +		return EFI_LOAD_ERROR;
> +
> +	while (relsz > 0) {
> +		/* apply the relocs */
> +		switch (ELF_R_TYPE(rel->r_info)) {
> +		case R_LARCH_NONE:
> +			break;
> +		case R_LARCH_RELATIVE:
> +			addr = (unsigned long *)
> +				(ldbase + rel->r_offset);
> +			*addr += ldbase;
> +			break;
> +		default:
> +			break;
> +		}
> +		rel = (Elf_Rela *)((char *)rel + relent);
> +		relsz -= relent;
> +	}
> +	return EFI_SUCCESS;
> +}
> +
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index 430bb7f0f7dc..1d82a062a215 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -5,7 +5,7 @@ config EFI_LOADER
>   			SYS_CPU = arm1176 || \
>   			SYS_CPU = armv7   || \
>   			SYS_CPU = armv8)  || \
> -		X86 || RISCV || SANDBOX)
> +		X86 || RISCV || LOONGARCH || SANDBOX)
>   	# We need EFI_STUB_64BIT to be set on x86_64 with EFI_STUB
>   	depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT
>   	# We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB
>
Jiaxun Yang May 23, 2024, 4:46 p.m. UTC | #2
在2024年5月23日五月 下午5:26,Heinrich Schuchardt写道:

>> diff --git a/arch/loongarch/lib/reloc_loongarch_efi.c b/arch/loongarch/lib/reloc_loongarch_efi.c
>> new file mode 100644
>> index 000000000000..32a7d792103d
>> --- /dev/null
>> +++ b/arch/loongarch/lib/reloc_loongarch_efi.c
>
> The code seems to be very similar for all architectures. I wonder if one
> implementation could cover them all.

Not for MIPS due to differences on psABI dynamic relocations.
We still need to handle differences between Rel and Rela and other tiny bits.

I think most architectures have their relocation handling code rooted from
gnu-efi.

Thanks
- Jiaxun

>
> Best regards
>
> Heinrich
>
diff mbox series

Patch

diff --git a/arch/loongarch/config.mk b/arch/loongarch/config.mk
index 7c247400e361..bae4566e9b62 100644
--- a/arch/loongarch/config.mk
+++ b/arch/loongarch/config.mk
@@ -21,3 +21,7 @@  endif
 PLATFORM_CPPFLAGS	+= -fpic
 PLATFORM_RELFLAGS	+= -fno-common -ffunction-sections -fdata-sections
 LDFLAGS_u-boot		+= --gc-sections -static -pie
+
+EFI_LDS				:= elf_loongarch_efi.lds
+EFI_CRT0			:= crt0_loongarch_efi.o
+EFI_RELOC			:= reloc_loongarch_efi.o
diff --git a/arch/loongarch/lib/Makefile b/arch/loongarch/lib/Makefile
index e65e66357a9b..17d2b1160b41 100644
--- a/arch/loongarch/lib/Makefile
+++ b/arch/loongarch/lib/Makefile
@@ -12,3 +12,15 @@  ifeq ($(CONFIG_$(SPL_)SYSRESET),)
 obj-y	+= reset.o
 endif
 obj-y	+= setjmp.o
+
+# For building EFI apps
+CFLAGS_NON_EFI := -fstack-protector-strong
+CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI)
+CFLAGS_REMOVE_$(EFI_CRT0) := $(CFLAGS_NON_EFI)
+
+CFLAGS_$(EFI_RELOC) := $(CFLAGS_EFI)
+CFLAGS_REMOVE_$(EFI_RELOC) := $(CFLAGS_NON_EFI)
+
+extra-$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE) += $(EFI_CRT0) $(EFI_RELOC)
+extra-$(CONFIG_CMD_BOOTEFI_SELFTEST) += $(EFI_CRT0) $(EFI_RELOC)
+extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC)
diff --git a/arch/loongarch/lib/crt0_loongarch_efi.S b/arch/loongarch/lib/crt0_loongarch_efi.S
new file mode 100644
index 000000000000..5be47045ad8a
--- /dev/null
+++ b/arch/loongarch/lib/crt0_loongarch_efi.S
@@ -0,0 +1,182 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * crt0-efi-loongarch.S - PE/COFF header for LoongArch EFI applications
+ *
+ * Copright (C) 2024 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ */
+
+#include <asm-generic/pe.h>
+#include <asm/asm.h>
+
+#ifdef __loongarch64
+#define PE_MACHINE	IMAGE_FILE_MACHINE_LOONGARCH64
+#define PE_MAGIC    IMAGE_NT_OPTIONAL_HDR64_MAGIC
+#define IMG_CHARACTERISTICS \
+	(IMAGE_FILE_EXECUTABLE_IMAGE | \
+	 IMAGE_FILE_LINE_NUMS_STRIPPED | \
+	 IMAGE_FILE_LOCAL_SYMS_STRIPPED | \
+	 IMAGE_FILE_LARGE_ADDRESS_AWARE | \
+	 IMAGE_FILE_DEBUG_STRIPPED)
+#else
+#define PE_MACHINE	IMAGE_FILE_MACHINE_LOONGARCH32
+#define PE_MAGIC    IMAGE_NT_OPTIONAL_HDR32_MAGIC
+#define IMG_CHARACTERISTICS \
+	(IMAGE_FILE_EXECUTABLE_IMAGE | \
+	 IMAGE_FILE_LINE_NUMS_STRIPPED | \
+	 IMAGE_FILE_LOCAL_SYMS_STRIPPED | \
+	 IMAGE_FILE_DEBUG_STRIPPED)
+#endif
+
+	.section	.text.head
+
+	/*
+	 * Magic "MZ" signature for PE/COFF
+	 */
+	.globl	ImageBase
+ImageBase:
+	.short	IMAGE_DOS_SIGNATURE		/* 'MZ' */
+	.skip	58
+	.long	pe_header - ImageBase		/* Offset to the PE header */
+pe_header:
+	.long	IMAGE_NT_SIGNATURE		/* 'PE' */
+coff_header:
+	.short	PE_MACHINE			/* LoongArch 64/32-bit */
+	.short	3				/* nr_sections */
+	.long	0				/* TimeDateStamp */
+	.long	0				/* PointerToSymbolTable */
+	.long	0				/* NumberOfSymbols */
+	.short	section_table - optional_header	/* SizeOfOptionalHeader */
+	.short	IMG_CHARACTERISTICS		/* Characteristics */
+optional_header:
+	.short	PE_MAGIC			/* PE32(+) format */
+	.byte	0x02				/* MajorLinkerVersion */
+	.byte	0x14				/* MinorLinkerVersion */
+	.long	_edata - _start			/* SizeOfCode */
+	.long	0				/* SizeOfInitializedData */
+	.long	0				/* SizeOfUninitializedData */
+	.long	_start - ImageBase		/* AddressOfEntryPoint */
+	.long	_start - ImageBase		/* BaseOfCode */
+#ifndef __loongarch64
+	.long	0				/* BaseOfData */
+#endif
+
+extra_header_fields:
+	LONG	0
+	.long	0x200				/* SectionAlignment */
+	.long	0x200				/* FileAlignment */
+	.short	0				/* MajorOperatingSystemVersion */
+	.short	0				/* MinorOperatingSystemVersion */
+	.short	1				/* MajorImageVersion */
+	.short	0				/* MinorImageVersion */
+	.short	0				/* MajorSubsystemVersion */
+	.short	0				/* MinorSubsystemVersion */
+	.long	0				/* Win32VersionValue */
+
+	.long	_edata - ImageBase		/* SizeOfImage */
+
+	/*
+	 * Everything before the kernel image is considered part of the header
+	 */
+	.long	_start - ImageBase		/* SizeOfHeaders */
+	.long	0				/* CheckSum */
+	.short	IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */
+#if CONFIG_VENDOR_EFI
+	.short	0				/* DllCharacteristics */
+#else
+	.short	IMAGE_DLLCHARACTERISTICS_NX_COMPAT
+#endif
+	LONG	0				/* SizeOfStackReserve */
+	LONG	0				/* SizeOfStackCommit */
+	LONG	0				/* SizeOfHeapReserve */
+	LONG	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 */
+
+	/* 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 */
+	.long	0x42100040		/* Characteristics (section flags) */
+
+
+	.ascii	".text"
+	.byte	0
+	.byte	0
+	.byte	0			/* end of 0 padding of section name */
+	.long	_etext - _start		/* VirtualSize */
+	.long	_start - ImageBase	/* VirtualAddress */
+	.long	_etext - _start		/* SizeOfRawData */
+	.long	_start - ImageBase	/* PointerToRawData */
+	.long	0			/* PointerToRelocations (0 for executables) */
+	.long	0			/* PointerToLineNumbers (0 for executables) */
+	.short	0			/* NumberOfRelocations  (0 for executables) */
+	.short	0			/* NumberOfLineNumbers  (0 for executables) */
+	/* 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	_edata - _data		/* VirtualSize */
+	.long	_data - ImageBase	/* VirtualAddress */
+	.long	_edata - _data		/* SizeOfRawData */
+	.long	_data - ImageBase	/* 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
+	.globl	_start
+	.type	_start, @function
+_start:
+	PTR_ADDI	sp, sp, -(3 * LONGSIZE)
+	LONG_S		ra, sp, 0
+	LONG_S		a0, sp, (1 * LONGSIZE)
+	LONG_S		a1, sp, (2 * LONGSIZE)
+
+	move		a2, a0		/* a2: ImageHandle */
+	move		a3, a1		/* a3: SystemTable */
+	la.local	a0, ImageBase	/* a0: ImageBase */
+	la.local	a1, _DYNAMIC	/* a1: DynamicSection */
+	bl 	  	_relocate
+	bnez		a0, 0f
+
+	LONG_L		a0, sp, (1 * LONGSIZE)
+	LONG_L		a1, sp, (2 * LONGSIZE)
+	bl		efi_main
+
+0:	LONG_L		ra, sp, 0
+	PTR_ADDI	sp, sp, (3 * LONGSIZE)
+	jr			ra
+	.end	  _start
diff --git a/arch/loongarch/lib/elf_loongarch_efi.lds b/arch/loongarch/lib/elf_loongarch_efi.lds
new file mode 100644
index 000000000000..050e5a52a0b3
--- /dev/null
+++ b/arch/loongarch/lib/elf_loongarch_efi.lds
@@ -0,0 +1,76 @@ 
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * U-Boot LoongArch
+ *
+ * Modified from arch/riscv/lib/elf_riscv64_efi.lds
+ */
+
+OUTPUT_ARCH(loongarch)
+
+PHDRS
+{
+	data PT_LOAD FLAGS(3); /* SHF_WRITE | SHF_ALLOC */
+}
+
+ENTRY(_start)
+SECTIONS
+{
+	.text 0x0 : {
+		_text = .;
+		*(.text.head)
+		*(.text)
+		*(.text.*)
+		*(.gnu.linkonce.t.*)
+		*(.srodata)
+		*(.rodata*)
+		. = ALIGN(16);
+		*(.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(4096);
+	.data : {
+		_data = .;
+		*(.sdata)
+		*(.data)
+		*(.data1)
+		*(.data.*)
+		*(.got.plt)
+		*(.got)
+
+		/*
+		 * The EFI loader doesn't seem to like a .bss section, so we
+		 * stick it all into .data:
+		 */
+		. = ALIGN(16);
+		_bss = .;
+		*(.sbss)
+		*(.scommon)
+		*(.dynbss)
+		*(.bss)
+		*(.bss.*)
+		*(COMMON)
+		. = ALIGN(512);
+		_bss_end = .;
+		_edata = .;
+	} :data
+	_data_size = _edata - _data;
+
+	. = ALIGN(4096);
+	.dynsym   : { *(.dynsym) }
+	. = ALIGN(4096);
+	.dynstr   : { *(.dynstr) }
+	. = ALIGN(4096);
+	.note.gnu.build-id : { *(.note.gnu.build-id) }
+	/DISCARD/ : {
+		*(.rel.reloc)
+		*(.eh_frame)
+		*(.note.GNU-stack)
+	}
+	.comment 0 : { *(.comment) }
+}
diff --git a/arch/loongarch/lib/reloc_loongarch_efi.c b/arch/loongarch/lib/reloc_loongarch_efi.c
new file mode 100644
index 000000000000..32a7d792103d
--- /dev/null
+++ b/arch/loongarch/lib/reloc_loongarch_efi.c
@@ -0,0 +1,107 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/* reloc_loongarch.c - position independent ELF shared object relocator
+   Copyright (C) 2018 Alexander Graf <agraf@suse.de>
+   Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+   Copyright (C) 1999 Hewlett-Packard Co.
+	Contributed by David Mosberger <davidm@hpl.hp.com>.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials
+      provided with the distribution.
+    * Neither the name of Hewlett-Packard Co. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+    BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+*/
+
+#include <efi.h>
+
+#include <elf.h>
+
+#ifdef __loongarch64
+#define Elf_Dyn		Elf64_Dyn
+#define Elf_Rela	Elf64_Rela
+#define ELF_R_TYPE	ELF64_R_TYPE
+#else
+#define Elf_Dyn		Elf32_Dyn
+#define Elf_Rela	Elf32_Rela
+#define ELF_R_TYPE	ELF32_R_TYPE
+#endif
+
+efi_status_t EFIAPI _relocate(long ldbase, Elf_Dyn *dyn)
+{
+	long relsz = 0, relent = 0;
+	Elf_Rela *rel = 0;
+	unsigned long *addr;
+	int i;
+
+	for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+		switch (dyn[i].d_tag) {
+		case DT_RELA:
+			rel = (Elf_Rela *)
+				((unsigned long)dyn[i].d_un.d_ptr
+					+ ldbase);
+			break;
+		case DT_RELASZ:
+			relsz = dyn[i].d_un.d_val;
+			break;
+		case DT_RELAENT:
+			relent = dyn[i].d_un.d_val;
+			break;
+		case DT_PLTGOT:
+			addr = (unsigned long *)
+				((unsigned long)dyn[i].d_un.d_ptr
+					+ ldbase);
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (!rel && relent == 0)
+		return EFI_SUCCESS;
+
+	if (!rel || relent == 0)
+		return EFI_LOAD_ERROR;
+
+	while (relsz > 0) {
+		/* apply the relocs */
+		switch (ELF_R_TYPE(rel->r_info)) {
+		case R_LARCH_NONE:
+			break;
+		case R_LARCH_RELATIVE:
+			addr = (unsigned long *)
+				(ldbase + rel->r_offset);
+			*addr += ldbase;
+			break;
+		default:
+			break;
+		}
+		rel = (Elf_Rela *)((char *)rel + relent);
+		relsz -= relent;
+	}
+	return EFI_SUCCESS;
+}
+
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 430bb7f0f7dc..1d82a062a215 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -5,7 +5,7 @@  config EFI_LOADER
 			SYS_CPU = arm1176 || \
 			SYS_CPU = armv7   || \
 			SYS_CPU = armv8)  || \
-		X86 || RISCV || SANDBOX)
+		X86 || RISCV || LOONGARCH || SANDBOX)
 	# We need EFI_STUB_64BIT to be set on x86_64 with EFI_STUB
 	depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT
 	# We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB