Implement crt, reloc, linker scripts, wire things up in
Makefiles and Kconfig.

Signed-off-by: Jiaxun Yang <jiaxun.y...@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.y...@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 <ag...@suse.de>
+   Copyright (C) 2014 Linaro Ltd. <ard.biesheu...@linaro.org>
+   Copyright (C) 1999 Hewlett-Packard Co.
+       Contributed by David Mosberger <dav...@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

-- 
2.43.0

Reply via email to