File riscv.patch of Package grub2

Index: grub-2.02/configure.ac
===================================================================
--- grub-2.02.orig/configure.ac
+++ grub-2.02/configure.ac
@@ -104,6 +104,12 @@ case "$target_cpu" in
   aarch64*)
 		target_cpu=arm64
 		;;
+  riscv32*)
+		target_cpu=riscv32
+		;;
+  riscv64*)
+		target_cpu=riscv64
+		;;
 esac
 
 # Specify the platform (such as firmware).
@@ -127,6 +133,8 @@ if test "x$with_platform" = x; then
     ia64-*) platform=efi ;;
     arm-*) platform=uboot ;;
     arm64-*) platform=efi ;;
+    riscv32-*) platform=efi ;;
+    riscv64-*) platform=efi ;;
     *)
       AC_MSG_WARN([unsupported CPU: "$target_cpu" - only building utilities])
       platform=none
@@ -173,6 +181,8 @@ case "$target_cpu"-"$platform" in
   arm-uboot) ;;
   arm-efi) ;;
   arm64-efi) ;;
+  riscv32-efi) ;;
+  riscv64-efi) ;;
   *-emu) ;;
   *-none) ;;
   *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;;
@@ -810,6 +820,16 @@ if test x"$platform" != xemu ; then
        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
 		         [grub_cv_target_cc_soft_float="-mgeneral-regs-only"], [])
     fi
+    if test "x$target_cpu" = xriscv32; then
+       CFLAGS="$TARGET_CFLAGS -march=rv32imac -mabi=ilp32 -Werror"
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+		         [grub_cv_target_cc_soft_float="-march=rv32imac -mabi=ilp32"], [])
+    fi
+    if test "x$target_cpu" = xriscv64; then
+       CFLAGS="$TARGET_CFLAGS -march=rv64imac -mabi=lp64 -Werror"
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+		         [grub_cv_target_cc_soft_float="-march=rv64imac -mabi=lp64"], [])
+    fi
     if test "x$target_cpu" = xia64; then
        CFLAGS="$TARGET_CFLAGS -mno-inline-float-divide -mno-inline-sqrt -Werror"
        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
@@ -1899,6 +1919,10 @@ AM_CONDITIONAL([COND_arm64_efi], [test x
 AM_CONDITIONAL([COND_s390x], [test x$target_cpu = xs390x ])
 AM_CONDITIONAL([COND_NOT_s390x], [test x$target_cpu != xs390x ])
 AM_CONDITIONAL([COND_s390x_emu], [test x$target_cpu = xs390x -a x$platform = xemu])
+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_HOST_HURD], [test x$host_kernel = xhurd])
 AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux])
Index: grub-2.02/gentpl.py
===================================================================
--- grub-2.02.orig/gentpl.py
+++ grub-2.02/gentpl.py
@@ -31,7 +31,8 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i3
                    "i386_xen", "x86_64_xen",
                    "mips_loongson", "sparc64_ieee1275",
                    "powerpc_ieee1275", "mips_arc", "ia64_efi",
-                   "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi" ]
+                   "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi",
+                   "riscv32_efi", "riscv64_efi" ]
 
 GROUPS = {}
 
@@ -46,9 +47,12 @@ GROUPS["sparc64"]  = [ "sparc64_ieee1275
 GROUPS["powerpc"]  = [ "powerpc_ieee1275" ]
 GROUPS["arm"]      = [ "arm_uboot", "arm_efi" ]
 GROUPS["arm64"]    = [ "arm64_efi" ]
+GROUPS["riscv32"]  = [ "riscv32_efi" ]
+GROUPS["riscv64"]  = [ "riscv64_efi" ]
 
 # Groups based on firmware
-GROUPS["efi"]  = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi" ]
+GROUPS["efi"]  = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi",
+		   "riscv32_efi", "riscv64_efi" ]
 GROUPS["ieee1275"]   = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ]
 GROUPS["uboot"] = [ "arm_uboot" ]
 GROUPS["xen"]  = [ "i386_xen", "x86_64_xen" ]
@@ -74,7 +78,7 @@ GROUPS["terminfomodule"]   = GRUB_PLATFO
 for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i)
 
 # Flattened Device Trees (FDT)
-GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi" ]
+GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi", "riscv32_efi", "riscv64_efi" ]
 
 # Needs software helpers for division
 # Must match GRUB_DIVISION_IN_SOFTWARE in misc.h
Index: grub-2.02/grub-core/Makefile.am
===================================================================
--- grub-2.02.orig/grub-core/Makefile.am
+++ grub-2.02/grub-core/Makefile.am
@@ -254,6 +254,18 @@ KERNEL_HEADER_FILES += $(top_srcdir)/inc
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
 endif
 
+if COND_riscv32_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/acpi.h
+endif
+
+if COND_riscv64_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/acpi.h
+endif
+
 if COND_emu
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h
Index: grub-2.02/grub-core/Makefile.core.def
===================================================================
--- grub-2.02.orig/grub-core/Makefile.core.def
+++ grub-2.02/grub-core/Makefile.core.def
@@ -65,6 +65,12 @@ kernel = {
   arm64_efi_ldflags          = '-Wl,-r,-d';
   arm64_efi_stripflags       = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame';
 
+  riscv32_efi_ldflags      = '-Wl,-r,-d';
+  riscv32_efi_stripflags   = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame';
+
+  riscv64_efi_ldflags      = '-Wl,-r,-d';
+  riscv64_efi_stripflags   = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame';
+
   i386_pc_ldflags          = '$(TARGET_IMG_LDFLAGS)';
   i386_pc_ldflags          = '$(TARGET_IMG_BASE_LDOPT),0x9000';
   i386_qemu_ldflags        = '$(TARGET_IMG_LDFLAGS)';
@@ -108,6 +114,8 @@ kernel = {
   arm_uboot_startup = kern/arm/uboot/startup.S;
   arm_efi_startup = kern/arm/efi/startup.S;
   arm64_efi_startup = kern/arm64/efi/startup.S;
+  riscv32_efi_startup = kern/riscv/efi/startup.S;
+  riscv64_efi_startup = kern/riscv/efi/startup.S;
 
   common = kern/command.c;
   common = kern/corecmd.c;
@@ -218,6 +226,12 @@ kernel = {
   arm64_efi = kern/arm64/efi/init.c;
   arm64_efi = kern/efi/fdt.c;
 
+  riscv32_efi = kern/riscv/efi/init.c;
+  riscv32_efi = kern/efi/fdt.c;
+
+  riscv64_efi = kern/riscv/efi/init.c;
+  riscv64_efi = kern/efi/fdt.c;
+
   i386_pc = kern/i386/pc/init.c;
   i386_pc = kern/i386/pc/mmap.c;
   i386_pc = term/i386/pc/console.c;
@@ -285,6 +299,14 @@ kernel = {
   arm64 = kern/arm64/dl.c;
   arm64 = kern/arm64/dl_helper.c;
 
+  riscv32 = kern/riscv/cache.c;
+  riscv32 = kern/riscv/cache_flush.S;
+  riscv32 = kern/riscv/dl.c;
+
+  riscv64 = kern/riscv/cache.c;
+  riscv64 = kern/riscv/cache_flush.S;
+  riscv64 = kern/riscv/dl.c;
+
   emu = disk/host.c;
   emu = kern/emu/cache_s.S;
   emu = kern/emu/hostdisk.c;
@@ -782,6 +804,8 @@ module = {
   enable = arm_efi;
   enable = arm64_efi;
   enable = arm_uboot;
+  enable = riscv32_efi;
+  enable = riscv64_efi;
 };
 
 module = {
@@ -1597,6 +1621,7 @@ module = {
   extra_dist = lib/ia64/longjmp.S;
   extra_dist = lib/arm/setjmp.S;
   extra_dist = lib/arm64/setjmp.S;
+  extra_dist = lib/riscv/setjmp.S;
 };
 
 module = {
@@ -1696,6 +1721,8 @@ module = {
   ia64_efi = loader/ia64/efi/linux.c;
   arm = loader/arm/linux.c;
   arm64 = loader/arm64/linux.c;
+  riscv32 = loader/riscv/linux.c;
+  riscv64 = loader/riscv/linux.c;
   emu = loader/emu/linux.c;
   common = loader/linux.c;
   common = lib/cmdline.c;
@@ -1704,6 +1731,8 @@ module = {
 module = {
   name = fdt;
   arm64 = loader/arm64/fdt.c;
+  riscv32 = loader/arm64/fdt.c;
+  riscv64 = loader/arm64/fdt.c;
   common = lib/fdt.c;
   enable = fdt;
 };
@@ -1795,6 +1824,8 @@ module = {
   enable = ia64_efi;
   enable = arm_efi;
   enable = arm64_efi;
+  enable = riscv32_efi;
+  enable = riscv64_efi;
   enable = mips;
 };
 
Index: grub-2.02/grub-core/commands/file.c
===================================================================
--- grub-2.02.orig/grub-core/commands/file.c
+++ grub-2.02/grub-core/commands/file.c
@@ -88,6 +88,10 @@ static const struct grub_arg_option opti
    N_("Check if FILE is ARM64 EFI file"), 0, 0},
   {"is-arm-efi", 0, 0,
    N_("Check if FILE is ARM EFI file"), 0, 0},
+  {"is-riscv32-efi", 0, 0,
+   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-hibernated-hiberfil", 0, 0,
    N_("Check if FILE is hiberfil.sys in hibernated state"), 0, 0},
   {"is-x86_64-xnu", 0, 0,
@@ -128,6 +132,7 @@ enum
   IS_IA_EFI,
   IS_ARM64_EFI,
   IS_ARM_EFI,
+  IS_RISCV_EFI,
   IS_HIBERNATED,
   IS_XNU64,
   IS_XNU32,
@@ -570,6 +575,7 @@ grub_cmd_file (grub_extcmd_context_t ctx
     case IS_IA_EFI:
     case IS_ARM64_EFI:
     case IS_ARM_EFI:
+    case IS_RISCV_EFI:
       {
 	char signature[4];
 	grub_uint32_t pe_offset;
@@ -615,7 +621,13 @@ grub_cmd_file (grub_extcmd_context_t ctx
 	    && coff_head.machine !=
 	    grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_ARMTHUMB_MIXED))
 	  break;
-	if (type == IS_IA_EFI || type == IS_64_EFI || type == IS_ARM64_EFI)
+	if (type == IS_RISCV_EFI
+	    && coff_head.machine !=
+	    grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_RISCV64))
+          /* TODO: Determine bitness dynamically */
+	  break;
+	if (type == IS_IA_EFI || type == IS_64_EFI || type == IS_ARM64_EFI ||
+	    type == IS_RISCV_EFI)
 	  {
 	    struct grub_pe64_optional_header o64;
 	    if (grub_file_read (file, &o64, sizeof (o64)) != sizeof (o64))
Index: grub-2.02/grub-core/kern/compiler-rt.c
===================================================================
--- grub-2.02.orig/grub-core/kern/compiler-rt.c
+++ grub-2.02/grub-core/kern/compiler-rt.c
@@ -343,7 +343,8 @@ __ucmpdi2 (grub_uint64_t a, grub_uint64_
 
 #endif
 
-#if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || defined(__arm__)
+#if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || \
+    defined(__arm__) || defined(__riscv)
 
 /* Based on libgcc2.c from gcc suite.  */
 grub_uint32_t
Index: grub-2.02/grub-core/kern/dl.c
===================================================================
--- grub-2.02.orig/grub-core/kern/dl.c
+++ grub-2.02/grub-core/kern/dl.c
@@ -230,7 +230,7 @@ grub_dl_load_segments (grub_dl_t mod, co
   unsigned i;
   const Elf_Shdr *s;
   grub_size_t tsize = 0, talign = 1;
-#if !defined (__i386__) && !defined (__x86_64__) && !defined (__s390x__)
+#if !defined (__i386__) && !defined (__x86_64__) && !defined (__s390x__) && !defined(__riscv)
   grub_size_t tramp;
   grub_size_t got;
   grub_err_t err;
@@ -246,7 +246,7 @@ grub_dl_load_segments (grub_dl_t mod, co
 	talign = s->sh_addralign;
     }
 
-#if !defined (__i386__) && !defined (__x86_64__) && !defined (__s390x__)
+#if !defined (__i386__) && !defined (__x86_64__) && !defined (__s390x__) && !defined(__riscv)
   err = grub_arch_dl_get_tramp_got_size (e, &tramp, &got);
   if (err)
     return err;
@@ -309,7 +309,7 @@ grub_dl_load_segments (grub_dl_t mod, co
 	  mod->segment = seg;
 	}
     }
-#if !defined (__i386__) && !defined (__x86_64__) && !defined (__s390x__)
+#if !defined (__i386__) && !defined (__x86_64__) && !defined (__s390x__) && !defined(__riscv)
   ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN);
   mod->tramp = ptr;
   mod->trampptr = ptr;
Index: grub-2.02/grub-core/kern/emu/cache.c
===================================================================
--- grub-2.02.orig/grub-core/kern/emu/cache.c
+++ grub-2.02/grub-core/kern/emu/cache.c
@@ -25,5 +25,11 @@ grub_arch_sync_caches (void *address, gr
   return _flush_cache (address, len, 0);
 }
 
+#elif defined(__riscv)
+void
+grub_arch_sync_caches (void *address, grub_size_t len)
+{
+}
+
 #endif
 
Index: grub-2.02/grub-core/kern/emu/cache_s.S
===================================================================
--- grub-2.02.orig/grub-core/kern/emu/cache_s.S
+++ grub-2.02/grub-core/kern/emu/cache_s.S
@@ -10,6 +10,7 @@
 #include "../powerpc/cache.S"
 #elif defined(__ia64__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__)
 #elif defined(__s390x__)
+#elif defined(__riscv)
 #else
 #error "No target cpu type is defined"
 #endif
Index: grub-2.02/grub-core/kern/emu/lite.c
===================================================================
--- grub-2.02.orig/grub-core/kern/emu/lite.c
+++ grub-2.02/grub-core/kern/emu/lite.c
@@ -26,6 +26,8 @@
 #include "../arm64/dl.c"
 #elif defined(__s390x__)
 #include "../s390x/dl.c"
+#elif defined(__riscv)
+#include "../riscv/dl.c"
 #else
 #error "No target cpu type is defined"
 #endif
Index: grub-2.02/grub-core/kern/riscv/cache.c
===================================================================
--- /dev/null
+++ grub-2.02/grub-core/kern/riscv/cache.c
@@ -0,0 +1,56 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/cache.h>
+#include <grub/misc.h>
+
+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_uint64_t line_size);
+void grub_arch_invalidate_icache_range (grub_addr_t beg, grub_addr_t end,
+					grub_uint64_t line_size);
+
+static void
+probe_caches (void)
+{
+  /* TODO */
+  dlinesz = 32;
+  ilinesz = 32;
+}
+
+void
+grub_arch_sync_caches (void *address, grub_size_t len)
+{
+  grub_uint64_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_uint64_t) address, max_align);
+  end = ALIGN_UP ((grub_uint64_t) address + len, max_align);
+
+  grub_arch_clean_dcache_range (start, end, dlinesz);
+  grub_arch_invalidate_icache_range (start, end, ilinesz);
+}
Index: grub-2.02/grub-core/kern/riscv/cache_flush.S
===================================================================
--- /dev/null
+++ grub-2.02/grub-core/kern/riscv/cache_flush.S
@@ -0,0 +1,40 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+
+	.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)
+	// TODO
+	ret
Index: grub-2.02/grub-core/kern/riscv/dl.c
===================================================================
--- /dev/null
+++ grub-2.02/grub-core/kern/riscv/dl.c
@@ -0,0 +1,208 @@
+/* dl.c - arch-dependent part of loadable module support */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/i18n.h>
+
+#define LDR 0x58000050
+#define BR 0xd61f0200
+
+
+/*
+ * 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_RISCV)
+    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_Rel *rel, *max;
+
+  for (rel = (Elf_Rel *) ((char *) ehdr + s->sh_offset),
+	 max = (Elf_Rel *) ((char *) rel + s->sh_size);
+       rel < max;
+       rel = (Elf_Rel *) ((char *) rel + s->sh_entsize))
+    {
+      Elf_Sym *sym;
+      void *place;
+      grub_uint64_t sym_addr;
+
+      if (rel->r_offset >= seg->size)
+	return grub_error (GRUB_ERR_BAD_MODULE,
+			   "reloc offset is out of the segment");
+
+      sym = (Elf_Sym *) ((char *) mod->symtab
+			 + mod->symsize * ELF_R_SYM (rel->r_info));
+
+      sym_addr = sym->st_value;
+      if (s->sh_type == SHT_RELA)
+	sym_addr += ((Elf_Rela *) rel)->r_addend;
+
+      place = (void *) ((grub_addr_t) seg->addr + rel->r_offset);
+
+      switch (ELF_R_TYPE (rel->r_info))
+	{
+	case R_RISCV_32:
+	  {
+	    grub_uint32_t *abs_place = place;
+
+	    grub_dprintf ("dl", "  reloc_abs32 %p => 0x%016llx\n",
+			  place, (unsigned long long) sym_addr);
+
+	    *abs_place = (grub_uint32_t) sym_addr;
+	  }
+	  break;
+	case R_RISCV_64:
+	  {
+	    grub_uint64_t *abs_place = place;
+
+	    grub_dprintf ("dl", "  reloc_abs64 %p => 0x%016llx\n",
+			  place, (unsigned long long) sym_addr);
+
+	    *abs_place = (grub_uint64_t) sym_addr;
+	  }
+	  break;
+
+	case R_RISCV_BRANCH:
+	  {
+	    grub_uint32_t *abs_place = place;
+	    grub_int64_t off = sym_addr - (grub_uint64_t) place;
+	    grub_uint32_t imm12 = (off & 0x1000) << (31 - 12);
+	    grub_uint32_t imm11 = (off & 0x800) >> (11 - 7);
+	    grub_uint32_t imm10_5 = (off & 0x7e0) << (30 - 10);
+	    grub_uint32_t imm4_1 = (off & 0x1e) << (11 - 4);
+	    *abs_place = (*abs_place & 0x1fff07f) | imm12 | imm11 | imm10_5 | imm4_1;
+	  }
+	  break;
+
+	case R_RISCV_JAL:
+	  {
+	    grub_uint32_t *abs_place = place;
+	    grub_int64_t off = sym_addr - (grub_uint64_t) place;
+	    grub_uint32_t imm20 = (off & 0x100000) << (31 - 20);
+	    grub_uint32_t imm19_12 = (off & 0xff000);
+	    grub_uint32_t imm11 = (off & 0x800) << (20 - 11);
+	    grub_uint32_t imm10_1 = (off & 0x7fe) << (30 - 10);
+	    *abs_place = (*abs_place & 0xfff) | imm20 | imm19_12 | imm11 | imm10_1;
+	  }
+	  break;
+
+	case R_RISCV_CALL:
+	  {
+	    grub_uint32_t *abs_place = place;
+	    grub_int64_t off = sym_addr - (grub_uint64_t) place;
+	    grub_uint32_t hi20, lo12;
+
+	    if (off != (grub_int32_t) off)
+	      return grub_error (GRUB_ERR_BAD_MODULE, "relocation overflow");
+
+	    hi20 = (off + 0x800) & 0xfffff000;
+	    lo12 = (off - hi20) & 0xfff;
+	    abs_place[0] = (abs_place[0] & 0xfff) | hi20;
+	    abs_place[1] = (abs_place[1] & 0xfffff) | (lo12 << 20);
+	  }
+	  break;
+
+	case R_RISCV_RVC_BRANCH:
+	  {
+	    grub_uint16_t *abs_place = place;
+	    grub_int64_t off = sym_addr - (grub_uint64_t) place;
+	    grub_uint16_t imm8 = (off & 0x100) << (12 - 8);
+	    grub_uint16_t imm7_6 = (off & 0xc0) >> (6 - 5);
+	    grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
+	    grub_uint16_t imm4_3 = (off & 0x18) << (12 - 5);
+	    grub_uint16_t imm2_1 = (off & 0x6) << (12 - 10);
+	    *abs_place = (*abs_place & 0xe383) | imm8 | imm7_6 | imm5 | imm4_3 | imm2_1;
+	  }
+	  break;
+
+	case R_RISCV_RVC_JUMP:
+	  {
+	    grub_uint16_t *abs_place = place;
+	    grub_int64_t off = sym_addr - (grub_uint64_t) place;
+	    grub_uint16_t imm11 = (off & 0x800) << (12 - 11);
+	    grub_uint16_t imm10 = (off & 0x400) >> (10 - 8);
+	    grub_uint16_t imm9_8 = (off & 0x300) << (12 - 11);
+	    grub_uint16_t imm7 = (off & 0x80) >> (7 - 6);
+	    grub_uint16_t imm6 = (off & 0x40) << (12 - 11);
+	    grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
+	    grub_uint16_t imm4 = (off & 0x10) << (12 - 5);
+	    grub_uint16_t imm3_1 = (off & 0xe) << (12 - 10);
+	    *abs_place = ((*abs_place & 0xe003)
+			  | imm11 | imm10 | imm9_8 | imm7 | imm6
+			  | imm5 | imm4 | imm3_1);
+	  }
+	  break;
+
+	case R_RISCV_HI20:
+	  {
+	    grub_uint32_t *abs_place = place;
+	    *abs_place = (*abs_place & 0xfff) | (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
+	  }
+	  break;
+
+	case R_RISCV_LO12_I:
+	  {
+	    grub_uint32_t *abs_place = place;
+	    grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
+	    *abs_place = (*abs_place & 0xfffff) | ((lo12 & 0xfff) << 20);
+	  }
+	  break;
+
+	case R_RISCV_LO12_S:
+	  {
+	    grub_uint32_t *abs_place = place;
+	    grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
+	    grub_uint32_t imm11_5 = (lo12 & 0xfe0) << (31 - 11);
+	    grub_uint32_t imm4_0 = (lo12 & 0x1f) << (11 - 4);
+	    *abs_place = (*abs_place & 0x1fff07f) | imm11_5 | imm4_0;
+	  }
+	  break;
+
+	case R_RISCV_RELAX:
+	  break;
+
+	default:
+	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+			     N_("relocation 0x%x is not implemented yet"),
+			     ELF_R_TYPE (rel->r_info));
+	}
+    }
+
+  return GRUB_ERR_NONE;
+}
Index: grub-2.02/grub-core/kern/riscv/efi/init.c
===================================================================
--- /dev/null
+++ grub-2.02/grub-core/kern/riscv/efi/init.c
@@ -0,0 +1,82 @@
+/* init.c - initialize a riscv-based EFI system */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/env.h>
+#include <grub/kernel.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/efi/efi.h>
+#include <grub/loader.h>
+
+static grub_uint64_t timer_frequency_in_khz;
+
+static grub_uint64_t
+grub_efi_get_time_ms (void)
+{
+  grub_uint64_t tmr;
+
+#if 0
+#if __riscv_xlen == 64
+  asm volatile ("rdtime %0" : "=r" (tmr));
+#else
+  grub_uint32_t lo, hi, tmp;
+  asm volatile (
+    "1:\n"
+    "rdtimeh %0\n"
+    "rdtime %1\n"
+    "rdtimeh %2\n"
+    "bne %0, %2, 1b"
+    : "=&r" (hi), "=&r" (lo), "=&r" (tmp));
+  tmr = ((u64)hi << 32) | lo;
+#endif
+#else
+  static grub_uint64_t val;
+  tmr = val++;
+#endif
+
+  return tmr / timer_frequency_in_khz;
+}
+
+
+void
+grub_machine_init (void)
+{
+  grub_uint64_t time_before, time_after;
+
+  grub_efi_init ();
+
+  /* Calculate timer frequency */
+  timer_frequency_in_khz = 1;
+  time_before = grub_efi_get_time_ms();
+  grub_efi_stall(1000);
+  time_after = grub_efi_get_time_ms();
+  timer_frequency_in_khz = time_after - time_before;
+
+  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 ();
+}
Index: grub-2.02/grub-core/kern/riscv/efi/startup.S
===================================================================
--- /dev/null
+++ grub-2.02/grub-core/kern/riscv/efi/startup.S
@@ -0,0 +1,49 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+
+#if __riscv_xlen == 64
+#define sl		sd
+#define ll		ld
+#else
+#define sl		sw
+#define ll		lw
+#endif
+
+
+	.file 	"startup.S"
+	.text
+FUNCTION(_start)
+	/*
+	 *  EFI_SYSTEM_TABLE and EFI_HANDLE are passed in a1/a0.
+	 */
+
+	ll	a2, efi_image_handle_val
+	sl	a0, 0(a2)
+	ll	a2, efi_system_table_val
+	sl	a1, 0(a2)
+	ll	a2, grub_main_val
+	jr	a2
+grub_main_val:
+	.quad	EXT_C(grub_main)
+efi_system_table_val:
+	.quad	EXT_C(grub_efi_system_table)
+efi_image_handle_val:
+	.quad	EXT_C(grub_efi_image_handle)
+
Index: grub-2.02/grub-core/lib/efi/halt.c
===================================================================
--- grub-2.02.orig/grub-core/lib/efi/halt.c
+++ grub-2.02/grub-core/lib/efi/halt.c
@@ -29,7 +29,8 @@ void
 grub_halt (void)
 {
   grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
-#if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__)
+#if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__) && \
+    !defined(__riscv)
   grub_acpi_halt ();
 #endif
   efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
Index: grub-2.02/grub-core/lib/riscv/setjmp.S
===================================================================
--- /dev/null
+++ grub-2.02/grub-core/lib/riscv/setjmp.S
@@ -0,0 +1,82 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+#include <grub/dl.h>
+
+	.file	"setjmp.S"
+GRUB_MOD_LICENSE "GPLv3+"
+	.text
+
+#if __riscv_xlen == 64
+#define STORE_IDX(reg, idx)     sd reg, (idx*8)(a0)
+#define LOAD_IDX(reg, idx)      ld reg, (idx*8)(a0)
+#else
+#define STORE_IDX(reg, idx)     sw reg, (idx*4)(a0)
+#define LOAD_IDX(reg, idx)      lw reg, (idx*4)(a0)
+#endif
+
+/*
+ * int grub_setjmp (grub_jmp_buf env)
+ */
+FUNCTION(grub_setjmp)
+        /* Preserve all callee-saved registers and the SP */
+        STORE_IDX(s0, 0)
+        STORE_IDX(s1, 1)
+        STORE_IDX(s2, 2)
+        STORE_IDX(s3, 3)
+        STORE_IDX(s4, 4)
+        STORE_IDX(s5, 5)
+        STORE_IDX(s6, 6)
+        STORE_IDX(s7, 7)
+        STORE_IDX(s8, 8)
+        STORE_IDX(s9, 9)
+        STORE_IDX(s10, 10)
+        STORE_IDX(s11, 11)
+        STORE_IDX(ra, 12)
+        STORE_IDX(sp, 13)
+        li  a0, 0
+        ret
+
+/*
+ * int grub_longjmp (grub_jmp_buf env, int val)
+ */
+FUNCTION(grub_longjmp)
+        LOAD_IDX(s0, 0)
+        LOAD_IDX(s1, 1)
+        LOAD_IDX(s2, 2)
+        LOAD_IDX(s3, 3)
+        LOAD_IDX(s4, 4)
+        LOAD_IDX(s5, 5)
+        LOAD_IDX(s6, 6)
+        LOAD_IDX(s7, 7)
+        LOAD_IDX(s8, 8)
+        LOAD_IDX(s9, 9)
+        LOAD_IDX(s10, 10)
+        LOAD_IDX(s11, 11)
+        LOAD_IDX(ra, 12)
+        LOAD_IDX(sp, 13)
+
+        /* Move the return value in place, but return 1 if passed 0. */
+        beq a1, zero, longjmp_1
+        mv a0, a1
+        ret
+
+        longjmp_1:
+        li a0, 1
+        ret
Index: grub-2.02/grub-core/lib/setjmp.S
===================================================================
--- grub-2.02.orig/grub-core/lib/setjmp.S
+++ grub-2.02/grub-core/lib/setjmp.S
@@ -17,6 +17,8 @@
 #include "./arm64/setjmp.S"
 #elif defined(__s390x__)
 #include "./s390x/setjmp.S"
+#elif defined(__riscv)
+#include "./riscv/setjmp.S"
 #else
 #error "Unknown target cpu type"
 #endif
Index: grub-2.02/grub-core/loader/riscv/linux.c
===================================================================
--- /dev/null
+++ grub-2.02/grub-core/loader/riscv/linux.c
@@ -0,0 +1,352 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/charset.h>
+#include <grub/command.h>
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/fdt.h>
+#include <grub/linux.h>
+#include <grub/loader.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/cpu/linux.h>
+#include <grub/cpu/fdtload.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/memory.h>
+#include <grub/efi/pe32.h>
+#include <grub/i18n.h>
+#include <grub/lib/cmdline.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_dl_t my_mod;
+static int loaded;
+
+static void *kernel_addr;
+static grub_uint64_t kernel_size;
+
+static char *linux_args;
+static grub_uint32_t cmdline_size;
+
+static grub_addr_t initrd_start;
+static grub_addr_t initrd_end;
+
+grub_err_t
+grub_riscv_uefi_check_image (struct linux_riscv_kernel_header * lh)
+{
+  if (lh->magic != GRUB_LINUX_RISCV_MAGIC_SIGNATURE)
+    return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
+
+  if ((lh->code0 & 0xffff) != GRUB_EFI_PE_MAGIC)
+    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+		       N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
+
+  grub_dprintf ("linux", "UEFI stub kernel:\n");
+  grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+finalize_params_linux (void)
+{
+  int node, retval;
+
+  void *fdt;
+
+  fdt = grub_fdt_load (0x400);
+
+  if (!fdt)
+    goto failure;
+
+  node = grub_fdt_find_subnode (fdt, 0, "chosen");
+  if (node < 0)
+    node = grub_fdt_add_subnode (fdt, 0, "chosen");
+
+  if (node < 1)
+    goto failure;
+
+  /* Set initrd info */
+  if (initrd_start && initrd_end > initrd_start)
+    {
+      grub_dprintf ("linux", "Initrd @ %p-%p\n",
+		    (void *) initrd_start, (void *) initrd_end);
+
+      retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start",
+				    initrd_start);
+      if (retval)
+	goto failure;
+      retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end",
+				    initrd_end);
+      if (retval)
+	goto failure;
+    }
+
+  if (grub_fdt_install() != GRUB_ERR_NONE)
+    goto failure;
+
+  return GRUB_ERR_NONE;
+
+failure:
+  grub_fdt_unload();
+  return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+}
+
+grub_err_t
+grub_riscv_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
+{
+  grub_efi_memory_mapped_device_path_t *mempath;
+  grub_efi_handle_t image_handle;
+  grub_efi_boot_services_t *b;
+  grub_efi_status_t status;
+  grub_efi_loaded_image_t *loaded_image;
+  int len;
+
+  mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t));
+  if (!mempath)
+    return grub_errno;
+
+  mempath[0].header.type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE;
+  mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE;
+  mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath));
+  mempath[0].memory_type = GRUB_EFI_LOADER_DATA;
+  mempath[0].start_address = addr;
+  mempath[0].end_address = addr + size;
+
+  mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+  mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+  mempath[1].header.length = sizeof (grub_efi_device_path_t);
+
+  b = grub_efi_system_table->boot_services;
+  status = b->load_image (0, grub_efi_image_handle,
+			  (grub_efi_device_path_t *) mempath,
+			  (void *) addr, size, &image_handle);
+  if (status != GRUB_EFI_SUCCESS)
+    return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
+
+  grub_dprintf ("linux", "linux command line: '%s'\n", args);
+
+  /* Convert command line to UCS-2 */
+  loaded_image = grub_efi_get_loaded_image (image_handle);
+  loaded_image->load_options_size = len =
+    (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t);
+  loaded_image->load_options =
+    grub_efi_allocate_pages (0,
+			     GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+  if (!loaded_image->load_options)
+    return grub_errno;
+
+  loaded_image->load_options_size =
+    2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
+			    (grub_uint8_t *) args, len, NULL);
+
+  grub_dprintf ("linux", "starting image %p\n", image_handle);
+  status = b->start_image (image_handle, 0, NULL);
+
+  /* When successful, not reached */
+  b->unload_image (image_handle);
+  grub_efi_free_pages ((grub_addr_t) loaded_image->load_options,
+		       GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_linux_boot (void)
+{
+  if (finalize_params_linux () != GRUB_ERR_NONE)
+    return grub_errno;
+
+  return (grub_riscv_uefi_boot_image((grub_addr_t)kernel_addr,
+                                     kernel_size, linux_args));
+}
+
+static grub_err_t
+grub_linux_unload (void)
+{
+  grub_dl_unref (my_mod);
+  loaded = 0;
+  if (initrd_start)
+    grub_efi_free_pages ((grub_efi_physical_address_t) initrd_start,
+			 GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start));
+  initrd_start = initrd_end = 0;
+  grub_free (linux_args);
+  if (kernel_addr)
+    grub_efi_free_pages ((grub_addr_t) kernel_addr,
+			 GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+  grub_fdt_unload ();
+  return GRUB_ERR_NONE;
+}
+
+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 };
+  int initrd_size, initrd_pages;
+  void *initrd_mem = NULL;
+
+  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\n");
+
+  initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
+  initrd_mem = grub_efi_allocate_pages (0, initrd_pages);
+  if (!initrd_mem)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+      goto fail;
+    }
+
+  if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
+    goto fail;
+
+  initrd_start = (grub_addr_t) initrd_mem;
+  initrd_end = initrd_start + initrd_size;
+  grub_dprintf ("linux", "[addr=%p, size=0x%x]\n",
+		(void *) initrd_start, initrd_size);
+
+ 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_err_t
+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+		int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  struct linux_riscv_kernel_header lh;
+
+  grub_dl_ref (my_mod);
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+      goto fail;
+    }
+
+  file = grub_file_open (argv[0]);
+  if (!file)
+    goto fail;
+
+  kernel_size = grub_file_size (file);
+
+  if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh))
+    return grub_errno;
+
+  if (grub_riscv_uefi_check_image (&lh) != GRUB_ERR_NONE)
+    goto fail;
+
+  grub_loader_unset();
+
+  grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
+  kernel_addr = grub_efi_allocate_pages (0, GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+  grub_dprintf ("linux", "kernel numpages: %lld\n",
+		(long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+  if (!kernel_addr)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+      goto fail;
+    }
+
+  grub_file_seek (file, 0);
+  if (grub_file_read (file, kernel_addr, kernel_size)
+      < (grub_int64_t) kernel_size)
+    {
+      if (!grub_errno)
+	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
+      goto fail;
+    }
+
+  grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+
+  cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
+  linux_args = grub_malloc (cmdline_size);
+  if (!linux_args)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+      goto fail;
+    }
+  grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+  grub_create_loader_cmdline (argc, argv,
+			      linux_args + sizeof (LINUX_IMAGE) - 1,
+			      cmdline_size);
+
+  if (grub_errno == GRUB_ERR_NONE)
+    {
+      grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
+      loaded = 1;
+    }
+
+fail:
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_dl_unref (my_mod);
+      loaded = 0;
+    }
+
+  if (linux_args && !loaded)
+    grub_free (linux_args);
+
+  if (kernel_addr && !loaded)
+    grub_efi_free_pages ((grub_addr_t) kernel_addr,
+			 GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+
+  return grub_errno;
+}
+
+
+static grub_command_t cmd_linux, cmd_initrd;
+
+GRUB_MOD_INIT (linux)
+{
+  cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0,
+				     N_("Load Linux."));
+  cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0,
+				      N_("Load initrd."));
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI (linux)
+{
+  grub_unregister_command (cmd_linux);
+  grub_unregister_command (cmd_initrd);
+}
Index: grub-2.02/include/grub/compiler-rt.h
===================================================================
--- grub-2.02.orig/include/grub/compiler-rt.h
+++ grub-2.02/include/grub/compiler-rt.h
@@ -53,7 +53,8 @@ EXPORT_FUNC (__umoddi3) (grub_uint64_t a
 
 #endif
 
-#if defined (__sparc__) || defined (__powerpc__) || defined (__mips__) || defined (__arm__)
+#if defined (__sparc__) || defined (__powerpc__) || defined (__mips__) || \
+    defined (__arm__) || defined(__riscv)
 unsigned
 EXPORT_FUNC (__ctzdi2) (grub_uint64_t x);
 #define NEED_CTZDI2 1
@@ -165,7 +166,8 @@ grub_uint64_t
 EXPORT_FUNC (__lshrdi3) (grub_uint64_t u, int b);
 #endif
 
-#if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || defined (__arm__)
+#if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || \
+    defined (__arm__) || defined(__riscv)
 grub_uint32_t
 EXPORT_FUNC(__bswapsi2) (grub_uint32_t u);
 
Index: grub-2.02/include/grub/dl.h
===================================================================
--- grub-2.02.orig/include/grub/dl.h
+++ grub-2.02/include/grub/dl.h
@@ -279,12 +279,14 @@ grub_arch_dl_get_tramp_got_size (const v
 				 grub_size_t *got);
 #endif
 
-#if defined (__powerpc__) || defined (__mips__) || defined (__arm__)
+#if defined (__powerpc__) || defined (__mips__) || defined (__arm__) || \
+    (defined(__riscv) && (__riscv_xlen == 32))
 #define GRUB_ARCH_DL_TRAMP_ALIGN 4
 #define GRUB_ARCH_DL_GOT_ALIGN 4
 #endif
 
-#if defined (__aarch64__) || defined (__sparc__)
+#if defined (__aarch64__) || defined (__sparc__) || \
+    (defined(__riscv) && (__riscv_xlen == 64))
 #define GRUB_ARCH_DL_TRAMP_ALIGN 8
 #define GRUB_ARCH_DL_GOT_ALIGN 8
 #endif
Index: grub-2.02/include/grub/efi/api.h
===================================================================
--- grub-2.02.orig/include/grub/efi/api.h
+++ grub-2.02/include/grub/efi/api.h
@@ -1971,7 +1971,8 @@ struct grub_efi_ip6_config_manual_addres
 typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t;
 
 #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
-  || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__)
+  || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \
+  || defined(__riscv)
 
 #define efi_call_0(func)		func()
 #define efi_call_1(func, a)		func(a)
Index: grub-2.02/include/grub/efi/efi.h
===================================================================
--- grub-2.02.orig/include/grub/efi/efi.h
+++ grub-2.02/include/grub/efi/efi.h
@@ -86,7 +86,7 @@ extern void (*EXPORT_VAR(grub_efi_net_co
 						char **device,
 						char **path);
 
-#if defined(__arm__) || defined(__aarch64__)
+#if defined(__arm__) || defined(__aarch64__) || defined(__riscv)
 void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void);
 #endif
 
Index: grub-2.02/include/grub/efi/pe32.h
===================================================================
--- grub-2.02.orig/include/grub/efi/pe32.h
+++ grub-2.02/include/grub/efi/pe32.h
@@ -68,6 +68,8 @@ struct grub_pe32_coff_header
 #define GRUB_PE32_MACHINE_X86_64		0x8664
 #define GRUB_PE32_MACHINE_ARMTHUMB_MIXED	0x01c2
 #define GRUB_PE32_MACHINE_ARM64			0xAA64
+#define GRUB_PE32_MACHINE_RISCV32		0x5032
+#define GRUB_PE32_MACHINE_RISCV64		0x5064
 
 #define GRUB_PE32_RELOCS_STRIPPED		0x0001
 #define GRUB_PE32_EXECUTABLE_IMAGE		0x0002
@@ -279,9 +281,12 @@ struct grub_pe32_fixup_block
 #define GRUB_PE32_REL_BASED_HIGHADJ	4
 #define GRUB_PE32_REL_BASED_MIPS_JMPADDR 5
 #define GRUB_PE32_REL_BASED_ARM_MOV32A  5
+#define GRUB_PE32_REL_BASED_RISCV_HI20	5
 #define GRUB_PE32_REL_BASED_SECTION	6
 #define GRUB_PE32_REL_BASED_REL		7
 #define GRUB_PE32_REL_BASED_ARM_MOV32T  7
+#define GRUB_PE32_REL_BASED_RISCV_LOW12I 7
+#define GRUB_PE32_REL_BASED_RISCV_LOW12S 8
 #define GRUB_PE32_REL_BASED_IA64_IMM64	9
 #define GRUB_PE32_REL_BASED_DIR64	10
 #define GRUB_PE32_REL_BASED_HIGH3ADJ	11
Index: grub-2.02/include/grub/elf.h
===================================================================
--- grub-2.02.orig/include/grub/elf.h
+++ grub-2.02/include/grub/elf.h
@@ -247,6 +247,7 @@ typedef struct
 #define EM_XTENSA	94		/* Tensilica Xtensa Architecture */
 #define EM_NUM		95
 #define EM_AARCH64	183		/* ARM 64-bit architecture */
+#define EM_RISCV	243		/* RISC-V */
 
 /* If it is necessary to assign new unofficial EM_* values, please
    pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
@@ -2473,6 +2474,64 @@ typedef Elf32_Addr Elf32_Conflict;
 
 #define R_X86_64_NUM		24
 
+/* RISC-V relocations */
+#define R_RISCV_NONE            0
+#define R_RISCV_32              1
+#define R_RISCV_64              2
+#define R_RISCV_RELATIVE        3
+#define R_RISCV_COPY            4
+#define R_RISCV_JUMP_SLOT       5
+#define R_RISCV_TLS_DTPMOD32    6
+#define R_RISCV_TLS_DTPMOD64    7
+#define R_RISCV_TLS_DTPREL32    8
+#define R_RISCV_TLS_DTPREL64    9
+#define R_RISCV_TLS_TPREL32     10
+#define R_RISCV_TLS_TPREL64     11
+
+#define R_RISCV_BRANCH          16
+#define R_RISCV_JAL             17
+#define R_RISCV_CALL            18
+#define R_RISCV_CALL_PLT        19
+#define R_RISCV_GOT_HI20        20
+#define R_RISCV_TLS_GOT_HI20    21
+#define R_RISCV_TLS_GD_HI20     22
+#define R_RISCV_PCREL_HI20      23
+#define R_RISCV_PCREL_LO12_I    24
+#define R_RISCV_PCREL_LO12_S    25
+#define R_RISCV_HI20            26
+#define R_RISCV_LO12_I          27
+#define R_RISCV_LO12_S          28
+#define R_RISCV_TPREL_HI20      29
+#define R_RISCV_TPREL_LO12_I    30
+#define R_RISCV_TPREL_LO12_S    31
+#define R_RISCV_TPREL_ADD       32
+#define R_RISCV_ADD8            33
+#define R_RISCV_ADD16           34
+#define R_RISCV_ADD32           35
+#define R_RISCV_ADD64           36
+#define R_RISCV_SUB8            37
+#define R_RISCV_SUB16           38
+#define R_RISCV_SUB32           39
+#define R_RISCV_SUB64           40
+#define R_RISCV_GNU_VTINHERIT   41
+#define R_RISCV_GNU_VTENTRY     42
+#define R_RISCV_ALIGN           43
+#define R_RISCV_RVC_BRANCH      44
+#define R_RISCV_RVC_JUMP        45
+#define R_RISCV_LUI             46
+#define R_RISCV_GPREL_I         47
+#define R_RISCV_GPREL_S         48
+#define R_RISCV_TPREL_I         49
+#define R_RISCV_TPREL_S         50
+#define R_RISCV_RELAX           51
+#define R_RISCV_SUB6            52
+#define R_RISCV_SET6            53
+#define R_RISCV_SET8            54
+#define R_RISCV_SET16           55
+#define R_RISCV_SET32           56
+#define R_RISCV_32_PCREL        57
+
+
 #ifdef GRUB_TARGET_WORDSIZE
 #if GRUB_TARGET_WORDSIZE == 32
 
Index: grub-2.02/include/grub/riscv32/efi/memory.h
===================================================================
--- /dev/null
+++ grub-2.02/include/grub/riscv32/efi/memory.h
@@ -0,0 +1,6 @@
+#ifndef GRUB_MEMORY_CPU_HEADER
+#include <grub/efi/memory.h>
+
+#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffUL
+
+#endif /* ! GRUB_MEMORY_CPU_HEADER */
Index: grub-2.02/include/grub/riscv32/linux.h
===================================================================
--- /dev/null
+++ grub-2.02/include/grub/riscv32/linux.h
@@ -0,0 +1,45 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_RISCV64_LINUX_HEADER
+#define GRUB_RISCV64_LINUX_HEADER 1
+
+#include <grub/efi/efi.h>
+
+#define GRUB_LINUX_RISCV_MAGIC_SIGNATURE 0x52534356 /* 'RSCV' */
+
+/* From linux/Documentation/riscv/booting.txt */
+struct linux_riscv_kernel_header
+{
+  grub_uint32_t code0;		/* Executable code */
+  grub_uint32_t code1;		/* Executable code */
+  grub_uint64_t text_offset;    /* Image load offset */
+  grub_uint64_t res0;		/* reserved */
+  grub_uint64_t res1;		/* reserved */
+  grub_uint64_t res2;		/* reserved */
+  grub_uint64_t res3;		/* reserved */
+  grub_uint64_t res4;		/* reserved */
+  grub_uint32_t magic;		/* Magic number, little endian, "RSCV" */
+  grub_uint32_t hdr_offset;	/* Offset of PE/COFF header */
+};
+
+grub_err_t grub_riscv_uefi_check_image (struct linux_riscv_kernel_header *lh);
+grub_err_t grub_riscv_uefi_boot_image (grub_addr_t addr, grub_size_t size,
+                                       char *args);
+
+#endif /* ! GRUB_RISCV64_LINUX_HEADER */
Index: grub-2.02/include/grub/riscv32/setjmp.h
===================================================================
--- /dev/null
+++ grub-2.02/include/grub/riscv32/setjmp.h
@@ -0,0 +1,27 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_SETJMP_CPU_HEADER
+#define GRUB_SETJMP_CPU_HEADER	1
+
+typedef unsigned long long grub_jmp_buf[14];
+
+int grub_setjmp (grub_jmp_buf env) RETURNS_TWICE;
+void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn));
+
+#endif /* ! GRUB_SETJMP_CPU_HEADER */
Index: grub-2.02/include/grub/riscv32/time.h
===================================================================
--- /dev/null
+++ grub-2.02/include/grub/riscv32/time.h
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_CPU_TIME_HEADER
+#define KERNEL_CPU_TIME_HEADER	1
+
+static __inline void
+grub_cpu_idle (void)
+{
+  /* TODO */
+}
+
+#endif /* ! KERNEL_CPU_TIME_HEADER */
Index: grub-2.02/include/grub/riscv32/types.h
===================================================================
--- /dev/null
+++ grub-2.02/include/grub/riscv32/types.h
@@ -0,0 +1,34 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER	1
+
+/* The size of void *.  */
+#define GRUB_TARGET_SIZEOF_VOID_P	4
+
+/* The size of long.  */
+#define GRUB_TARGET_SIZEOF_LONG		4
+
+/* currently only support little-endian.  */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+/* Unaligned accesses can be very slow, so avoid them */
+#undef GRUB_HAVE_UNALIGNED_ACCESS
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
Index: grub-2.02/include/grub/riscv64/efi/memory.h
===================================================================
--- /dev/null
+++ grub-2.02/include/grub/riscv64/efi/memory.h
@@ -0,0 +1,6 @@
+#ifndef GRUB_MEMORY_CPU_HEADER
+#include <grub/efi/memory.h>
+
+#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffffffULL
+
+#endif /* ! GRUB_MEMORY_CPU_HEADER */
Index: grub-2.02/include/grub/riscv64/fdtload.h
===================================================================
--- /dev/null
+++ grub-2.02/include/grub/riscv64/fdtload.h
@@ -0,0 +1,35 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013-2015  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_FDTLOAD_CPU_HEADER
+#define GRUB_FDTLOAD_CPU_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+void *
+grub_fdt_load (grub_size_t additional_size);
+void
+grub_fdt_unload (void);
+grub_err_t
+grub_fdt_install (void);
+
+#define GRUB_EFI_PAGE_SHIFT	12
+#define GRUB_EFI_BYTES_TO_PAGES(bytes)   (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT)
+
+#endif
Index: grub-2.02/include/grub/riscv64/linux.h
===================================================================
--- /dev/null
+++ grub-2.02/include/grub/riscv64/linux.h
@@ -0,0 +1,47 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_RISCV64_LINUX_HEADER
+#define GRUB_RISCV64_LINUX_HEADER 1
+
+#include <grub/efi/efi.h>
+
+#define GRUB_LINUX_RISCV_MAGIC_SIGNATURE 0x52534356 /* 'RSCV' */
+
+#define GRUB_EFI_PE_MAGIC	0x5A4D
+
+/* From linux/Documentation/riscv/booting.txt */
+struct linux_riscv_kernel_header
+{
+  grub_uint32_t code0;		/* Executable code */
+  grub_uint32_t code1;		/* Executable code */
+  grub_uint64_t text_offset;    /* Image load offset */
+  grub_uint64_t res0;		/* reserved */
+  grub_uint64_t res1;		/* reserved */
+  grub_uint64_t res2;		/* reserved */
+  grub_uint64_t res3;		/* reserved */
+  grub_uint64_t res4;		/* reserved */
+  grub_uint32_t magic;		/* Magic number, little endian, "RSCV" */
+  grub_uint32_t hdr_offset;	/* Offset of PE/COFF header */
+};
+
+grub_err_t grub_riscv_uefi_check_image (struct linux_riscv_kernel_header *lh);
+grub_err_t grub_riscv_uefi_boot_image (grub_addr_t addr, grub_size_t size,
+                                       char *args);
+
+#endif /* ! GRUB_RISCV64_LINUX_HEADER */
Index: grub-2.02/include/grub/riscv64/setjmp.h
===================================================================
--- /dev/null
+++ grub-2.02/include/grub/riscv64/setjmp.h
@@ -0,0 +1,27 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_SETJMP_CPU_HEADER
+#define GRUB_SETJMP_CPU_HEADER	1
+
+typedef unsigned long long grub_jmp_buf[14];
+
+int grub_setjmp (grub_jmp_buf env) RETURNS_TWICE;
+void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn));
+
+#endif /* ! GRUB_SETJMP_CPU_HEADER */
Index: grub-2.02/include/grub/riscv64/time.h
===================================================================
--- /dev/null
+++ grub-2.02/include/grub/riscv64/time.h
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_CPU_TIME_HEADER
+#define KERNEL_CPU_TIME_HEADER	1
+
+static __inline void
+grub_cpu_idle (void)
+{
+  /* TODO */
+}
+
+#endif /* ! KERNEL_CPU_TIME_HEADER */
Index: grub-2.02/include/grub/riscv64/types.h
===================================================================
--- /dev/null
+++ grub-2.02/include/grub/riscv64/types.h
@@ -0,0 +1,34 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 <http://www.gnu.org/licenses/>.
+ */
+
+#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
+
+/* currently only support little-endian.  */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+/* Unaligned accesses can be very slow, so avoid them */
+#undef GRUB_HAVE_UNALIGNED_ACCESS
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
Index: grub-2.02/include/grub/util/install.h
===================================================================
--- grub-2.02.orig/include/grub/util/install.h
+++ grub-2.02/include/grub/util/install.h
@@ -100,6 +100,8 @@ enum grub_install_plat
     GRUB_INSTALL_PLATFORM_X86_64_XEN,
     GRUB_INSTALL_PLATFORM_ARM64_EFI,
     GRUB_INSTALL_PLATFORM_S390X_EMU,
+    GRUB_INSTALL_PLATFORM_RISCV32_EFI,
+    GRUB_INSTALL_PLATFORM_RISCV64_EFI,
     GRUB_INSTALL_PLATFORM_MAX
   };
 
Index: grub-2.02/util/grub-install-common.c
===================================================================
--- grub-2.02.orig/util/grub-install-common.c
+++ grub-2.02/util/grub-install-common.c
@@ -667,6 +667,8 @@ static struct
     [GRUB_INSTALL_PLATFORM_ARM64_EFI] =        { "arm64",   "efi"       },
     [GRUB_INSTALL_PLATFORM_ARM_UBOOT] =        { "arm",     "uboot"     },
     [GRUB_INSTALL_PLATFORM_S390X_EMU] =        { "s390x",   "emu"       },
+    [GRUB_INSTALL_PLATFORM_RISCV32_EFI] =      { "riscv32", "efi"       },
+    [GRUB_INSTALL_PLATFORM_RISCV64_EFI] =      { "riscv64", "efi"       },
   }; 
 
 char *
Index: grub-2.02/util/grub-install.c
===================================================================
--- grub-2.02.orig/util/grub-install.c
+++ grub-2.02/util/grub-install.c
@@ -366,6 +366,14 @@ get_default_platform (void)
    return grub_install_get_default_x86_platform ();
 #elif defined (__s390x__)
    return "s390x-emu";
+#elif defined (__riscv)
+#if __riscv_xlen == 32
+   return "riscv32-efi";
+#elif __riscv_xlen == 64
+   return "riscv64-efi";
+#else
+   return NULL;
+#endif
 #else
    return NULL;
 #endif
@@ -535,6 +543,8 @@ have_bootdev (enum grub_install_plat pl)
     case GRUB_INSTALL_PLATFORM_IA64_EFI:
     case GRUB_INSTALL_PLATFORM_ARM_EFI:
     case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
     case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
     case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
     case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
@@ -935,6 +945,8 @@ main (int argc, char *argv[])
     case GRUB_INSTALL_PLATFORM_X86_64_EFI:
     case GRUB_INSTALL_PLATFORM_ARM_EFI:
     case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
     case GRUB_INSTALL_PLATFORM_IA64_EFI:
     case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
     case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
@@ -979,6 +991,8 @@ main (int argc, char *argv[])
     case GRUB_INSTALL_PLATFORM_X86_64_EFI:
     case GRUB_INSTALL_PLATFORM_ARM_EFI:
     case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
     case GRUB_INSTALL_PLATFORM_IA64_EFI:
     case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
     case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
@@ -1031,6 +1045,8 @@ main (int argc, char *argv[])
     case GRUB_INSTALL_PLATFORM_X86_64_EFI:
     case GRUB_INSTALL_PLATFORM_ARM_EFI:
     case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
     case GRUB_INSTALL_PLATFORM_IA64_EFI:
       is_efi = 1;
       break;
@@ -1144,6 +1160,12 @@ main (int argc, char *argv[])
 	    case GRUB_INSTALL_PLATFORM_ARM64_EFI:
 	      efi_file = "BOOTAA64.EFI";
 	      break;
+	    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+	      efi_file = "BOOTRISCV32.EFI";
+	      break;
+	    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
+	      efi_file = "BOOTRISCV64.EFI";
+	      break;
 	    default:
 	      grub_util_error ("%s", _("You've found a bug"));
 	      break;
@@ -1171,6 +1193,12 @@ main (int argc, char *argv[])
 	    case GRUB_INSTALL_PLATFORM_ARM64_EFI:
 	      efi_file = "grubaa64.efi";
 	      break;
+	    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+	      efi_file = "grubriscv32.efi";
+	      break;
+	    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
+	      efi_file = "grubriscv64.efi";
+	      break;
 	    default:
 	      efi_file = "grub.efi";
 	      break;
@@ -1500,6 +1528,8 @@ main (int argc, char *argv[])
 		  case GRUB_INSTALL_PLATFORM_X86_64_EFI:
 		  case GRUB_INSTALL_PLATFORM_ARM_EFI:
 		  case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+		  case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+		  case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
 		  case GRUB_INSTALL_PLATFORM_IA64_EFI:
 		    g = grub_util_guess_efi_drive (*curdev);
 		    break;
@@ -1664,6 +1694,8 @@ main (int argc, char *argv[])
     case GRUB_INSTALL_PLATFORM_X86_64_EFI:
     case GRUB_INSTALL_PLATFORM_I386_EFI:
     case GRUB_INSTALL_PLATFORM_ARM_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
     case GRUB_INSTALL_PLATFORM_IA64_EFI:
       core_name = "core.efi";
       snprintf (mkimage_target, sizeof (mkimage_target),
@@ -1846,6 +1878,8 @@ main (int argc, char *argv[])
 
     case GRUB_INSTALL_PLATFORM_ARM_EFI:
     case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
     case GRUB_INSTALL_PLATFORM_IA64_EFI:
     case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
     case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
@@ -2068,6 +2102,8 @@ main (int argc, char *argv[])
       /* FALLTHROUGH */
     case GRUB_INSTALL_PLATFORM_ARM_EFI:
     case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
     case GRUB_INSTALL_PLATFORM_IA64_EFI:
       {
 	char *dst = grub_util_path_concat (2, efidir, efi_file);
Index: grub-2.02/util/grub-mkimagexx.c
===================================================================
--- grub-2.02.orig/util/grub-mkimagexx.c
+++ grub-2.02/util/grub-mkimagexx.c
@@ -1156,6 +1156,174 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e
 		 break;
 	       }
 #endif /* MKIMAGE_ELF32 */
+	     case EM_RISCV:
+	       {
+		 grub_uint64_t *t64 = (grub_uint64_t *) target;
+		 grub_uint32_t *t32 = (grub_uint32_t *) target;
+		 grub_uint16_t *t16 = (grub_uint16_t *) target;
+		 grub_int64_t off;
+
+		 sym_addr += addend;
+		 off = sym_addr - target_section_addr - offset - image_target->vaddr_offset;
+
+		 switch (ELF_R_TYPE (info))
+		   {
+		   case R_RISCV_32:
+		     {
+		       *t32 = grub_host_to_target32 (grub_target_to_host32 (*t32) + sym_addr);
+		     }
+		     break;
+		   case R_RISCV_64:
+		     {
+		       *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) + sym_addr);
+		     }
+		     break;
+		   case R_RISCV_BRANCH:
+		     {
+		       grub_uint32_t imm12 = (off & 0x1000) << (31 - 12);
+		       grub_uint32_t imm11 = (off & 0x800) >> (11 - 7);
+		       grub_uint32_t imm10_5 = (off & 0x7e0) << (30 - 10);
+		       grub_uint32_t imm4_1 = (off & 0x1e) << (11 - 4);
+		       *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f)
+						     | imm12 | imm11 | imm10_5 | imm4_1);
+		     }
+		     break;
+		   case R_RISCV_JAL:
+		     {
+		       grub_uint32_t imm20 = (off & 0x100000) << (31 - 20);
+		       grub_uint32_t imm19_12 = (off & 0xff000);
+		       grub_uint32_t imm11 = (off & 0x800) << (20 - 11);
+		       grub_uint32_t imm10_1 = (off & 0x7fe) << (30 - 10);
+		       *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff)
+						     | imm20 | imm19_12 | imm11 | imm10_1);
+		     }
+		     break;
+		   case R_RISCV_CALL:
+		     {
+		       grub_uint32_t hi20, lo12;
+
+		       if (off != (grub_int32_t)off)
+			 grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr, (long)target);
+
+		       hi20 = (off + 0x800) & 0xfffff000;
+		       lo12 = (off - hi20) & 0xfff;
+		       t32[0] = grub_host_to_target32 ((grub_target_to_host32 (t32[0]) & 0xfff) | hi20);
+		       t32[1] = grub_host_to_target32 ((grub_target_to_host32 (t32[1]) & 0xfffff) | (lo12 << 20));
+		     }
+		     break;
+		   case R_RISCV_RVC_BRANCH:
+		     {
+		       grub_uint16_t imm8 = (off & 0x100) << (12 - 8);
+		       grub_uint16_t imm7_6 = (off & 0xc0) >> (6 - 5);
+		       grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
+		       grub_uint16_t imm4_3 = (off & 0x18) << (12 - 5);
+		       grub_uint16_t imm2_1 = (off & 0x6) << (12 - 10);
+		       *t16 = grub_host_to_target16 ((grub_target_to_host16 (*t16) & 0xe383)
+						     | imm8 | imm7_6 | imm5 | imm4_3 | imm2_1);
+		     }
+		     break;
+		   case R_RISCV_RVC_JUMP:
+		     {
+		       grub_uint16_t imm11 = (off & 0x800) << (12 - 11);
+		       grub_uint16_t imm10 = (off & 0x400) >> (10 - 8);
+		       grub_uint16_t imm9_8 = (off & 0x300) << (12 - 11);
+		       grub_uint16_t imm7 = (off & 0x80) >> (7 - 6);
+		       grub_uint16_t imm6 = (off & 0x40) << (12 - 11);
+		       grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
+		       grub_uint16_t imm4 = (off & 0x10) << (12 - 5);
+		       grub_uint16_t imm3_1 = (off & 0xe) << (12 - 10);
+		       *t16 = grub_host_to_target16 ((grub_target_to_host16 (*t16) & 0xe003)
+						     | imm11 | imm10 | imm9_8 | imm7 | imm6
+						     | imm5 | imm4 | imm3_1);
+		     }
+		     break;
+		   case R_RISCV_PCREL_HI20:
+		     {
+		       grub_int32_t hi20;
+
+		       if (off != (grub_uint32_t)off)
+			 grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr, (long)target);
+
+		       hi20 = (off + 0x800) & 0xfffff000;
+		       *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff) | hi20);
+		     }
+		     break;
+		   case R_RISCV_PCREL_LO12_I:
+		   case R_RISCV_PCREL_LO12_S:
+		     {
+		       Elf_Rela *rel2;
+		       Elf_Word k;
+		       /* Search backwards for matching HI20 reloc.  */
+		       for (k = j, rel2 = (Elf_Rela *) ((char *) r - r_size);
+			    k > 0;
+			    k--, rel2 = (Elf_Rela *) ((char *) rel2 - r_size))
+			 {
+			   Elf_Addr rel2_info;
+			   Elf_Addr rel2_offset;
+			   Elf_Addr rel2_sym_addr;
+			   Elf_Addr *rel2_target;
+			   Elf_Addr rel2_addend;
+			   Elf_Addr rel2_loc;
+			   grub_int64_t rel2_off;
+
+			   rel2_offset = grub_target_to_host (rel2->r_offset);
+			   rel2_info = grub_target_to_host (rel2->r_info);
+			   rel2_loc = target_section_addr + rel2_offset + image_target->vaddr_offset;
+
+			   if (ELF_R_TYPE (rel2_info) == R_RISCV_PCREL_HI20
+			       && rel2_loc == sym_addr)
+			     {
+			       rel2_sym_addr = SUFFIX (get_symbol_address)
+				 (e, symtab_section, ELF_R_SYM (rel2_info),
+				  image_target);
+			       rel2_target = SUFFIX (get_target_address)
+				 (e, target_section, rel2_offset, image_target);
+			       rel2_addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
+				 grub_target_to_host (rel2->r_addend) : 0;
+			       rel2_off = rel2_sym_addr + rel2_addend - rel2_loc;
+			       off = rel2_off - ((rel2_off + 0x800) & 0xfffff000);
+
+			       if (ELF_R_TYPE (info) == R_RISCV_PCREL_LO12_I)
+				 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfffff) | (off & 0xfff) << 20);
+			       else
+				 {
+				   grub_uint32_t imm11_5 = (off & 0xfe0) << (31 - 11);
+				   grub_uint32_t imm4_0 = (off & 0x1f) << (11 - 4);
+				   *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f) | imm11_5 | imm4_0);
+				 }
+			       break;
+			     }
+			 }
+		       if (k == 0)
+			 grub_util_error ("cannot find matching HI20 relocation");
+		     }
+		     break;
+		   case R_RISCV_HI20:
+		     *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff) | (((grub_int32_t) sym_addr + 0x800) & 0xfffff000));
+		     break;
+		   case R_RISCV_LO12_I:
+		     {
+		       grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
+		       *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfffff) | ((lo12 & 0xfff) << 20));
+		     }
+		     break;
+		   case R_RISCV_LO12_S:
+		     {
+		       grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
+		       grub_uint32_t imm11_5 = (lo12 & 0xfe0) << (31 - 11);
+		       grub_uint32_t imm4_0 = (lo12 & 0x1f) << (11 - 4);
+		       *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f) | imm11_5 | imm4_0);
+		     }
+		     break;
+		   case R_RISCV_RELAX:
+		     break;
+		   default:
+		     grub_util_error (_("relocation 0x%x is not implemented yet"),
+				      (unsigned int) ELF_R_TYPE (info));
+		     break;
+		   }
+	       break;
+	       }
 	     default:
 	       grub_util_error ("unknown architecture type %d",
 				image_target->elf_target);
@@ -1440,6 +1608,73 @@ translate_relocation_pe (struct translat
 	}
       break;
 #endif /* defined(MKIMAGE_ELF32) */
+    case EM_RISCV:
+      switch (ELF_R_TYPE (info))
+	{
+	case R_RISCV_32:
+	  {
+	    ctx->current_address
+	      = add_fixup_entry (&ctx->lst,
+				 GRUB_PE32_REL_BASED_HIGHLOW,
+				 addr, 0, ctx->current_address,
+				 image_target);
+	  }
+	  break;
+	case R_RISCV_64:
+	  {
+	    ctx->current_address
+	      = add_fixup_entry (&ctx->lst,
+				 GRUB_PE32_REL_BASED_DIR64,
+				 addr, 0, ctx->current_address,
+				 image_target);
+	  }
+	  break;
+	  /* Relative relocations do not require fixup entries. */
+	case R_RISCV_BRANCH:
+	case R_RISCV_JAL:
+	case R_RISCV_CALL:
+	case R_RISCV_PCREL_HI20:
+	case R_RISCV_PCREL_LO12_I:
+	case R_RISCV_PCREL_LO12_S:
+	case R_RISCV_RVC_BRANCH:
+	case R_RISCV_RVC_JUMP:
+	  grub_util_info ("  %s:  not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
+	  break;
+	case R_RISCV_HI20:
+	  {
+	    ctx->current_address
+	      = add_fixup_entry (&ctx->lst,
+				 GRUB_PE32_REL_BASED_RISCV_HI20,
+				 addr, 0, ctx->current_address,
+				 image_target);
+	  }
+	  break;
+	case R_RISCV_LO12_I:
+	  {
+	    ctx->current_address
+	      = add_fixup_entry (&ctx->lst,
+				 GRUB_PE32_REL_BASED_RISCV_LOW12I,
+				 addr, 0, ctx->current_address,
+				 image_target);
+	  }
+	  break;
+	case R_RISCV_LO12_S:
+	  {
+	    ctx->current_address
+	      = add_fixup_entry (&ctx->lst,
+				 GRUB_PE32_REL_BASED_RISCV_LOW12S,
+				 addr, 0, ctx->current_address,
+				 image_target);
+	  }
+	  break;
+	case R_RISCV_RELAX:
+	  break;
+	default:
+	  grub_util_error (_("relocation 0x%x is not implemented yet"),
+			   (unsigned int) ELF_R_TYPE (info));
+	  break;
+	}
+      break;
     default:
       grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
     }
Index: grub-2.02/util/grub-mknetdir.c
===================================================================
--- grub-2.02.orig/util/grub-mknetdir.c
+++ grub-2.02/util/grub-mknetdir.c
@@ -112,7 +112,9 @@ static struct
     [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64-efi", "efinet", ".efi" },
     [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64-efi", "efinet", ".efi" },
     [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm-efi", "efinet", ".efi" },
-    [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64-efi", "efinet", ".efi" }
+    [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64-efi", "efinet", ".efi" },
+    [GRUB_INSTALL_PLATFORM_RISCV32_EFI] = { "riscv32-efi", "efinet", ".efi" },
+    [GRUB_INSTALL_PLATFORM_RISCV64_EFI] = { "riscv64-efi", "efinet", ".efi" },
   };
 
 static void
Index: grub-2.02/util/grub-mkrescue.c
===================================================================
--- grub-2.02.orig/util/grub-mkrescue.c
+++ grub-2.02/util/grub-mkrescue.c
@@ -530,6 +530,8 @@ main (int argc, char *argv[])
 	  || source_dirs[GRUB_INSTALL_PLATFORM_IA64_EFI]
 	  || source_dirs[GRUB_INSTALL_PLATFORM_ARM_EFI]
 	  || source_dirs[GRUB_INSTALL_PLATFORM_ARM64_EFI]
+	  || source_dirs[GRUB_INSTALL_PLATFORM_RISCV32_EFI]
+	  || source_dirs[GRUB_INSTALL_PLATFORM_RISCV64_EFI]
 	  || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI])
 	system_area = SYS_AREA_COMMON;
       else if (source_dirs[GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275])
@@ -727,7 +729,9 @@ main (int argc, char *argv[])
       || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI]
       || source_dirs[GRUB_INSTALL_PLATFORM_IA64_EFI]
       || source_dirs[GRUB_INSTALL_PLATFORM_ARM_EFI]
-      || source_dirs[GRUB_INSTALL_PLATFORM_ARM64_EFI])
+      || source_dirs[GRUB_INSTALL_PLATFORM_ARM64_EFI]
+      || source_dirs[GRUB_INSTALL_PLATFORM_RISCV32_EFI]
+      || source_dirs[GRUB_INSTALL_PLATFORM_RISCV64_EFI])
     {
       char *efidir = grub_util_make_temporary_dir ();
       char *efidir_efi = grub_util_path_concat (2, efidir, "efi");
@@ -762,6 +766,16 @@ main (int argc, char *argv[])
 			     imgname);
       free (imgname);
 
+      imgname = grub_util_path_concat (2, efidir_efi_boot, "bootriscv32.efi");
+      make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_RISCV32_EFI, "riscv32-efi",
+			     imgname);
+      free (imgname);
+
+      imgname = grub_util_path_concat (2, efidir_efi_boot, "bootriscv64.efi");
+      make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_RISCV64_EFI, "riscv64-efi",
+			     imgname);
+      free (imgname);
+
       if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI])
 	{
 	  imgname = grub_util_path_concat (2, efidir_efi_boot, "boot.efi");
Index: grub-2.02/util/grub-module-verifier.c
===================================================================
--- grub-2.02.orig/util/grub-module-verifier.c
+++ grub-2.02/util/grub-module-verifier.c
@@ -117,6 +117,34 @@ struct grub_module_verifier_arch archs[]
       R_AARCH64_LDST64_ABS_LO12_NC,
       R_AARCH64_PREL32,
       -1
+    } },
+  { "riscv32", 4, 0, EM_RISCV, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
+      R_RISCV_32,
+      R_RISCV_64,
+      R_RISCV_RELATIVE,
+      -1 // XXX
+    } },
+  { "riscv64", 8, 0, EM_RISCV, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
+      R_RISCV_32,
+      R_RISCV_64,
+      R_RISCV_ADD32,
+      R_RISCV_ALIGN,
+      R_RISCV_BRANCH,
+      R_RISCV_CALL,
+      R_RISCV_CALL_PLT,
+      R_RISCV_GOT_HI20,
+      R_RISCV_HI20,
+      R_RISCV_JAL,
+      R_RISCV_LO12_I,
+      R_RISCV_LO12_S,
+      R_RISCV_PCREL_HI20,
+      R_RISCV_PCREL_LO12_I,
+      R_RISCV_PCREL_LO12_S,
+      R_RISCV_RELAX,
+      R_RISCV_RVC_BRANCH,
+      R_RISCV_RVC_JUMP,
+      R_RISCV_SUB32,
+      -1
     }
   },
 };
Index: grub-2.02/util/mkimage.c
===================================================================
--- grub-2.02.orig/util/mkimage.c
+++ grub-2.02/util/mkimage.c
@@ -586,6 +586,38 @@ static const struct grub_install_image_t
       .pe_target = GRUB_PE32_MACHINE_ARM64,
       .elf_target = EM_AARCH64,
     },
+    {
+      .dirname = "riscv32-efi",
+      .names = { "riscv32-efi", NULL },
+      .voidp_sizeof = 4,
+      .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 = EFI32_HEADER_SIZE,
+      .pe_target = GRUB_PE32_MACHINE_RISCV32,
+      .elf_target = EM_RISCV,
+    },
+    {
+      .dirname = "riscv64-efi",
+      .names = { "riscv64-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_RISCV64,
+      .elf_target = EM_RISCV,
+    },
   };
 
 #include <grub/lib/LzmaEnc.h>