New Upstream Release - gnu-efi

Ready changes

Summary

Merged new upstream version: 3.0.17 (was: 3.0.15).

Diff

diff --git a/Make.defaults b/Make.defaults
index 47ed361..1277d14 100755
--- a/Make.defaults
+++ b/Make.defaults
@@ -45,10 +45,24 @@ TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
 # Where to install the package. GNU-EFI will create and access
 # lib and include under the root
 #
-INSTALLROOT  := /
+DESTDIR ?= /
+ifeq ($(origin INSTALLROOT),undefined)
+INSTALLROOT = $(DESTDIR)
+endif
+
+empty :=
+space := $(empty) $(empty)
+stripped = $(subst $(space),/,$(strip $(subst /,$(space),$(1))))
+unstripped = $(subst $(space),/,$(subst /,$(space),$(1)))
+is_absolute = $(subst $(call stripped,$(1)),$(empty),$(call unstripped,$(1)))
+
+override INSTALLROOT:=$(if $(call is_absolute,$(INSTALLROOT)),,$(TOPDIR)/)$(INSTALLROOT)
+
 PREFIX       := /usr/local
-LIBDIR 	     := $(PREFIX)/lib
-INSTALL	     := install
+EXEC_PREFIX  := $(PREFIX)
+LIBDIR 	 := $(EXEC_PREFIX)/lib
+INCLUDEDIR   := $(PREFIX)/include
+INSTALL	 := install
 
 # Compilation tools
 HOSTCC       := $(prefix)gcc
@@ -139,41 +153,42 @@ endif
 # Set HAVE_EFI_OBJCOPY if objcopy understands --target efi-[app|bsdrv|rtdrv],
 # otherwise we need to compose the PE/COFF header using the assembler
 #
-ifneq ($(ARCH),aarch64)
 ifneq ($(ARCH),arm)
 ifneq ($(ARCH),mips64el)
 ifneq ($(ARCH),riscv64)
+ifneq ($(ARCH),loongarch64)
 export HAVE_EFI_OBJCOPY=y
 endif
 endif
 endif
 endif
 
-ifneq ($(ARCH),arm)
-export LIBGCC=$(shell $(CC) $(ARCH3264) -print-libgcc-file-name)
-endif
-
 ifeq ($(ARCH),arm)
 CFLAGS += -marm
 endif
 
+ifeq ($(ARCH),aarch64)
+LDFLAGS += -z common-page-size=4096
+LDFLAGS += -z max-page-size=4096
+endif
+
 # Generic compilation flags
 INCDIR  += -I$(SRCDIR) -I$(TOPDIR)/inc -I$(TOPDIR)/inc/$(ARCH) \
            -I$(TOPDIR)/inc/protocol
 
-# Only enable -fpic for non MinGW compilers (unneeded on MinGW)
+# Only enable -fPIE for non MinGW compilers (unneeded on MinGW)
 GCCMACHINE := $(shell $(CC) -dumpmachine)
 ifneq (mingw32,$(findstring mingw32, $(GCCMACHINE)))
-  CFLAGS += -fpic
+  CFLAGS += -fPIE
 endif
 
 ifeq (FreeBSD, $(findstring FreeBSD, $(OS)))
 CFLAGS  += $(ARCH3264) -g -O2 -Wall -Wextra -Werror \
-           -fshort-wchar -fno-strict-aliasing \
+           -funsigned-char -fshort-wchar -fno-strict-aliasing \
            -ffreestanding -fno-stack-protector
 else
-CFLAGS  += $(ARCH3264) -g -O2 -Wall -Wextra -Werror \
-           -fshort-wchar -fno-strict-aliasing \
+CFLAGS  += $(ARCH3264) -g -O2 -Wall -Wextra -Wno-pointer-sign -Werror \
+           -funsigned-char -fshort-wchar -fno-strict-aliasing \
 	   -ffreestanding -fno-stack-protector -fno-stack-check \
            -fno-stack-check \
            $(if $(findstring gcc,$(CC)),-fno-merge-all-constants,)
@@ -183,3 +198,7 @@ ARFLAGS := rDv
 ASFLAGS += $(ARCH3264)
 LDFLAGS	+= -nostdlib --warn-common --no-undefined --fatal-warnings \
 	   --build-id=sha1
+
+ifneq ($(ARCH),arm)
+export LIBGCC=$(shell $(CC) $(CFLAGS) $(ARCH3264) -print-libgcc-file-name)
+endif
diff --git a/Makefile b/Makefile
index 897628b..e58d02a 100644
--- a/Makefile
+++ b/Makefile
@@ -34,7 +34,7 @@
 #    SUCH DAMAGE.
 #
 
-VERSION = 3.0.15
+export VERSION = 3.0.17
 
 MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
 SRCDIR = $(dir $(MKFILE_PATH))
@@ -44,10 +44,12 @@ VPATH = $(SRCDIR)
 include $(SRCDIR)/Make.defaults
 
 SUBDIRS = lib gnuefi inc apps
-gnuefi: lib
 
 all:	check_gcc $(SUBDIRS)
 
+gnuefi: lib
+apps:	gnuefi
+
 mkvars:
 	@echo AR=$(AR)
 	@echo ARCH=$(ARCH)
@@ -81,14 +83,14 @@ $(SUBDIRS):
 
 clean:
 	rm -f *~
-	@for d in $(SUBDIRS); do \
+	@set -e ; for d in $(SUBDIRS); do \
 		if [ -d $(OBJDIR)/$$d ]; then \
 			$(MAKE) -C $(OBJDIR)/$$d -f $(SRCDIR)/$$d/Makefile SRCDIR=$(SRCDIR)/$$d clean; \
 		fi; \
 	done
 
 install:
-	@for d in $(SUBDIRS); do \
+	@set -e ; for d in $(SUBDIRS); do \
 		mkdir -p $(OBJDIR)/$$d; \
 		$(MAKE) -C $(OBJDIR)/$$d -f $(SRCDIR)/$$d/Makefile SRCDIR=$(SRCDIR)/$$d install; done
 
diff --git a/apps/Makefile b/apps/Makefile
index 4e1b69a..6ebd438 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -44,6 +44,7 @@ TOPDIR = $(SRCDIR)/..
 
 CDIR=$(TOPDIR)/..
 LINUX_HEADERS	= /usr/src/sys/build
+APPSDIR		= $(LIBDIR)/gnuefi/apps
 CPPFLAGS	+= -D__KERNEL__ -I$(LINUX_HEADERS)/include
 CRTOBJS		= ../gnuefi/crt0-efi-$(ARCH).o
 
@@ -62,7 +63,8 @@ TARGET_APPS = t.efi t2.efi t3.efi t4.efi t5.efi t6.efi \
 	      printenv.efi t7.efi t8.efi tcc.efi modelist.efi \
 	      route80h.efi drv0_use.efi AllocPages.efi exit.efi \
 	      FreePages.efi setjmp.efi debughook.efi debughook.efi.debug \
-	      bltgrid.efi lfbgrid.efi setdbg.efi unsetdbg.efi
+	      bltgrid.efi lfbgrid.efi setdbg.efi unsetdbg.efi \
+	      ctors_test.efi
 TARGET_BSDRIVERS = drv0.efi
 TARGET_RTDRIVERS =
 
@@ -87,9 +89,15 @@ TARGETS = $(TARGET_APPS) $(TARGET_BSDRIVERS) $(TARGET_RTDRIVERS)
 
 all:	$(TARGETS)
 
+ctors_test.so : ctors_fns.o ctors_test.o
+
 clean:
 	rm -f $(TARGETS) *~ *.o *.so
 
+install:
+	mkdir -p $(INSTALLROOT)$(APPSDIR)
+	$(INSTALL) -m 644 $(TARGETS) $(INSTALLROOT)$(APPSDIR)
+
 .PHONY: install
 
 include $(SRCDIR)/../Make.rules
diff --git a/apps/bltgrid.c b/apps/bltgrid.c
index 4500fbb..ff69753 100644
--- a/apps/bltgrid.c
+++ b/apps/bltgrid.c
@@ -64,7 +64,8 @@ draw_boxes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
 		if (CompareMem(info, gop->Mode->Info, sizeof (*info)))
 			continue;
 
-		NumPixels = info->VerticalResolution * info->HorizontalResolution;
+		NumPixels = (UINTN)info->VerticalResolution
+                            * (UINTN)info->HorizontalResolution;
 		BufferSize = NumPixels * sizeof(UINT32);
 
 		PixelBuffer = AllocatePool(BufferSize);
diff --git a/apps/ctors_fns.c b/apps/ctors_fns.c
new file mode 100644
index 0000000..6241904
--- /dev/null
+++ b/apps/ctors_fns.c
@@ -0,0 +1,26 @@
+/*
+ * ctors.c
+ * Copyright 2019 Peter Jones <pjones@redhat.com>
+ *
+ */
+
+#include <efi.h>
+#include <efilib.h>
+
+int constructed_value = 0;
+
+static void __attribute__((__constructor__)) ctor(void)
+{
+	Print(L"%a:%d:%a() constructed_value:%d\n", __FILE__, __LINE__, __func__, constructed_value);
+	constructed_value = 1;
+	Print(L"%a:%d:%a() constructed_value:%d\n", __FILE__, __LINE__, __func__, constructed_value);
+}
+
+static void __attribute__((__destructor__)) dtor(void)
+{
+	Print(L"%a:%d:%a() constructed_value:%d\n", __FILE__, __LINE__, __func__, constructed_value);
+	constructed_value = 0;
+	Print(L"%a:%d:%a() constructed_value:%d\n", __FILE__, __LINE__, __func__, constructed_value);
+}
+
+// vim:fenc=utf-8:tw=75:noet
diff --git a/apps/ctors_test.c b/apps/ctors_test.c
new file mode 100644
index 0000000..7e48da8
--- /dev/null
+++ b/apps/ctors_test.c
@@ -0,0 +1,20 @@
+/*
+ * ctors_test.c
+ * Copyright 2019 Peter Jones <pjones@redhat.com>
+ *
+ */
+
+#include <efi.h>
+#include <efilib.h>
+
+extern int constructed_value;
+
+EFI_STATUS
+efi_main (EFI_HANDLE image EFI_UNUSED, EFI_SYSTEM_TABLE *systab EFI_UNUSED)
+{
+	Print(L"%a:%d:%a() constructed_value:%d\n", __FILE__, __LINE__, __func__, constructed_value);
+
+	return EFI_SUCCESS;
+}
+
+// vim:fenc=utf-8:tw=75:noet
diff --git a/apps/lfbgrid.c b/apps/lfbgrid.c
index 05977d2..3914313 100644
--- a/apps/lfbgrid.c
+++ b/apps/lfbgrid.c
@@ -51,10 +51,9 @@ draw_boxes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
 	UINTN NumPixels;
 	UINT32 *PixelBuffer;
 	UINT32 CopySize, BufferSize;
-#if defined(__x86_64__) || defined(__aarch64__) || \
-    (defined (__riscv) && __riscv_xlen == 64)
+#if __SIZEOF_POINTER__ == 8
 	UINT64 FrameBufferAddr;
-#elif defined(__i386__) || defined(__arm__)
+#elif __SIZEOF_POINTER__ == 4
 	UINT32 FrameBufferAddr;
 #else
 #error YOUR ARCH HERE
@@ -89,7 +88,8 @@ draw_boxes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
 		if (CompareMem(info, gop->Mode->Info, sizeof (*info)))
 			continue;
 
-		NumPixels = info->VerticalResolution * info->PixelsPerScanLine;
+		NumPixels = (UINTN)info->VerticalResolution
+                            * (UINTN)info->PixelsPerScanLine;
 		BufferSize = NumPixels * sizeof(UINT32);
 		if (BufferSize == gop->Mode->FrameBufferSize) {
 			CopySize = BufferSize;
@@ -115,10 +115,9 @@ draw_boxes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
 			Print(L"No linear framebuffer on this device.\n");
 			return;
 		}
-#if defined(__x86_64__) || defined(__aarch64__) || \
-    (defined (__riscv) && __riscv_xlen == 64)
+#if __SIZEOF_POINTER__ == 8
 		FrameBufferAddr = (UINT64)gop->Mode->FrameBufferBase;
-#elif defined(__i386__) || defined(__arm__)
+#elif __SIZEOF_POINTER__ == 4
 		FrameBufferAddr = (UINT32)(UINT64)gop->Mode->FrameBufferBase;
 #else
 #error YOUR ARCH HERE
diff --git a/debian/changelog b/debian/changelog
index da2a37c..d76026a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+gnu-efi (3.0.17-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Mon, 26 Jun 2023 20:02:07 -0000
+
 gnu-efi (3.0.15-1) unstable; urgency=medium
 
   * New upstream version 3.0.15
diff --git a/gnuefi/Makefile b/gnuefi/Makefile
index 10d4e7a..e0c9da8 100644
--- a/gnuefi/Makefile
+++ b/gnuefi/Makefile
@@ -43,6 +43,7 @@ include $(SRCDIR)/../Make.defaults
 TOPDIR = $(SRCDIR)/..
 
 CDIR=$(TOPDIR)/..
+PKGCONFIGDIR ?= $(LIBDIR)/pkgconfig
 FILES	= reloc_$(ARCH)  
 
 OBJS	= $(FILES:%=%.o)
@@ -52,11 +53,20 @@ reloc_aarch64.o: CFLAGS += -fno-jump-tables
 
 TARGETS	= crt0-efi-$(ARCH).o libgnuefi.a
 
-all:	$(TARGETS)
+all:	$(TARGETS) gnu-efi.pc
 
 libgnuefi.a: $(OBJS)
 	$(AR) $(ARFLAGS) $@ $^
 
+gnu-efi.pc:
+	sed \
+		-e 's:@PREFIX@:$(PREFIX):g' \
+		-e 's:@EXEC_PREFIX@:$(EXEC_PREFIX):g' \
+		-e 's:@INCLUDEDIR@:$(INCLUDEDIR):g' \
+		-e 's:@LIBDIR@:$(LIBDIR):g' \
+		-e 's:@VERSION@:$(VERSION):g' \
+	$(SRCDIR)/gnu-efi.pc.in > gnu-efi.pc
+
 
 clean:
 	rm -f $(TARGETS) *~ *.o $(OBJS)
@@ -73,5 +83,7 @@ ifneq (,$(findstring FreeBSD,$(OS)))
 else
 	$(INSTALL) -m 644 $(SRCDIR)/elf_$(ARCH)_efi.lds $(INSTALLROOT)$(LIBDIR)
 endif
+	$(INSTALL) -d $(INSTALLROOT)$(PKGCONFIGDIR)
+	$(INSTALL) -m 644 gnu-efi.pc $(INSTALLROOT)$(PKGCONFIGDIR)
 
 include $(SRCDIR)/../Make.rules
diff --git a/gnuefi/crt0-efi-aarch64.S b/gnuefi/crt0-efi-aarch64.S
index a0687b1..6016698 100644
--- a/gnuefi/crt0-efi-aarch64.S
+++ b/gnuefi/crt0-efi-aarch64.S
@@ -16,100 +16,10 @@
  * either version 2 of the License, or (at your option) any later version.
  */
 
-	.section	.text.head
-
-	/*
-	 * Magic "MZ" signature for PE/COFF
-	 */
-	.globl	ImageBase
-ImageBase:
-	.ascii	"MZ"
-	.skip	58				// 'MZ' + pad + offset == 64
-	.long	pe_header - ImageBase		// Offset to the PE header.
-pe_header:
-	.ascii	"PE"
-	.short 	0
-coff_header:
-	.short	0xaa64				// AArch64
-	.short	2				// nr_sections
-	.long	0 				// TimeDateStamp
-	.long	0				// PointerToSymbolTable
-	.long	0				// NumberOfSymbols
-	.short	section_table - optional_header	// SizeOfOptionalHeader
-	.short	0x206				// Characteristics.
-						// IMAGE_FILE_DEBUG_STRIPPED |
-						// IMAGE_FILE_EXECUTABLE_IMAGE |
-						// IMAGE_FILE_LINE_NUMS_STRIPPED
-optional_header:
-	.short	0x20b				// PE32+ format
-	.byte	0x02				// MajorLinkerVersion
-	.byte	0x14				// MinorLinkerVersion
-	.long	_data - _start			// SizeOfCode
-	.long	_data_size			// SizeOfInitializedData
-	.long	0				// SizeOfUninitializedData
-	.long	_start - ImageBase		// AddressOfEntryPoint
-	.long	_start - ImageBase		// BaseOfCode
-
-extra_header_fields:
-	.quad	0				// ImageBase
-	.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 - ImageBase		// SizeOfImage
-
-	// Everything before the kernel image is considered part of the header
-	.long	_start - ImageBase		// SizeOfHeaders
-	.long	0				// CheckSum
-	.short	EFI_SUBSYSTEM			// Subsystem
-	.short	0				// DllCharacteristics
-	.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
-
-	// Section table
-section_table:
-	.ascii	".text\0\0\0"
-	.long	_data - _start		// VirtualSize
-	.long	_start - ImageBase	// VirtualAddress
-	.long	_data - _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)
-	.long	0x60000020	// Characteristics (section flags)
-
-	.ascii	".data\0\0\0"
-	.long	_data_size		// VirtualSize
-	.long	_data - ImageBase	// VirtualAddress
-	.long	_data_size		// SizeOfRawData
-	.long	_data - 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)
-	.long	0xc0000040	// Characteristics (section flags)
-
+	.text
 	.align		12
+
+	.globl _start
 _start:
 	stp		x29, x30, [sp, #-32]!
 	mov		x29, sp
@@ -124,11 +34,24 @@ _start:
 	cbnz		x0, 0f
 
 	ldp		x0, x1, [sp, #16]
-	bl		efi_main
+	bl		_entry
 
 0:	ldp		x29, x30, [sp], #32
 	ret
 
+	// hand-craft a dummy .reloc section so EFI knows it's a relocatable executable:
+ 
+ 	.data
+dummy:	.long	0
+
+#define IMAGE_REL_ABSOLUTE	0
+ 	.section .reloc, "a"
+label1:
+	.long	dummy-label1				// Page RVA
+	.long	12					// Block Size (2*4+2*2), must be aligned by 32 Bits
+	.word	(IMAGE_REL_ABSOLUTE<<12) +  0		// reloc for dummy
+	.word	(IMAGE_REL_ABSOLUTE<<12) +  0		// reloc for dummy
+
 #if defined(__ELF__) && defined(__linux__)
 	.section .note.GNU-stack,"",%progbits
 #endif
diff --git a/gnuefi/crt0-efi-arm.S b/gnuefi/crt0-efi-arm.S
index ea3bbc4..716699b 100644
--- a/gnuefi/crt0-efi-arm.S
+++ b/gnuefi/crt0-efi-arm.S
@@ -136,7 +136,7 @@ _start:
 	bne		0f
 
 	ldmfd		sp, {r0-r1}
-	bl		efi_main
+	bl		_entry
 
 0:	add		sp, sp, #12
 	ldr		pc, [sp], #4
diff --git a/gnuefi/crt0-efi-ia32.S b/gnuefi/crt0-efi-ia32.S
index 9e9c865..df3340a 100644
--- a/gnuefi/crt0-efi-ia32.S
+++ b/gnuefi/crt0-efi-ia32.S
@@ -56,13 +56,13 @@ _start:
 	call _relocate
 	popl %ebx
 	popl %ebx
- 	testl %eax,%eax
- 	jne .exit
+	testl %eax,%eax
+	jne .exit
   
-  	call efi_main			# call app with "image" and "systab" argument
+	call _entry			# call app with "image" and "systab" argument
 
 .exit:	leave
-  	ret
+	ret
  
  	// hand-craft a dummy .reloc section so EFI knows it's a relocatable executable:
  
diff --git a/gnuefi/crt0-efi-ia64.S b/gnuefi/crt0-efi-ia64.S
index 38af615..30714d3 100644
--- a/gnuefi/crt0-efi-ia64.S
+++ b/gnuefi/crt0-efi-ia64.S
@@ -56,7 +56,7 @@ _start:
 
 	mov out0=in0			// image handle
 	mov out1=in1			// systab
-	br.call.sptk.few rp=efi_main
+	br.call.sptk.few rp=_entry
 .Lret2:
 .exit:
 	mov ar.pfs=loc0
diff --git a/gnuefi/crt0-efi-loongarch64.S b/gnuefi/crt0-efi-loongarch64.S
new file mode 100644
index 0000000..af45d46
--- /dev/null
+++ b/gnuefi/crt0-efi-loongarch64.S
@@ -0,0 +1,151 @@
+/*
+ * crt0-efi-loongarch64.S - PE/COFF header for LoongArch64 EFI applications
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited. <zhoumingtao@loongson.cn>
+ * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice and this list of conditions, without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef EFI_SUBSYSTEM
+#define EFI_SUBSYSTEM 0xa
+#endif
+	.section	.text.head
+
+	/*
+	 * Magic "MZ" signature for PE/COFF
+	 */
+	.globl	ImageBase
+ImageBase:
+	.ascii	"MZ"
+	.skip	58				// 'MZ' + pad + offset == 64
+	.long	pe_header - ImageBase		// Offset to the PE header.
+pe_header:
+	.ascii	"PE"
+	.short 	0
+coff_header:
+	.short	0x6264				// loongarch64 little endian
+	.short	2				// nr_sections
+	.long	0 				// TimeDateStamp
+	.long	0				// PointerToSymbolTable
+	.long	1				// NumberOfSymbols
+	.short	section_table - optional_header	// SizeOfOptionalHeader
+	.short	0x206				// Characteristics.
+						// IMAGE_FILE_DEBUG_STRIPPED |
+						// IMAGE_FILE_EXECUTABLE_IMAGE |
+						// IMAGE_FILE_LINE_NUMS_STRIPPED
+optional_header:
+	.short	0x20b				// 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
+
+extra_header_fields:
+	.quad	0				// ImageBase
+	.long	0x20				// SectionAlignment
+	.long	0x8				// FileAlignment
+	.short	0				// MajorOperatingSystemVersion
+	.short	0				// MinorOperatingSystemVersion
+	.short	0				// 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	EFI_SUBSYSTEM			// Subsystem
+	.short	0				// DllCharacteristics
+	.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
+
+	// 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	_edata - _start		// VirtualSize
+	.long	_start - ImageBase	// VirtualAddress
+	.long	_edata - _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)
+	.long	0xe0500020		// Characteristics (section flags)
+
+	.align  4
+
+	.globl	_start
+	.type	_start, @function
+_start:
+	addi.d	  $sp, $sp, -24
+	st.d	  $ra, $sp, 0
+	st.d	  $a0, $sp, 8
+	st.d 	  $a1, $sp, 16
+
+	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
+
+	ld.d	  $a0, $sp, 8
+	ld.d	  $a1, $sp, 16
+	bl        efi_main
+
+0:	ld.d	  $ra, $sp, 0
+	addi.d	  $sp, $sp, 24
+	jr	      $ra
+	.end	  _start
diff --git a/gnuefi/crt0-efi-mips64el.S b/gnuefi/crt0-efi-mips64el.S
index 4b2c1b2..cecabfb 100644
--- a/gnuefi/crt0-efi-mips64el.S
+++ b/gnuefi/crt0-efi-mips64el.S
@@ -172,8 +172,8 @@ _pc:
 
 	// a0: ImageHandle
 	ld		$a0, 16($sp)
-	// call efi_main
-	dla		$t9, efi_main
+	// call _start
+	dla		$t9, _entry
 	jalr		$t9
 	// a1: SystemTable
 	ld		$a1, 24($sp)
diff --git a/gnuefi/crt0-efi-riscv64.S b/gnuefi/crt0-efi-riscv64.S
index 0a5b7fc..2322b56 100644
--- a/gnuefi/crt0-efi-riscv64.S
+++ b/gnuefi/crt0-efi-riscv64.S
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */
 /*
  * Copright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
  * Copright (C) 2018 Alexander Graf <agraf@suse.de>
diff --git a/gnuefi/crt0-efi-x86_64.S b/gnuefi/crt0-efi-x86_64.S
index 49f0a0d..5179439 100644
--- a/gnuefi/crt0-efi-x86_64.S
+++ b/gnuefi/crt0-efi-x86_64.S
@@ -56,7 +56,7 @@ _start:
 	popq %rdi
 	popq %rsi
 
-	call efi_main
+	call _entry
 	addq $8, %rsp
 
 .exit:	
diff --git a/gnuefi/elf_aarch64_efi.lds b/gnuefi/elf_aarch64_efi.lds
index 836d982..563e22d 100644
--- a/gnuefi/elf_aarch64_efi.lds
+++ b/gnuefi/elf_aarch64_efi.lds
@@ -3,9 +3,17 @@ OUTPUT_ARCH(aarch64)
 ENTRY(_start)
 SECTIONS
 {
-  .text 0x0 : {
+  . = 0;
+  ImageBase = .;
+  /* .hash and/or .gnu.hash MUST come first! */
+  .hash : { *(.hash) }
+  .gnu.hash : { *(.gnu.hash) }
+  . = ALIGN(4096);
+  .eh_frame : { *(.eh_frame) }
+  .gcc_except_table : { *(.gcc_except_table*) }
+  . = ALIGN(4096);
+  .text : {
     _text = .;
-    *(.text.head)
     *(.text)
     *(.text.*)
     *(.gnu.linkonce.t.*)
@@ -15,8 +23,15 @@ SECTIONS
   }
   _etext = .;
   _text_size = . - _text;
+  . = ALIGN(4096);
+  .reloc :
+  {
+    KEEP (*(.reloc))
+  }
+  . = ALIGN(65536);
   .dynamic  : { *(.dynamic) }
-  .data : ALIGN(4096)
+  . = ALIGN(4096);
+  .data :
   {
    _data = .;
    *(.sdata)
@@ -26,6 +41,26 @@ SECTIONS
    *(.got.plt)
    *(.got)
 
+   /*
+    * Note that these aren't the using the GNU "CONSTRUCTOR" output section
+    * command, so they don't start with a size.  Because of p2align and the
+    * end/END definitions, and the fact that they're mergeable, they can also
+    * have NULLs which aren't guaranteed to be at the end.
+    */
+   . = ALIGN(16);
+   _init_array = .;
+   *(SORT_BY_NAME(.init_array))
+   _init_array_end = .;
+   __CTOR_LIST__ = .;
+   *(SORT_BY_NAME(.ctors))
+   __CTOR_END__ = .;
+   __DTOR_LIST__ = .;
+   *(SORT_BY_NAME(.dtors))
+   __DTOR_END__ = .;
+   _fini_array = .;
+   *(SORT_BY_NAME(.fini_array))
+   _fini_array_end = .;
+
    /* the EFI loader doesn't seem to like a .bss section, so we stick
       it all into .data: */
    . = ALIGN(16);
@@ -33,16 +68,25 @@ SECTIONS
    *(.sbss)
    *(.scommon)
    *(.dynbss)
-   *(.bss)
+   *(.bss*)
    *(COMMON)
+   *(.rel.local)
    . = ALIGN(16);
+
    _bss_end = .;
   }
 
-  .rela.dyn : { *(.rela.dyn) }
+  . = ALIGN(4096);
+  .rela :
+  {
+    *(.rela.text*)
+    *(.rela.data*)
+    *(.rela.got)
+    *(.rela.dyn)
+    *(.rela.stab)
+  }
+  . = ALIGN(4096);
   .rela.plt : { *(.rela.plt) }
-  .rela.got : { *(.rela.got) }
-  .rela.data : { *(.rela.data) *(.rela.data*) }
   . = ALIGN(512);
   _edata = .;
   _data_size = . - _data;
@@ -53,10 +97,9 @@ SECTIONS
   .dynstr   : { *(.dynstr) }
   . = ALIGN(4096);
   .note.gnu.build-id : { *(.note.gnu.build-id) }
-  /DISCARD/ :
+  .ignored.reloc :
   {
-    *(.rel.reloc)
-    *(.eh_frame)
+    *(.rela.reloc)
     *(.note.GNU-stack)
   }
   .comment 0 : { *(.comment) }
diff --git a/gnuefi/elf_arm_efi.lds b/gnuefi/elf_arm_efi.lds
index 665bbdb..3023ebc 100644
--- a/gnuefi/elf_arm_efi.lds
+++ b/gnuefi/elf_arm_efi.lds
@@ -15,7 +15,9 @@ SECTIONS
   }
   _etext = .;
   _text_size = . - _text;
+  . = ALIGN(4096);
   .dynamic  : { *(.dynamic) }
+  . = ALIGN(4096);
   .data :
   {
    _data = .;
@@ -26,6 +28,26 @@ SECTIONS
    *(.got.plt)
    *(.got)
 
+   /*
+    * Note that these aren't the using the GNU "CONSTRUCTOR" output section
+    * command, so they don't start with a size.  Because of p2align and the
+    * end/END definitions, and the fact that they're mergeable, they can also
+    * have NULLs which aren't guaranteed to be at the end.
+    */
+   . = ALIGN(16);
+   _init_array = .;
+   *(SORT_BY_NAME(.init_array))
+   _init_array_end = .;
+   __CTOR_LIST__ = .;
+   *(SORT_BY_NAME(.ctors))
+   __CTOR_END__ = .;
+   __DTOR_LIST__ = .;
+   *(SORT_BY_NAME(.dtors))
+   __DTOR_END__ = .;
+   _fini_array = .;
+   *(SORT_BY_NAME(.fini_array))
+   _fini_array_end = .;
+
    /* the EFI loader doesn't seem to like a .bss section, so we stick
       it all into .data: */
    . = ALIGN(16);
@@ -40,10 +62,17 @@ SECTIONS
    _bss_end = .;
   }
 
-  .rel.dyn : { *(.rel.dyn) }
+  . = ALIGN(4096);
+  .rel :
+  {
+    *(.rel.text*)
+    *(.rel.data*)
+    *(.rel.got)
+    *(.rel.dyn)
+    *(.rel.stab)
+  }
+  . = ALIGN(4096);
   .rel.plt : { *(.rel.plt) }
-  .rel.got : { *(.rel.got) }
-  .rel.data : { *(.rel.data) *(.rel.data*) }
   _edata = .;
   _data_size = . - _etext;
 
diff --git a/gnuefi/elf_ia32_efi.lds b/gnuefi/elf_ia32_efi.lds
index f27fe5f..5eec529 100644
--- a/gnuefi/elf_ia32_efi.lds
+++ b/gnuefi/elf_ia32_efi.lds
@@ -8,6 +8,8 @@ SECTIONS
   /* .hash and/or .gnu.hash MUST come first! */
   .hash : { *(.hash) }
   .gnu.hash : { *(.gnu.hash) }
+  .eh_frame : { *(.eh_frame) }
+  .gcc_except_table : { *(.gcc_except_table*) }
   . = ALIGN(4096);
   .text :
   {
@@ -19,33 +21,41 @@ SECTIONS
   }
   _etext = .;
   _text_size = . - _text;
-  . = ALIGN(4096);
-  .sdata :
+  . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+  .data :
   {
    _data = .;
    *(.got.plt)
    *(.got)
-   *(.srodata)
-   *(.sdata)
-   *(.sbss)
-   *(.scommon)
-  }
-  . = ALIGN(4096);
-  .data :
-  {
    *(.rodata*)
    *(.data)
    *(.data1)
    *(.data.*)
-   *(.sdata)
-   *(.got.plt)
-   *(.got)
+
+   /*
+    * Note that these aren't the using the GNU "CONSTRUCTOR" output section
+    * command, so they don't start with a size.  Because of p2align and the
+    * end/END definitions, and the fact that they're mergeable, they can also
+    * have NULLs which aren't guaranteed to be at the end.
+    */
+   . = ALIGN(16);
+   _init_array = .;
+   *(SORT_BY_NAME(.init_array))
+   _init_array_end = .;
+   __CTOR_LIST__ = .;
+   *(SORT_BY_NAME(.ctors))
+   __CTOR_END__ = .;
+   __DTOR_LIST__ = .;
+   *(SORT_BY_NAME(.dtors))
+   __DTOR_END__ = .;
+   _fini_array = .;
+   *(SORT_BY_NAME(.fini_array))
+   _fini_array_end = .;
+
    /* the EFI loader doesn't seem to like a .bss section, so we stick
       it all into .data: */
-   *(.sbss)
-   *(.scommon)
    *(.dynbss)
-   *(.bss)
+   *(.bss*)
    *(COMMON)
   }
   .note.gnu.build-id : { *(.note.gnu.build-id) }
@@ -55,31 +65,34 @@ SECTIONS
   . = ALIGN(4096);
   .rel :
   {
-    *(.rel.data)
-    *(.rel.data.*)
+    *(.rel.text*)
+    *(.rel.data*)
     *(.rel.got)
+    *(.rel.dyn)
     *(.rel.stab)
     *(.data.rel.ro.local)
     *(.data.rel.local)
     *(.data.rel.ro)
     *(.data.rel*)
   }
+  . = ALIGN(4096);
+  .rel.plt : { *(.rel.plt) }
   _edata = .;
   _data_size = . - _etext;
   . = ALIGN(4096);
   .reloc :		/* This is the PECOFF .reloc section! */
   {
-    *(.reloc)
+    KEEP (*(.reloc))
   }
   . = ALIGN(4096);
   .dynsym   : { *(.dynsym) }
   . = ALIGN(4096);
   .dynstr   : { *(.dynstr) }
   . = ALIGN(4096);
+  . = DATA_SEGMENT_END (.);
   /DISCARD/ :
   {
     *(.rel.reloc)
-    *(.eh_frame)
     *(.note.GNU-stack)
   }
   .comment 0 : { *(.comment) }
diff --git a/gnuefi/elf_ia32_fbsd_efi.lds b/gnuefi/elf_ia32_fbsd_efi.lds
index cd309e2..9e9baec 100644
--- a/gnuefi/elf_ia32_fbsd_efi.lds
+++ b/gnuefi/elf_ia32_fbsd_efi.lds
@@ -40,6 +40,27 @@ SECTIONS
    *(.sdata)
    *(.got.plt)
    *(.got)
+
+   /*
+    * Note that these aren't the using the GNU "CONSTRUCTOR" output section
+    * command, so they don't start with a size.  Because of p2align and the
+    * end/END definitions, and the fact that they're mergeable, they can also
+    * have NULLs which aren't guaranteed to be at the end.
+    */
+   . = ALIGN(16);
+   _init_array = .;
+   *(SORT_BY_NAME(.init_array))
+   _init_array_end = .;
+   __CTOR_LIST__ = .;
+   *(SORT_BY_NAME(.ctors))
+   __CTOR_END__ = .;
+   __DTOR_LIST__ = .;
+   *(SORT_BY_NAME(.dtors))
+   __DTOR_END__ = .;
+   _fini_array = .;
+   *(SORT_BY_NAME(.fini_array))
+   _fini_array_end = .;
+
    /* the EFI loader doesn't seem to like a .bss section, so we stick
       it all into .data: */
    *(.sbss)
diff --git a/gnuefi/elf_ia64_efi.lds b/gnuefi/elf_ia64_efi.lds
index 190792a..e45799c 100644
--- a/gnuefi/elf_ia64_efi.lds
+++ b/gnuefi/elf_ia64_efi.lds
@@ -8,6 +8,8 @@ SECTIONS
   /* .hash and/or .gnu.hash MUST come first! */
   .hash : { *(.hash) }
   .gnu.hash : { *(.gnu.hash) }
+  .eh_frame : { *(.eh_frame) }
+  .gcc_except_table : { *(.gcc_except_table*) }
   . = ALIGN(4096);
   .text :
   {
@@ -19,7 +21,7 @@ SECTIONS
   }
   _etext = .;
   _text_size = . - _text;
-  . = ALIGN(4096);
+  . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
   __gp = ALIGN (8) + 0x200000;
   .sdata :
   {
@@ -39,10 +41,31 @@ SECTIONS
    *(.data*)
    *(.gnu.linkonce.d*)
    *(.plabel)	/* data whose relocs we want to ignore */
+
+   /*
+    * Note that these aren't the using the GNU "CONSTRUCTOR" output section
+    * command, so they don't start with a size.  Because of p2align and the
+    * end/END definitions, and the fact that they're mergeable, they can also
+    * have NULLs which aren't guaranteed to be at the end.
+    */
+   . = ALIGN(16);
+   _init_array = .;
+   *(SORT_BY_NAME(.init_array))
+   _init_array_end = .;
+   __CTOR_LIST__ = .;
+   *(SORT_BY_NAME(.ctors))
+   __CTOR_END__ = .;
+   __DTOR_LIST__ = .;
+   *(SORT_BY_NAME(.dtors))
+   __DTOR_END__ = .;
+   _fini_array = .;
+   *(SORT_BY_NAME(.fini_array))
+   _fini_array_end = .;
+
    /* the EFI loader doesn't seem to like a .bss section, so we stick
       it all into .data: */
    *(.dynbss)
-   *(.bss)
+   *(.bss*)
    *(COMMON)
   }
   .note.gnu.build-id : { *(.note.gnu.build-id) }
@@ -52,25 +75,29 @@ SECTIONS
   . = ALIGN(4096);
   .rela :
   {
-    *(.rela.text)
+    *(.rela.text*)
+    *(.rela.sdata*)
     *(.rela.data*)
-    *(.rela.sdata)
     *(.rela.got)
+    *(.rela.dyn)
     *(.rela.gnu.linkonce.d*)
     *(.rela.stab)
     *(.rela.ctors)
   }
+  . = ALIGN(4096);
+  .rela.plt : { *(.rela.plt) }
   _edata = .;
   _data_size = . - _etext;
   . = ALIGN(4096);
   .reloc :		/* This is the PECOFF .reloc section! */
   {
-    *(.reloc)
+    KEEP (*(.reloc))
   }
   . = ALIGN(4096);
   .dynsym   : { *(.dynsym) }
   . = ALIGN(4096);
   .dynstr   : { *(.dynstr) }
+  . = DATA_SEGMENT_END (.);
   /DISCARD/ :
   {
     *(.rela.plabel)
diff --git a/gnuefi/elf_loongarch64_efi.lds b/gnuefi/elf_loongarch64_efi.lds
new file mode 100644
index 0000000..e7b4d6b
--- /dev/null
+++ b/gnuefi/elf_loongarch64_efi.lds
@@ -0,0 +1,63 @@
+OUTPUT_FORMAT("elf64-loongarch", "elf64-loongarch", "elf64-loongarch")
+OUTPUT_ARCH(loongarch)
+ENTRY(_start)
+SECTIONS
+{
+  .text 0x0 : {
+    _text = .;
+    *(.text.head)
+    *(.text)
+    *(.text.*)
+    *(.gnu.linkonce.t.*)
+    *(.srodata)
+    *(.rodata*)
+    . = ALIGN(16);
+  }
+  _etext = .;
+  _text_size = . - _text;
+  .dynamic  : { *(.dynamic) }
+  .data : ALIGN(4096)
+  {
+   _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)
+   *(COMMON)
+   . = ALIGN(16);
+   _bss_end = .;
+  }
+
+  .rela.dyn : { *(.rela.dyn) }
+  .rela.plt : { *(.rela.plt) }
+  .rela.got : { *(.rela.got) }
+  .rela.data : { *(.rela.data) *(.rela.data*) }
+  . = ALIGN(512);
+  _edata = .;
+  _data_size = . - _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/gnuefi/elf_mips64el_efi.lds b/gnuefi/elf_mips64el_efi.lds
index 4d1a077..bf96841 100644
--- a/gnuefi/elf_mips64el_efi.lds
+++ b/gnuefi/elf_mips64el_efi.lds
@@ -15,7 +15,9 @@ SECTIONS
   }
   _etext = .;
   _text_size = . - _text;
+  . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
   .dynamic  : { *(.dynamic) }
+  . = ALIGN(4096);
   .data :
   {
    _data = .;
@@ -27,6 +29,26 @@ SECTIONS
    HIDDEN (_gp = ALIGN (16) + 0x7ff0);
    *(.got)
 
+   /*
+    * Note that these aren't the using the GNU "CONSTRUCTOR" output section
+    * command, so they don't start with a size.  Because of p2align and the
+    * end/END definitions, and the fact that they're mergeable, they can also
+    * have NULLs which aren't guaranteed to be at the end.
+    */
+   . = ALIGN(16);
+   _init_array = .;
+   *(SORT_BY_NAME(.init_array))
+   _init_array_end = .;
+   __CTOR_LIST__ = .;
+   *(SORT_BY_NAME(.ctors))
+   __CTOR_END__ = .;
+   __DTOR_LIST__ = .;
+   *(SORT_BY_NAME(.dtors))
+   __DTOR_END__ = .;
+   _fini_array = .;
+   *(SORT_BY_NAME(.fini_array))
+   _fini_array_end = .;
+
    /* the EFI loader doesn't seem to like a .bss section, so we stick
       it all into .data: */
    . = ALIGN(16);
@@ -34,16 +56,23 @@ SECTIONS
    *(.sbss)
    *(.scommon)
    *(.dynbss)
-   *(.bss)
+   *(.bss*)
    *(COMMON)
    . = ALIGN(16);
    _bss_end = .;
   }
 
-  .rel.dyn : { *(.rel.dyn) }
+  . = ALIGN(4096);
+  .rel :
+  {
+    *(.rel.text*)
+    *(.rel.data*)
+    *(.rel.got)
+    *(.rel.dyn)
+    *(.rel.stab)
+  }
+  . = ALIGN(4096);
   .rel.plt : { *(.rel.plt) }
-  .rel.got : { *(.rel.got) }
-  .rel.data : { *(.rel.data) *(.rel.data*) }
   _edata = .;
   _data_size = . - _etext;
 
@@ -53,6 +82,7 @@ SECTIONS
   .dynstr   : { *(.dynstr) }
   . = ALIGN(4096);
   .note.gnu.build-id : { *(.note.gnu.build-id) }
+  . = DATA_SEGMENT_END (.);
   /DISCARD/ :
   {
     *(.rel.reloc)
diff --git a/gnuefi/elf_riscv64_efi.lds b/gnuefi/elf_riscv64_efi.lds
index bb64d81..3b47247 100644
--- a/gnuefi/elf_riscv64_efi.lds
+++ b/gnuefi/elf_riscv64_efi.lds
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */
 
 OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv")
 OUTPUT_ARCH(riscv)
@@ -17,6 +17,7 @@ SECTIONS {
 	}
 	_etext = .;
 	_text_size = . - _text;
+. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
 .dynamic  :
 	{ *(.dynamic) }
 .data :
@@ -37,22 +38,23 @@ SECTIONS {
 		*(.sbss)
 		*(.scommon)
 		*(.dynbss)
-		*(.bss)
+		*(.bss*)
 		*(COMMON)
 		. = ALIGN(16);
 		_bss_end = .;
 	}
 
-.rela.text :
-	{ *(.rela.text) *(.rela.text*) }
-.rela.dyn :
-	{ *(.rela.dyn) }
-.rela.plt :
-	{ *(.rela.plt) }
-.rela.got :
-	{ *(.rela.got) }
-.rela.data :
-	{ *(.rela.data) *(.rela.data*) }
+. = ALIGN(4096);
+.rela :
+  {
+    *(.rela.text*)
+    *(.rela.data*)
+    *(.rela.got)
+    *(.rela.dyn)
+    *(.rela.stab)
+  }
+. = ALIGN(4096);
+.rela.plt : { *(.rela.plt) }
 	. = ALIGN(512);
 	_edata = .;
 	_data_size = . - _data;
@@ -66,6 +68,7 @@ SECTIONS {
 	. = ALIGN(4096);
 .note.gnu.build-id :
 	{ *(.note.gnu.build-id) }
+. = DATA_SEGMENT_END (.);
 /DISCARD/ :
 	{
 		*(.rel.reloc)
diff --git a/gnuefi/elf_x86_64_efi.lds b/gnuefi/elf_x86_64_efi.lds
index 7be5902..2e0e0cb 100644
--- a/gnuefi/elf_x86_64_efi.lds
+++ b/gnuefi/elf_x86_64_efi.lds
@@ -10,10 +10,8 @@ SECTIONS
   .hash : { *(.hash) }
   .gnu.hash : { *(.gnu.hash) }
   . = ALIGN(4096);
-  .eh_frame : 
-  { 
-    *(.eh_frame)
-  }
+  .eh_frame : { *(.eh_frame) }
+  .gcc_except_table : { *(.gcc_except_table*) }
   . = ALIGN(4096);
   .text :
   {
@@ -28,8 +26,9 @@ SECTIONS
   . = ALIGN(4096);
   .reloc :
   {
-   *(.reloc)
+   KEEP (*(.reloc))
   }
+
   . = ALIGN(4096);
   .data :
   {
@@ -39,12 +38,33 @@ SECTIONS
    *(.got)
    *(.data*)
    *(.sdata)
+
+   /*
+    * Note that these aren't the using the GNU "CONSTRUCTOR" output section
+    * command, so they don't start with a size.  Because of p2align and the
+    * end/END definitions, and the fact that they're mergeable, they can also
+    * have NULLs which aren't guaranteed to be at the end.
+    */
+   . = ALIGN(16);
+   _init_array = .;
+   *(SORT_BY_NAME(.init_array))
+   _init_array_end = .;
+   __CTOR_LIST__ = .;
+   *(SORT_BY_NAME(.ctors))
+   __CTOR_END__ = .;
+   __DTOR_LIST__ = .;
+   *(SORT_BY_NAME(.dtors))
+   __DTOR_END__ = .;
+   _fini_array = .;
+   *(SORT_BY_NAME(.fini_array))
+   _fini_array_end = .;
+
    /* the EFI loader doesn't seem to like a .bss section, so we stick
       it all into .data: */
    *(.sbss)
    *(.scommon)
    *(.dynbss)
-   *(.bss)
+   *(.bss*)
    *(COMMON)
    *(.rel.local)
   }
@@ -57,11 +77,15 @@ SECTIONS
   . = ALIGN(4096);
   .rela :
   {
+    *(.rela.text*)
     *(.rela.data*)
     *(.rela.got)
+    *(.rela.dyn)
     *(.rela.stab)
   }
   . = ALIGN(4096);
+  .rela.plt : { *(.rela.plt) }
+  . = ALIGN(4096);
   .dynsym   : { *(.dynsym) }
   . = ALIGN(4096);
   .dynstr   : { *(.dynstr) }
@@ -69,7 +93,6 @@ SECTIONS
   .ignored.reloc :
   {
     *(.rela.reloc)
-    *(.eh_frame)
     *(.note.GNU-stack)
   }
   .comment 0 : { *(.comment) }
diff --git a/gnuefi/elf_x86_64_fbsd_efi.lds b/gnuefi/elf_x86_64_fbsd_efi.lds
index fe1f334..721ce9a 100644
--- a/gnuefi/elf_x86_64_fbsd_efi.lds
+++ b/gnuefi/elf_x86_64_fbsd_efi.lds
@@ -36,6 +36,27 @@ SECTIONS
    *(.got)
    *(.data*)
    *(.sdata)
+
+   /*
+    * Note that these aren't the using the GNU "CONSTRUCTOR" output section
+    * command, so they don't start with a size.  Because of p2align and the
+    * end/END definitions, and the fact that they're mergeable, they can also
+    * have NULLs which aren't guaranteed to be at the end.
+    */
+   . = ALIGN(16);
+   _init_array = .;
+   *(SORT_BY_NAME(.init_array))
+   _init_array_end = .;
+   __CTOR_LIST__ = .;
+   *(SORT_BY_NAME(.ctors))
+   __CTOR_END__ = .;
+   __DTOR_LIST__ = .;
+   *(SORT_BY_NAME(.dtors))
+   __DTOR_END__ = .;
+   _fini_array = .;
+   *(SORT_BY_NAME(.fini_array))
+   _fini_array_end = .;
+
    /* the EFI loader doesn't seem to like a .bss section, so we stick
       it all into .data: */
    *(.sbss)
diff --git a/gnuefi/gnu-efi.pc.in b/gnuefi/gnu-efi.pc.in
new file mode 100644
index 0000000..9280bc0
--- /dev/null
+++ b/gnuefi/gnu-efi.pc.in
@@ -0,0 +1,10 @@
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+includedir=@INCLUDEDIR@
+libdir=@LIBDIR@
+
+Name: gnu-efi
+Description: EFI development toolkit
+Version: @VERSION@
+Cflags: -I${includedir}/efi
+Libs: -lefi
diff --git a/gnuefi/reloc_loongarch64.c b/gnuefi/reloc_loongarch64.c
new file mode 100644
index 0000000..7860f9d
--- /dev/null
+++ b/gnuefi/reloc_loongarch64.c
@@ -0,0 +1,104 @@
+/* reloc_loongarch64.c - position independent loongarch64 ELF shared object relocator
+   Copyright (C) 2021 Loongson Technology Corporation Limited. <zhoumingtao@loongson.cn>
+   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 <efilib.h>
+
+#include <elf.h>
+
+EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn,
+                      EFI_HANDLE image EFI_UNUSED,
+                      EFI_SYSTEM_TABLE *systab EFI_UNUSED)
+{
+	long relsz = 0, relent = 0;
+	Elf64_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 = (Elf64_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 (ELF64_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 = (Elf64_Rela*) ((char *) rel + relent);
+		relsz -= relent;
+	}
+	return EFI_SUCCESS;
+}
diff --git a/gnuefi/reloc_riscv64.c b/gnuefi/reloc_riscv64.c
index 73e8d13..0b02d83 100644
--- a/gnuefi/reloc_riscv64.c
+++ b/gnuefi/reloc_riscv64.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
 /* reloc_riscv.c - position independent ELF shared object relocator
    Copyright (C) 2018 Alexander Graf <agraf@suse.de>
    Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
diff --git a/inc/Makefile b/inc/Makefile
index 273d303..db3929f 100644
--- a/inc/Makefile
+++ b/inc/Makefile
@@ -13,15 +13,15 @@ all:
 clean:
 
 install:
-	mkdir -p $(INSTALLROOT)$(PREFIX)/include/efi
-	mkdir -p $(INSTALLROOT)$(PREFIX)/include/efi/protocol
-	mkdir -p $(INSTALLROOT)$(PREFIX)/include/efi/$(ARCH)
-	$(INSTALL) -m 644 $(SRCDIR)/*.h $(INSTALLROOT)$(PREFIX)/include/efi
-	$(INSTALL) -m 644 $(SRCDIR)/protocol/*.h $(INSTALLROOT)$(PREFIX)/include/efi/protocol
-	$(INSTALL) -m 644 $(SRCDIR)/$(ARCH)/*.h $(INSTALLROOT)$(PREFIX)/include/efi/$(ARCH)
+	mkdir -p $(INSTALLROOT)$(INCLUDEDIR)/efi
+	mkdir -p $(INSTALLROOT)$(INCLUDEDIR)/efi/protocol
+	mkdir -p $(INSTALLROOT)$(INCLUDEDIR)/efi/$(ARCH)
+	$(INSTALL) -m 644 $(SRCDIR)/*.h $(INSTALLROOT)$(INCLUDEDIR)/efi
+	$(INSTALL) -m 644 $(SRCDIR)/protocol/*.h $(INSTALLROOT)$(INCLUDEDIR)/efi/protocol
+	$(INSTALL) -m 644 $(SRCDIR)/$(ARCH)/*.h $(INSTALLROOT)$(INCLUDEDIR)/efi/$(ARCH)
 ifeq ($(ARCH),ia64)
-	mkdir -p $(INSTALLROOT)$(PREFIX)/include/efi/protocol/ia64
-	$(INSTALL) -m 644 $(SRCDIR)/protocol/ia64/*.h $(INSTALLROOT)$(PREFIX)/include/efi/protocol/ia64
+	mkdir -p $(INSTALLROOT)$(INCLUDEDIR)/efi/protocol/ia64
+	$(INSTALL) -m 644 $(SRCDIR)/protocol/ia64/*.h $(INSTALLROOT)$(INCLUDEDIR)/efi/protocol/ia64
 endif
 
 include $(SRCDIR)/../Make.rules
diff --git a/inc/aarch64/efibind.h b/inc/aarch64/efibind.h
index c2c546b..d6b5d0f 100644
--- a/inc/aarch64/efibind.h
+++ b/inc/aarch64/efibind.h
@@ -38,9 +38,10 @@ typedef int64_t             intptr_t;
 // Basic EFI types of various widths
 //
 
-#ifndef __WCHAR_TYPE__
-# define __WCHAR_TYPE__ short
-#endif
+#include <stddef.h>
+
+typedef wchar_t CHAR16;
+#define WCHAR CHAR16
 
 typedef uint64_t   UINT64;
 typedef int64_t    INT64;
@@ -50,12 +51,13 @@ typedef int32_t    INT32;
 
 typedef uint16_t   UINT16;
 typedef int16_t    INT16;
+
 typedef uint8_t    UINT8;
+typedef char       CHAR8;
 typedef int8_t     INT8;
-typedef __WCHAR_TYPE__ WCHAR;
 
 #undef VOID
-#define VOID    void
+typedef void       VOID;
 
 typedef int64_t    INTN;
 typedef uint64_t   UINTN;
diff --git a/inc/aarch64/efisetjmp_arch.h b/inc/aarch64/efisetjmp_arch.h
index 8dbce07..d960706 100644
--- a/inc/aarch64/efisetjmp_arch.h
+++ b/inc/aarch64/efisetjmp_arch.h
@@ -18,6 +18,7 @@ typedef struct {
 	UINT64	FP;
 	UINT64	LR;
 	UINT64	IP0;
+	UINT64	_pad1;
 
 	/* FP regs */
 	UINT64	D8;
diff --git a/inc/arm/efibind.h b/inc/arm/efibind.h
index 9e2cb10..8c578df 100644
--- a/inc/arm/efibind.h
+++ b/inc/arm/efibind.h
@@ -46,9 +46,10 @@ typedef int32_t             intptr_t;
 // Basic EFI types of various widths
 //
 
-#ifndef __WCHAR_TYPE__
-# define __WCHAR_TYPE__ short
-#endif
+#include <stddef.h>
+
+typedef wchar_t CHAR16;
+#define WCHAR CHAR16
 
 typedef uint64_t   UINT64;
 typedef int64_t    INT64;
@@ -58,12 +59,13 @@ typedef int32_t    INT32;
 
 typedef uint16_t   UINT16;
 typedef int16_t    INT16;
+
 typedef uint8_t    UINT8;
+typedef char       CHAR8;
 typedef int8_t     INT8;
-typedef __WCHAR_TYPE__ WCHAR;
 
 #undef VOID
-#define VOID    void
+typedef void       VOID;
 
 typedef int32_t    INTN;
 typedef uint32_t   UINTN;
diff --git a/inc/efi.h b/inc/efi.h
index b193932..b251a34 100644
--- a/inc/efi.h
+++ b/inc/efi.h
@@ -52,6 +52,8 @@ Revision History
 #include "mips64el/efibind.h"
 #elif defined (__riscv) && __riscv_xlen == 64
 #include "riscv64/efibind.h"
+#elif defined (__loongarch64)
+#include "loongarch64/efibind.h"
 #else
 #error Usupported architecture
 #endif
diff --git a/inc/efiapi.h b/inc/efiapi.h
index 7dbedc4..01a0938 100644
--- a/inc/efiapi.h
+++ b/inc/efiapi.h
@@ -354,6 +354,14 @@ EFI_STATUS
 #define EFI_IMAGE_MACHINE_RISCV128  0x5128
 #endif
 
+#if !defined(EFI_IMAGE_MACHINE_LOONGARCH32)
+#define EFI_IMAGE_MACHINE_LOONGARCH32   0x6232
+#endif
+
+#if !defined(EFI_IMAGE_MACHINE_LOONGARCH64)
+#define EFI_IMAGE_MACHINE_LOONGARCH64   0x6264
+#endif
+
 // Image Entry prototype
 
 typedef 
diff --git a/inc/efidef.h b/inc/efidef.h
index 8b70051..5953b69 100644
--- a/inc/efidef.h
+++ b/inc/efidef.h
@@ -20,19 +20,39 @@ Revision History
 
 --*/
 
-typedef UINT16          CHAR16;
-typedef UINT8           CHAR8;
-typedef UINT8           BOOLEAN;
+#if !defined(__cplusplus)
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+typedef _Bool BOOLEAN;
+#else
+typedef unsigned char BOOLEAN;
+#endif
+#else
+typedef bool BOOLEAN;
+#endif
+
 #ifndef CONST
    #define CONST const
 #endif
 #ifndef TRUE
+#if defined(__cplusplus) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L)
+    #define TRUE    true
+    #define FALSE   false
+#else
     #define TRUE    ((BOOLEAN) 1)
     #define FALSE   ((BOOLEAN) 0)
 #endif
+#endif
 
 #ifndef NULL
+#if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L)
+    #define NULL    nullptr
+#else
+#if !defined(__cplusplus)
     #define NULL    ((VOID *) 0)
+#else
+    #define NULL    0
+#endif
+#endif
 #endif
 
 typedef UINTN           EFI_STATUS;
@@ -194,7 +214,7 @@ typedef struct {
 // International Language
 //
 
-typedef UINT8   ISO_639_2;
+typedef CHAR8 ISO_639_2;
 #define ISO_639_2_ENTRY_SIZE    3
 
 //
diff --git a/inc/efilib.h b/inc/efilib.h
index a2b39b2..e73177c 100644
--- a/inc/efilib.h
+++ b/inc/efilib.h
@@ -35,6 +35,8 @@ Revision History
 #include "mips64el/efilibplat.h"
 #elif defined (__riscv) && __riscv_xlen == 64
 #include "riscv64/efilibplat.h"
+#elif defined (__loongarch64)
+#include "loongarch64/efilibplat.h"
 #endif
 #include "efilink.h"
 #include "efirtlib.h"
diff --git a/inc/ia32/efibind.h b/inc/ia32/efibind.h
index 27459e4..718e8d1 100644
--- a/inc/ia32/efibind.h
+++ b/inc/ia32/efibind.h
@@ -85,9 +85,11 @@ Revision History
 // Basic EFI types of various widths
 //
 
-#ifndef __WCHAR_TYPE__
-# define __WCHAR_TYPE__ short
-#endif
+#include <stddef.h>
+
+typedef wchar_t CHAR16;
+#define WCHAR CHAR16
+
 
 typedef uint64_t   UINT64;
 typedef int64_t    INT64;
@@ -99,12 +101,13 @@ typedef int64_t    INT64;
 
 typedef uint16_t   UINT16;
 typedef int16_t    INT16;
+
 typedef uint8_t    UINT8;
+typedef char       CHAR8;
 typedef int8_t     INT8;
-typedef __WCHAR_TYPE__ WCHAR;
 
 #undef VOID
-#define VOID    void
+typedef void       VOID;
 
 
 typedef int32_t    INTN;
diff --git a/inc/ia64/efibind.h b/inc/ia64/efibind.h
index 3ace8d5..1d2745b 100644
--- a/inc/ia64/efibind.h
+++ b/inc/ia64/efibind.h
@@ -71,24 +71,27 @@ Revision History
 //
 // Basic EFI types of various widths
 //
-#ifndef __WCHAR_TYPE__
-# define __WCHAR_TYPE__	short
-#endif
 
+#include <stddef.h>
+
+typedef wchar_t CHAR16;
+#define WCHAR CHAR16
 
 typedef uint64_t   UINT64;
 typedef int64_t    INT64;
+
 typedef uint32_t   UINT32;
 typedef int32_t    INT32;
+
 typedef uint16_t   UINT16;
 typedef int16_t    INT16;
+
 typedef uint8_t    UINT8;
+typedef char       CHAR8;
 typedef int8_t     INT8;
-typedef __WCHAR_TYPE__ WCHAR;
-
 
 #undef VOID
-#define VOID    void
+typedef void       VOID;
 
 
 typedef int64_t    INTN;
diff --git a/inc/loongarch64/efibind.h b/inc/loongarch64/efibind.h
new file mode 100644
index 0000000..aaf3fb7
--- /dev/null
+++ b/inc/loongarch64/efibind.h
@@ -0,0 +1,157 @@
+/*
+ * Copright (C) 2014 - 2015 Linaro Ltd.
+ * Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+ * Copright (C) 2017 Lemote Co.
+ * Author: Heiher <r@hev.cc>
+ * Copright (C) 2021 Loongson Technology Corporation Limited.
+ * Author: zhoumingtao <zhoumingtao@loongson.cn>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice and this list of conditions, without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any later version.
+ */
+
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) && !defined(__cplusplus)
+
+// ANSI C 1999/2000 stdint.h integer width declarations
+
+typedef unsigned long       uint64_t;
+typedef long                int64_t;
+typedef unsigned int        uint32_t;
+typedef int                 int32_t;
+typedef unsigned short      uint16_t;
+typedef short               int16_t;
+typedef unsigned char       uint8_t;
+typedef signed char         int8_t;
+typedef uint64_t            uintptr_t;
+typedef int64_t             intptr_t;
+
+#else
+#include <stdint.h>
+#endif
+
+//
+// Basic EFI types of various widths
+//
+
+#ifndef __WCHAR_TYPE__
+# define __WCHAR_TYPE__ short
+#endif
+
+typedef uint64_t   UINT64;
+typedef int64_t    INT64;
+
+typedef uint32_t   UINT32;
+typedef int32_t    INT32;
+
+typedef uint16_t   UINT16;
+typedef int16_t    INT16;
+typedef uint8_t    UINT8;
+typedef int8_t     INT8;
+typedef __WCHAR_TYPE__ WCHAR;
+
+#undef VOID
+#define VOID    void
+
+typedef int64_t    INTN;
+typedef uint64_t   UINTN;
+
+#define EFIERR(a)           (0x8000000000000000 | a)
+#define EFI_ERROR_MASK      0x8000000000000000
+#define EFIERR_OEM(a)       (0xc000000000000000 | a)
+
+#define BAD_POINTER         0xFBFBFBFBFBFBFBFB
+#define MAX_ADDRESS         0xFFFFFFFFFFFFFFFF
+
+#define BREAKPOINT()        while (TRUE);    // Make it hang on Bios[Dbg]32
+
+//
+// Pointers must be aligned to these address to function
+//
+
+#define MIN_ALIGNMENT_SIZE  8
+
+#define ALIGN_VARIABLE(Value ,Adjustment) \
+            (UINTN)Adjustment = 0; \
+            if((UINTN)Value % MIN_ALIGNMENT_SIZE) \
+                (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \
+            Value = (UINTN)Value + (UINTN)Adjustment
+
+
+//
+// Define macros to build data structure signatures from characters.
+//
+
+#define EFI_SIGNATURE_16(A,B)             ((A) | (B<<8))
+#define EFI_SIGNATURE_32(A,B,C,D)         (EFI_SIGNATURE_16(A,B)     | (EFI_SIGNATURE_16(C,D)     << 16))
+#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
+
+//
+// EFIAPI - prototype calling convention for EFI function pointers
+// BOOTSERVICE - prototype for implementation of a boot service interface
+// RUNTIMESERVICE - prototype for implementation of a runtime service interface
+// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service
+// RUNTIME_CODE - pragma macro for declaring runtime code
+//
+
+#ifndef EFIAPI          // Forces EFI calling conventions reguardless of compiler options
+#define EFIAPI          // Substitute expresion to force C calling convention
+#endif
+
+#define BOOTSERVICE
+#define RUNTIMESERVICE
+#define RUNTIMEFUNCTION
+
+
+#define RUNTIME_CODE(a)         alloc_text("rtcode", a)
+#define BEGIN_RUNTIME_DATA()    data_seg("rtdata")
+#define END_RUNTIME_DATA()      data_seg("")
+
+#define VOLATILE                volatile
+
+#define MEMORY_FENCE            __sync_synchronize
+
+//
+// When build similiar to FW, then link everything together as
+// one big module.
+//
+
+#define EFI_DRIVER_ENTRY_POINT(InitFunction)    \
+    UINTN                                       \
+    InitializeDriver (                          \
+        VOID    *ImageHandle,                   \
+        VOID    *SystemTable                    \
+        )                                       \
+    {                                           \
+        return InitFunction(ImageHandle,        \
+                SystemTable);                   \
+    }                                           \
+                                                \
+    EFI_STATUS efi_main(                        \
+        EFI_HANDLE image,                       \
+        EFI_SYSTEM_TABLE *systab                \
+        ) __attribute__((weak,                  \
+                alias ("InitializeDriver")));
+
+#define LOAD_INTERNAL_DRIVER(_if, type, name, entry)    \
+        (_if)->LoadInternal(type, name, entry)
+
+
+//
+// Some compilers don't support the forward reference construct:
+//  typedef struct XXXXX
+//
+// The following macro provide a workaround for such cases.
+
+#define INTERFACE_DECL(x) struct x
+
+#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__)
+#define EFI_FUNCTION
diff --git a/inc/loongarch64/efilibplat.h b/inc/loongarch64/efilibplat.h
new file mode 100644
index 0000000..eda7c83
--- /dev/null
+++ b/inc/loongarch64/efilibplat.h
@@ -0,0 +1,24 @@
+/*++
+
+Copyright (c) 1998  Intel Corporation
+
+Module Name:
+
+    efilibplat.h
+
+Abstract:
+
+    EFI to compile bindings
+
+
+
+
+Revision History
+
+--*/
+
+VOID
+InitializeLibPlatform (
+    IN EFI_HANDLE           ImageHandle,
+    IN EFI_SYSTEM_TABLE     *SystemTable
+    );
diff --git a/inc/loongarch64/efisetjmp_arch.h b/inc/loongarch64/efisetjmp_arch.h
new file mode 100644
index 0000000..18aefaf
--- /dev/null
+++ b/inc/loongarch64/efisetjmp_arch.h
@@ -0,0 +1,23 @@
+#ifndef GNU_EFI_LOONGARCH64_SETJMP_H
+#define GNU_EFI_LOONGARCH64_SETJMP_H
+
+#define JMPBUF_ALIGN 8
+
+typedef struct {
+	/* GP regs */
+	UINT64	RA;
+	UINT64	SP;
+	UINT64	FP;
+
+	UINT64	S0;
+	UINT64	S1;
+	UINT64	S2;
+	UINT64	S3;
+	UINT64	S4;
+	UINT64	S5;
+	UINT64	S6;
+	UINT64	S7;
+	UINT64	S8;
+} ALIGN(JMPBUF_ALIGN) jmp_buf[1];
+
+#endif /* GNU_EFI_LOONGARCH64_SETJMP_H */
diff --git a/inc/mips64el/efibind.h b/inc/mips64el/efibind.h
index 1f08cd3..cf77ddc 100644
--- a/inc/mips64el/efibind.h
+++ b/inc/mips64el/efibind.h
@@ -40,9 +40,10 @@ typedef int64_t             intptr_t;
 // Basic EFI types of various widths
 //
 
-#ifndef __WCHAR_TYPE__
-# define __WCHAR_TYPE__ short
-#endif
+#include <stddef.h>
+
+typedef wchar_t CHAR16;
+#define WCHAR CHAR16
 
 typedef uint64_t   UINT64;
 typedef int64_t    INT64;
@@ -52,12 +53,13 @@ typedef int32_t    INT32;
 
 typedef uint16_t   UINT16;
 typedef int16_t    INT16;
+
 typedef uint8_t    UINT8;
+typedef char       CHAR8;
 typedef int8_t     INT8;
-typedef __WCHAR_TYPE__ WCHAR;
 
 #undef VOID
-#define VOID    void
+typedef void       VOID;
 
 typedef int64_t    INTN;
 typedef uint64_t   UINTN;
diff --git a/inc/riscv64/efibind.h b/inc/riscv64/efibind.h
index 0a818ae..4fdf81d 100644
--- a/inc/riscv64/efibind.h
+++ b/inc/riscv64/efibind.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */
 /*
  * Copright (C) 2014 - 2015 Linaro Ltd.
  * Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
@@ -21,7 +22,7 @@
 // Basic EFI types of various widths
 //
 
-
+#include <stddef.h>
 
 typedef uint64_t                UINT64;
 typedef int64_t                 INT64;
@@ -31,15 +32,13 @@ typedef uint16_t                UINT16;
 typedef int16_t                 INT16;
 typedef uint8_t                 UINT8;
 typedef int8_t                  INT8;
-#ifndef __WCHAR_TYPE__
-#define __WCHAR_TYPE__          short
-#endif
-typedef __WCHAR_TYPE__          WCHAR;
+typedef wchar_t                 CHAR16;
+#define WCHAR                   CHAR16
 #ifndef BOOLEAN
 typedef uint8_t                 BOOLEAN;
 #endif
 #undef VOID
-#define VOID                    void
+typedef void                    VOID;
 typedef int64_t                 INTN;
 typedef uint64_t                UINTN;
 
diff --git a/inc/riscv64/efilibplat.h b/inc/riscv64/efilibplat.h
index 0a61b24..9b15163 100644
--- a/inc/riscv64/efilibplat.h
+++ b/inc/riscv64/efilibplat.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */
 
 VOID
 InitializeLibPlatform (
diff --git a/inc/riscv64/efisetjmp_arch.h b/inc/riscv64/efisetjmp_arch.h
index 2bb4efd..9288c1f 100644
--- a/inc/riscv64/efisetjmp_arch.h
+++ b/inc/riscv64/efisetjmp_arch.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */
+
 #ifndef GNU_EFI_RISCV64_SETJMP_H
 #define GNU_EFI_RISCV64_SETJMP_H
 
diff --git a/inc/x86_64/efibind.h b/inc/x86_64/efibind.h
index b8c32c3..e454ed2 100644
--- a/inc/x86_64/efibind.h
+++ b/inc/x86_64/efibind.h
@@ -96,9 +96,10 @@ Revision History
 // Basic EFI types of various widths
 //
 
-#ifndef __WCHAR_TYPE__
-# define __WCHAR_TYPE__ short
-#endif
+#include <stddef.h>
+
+typedef wchar_t CHAR16;
+#define WCHAR CHAR16
 
 typedef uint64_t   UINT64;
 typedef int64_t    INT64;
@@ -110,12 +111,13 @@ typedef int64_t    INT64;
 
 typedef uint16_t   UINT16;
 typedef int16_t    INT16;
+
 typedef uint8_t    UINT8;
+typedef char       CHAR8;
 typedef int8_t     INT8;
-typedef __WCHAR_TYPE__ WCHAR;
 
 #undef VOID
-#define VOID    void
+typedef void       VOID;
 
 
 typedef int64_t    INTN;
diff --git a/lib/Makefile b/lib/Makefile
index 1fc6a47..4e0c9be 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -43,8 +43,8 @@ include $(SRCDIR)/../Make.defaults
 TOPDIR = $(SRCDIR)/..
 
 CDIR = $(TOPDIR)/..
-FILES = boxdraw smbios console crc data debug dpath  \
-        error event exit guid hand hw init lock   \
+FILES = boxdraw smbios console crc data debug dpath \
+        entry error event exit guid hand hw init lock \
         misc pause print sread str cmdline\
 	runtime/rtlock runtime/efirtlib runtime/rtstr runtime/vm runtime/rtdata  \
 	$(ARCH)/initplat $(ARCH)/math $(ARCH)/setjmp
@@ -62,9 +62,9 @@ FILES += $(ARCH)/uldiv $(ARCH)/ldivmod $(ARCH)/div $(ARCH)/llsl $(ARCH)/llsr \
 	 $(ARCH)/mullu
 endif
 
-OBJS  = $(FILES:%=%.o)
+OBJS  = $(FILES:%=%.o) ctors.o
 
-SUBDIRS = ia32 x86_64 ia64 aarch64 arm mips64el riscv64 runtime
+SUBDIRS = ia32 x86_64 ia64 aarch64 arm mips64el riscv64 loongarch64 runtime
 
 LIBDIRINSTALL = $(INSTALLROOT)$(LIBDIR)
 
@@ -72,7 +72,7 @@ all: libsubdirs libefi.a
 
 .PHONY: libsubdirs
 libsubdirs:
-	for sdir in $(SUBDIRS); do mkdir -p $$sdir; done
+	@set -e ; for sdir in $(SUBDIRS); do mkdir -p $$sdir; done
 
 $(OBJS): libsubdirs
 
diff --git a/lib/Makefile.orig b/lib/Makefile.orig
deleted file mode 100644
index 65aa8ca..0000000
--- a/lib/Makefile.orig
+++ /dev/null
@@ -1,91 +0,0 @@
-#
-#  Copyright (C) 1999-2001 Hewlett-Packard Co.
-#	Contributed by David Mosberger <davidm@hpl.hp.com>
-#	Contributed by Stephane Eranian <eranian@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.
-#
-
-SRCDIR = .
-
-VPATH = $(SRCDIR)
-
-include $(SRCDIR)/../Make.defaults
-
-TOPDIR = $(SRCDIR)/..
-
-CDIR = $(TOPDIR)/..
-FILES = boxdraw smbios console crc data debug dpath  \
-        error event guid hand hw init lock   \
-        misc print sread str cmdline \
-	runtime/rtlock runtime/efirtlib runtime/rtstr runtime/vm runtime/rtdata  \
-	$(ARCH)/initplat $(ARCH)/math 
-
-ifeq ($(ARCH),ia64)
-FILES += $(ARCH)/salpal $(ARCH)/palproc
-endif
-
-ifeq ($(ARCH),x86_64)
-FILES += $(ARCH)/callwrap $(ARCH)/efi_stub
-endif
-
-ifeq ($(ARCH),arm)
-FILES += $(ARCH)/lib1funcs $(ARCH)/div64
-endif
-
-OBJS  = $(FILES:%=%.o)
-
-SUBDIRS = ia32 x86_64 ia64 aarch64 arm runtime
-
-LIBDIRINSTALL = $(INSTALLROOT)$(LIBDIR)
-
-all: libsubdirs libefi.a
-
-.PHONY: libsubdirs
-libsubdirs:
-	for sdir in $(SUBDIRS); do mkdir -p $$sdir; done
-
-libefi.a: $(patsubst %,libefi.a(%),$(OBJS))
-
-clean:
-	rm -f libefi.a *~ $(OBJS) */*.o
-
-$(LIBDIRINSTALL):
-	mkdir -p $@
-
-$(LIBDIRINSTALL)/libefi.a: libefi.a | $(LIBDIRINSTALL)
-	$(INSTALL) -m 644 $< $(dir $@)
-
-install: $(LIBDIRINSTALL)/libefi.a
-
-include $(SRCDIR)/../Make.rules
-
-.PHONY: libsubdirs
diff --git a/lib/ctors.S b/lib/ctors.S
new file mode 100644
index 0000000..4a0c6ab
--- /dev/null
+++ b/lib/ctors.S
@@ -0,0 +1,47 @@
+/*
+ * Try to define the minimal empty init/ctor/dtor/fini_arrays so building with
+ * older or out-of-tree linker scripts will still work.
+ */
+/*
+ * Note that these aren't the using the GNU "CONSTRUCTOR" output section
+ * command, so they don't start with a size.  Because of p2align and the
+ * end/END definitions, and the fact that they're mergeable, they can also
+ * have NULLs which aren't guaranteed to be at the end.
+ */
+	.section .init_array, "aM", @init_array
+	.p2align 3, 0
+	.globl _init_array
+_init_array:
+	.p2align 3, 0
+	.globl _init_array_end
+_init_array_end:
+	.long 0
+	.section .ctors, "aM", @init_array
+	.p2align 3, 0
+	.globl __CTOR_LIST__
+__CTOR_LIST__:
+	.p2align 3, 0
+	.globl __CTOR_END__
+__CTOR_END__:
+	.long 0
+	.section .dtors, "aM", @fini_array
+	.p2align 3, 0
+	.globl __DTOR_LIST__
+__DTOR_LIST__:
+	.p2align 3, 0
+	.globl __DTOR_END__
+__DTOR_END__:
+	.long 0
+	.section .fini_array, "aM", @fini_array
+	.p2align 3, 0
+	.globl _fini_array
+_fini_array:
+	.p2align 3, 0
+	.globl _fini_array_end
+_fini_array_end:
+	.long 0
+
+#if defined(__ELF__) && defined(__linux__)
+	.section .note.GNU-stack,"",%progbits
+#endif
+
diff --git a/lib/entry.c b/lib/entry.c
new file mode 100644
index 0000000..d852608
--- /dev/null
+++ b/lib/entry.c
@@ -0,0 +1,67 @@
+/*
+ * ctors.c
+ * Copyright 2019 Peter Jones <pjones@redhat.com>
+ *
+ */
+
+#include <efi.h>
+#include <efilib.h>
+
+/*
+ * Note that these aren't the using the GNU "CONSTRUCTOR" output section
+ * command, so they don't start with a size.  Because of p2align and the
+ * end/END definitions, and the fact that they're mergeable, they can also
+ * have NULLs which aren't guaranteed to be at the end.
+ */
+extern UINTN _init_array, _init_array_end;
+extern UINTN __CTOR_LIST__, __CTOR_END__;
+extern UINTN _fini_array, _fini_array_end;
+extern UINTN __DTOR_LIST__, __DTOR_END__;
+
+typedef void (*funcp)(void);
+
+static void ctors(void)
+{
+	for (funcp *location = (void *)&_init_array; location < (funcp *)&_init_array_end; location++) {
+		funcp func = *location;
+		if (location != NULL)
+			func();
+	}
+
+	for (funcp *location = (void *)&__CTOR_LIST__; location < (funcp *)&__CTOR_END__; location++) {
+		funcp func = *location;
+		if (location != NULL)
+			func();
+	}
+}
+
+static void dtors(void)
+{
+	for (funcp *location = (void *)&__DTOR_LIST__; location < (funcp *)&__DTOR_END__; location++) {
+		funcp func = *location;
+		if (location != NULL)
+			func();
+	}
+
+	for (funcp *location = (void *)&_fini_array; location < (funcp *)&_fini_array_end; location++) {
+		funcp func = *location;
+		if (location != NULL)
+			func();
+	}
+}
+
+extern EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab);
+
+EFI_STATUS _entry(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
+{
+	EFI_STATUS status;
+	InitializeLib(image, systab);
+
+	ctors();
+	status = efi_main(image, systab);
+	dtors();
+
+	return status;
+}
+
+// vim:fenc=utf-8:tw=75:noet
diff --git a/lib/ia32/math.c b/lib/ia32/math.c
index fce7a8d..2ef7588 100644
--- a/lib/ia32/math.c
+++ b/lib/ia32/math.c
@@ -158,7 +158,7 @@ DivU64x32 (
     Rem = 0;
     for (bit=0; bit < 64; bit++) {
 #if defined(__GNUC__) || defined(__MINGW32__)
-        asm (
+        __asm__ (
             "shll	$1, %0\n\t"
             "rcll	$1, 4%0\n\t"
             "rcll	$1, %2\n\t"
diff --git a/lib/init.c b/lib/init.c
index 4f238c0..726e493 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -46,57 +46,52 @@ Returns:
     EFI_STATUS              Status;
     CHAR8                   *LangCode;
 
-    if (!LibInitialized) {
-        LibInitialized = TRUE;
-        LibFwInstance = FALSE;
-        LibImageHandle = ImageHandle;
+    if (LibInitialized)
+	return;
 
+    LibInitialized = TRUE;
+    LibFwInstance = FALSE;
+    LibImageHandle = ImageHandle;
 
-        //
-        // Set up global pointer to the system table, boot services table,
-        // and runtime services table
-        //
-
-        ST = SystemTable;
-        BS = SystemTable->BootServices;
-        RT = SystemTable->RuntimeServices;
-//        ASSERT (CheckCrc(0, &ST->Hdr));
-//        ASSERT (CheckCrc(0, &BS->Hdr));
-//        ASSERT (CheckCrc(0, &RT->Hdr));
-
-
-        //
-        // Initialize pool allocation type
-        //
-
-        if (ImageHandle) {
-            Status = uefi_call_wrapper(
-                BS->HandleProtocol,
-                3,
-                ImageHandle, 
-                &LoadedImageProtocol,
-                (VOID*)&LoadedImage
-            );
-
-            if (!EFI_ERROR(Status)) {
-                PoolAllocationType = LoadedImage->ImageDataType;
-            }
-            EFIDebugVariable ();
-        }
+    //
+    // Set up global pointer to the system table, boot services table,
+    // and runtime services table
+    //
 
-        //
-        // Initialize Guid table
-        //
+    ST = SystemTable;
+    BS = SystemTable->BootServices;
+    RT = SystemTable->RuntimeServices;
+    // ASSERT (CheckCrc(0, &ST->Hdr));
+    // ASSERT (CheckCrc(0, &BS->Hdr));
+    // ASSERT (CheckCrc(0, &RT->Hdr));
 
-        InitializeGuid();
+    //
+    // Initialize pool allocation type
+    //
 
-        InitializeLibPlatform(ImageHandle,SystemTable);
+    if (ImageHandle) {
+	Status = uefi_call_wrapper(
+	    BS->HandleProtocol,
+	    3,
+	    ImageHandle,
+	    &LoadedImageProtocol,
+	    (VOID*)&LoadedImage
+	);
+
+	if (!EFI_ERROR(Status)) {
+	    PoolAllocationType = LoadedImage->ImageDataType;
+	}
+	EFIDebugVariable ();
     }
 
     //
-    // 
+    // Initialize Guid table
     //
 
+    InitializeGuid();
+
+    InitializeLibPlatform(ImageHandle,SystemTable);
+
     if (ImageHandle && UnicodeInterface == &LibStubUnicodeInterface) {
         LangCode = LibGetVariable (VarLanguage, &EfiGlobalVariable);
         InitializeUnicodeSupport (LangCode);
diff --git a/lib/loongarch64/efi_stub.S b/lib/loongarch64/efi_stub.S
new file mode 100644
index 0000000..464eae5
--- /dev/null
+++ b/lib/loongarch64/efi_stub.S
@@ -0,0 +1 @@
+/* This stub is a stub to make the build happy */
diff --git a/lib/loongarch64/initplat.c b/lib/loongarch64/initplat.c
new file mode 100644
index 0000000..6c5e1fa
--- /dev/null
+++ b/lib/loongarch64/initplat.c
@@ -0,0 +1,26 @@
+/*
+ * Copright (C) 2014 Linaro Ltd.
+ * Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice and this list of conditions, without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any later version.
+ */
+
+#include "lib.h"
+
+VOID
+InitializeLibPlatform (
+    IN EFI_HANDLE           ImageHandle EFI_UNUSED,
+    IN EFI_SYSTEM_TABLE     *SystemTable EFI_UNUSED
+    )
+{
+}
diff --git a/lib/loongarch64/math.c b/lib/loongarch64/math.c
new file mode 100644
index 0000000..8c16444
--- /dev/null
+++ b/lib/loongarch64/math.c
@@ -0,0 +1,63 @@
+/*
+ * Copright (C) 2014 Linaro Ltd.
+ * Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice and this list of conditions, without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any later version.
+ */
+
+#include "lib.h"
+
+UINT64
+LShiftU64 (
+    IN UINT64   Operand,
+    IN UINTN    Count
+    )
+// Left shift 64bit by 32bit and get a 64bit result
+{
+    return Operand << Count;
+}
+
+UINT64
+RShiftU64 (
+    IN UINT64   Operand,
+    IN UINTN    Count
+    )
+// Right shift 64bit by 32bit and get a 64bit result
+{
+    return Operand >> Count;
+}
+
+
+UINT64
+MultU64x32 (
+    IN UINT64   Multiplicand,
+    IN UINTN    Multiplier
+    )
+// Multiple 64bit by 32bit and get a 64bit result
+{
+    return Multiplicand * Multiplier;
+}
+
+UINT64
+DivU64x32 (
+    IN UINT64   Dividend,
+    IN UINTN    Divisor,
+    OUT UINTN   *Remainder OPTIONAL
+    )
+// divide 64bit by 32bit and get a 64bit result
+// N.B. only works for 31bit divisors!!
+{
+    if (Remainder)
+	*Remainder = Dividend % Divisor;
+    return Dividend / Divisor;
+}
diff --git a/lib/loongarch64/setjmp.S b/lib/loongarch64/setjmp.S
new file mode 100644
index 0000000..6821af3
--- /dev/null
+++ b/lib/loongarch64/setjmp.S
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ * Copyright (c) 2021 Loongson Technology Corporation Limited.All rights
+ * reserved.
+ * Author: zhoumingtao <zhoumingtao@loongson.cn>
+ *
+ * This program and the accompanying materials are licensed and made
+ * available
+ * under the terms and conditions of the BSD License which accompanies
+ * this
+ * distribution.  The full text of the license may be found at
+ * http://opensource.org/licenses/bsd-license.php.
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS,
+ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED.
+ */
+
+	.text
+	.p2align 3
+
+/*
+   int setjmp(jmp_buf env);
+*/
+	.globl	setjmp
+	.type	setjmp, @function
+setjmp:
+	st.d $ra, $a0, 0x0
+	st.d $sp, $a0, 0x8
+	st.d $fp, $a0, 0x10
+	st.d $s0, $a0, 0x18
+	st.d $s1, $a0, 0x20
+	st.d $s2, $a0, 0x28
+	st.d $s3, $a0, 0x30
+	st.d $s4, $a0, 0x38
+	st.d $s5, $a0, 0x40
+	st.d $s6, $a0, 0x48
+	st.d $s7, $a0, 0x50
+	st.d $s8, $a0, 0x58
+
+	move $a0, $zero
+	jr   $ra
+
+/*
+   void longjmp(jmp_buf env, int val);
+*/
+	.globl	longjmp
+	.type	longjmp, @function
+longjmp:
+	ld.d $ra, $a0, 0x0
+	ld.d $sp, $a0, 0x8
+	ld.d $fp, $a0, 0x10
+	ld.d $s0, $a0, 0x18
+	ld.d $s1, $a0, 0x20
+	ld.d $s2, $a0, 0x28
+	ld.d $s3, $a0, 0x30
+	ld.d $s4, $a0, 0x38
+	ld.d $s5, $a0, 0x40
+	ld.d $s6, $a0, 0x48
+	ld.d $s7, $a0, 0x50
+	ld.d $s8, $a0, 0x58
+
+	addi.d $a0, $zero, 1	# a0 = 1
+	beqz $a1, .L0		# if (a1 == 0); goto L0
+	move $a0, $a1		# a0 = a1
+.L0:
+	jr   $ra
diff --git a/lib/print.c b/lib/print.c
index 8a7466c..a43dc8c 100644
--- a/lib/print.c
+++ b/lib/print.c
@@ -1125,24 +1125,24 @@ Returns:
                 Item.Item.pw = Item.Scratch;
                 break;
 
-            case '0':
-                Item.Pad = '0';
+            case ',':
+                Item.Comma = TRUE;
                 break;
 
             case '-':
                 Item.PadBefore = FALSE;
                 break;
 
-            case ',':
-                Item.Comma = TRUE;
+            case '*':
+                *Item.WidthParse = va_arg(ps->args, UINTN);
                 break;
 
             case '.':
                 Item.WidthParse = &Item.FieldWidth;
                 break;
 
-            case '*':
-                *Item.WidthParse = va_arg(ps->args, UINTN);
+            case '0':
+                Item.Pad = '0';
                 break;
 
             case '1':
@@ -1170,52 +1170,23 @@ Returns:
                 }
                 break;
 
-            case 's':
-                Item.Item.pw = va_arg(ps->args, CHAR16 *);
-                if (!Item.Item.pw) {
-                    Item.Item.pw = L"(null)";
-                }
-                break;
-
             case 'c':
                 Item.Scratch[0] = (CHAR16) va_arg(ps->args, UINTN);
                 Item.Scratch[1] = 0;
                 Item.Item.pw = Item.Scratch;
                 break;
 
-            case 'l':
-                Item.Long = TRUE;
-                break;
-
-            case 'X':
-                Item.Width = Item.Long ? 16 : 8;
-                Item.Pad = '0';
-#if __GNUC__ >= 7
-		__attribute__ ((fallthrough));
-#endif
-            case 'x':
-                ValueToHex (
-                    Item.Scratch,
-                    Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
-                    );
-                Item.Item.pw = Item.Scratch;
-
-                break;
-
+            case 'D':
+            {
+                EFI_DEVICE_PATH *dp = va_arg(ps->args, EFI_DEVICE_PATH *);
+                CHAR16 *dpstr = DevicePathToStr(dp);
+                StrnCpy(Item.Scratch, dpstr, PRINT_ITEM_BUFFER_LEN);
+                Item.Scratch[PRINT_ITEM_BUFFER_LEN-1] = L'\0';
+                FreePool(dpstr);
 
-            case 'g':
-                GuidToString (Item.Scratch, va_arg(ps->args, EFI_GUID *));
-                Item.Item.pw = Item.Scratch;
-                break;
-
-            case 'u':
-                ValueToString (
-                    Item.Scratch,
-                    Item.Comma,
-                    Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
-                    );
                 Item.Item.pw = Item.Scratch;
                 break;
+            }
 
             case 'd':
                 ValueToString (
@@ -1226,17 +1197,13 @@ Returns:
                 Item.Item.pw = Item.Scratch;
                 break;
 
-            case 'D':
-            {
-                EFI_DEVICE_PATH *dp = va_arg(ps->args, EFI_DEVICE_PATH *);
-                CHAR16 *dpstr = DevicePathToStr(dp);
-                StrnCpy(Item.Scratch, dpstr, PRINT_ITEM_BUFFER_LEN);
-                Item.Scratch[PRINT_ITEM_BUFFER_LEN-1] = L'\0';
-                FreePool(dpstr);
+            case 'E':
+                Attr = ps->AttrError;
+                break;
 
-                Item.Item.pw = Item.Scratch;
+            case 'e':
+                PSETATTR(ps, ps->AttrError);
                 break;
-            }
 
             case 'f':
                 FloatToString (
@@ -1247,38 +1214,83 @@ Returns:
                 Item.Item.pw = Item.Scratch;
                 break;
 
-            case 't':
-                TimeToString (Item.Scratch, va_arg(ps->args, EFI_TIME *));
-                Item.Item.pw = Item.Scratch;
-                break;
-
-            case 'r':
-                StatusToString (Item.Scratch, va_arg(ps->args, EFI_STATUS));
+            case 'g':
+                GuidToString (Item.Scratch, va_arg(ps->args, EFI_GUID *));
                 Item.Item.pw = Item.Scratch;
                 break;
 
-            case 'n':
-                PSETATTR(ps, ps->AttrNorm);
+            case 'H':
+                Attr = ps->AttrHighlight;
                 break;
 
             case 'h':
                 PSETATTR(ps, ps->AttrHighlight);
                 break;
 
-            case 'e':
-                PSETATTR(ps, ps->AttrError);
+            case 'l':
+                Item.Long = TRUE;
                 break;
 
             case 'N':
                 Attr = ps->AttrNorm;
                 break;
 
-            case 'H':
-                Attr = ps->AttrHighlight;
+            case 'n':
+                PSETATTR(ps, ps->AttrNorm);
                 break;
 
-            case 'E':
-                Attr = ps->AttrError;
+            case 'p':
+                Item.Width = sizeof(void *) == (8 ? 16 : 8) + 2;
+                Item.Pad = '0';
+                Item.Scratch[0] = ' ';
+                Item.Scratch[1] = ' ';
+                ValueToHex (
+                    Item.Scratch+2,
+                    Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
+                    );
+                Item.Scratch[0] = '0';
+                Item.Scratch[1] = 'x';
+                Item.Item.pw = Item.Scratch;
+                break;
+
+            case 'r':
+                StatusToString (Item.Scratch, va_arg(ps->args, EFI_STATUS));
+                Item.Item.pw = Item.Scratch;
+                break;
+
+            case 's':
+                Item.Item.pw = va_arg(ps->args, CHAR16 *);
+                if (!Item.Item.pw) {
+                    Item.Item.pw = L"(null)";
+                }
+                break;
+
+            case 't':
+                TimeToString (Item.Scratch, va_arg(ps->args, EFI_TIME *));
+                Item.Item.pw = Item.Scratch;
+                break;
+
+            case 'u':
+                ValueToString (
+                    Item.Scratch,
+                    Item.Comma,
+                    Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
+                    );
+                Item.Item.pw = Item.Scratch;
+                break;
+
+            case 'X':
+                Item.Width = Item.Long ? 16 : 8;
+                Item.Pad = '0';
+#if __GNUC__ >= 7
+		__attribute__ ((fallthrough));
+#endif
+            case 'x':
+                ValueToHex (
+                    Item.Scratch,
+                    Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
+                    );
+                Item.Item.pw = Item.Scratch;
                 break;
 
             default:
diff --git a/lib/riscv64/initplat.c b/lib/riscv64/initplat.c
index ed42037..895353a 100644
--- a/lib/riscv64/initplat.c
+++ b/lib/riscv64/initplat.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause
 
 #include "lib.h"
 
diff --git a/lib/riscv64/setjmp.S b/lib/riscv64/setjmp.S
index f7928e5..275a715 100644
--- a/lib/riscv64/setjmp.S
+++ b/lib/riscv64/setjmp.S
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause
 /*
  * Copyright Heinrich Schuchardt <xypron.glpk@gmx.de>
  */

More details

Full run details

Historical runs