From 5d5982a209bc71a4c61e88b31189ba4c9584ec32 Mon Sep 17 00:00:00 2001 From: kun-chang Date: Tue, 5 Aug 2025 21:13:25 +0800 Subject: [PATCH] add shim riscv64 support Signed-off-by: kun-chang --- BOOTRISCV64.CSV | Bin 0 -> 130 bytes ...im-submodule-gnu-efi-support-riscv64.patch | 732 ++++++++++++++++++ Feature-shim-support-riscv64.patch | 424 ++++++++++ shim.spec | 36 +- 4 files changed, 1184 insertions(+), 8 deletions(-) create mode 100644 BOOTRISCV64.CSV create mode 100644 Feature-shim-submodule-gnu-efi-support-riscv64.patch create mode 100644 Feature-shim-support-riscv64.patch diff --git a/BOOTRISCV64.CSV b/BOOTRISCV64.CSV new file mode 100644 index 0000000000000000000000000000000000000000..a290428bf13b4b1a8f450912ab09d29e19d2c69f GIT binary patch literal 130 zcmZXM!3lsc6hq(HDLO#$Bu?T4N{fP8>92yztD#p9KR*dc-p80(*vLX-;-aUcB@pF! n5{LM%J6VNUo@b~n!_}6fNC&A=`6T6Przm}kM|oNQzt!*o0gD-M literal 0 HcmV?d00001 diff --git a/Feature-shim-submodule-gnu-efi-support-riscv64.patch b/Feature-shim-submodule-gnu-efi-support-riscv64.patch new file mode 100644 index 0000000..99851ac --- /dev/null +++ b/Feature-shim-submodule-gnu-efi-support-riscv64.patch @@ -0,0 +1,732 @@ +From fa754c6941e3d1d151d17a7c59699b90408c7f40 Mon Sep 17 00:00:00 2001 +From: kun-chang +Date: Tue, 5 Aug 2025 15:55:00 +0800 +Subject: [PATCH] submodule gnu-efi support riscv64 + +Signed-off-by: kun-chang +--- + gnu-efi/Make.defaults | 2 +- + gnu-efi/gnuefi/crt0-efi-riscv64.S | 54 +++++++++++ + gnu-efi/gnuefi/elf_riscv64_efi.lds | 123 +++++++++++++++++++++++++ + gnu-efi/gnuefi/reloc_riscv64.c | 90 +++++++++++++++++++ + gnu-efi/inc/efi.h | 2 + + gnu-efi/inc/efilib.h | 2 + + gnu-efi/inc/efirtlib.h | 2 + + gnu-efi/inc/riscv64/efibind.h | 128 +++++++++++++++++++++++++++ + gnu-efi/inc/riscv64/efilibplat.h | 7 ++ + gnu-efi/inc/riscv64/efisetjmp_arch.h | 40 +++++++++ + gnu-efi/lib/riscv64/initplat.c | 12 +++ + gnu-efi/lib/riscv64/math.c | 62 +++++++++++++ + gnu-efi/lib/riscv64/setjmp.S | 69 +++++++++++++++ + 13 files changed, 592 insertions(+), 1 deletion(-) + create mode 100644 gnu-efi/gnuefi/crt0-efi-riscv64.S + create mode 100644 gnu-efi/gnuefi/elf_riscv64_efi.lds + create mode 100644 gnu-efi/gnuefi/reloc_riscv64.c + create mode 100644 gnu-efi/inc/riscv64/efibind.h + create mode 100644 gnu-efi/inc/riscv64/efilibplat.h + create mode 100644 gnu-efi/inc/riscv64/efisetjmp_arch.h + create mode 100644 gnu-efi/lib/riscv64/initplat.c + create mode 100644 gnu-efi/lib/riscv64/math.c + create mode 100644 gnu-efi/lib/riscv64/setjmp.S + +diff --git a/gnu-efi/Make.defaults b/gnu-efi/Make.defaults +index 3b56150..6198b3a 100644 +--- a/gnu-efi/Make.defaults ++++ b/gnu-efi/Make.defaults +@@ -36,7 +36,7 @@ + + TOPDIR ?= $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) + +-ARCHES = ia32 x86_64 ia64 aarch64 arm mips64el ++ARCHES = ia32 x86_64 ia64 aarch64 arm mips64el riscv64 + + # + # Variables below overridable from command-line: +diff --git a/gnu-efi/gnuefi/crt0-efi-riscv64.S b/gnu-efi/gnuefi/crt0-efi-riscv64.S +new file mode 100644 +index 0000000..296d03d +--- /dev/null ++++ b/gnu-efi/gnuefi/crt0-efi-riscv64.S +@@ -0,0 +1,54 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause */ ++/* ++ * Copyright (C) 2014 Linaro Ltd. ++ * Copyright (C) 2018 Alexander Graf ++ * ++ * 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. ++ */ ++ ++ .text ++ .globl _start ++ .type _start,%function ++_start: ++ addi sp, sp, -24 ++ sd a0, 0(sp) ++ sd a1, 8(sp) ++ sd ra, 16(sp) ++ lla a0, ImageBase ++ lla a1, _DYNAMIC ++ call _relocate ++ bne a0, zero, .L_exit ++ ld a1, 8(sp) ++ ld a0, 0(sp) ++ call efi_main ++ ld ra, 16(sp) ++.L_exit: ++ addi sp, sp, 24 ++ ret ++ ++// hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: ++ ++ .data ++dummy0: .4byte 0 ++dummy1: .4byte 0 ++ ++#define IMAGE_REL_ABSOLUTE 0 ++ .section .reloc, "a", %progbits ++ .4byte dummy1 - dummy0 // Page RVA ++ .4byte 12 // Block Size (2*4+2*2), must be aligned by 32 Bits ++ .2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy ++ .2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy ++ ++#if defined(__ELF__) && defined(__linux__) ++ .section .note.GNU-stack,"",%progbits ++#endif +diff --git a/gnu-efi/gnuefi/elf_riscv64_efi.lds b/gnu-efi/gnuefi/elf_riscv64_efi.lds +new file mode 100644 +index 0000000..d6663ee +--- /dev/null ++++ b/gnu-efi/gnuefi/elf_riscv64_efi.lds +@@ -0,0 +1,123 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause */ ++ ++OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv") ++OUTPUT_ARCH(riscv) ++ENTRY(_start) ++SECTIONS ++{ ++ . = 0; ++ ImageBase = .; ++ /* .hash and/or .gnu.hash MUST come first! */ ++ .hash : { *(.hash) } ++ .gnu.hash : { *(.gnu.hash) } ++ . = ALIGN(4096); ++ .eh_frame : { *(.eh_frame) } ++ .eh_frame_hdr : { *(.eh_frame_hdr) } ++ .gcc_except_table : { *(.gcc_except_table*) } ++ . = ALIGN(4096); ++ .text : { ++ _text = .; ++ *(.text) ++ *(.text.*) ++ *(.gnu.linkonce.t.*) ++ *(.plt) ++ . = ALIGN(16); ++ } ++ _etext = .; ++ _text_size = _etext - _text; ++ . = ALIGN(65536); ++ _DYNAMIC = .; ++ .dynamic : { *(.dynamic) } ++ . = ALIGN(4096); ++ .data : ++ { ++ _data = .; ++ *(.sdata) ++ *(.data) ++ *(.data1) ++ *(.data.*) ++ *(.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_start = .; ++ *(SORT(.init_array.*)) ++ *(.init_array) ++ __init_array_end = .; ++ . = ALIGN(16); ++ __CTOR_LIST__ = .; ++ *(SORT(.ctors.*)) ++ *(.ctors) ++ __CTOR_END__ = .; ++ . = ALIGN(16); ++ __DTOR_LIST__ = .; ++ *(SORT(.dtors.*)) ++ *(.dtors) ++ __DTOR_END__ = .; ++ . = ALIGN(16); ++ __fini_array_start = .; ++ *(SORT(.fini_array.*)) ++ *(.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); ++ _bss = .; ++ *(.sbss) ++ *(.scommon) ++ *(.dynbss) ++ *(.bss*) ++ *(COMMON) ++ *(.rel.local) ++ . = ALIGN(16); ++ ++ _bss_end = .; ++ } ++ . = ALIGN(4096); ++ .reloc : ++ { ++ KEEP (*(.reloc)) ++ } ++ ++ . = ALIGN(4096); ++ .rela : ++ { ++ *(.rela.text*) ++ *(.rela.data*) ++ *(.rela.got) ++ *(.rela.dyn) ++ *(.rela.stab) ++ *(.rela.init_array*) ++ *(.rela.fini_array*) ++ *(.rela.ctors*) ++ *(.rela.dtors*) ++ ++ } ++ . = ALIGN(4096); ++ .rela.plt : { *(.rela.plt) } ++ . = ALIGN(4096); ++ .rodata : { *(.rodata*) } ++ . = ALIGN(512); ++ _edata = .; ++ _data_size = _edata - _data; ++ ++ . = ALIGN(4096); ++ .dynsym : { *(.dynsym) } ++ . = ALIGN(4096); ++ .dynstr : { *(.dynstr) } ++ . = ALIGN(4096); ++ .note.gnu.build-id : { *(.note.gnu.build-id) } ++ .ignored.reloc : ++ { ++ *(.rela.reloc) ++ *(.note.GNU-stack) ++ } ++ .comment 0 : { *(.comment) } ++} +diff --git a/gnu-efi/gnuefi/reloc_riscv64.c b/gnu-efi/gnuefi/reloc_riscv64.c +new file mode 100644 +index 0000000..3649d9d +--- /dev/null ++++ b/gnu-efi/gnuefi/reloc_riscv64.c +@@ -0,0 +1,90 @@ ++// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause ++/* reloc_riscv.c - position independent ELF shared object relocator ++ Copyright (C) 2018 Alexander Graf ++ Copyright (C) 2014 Linaro Ltd. ++ Copyright (C) 1999 Hewlett-Packard Co. ++ Contributed by David Mosberger . ++ ++ 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 ++ ++#include ++ ++#define Elf_Dyn Elf64_Dyn ++#define Elf_Rela Elf64_Rela ++#define ELF_R_TYPE ELF64_R_TYPE ++ ++EFI_STATUS EFIAPI _relocate(long ldbase, Elf_Dyn *dyn) ++{ ++ long relsz = 0, relent = 0; ++ Elf_Rela *rel = NULL; ++ 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; ++ 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_RISCV_RELATIVE: ++ addr = (unsigned long *)(ldbase + rel->r_offset); ++ *addr = ldbase + rel->r_addend; ++ break; ++ default: ++ break; ++ } ++ rel = (Elf_Rela *)((char *)rel + relent); ++ relsz -= relent; ++ } ++ return EFI_SUCCESS; ++} +\ No newline at end of file +diff --git a/gnu-efi/inc/efi.h b/gnu-efi/inc/efi.h +index bd99451..f87477b 100644 +--- a/gnu-efi/inc/efi.h ++++ b/gnu-efi/inc/efi.h +@@ -50,6 +50,8 @@ Revision History + #include "arm/efibind.h" + #elif defined (_M_MIPS64) || defined(__mips64__) + #include "mips64el/efibind.h" ++#elif defined (__riscv) && __riscv_xlen == 64 ++#include "riscv64/efibind.h" + #else + #error Usupported architecture + #endif +diff --git a/gnu-efi/inc/efilib.h b/gnu-efi/inc/efilib.h +index af47019..c00544a 100644 +--- a/gnu-efi/inc/efilib.h ++++ b/gnu-efi/inc/efilib.h +@@ -33,6 +33,8 @@ Revision History + #include "arm/efilibplat.h" + #elif defined (_M_MIPS64) || defined(__mips64__) + #include "mips64el/efilibplat.h" ++#elif defined (__riscv) && __riscv_xlen == 64 ++#include "riscv64/efilibplat.h" + #endif + #include "efilink.h" + #include "efirtlib.h" +diff --git a/gnu-efi/inc/efirtlib.h b/gnu-efi/inc/efirtlib.h +index 5071493..8643061 100644 +--- a/gnu-efi/inc/efirtlib.h ++++ b/gnu-efi/inc/efirtlib.h +@@ -32,6 +32,8 @@ Revision History + #include "arm/efilibplat.h" + #elif defined (_M_MIPS64) || defined(__mips64__) + #include "mips64el/efilibplat.h" ++#elif defined (__riscv) && __riscv_xlen == 64 ++#include "riscv64/efilibplat.h" + #endif + + +diff --git a/gnu-efi/inc/riscv64/efibind.h b/gnu-efi/inc/riscv64/efibind.h +new file mode 100644 +index 0000000..de1421b +--- /dev/null ++++ b/gnu-efi/inc/riscv64/efibind.h +@@ -0,0 +1,128 @@ ++/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */ ++/* ++ * Copright (C) 2014 - 2015 Linaro Ltd. ++ * Author: Ard Biesheuvel ++ * ++ * 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 ++ ++// ++// Basic EFI types of various widths ++// ++ ++#include ++ ++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 char CHAR8; ++typedef wchar_t CHAR16; ++#define WCHAR CHAR16 ++#undef VOID ++typedef void VOID; ++typedef int64_t INTN; ++typedef uint64_t UINTN; ++ ++#define EFI_ERROR_MASK 0x8000000000000000 ++#define EFIERR(a) (EFI_ERROR_MASK | a) ++#define EFIERR_OEM(a) (0xc000000000000000 | a) ++ ++#define BAD_POINTER 0xFBFBFBFBFBFBFBFB ++#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF ++ ++#define BREAKPOINT() while(1); ++ ++// ++// 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. For the MSVC toolchain, we simply tell the ++// linker what our driver init function is using /ENTRY. ++// ++#if defined(_MSC_EXTENSIONS) ++#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ ++ __pragma(comment(linker, "/ENTRY:" # InitFunction)) ++#else ++#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"))); ++#endif ++ ++#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 +\ No newline at end of file +diff --git a/gnu-efi/inc/riscv64/efilibplat.h b/gnu-efi/inc/riscv64/efilibplat.h +new file mode 100644 +index 0000000..b099947 +--- /dev/null ++++ b/gnu-efi/inc/riscv64/efilibplat.h +@@ -0,0 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */ ++ ++VOID ++InitializeLibPlatform ( ++ IN EFI_HANDLE ImageHandle, ++ IN EFI_SYSTEM_TABLE *SystemTable ++ ); +\ No newline at end of file +diff --git a/gnu-efi/inc/riscv64/efisetjmp_arch.h b/gnu-efi/inc/riscv64/efisetjmp_arch.h +new file mode 100644 +index 0000000..293329e +--- /dev/null ++++ b/gnu-efi/inc/riscv64/efisetjmp_arch.h +@@ -0,0 +1,40 @@ ++/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */ ++ ++#ifndef GNU_EFI_RISCV64_SETJMP_H ++#define GNU_EFI_RISCV64_SETJMP_H ++ ++#define JMPBUF_ALIGN 8 ++ ++typedef struct { ++ /* GP regs */ ++ UINT64 s0; ++ UINT64 s1; ++ UINT64 s2; ++ UINT64 s3; ++ UINT64 s4; ++ UINT64 s5; ++ UINT64 s6; ++ UINT64 s7; ++ UINT64 s8; ++ UINT64 s9; ++ UINT64 s10; ++ UINT64 s11; ++ UINT64 sp; ++ UINT64 ra; ++ ++ /* FP regs */ ++ UINT64 fs0; ++ UINT64 fs1; ++ UINT64 fs2; ++ UINT64 fs3; ++ UINT64 fs4; ++ UINT64 fs5; ++ UINT64 fs6; ++ UINT64 fs7; ++ UINT64 fs8; ++ UINT64 fs9; ++ UINT64 fs10; ++ UINT64 fs11; ++} EFI_ALIGN(JMPBUF_ALIGN) jmp_buf[1]; ++ ++#endif /* GNU_EFI_RISCV64_SETJMP_H */ +\ No newline at end of file +diff --git a/gnu-efi/lib/riscv64/initplat.c b/gnu-efi/lib/riscv64/initplat.c +new file mode 100644 +index 0000000..1e7b700 +--- /dev/null ++++ b/gnu-efi/lib/riscv64/initplat.c +@@ -0,0 +1,12 @@ ++ ++// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause ++ ++#include "lib.h" ++ ++VOID ++InitializeLibPlatform ( ++ IN EFI_HANDLE ImageHandle EFI_UNUSED, ++ IN EFI_SYSTEM_TABLE *SystemTable EFI_UNUSED ++ ) ++{ ++} +\ No newline at end of file +diff --git a/gnu-efi/lib/riscv64/math.c b/gnu-efi/lib/riscv64/math.c +new file mode 100644 +index 0000000..05064d3 +--- /dev/null ++++ b/gnu-efi/lib/riscv64/math.c +@@ -0,0 +1,62 @@ ++// SPDX-License-Identifier: BSD-2-Clause-Patent ++/* ++ * This code is based on EDK II MdePkg/Library/BaseLib/Math64.c ++ * Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. ++ */ ++ ++#include "lib.h" ++ ++/** ++ * LShiftU64() - left shift ++ */ ++UINT64 ++LShiftU64 ( ++ IN UINT64 Operand, ++ IN UINTN Count ++) ++{ ++ return Operand << Count; ++} ++ ++/** ++ * RShiftU64() - right shift ++ */ ++UINT64 ++RShiftU64 ( ++ IN UINT64 Operand, ++ IN UINTN Count ++) ++{ ++ return Operand >> Count; ++} ++ ++/** ++ * MultU64x32() - multiply ++ */ ++UINT64 ++MultU64x32 ( ++ IN UINT64 Multiplicand, ++ IN UINTN Multiplier ++) ++{ ++ return Multiplicand * Multiplier; ++} ++ ++/** ++ * DivU64x32() - divide ++ */ ++UINT64 ++DivU64x32 ( ++ IN UINT64 Dividend, ++ IN UINTN Divisor, ++ OUT UINTN *Remainder OPTIONAL ++) ++{ ++ ASSERT(Divisor != 0); ++ ++ if (Remainder) { ++ *Remainder = Dividend % Divisor; ++ } ++ ++ return Dividend / Divisor; ++} +\ No newline at end of file +diff --git a/gnu-efi/lib/riscv64/setjmp.S b/gnu-efi/lib/riscv64/setjmp.S +new file mode 100644 +index 0000000..b9fcf29 +--- /dev/null ++++ b/gnu-efi/lib/riscv64/setjmp.S +@@ -0,0 +1,69 @@ ++// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause ++/* ++ * Copyright Heinrich Schuchardt ++ */ ++ ++ .text ++ .p2align 3 ++ ++#define GREG_LIST \ ++ REG_ONE(s0, 0); \ ++ REG_ONE(s1, 8); \ ++ REG_ONE(s2, 16); \ ++ REG_ONE(s3, 24); \ ++ REG_ONE(s4, 32); \ ++ REG_ONE(s5, 40); \ ++ REG_ONE(s6, 48); \ ++ REG_ONE(s7, 56); \ ++ REG_ONE(s8, 64); \ ++ REG_ONE(s9, 72); \ ++ REG_ONE(s10, 80); \ ++ REG_ONE(s11, 88); \ ++ REG_ONE(sp, 96); \ ++ REG_ONE(ra, 104); ++ ++#define FREG_LIST \ ++ FREG_ONE(fs0, 112); \ ++ FREG_ONE(fs1, 120); \ ++ FREG_ONE(fs2, 128); \ ++ FREG_ONE(fs3, 136); \ ++ FREG_ONE(fs4, 144); \ ++ FREG_ONE(fs5, 152); \ ++ FREG_ONE(fs6, 160); \ ++ FREG_ONE(fs7, 168); \ ++ FREG_ONE(fs8, 176); \ ++ FREG_ONE(fs9, 184); \ ++ FREG_ONE(fs10, 192); \ ++ FREG_ONE(fs11, 200); ++ ++#define REG_ONE(R, P) sd R, P(a0) ++#define FREG_ONE(R, P) fsd R, P(a0) ++ ++ .globl setjmp ++ .type setjmp, @function ++ ++setjmp: ++ GREG_LIST ++#ifndef __riscv_float_abi_soft ++ FREG_LIST ++#endif ++ li a0, 0 ++ ret ++ ++#undef REG_ONE ++#undef FREG_ONE ++ ++#define REG_ONE(R, P) ld R, P(a0) ++#define FREG_ONE(R, P) fld R, P(a0) ++ ++ .globl longjmp ++ .type longjmp, @function ++ ++longjmp: ++ GREG_LIST ++#ifndef __riscv_float_abi_soft ++ FREG_LIST ++#endif ++ seqz a0, a1 ++ add a0, a0, a1 ++ ret +\ No newline at end of file +-- +2.34.1 + diff --git a/Feature-shim-support-riscv64.patch b/Feature-shim-support-riscv64.patch new file mode 100644 index 0000000..c420b59 --- /dev/null +++ b/Feature-shim-support-riscv64.patch @@ -0,0 +1,424 @@ +From e723ffad12cfd2cb54516ebe4988017e5a219c81 Mon Sep 17 00:00:00 2001 +From: kun-chang +Date: Tue, 5 Aug 2025 15:53:33 +0800 +Subject: [PATCH] shim support riscv64 + +Signed-off-by: kun-chang +--- + Cryptlib/Include/OpenSslSupport.h | 3 +- + Cryptlib/Makefile | 3 + + Cryptlib/OpenSSL/Makefile | 3 + + Make.defaults | 6 ++ + elf_riscv64_efi.lds | 135 ++++++++++++++++++++++++++++++ + include/asm.h | 2 + + include/peimage.h | 4 +- + include/system/stdarg.h | 2 +- + include/test.h | 2 + + lib/Makefile | 21 ++++- + lib/riscv64/cache.S | 10 +++ + lib/riscv64/edk2asm.h | 6 ++ + pe.c | 6 ++ + shim.h | 15 ++++ + test-str.c | 2 +- + 15 files changed, 214 insertions(+), 6 deletions(-) + create mode 100644 elf_riscv64_efi.lds + create mode 100644 lib/riscv64/cache.S + create mode 100644 lib/riscv64/edk2asm.h + +diff --git a/Cryptlib/Include/OpenSslSupport.h b/Cryptlib/Include/OpenSslSupport.h +index 0c2fb8b..a0a7124 100644 +--- a/Cryptlib/Include/OpenSslSupport.h ++++ b/Cryptlib/Include/OpenSslSupport.h +@@ -61,7 +61,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + #define CONFIG_HEADER_BN_H + +-#if defined(MDE_CPU_X64) || defined(MDE_CPU_AARCH64) || defined(MDE_CPU_IA64) ++#if defined(MDE_CPU_X64) || defined(MDE_CPU_AARCH64) || \ ++ defined(MDE_CPU_IA64) || defined(MDE_CPU_RISCV64) + // + // With GCC we would normally use SIXTY_FOUR_BIT_LONG, but MSVC needs + // SIXTY_FOUR_BIT, because 'long' is 32-bit and only 'long long' is +diff --git a/Cryptlib/Makefile b/Cryptlib/Makefile +index 89fd5cd..6de37e8 100644 +--- a/Cryptlib/Makefile ++++ b/Cryptlib/Makefile +@@ -36,6 +36,9 @@ endif + ifeq ($(ARCH),arm) + DEFINES += -DMDE_CPU_ARM + endif ++ifeq ($(ARCH),riscv64) ++DEFINES += -DMDE_CPU_RISCV64 ++endif + + LDFLAGS = -nostdlib -znocombreloc + +diff --git a/Cryptlib/OpenSSL/Makefile b/Cryptlib/OpenSSL/Makefile +index 795f471..afef979 100644 +--- a/Cryptlib/OpenSSL/Makefile ++++ b/Cryptlib/OpenSSL/Makefile +@@ -49,6 +49,9 @@ endif + ifeq ($(ARCH),arm) + DEFINES += -DMDE_CPU_ARM + endif ++ifeq ($(ARCH),riscv64) ++DEFINES += -DMDE_CPU_RISCV64 ++endif + + LDFLAGS = -nostdlib -znocombreloc + +diff --git a/Make.defaults b/Make.defaults +index c46164a..7c88f1f 100644 +--- a/Make.defaults ++++ b/Make.defaults +@@ -96,6 +96,12 @@ ifeq ($(ARCH),arm) + SUBSYSTEM := 0xa + ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM) + endif ++ifeq ($(ARCH),riscv64) ++ ARCH_CFLAGS ?= -DMDE_CPU_RISCV64 -DPAGE_SIZE=4096 ++ ARCH_GNUEFI ?= riscv64 ++ ARCH_SUFFIX ?= riscv64 ++ ARCH_SUFFIX_UPPER ?= RISCV64 ++endif + + DEFINES = -DDEFAULT_LOADER='L"$(DEFAULT_LOADER)"' \ + -DDEFAULT_LOADER_CHAR='"$(DEFAULT_LOADER)"' +diff --git a/elf_riscv64_efi.lds b/elf_riscv64_efi.lds +new file mode 100644 +index 0000000..e2bd896 +--- /dev/null ++++ b/elf_riscv64_efi.lds +@@ -0,0 +1,135 @@ ++/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */ ++ ++OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv") ++OUTPUT_ARCH(riscv) ++ENTRY(_start) ++SECTIONS ++{ ++ . = 0; ++ ImageBase = .; ++ /* .hash and/or .gnu.hash MUST come first! */ ++ .hash : { *(.hash) } ++ .gnu.hash : { *(.gnu.hash) } ++ . = ALIGN(4096); ++ .eh_frame : { *(.eh_frame) } ++ .eh_frame_hdr : { *(.eh_frame_hdr) } ++ .gcc_except_table : { *(.gcc_except_table*) } ++ . = ALIGN(4096); ++ .text : { ++ _text = .; ++ *(.text) ++ *(.text.*) ++ *(.gnu.linkonce.t.*) ++ *(.plt) ++ . = ALIGN(16); ++ } ++ _etext = .; ++ _text_size = _etext - _text; ++ . = ALIGN(65536); ++ .reloc : ++ { ++ KEEP (*(.reloc)) ++ } ++ . = ALIGN(4096); ++ .dynamic : { *(.dynamic) } ++ . = ALIGN(4096); ++ .data : ++ { ++ _data = .; ++ *(.sdata) ++ *(.data) ++ *(.data1) ++ *(.data.*) ++ *(.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_start = .; ++ *(SORT(.init_array.*)) ++ *(.init_array) ++ __init_array_end = .; ++ . = ALIGN(16); ++ __CTOR_LIST__ = .; ++ *(SORT(.ctors.*)) ++ *(.ctors) ++ __CTOR_END__ = .; ++ . = ALIGN(16); ++ __DTOR_LIST__ = .; ++ *(SORT(.dtors.*)) ++ *(.dtors) ++ __DTOR_END__ = .; ++ . = ALIGN(16); ++ __fini_array_start = .; ++ *(SORT(.fini_array.*)) ++ *(.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); ++ _bss = .; ++ *(.sbss) ++ *(.scommon) ++ *(.dynbss) ++ *(.bss*) ++ *(COMMON) ++ *(.rel.local) ++ . = ALIGN(16); ++ ++ _bss_end = .; ++ } ++ ++ . = ALIGN(4096); ++ .rela : ++ { ++ *(.rela.text*) ++ *(.rela.data*) ++ *(.rela.got) ++ *(.rela.dyn) ++ *(.rela.stab) ++ *(.rela.init_array*) ++ *(.rela.fini_array*) ++ *(.rela.ctors*) ++ *(.rela.dtors*) ++ ++ } ++ . = ALIGN(4096); ++ .rela.plt : { *(.rela.plt) } ++ . = ALIGN(4096); ++ .rodata : { *(.rodata*) } ++ . = ALIGN(512); ++ _edata = .; ++ _data_size = _edata - _data; ++ ++ . = ALIGN(4096); ++ .sbat : ++ { ++ _sbat = .; ++ *(.sbat) ++ *(.sbat.*) ++ _esbat = .; ++ . = ALIGN(4096); ++ _epsbat = .; ++ } ++ _sbat_size = _epsbat - _sbat; ++ _sbat_vsize = _esbat - _sbat; ++ ++ . = ALIGN(4096); ++ .dynsym : { *(.dynsym) } ++ . = ALIGN(4096); ++ .dynstr : { *(.dynstr) } ++ . = ALIGN(4096); ++ .note.gnu.build-id : { *(.note.gnu.build-id) } ++ .ignored.reloc : ++ { ++ *(.rela.reloc) ++ *(.note.GNU-stack) ++ } ++ .comment 0 : { *(.comment) } ++} +diff --git a/include/asm.h b/include/asm.h +index 03b0655..7ba4efe 100644 +--- a/include/asm.h ++++ b/include/asm.h +@@ -19,6 +19,8 @@ static inline uint64_t read_counter(void) + __asm__ __volatile__ ("mrs %0, pmccntr_el0" : "=r" (val)); + #elif defined(__arm__) + __asm__ __volatile__ ("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); ++#elif defined(__riscv) && __riscv_xlen == 64 ++ __asm__ __volatile__ ("csrr %0, 0xc01" : "=r" (val) : : "memory"); + #else + #error unsupported arch + #endif +diff --git a/include/peimage.h b/include/peimage.h +index e97b29c..907d569 100644 +--- a/include/peimage.h ++++ b/include/peimage.h +@@ -46,7 +46,9 @@ + #define IMAGE_FILE_MACHINE_EBC 0x0EBC + #define IMAGE_FILE_MACHINE_X64 0x8664 + #define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x01c2 +-#define IMAGE_FILE_MACHINE_ARM64 0xaa64 ++#define IMAGE_FILE_MACHINE_ARM64 0xaa64 ++#define IMAGE_FILE_MACHINE_RISCV32 0x5032 ++#define IMAGE_FILE_MACHINE_RISCV64 0x5064 + + // + // EXE file formats +diff --git a/include/system/stdarg.h b/include/system/stdarg.h +index 68c171b..a3919cf 100644 +--- a/include/system/stdarg.h ++++ b/include/system/stdarg.h +@@ -24,7 +24,7 @@ typedef __builtin_va_list __builtin_sysv_va_list; + #endif + + #if defined(__aarch64__) || defined(__arm__) || defined(__i386__) || \ +- defined(__i486__) || defined(__i686__) || defined(__COVERITY__) ++ defined(__i486__) || defined(__i686__) || defined(__COVERITY__) || defined(__riscv) + + typedef __builtin_va_list ms_va_list; + typedef __builtin_va_list __builtin_ms_va_list; +diff --git a/include/test.h b/include/test.h +index 5261dbd..ae7d9fe 100644 +--- a/include/test.h ++++ b/include/test.h +@@ -19,6 +19,8 @@ + + #if defined(__aarch64__) + #include ++#elif defined(__riscv) && __riscv_xlen == 64 ++#include + #elif defined(__arm__) + #include + #elif defined(__i386__) || defined(__i486__) || defined(__i686__) +diff --git a/lib/Makefile b/lib/Makefile +index f81c5c9..8a30850 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -30,6 +30,10 @@ endif + ifeq ($(ARCH),arm) + DEFINES += -DMDE_CPU_ARM + endif ++ifeq ($(ARCH),riscv64) ++DEFINES += -DMDE_CPU_RISCV64 ++LIBFILES += $(ARCH)/cache.o ++endif + + LDFLAGS = -nostdlib -znocombreloc + +@@ -45,11 +49,24 @@ ifneq ($(origin ENABLE_SHIM_DEVEL),undefined) + CFLAGS += -DENABLE_SHIM_DEVEL + endif + ++ifeq ($(ARCH),riscv64) ++SUBDIRS += riscv64 ++endif ++ ++all: libsubdirs $(TARGET) ++ ++$(TARGET): | libsubdirs ++$(LIBFILES): | libsubdirs ++ ++.PHONY: libsubdirs ++libsubdirs: ++ @set -e ; for d in $(SUBDIRS) ; do \ ++ [ -z "$$d" ] || mkdir -p "$$d" ; \ ++ done ++ + lib.a: $(LIBFILES) + $(AR) rcs lib.a $(LIBFILES) + +-all: $(TARGET) +- + clean: + rm -f lib.a + rm -f $(LIBFILES) +diff --git a/lib/riscv64/cache.S b/lib/riscv64/cache.S +new file mode 100644 +index 0000000..b31d6d7 +--- /dev/null ++++ b/lib/riscv64/cache.S +@@ -0,0 +1,10 @@ ++#include "edk2asm.h" ++ ++ .file "cache.S" ++ .text ++ ++GCC_ASM_EXPORT(__riscv_flush_icache) ++ ++ASM_PFX(__riscv_flush_icache): ++ fence.i ++ ret +diff --git a/lib/riscv64/edk2asm.h b/lib/riscv64/edk2asm.h +new file mode 100644 +index 0000000..9515eaf +--- /dev/null ++++ b/lib/riscv64/edk2asm.h +@@ -0,0 +1,6 @@ ++ ++#define ASM_PFX(x) x ++#define GCC_ASM_EXPORT(x) \ ++ .globl x ; \ ++ .type x, %function ++ +diff --git a/pe.c b/pe.c +index 9a3679e..c2a7a75 100644 +--- a/pe.c ++++ b/pe.c +@@ -602,6 +602,8 @@ allow_64_bit(void) + if (in_protocol) + return 1; + return 0; ++#elif defined (__riscv) && __riscv_xlen == 64 ++ return 1; + #else /* assuming everything else is 32-bit... */ + return 0; + #endif +@@ -622,6 +624,8 @@ allow_32_bit(void) + return 1; + #elif defined(__aarch64__) + return 0; ++#elif defined (__riscv) && __riscv_xlen == 64 ++ return 0; + #else /* assuming everything else is 32-bit... */ + return 1; + #endif +@@ -648,6 +652,8 @@ static const UINT16 machine_type = + IMAGE_FILE_MACHINE_I386; + #elif defined(__ia64__) + IMAGE_FILE_MACHINE_IA64; ++#elif defined(__riscv) && __riscv_xlen == 64 ++ IMAGE_FILE_MACHINE_RISCV64; + #else + #error this architecture is not supported by shim + #endif +diff --git a/shim.h b/shim.h +index 14824c6..e5550f4 100644 +--- a/shim.h ++++ b/shim.h +@@ -128,6 +128,21 @@ + #endif + #endif + ++#if defined(__riscv) && __riscv_xlen == 64 ++#ifndef DEFAULT_LOADER ++#define DEFAULT_LOADER L"\\grubriscv64.efi" ++#endif ++#ifndef DEFAULT_LOADER_CHAR ++#define DEFAULT_LOADER_CHAR "\\grubriscv64.efi" ++#endif ++#ifndef EFI_ARCH ++#define EFI_ARCH L"riscv64" ++#endif ++#ifndef DEBUGDIR ++#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/riscv64/" ++#endif ++#endif ++ + #ifndef DEBUGSRC + #define DEBUGSRC L"/usr/src/debug/shim-" VERSIONSTR "." EFI_ARCH + #endif +diff --git a/test-str.c b/test-str.c +index 30f8dd0..254cabc 100644 +--- a/test-str.c ++++ b/test-str.c +@@ -484,7 +484,7 @@ gnuefi_strncmp ( + * This is still broken, and fails the test case as written on arm. + * We no longer use this, so we do not strictly need to run it. + */ +-#if !defined(__arm__) && !defined(__aarch64__) ++#if !defined(__arm__) && !defined(__aarch64__) && !defined(__riscv) + static inline INTN + gnuefi_signed_strncmp ( + IN CONST CHAR8 *s1, +-- +2.34.1 + diff --git a/shim.spec b/shim.spec index 97dedce..ede57ea 100644 --- a/shim.spec +++ b/shim.spec @@ -10,6 +10,12 @@ %global bootefi BOOTX64.EFI %endif +%ifarch riscv64 +%global efi_arch riscv64 +%global bootcsv BOOTRISCV64.CSV +%global bootefi BOOTRISCV64.EFI +%endif + %global debug_package %{nil} %global __debug_package 1 %global _binaries_in_noarch_packages_terminate_build 0 @@ -21,21 +27,22 @@ %global shimBOOT /boot/efi/EFI/BOOT/ %global enable_sm 0 -%global vendor_cert %{SOURCE3} +%global vendor_cert %{SOURCE4} Name: shim Version: 15.7 -Release: 16 +Release: 17 Summary: First-stage UEFI bootloader -ExclusiveArch: x86_64 aarch64 +ExclusiveArch: x86_64 aarch64 riscv64 License: BSD URL: https://github.com/rhboot/shim Source0: https://github.com/rhboot/shim/releases/download/%{version}/shim-%{version}.tar.bz2 Source1: BOOTAA64.CSV Source2: BOOTX64.CSV -Source3: openEuler_ca.der -Source4: shimaa64-cfca.efi -Source5: shimx64-cfca.efi +Source3: BOOTRISCV64.CSV +Source4: openEuler_ca.der +Source5: shimaa64-cfca.efi +Source6: shimx64-cfca.efi Patch1:backport-CVE-2023-40546.patch Patch2:backport-CVE-2023-40551-pe-relocate-Fix-bounds-check-for-MZ-b.patch @@ -66,11 +73,18 @@ Patch9004:Feature-shim-support-sm2-and-sm3-algorithm.patch # Feature for shim TPCM support Patch9005:Feature-add-tpcm-support-with-ipmi-channel.patch +# Feature for shim RISC-V support +Patch10000:Feature-shim-support-riscv64.patch +Patch10001:Feature-shim-submodule-gnu-efi-support-riscv64.patch + BuildRequires: elfutils-libelf-devel openssl-devel openssl git pesign gnu-efi gnu-efi-devel gcc vim-common efivar-devel %ifarch aarch64 BuildRequires: binutils >= 2.37-7 %endif +%ifarch riscv64 +BuildRequires: binutils >= 2.42 +%endif Requires: dbxtool efi-filesystem mokutil Provides: bundled(openssl) = 1.0.2k Provides: shim-%{efi_arch} = %{version}-%{release} @@ -162,11 +176,14 @@ install -m 0700 *.efi ${RPM_BUILD_ROOT}/%{shimefivendor} install -m 0700 *.hash ${RPM_BUILD_ROOT}/%{shimefivendor} %ifarch aarch64 install -m 0700 %{SOURCE1} ${RPM_BUILD_ROOT}/%{shimefivendor} -install -m 0700 %{SOURCE4} ${RPM_BUILD_ROOT}/%{shimBOOT}/BOOTAA64_CFCA.EFI +install -m 0700 %{SOURCE5} ${RPM_BUILD_ROOT}/%{shimBOOT}/BOOTAA64_CFCA.EFI %endif %ifarch x86_64 install -m 0700 %{SOURCE2} ${RPM_BUILD_ROOT}/%{shimefivendor} -install -m 0700 %{SOURCE5} ${RPM_BUILD_ROOT}/%{shimBOOT}/BOOTX64_CFCA.EFI +install -m 0700 %{SOURCE6} ${RPM_BUILD_ROOT}/%{shimBOOT}/BOOTX64_CFCA.EFI +%endif +%ifarch riscv64 +install -m 0700 %{SOURCE3} ${RPM_BUILD_ROOT}/%{shimefivendor} %endif %if "%{_vendor}" != "openEuler" iconv -f UTF-16LE -t UTF-8 ${RPM_BUILD_ROOT}/%{shimefivendor}/%{bootcsv} > /tmp/%{bootcsv}.tmp @@ -213,6 +230,9 @@ make test /usr/src/debug/%{name}-%{version}-%{release}/* %changelog +* Tue Aug 5 2025 changk -15.7-17 +- shim 15.7 support riscv64 rpm build. + * Mon Jan 20 2025 xuce -15.7-16 - fix the issue that the gBS->LoadImage pointer was empty. -- Gitee