diff --git a/0021-grub-enable-kernel.kss.img-build-for-sw64_efi.patch b/0021-grub-enable-kernel.kss.img-build-for-sw64_efi.patch new file mode 100644 index 0000000000000000000000000000000000000000..8e36b2ba6042899c4e6440ef701c90c4c3b94747 --- /dev/null +++ b/0021-grub-enable-kernel.kss.img-build-for-sw64_efi.patch @@ -0,0 +1,127 @@ +From 42f4e1ab7fbecfbb4ba6832a0875d72aafc4f76a Mon Sep 17 00:00:00 2001 +From: Wang Zhijiang +Date: Thu, 1 Jun 2023 09:53:15 +0800 +Subject: [PATCH] grub: enable kernel.kss.img build for sw64_efi + +--- + grub-core/Makefile.core.def | 16 ++++++++++++++++ + grub-core/loader/sw64/efi/linux.c | 30 ++++++++++++++++++++++++++---- + 2 files changed, 42 insertions(+), 4 deletions(-) + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 1157f3736..d4c477f54 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -464,6 +464,8 @@ kernel = { + sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; + mips_arc_ldflags = '-Wl,-Ttext,$(TARGET_LINK_ADDR)'; + mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000'; ++ sw_64_efi_ldflags = '-Wl,-r,-d'; ++ sw_64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + + mips_arc_cppflags = '-DGRUB_DECOMPRESSOR_LINK_ADDR=$(TARGET_DECOMPRESSOR_LINK_ADDR)'; + i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; +@@ -478,6 +480,7 @@ kernel = { + i386_efi_cflags = '-DKSS'; + x86_64_efi_cflags = '-DKSS'; + arm64_efi_cflags = '-DKSS'; ++ sw_64_efi_cflags = '-DKSS'; + + i386_pc_startup = kern/i386/pc/startup.S; + i386_efi_startup = kern/i386/efi/startup.S; +@@ -498,6 +501,7 @@ kernel = { + arm64_efi_startup = kern/arm64/efi/startup.S; + riscv32_efi_startup = kern/riscv/efi/startup.S; + riscv64_efi_startup = kern/riscv/efi/startup.S; ++ sw_64_efi_startup = kern/sw64/efi/startup.S; + + common = kern/buffer.c; + common = kern/command.c; +@@ -703,6 +707,17 @@ kernel = { + extra_dist = video/sis315_init.c; + mips_loongson = commands/keylayouts.c; + ++ sw_64_efi = kern/sw64/dl.c; ++ sw_64_efi = kern/sw64/dl_helper.c; ++ sw_64_efi = kern/sw64/efi/init.c; ++ sw_64_efi = kern/efi/fdt.c; ++ sw_64_efi = lib/sw64/divide.S; ++ sw_64_efi = kern/sw64/efi/callwrap.S; ++ sw_64_efi = kern/sw64/cache.c; ++ sw_64_efi = kern/sw64/cache_flush.S; ++ sw_64_efi = commands/keylayouts.c; ++ sw_64_efi = kern/sw64/debug.c; ++ + powerpc_ieee1275 = kern/powerpc/cache.S; + powerpc_ieee1275 = kern/powerpc/dl.c; + powerpc_ieee1275 = kern/powerpc/compiler-rt.S; +@@ -785,6 +800,7 @@ kernel = { + enable = x86_64_efi; + enable = i386_efi; + enable = arm64_efi; ++ enable = sw_64_efi; + }; + + module = { +diff --git a/grub-core/loader/sw64/efi/linux.c b/grub-core/loader/sw64/efi/linux.c +index 51c2a98b7..5fad51230 100644 +--- a/grub-core/loader/sw64/efi/linux.c ++++ b/grub-core/loader/sw64/efi/linux.c +@@ -40,6 +40,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -200,6 +201,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + { + grub_ssize_t size; + grub_elf_t elf = 0; ++ unsigned char digest[32]; ++ char *filename = argv[0]; ++ + + grub_dl_ref (my_mod); + +@@ -211,14 +215,32 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- elf = grub_elf_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL); ++ if (grub_kss_verify(argv[0], digest)) ++ { ++ /* We should clear the errno so that the next call of grub_file_open will ++ * not failed abnormally. ++ */ ++ grub_errno = GRUB_ERR_NONE; ++ grub_printf ("fallback to bakcup kernel\n"); ++ ++ if (grub_kss_verify(KSS_FALLBACK_KERNEL, digest)) { ++ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("failed to verify the signature of backup kernel")); ++ goto fail; ++ } ++ ++ filename = KSS_FALLBACK_KERNEL; ++ } ++ ++ grub_kss_log_kernel_hash(digest); ++ ++ elf = grub_elf_open (filename, GRUB_FILE_TYPE_LINUX_KERNEL); + if (! elf) + goto fail; + +- grub_dprintf ("linux", "Loading linux: %s\n", argv[0]); +- grub_printk ("Loading linux: %s\n", argv[0]); ++ grub_dprintf ("linux", "Loading linux: %s\n", filename); ++ grub_printk ("Loading linux: %s\n", filename); + +- if (grub_load_elf64 (elf, argv[0])) ++ if (grub_load_elf64 (elf, filename)) + goto fail; + + grub_memset (sunway_boot_params, 0, sizeof(*sunway_boot_params)); +-- +2.33.0 + diff --git a/9000-Add-sw_64-support.patch b/9000-Add-sw_64-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..36969844858dafb1b149f934af130eea0cf37bca --- /dev/null +++ b/9000-Add-sw_64-support.patch @@ -0,0 +1,3578 @@ +From dcfac5c50b988c3a535005ae6f2ce79281c9195d Mon Sep 17 00:00:00 2001 +From: Yang Qiang +Date: Thu, 29 Sep 2022 18:29:57 +0800 +Subject: [PATCH] Release GRUB 2.06-100.50.2.2.0 for SW64 + +Signed-off-by: Yang Qiang +--- + include/grub/fdt.h | 4 +- + grub-core/loader/efi/chainloader.c | 2 + + Makefile.util.def | 1 + + bootstrap | 6 + + bootstrap.conf | 6 + + conf/Makefile.common | 3 + + configure.ac | 8 +- + gentpl.py | 8 +- + grub-core/Makefile.am | 7 + + grub-core/Makefile.core.def | 20 + + grub-core/commands/file.c | 11 +- + grub-core/kern/compiler-rt.c | 2 +- + grub-core/kern/efi/mm.c | 2 +- + grub-core/kern/misc.c | 57 ++ + grub-core/kern/sw64/cache.c | 63 ++ + grub-core/kern/sw64/cache_flush.S | 44 ++ + grub-core/kern/sw64/debug.c | 38 + + grub-core/kern/sw64/dl.c | 214 ++++++ + grub-core/kern/sw64/dl_helper.c | 72 ++ + grub-core/kern/sw64/efi/callwrap.S | 261 +++++++ + grub-core/kern/sw64/efi/init.c | 75 ++ + grub-core/kern/sw64/efi/startup.S | 35 + + .../lib/gnulib-patches/add-sw64-support.patch | 40 ++ + grub-core/lib/setjmp.S | 2 + + grub-core/lib/sw64/divide.S | 677 ++++++++++++++++++ + grub-core/lib/sw64/setjmp.S | 75 ++ + grub-core/loader/sw64/efi/linux.c | 330 +++++++++ + include/grub/compiler-rt.h | 2 +- + include/grub/dl.h | 14 +- + include/grub/efi/api.h | 2 +- + include/grub/efi/efi.h | 2 +- + include/grub/efi/pe32.h | 1 + + include/grub/elf.h | 42 ++ + include/grub/misc.h | 11 +- + include/grub/sw64/divide.h | 11 + + include/grub/sw64/efi/memory.h | 6 + + include/grub/sw64/efi/time.h | 23 + + include/grub/sw64/io.h | 62 ++ + include/grub/sw64/jmpbuf-offsets.h | 35 + + include/grub/sw64/kernel.h | 25 + + include/grub/sw64/linux.h | 50 ++ + include/grub/sw64/pal.h | 49 ++ + include/grub/sw64/regdef.h | 44 ++ + include/grub/sw64/setjmp.h | 28 + + include/grub/sw64/time.h | 28 + + include/grub/sw64/types.h | 32 + + include/grub/util/install.h | 1 + + include/grub/util/misc.h | 4 + + util/grub-install-common.c | 1 + + util/grub-install.c | 16 + + util/grub-mkimagexx.c | 151 +++- + util/grub-module-verifier.c | 18 + + util/misc.c | 6 + + util/mkimage.c | 16 + + 52 files changed, 2721 insertions(+), 16 deletions(-) + create mode 100644 grub-core/kern/sw64/cache.c + create mode 100644 grub-core/kern/sw64/cache_flush.S + create mode 100644 grub-core/kern/sw64/debug.c + create mode 100644 grub-core/kern/sw64/dl.c + create mode 100644 grub-core/kern/sw64/dl_helper.c + create mode 100644 grub-core/kern/sw64/efi/callwrap.S + create mode 100644 grub-core/kern/sw64/efi/init.c + create mode 100644 grub-core/kern/sw64/efi/startup.S + create mode 100644 grub-core/lib/gnulib-patches/add-sw64-support.patch + create mode 100644 grub-core/lib/sw64/divide.S + create mode 100644 grub-core/lib/sw64/setjmp.S + create mode 100644 grub-core/loader/sw64/efi/linux.c + create mode 100644 include/grub/sw64/divide.h + create mode 100644 include/grub/sw64/efi/memory.h + create mode 100644 include/grub/sw64/efi/time.h + create mode 100644 include/grub/sw64/io.h + create mode 100644 include/grub/sw64/jmpbuf-offsets.h + create mode 100644 include/grub/sw64/kernel.h + create mode 100644 include/grub/sw64/linux.h + create mode 100644 include/grub/sw64/pal.h + create mode 100644 include/grub/sw64/regdef.h + create mode 100644 include/grub/sw64/setjmp.h + create mode 100644 include/grub/sw64/time.h + create mode 100644 include/grub/sw64/types.h + +diff --git a/include/grub/fdt.h b/include/grub/fdt.h +index 3514aa4..ba2f9a9 100644 +--- a/include/grub/fdt.h ++++ b/include/grub/fdt.h +@@ -20,7 +20,7 @@ + #define GRUB_FDT_HEADER 1 + + #if !defined(GRUB_MACHINE_EMU) && \ +- (defined(__arm__) || defined(__aarch64__) || defined(__riscv)) ++ (defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__sw_64__)) + + #include + #include +@@ -148,6 +148,6 @@ int EXPORT_FUNC(grub_fdt_set_prop) (void *fdt, unsigned int nodeoffset, const ch + }) + + #endif /* !defined(GRUB_MACHINE_EMU) && \ +- (defined(__arm__) || defined(__aarch64__) || defined(__riscv)) */ ++ (defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__sw_64__)) */ + + #endif /* ! GRUB_FDT_HEADER */ +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index fb874f1..faf60ef 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -345,6 +345,8 @@ static const grub_uint16_t machine_type __attribute__((__unused__)) = + GRUB_PE32_MACHINE_I386; + #elif defined(__ia64__) + GRUB_PE32_MACHINE_IA64; ++#elif defined(__sw_64__) ++ GRUB_PE32_MACHINE_SW_64; + #elif defined(__riscv) && (__riscv_xlen == 32) + GRUB_PE32_MACHINE_RISCV32; + #elif defined(__riscv) && (__riscv_xlen == 64) +diff --git a/Makefile.util.def b/Makefile.util.def +index f8b356cc1..ebe86f06e 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -161,6 +161,7 @@ library = { + common = grub-core/io/xzio.c; + common = grub-core/io/lzopio.c; + common = grub-core/kern/ia64/dl_helper.c; ++ common = grub-core/kern/sw64/dl_helper.c; + common = grub-core/kern/arm/dl_helper.c; + common = grub-core/kern/arm64/dl_helper.c; + common = grub-core/lib/minilzo/minilzo.c; +diff --git a/bootstrap b/bootstrap +index 5b08e7e2d..fe7557afe 100755 +--- a/bootstrap ++++ b/bootstrap +@@ -162,6 +162,11 @@ bootstrap_post_import_hook() { :; } + # Override it via your own definition in bootstrap.conf. + bootstrap_epilogue() { :; } + ++# A function to be called after bootstrap_epilogue. It adds support ++# for SW64. ++# Override it via your own definition in bootstrap.conf. ++bootstrap_sunway() { :; } ++ + # The command to download all .po files for a specified domain into a + # specified directory. Fill in the first %s with the destination + # directory and the second with the domain name. +@@ -1061,6 +1066,7 @@ if test $with_gettext = yes; then + fi + + bootstrap_epilogue ++bootstrap_sunway + + echo "$0: done. Now you can run './configure'." + +diff --git a/bootstrap.conf b/bootstrap.conf +index 6b043fc35..badc90633 100644 +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -99,3 +99,9 @@ bootstrap_post_import_hook () { + bootstrap_epilogue () { + mv INSTALL.grub INSTALL + } ++ ++bootstrap_sunway () { ++ set -e ++ patch -p1 < "grub-core/lib/gnulib-patches/add-sw64-support.patch" ++ set +e ++} +diff --git a/conf/Makefile.common b/conf/Makefile.common +index 2a1a886f6..1fe0761ea 100644 +--- a/conf/Makefile.common ++++ b/conf/Makefile.common +@@ -9,6 +9,9 @@ unexport LC_ALL + if COND_sparc64_ieee1275 + LDFLAGS_PLATFORM = -Wl,-melf64_sparc + endif ++if COND_sw_64_efi ++ CFLAGS_PLATFORM += -Wno-packed-not-aligned -Wno-cast-align -Wno-sign-compare ++endif + if COND_arm + if !COND_emu + LDFLAGS_PLATFORM = -Wl,--wrap=__clear_cache +diff --git a/configure.ac b/configure.ac +index 7517fc49d..49efcb635 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -80,7 +80,7 @@ grub_TRANSFORM([grub-file]) + + # Optimization flag. Allow user to override. + if test "x$TARGET_CFLAGS" = x; then +- TARGET_CFLAGS=-Os ++ TARGET_CFLAGS=-O2 + fi + + # Enable support for "restrict" keyword and other +@@ -119,6 +119,9 @@ case "$target_cpu" in + riscv64*) + target_cpu=riscv64 + ;; ++ sw_64*) ++ target_cpu=sw64 ++ ;; + esac + + # Specify the platform (such as firmware). +@@ -144,6 +147,7 @@ if test "x$with_platform" = x; then + arm64-*) platform=efi ;; + riscv32-*) platform=efi ;; + riscv64-*) platform=efi ;; ++ sw64-*) platform=efi ;; + *) + AC_MSG_WARN([unsupported CPU: "$target_cpu" - only building utilities]) + platform=none +@@ -194,6 +198,7 @@ case "$target_cpu"-"$platform" in + arm64-efi) ;; + riscv32-efi) ;; + riscv64-efi) ;; ++ sw64-efi) ;; + *-emu) ;; + *-none) ;; + *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; +@@ -1999,6 +2004,7 @@ AM_CONDITIONAL([COND_riscv32], [test x$target_cpu = xriscv32 ]) + AM_CONDITIONAL([COND_riscv64], [test x$target_cpu = xriscv64 ]) + AM_CONDITIONAL([COND_riscv32_efi], [test x$target_cpu = xriscv32 -a x$platform = xefi]) + AM_CONDITIONAL([COND_riscv64_efi], [test x$target_cpu = xriscv64 -a x$platform = xefi]) ++AM_CONDITIONAL([COND_sw_64_efi], [test x$target_cpu = xsw64 -a x$platform = xefi]) + + AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd]) + AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) +diff --git a/gentpl.py b/gentpl.py +index c86550d4f..1a088e72c 100644 +--- a/gentpl.py ++++ b/gentpl.py +@@ -32,7 +32,8 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", + "mips_loongson", "sparc64_ieee1275", + "powerpc_ieee1275", "mips_arc", "ia64_efi", + "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi", +- "arm_coreboot", "riscv32_efi", "riscv64_efi" ] ++ "arm_coreboot", "riscv32_efi", "riscv64_efi", ++ "sw_64_efi" ] + + GROUPS = {} + +@@ -49,11 +50,12 @@ GROUPS["arm"] = [ "arm_uboot", "arm_efi", "arm_coreboot" ] + GROUPS["arm64"] = [ "arm64_efi" ] + GROUPS["riscv32"] = [ "riscv32_efi" ] + GROUPS["riscv64"] = [ "riscv64_efi" ] ++GROUPS["sw_64"] = [ "sw_64_efi" ] + + # Groups based on firmware + GROUPS["pc"] = [ "i386_pc" ] + GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi", +- "riscv32_efi", "riscv64_efi" ] ++ "riscv32_efi", "riscv64_efi", "sw_64_efi" ] + GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ] + GROUPS["uboot"] = [ "arm_uboot" ] + GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ] +@@ -79,7 +81,7 @@ GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; + for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) + + # Flattened Device Trees (FDT) +-GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi", "riscv32_efi", "riscv64_efi" ] ++GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi", "riscv32_efi", "riscv64_efi", "sw_64_efi" ] + + # Needs software helpers for division + # Must match GRUB_DIVISION_IN_SOFTWARE in misc.h +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index ee88e44e9..817efa054 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -198,6 +198,13 @@ if COND_mips + KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/kernel.h + endif + ++if COND_sw_64_efi ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sw64/divide.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h ++endif ++ + if COND_mips_arc + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arc/arc.h +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 8022e1c0a..692e649e0 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -93,6 +93,8 @@ kernel = { + sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; + mips_arc_ldflags = '-Wl,-Ttext,$(TARGET_LINK_ADDR)'; + mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000'; ++ sw_64_efi_ldflags = '-Wl,-r,-d'; ++ sw_64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + + mips_arc_cppflags = '-DGRUB_DECOMPRESSOR_LINK_ADDR=$(TARGET_DECOMPRESSOR_LINK_ADDR)'; + i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; +@@ -122,6 +124,7 @@ kernel = { + arm64_efi_startup = kern/arm64/efi/startup.S; + riscv32_efi_startup = kern/riscv/efi/startup.S; + riscv64_efi_startup = kern/riscv/efi/startup.S; ++ sw_64_efi_startup = kern/sw64/efi/startup.S; + + common = kern/buffer.c; + common = kern/command.c; +@@ -314,6 +317,17 @@ kernel = { + extra_dist = video/sis315_init.c; + mips_loongson = commands/keylayouts.c; + ++ sw_64_efi = kern/sw64/dl.c; ++ sw_64_efi = kern/sw64/dl_helper.c; ++ sw_64_efi = kern/sw64/efi/init.c; ++ sw_64_efi = kern/efi/fdt.c; ++ sw_64_efi = lib/sw64/divide.S; ++ sw_64_efi = kern/sw64/efi/callwrap.S; ++ sw_64_efi = kern/sw64/cache.c; ++ sw_64_efi = kern/sw64/cache_flush.S; ++ sw_64_efi = commands/keylayouts.c; ++ sw_64_efi = kern/sw64/debug.c; ++ + powerpc_ieee1275 = kern/powerpc/cache.S; + powerpc_ieee1275 = kern/powerpc/dl.c; + powerpc_ieee1275 = kern/powerpc/compiler-rt.S; +@@ -829,6 +843,7 @@ module = { + enable = arm_coreboot; + enable = riscv32_efi; + enable = riscv64_efi; ++ enable = sw_64_efi; + }; + + module = { +@@ -906,6 +921,7 @@ module = { + i386_multiboot = commands/acpihalt.c; + i386_efi = commands/acpihalt.c; + x86_64_efi = commands/acpihalt.c; ++ sw_64_efi = commands/acpihalt.c; + i386_multiboot = lib/i386/halt.c; + i386_coreboot = lib/i386/halt.c; + i386_qemu = lib/i386/halt.c; +@@ -1708,6 +1724,8 @@ module = { + extra_dist = lib/arm/setjmp.S; + extra_dist = lib/arm64/setjmp.S; + extra_dist = lib/riscv/setjmp.S; ++ extra_dist = lib/sw64/setjmp.S; ++ extra_dist = lib/sw64/divide.S; + }; + + module = { +@@ -1811,6 +1829,7 @@ module = { + arm64 = loader/arm64/linux.c; + riscv32 = loader/riscv/linux.c; + riscv64 = loader/riscv/linux.c; ++ sw_64_efi = loader/sw64/efi/linux.c; + emu = loader/emu/linux.c; + + common = loader/linux.c; +@@ -1908,6 +1927,7 @@ module = { + enable = riscv32_efi; + enable = riscv64_efi; + enable = mips; ++ enable = sw_64; + }; + + module = { +diff --git a/grub-core/commands/file.c b/grub-core/commands/file.c +index 9de00061e..868930bda 100644 +--- a/grub-core/commands/file.c ++++ b/grub-core/commands/file.c +@@ -94,6 +94,8 @@ static const struct grub_arg_option options[] = { + N_("Check if FILE is RISC-V 32bit EFI file"), 0, 0}, + {"is-riscv64-efi", 0, 0, + N_("Check if FILE is RISC-V 64bit EFI file"), 0, 0}, ++ {"is-sw64-efi", 0, 0, ++ N_("Check if FILE is SW64 EFI file"), 0, 0}, + {"is-hibernated-hiberfil", 0, 0, + N_("Check if FILE is hiberfil.sys in hibernated state"), 0, 0}, + {"is-x86_64-xnu", 0, 0, +@@ -136,6 +138,7 @@ enum + IS_ARM_EFI, + IS_RISCV32_EFI, + IS_RISCV64_EFI, ++ IS_SW64_EFI, + IS_HIBERNATED, + IS_XNU64, + IS_XNU32, +@@ -579,6 +582,7 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args) + case IS_ARM_EFI: + case IS_RISCV32_EFI: + case IS_RISCV64_EFI: ++ case IS_SW64_EFI: + { + char signature[4]; + grub_uint32_t pe_offset; +@@ -629,8 +633,13 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args) + grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_RISCV64)) + /* TODO: Determine bitness dynamically */ + break; ++ if (type == IS_SW64_EFI ++ && coff_head.machine != ++ grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_SW_64)) ++ /* TODO: Determine bitness dynamically */ ++ break; + if (type == IS_IA_EFI || type == IS_64_EFI || type == IS_ARM64_EFI || +- type == IS_RISCV32_EFI || type == IS_RISCV64_EFI) ++ type == IS_RISCV32_EFI || type == IS_RISCV64_EFI || type == IS_SW64_EFI) + { + struct grub_pe64_optional_header o64; + if (grub_file_read (file, &o64, sizeof (o64)) != sizeof (o64)) +diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c +index 2057c2e0c..aac8742bc 100644 +--- a/grub-core/kern/compiler-rt.c ++++ b/grub-core/kern/compiler-rt.c +@@ -345,7 +345,7 @@ __ucmpdi2 (grub_uint64_t a, grub_uint64_t b) + #endif + + #if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || \ +- defined(__arm__) || defined(__riscv) ++ defined(__arm__) || defined(__riscv) || defined(__sw_64__) + + /* Based on libgcc2.c from gcc suite. */ + grub_uint32_t +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 9838fb2f5..5c0b108a6 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -659,7 +659,7 @@ grub_efi_mm_init (void) + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + } + +-#if defined (__aarch64__) || defined (__arm__) || defined (__riscv) ++#if defined (__aarch64__) || defined (__arm__) || defined (__riscv) || defined (__sw_64__) + grub_err_t + grub_efi_get_ram_base(grub_addr_t *base_addr) + { +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index 3af336ee2..fdb91ecd9 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -133,6 +133,21 @@ grub_printf_ (const char *fmt, ...) + return ret; + } + ++#ifdef __sw_64__ ++int ++grub_printk (const char *fmt, ...) ++{ ++ va_list ap; ++ int ret; ++ ++ va_start (ap, fmt); ++ ret = grub_vprintk (fmt, ap); ++ va_end (ap); ++ ++ return ret; ++} ++#endif ++ + int + grub_puts_ (const char *s) + { +@@ -221,6 +236,9 @@ grub_vprintf (const char *fmt, va_list ap) + + free_printf_args (&args); + ++#ifdef __sw_64__ ++ sunway_debug_delegate(curbuf); ++#endif + grub_xputs (curbuf); + + if (curbuf != buf) +@@ -229,6 +247,45 @@ grub_vprintf (const char *fmt, va_list ap) + return s; + } + ++#ifdef __sw_64__ ++int ++grub_vprintk (const char *fmt, va_list ap) ++{ ++ grub_size_t s; ++ static char buf[PREALLOC_SIZE + 1]; ++ char *curbuf = buf; ++ struct printf_args args; ++ ++ parse_printf_args (fmt, &args, ap); ++ ++ s = grub_vsnprintf_real (buf, PREALLOC_SIZE, fmt, &args); ++ if (s > PREALLOC_SIZE) ++ { ++ curbuf = grub_malloc (s + 1); ++ if (!curbuf) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ buf[PREALLOC_SIZE - 3] = '.'; ++ buf[PREALLOC_SIZE - 2] = '.'; ++ buf[PREALLOC_SIZE - 1] = '.'; ++ buf[PREALLOC_SIZE] = 0; ++ curbuf = buf; ++ } ++ else ++ s = grub_vsnprintf_real (curbuf, s, fmt, &args); ++ } ++ ++ free_printf_args (&args); ++ ++ sunway_debug_delegate(curbuf); ++ ++ if (curbuf != buf) ++ grub_free (curbuf); ++ ++ return s; ++} ++#endif ++ + int + grub_memcmp (const void *s1, const void *s2, grub_size_t n) + { +diff --git a/grub-core/kern/sw64/cache.c b/grub-core/kern/sw64/cache.c +new file mode 100644 +index 000000000..9278dda83 +--- /dev/null ++++ b/grub-core/kern/sw64/cache.c +@@ -0,0 +1,63 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++ ++static grub_int64_t dlinesz; ++static grub_int64_t ilinesz; ++ ++/* Prototypes for asm functions. */ ++void grub_arch_clean_dcache_range (grub_addr_t beg, grub_addr_t end, ++ grub_size_t line_size); ++void grub_arch_invalidate_icache_range (grub_addr_t beg, grub_addr_t end, ++ grub_size_t line_size); ++ ++static void ++probe_caches (void) ++{ ++ /* TODO */ ++ dlinesz = 128; ++ ilinesz = 128; ++} ++ ++void ++grub_arch_sync_caches (void *address, grub_size_t len) ++{ ++ grub_size_t start, end, max_align; ++ ++ if (dlinesz == 0) ++ probe_caches(); ++ if (dlinesz == 0) ++ grub_fatal ("Unknown cache line size!"); ++ ++ max_align = dlinesz > ilinesz ? dlinesz : ilinesz; ++ ++ start = ALIGN_DOWN ((grub_size_t) address, max_align); ++ end = ALIGN_UP ((grub_size_t) address + len, max_align); ++ ++ grub_arch_clean_dcache_range (start, end, dlinesz); ++ grub_arch_invalidate_icache_range (start, end, ilinesz); ++} ++ ++void ++grub_arch_sync_dma_caches (volatile void *address __attribute__((unused)), ++ grub_size_t len __attribute__((unused))) ++{ ++ /* DMA incoherent devices not supported yet */ ++} +diff --git a/grub-core/kern/sw64/cache_flush.S b/grub-core/kern/sw64/cache_flush.S +new file mode 100644 +index 000000000..dde3e5c3e +--- /dev/null ++++ b/grub-core/kern/sw64/cache_flush.S +@@ -0,0 +1,44 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++ ++ .file "cache_flush.S" ++ .text ++ ++/* ++ * Simple cache maintenance functions ++ */ ++ ++/* ++ * a0 - *beg (inclusive) ++ * a1 - *end (exclusive) ++ * a2 - line size ++*/ ++FUNCTION(grub_arch_clean_dcache_range) ++ /* TODO */ ++ ret ++ ++/* ++ * a0 - *beg (inclusive) ++ * a1 - *end (exclusive) ++ * a2 - line size ++ */ ++FUNCTION(grub_arch_invalidate_icache_range) ++ memb ++ ret +diff --git a/grub-core/kern/sw64/debug.c b/grub-core/kern/sw64/debug.c +new file mode 100644 +index 000000000..2d9fe240c +--- /dev/null ++++ b/grub-core/kern/sw64/debug.c +@@ -0,0 +1,38 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++ ++void sunway_debug_delegate(char *buffer) ++{ ++ unsigned int *print_base = (unsigned int *)(GRUB_PRINTK_START + GRUB_PRINTK_SIZE - sizeof(int)); ++ unsigned int bytes_written = *print_base; ++ int num_bytes = grub_strlen(buffer); ++ ++ if ((bytes_written + num_bytes) > (GRUB_PRINTK_SIZE - sizeof(unsigned int))) ++ { ++ grub_memset((void *)GRUB_PRINTK_START, 0, GRUB_PRINTK_SIZE); ++ bytes_written = *print_base = 0; ++ } ++ ++ grub_memcpy((void *)(GRUB_PRINTK_START + bytes_written), (void *)buffer, num_bytes); ++ *print_base += num_bytes; ++ ++ return ; ++} +diff --git a/grub-core/kern/sw64/dl.c b/grub-core/kern/sw64/dl.c +new file mode 100644 +index 000000000..8e3cac26b +--- /dev/null ++++ b/grub-core/kern/sw64/dl.c +@@ -0,0 +1,214 @@ ++/* dl.c - arch-dependent part of loadable module support */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * Check if EHDR is a valid ELF header. ++ */ ++grub_err_t ++grub_arch_dl_check_header (void *ehdr) ++{ ++ Elf_Ehdr *e = ehdr; ++ ++ /* Check the magic numbers. */ ++ if (e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_SW_64) ++ return grub_error (GRUB_ERR_BAD_OS, ++ N_("invalid arch-dependent ELF magic")); ++ ++ return GRUB_ERR_NONE; ++} ++ ++#pragma GCC diagnostic ignored "-Wcast-align" ++ ++/* Relocate symbols. */ ++grub_err_t ++grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, ++ Elf_Shdr *s, grub_dl_segment_t seg) ++{ ++ Elf_Rela *rel, *max; ++ grub_uint64_t *gpptr, *gotptr; ++ ++ gotptr = (grub_uint64_t *) mod->got; ++ gpptr = (grub_uint64_t *) ((grub_uint64_t) mod->got + 0x8000); ++ ++ for (rel = (Elf_Rela *) ((char *) ehdr + s->sh_offset), ++ max = (Elf_Rela *) ((char *) rel + s->sh_size); ++ rel < max; ++ rel = (Elf_Rela *) ((char *) rel + s->sh_entsize)) ++ { ++ grub_addr_t addr; ++ Elf_Sym *sym; ++ grub_uint64_t value; ++ ++ if (seg->size < (rel->r_offset & ~3)) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "reloc offset is out of the segment"); ++ ++ addr = (grub_addr_t) seg->addr + rel->r_offset; ++ sym = (Elf_Sym *) ((char *) mod->symtab ++ + mod->symsize * ELF_R_SYM (rel->r_info)); ++ ++ /* On the PPC the value does not have an explicit ++ addend, add it. */ ++ value = sym->st_value + rel->r_addend; ++ ++ switch (ELF_R_TYPE (rel->r_info)) ++ { ++ case R_SW64_NONE: ++ break; ++ case R_SW64_REFLONG: ++ *(grub_uint32_t *)addr = value; ++ break; ++ case R_SW64_REFQUAD: ++ { ++ *(grub_uint32_t *)addr = value; ++ *((grub_uint32_t *)addr + 1) = value >> 32; ++ break; ++ } ++ case R_SW64_GPREL32: ++ { ++ value -= (grub_uint64_t)gpptr; ++ if ((grub_int32_t)value != value) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "R_SW64_GPREL32 relocation out of range"); ++ *(grub_uint32_t *) addr = value; ++ break; ++ } ++ case R_SW64_LITERAL: ++ { ++ grub_uint64_t li_hi; ++ grub_uint64_t li_lo; ++ ++ li_hi = (grub_uint64_t) gotptr + (((grub_uint64_t)ELF_R_TYPE(rel->r_info)) >> 8 ); ++ li_lo = li_hi - ((grub_uint64_t) gpptr); ++ if ((grub_int16_t)li_lo != li_lo) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "R_SW64_LITERAL relocation out of range"); ++ ++ *(grub_uint16_t *) addr = (li_lo & 0xffff); ++ *(grub_uint64_t *) (li_hi) = value; ++ gotptr++; ++ break; ++ } ++ case R_SW64_LITERAL_GOT: ++ break; ++ case R_SW64_LITUSE: ++ break; ++ case R_SW64_GPDISP: ++ { ++ grub_uint64_t hi; ++ grub_uint64_t lo; ++ grub_uint64_t gpoffset = (grub_int64_t)gpptr - addr; ++ lo = (grub_int16_t) gpoffset; ++ hi = (grub_int32_t) (gpoffset - lo); ++ if (hi + lo != gpoffset) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "R_SW64_GPDISP relocation out of range"); ++ ++ if (gpoffset & 0x8000) { ++ hi = ((gpoffset + 0x8000) >> 16) & 0xffff; ++ lo = gpoffset & 0xffff; ++ } else { ++ hi = (gpoffset >> 16) & 0xffff; ++ lo = gpoffset & 0xffff; ++ } ++ ++ *(grub_uint32_t *) addr = ( *(grub_uint32_t *)addr & 0xffff0000) | (hi & 0xffff); ++ *(grub_uint32_t *) ((unsigned long)addr + rel->r_addend) = ++ (((*(grub_uint32_t *)((unsigned long)addr + rel->r_addend)) & 0xffff0000) | (lo & 0xffff)); ++ break; ++ } ++ case R_SW64_BRADDR: ++ { ++ grub_uint64_t braddr = (*(grub_uint64_t *)addr) + value - ((grub_uint64_t)addr + 4); ++ braddr = (grub_int64_t)braddr >> 2; ++ if (braddr + (1<<21) >= 1<<21) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "R_SW64_BRADDR relocation out of range"); ++ ++ *(grub_uint32_t *) addr = (*(grub_uint32_t *)addr & (~0x1fffff)) | (braddr & 0x1fffff); ++ break; ++ } ++ case R_SW64_HINT: ++ break; ++ case R_SW64_SREL32: ++ { ++ value -= (grub_uint64_t)addr; ++ if ((grub_int32_t)value != value) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "R_SW64_SREL32 relocation out of range"); ++ ++ *(grub_uint32_t *) addr = value; ++ break; ++ } ++ case R_SW64_SREL64: ++ { ++ grub_uint64_t srel64 = *(grub_uint64_t *)addr + value;; ++ srel64 -= (grub_uint64_t)addr; ++ *(grub_uint64_t *) addr = srel64; ++ break; ++ } ++ case R_SW64_GPRELHIGH: ++ { ++ grub_uint64_t gprel_hi = (grub_int64_t)(value - (grub_uint64_t)gpptr); ++ ++ if (gprel_hi & 0x8000) ++ gprel_hi = (grub_int64_t)(((grub_int64_t)gprel_hi + 0x8000) >> 16); ++ else ++ gprel_hi = (grub_int64_t)gprel_hi >> 16; ++ ++ if ((grub_int16_t)gprel_hi != gprel_hi) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "GPRELHIGH out of range\n"); ++ ++ *(grub_uint32_t *) addr = (*(grub_uint32_t *)addr & 0xffff0000) | (gprel_hi & 0xffff); ++ break; ++ } ++ case R_SW64_GPRELLOW: ++ { ++ grub_uint64_t gprel_lo = value - (grub_uint64_t)gpptr; ++ *(grub_uint32_t *) addr = (*(grub_uint32_t *)addr & 0xffff0000) | (gprel_lo & 0xffff); ++ break; ++ } ++ case R_SW64_GPREL16: ++ { ++ grub_uint64_t gprel16 = (*(grub_uint64_t *)addr + value); ++ gprel16 = (grub_uint64_t)(gprel16 - (grub_uint64_t)gpptr); ++ if ((grub_int16_t)gprel16 != gprel16) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "R_SW64_GPREL16 relocation out of range"); ++ *(grub_uint16_t *) addr = gprel16; ++ break; ++ } ++ default: ++ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ N_("relocation 0x%lx is not implemented yet"), ++ ELF_R_TYPE (rel->r_info)); ++ } ++ } ++ ++ return GRUB_ERR_NONE; ++} +diff --git a/grub-core/kern/sw64/dl_helper.c b/grub-core/kern/sw64/dl_helper.c +new file mode 100644 +index 000000000..9628ddf7b +--- /dev/null ++++ b/grub-core/kern/sw64/dl_helper.c +@@ -0,0 +1,72 @@ ++/* dl.c - arch-dependent part of loadable module support */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2002,2004,2005,2007,2009 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#pragma GCC diagnostic ignored "-Wcast-align" ++ ++grub_err_t ++grub_sw64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, ++ grub_size_t *got) ++{ ++ const Elf64_Ehdr *e = ehdr; ++ grub_size_t cntt = 0, cntg = 0;; ++ const Elf64_Shdr *s; ++ unsigned i; ++ ++ *tramp = 0; ++ *got = 0; ++ ++ /* Find a symbol table. */ ++ for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); ++ i < grub_le_to_cpu16 (e->e_shnum); ++ i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) ++ if (grub_le_to_cpu32 (s->sh_type) == SHT_SYMTAB) ++ break; ++ ++ if (i == grub_le_to_cpu16 (e->e_shnum)) ++ return GRUB_ERR_NONE; ++ ++ for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); ++ i < grub_le_to_cpu16 (e->e_shnum); ++ i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) ++ if (grub_le_to_cpu32 (s->sh_type) == SHT_RELA) ++ { ++ Elf64_Rela *rel, *max; ++ ++ for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu32 (s->sh_offset)), ++ max = rel + grub_le_to_cpu32 (s->sh_size) / grub_le_to_cpu16 (s->sh_entsize); ++ rel < max; rel++) ++ switch (ELF64_R_TYPE (grub_le_to_cpu32 (rel->r_info))) ++ { ++ case R_SW64_LITERAL: ++ cntg++; ++ break; ++ } ++ } ++ *tramp = cntt; ++ *got = cntg * sizeof (grub_uint64_t); ++ ++ return GRUB_ERR_NONE; ++} ++ +diff --git a/grub-core/kern/sw64/efi/callwrap.S b/grub-core/kern/sw64/efi/callwrap.S +new file mode 100644 +index 000000000..13ee13d68 +--- /dev/null ++++ b/grub-core/kern/sw64/efi/callwrap.S +@@ -0,0 +1,261 @@ ++ .file "callwrap.S" ++ .text ++ .align 4 ++ .globl sw_efi_wrap_0 ++ .globl sw_efi_wrap_1 ++ .globl sw_efi_wrap_2 ++ .globl sw_efi_wrap_3 ++ .globl sw_efi_wrap_4 ++ .globl sw_efi_wrap_5 ++ .globl sw_efi_wrap_6 ++ .globl sw_efi_wrap_7 ++ .globl sw_efi_wrap_10 ++ ++ .ent sw_efi_wrap_0 ++sw_efi_wrap_0: ++ ++ ldi $30,-32($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ ldl $27,16($15) ++ call $26,($27),0 ++ #ldi $29,0($29) !gpdisp!29 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,32($30) ++ ret $31,($26),1 ++ ++ .end sw_efi_wrap_0 ++ ++ .ent sw_efi_wrap_1 ++sw_efi_wrap_1: ++ ++ ldi $30,-32($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ stl $17,24($15) ++ ldl $27,16($15) ++ ldl $16,24($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!31 ++ #ldi $29,0($29) !gpdisp!31 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,32($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_1 ++ ++ .ent sw_efi_wrap_2 ++sw_efi_wrap_2: ++ ldi $30,-48($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ stl $17,24($15) ++ stl $18,32($15) ++ ldl $27,16($15) ++ ldl $16,24($15) ++ ldl $17,32($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!33 ++ #ldi $29,0($29) !gpdisp!33 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,48($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_2 ++ ++ .ent sw_efi_wrap_3 ++sw_efi_wrap_3: ++ ldi $30,-48($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ stl $17,24($15) ++ stl $18,32($15) ++ stl $19,40($15) ++ ldl $27,16($15) ++ ldl $16,24($15) ++ ldl $17,32($15) ++ ldl $18,40($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!35 ++ #ldi $29,0($29) !gpdisp!35 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,48($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_3 ++ ++ .ent sw_efi_wrap_4 ++sw_efi_wrap_4: ++ ldi $30,-64($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ stl $17,24($15) ++ stl $18,32($15) ++ stl $19,40($15) ++ stl $20,48($15) ++ ldl $27,16($15) ++ ldl $16,24($15) ++ ldl $17,32($15) ++ ldl $18,40($15) ++ ldl $19,48($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!37 ++ #ldi $29,0($29) !gpdisp!37 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,64($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_4 ++ ++ .ent sw_efi_wrap_5 ++sw_efi_wrap_5: ++ ldi $30,-64($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ stl $17,24($15) ++ stl $18,32($15) ++ stl $19,40($15) ++ stl $20,48($15) ++ stl $21,56($15) ++ ldl $27,16($15) ++ ldl $16,24($15) ++ ldl $17,32($15) ++ ldl $18,40($15) ++ ldl $19,48($15) ++ ldl $20,56($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!39 ++ #ldi $29,0($29) !gpdisp!39 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,64($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_5 ++ ++ ++ .ent sw_efi_wrap_6 ++sw_efi_wrap_6: ++ ldi $30,-64($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ stl $17,24($15) ++ stl $18,32($15) ++ stl $19,40($15) ++ stl $20,48($15) ++ stl $21,56($15) ++ ldl $27,16($15) ++ ldl $16,24($15) ++ ldl $17,32($15) ++ ldl $18,40($15) ++ ldl $19,48($15) ++ ldl $20,56($15) ++ ldl $21,64($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!41 ++ #ldi $29,0($29) !gpdisp!41 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,64($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_6 ++ ++ .ent sw_efi_wrap_7 ++sw_efi_wrap_7: ++ ldi $30,-80($30) ++ stl $26,16($30) ++ stl $15,24($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,32($15) ++ stl $17,40($15) ++ stl $18,48($15) ++ stl $19,56($15) ++ stl $20,64($15) ++ stl $21,72($15) ++ ldl $1,88($15) ++ stl $1,0($30) ++ ldl $27,32($15) ++ ldl $16,40($15) ++ ldl $17,48($15) ++ ldl $18,56($15) ++ ldl $19,64($15) ++ ldl $20,72($15) ++ ldl $21,80($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!43 ++ #ldi $29,0($29) !gpdisp!43 ++ mov $15,$30 ++ ldl $26,16($30) ++ ldl $15,24($30) ++ ldi $30,80($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_7 ++ ++ ++ .ent sw_efi_wrap_10 ++sw_efi_wrap_10: ++ ldi $30,-96($30) ++ stl $26,32($30) ++ stl $15,40($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,48($15) ++ stl $17,56($15) ++ stl $18,64($15) ++ stl $19,72($15) ++ stl $20,80($15) ++ stl $21,88($15) ++ ldl $1,104($15) ++ stl $1,0($30) ++ ldl $1,112($15) ++ stl $1,8($30) ++ ldl $1,120($15) ++ stl $1,16($30) ++ ldl $1,128($15) ++ stl $1,24($30) ++ ldl $27,48($15) ++ ldl $16,56($15) ++ ldl $17,64($15) ++ ldl $18,72($15) ++ ldl $19,80($15) ++ ldl $20,88($15) ++ ldl $21,96($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!45 ++ #ldi $29,0($29) !gpdisp!45 ++ mov $15,$30 ++ ldl $26,32($30) ++ ldl $15,40($30) ++ ldi $30,96($30) ++ ret $31,($26),1 ++ ++ .end sw_efi_wrap_10 +diff --git a/grub-core/kern/sw64/efi/init.c b/grub-core/kern/sw64/efi/init.c +new file mode 100644 +index 000000000..1a1b2392b +--- /dev/null ++++ b/grub-core/kern/sw64/efi/init.c +@@ -0,0 +1,75 @@ ++/* init.c - initialize a riscv-based EFI system */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++grub_uint64_t cycle_freq; ++ ++static grub_uint64_t ++rpcc(void) ++{ ++ grub_uint64_t result; ++ ++ asm volatile ("rtc %0" : "=r"(result)); ++ ++ return result; ++} ++ ++static grub_uint64_t ++grub_efi_get_time_ms(void) ++{ ++ cycle_freq = cpuid(GET_CPU_FREQ, 0) * 1000UL * 1000UL; ++ ++ return rpcc() * 1000 / cycle_freq; ++} ++ ++static void ++grub_print_info (void) ++{ ++ grub_printk ("GNU %s %s\n", PACKAGE_NAME, PACKAGE_VERSION); ++ grub_printk ("CPU freq: %ld Mhz\n", cpuid(GET_CPU_FREQ, 0)); ++ grub_printk ("Build Time: %s %s\n", __DATE__, __TIME__); ++} ++ ++void ++grub_machine_init (void) ++{ ++ grub_efi_init (); ++ grub_print_info (); ++ grub_install_get_time_ms (grub_efi_get_time_ms); ++} ++ ++void ++grub_machine_fini (int flags) ++{ ++ if (!(flags & GRUB_LOADER_FLAG_NORETURN)) ++ return; ++ ++ grub_efi_fini (); ++ ++ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY)) ++ grub_efi_memory_fini (); ++} +diff --git a/grub-core/kern/sw64/efi/startup.S b/grub-core/kern/sw64/efi/startup.S +new file mode 100644 +index 000000000..a78cf5cf3 +--- /dev/null ++++ b/grub-core/kern/sw64/efi/startup.S +@@ -0,0 +1,35 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++ .file "startup.S" ++ .text ++FUNCTION(start) ++FUNCTION(_start) ++ /* ++ * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in a1/a0. ++ */ ++ ldih $29,0($27) !gpdisp!1 ++ ldi $29,0($29) !gpdisp!1 ++ ldi $20, EXT_C(grub_efi_image_handle) ++ stl a0, 0($20) ++ ldi $20, EXT_C(grub_efi_system_table) ++ stl a1, 0($20) ++ call $31, grub_main ++ ret +diff --git a/grub-core/lib/gnulib-patches/add-sw64-support.patch b/grub-core/lib/gnulib-patches/add-sw64-support.patch +new file mode 100644 +index 000000000..e5d9d4974 +--- /dev/null ++++ b/grub-core/lib/gnulib-patches/add-sw64-support.patch +@@ -0,0 +1,40 @@ ++diff --git a/build-aux/config.guess b/build-aux/config.guess ++index 8e2a58b86..d664f14cf 100755 ++--- a/build-aux/config.guess +++++ b/build-aux/config.guess ++@@ -930,6 +930,10 @@ EOF ++ UNAME_MACHINE=aarch64_be ++ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" ++ exit ;; +++ sw_64:Linux:*:*) +++ UNAME_MACHINE=sw_64 +++ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +++ exit ;; ++ alpha:Linux:*:*) ++ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in ++ EV5) UNAME_MACHINE=alphaev5 ;; ++diff --git a/build-aux/config.sub b/build-aux/config.sub ++index 1fc4cde1d..4bc0f8dbf 100755 ++--- a/build-aux/config.sub +++++ b/build-aux/config.sub ++@@ -917,6 +917,10 @@ case $basic_machine in ++ cpu=sparc ++ vendor=`echo "$basic_machine" | sed 's/-.*//'` ++ ;; +++ sw_64*) +++ cpu=sw_64 +++ vendor=sunway +++ ;; ++ ++ *-*) ++ # shellcheck disable=SC2162 ++@@ -1150,6 +1154,9 @@ case $cpu-$vendor in ++ tile*-*) ++ os=${os:-linux-gnu} ++ ;; +++ sw_64-*) +++ os=${os:-linux-gnu} +++ ;; ++ ++ *) ++ # Recognize the canonical CPU types that are allowed with any +diff --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S +index aa297ab0a..483ba1223 100644 +--- a/grub-core/lib/setjmp.S ++++ b/grub-core/lib/setjmp.S +@@ -17,6 +17,8 @@ + #include "./arm64/setjmp.S" + #elif defined(__riscv) + #include "./riscv/setjmp.S" ++#elif defined(__sw_64__) ++#include "./sw64/setjmp.S" + #else + #error "Unknown target cpu type" + #endif +diff --git a/grub-core/lib/sw64/divide.S b/grub-core/lib/sw64/divide.S +new file mode 100644 +index 000000000..980aba670 +--- /dev/null ++++ b/grub-core/lib/sw64/divide.S +@@ -0,0 +1,677 @@ ++/* ++ * divide.S ++ * ++ * (C) 1995 Linus Torvalds ++ * ++ * Alpha division.. ++ */ ++ ++/* ++ * The alpha chip doesn't provide hardware division, so we have to do it ++ * by hand. The compiler expects the functions ++ * ++ * __divqu: 64-bit unsigned long divide ++ * __remqu: 64-bit unsigned long remainder ++ * __divqs/__remqs: signed 64-bit ++ * __divlu/__remlu: unsigned 32-bit ++ * __divls/__remls: signed 32-bit ++ * ++ * These are not normal C functions: instead of the normal ++ * calling sequence, these expect their arguments in registers ++ * $24 and $25, and return the result in $27. Register $28 may ++ * be clobbered (assemembly temporary), anything else must be saved. ++ * ++ * In short: painful. ++ * ++ * This is a rather simple bit-at-a-time algorithm: it's very good ++ * at dividing random 64-bit numembers, but the more usual case where ++ * the divisor is small is handled better by the DEC algorithm ++ * using lookup tables. This uses much less memory, though, and is ++ * nicer on the cache.. Besides, I don't know the copyright status ++ * of the DEC code. ++ */ ++ ++/* ++ * My temporaries: ++ * $0 - current bit ++ * $1 - shifted divisor ++ * $2 - modulus/quotient ++ * ++ * $23 - return address ++ * $24 - dividend ++ * $25 - divisor ++ * ++ * $27 - quotient/modulus ++ * $28 - compare status ++ */ ++ ++#define halt .long 0 ++ ++/* ++ * Select function type and registers ++ */ ++#define mask $0 ++#define divisor $1 ++#define compare $28 ++#define tmp1 $3 ++#define tmp2 $4 ++ ++#define DIV ++#define INTSIZE ++ ++#undef DIV_ONLY ++#undef MOD_ONLY ++#undef func ++#undef modulus ++#undef quotient ++#undef GETSIGN ++#undef STACK ++#undef ufunction ++#undef sfunction ++#undef LONGIFY ++#undef SLONGIFY ++ ++#ifdef DIV ++#define DIV_ONLY(x,y...) x,##y ++#define MOD_ONLY(x,y...) ++#define func(x) __div##x ++#define modulus $2 ++#define quotient $27 ++#define GETSIGN(x) xor $24,$25,x ++#define STACK 48 ++#else ++#define DIV_ONLY(x,y...) ++#define MOD_ONLY(x,y...) x,##y ++#define func(x) __rem##x ++#define modulus $27 ++#define quotient $2 ++#define GETSIGN(x) bis $24,$24,x ++#define STACK 32 ++#endif ++ ++/* ++ * For 32-bit operations, we need to extend to 64-bit ++ */ ++#ifdef INTSIZE ++#define ufunction func(wu) ++#define sfunction func(w) ++#define LONGIFY(x) zapnot x,15,x ++/* define SLONGIFY(x) addw x,0,x */ ++#define SLONGIFY(x) ++#else ++#define ufunction func(lu) ++#define sfunction func(l) ++#define LONGIFY(x) ++#define SLONGIFY(x) ++#endif ++ ++.set noat ++.align 3 ++.globl ufunction ++.ent ufunction ++ufunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ ++7: stl $1, 0($30) ++ bis $25,$25,divisor ++ stl $2, 8($30) ++ bis $24,$24,modulus ++ stl $0,16($30) ++ bis $31,$31,quotient ++ LONGIFY(divisor) ++ stl tmp1,24($30) ++ LONGIFY(modulus) ++ bis $31,1,mask ++ DIV_ONLY(stl tmp2,32($30)) ++ beq divisor, 9f /* div by zero */ ++ ++#ifdef INTSIZE ++ /* ++ * shift divisor left, using 3-bit shifts for ++ * 32-bit divides as we can't overflow. Three-bit ++ * shifts will result in looping three times less ++ * here, but can result in two loops more later. ++ * Thus using a large shift isn't worth it (and ++ * s8add pairs better than a sll..) ++ */ ++1: cmpult divisor,modulus,compare ++ s8addl divisor,$31,divisor ++ s8addl mask,$31,mask ++ bne compare,1b ++#else ++1: cmpult divisor,modulus,compare ++ blt divisor, 2f ++ addl divisor,divisor,divisor ++ addl mask,mask,mask ++ bne compare,1b ++ nop ++#endif ++ ++ /* ok, start to go right again.. */ ++2: DIV_ONLY(addl quotient,mask,tmp2) ++ srl mask,1,mask ++ cmpule divisor,modulus,compare ++ subl modulus,divisor,tmp1 ++ DIV_ONLY(selne compare,tmp2,quotient,quotient) ++ srl divisor,1,divisor ++ selne compare,tmp1,modulus,modulus ++ bne mask,2b ++ ++9: ldl $1, 0($30) ++ ldl $2, 8($30) ++ ldl $0,16($30) ++ ldl tmp1,24($30) ++ DIV_ONLY(ldl tmp2,32($30)) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end ufunction ++ ++/* ++ * Uhh.. Ugly signed division. I'd rather not have it at all, but ++ * it's needed in some circumstances. There are different ways to ++ * handle this, really. This does: ++ * -a / b = a / -b = -(a / b) ++ * -a % b = -(a % b) ++ * a % -b = a % b ++ * which is probably not the best solution, but at least should ++ * have the property that (x/y)*y + (x%y) = x. ++ */ ++.align 3 ++.globl sfunction ++.ent sfunction ++sfunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ bis $24,$25,$28 ++ SLONGIFY($28) ++ bge $28,7b ++ stl $24,0($30) ++ subl $31,$24,$28 ++ stl $25,8($30) ++ sellt $24,$28,$24,$24 /* abs($24) */ ++ stl $23,16($30) ++ subl $31,$25,$28 ++ stl tmp1,24($30) ++ sellt $25,$28,$25,$25 /* abs($25) */ ++ nop ++ bsr $23,ufunction ++ ldl $24,0($30) ++ ldl $25,8($30) ++ GETSIGN($28) ++ subl $31,$27,tmp1 ++ SLONGIFY($28) ++ ldl $23,16($30) ++ sellt $28,tmp1,$27,$27 ++ ldl tmp1,24($30) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end sfunction ++ ++/*rem 32 */ ++ ++#undef DIV_ONLY ++#undef MOD_ONLY ++#undef func ++#undef modulus ++#undef quotient ++#undef GETSIGN ++#undef STACK ++#undef ufunction ++#undef sfunction ++#undef LONGIFY ++#undef SLONGIFY ++ ++ ++#undef DIV ++ ++ ++#ifdef DIV ++#define DIV_ONLY(x,y...) x,##y ++#define MOD_ONLY(x,y...) ++#define func(x) __div##x ++#define modulus $2 ++#define quotient $27 ++#define GETSIGN(x) xor $24,$25,x ++#define STACK 48 ++#else ++#define DIV_ONLY(x,y...) ++#define MOD_ONLY(x,y...) x,##y ++#define func(x) __rem##x ++#define modulus $27 ++#define quotient $2 ++#define GETSIGN(x) bis $24,$24,x ++#define STACK 32 ++#endif ++ ++/* ++ * For 32-bit operations, we need to extend to 64-bit ++ */ ++#ifdef INTSIZE ++#define ufunction func(wu) ++#define sfunction func(w) ++#define LONGIFY(x) zapnot x,15,x ++#define SLONGIFY(x) ++#else ++#define ufunction func(lu) ++#define sfunction func(l) ++#define LONGIFY(x) ++#define SLONGIFY(x) ++#endif ++ ++.align 3 ++.globl ufunction ++.ent ufunction ++ufunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ ++7: stl $1, 0($30) ++ bis $25,$25,divisor ++ stl $2, 8($30) ++ bis $24,$24,modulus ++ stl $0,16($30) ++ bis $31,$31,quotient ++ LONGIFY(divisor) ++ stl tmp1,24($30) ++ LONGIFY(modulus) ++ bis $31,1,mask ++ DIV_ONLY(stl tmp2,32($30)) ++ beq divisor, 9f /* div by zero */ ++ ++#ifdef INTSIZE ++ /* ++ * shift divisor left, using 3-bit shifts for ++ * 32-bit divides as we can't overflow. Three-bit ++ * shifts will result in looping three times less ++ * here, but can result in two loops more later. ++ * Thus using a large shift isn't worth it (and ++ * s8add pairs better than a sll..) ++ */ ++1: cmpult divisor,modulus,compare ++ s8addl divisor,$31,divisor ++ s8addl mask,$31,mask ++ bne compare,1b ++#else ++1: cmpult divisor,modulus,compare ++ blt divisor, 2f ++ addl divisor,divisor,divisor ++ addl mask,mask,mask ++ bne compare,1b ++ nop ++#endif ++ ++ /* ok, start to go right again.. */ ++2: DIV_ONLY(addl quotient,mask,tmp2) ++ srl mask,1,mask ++ cmpule divisor,modulus,compare ++ subl modulus,divisor,tmp1 ++ DIV_ONLY(selne compare,tmp2,quotient,quotient) ++ srl divisor,1,divisor ++ selne compare,tmp1,modulus,modulus ++ bne mask,2b ++ ++9: ldl $1, 0($30) ++ ldl $2, 8($30) ++ ldl $0,16($30) ++ ldl tmp1,24($30) ++ DIV_ONLY(ldl tmp2,32($30)) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end ufunction ++ ++/* ++ * Uhh.. Ugly signed division. I'd rather not have it at all, but ++ * it's needed in some circumstances. There are different ways to ++ * handle this, really. This does: ++ * -a / b = a / -b = -(a / b) ++ * -a % b = -(a % b) ++ * a % -b = a % b ++ * which is probably not the best solution, but at least should ++ * have the property that (x/y)*y + (x%y) = x. ++ */ ++.align 3 ++.globl sfunction ++.ent sfunction ++sfunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ bis $24,$25,$28 ++ SLONGIFY($28) ++ bge $28,7b ++ stl $24,0($30) ++ subl $31,$24,$28 ++ stl $25,8($30) ++ sellt $24,$28,$24,$24 /* abs($24) */ ++ stl $23,16($30) ++ subl $31,$25,$28 ++ stl tmp1,24($30) ++ sellt $25,$28,$25,$25 /* abs($25) */ ++ nop ++ bsr $23,ufunction ++ ldl $24,0($30) ++ ldl $25,8($30) ++ GETSIGN($28) ++ subl $31,$27,tmp1 ++ SLONGIFY($28) ++ ldl $23,16($30) ++ sellt $28,tmp1,$27,$27 ++ ldl tmp1,24($30) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end sfunction ++ ++/*div 64*/ ++ ++#undef DIV_ONLY ++#undef MOD_ONLY ++#undef func ++#undef modulus ++#undef quotient ++#undef GETSIGN ++#undef STACK ++#undef ufunction ++#undef sfunction ++#undef LONGIFY ++#undef SLONGIFY ++ ++ ++#define DIV ++#undef INTSIZE ++ ++#ifdef DIV ++#define DIV_ONLY(x,y...) x,##y ++#define MOD_ONLY(x,y...) ++#define func(x) __div##x ++#define modulus $2 ++#define quotient $27 ++#define GETSIGN(x) xor $24,$25,x ++#define STACK 48 ++#else ++#define DIV_ONLY(x,y...) ++#define MOD_ONLY(x,y...) x,##y ++#define func(x) __rem##x ++#define modulus $27 ++#define quotient $2 ++#define GETSIGN(x) bis $24,$24,x ++#define STACK 32 ++#endif ++ ++/* ++ * For 32-bit operations, we need to extend to 64-bit ++ */ ++#ifdef INTSIZE ++#define ufunction func(wu) ++#define sfunction func(w) ++#define LONGIFY(x) zapnot x,15,x ++#define SLONGIFY(x) ++#else ++#define ufunction func(lu) ++#define sfunction func(l) ++#define LONGIFY(x) ++#define SLONGIFY(x) ++#endif ++ ++.align 3 ++.globl ufunction ++.ent ufunction ++ufunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ ++7: stl $1, 0($30) ++ bis $25,$25,divisor ++ stl $2, 8($30) ++ bis $24,$24,modulus ++ stl $0,16($30) ++ bis $31,$31,quotient ++ LONGIFY(divisor) ++ stl tmp1,24($30) ++ LONGIFY(modulus) ++ bis $31,1,mask ++ DIV_ONLY(stl tmp2,32($30)) ++ beq divisor, 9f /* div by zero */ ++ ++#ifdef INTSIZE ++ /* ++ * shift divisor left, using 3-bit shifts for ++ * 32-bit divides as we can't overflow. Three-bit ++ * shifts will result in looping three times less ++ * here, but can result in two loops more later. ++ * Thus using a large shift isn't worth it (and ++ * s8add pairs better than a sll..) ++ */ ++1: cmpult divisor,modulus,compare ++ s8addl divisor,$31,divisor ++ s8addl mask,$31,mask ++ bne compare,1b ++#else ++1: cmpult divisor,modulus,compare ++ blt divisor, 2f ++ addl divisor,divisor,divisor ++ addl mask,mask,mask ++ bne compare,1b ++ nop ++#endif ++ ++ /* ok, start to go right again.. */ ++2: DIV_ONLY(addl quotient,mask,tmp2) ++ srl mask,1,mask ++ cmpule divisor,modulus,compare ++ subl modulus,divisor,tmp1 ++ DIV_ONLY(selne compare,tmp2,quotient,quotient) ++ srl divisor,1,divisor ++ selne compare,tmp1,modulus,modulus ++ bne mask,2b ++ ++9: ldl $1, 0($30) ++ ldl $2, 8($30) ++ ldl $0,16($30) ++ ldl tmp1,24($30) ++ DIV_ONLY(ldl tmp2,32($30)) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end ufunction ++ ++/* ++ * Uhh.. Ugly signed division. I'd rather not have it at all, but ++ * it's needed in some circumstances. There are different ways to ++ * handle this, really. This does: ++ * -a / b = a / -b = -(a / b) ++ * -a % b = -(a % b) ++ * a % -b = a % b ++ * which is probably not the best solution, but at least should ++ * have the property that (x/y)*y + (x%y) = x. ++ */ ++.align 3 ++.globl sfunction ++.ent sfunction ++sfunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ bis $24,$25,$28 ++ SLONGIFY($28) ++ bge $28,7b ++ stl $24,0($30) ++ subl $31,$24,$28 ++ stl $25,8($30) ++ sellt $24,$28,$24,$24 /* abs($24) */ ++ stl $23,16($30) ++ subl $31,$25,$28 ++ stl tmp1,24($30) ++ sellt $25,$28,$25,$25 /* abs($25) */ ++ nop ++ bsr $23,ufunction ++ ldl $24,0($30) ++ ldl $25,8($30) ++ GETSIGN($28) ++ subl $31,$27,tmp1 ++ SLONGIFY($28) ++ ldl $23,16($30) ++ sellt $28,tmp1,$27,$27 ++ ldl tmp1,24($30) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end sfunction ++ ++ ++/*rem 64*/ ++ ++#undef DIV_ONLY ++#undef MOD_ONLY ++#undef func ++#undef modulus ++#undef quotient ++#undef GETSIGN ++#undef STACK ++#undef ufunction ++#undef sfunction ++#undef LONGIFY ++#undef SLONGIFY ++ ++ ++#undef DIV ++ ++#ifdef DIV ++#define DIV_ONLY(x,y...) x,##y ++#define MOD_ONLY(x,y...) ++#define func(x) __div##x ++#define modulus $2 ++#define quotient $27 ++#define GETSIGN(x) xor $24,$25,x ++#define STACK 48 ++#else ++#define DIV_ONLY(x,y...) ++#define MOD_ONLY(x,y...) x,##y ++#define func(x) __rem##x ++#define modulus $27 ++#define quotient $2 ++#define GETSIGN(x) bis $24,$24,x ++#define STACK 32 ++#endif ++ ++/* ++ * For 32-bit operations, we need to extend to 64-bit ++ */ ++#ifdef INTSIZE ++#define ufunction func(wu) ++#define sfunction func(w) ++#define LONGIFY(x) zapnot x,15,x ++#define SLONGIFY(x) ++#else ++#define ufunction func(lu) ++#define sfunction func(l) ++#define LONGIFY(x) ++#define SLONGIFY(x) ++#endif ++ ++ ++.align 3 ++.globl ufunction ++.ent ufunction ++ufunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ ++7: stl $1, 0($30) ++ bis $25,$25,divisor ++ stl $2, 8($30) ++ bis $24,$24,modulus ++ stl $0,16($30) ++ bis $31,$31,quotient ++ LONGIFY(divisor) ++ stl tmp1,24($30) ++ LONGIFY(modulus) ++ bis $31,1,mask ++ DIV_ONLY(stl tmp2,32($30)) ++ beq divisor, 9f /* div by zero */ ++ ++#ifdef INTSIZE ++ /* ++ * shift divisor left, using 3-bit shifts for ++ * 32-bit divides as we can't overflow. Three-bit ++ * shifts will result in looping three times less ++ * here, but can result in two loops more later. ++ * Thus using a large shift isn't worth it (and ++ * s8add pairs better than a sll..) ++ */ ++1: cmpult divisor,modulus,compare ++ s8addl divisor,$31,divisor ++ s8addl mask,$31,mask ++ bne compare,1b ++#else ++1: cmpult divisor,modulus,compare ++ blt divisor, 2f ++ addl divisor,divisor,divisor ++ addl mask,mask,mask ++ bne compare,1b ++ nop ++#endif ++ ++ /* ok, start to go right again.. */ ++2: DIV_ONLY(addl quotient,mask,tmp2) ++ srl mask,1,mask ++ cmpule divisor,modulus,compare ++ subl modulus,divisor,tmp1 ++ DIV_ONLY(selne compare,tmp2,quotient,quotient) ++ srl divisor,1,divisor ++ selne compare,tmp1,modulus,modulus ++ bne mask,2b ++ ++9: ldl $1, 0($30) ++ ldl $2, 8($30) ++ ldl $0,16($30) ++ ldl tmp1,24($30) ++ DIV_ONLY(ldl tmp2,32($30)) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end ufunction ++ ++/* ++ * Uhh.. Ugly signed division. I'd rather not have it at all, but ++ * it's needed in some circumstances. There are different ways to ++ * handle this, really. This does: ++ * -a / b = a / -b = -(a / b) ++ * -a % b = -(a % b) ++ * a % -b = a % b ++ * which is probably not the best solution, but at least should ++ * have the property that (x/y)*y + (x%y) = x. ++ */ ++.align 3 ++.globl sfunction ++.ent sfunction ++sfunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ bis $24,$25,$28 ++ SLONGIFY($28) ++ bge $28,7b ++ stl $24,0($30) ++ subl $31,$24,$28 ++ stl $25,8($30) ++ sellt $24,$28,$24,$24 /* abs($24) */ ++ stl $23,16($30) ++ subl $31,$25,$28 ++ stl tmp1,24($30) ++ sellt $25,$28,$25,$25 /* abs($25) */ ++ nop ++ bsr $23,ufunction ++ ldl $24,0($30) ++ ldl $25,8($30) ++ GETSIGN($28) ++ subl $31,$27,tmp1 ++ SLONGIFY($28) ++ ldl $23,16($30) ++ sellt $28,tmp1,$27,$27 ++ ldl tmp1,24($30) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end sfunction +diff --git a/grub-core/lib/sw64/setjmp.S b/grub-core/lib/sw64/setjmp.S +new file mode 100644 +index 000000000..a04d6007b +--- /dev/null ++++ b/grub-core/lib/sw64/setjmp.S +@@ -0,0 +1,75 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++ ++ .file "setjmp.S" ++ ++GRUB_MOD_LICENSE "GPLv2+" ++ ++FUNCTION(grub_setjmp) ++ ldgp gp, 0(pv) ++#define FRAME 0 ++ .frame sp, FRAME, ra, 0 ++ ++ stl s0, JB_S0*8(a0) ++ stl s1, JB_S1*8(a0) ++ stl s2, JB_S2*8(a0) ++ stl s3, JB_S3*8(a0) ++ stl s4, JB_S4*8(a0) ++ stl s5, JB_S5*8(a0) ++ stl ra, JB_PC*8(a0) ++ addl sp, FRAME, t1 ++ stl t1, JB_SP*8(a0) ++ stl fp, JB_FP*8(a0) ++ fstd $f2, JB_F2*8(a0) ++ fstd $f3, JB_F3*8(a0) ++ fstd $f4, JB_F4*8(a0) ++ fstd $f5, JB_F5*8(a0) ++ fstd $f6, JB_F6*8(a0) ++ fstd $f7, JB_F7*8(a0) ++ fstd $f8, JB_F8*8(a0) ++ fstd $f9, JB_F9*8(a0) ++ ldi a0, 0($31) ++ ret ++ ++FUNCTION(grub_longjmp) ++ mov a1, v0 ++ ldl s0, JB_S0*8(a0) ++ ldl s1, JB_S1*8(a0) ++ ldl s2, JB_S2*8(a0) ++ ldl s3, JB_S3*8(a0) ++ ldl s4, JB_S4*8(a0) ++ ldl s5, JB_S5*8(a0) ++ ldl ra, JB_PC*8(a0) ++ ldl fp, JB_FP*8(a0) ++ ldl t0, JB_SP*8(a0) ++ fldd $f2, JB_F2*8(a0) ++ fldd $f3, JB_F3*8(a0) ++ fldd $f4, JB_F4*8(a0) ++ fldd $f5, JB_F5*8(a0) ++ fldd $f6, JB_F6*8(a0) ++ fldd $f7, JB_F7*8(a0) ++ fldd $f8, JB_F8*8(a0) ++ fldd $f9, JB_F9*8(a0) ++ seleq v0, 1, v0, v0 ++ mov t0, sp ++ ret +diff --git a/grub-core/loader/sw64/efi/linux.c b/grub-core/loader/sw64/efi/linux.c +new file mode 100644 +index 000000000..51c2a98b7 +--- /dev/null ++++ b/grub-core/loader/sw64/efi/linux.c +@@ -0,0 +1,330 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++#pragma GCC diagnostic ignored "-Wcast-align" ++ ++static grub_dl_t my_mod; ++static int loaded; ++static char *linux_args; ++ ++/* Initrd base and size. */ ++static void *initrd_mem; ++static grub_efi_uintn_t initrd_pages; ++static grub_addr_t initrd_start; ++static grub_efi_uintn_t initrd_size; ++ ++void *raw_fdt; ++static struct boot_param *sunway_boot_params = (struct boot_param *)BOOT_PARAM_START; ++ ++static grub_err_t ++finalize_params_linux (void) ++{ ++ grub_efi_uintn_t mmap_size; ++ grub_efi_uintn_t map_key; ++ grub_efi_uintn_t desc_size; ++ grub_efi_uint32_t desc_version; ++ grub_efi_memory_descriptor_t *mmap_buf; ++ grub_err_t err; ++ grub_efi_uintn_t i; ++ ++ /* Initrd. */ ++ sunway_boot_params->initrd_start = (grub_uint64_t)initrd_start; ++ sunway_boot_params->initrd_size = (grub_uint64_t)initrd_size; ++ ++ /* DTB. */ ++ raw_fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE); ++ ++ if (!raw_fdt) ++ { ++ sunway_boot_params->dtb_start = 0; ++ grub_dprintf ("linux", "not found registered FDT\n"); ++ } ++ ++ if (raw_fdt) ++ { ++ err = grub_fdt_check_header_nosize(raw_fdt); ++ if (err) ++ grub_dprintf ("linux", "illegal FDT file\n"); ++ ++ sunway_boot_params->dtb_start = (grub_uint64_t)raw_fdt; ++ grub_dprintf ("linux", "dtb: [addr=0x%lx, size=0x%x]\n", ++ (grub_uint64_t) raw_fdt, grub_fdt_get_totalsize(raw_fdt)); ++ grub_printk ("dtb: [addr=0x%lx, size=0x%x]\n", ++ (grub_uint64_t) raw_fdt, grub_fdt_get_totalsize(raw_fdt)); ++ } ++ ++ /* MDT. ++ Must be done after grub_machine_fini because map_key is used by ++ exit_boot_services. */ ++ mmap_size = grub_efi_find_mmap_size (); ++ if (! mmap_size) ++ return grub_errno; ++ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); ++ if (! mmap_buf) ++ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); ++ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, &map_key, ++ &desc_size, &desc_version); ++ if (err) ++ return err; ++ ++ for (i = 0; i < mmap_size / desc_size; i++) ++ { ++ grub_efi_memory_descriptor_t *curdesc = (grub_efi_memory_descriptor_t *) ++ ((char *) mmap_buf + desc_size * i); ++ ++ /* Bypass the low address segment that used by OS */ ++ if (grub_virt_to_phys(curdesc->physical_start) < 0x2f00000UL) ++ curdesc->physical_start = 0x2f00000UL; ++ ++ curdesc->physical_start = grub_virt_to_phys(curdesc->physical_start); ++ } ++ ++ sunway_boot_params->efi_systab = grub_virt_to_phys((grub_uint64_t)grub_efi_system_table); ++ sunway_boot_params->efi_memmap = grub_virt_to_phys((grub_uint64_t)mmap_buf); ++ sunway_boot_params->efi_memmap_size = mmap_size; ++ sunway_boot_params->efi_memdesc_size = desc_size; ++ sunway_boot_params->efi_memdesc_version = desc_version; ++ ++ return GRUB_ERR_NONE; ++} ++static void ++start_kernel(void) ++{ ++ local_irq_disable (); ++ grub_dprintf ("linux", "Jump to entry: %lx\n", VMLINUX_ADDR); ++ grub_printk("Jump to entry: %lx\n", VMLINUX_ADDR); ++ ++ ret(VMLINUX_ADDR | 2); ++} ++ ++static grub_err_t ++grub_linux_boot (void) ++{ ++ finalize_params_linux (); ++ start_kernel (); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_linux_unload (void) ++{ ++ grub_dl_unref (my_mod); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_load_elf64 (grub_elf_t elf, const char *filename) ++{ ++ Elf64_Addr base_addr; ++ grub_size_t linux_size; ++ grub_uint64_t align; ++ ++ if (elf->ehdr.ehdr64.e_ident[EI_MAG0] != ELFMAG0 ++ || elf->ehdr.ehdr64.e_ident[EI_MAG1] != ELFMAG1 ++ || elf->ehdr.ehdr64.e_ident[EI_MAG2] != ELFMAG2 ++ || elf->ehdr.ehdr64.e_ident[EI_MAG3] != ELFMAG3 ++ || elf->ehdr.ehdr64.e_ident[EI_DATA] != ELFDATA2LSB) ++ return grub_error(GRUB_ERR_UNKNOWN_OS, ++ N_("invalid arch-independent ELF magic")); ++ ++ if (elf->ehdr.ehdr64.e_ident[EI_CLASS] != ELFCLASS64 ++ || elf->ehdr.ehdr64.e_version != EV_CURRENT ++ || elf->ehdr.ehdr64.e_machine != EM_SW_64) ++ return grub_error (GRUB_ERR_UNKNOWN_OS, ++ N_("invalid arch-dependent ELF magic")); ++ ++ if (elf->ehdr.ehdr64.e_type != ET_EXEC) ++ return grub_error (GRUB_ERR_UNKNOWN_OS, ++ N_("this ELF file is not of the right type")); ++ ++ /* FIXME: Should we support program headers at strange locations? */ ++ if (elf->ehdr.ehdr64.e_phoff + elf->ehdr.ehdr64.e_phnum * elf->ehdr.ehdr64.e_phentsize > GRUB_ELF_SEARCH) ++ return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset"); ++ ++ linux_size = grub_elf64_size (elf, &base_addr, &align); ++ if (linux_size == 0) ++ return grub_error (GRUB_ERR_BAD_OS, "linux size is 0"); ++ ++ grub_dprintf ("linux", "Segment phy_addr: %lx entry: %lx\n", (grub_uint64_t)base_addr,(grub_uint64_t)elf->ehdr.ehdr64.e_entry); ++ grub_printk ("Segment phy_addr: %lx entry: %lx\n", (grub_uint64_t)base_addr,(grub_uint64_t)elf->ehdr.ehdr64.e_entry); ++ ++ /* Now load the segments into the area we claimed. */ ++ return grub_elf64_load (elf, filename, (void *) (grub_addr_t) (0), GRUB_ELF_LOAD_FLAGS_NONE, 0, 0); ++} ++ ++static grub_err_t ++grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ grub_ssize_t size; ++ grub_elf_t elf = 0; ++ ++ grub_dl_ref (my_mod); ++ ++ grub_loader_unset (); ++ ++ if (argc == 0) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ goto fail; ++ } ++ ++ elf = grub_elf_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL); ++ if (! elf) ++ goto fail; ++ ++ grub_dprintf ("linux", "Loading linux: %s\n", argv[0]); ++ grub_printk ("Loading linux: %s\n", argv[0]); ++ ++ if (grub_load_elf64 (elf, argv[0])) ++ goto fail; ++ ++ grub_memset (sunway_boot_params, 0, sizeof(*sunway_boot_params)); ++ size = grub_loader_cmdline_size(argc, argv); ++ ++ linux_args = grub_malloc (size + sizeof (LINUX_IMAGE)); ++ if (!linux_args) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto fail; ++ } ++ ++ sunway_boot_params->command_line = (grub_uint64_t) linux_args; ++ ++ /* Create kernel command line. */ ++ grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); ++ grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1, ++ size, GRUB_VERIFY_KERNEL_CMDLINE); ++ ++ grub_dprintf ("linux", "linux_args: '%s'\n", ((char *)((sunway_boot_params->command_line)))); ++ grub_printk ("linux_args: '%s'\n", ((char *)((sunway_boot_params->command_line)))); ++ grub_errno = GRUB_ERR_NONE; ++ ++ grub_loader_set (grub_linux_boot, grub_linux_unload, 0); ++ ++ fail: ++ if (elf) ++ grub_elf_close (elf); ++ ++ if (grub_errno != GRUB_ERR_NONE) ++ { ++ grub_dl_unref (my_mod); ++ loaded = 0; ++ } ++ else ++ loaded = 1; ++ ++ return grub_errno; ++} ++ ++static grub_err_t ++grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; ++ ++ if (argc == 0) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ goto fail; ++ } ++ ++ if (! loaded) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); ++ goto fail; ++ } ++ ++ if (grub_initrd_init (argc, argv, &initrd_ctx)) ++ goto fail; ++ ++ initrd_size = grub_get_initrd_size (&initrd_ctx); ++ grub_dprintf ("linux", "Loading initrd %s\n", argv[0]); ++ grub_printk ("Loading initrd %s\n", argv[0]); ++ ++ initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size)); ++ initrd_mem = grub_efi_allocate_any_pages (initrd_pages); ++ if (! initrd_mem) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate pages"); ++ goto fail; ++ } ++ ++ grub_dprintf ("linux", "initrd: [addr=0x%lx, size=0x%lx]\n", ++ (grub_uint64_t) initrd_mem, initrd_size); ++ grub_printk ("initrd: [addr=0x%lx, size=0x%lx]\n", ++ (grub_uint64_t) initrd_mem, initrd_size); ++ ++ if (grub_initrd_load (&initrd_ctx, argv, initrd_mem)) ++ goto fail; ++ ++ initrd_start = (grub_addr_t) initrd_mem; ++ ++ fail: ++ grub_initrd_close (&initrd_ctx); ++ if (initrd_mem && !initrd_start) ++ grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages); ++ ++ return grub_errno; ++} ++ ++static grub_command_t cmd_linux, cmd_initrd; ++ ++GRUB_MOD_INIT (linux) ++{ ++ cmd_linux = grub_register_command ("linux", grub_cmd_linux, ++ N_("FILE [ARGS...]"), N_("Load Linux.")); ++ ++ cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, ++ N_("FILE"), N_("Load initrd.")); ++ ++ my_mod = mod; ++} ++ ++GRUB_MOD_FINI (linux) ++{ ++ grub_unregister_command (cmd_linux); ++ grub_unregister_command (cmd_initrd); ++} +diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h +index 17828b322..a8782fc80 100644 +--- a/include/grub/compiler-rt.h ++++ b/include/grub/compiler-rt.h +@@ -178,7 +178,7 @@ EXPORT_FUNC (__lshrdi3) (grub_uint64_t u, int b); + #endif + + #if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || \ +- defined (__arm__) || defined(__riscv) ++ defined (__arm__) || defined(__riscv) || defined(__sw_64__) + grub_uint32_t + EXPORT_FUNC(__bswapsi2) (grub_uint32_t u); + +diff --git a/include/grub/dl.h b/include/grub/dl.h +index b3753c9ca..32f365d48 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -282,17 +282,29 @@ grub_err_t + grub_arm64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_size_t *got); + ++#define GRUB_SW64_DL_TRAMP_ALIGN 16 ++#define GRUB_SW64_DL_GOT_ALIGN 16 ++ ++grub_err_t ++grub_sw64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, ++ grub_size_t *got); ++ + #if defined (__ia64__) + #define GRUB_ARCH_DL_TRAMP_ALIGN GRUB_IA64_DL_TRAMP_ALIGN + #define GRUB_ARCH_DL_GOT_ALIGN GRUB_IA64_DL_GOT_ALIGN + #define grub_arch_dl_get_tramp_got_size grub_ia64_dl_get_tramp_got_size + #elif defined (__aarch64__) + #define grub_arch_dl_get_tramp_got_size grub_arm64_dl_get_tramp_got_size ++#elif defined (__sw_64__) ++#define GRUB_ARCH_DL_TRAMP_ALIGN GRUB_SW64_DL_TRAMP_ALIGN ++#define GRUB_ARCH_DL_GOT_ALIGN GRUB_SW64_DL_GOT_ALIGN ++#define grub_arch_dl_get_tramp_got_size grub_sw64_dl_get_tramp_got_size + #else + grub_err_t + grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_size_t *got); + #endif ++#endif + + #if defined (__powerpc__) || defined (__mips__) || defined (__arm__) || \ + (defined(__riscv) && (__riscv_xlen == 32)) +@@ -306,6 +318,4 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + #define GRUB_ARCH_DL_GOT_ALIGN 8 + #endif + +-#endif +- + #endif /* ! GRUB_DL_H */ +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index f1a52210c..e571bd053 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -1731,7 +1731,7 @@ typedef struct grub_efi_rng_protocol grub_efi_rng_protocol_t; + + #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ + || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ +- || defined(__riscv) ++ || defined(__riscv) || defined(__sw_64__) + + #define efi_call_0(func) func() + #define efi_call_1(func, a) func(a) +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 83d958f99..6f5fe163e 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -96,7 +96,7 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, + char **device, + char **path); + +-#if defined(__arm__) || defined(__aarch64__) || defined(__riscv) ++#if defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__sw_64__) + void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); + grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); + #include +diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h +index 0ed8781f0..2f50befc3 100644 +--- a/include/grub/efi/pe32.h ++++ b/include/grub/efi/pe32.h +@@ -79,6 +79,7 @@ struct grub_pe32_coff_header + #define GRUB_PE32_MACHINE_ARM64 0xAA64 + #define GRUB_PE32_MACHINE_RISCV32 0x5032 + #define GRUB_PE32_MACHINE_RISCV64 0x5064 ++#define GRUB_PE32_MACHINE_SW_64 0x284 + + #define GRUB_PE32_RELOCS_STRIPPED 0x0001 + #define GRUB_PE32_EXECUTABLE_IMAGE 0x0002 +diff --git a/include/grub/elf.h b/include/grub/elf.h +index c478933ee..f3727826e 100644 +--- a/include/grub/elf.h ++++ b/include/grub/elf.h +@@ -254,6 +254,7 @@ typedef struct + chances of collision with official or non-GNU unofficial values. */ + + #define EM_ALPHA 0x9026 ++#define EM_SW_64 0x9916 + + /* Legal values for e_version (version). */ + +@@ -2531,6 +2532,47 @@ typedef Elf32_Addr Elf32_Conflict; + #define R_RISCV_SET32 56 + #define R_RISCV_32_PCREL 57 + ++/* ++ * SW-64 ELF relocation types ++ */ ++#define R_SW64_NONE 0 /* No reloc */ ++#define R_SW64_REFLONG 1 /* Direct 32 bit */ ++#define R_SW64_REFQUAD 2 /* Direct 64 bit */ ++#define R_SW64_GPREL32 3 /* GP relative 32 bit */ ++#define R_SW64_LITERAL 4 /* GP relative 16 bit w/optimization */ ++#define R_SW64_LITUSE 5 /* Optimization hint for LITERAL */ ++#define R_SW64_GPDISP 6 /* Add displacement to GP */ ++#define R_SW64_BRADDR 7 /* PC+4 relative 23 bit shifted */ ++#define R_SW64_HINT 8 /* PC+4 relative 16 bit shifted */ ++#define R_SW64_SREL16 9 /* PC relative 16 bit */ ++#define R_SW64_SREL32 10 /* PC relative 32 bit */ ++#define R_SW64_SREL64 11 /* PC relative 64 bit */ ++#define R_SW64_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ ++#define R_SW64_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ ++#define R_SW64_GPREL16 19 /* GP relative 16 bit */ ++#define R_SW64_COPY 24 /* Copy symbol at runtime */ ++#define R_SW64_GLOB_DAT 25 /* Create GOT entry */ ++#define R_SW64_JMP_SLOT 26 /* Create PLT entry */ ++#define R_SW64_RELATIVE 27 /* Adjust by program base */ ++#define R_SW64_BRSGP 28 ++#define R_SW64_TLSGD 29 ++#define R_SW64_TLS_LDM 30 ++#define R_SW64_DTPMOD64 31 ++#define R_SW64_GOTDTPREL 32 ++#define R_SW64_DTPREL64 33 ++#define R_SW64_DTPRELHI 34 ++#define R_SW64_DTPRELLO 35 ++#define R_SW64_DTPREL16 36 ++#define R_SW64_GOTTPREL 37 ++#define R_SW64_TPREL64 38 ++#define R_SW64_TPRELHI 39 ++#define R_SW64_TPRELLO 40 ++#define R_SW64_TPREL16 41 ++#define R_SW64_LITERAL_GOT 43 ++ ++#define STO_SW64_NOPV 0x80 ++#define STO_SW64_STD_GPLOAD 0x88 ++ + #ifdef GRUB_TARGET_WORDSIZE + #if GRUB_TARGET_WORDSIZE == 32 + +diff --git a/include/grub/misc.h b/include/grub/misc.h +index 7d2b55196..73fd47c1a 100644 +--- a/include/grub/misc.h ++++ b/include/grub/misc.h +@@ -306,7 +306,9 @@ void *EXPORT_FUNC(grub_memset) (void *s, int c, grub_size_t n); + grub_size_t EXPORT_FUNC(grub_strlen) (const char *s) WARN_UNUSED_RESULT; + int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2))); + int EXPORT_FUNC(grub_printf_) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2))); +- ++#ifdef __sw_64__ ++int EXPORT_FUNC(grub_printk) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2))); ++#endif + /* Replace all `ch' characters of `input' with `with' and copy the + result into `output'; return EOS address of `output'. */ + static inline char * +@@ -346,6 +348,9 @@ void EXPORT_FUNC(grub_real_dprintf) (const char *file, + const char *condition, + const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 4, 5))); + int EXPORT_FUNC(grub_vprintf) (const char *fmt, va_list args); ++#ifdef __sw_64__ ++int EXPORT_FUNC(grub_vprintk) (const char *fmt, va_list args); ++#endif + int EXPORT_FUNC(grub_snprintf) (char *str, grub_size_t n, const char *fmt, ...) + __attribute__ ((format (GNU_PRINTF, 3, 4))); + int EXPORT_FUNC(grub_vsnprintf) (char *str, grub_size_t n, const char *fmt, +@@ -499,5 +504,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file, + #define grub_min(a, b) (((a) < (b)) ? (a) : (b)) + + #define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) - __builtin_clzll (n) - 1) +- ++#ifdef __sw_64__ ++void sunway_debug_delegate(char *buffer); ++#endif + #endif /* ! GRUB_MISC_HEADER */ +diff --git a/include/grub/sw64/divide.h b/include/grub/sw64/divide.h +new file mode 100644 +index 000000000..a6c8eae02 +--- /dev/null ++++ b/include/grub/sw64/divide.h +@@ -0,0 +1,11 @@ ++#ifndef __DIVIDE_H__ ++#define __DIVIDE_H__ ++void EXPORT_FUNC(__divw) (void); ++void EXPORT_FUNC(__remw) (void); ++void EXPORT_FUNC(__divl) (void); ++void EXPORT_FUNC(__reml) (void); ++void EXPORT_FUNC(__divwu) (void); ++void EXPORT_FUNC(__remwu) (void); ++void EXPORT_FUNC(__divlu) (void); ++void EXPORT_FUNC(__remlu) (void); ++#endif +diff --git a/include/grub/sw64/efi/memory.h b/include/grub/sw64/efi/memory.h +new file mode 100644 +index 000000000..3bc99d073 +--- /dev/null ++++ b/include/grub/sw64/efi/memory.h +@@ -0,0 +1,6 @@ ++#ifndef GRUB_MEMORY_CPU_HEADER ++#include ++ ++#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffffffffffULL ++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS ++#endif /* ! GRUB_MEMORY_CPU_HEADER */ +diff --git a/include/grub/sw64/efi/time.h b/include/grub/sw64/efi/time.h +new file mode 100644 +index 000000000..897ce9c00 +--- /dev/null ++++ b/include/grub/sw64/efi/time.h +@@ -0,0 +1,23 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2008 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++#ifndef GRUB_MACHINE_TIME_HEADER ++#define GRUB_MACHINE_TIME_HEADER 1 ++ ++#include ++ ++#endif /* ! GRUB_MACHINE_TIME_HEADER */ +diff --git a/include/grub/sw64/io.h b/include/grub/sw64/io.h +new file mode 100644 +index 000000000..dee76bde5 +--- /dev/null ++++ b/include/grub/sw64/io.h +@@ -0,0 +1,62 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2009 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_IO_H ++#define GRUB_IO_H 1 ++ ++#include ++ ++typedef grub_addr_t grub_port_t; ++ ++static __inline unsigned char ++grub_inb (grub_port_t port) ++{ ++ return *(volatile grub_uint8_t *) port; ++} ++ ++static __inline unsigned short int ++grub_inw (grub_port_t port) ++{ ++ return *(volatile grub_uint16_t *) port; ++} ++ ++static __inline unsigned int ++grub_inl (grub_port_t port) ++{ ++ return *(volatile grub_uint32_t *) port; ++} ++ ++static __inline void ++grub_outb (unsigned char value, grub_port_t port) ++{ ++ *(volatile grub_uint8_t *) port = value; ++} ++ ++static __inline void ++grub_outw (unsigned short int value, grub_port_t port) ++{ ++ *(volatile grub_uint16_t *) port = value; ++} ++ ++static __inline void ++grub_outl (unsigned int value, grub_port_t port) ++{ ++ *(volatile grub_uint32_t *) port = value; ++} ++ ++#endif /* _SYS_IO_H */ +diff --git a/include/grub/sw64/jmpbuf-offsets.h b/include/grub/sw64/jmpbuf-offsets.h +new file mode 100644 +index 000000000..86e8da2a1 +--- /dev/null ++++ b/include/grub/sw64/jmpbuf-offsets.h +@@ -0,0 +1,35 @@ ++/* Private macros for accessing __jmp_buf contents. Alpha version. ++ Copyright (C) 2006-2016 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#define JB_S0 0 ++#define JB_S1 1 ++#define JB_S2 2 ++#define JB_S3 3 ++#define JB_S4 4 ++#define JB_S5 5 ++#define JB_PC 6 ++#define JB_FP 7 ++#define JB_SP 8 ++#define JB_F2 9 ++#define JB_F3 10 ++#define JB_F4 11 ++#define JB_F5 12 ++#define JB_F6 13 ++#define JB_F7 14 ++#define JB_F8 15 ++#define JB_F9 16 +diff --git a/include/grub/sw64/kernel.h b/include/grub/sw64/kernel.h +new file mode 100644 +index 000000000..c5496a00b +--- /dev/null ++++ b/include/grub/sw64/kernel.h +@@ -0,0 +1,25 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2010 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_CPU_KERNEL_HEADER ++#define GRUB_CPU_KERNEL_HEADER 1 ++ ++#define GRUB_MOD_ALIGN 0x1 ++#define GRUB_MOD_GAP 0x0 ++ ++#endif /* ! GRUB_CPU_KERNEL_HEADER */ +diff --git a/include/grub/sw64/linux.h b/include/grub/sw64/linux.h +new file mode 100644 +index 000000000..068e303d0 +--- /dev/null ++++ b/include/grub/sw64/linux.h +@@ -0,0 +1,50 @@ ++#ifndef GRUB_SW_H ++#define GRUB_SW_H 1 ++#define PAGE_OFFSET 0xfff0000000000000UL ++#define KTEXT_OFFSET 0xffffffff80000000UL ++#define GRUB_PRINTK_START (KTEXT_OFFSET | 0x800000) ++#define GRUB_PRINTK_SIZE (0x20000) ++#define BOOT_PARAM_START 0xfff000000090a100ULL ++#define VMLINUX_ADDR (KTEXT_OFFSET | 0x910000) ++ ++#define GRUB_ELF_SEARCH 1024 ++#define IPL_MIN 0 ++#define IPL_MAX 7 ++#define barrier() __asm__ __volatile__("": : :"memory") ++#define local_irq_disable() do { swpipl(IPL_MAX); barrier(); } while(0) ++#define local_irq_enable() do { barrier(); swpipl(IPL_MIN); } while(0) ++ ++static inline ++grub_uint64_t ++grub_virt_to_phys(grub_uint64_t x) ++{ ++ if (x >= KTEXT_OFFSET) ++ x -= KTEXT_OFFSET; ++ else if (x >= PAGE_OFFSET) ++ x -= PAGE_OFFSET; ++ else ++ grub_error (GRUB_ERR_BUG, "not an valid address"); ++ ++ return x; ++} ++ ++struct boot_param ++{ ++ grub_uint64_t initrd_start; /* logical address of initrd */ ++ grub_uint64_t initrd_size; /* size of initrd */ ++ grub_uint64_t dtb_start; /* logical address of dtb */ ++ grub_uint64_t efi_systab; /* logical address of EFI system table */ ++ grub_uint64_t efi_memmap; /* logical address of EFI memory map */ ++ grub_uint64_t efi_memmap_size; /* size of EFI memory map */ ++ grub_uint64_t efi_memdesc_size; /* size of an EFI memory map descriptor */ ++ grub_uint64_t efi_memdesc_version; /* memory descriptor version */ ++ grub_uint64_t command_line; /* logical address of cmdline */ ++}; ++ ++struct linux_sw64_kernel_header ++{ ++}; ++ ++#define linux_arch_kernel_header linux_sw64_kernel_header ++ ++#endif +diff --git a/include/grub/sw64/pal.h b/include/grub/sw64/pal.h +new file mode 100644 +index 000000000..274f07d3a +--- /dev/null ++++ b/include/grub/sw64/pal.h +@@ -0,0 +1,49 @@ ++#ifndef __SW64_PAL_H ++#define __SW64_PAL_H ++ ++#define HMC_cpuid 0x03 ++#define HMC_ret 0x1A ++#define HMC_swpipl 0x35 ++ ++#define GET_CPU_FREQ 4 ++ ++#define __CALL_HMC_W1(NAME, TYPE0) \ ++static inline void NAME(TYPE0 arg0) \ ++{ \ ++ register TYPE0 __r16 __asm__("$16") = arg0; \ ++ __asm__ __volatile__ ("sys_call %1 # "#NAME \ ++ : "=r"(__r16) \ ++ : "i"(HMC_ ## NAME), "0"(__r16) \ ++ : "$1", "$22", "$23", "$24", "$25"); \ ++} ++ ++#define __CALL_HMC_RW1(NAME, RTYPE, TYPE0) \ ++static inline RTYPE NAME(TYPE0 arg0) \ ++{ \ ++ register RTYPE __r0 __asm__("$0"); \ ++ register TYPE0 __r16 __asm__("$16") = arg0; \ ++ __asm__ __volatile__ ("sys_call %2 # "#NAME \ ++ : "=r"(__r16), "=r"(__r0) \ ++ : "i"(HMC_ ## NAME), "0"(__r16) \ ++ : "$1", "$22", "$23", "$24", "$25"); \ ++ return __r0; \ ++} ++ ++#define __CALL_HMC_RW2(NAME, RTYPE, TYPE0, TYPE1) \ ++static inline RTYPE NAME(TYPE0 arg0, TYPE1 arg1) \ ++{ \ ++ register RTYPE __r0 __asm__("$0"); \ ++ register TYPE0 __r16 __asm__("$16") = arg0; \ ++ register TYPE1 __r17 __asm__("$17") = arg1; \ ++ __asm__ __volatile__ ("sys_call %3 # "#NAME \ ++ : "=r"(__r16), "=r"(__r17), "=r"(__r0) \ ++ : "i"(HMC_ ## NAME), "0"(__r16), "1"(__r17) \ ++ : "$1", "$22", "$23", "$24", "$25"); \ ++ return __r0; \ ++} ++ ++__CALL_HMC_W1(ret, unsigned long); ++__CALL_HMC_RW1(swpipl, unsigned long, unsigned long); ++__CALL_HMC_RW2(cpuid, unsigned long, unsigned long, unsigned long); ++ ++#endif /* __SW_64_HMC_H */ +diff --git a/include/grub/sw64/regdef.h b/include/grub/sw64/regdef.h +new file mode 100644 +index 000000000..b30eb770e +--- /dev/null ++++ b/include/grub/sw64/regdef.h +@@ -0,0 +1,44 @@ ++#ifndef __sw_regdef_h__ ++#define __sw_regdef_h__ ++ ++#define v0 $0 /* function return value */ ++ ++#define t0 $1 /* temporary registers (caller-saved) */ ++#define t1 $2 ++#define t2 $3 ++#define t3 $4 ++#define t4 $5 ++#define t5 $6 ++#define t6 $7 ++#define t7 $8 ++ ++#define s0 $9 /* saved-registers (callee-saved registers) */ ++#define s1 $10 ++#define s2 $11 ++#define s3 $12 ++#define s4 $13 ++#define s5 $14 ++#define s6 $15 ++#define fp s6 /* frame-pointer (s6 in frame-less procedures) */ ++ ++#define a0 $16 /* argument registers (caller-saved) */ ++#define a1 $17 ++#define a2 $18 ++#define a3 $19 ++#define a4 $20 ++#define a5 $21 ++ ++#define t8 $22 /* more temps (caller-saved) */ ++#define t9 $23 ++#define t10 $24 ++#define t11 $25 ++#define ra $26 /* return address register */ ++#define t12 $27 ++ ++#define pv t12 /* procedure-variable register */ ++#define AT $at /* assembler temporary */ ++#define gp $29 /* global pointer */ ++#define sp $30 /* stack pointer */ ++#define zero $31 /* reads as zero, writes are noops */ ++ ++#endif /* __sw_64_regdef_h__ */ +diff --git a/include/grub/sw64/setjmp.h b/include/grub/sw64/setjmp.h +new file mode 100644 +index 000000000..a71c9c56d +--- /dev/null ++++ b/include/grub/sw64/setjmp.h +@@ -0,0 +1,28 @@ ++/* Define the machine-dependent type `jmp_buf'. Linux/IA-64 version. ++ Copyright (C) 1999, 2000, 2008 Free Software Foundation, Inc. ++ Contributed by David Mosberger-Tang . ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Library General Public License as ++ published by the Free Software Foundation; either version 2 of the ++ License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Library General Public License for more details. ++ ++ You should have received a copy of the GNU Library General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If not, ++ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. */ ++ ++/* User code must not depend on the internal representation of jmp_buf. */ ++ ++#define _JBLEN 70 ++ ++/* the __jmp_buf element type should be __float80 per ABI... */ ++typedef long grub_jmp_buf[_JBLEN] __attribute__ ((aligned (16))); /* guarantees 128-bit alignment! */ ++ ++int grub_setjmp (grub_jmp_buf env); ++void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn)); +diff --git a/include/grub/sw64/time.h b/include/grub/sw64/time.h +new file mode 100644 +index 000000000..03ee79fa4 +--- /dev/null ++++ b/include/grub/sw64/time.h +@@ -0,0 +1,28 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2007, 2008 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef KERNEL_CPU_TIME_HEADER ++#define KERNEL_CPU_TIME_HEADER 1 ++ ++static __inline void ++grub_cpu_idle (void) ++{ ++ /* FIXME: not implemented */ ++} ++ ++#endif /* ! KERNEL_CPU_TIME_HEADER */ +diff --git a/include/grub/sw64/types.h b/include/grub/sw64/types.h +new file mode 100644 +index 000000000..91a546dd2 +--- /dev/null ++++ b/include/grub/sw64/types.h +@@ -0,0 +1,32 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2008 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_TYPES_CPU_HEADER ++#define GRUB_TYPES_CPU_HEADER 1 ++ ++/* The size of void *. */ ++#define GRUB_TARGET_SIZEOF_VOID_P 8 ++ ++/* The size of long. */ ++#define GRUB_TARGET_SIZEOF_LONG 8 ++ ++/* ia64 is little-endian (usually). */ ++#undef GRUB_TARGET_WORDS_BIGENDIAN ++ ++ ++#endif /* ! GRUB_TYPES_CPU_HEADER */ +diff --git a/include/grub/util/install.h b/include/grub/util/install.h +index 7df3191f4..13ad805e9 100644 +--- a/include/grub/util/install.h ++++ b/include/grub/util/install.h +@@ -109,6 +109,7 @@ enum grub_install_plat + GRUB_INSTALL_PLATFORM_ARM_COREBOOT, + GRUB_INSTALL_PLATFORM_RISCV32_EFI, + GRUB_INSTALL_PLATFORM_RISCV64_EFI, ++ GRUB_INSTALL_PLATFORM_SW64_EFI, + GRUB_INSTALL_PLATFORM_MAX + }; + +diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h +index e9e0a6724..e68ee361e 100644 +--- a/include/grub/util/misc.h ++++ b/include/grub/util/misc.h +@@ -49,4 +49,8 @@ void grub_util_host_init (int *argc, char ***argv); + + int grub_qsort_strcmp (const void *, const void *); + ++#ifdef __sw_64__ ++void __attribute__ ((weak)) sunway_debug_delegate(char *buffer); ++#endif ++ + #endif /* ! GRUB_UTIL_MISC_HEADER */ +diff --git a/util/grub-install-common.c b/util/grub-install-common.c +index 4e212e690..e09abd1a7 100644 +--- a/util/grub-install-common.c ++++ b/util/grub-install-common.c +@@ -902,6 +902,7 @@ static struct + [GRUB_INSTALL_PLATFORM_ARM_COREBOOT] = { "arm", "coreboot" }, + [GRUB_INSTALL_PLATFORM_RISCV32_EFI] = { "riscv32", "efi" }, + [GRUB_INSTALL_PLATFORM_RISCV64_EFI] = { "riscv64", "efi" }, ++ [GRUB_INSTALL_PLATFORM_SW64_EFI] = { "sw64", "efi" }, + }; + + char * +diff --git a/util/grub-install.c b/util/grub-install.c +index 0fbe7f78c..f4159b981 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -332,6 +332,8 @@ get_default_platform (void) + #else + return NULL; + #endif ++#elif defined (__sw_64__) ++ return "sw64-efi"; + #else + return NULL; + #endif +@@ -507,6 +509,7 @@ have_bootdev (enum grub_install_plat pl) + case GRUB_INSTALL_PLATFORM_I386_XEN: + case GRUB_INSTALL_PLATFORM_X86_64_XEN: + case GRUB_INSTALL_PLATFORM_I386_XEN_PVH: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + return 0; + + /* pacify warning. */ +@@ -912,6 +915,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + case GRUB_INSTALL_PLATFORM_RISCV32_EFI: + case GRUB_INSTALL_PLATFORM_RISCV64_EFI: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + case GRUB_INSTALL_PLATFORM_I386_IEEE1275: + case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: +@@ -959,6 +963,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + case GRUB_INSTALL_PLATFORM_RISCV32_EFI: + case GRUB_INSTALL_PLATFORM_RISCV64_EFI: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + case GRUB_INSTALL_PLATFORM_I386_IEEE1275: + case GRUB_INSTALL_PLATFORM_ARM_UBOOT: + +@@ -906,6 +909,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_I386_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + case GRUB_INSTALL_PLATFORM_X86_64_EFI: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + is_efi = 1; + grub_util_error (_("this utility cannot be used for EFI platforms" + " because it does not support UEFI Secure Boot")); +@@ -1133,6 +1139,9 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_RISCV64_EFI: + efi_file = "BOOTRISCV64.EFI"; + break; ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: ++ efi_file = "BOOTSW64.EFI"; ++ break; + default: + grub_util_error ("%s", _("You've found a bug")); + break; +@@ -1166,6 +1175,9 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_RISCV64_EFI: + efi_file = "grubriscv64.efi"; + break; ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: ++ efi_file = "grubsw64.efi"; ++ break; + default: + efi_file = "grub.efi"; + break; +@@ -1470,6 +1482,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + case GRUB_INSTALL_PLATFORM_RISCV32_EFI: + case GRUB_INSTALL_PLATFORM_RISCV64_EFI: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + g = grub_util_guess_efi_drive (*curdev); + break; +@@ -1565,6 +1578,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + case GRUB_INSTALL_PLATFORM_RISCV32_EFI: + case GRUB_INSTALL_PLATFORM_RISCV64_EFI: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + core_name = "core.efi"; + snprintf (mkimage_target, sizeof (mkimage_target), +@@ -1670,6 +1684,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + case GRUB_INSTALL_PLATFORM_RISCV32_EFI: + case GRUB_INSTALL_PLATFORM_RISCV64_EFI: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS: + case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS: +@@ -1924,6 +1939,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_ARM64_EFI: + case GRUB_INSTALL_PLATFORM_RISCV32_EFI: + case GRUB_INSTALL_PLATFORM_RISCV64_EFI: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + { + char *dst = grub_util_path_concat (2, efidir, efi_file); +diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c +index d78fa3e53..aa57aa638 100644 +--- a/util/grub-mkimagexx.c ++++ b/util/grub-mkimagexx.c +@@ -781,8 +781,18 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, + Elf_Half i; + Elf_Shdr *s; + #ifdef MKIMAGE_ELF64 ++ grub_uint64_t got_offset = 0; ++ grub_uint64_t *gpptr; ++ ++ if (image_target->elf_target == EM_SW_64) ++ { ++ got_offset = got_off; ++ gpptr = (void *) (pe_target + got_offset + 0x8000); ++ } ++ else ++ gpptr = (void *) (pe_target + got_off); ++ + struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off); +- grub_uint64_t *gpptr = (void *) (pe_target + got_off); + unsigned unmatched_adr_got_page = 0; + #define MASK19 ((1 << 19) - 1) + #else +@@ -1123,6 +1133,118 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, + } + break; + } ++ case EM_SW_64: ++ { ++ sym_addr += addend; ++ switch (ELF_R_TYPE (info)) ++ { ++ case R_SW64_NONE: ++ break; ++ case R_SW64_REFLONG: ++ *(grub_uint32_t *)target = grub_host_to_target32 (sym_addr); ++ break; ++ case R_SW64_REFQUAD: ++ { ++ *(grub_uint32_t *)target = grub_host_to_target32(sym_addr); ++ *((grub_uint32_t *)target + 1) = grub_host_to_target32(sym_addr >> 32); ++ break; ++ } ++ case R_SW64_GPREL32: ++ { ++ *(grub_uint32_t *) target = (grub_host_to_target64 (sym_addr) - ++ ((char *) gpptr - (char *)pe_target + image_target->vaddr_offset )) & 0xffffffff; ++ break; ++ } ++ case R_SW64_LITERAL: ++ { ++ grub_uint64_t li_hi; ++ grub_uint64_t li_lo; ++ ++ li_hi = (grub_uint64_t)pe_target + got_offset + (((grub_uint64_t)ELF_R_TYPE(r->r_info)) >> 8 ); ++ li_lo = li_hi - ((grub_uint64_t) gpptr); ++ *(grub_uint16_t *) target = (li_lo & 0xffff); ++ *(grub_uint64_t *) (li_hi) = grub_host_to_target64(grub_host_to_target64 (sym_addr)); ++ got_offset += 8; ++ break; ++ } ++ case R_SW64_LITERAL_GOT: ++ break; ++ case R_SW64_LITUSE: ++ break; ++ case R_SW64_GPDISP: ++ { ++ grub_uint64_t hi; ++ grub_uint64_t lo; ++ grub_int64_t gpoffset = (((char *) gpptr - (char *) pe_target + image_target->vaddr_offset)) ++ - ((offset + target_section_addr + image_target->vaddr_offset)); ++ if (gpoffset & 0x8000) { ++ hi = ((gpoffset + 0x8000) >> 16) & 0xffff; ++ lo = gpoffset & 0xffff; ++ } else { ++ hi = (gpoffset >> 16) & 0xffff; ++ lo = gpoffset & 0xffff; ++ } ++ *(grub_uint32_t *) target = grub_host_to_target32 ((grub_target_to_host32 (*target) & 0xffff0000) | (hi & 0xffff)); ++ *(grub_uint32_t *) ((unsigned long)target + addend) = ++ grub_host_to_target32 ((grub_target_to_host32 (*(grub_uint32_t *) ++ ((unsigned long)target + addend)) & 0xffff0000) | (lo & 0xffff)); ++ break; ++ } ++ case R_SW64_BRADDR: ++ { ++ grub_uint64_t braddr = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr) - ((grub_uint64_t)target + 4); ++ braddr = braddr >> 2; ++ *(grub_uint32_t *) target = (*(grub_uint32_t *)target & (~0x1fffff)) | (braddr & 0x1fffff); ++ break; ++ } ++ case R_SW64_HINT: ++ break; ++ case R_SW64_SREL32: ++ { ++ grub_uint64_t srel32 = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr); ++ srel32 -= (grub_uint64_t)target; ++ *(grub_uint32_t *) target = srel32; ++ break; ++ } ++ case R_SW64_SREL64: ++ { ++ grub_uint64_t srel64 = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr); ++ srel64 -= (grub_uint64_t)target; ++ *(grub_uint64_t *) target = srel64; ++ break; ++ } ++ case R_SW64_GPRELHIGH: ++ { ++ grub_uint64_t gprel_hi = ((grub_host_to_target64 (sym_addr) - (((char *) gpptr - (char *)pe_target + image_target->vaddr_offset) + 0x0))); ++ ++ if (gprel_hi & 0x8000) ++ gprel_hi = ((gprel_hi + 0x8000) >> 16) & 0xffff; ++ else ++ gprel_hi = (gprel_hi >> 16) & 0xffff; ++ ++ *(grub_uint32_t *) target = grub_host_to_target32 ((grub_target_to_host32 (*target) & 0xffff0000) | (gprel_hi & 0xffff)); ++ break; ++ } ++ case R_SW64_GPRELLOW: ++ { ++ grub_uint64_t gprel_lo = (grub_host_to_target64 (sym_addr) - ((char *) gpptr - (char *)pe_target + image_target->vaddr_offset)); ++ *(grub_uint32_t *) target = grub_host_to_target32 ((grub_target_to_host32 (*target) & 0xffff0000) | (gprel_lo & 0xffff)); ++ break; ++ } ++ case R_SW64_GPREL16: ++ { ++ grub_uint64_t gprel16 = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr); ++ gprel16 = (grub_uint64_t)(gprel16 - (grub_uint64_t)gpptr); ++ *(grub_uint16_t *) target = gprel16; ++ break; ++ } ++ default: ++ grub_util_error (_("relocation 0x%lx is not implemented yet"), ++ ELF_R_TYPE (info)); ++ break; ++ } ++ break; ++ } + #endif + #if defined(MKIMAGE_ELF32) + case EM_ARM: +@@ -1594,6 +1716,19 @@ translate_relocation_pe (struct translate_context *ctx, + image_target); + } + break; ++ case EM_SW_64: ++ if (ELF_R_TYPE (info) == R_SW64_REFQUAD) ++ { ++ grub_util_info ("adding a relocation entry for 0x%llx", ++ (unsigned long long) addr); ++ ctx->current_address ++ = add_fixup_entry (&ctx->lst, ++ GRUB_PE32_REL_BASED_DIR64, ++ addr, ++ 0, ctx->current_address, ++ image_target); ++ } ++ break; + case EM_IA_64: + switch (ELF_R_TYPE (info)) + { +@@ -2015,7 +2150,8 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, + + image_target->vaddr_offset, + 2 * layout->ia64jmpnum, + image_target); +- if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64) ++ if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64 || ++ image_target->elf_target == EM_SW_64) + create_u64_fixups (&ctx, + layout->got_off + + image_target->vaddr_offset, +@@ -2384,6 +2520,17 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, + + grub_arm64_dl_get_tramp_got_size (e, &tramp, &layout->got_size); + ++ layout->got_off = layout->kernel_size; ++ layout->kernel_size += ALIGN_UP (layout->got_size, 16); ++ } ++ else if (image_target->elf_target == EM_SW_64) ++ { ++ grub_size_t tramp; ++ ++ layout->kernel_size = ALIGN_UP (layout->kernel_size, 16); ++ ++ grub_sw64_dl_get_tramp_got_size (e, &tramp, &layout->got_size); ++ + layout->got_off = layout->kernel_size; + layout->kernel_size += ALIGN_UP (layout->got_size, 16); + } +diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c +index 163529ca9..f48bfbd56 100644 +--- a/util/grub-module-verifier.c ++++ b/util/grub-module-verifier.c +@@ -176,6 +176,24 @@ struct grub_module_verifier_arch archs[] = { + -1 + } + }, ++ { "sw64", 8, 0, EM_SW_64, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ ++ R_SW64_NONE, ++ R_SW64_REFQUAD, ++ R_SW64_GPREL32, ++ R_SW64_LITERAL, ++ R_SW64_LITERAL_GOT, ++ R_SW64_LITUSE, ++ R_SW64_GPDISP, ++ R_SW64_BRSGP, ++ R_SW64_BRADDR, ++ R_SW64_HINT, ++ R_SW64_SREL32, ++ R_SW64_SREL64, ++ R_SW64_GPRELHIGH, ++ R_SW64_GPRELLOW, ++ R_SW64_GPREL16, ++ -1 ++ } }, + }; + + struct platform_whitelist { +diff --git a/util/misc.c b/util/misc.c +index d545212d9..6b1e7d360 100644 +--- a/util/misc.c ++++ b/util/misc.c +@@ -223,3 +223,9 @@ grub_qsort_strcmp (const void *p1, const void *p2) + return strcmp(*(char *const *)p1, *(char *const *)p2); + } + ++#ifdef __sw_64__ ++void __attribute__ ((weak)) ++sunway_debug_delegate(char *buffer __attribute__ ((unused))) ++{ ++} ++#endif +diff --git a/util/mkimage.c b/util/mkimage.c +index a26cf76f7..895a0a57e 100644 +--- a/util/mkimage.c ++++ b/util/mkimage.c +@@ -425,6 +425,22 @@ static const struct grub_install_image_target_desc image_targets[] = + .pe_target = GRUB_PE32_MACHINE_IA64, + .elf_target = EM_IA_64, + }, ++ { ++ .dirname = "sw64-efi", ++ .names = {"sw64-efi", NULL}, ++ .voidp_sizeof = 8, ++ .bigendian = 0, ++ .id = IMAGE_EFI, ++ .flags = PLATFORM_FLAGS_NONE, ++ .total_module_size = TARGET_NO_FIELD, ++ .decompressor_compressed_size = TARGET_NO_FIELD, ++ .decompressor_uncompressed_size = TARGET_NO_FIELD, ++ .decompressor_uncompressed_addr = TARGET_NO_FIELD, ++ .section_align = GRUB_PE32_SECTION_ALIGNMENT, ++ .vaddr_offset = EFI64_HEADER_SIZE, ++ .pe_target = GRUB_PE32_MACHINE_SW_64, ++ .elf_target = EM_SW_64, ++ }, + { + .dirname = "mips-arc", + .names = {"mips-arc", NULL}, +-- +2.33.0 + diff --git a/grub2.spec b/grub2.spec index cedbd44528979bf7534cf4a44ecd0ce6b9ebaf7f..4da789b67eb6632c7d59f7f7f4d2aa75e977888d 100644 --- a/grub2.spec +++ b/grub2.spec @@ -1,3 +1,4 @@ +%define efi_vendor %{expand:%{_efi_srpm_macros_setup}}%{expand:%{_efi_vendor}} %undefine _hardened_build %global tarversion 2.06 @@ -14,7 +15,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 33 +Release: 34 Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -33,6 +34,10 @@ Source12: bootstrap.conf Source13: sbat.csv.in Source14: config_for_secure +Source3000: 9000-Add-sw_64-support.patch +Source3001: 0021-grub-enable-kernel.kss.img-build-for-sw64_efi.patch +Source3002: grubsw_64.efi + %include %{SOURCE1} %include %{SOURCE2} @@ -313,6 +318,57 @@ if [ -f /etc/default/grub ]; then fi fi +# kylinsec +if [ $(arch) == aarch64 ];then + lspci -v | grep "Kernel driver in use:" | grep mwv206 + if [ $? == 0 ];then + sed -i 's/terminal_output/#terminal_output/g' /etc/grub.d/00_header + fi +fi +# end kylinsec + +# kylinsec +%posttrans common +set -eu + +EFI_HOME=%{efi_esp_dir} +GRUB_HOME=/boot/%{name} +ESP_PATH=/boot/efi + +if ! mountpoint -q ${ESP_PATH}; then + exit 0 # no ESP mounted, nothing to do +fi + +if test ! -f ${EFI_HOME}/grub.cfg; then + # there's no config in ESP, create one + grub2-mkconfig -o ${EFI_HOME}/grub.cfg +fi + +if grep -q "configfile" ${EFI_HOME}/grub.cfg; then + exit 0 # already unified, nothing to do +fi + +# create a stub grub2 config in EFI +BOOT_UUID=$(%{name}-probe --target=fs_uuid ${GRUB_HOME}) +GRUB_DIR=$(%{name}-mkrelpath ${GRUB_HOME}) + +cat << EOF > ${EFI_HOME}/grub.cfg.stb +search --no-floppy --fs-uuid --set=dev ${BOOT_UUID} +set prefix=(\$dev)${GRUB_DIR} +export \$prefix +configfile \$prefix/grub.cfg +EOF + +if test -f ${EFI_HOME}/grubenv; then + cp -a ${EFI_HOME}/grubenv ${EFI_HOME}/grubenv.rpmsave + mv --force ${EFI_HOME}/grubenv ${GRUB_HOME}/grubenv +fi + +cp -a ${EFI_HOME}/grub.cfg ${EFI_HOME}/grub.cfg.rpmsave +cp -a ${EFI_HOME}/grub.cfg ${GRUB_HOME}/ +mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg +# end kylinsec + %files common -f grub.lang %defattr(-,root,root) %license COPYING @@ -440,6 +496,47 @@ fi %{_datadir}/man/man* %changelog +* Mon Apr 03 2023 majinhao - 1:2.06-27.kb17 +- KYOS-F: remove the grub parameter "rb.lvm.lv=ko/backup" for sw + +* Sun Apr 02 2023 majinhao - 1:2.06-27.kb16 +- KYOS-F: add the grub parameter crashkernel=512M for sw + +* Sat Apr 01 2023 majinhao - 1:2.06-27.kb15 +- KYOS-F: optimize backup and restore configuration files (#9159) + +* Fri Jul 28 2023 majinhao - 1:2.06-27.kb14 +- KYOS-F: modify duplicate grub2 boot entries (#9802) + +* Fri Jul 28 2023 guoqinglan - 1:2.06-27.kb13 +- KYOS-F: remove cmdline args audit=1 for sw_64 (#10373) +- KYOS-F: remove cmdline args console=tty0 console=ttyS0,115200n8 for sw_64 (#9811) + +* Mon Jul 17 2023 panchenbo - 1:2.06-27.kb12 +- KYOS-F: kss fallback to soft backend when hardware is not av + +* Wed Jul 05 2023 panchenbo - 1:2.06-27.kb11 +- KYOS-F: del some unused files for kss + set enforcing 0 for sw + +* Wed Jul 05 2023 mazhiguo - 1:2.06-27.kb10 +- KYOS-F: fixed kylin-backup-grub.sh for sw + +* Sat Jul 01 2023 mazhiguo - 1:2.06-27.kb9 +- KYOS-F: fixed 10_linux script for sw(#8642) + +* Tue Jun 27 2023 panchenbo - 1:2.06-27.kb8 +- KYOS-F: fix sw_64 grub.efi boot fail + +* Wed Jun 21 2023 mazhiguo - 1:2.06-27.kb7 +- KYOS-F: fixed kylin-backup-grub.sh + +* Mon Jun 5 2023 Wang Zhijiang - 1:2.06-27.kb6 +- KYOS-F: integrity trusted feature + +* Wed May 31 2023 mazhiguo - 1:2.06-27.kb5 +- KYOS-F: fixed boot para for backup(#4864) + * Mon Jul 24 2023 zhangqiumiao - 1:2.06-33 - Type:bugfix - CVE:NA @@ -656,7 +753,7 @@ fi * Wed Jan 12 2022 lvxiaoqian - 2.06-6 - update grub.macros for riscv - + * Thu Apr 14 2022 zhangqiumiao - 2.06-5 - Type:bugfix - CVE:NA @@ -853,8 +950,8 @@ strip kernel.exec and lnboot.image - add CPPFLAGS * Sat Aug 1 2020 hanzhijun - 2.04-1 -- update to 2.0.4 - +- update to 2.0.4 + * Fri Jul 17 2020 chenyaqiang - 2.02-75 - remove repeated buildrequest packge “rpm-devel” in grub2.spec diff --git a/grubsw_64.efi b/grubsw_64.efi new file mode 100755 index 0000000000000000000000000000000000000000..719f53ef508c6f8527234dd3569ea7fb484b8aee Binary files /dev/null and b/grubsw_64.efi differ