[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2] mips64: Add support for 64-bit MIPS.
From: |
wangr |
Subject: |
[PATCH v2] mips64: Add support for 64-bit MIPS. |
Date: |
Mon, 13 Feb 2017 23:57:50 +0800 |
From: Heiher <address@hidden>
---
configure.ac | 21 ++-
gentpl.py | 5 +-
grub-core/Makefile.am | 6 +
grub-core/Makefile.core.def | 13 ++
grub-core/kern/mips64/cache.S | 23 ++++
grub-core/kern/mips64/dl.c | 150 +++++++++++++++++++++
grub-core/kern/mips64/efi/init.c | 44 ++++++
grub-core/kern/mips64/efi/startup.S | 47 +++++++
grub-core/kern/mips64/init.c | 47 +++++++
grub-core/lib/efi/halt.c | 2 +-
grub-core/lib/mips64/setjmp.S | 69 ++++++++++
grub-core/lib/setjmp.S | 4 +
grub-core/term/serial.c | 8 +-
include/grub/cache.h | 2 +-
include/grub/dl.h | 8 +-
include/grub/efi/api.h | 2 +-
include/grub/efi/pe32.h | 5 +
include/grub/mips64/asm.h | 10 ++
include/grub/mips64/efi/boot.h | 0
include/grub/mips64/efi/loader.h | 25 ++++
include/grub/mips64/efi/memory.h | 6 +
include/grub/mips64/efi/time.h | 0
include/grub/mips64/io.h | 62 +++++++++
include/grub/mips64/kernel.h | 24 ++++
include/grub/mips64/memory.h | 56 ++++++++
include/grub/mips64/mips.h | 30 +++++
include/grub/mips64/setjmp.h | 27 ++++
include/grub/mips64/time.h | 39 ++++++
include/grub/mips64/types.h | 38 ++++++
include/grub/misc.h | 2 +-
include/grub/serial.h | 6 +-
include/grub/util/install.h | 1 +
util/grub-install-common.c | 1 +
util/grub-install.c | 18 +++
util/grub-mkimagexx.c | 259 ++++++++++++++++++++++++++++++++++--
util/grub-mknetdir.c | 3 +-
util/grub-mkrescue.c | 9 +-
util/grub-module-verifier.c | 13 ++
util/grub-module-verifierXX.c | 11 +-
util/mkimage.c | 16 +++
40 files changed, 1078 insertions(+), 34 deletions(-)
create mode 100644 grub-core/kern/mips64/cache.S
create mode 100644 grub-core/kern/mips64/dl.c
create mode 100644 grub-core/kern/mips64/efi/init.c
create mode 100644 grub-core/kern/mips64/efi/startup.S
create mode 100644 grub-core/kern/mips64/init.c
create mode 100644 grub-core/lib/mips64/setjmp.S
create mode 100644 include/grub/mips64/asm.h
create mode 100644 include/grub/mips64/efi/boot.h
create mode 100644 include/grub/mips64/efi/loader.h
create mode 100644 include/grub/mips64/efi/memory.h
create mode 100644 include/grub/mips64/efi/time.h
create mode 100644 include/grub/mips64/io.h
create mode 100644 include/grub/mips64/kernel.h
create mode 100644 include/grub/mips64/memory.h
create mode 100644 include/grub/mips64/mips.h
create mode 100644 include/grub/mips64/setjmp.h
create mode 100644 include/grub/mips64/time.h
create mode 100644 include/grub/mips64/types.h
diff --git a/configure.ac b/configure.ac
index 0893ad60c..fa017bc37 100644
--- a/configure.ac
+++ b/configure.ac
@@ -86,7 +86,11 @@ case "$target_cpu" in
i[[3456]]86) target_cpu=i386 ;;
amd64) target_cpu=x86_64 ;;
sparc) target_cpu=sparc64 ;;
- mipsel|mips64el)
+ mips64el)
+ target_cpu=mips64el
+ machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPS64EL=1"
+ ;;
+ mipsel)
target_cpu=mipsel
machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPSEL=1"
;;
@@ -118,6 +122,7 @@ if test "x$with_platform" = x; then
powerpc64-*) platform=ieee1275 ;;
powerpc64le-*) platform=ieee1275 ;;
sparc64-*) platform=ieee1275 ;;
+ mips64el-*) platform=efi;;
mipsel-*) platform=loongson ;;
mips-*) platform=arc ;;
ia64-*) platform=efi ;;
@@ -166,6 +171,7 @@ case "$target_cpu"-"$platform" in
mipsel-yeeloong) platform=loongson ;;
mipsel-fuloong) platform=loongson ;;
mipsel-loongson) ;;
+ mips64el-efi) ;;
arm-uboot) ;;
arm-efi) ;;
arm64-efi) ;;
@@ -1234,10 +1240,15 @@ grub_CHECK_PIC
# movk's which aren't representable.
# Since default varies across dictributions use either -fPIC or -fno-PIC
# explicitly.
-if ( test x$target_cpu = xmips || test x$target_cpu = xmipsel || test
x$target_cpu = xarm64 ) && test "x$grub_cv_cc_target_clang" = xyes ; then
+if ( test x$target_cpu = xmips || test x$target_cpu = xmipsel || test
x$target_cpu = xarm64 || test x$target_cpu = xmips64el ) && test
"x$grub_cv_cc_target_clang" = xyes ; then
TARGET_CFLAGS="$TARGET_CFLAGS -fPIC"
elif [ x"$pic_possible" = xyes ]; then
TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIC"
+fi
+# Don't generate SVR4-style position-independent code for MIPS64.
+if test x$target_cpu = xmips64el ; then
+ TARGET_CFLAGS="$TARGET_CFLAGS -mno-abicalls"
+ TARGET_CCASFLAGS="$TARGET_CCASFLAGS -mno-abicalls"
fi]
CFLAGS="$TARGET_CFLAGS"
@@ -1894,12 +1905,14 @@ AM_CONDITIONAL([COND_i386_multiboot], [test
x$target_cpu = xi386 -a x$platform =
AM_CONDITIONAL([COND_x86_64_efi], [test x$target_cpu = xx86_64 -a x$platform =
xefi])
AM_CONDITIONAL([COND_i386_xen], [test x$target_cpu = xi386 -a x$platform =
xxen])
AM_CONDITIONAL([COND_x86_64_xen], [test x$target_cpu = xx86_64 -a x$platform =
xxen])
+AM_CONDITIONAL([COND_mips64_efi], [test x$target_cpu = xmips64el -a x$platform
= xefi])
AM_CONDITIONAL([COND_mips_loongson], [test x$target_cpu = xmipsel -a
x$platform = xloongson])
AM_CONDITIONAL([COND_mips_qemu_mips], [test "(" x$target_cpu = xmips -o
x$target_cpu = xmipsel ")" -a x$platform = xqemu_mips])
AM_CONDITIONAL([COND_mips_arc], [test "(" x$target_cpu = xmips -o x$target_cpu
= xmipsel ")" -a x$platform = xarc])
AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a
x$platform = xieee1275])
AM_CONDITIONAL([COND_sparc64_emu], [test x$target_cpu = xsparc64 -a x$platform
= xemu])
AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a
x$platform = xieee1275])
+AM_CONDITIONAL([COND_mips64el], [test x$target_cpu = xmips64el])
AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips -o x$target_cpu =
xmipsel])
AM_CONDITIONAL([COND_mipsel], [test x$target_cpu = xmipsel])
AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips])
@@ -1956,7 +1969,9 @@ AC_DEFINE_UNQUOTED(GRUB_SYSCONFDIR, "$grub_sysconfdir",
[Configuration dir])
# Output files.
if test "$platform" != none; then
cpudir="${target_cpu}"
- if test x${cpudir} = xmipsel; then
+ if test x${cpudir} = xmips64el; then
+ cpudir=mips64;
+ elif test x${cpudir} = xmipsel; then
cpudir=mips;
fi
grub_CHECK_LINK_DIR
diff --git a/gentpl.py b/gentpl.py
index f08bcc404..e9ec540ca 100644
--- a/gentpl.py
+++ b/gentpl.py
@@ -29,7 +29,7 @@ import re
GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot",
"i386_multiboot", "i386_ieee1275", "x86_64_efi",
"i386_xen", "x86_64_xen",
- "mips_loongson", "sparc64_ieee1275",
+ "mips_loongson", "mips64_efi", "sparc64_ieee1275",
"powerpc_ieee1275", "mips_arc", "ia64_efi",
"mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi" ]
@@ -42,13 +42,14 @@ GROUPS["i386"] = [ "i386_pc", "i386_efi", "i386_qemu",
"i386_coreboot", "i38
GROUPS["x86_64"] = [ "x86_64_efi" ]
GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"]
GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ]
+GROUPS["mips64"] = [ "mips64_efi" ]
GROUPS["sparc64"] = [ "sparc64_ieee1275" ]
GROUPS["powerpc"] = [ "powerpc_ieee1275" ]
GROUPS["arm"] = [ "arm_uboot", "arm_efi" ]
GROUPS["arm64"] = [ "arm64_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", "mips64_efi" ]
GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275",
"powerpc_ieee1275" ]
GROUPS["uboot"] = [ "arm_uboot" ]
GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ]
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 04e9395fd..5512f274f 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -216,6 +216,12 @@ KERNEL_HEADER_FILES +=
$(top_builddir)/include/grub/machine/memory.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
endif
+if COND_mips64_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_powerpc_ieee1275
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 2dfa22a92..e23782c1f 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -93,6 +93,9 @@ kernel = {
arm_uboot_ldflags = '-Wl,-r,-d';
arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R
.note.gnu.gold-version';
+ mips64_efi_ldflags = '-Wl,-r,-d';
+ mips64_efi_stripflags = '--strip-unneeded -K start -R .note -R
.comment -R .note.gnu.gold-version -R .eh_frame -R .MIPS.abiflags';
+
i386_pc_startup = kern/i386/pc/startup.S;
i386_efi_startup = kern/i386/efi/startup.S;
x86_64_efi_startup = kern/x86_64/efi/startup.S;
@@ -103,6 +106,7 @@ kernel = {
i386_coreboot_startup = kern/i386/coreboot/startup.S;
i386_multiboot_startup = kern/i386/coreboot/startup.S;
mips_startup = kern/mips/startup.S;
+ mips64_efi_startup = kern/mips64/efi/startup.S;
sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S;
powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S;
arm_uboot_startup = kern/arm/uboot/startup.S;
@@ -263,6 +267,12 @@ kernel = {
extra_dist = video/sis315_init.c;
mips_loongson = commands/keylayouts.c;
+ mips64 = kern/mips64/init.c;
+ mips64 = kern/mips64/dl.c;
+ mips64 = kern/mips64/cache.S;
+ mips64 = kern/generic/rtc_get_time_ms.c;
+ mips64_efi = kern/mips64/efi/init.c;
+
powerpc_ieee1275 = kern/powerpc/cache.S;
powerpc_ieee1275 = kern/powerpc/dl.c;
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
@@ -750,6 +760,7 @@ module = {
enable = sparc64_ieee1275;
enable = powerpc_ieee1275;
enable = mips_arc;
+ enable = mips64_efi;
enable = ia64_efi;
enable = arm_efi;
enable = arm64_efi;
@@ -853,6 +864,7 @@ module = {
mips_arc = lib/mips/arc/reboot.c;
mips_loongson = lib/mips/loongson/reboot.c;
mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
+ mips64_efi = lib/efi/reboot.c;
xen = lib/xen/reboot.c;
uboot = lib/uboot/reboot.c;
common = commands/reboot.c;
@@ -1762,6 +1774,7 @@ module = {
enable = arm_efi;
enable = arm64_efi;
enable = mips;
+ enable = mips64_efi;
};
module = {
diff --git a/grub-core/kern/mips64/cache.S b/grub-core/kern/mips64/cache.S
new file mode 100644
index 000000000..c1fb4d44a
--- /dev/null
+++ b/grub-core/kern/mips64/cache.S
@@ -0,0 +1,23 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009,2017 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>
+
+FUNCTION (grub_arch_sync_caches)
+ jr.hb $ra
+
diff --git a/grub-core/kern/mips64/dl.c b/grub-core/kern/mips64/dl.c
new file mode 100644
index 000000000..7c6a0833b
--- /dev/null
+++ b/grub-core/kern/mips64/dl.c
@@ -0,0 +1,150 @@
+/* dl-mips64.c - arch-dependent part of loadable module support */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2005,2007,2009,2017 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/cpu/types.h>
+#include <grub/mm.h>
+#include <grub/i18n.h>
+
+/* 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. */
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ if (e->e_ident[EI_CLASS] != ELFCLASS64
+ || e->e_ident[EI_DATA] != ELFDATA2MSB
+ || e->e_machine != EM_MIPS)
+#else
+ if (e->e_ident[EI_CLASS] != ELFCLASS64
+ || e->e_ident[EI_DATA] != ELFDATA2LSB
+ || e->e_machine != EM_MIPS)
+#endif
+ return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF
magic"));
+
+ return GRUB_ERR_NONE;
+}
+
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+grub_err_t
+grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)),
+ grub_size_t *tramp, grub_size_t *got)
+{
+ *tramp = 0;
+ *got = 0;
+ return GRUB_ERR_NONE;
+}
+
+/* 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_Ehdr *e = ehdr;
+ Elf_Rel *rel, *max;
+
+ for (rel = (Elf_Rel *) ((char *) e + s->sh_offset),
+ max = (Elf_Rel *) ((char *) rel + s->sh_size);
+ rel < max;
+ rel = (Elf_Rel *) ((char *) rel + s->sh_entsize))
+ {
+ grub_uint8_t *addr;
+ Elf_Sym *sym;
+ Elf_Addr r_info;
+ grub_uint64_t sym_value;
+
+ if (seg->size < rel->r_offset)
+ return grub_error (GRUB_ERR_BAD_MODULE,
+ "reloc offset is out of the segment");
+
+ r_info = ((grub_uint64_t) rel->r_info << 32) |
+ (grub_uint32_t) grub_be_to_cpu64 (rel->r_info);
+
+ addr = (grub_uint8_t *) ((char *) seg->addr + rel->r_offset);
+ sym = (Elf_Sym *) ((char *) mod->symtab
+ + mod->symsize * ELF_R_SYM (r_info));
+ sym_value = sym->st_value;
+ if (s->sh_type == SHT_RELA)
+ {
+ sym_value += ((Elf_Rela *) rel)->r_addend;
+ }
+ switch (ELF_R_TYPE (r_info))
+ {
+ case R_MIPS_64:
+ *(grub_uint64_t *) addr += sym_value;
+ break;
+ case R_MIPS_32:
+ *(grub_uint32_t *) addr += sym_value;
+ break;
+ case R_MIPS_26:
+ {
+ grub_uint32_t value;
+ grub_uint32_t raw;
+ raw = (*(grub_uint32_t *) addr) & 0x3ffffff;
+ value = raw << 2;
+ value += sym_value;
+ raw = (value >> 2) & 0x3ffffff;
+
+ *(grub_uint32_t *) addr =
+ raw | ((*(grub_uint32_t *) addr) & 0xfc000000);
+ }
+ break;
+ case R_MIPS_LO16:
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ addr += 2;
+#endif
+ *(grub_uint16_t *) addr = (grub_int16_t) sym_value;
+ break;
+ case R_MIPS_HI16:
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ addr += 2;
+#endif
+ *(grub_uint16_t *) addr = (grub_int16_t) ((sym_value + 0x8000UL) >>
16);
+ break;
+ case R_MIPS_HIGHER:
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ addr += 2;
+#endif
+ *(grub_uint16_t *) addr = (grub_int16_t) ((sym_value + 0x80008000UL)
>> 32);
+ break;
+ case R_MIPS_HIGHEST:
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ addr += 2;
+#endif
+ *(grub_uint16_t *) addr = (grub_uint16_t) ((sym_value +
0x800080008000UL) >> 48);
+ break;
+ default:
+ {
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ N_("relocation 0x%x is not implemented yet"),
+ ELF_R_TYPE (r_info));
+ }
+ break;
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
diff --git a/grub-core/kern/mips64/efi/init.c b/grub-core/kern/mips64/efi/init.c
new file mode 100644
index 000000000..074736db9
--- /dev/null
+++ b/grub-core/kern/mips64/efi/init.c
@@ -0,0 +1,44 @@
+/* init.c - initialize an arm-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/cpu/time.h>
+#include <grub/efi/efi.h>
+#include <grub/loader.h>
+
+void
+grub_machine_init (void)
+{
+ grub_efi_init ();
+
+ /* FIXME: Get cpuclock from EFI. */
+ grub_timer_init (1000000000U);
+}
+
+void
+grub_machine_fini (int flags)
+{
+ if (!(flags & GRUB_LOADER_FLAG_NORETURN))
+ return;
+
+ grub_efi_fini ();
+}
diff --git a/grub-core/kern/mips64/efi/startup.S
b/grub-core/kern/mips64/efi/startup.S
new file mode 100644
index 000000000..4fee9bee1
--- /dev/null
+++ b/grub-core/kern/mips64/efi/startup.S
@@ -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/>.
+ */
+
+#include <grub/symbol.h>
+
+ .file "startup.S"
+ .text
+
+ .set push
+ .align 4
+
+FUNCTION(_start)
+ /*
+ * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in a1/a0.
+ */
+ daddiu $sp, -16
+ sd $ra, ($sp)
+
+ dla $a2, grub_efi_image_handle
+ sd $a0, ($a2)
+ dla $a2, grub_efi_system_table
+ sd $a1, ($a2)
+
+ jal grub_main
+
+1:
+ ld $ra, ($sp)
+ daddiu $sp, 16
+ jr $ra
+
+ .set pop
+
diff --git a/grub-core/kern/mips64/init.c b/grub-core/kern/mips64/init.c
new file mode 100644
index 000000000..8fd0a88a5
--- /dev/null
+++ b/grub-core/kern/mips64/init.c
@@ -0,0 +1,47 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009,2017 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/kernel.h>
+#include <grub/env.h>
+#include <grub/time.h>
+#include <grub/cpu/mips.h>
+
+grub_uint32_t grub_arch_cpuclock;
+
+/* FIXME: use interrupt to count high. */
+grub_uint64_t
+grub_get_rtc (void)
+{
+ static grub_uint32_t high = 0;
+ static grub_uint32_t last = 0;
+ grub_uint32_t low;
+
+ asm volatile ("mfc0 %0, " GRUB_CPU_MIPS_COP0_TIMER_COUNT : "=r" (low));
+ if (low < last)
+ high++;
+ last = low;
+
+ return (((grub_uint64_t) high) << 32) | low;
+}
+
+void
+grub_timer_init (grub_uint32_t cpuclock)
+{
+ grub_arch_cpuclock = cpuclock;
+ grub_install_get_time_ms (grub_rtc_get_time_ms);
+}
diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c
index e9441c844..3c4453922 100644
--- a/grub-core/lib/efi/halt.c
+++ b/grub-core/lib/efi/halt.c
@@ -29,7 +29,7 @@ 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(__mips__)
grub_acpi_halt ();
#endif
efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
diff --git a/grub-core/lib/mips64/setjmp.S b/grub-core/lib/mips64/setjmp.S
new file mode 100644
index 000000000..99ae22c18
--- /dev/null
+++ b/grub-core/lib/mips64/setjmp.S
@@ -0,0 +1,69 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+#include <grub/dl.h>
+#include <grub/mips64/asm.h>
+
+ .file "setjmp.S"
+
+GRUB_MOD_LICENSE "GPLv3+"
+
+ .text
+
+/*
+ * int grub_setjmp (grub_jmp_buf env)
+ */
+FUNCTION(grub_setjmp)
+ GRUB_ASM_REG_S $s0, 0($a0)
+ GRUB_ASM_REG_S $s1, 8($a0)
+ GRUB_ASM_REG_S $s2, 16($a0)
+ GRUB_ASM_REG_S $s3, 24($a0)
+ GRUB_ASM_REG_S $s4, 32($a0)
+ GRUB_ASM_REG_S $s5, 40($a0)
+ GRUB_ASM_REG_S $s6, 48($a0)
+ GRUB_ASM_REG_S $s7, 56($a0)
+ GRUB_ASM_REG_S $s8, 64($a0)
+ GRUB_ASM_REG_S $gp, 72($a0)
+ GRUB_ASM_REG_S $sp, 80($a0)
+ GRUB_ASM_REG_S $ra, 88($a0)
+ move $v0, $zero
+ move $v1, $zero
+ jr $ra
+ nop
+/*
+ * int grub_longjmp (grub_jmp_buf env, int val)
+ */
+FUNCTION(grub_longjmp)
+ GRUB_ASM_REG_L $s0, 0($a0)
+ GRUB_ASM_REG_L $s1, 8($a0)
+ GRUB_ASM_REG_L $s2, 16($a0)
+ GRUB_ASM_REG_L $s3, 24($a0)
+ GRUB_ASM_REG_L $s4, 32($a0)
+ GRUB_ASM_REG_L $s5, 40($a0)
+ GRUB_ASM_REG_L $s6, 48($a0)
+ GRUB_ASM_REG_L $s7, 56($a0)
+ GRUB_ASM_REG_L $s8, 64($a0)
+ GRUB_ASM_REG_L $gp, 72($a0)
+ GRUB_ASM_REG_L $sp, 80($a0)
+ GRUB_ASM_REG_L $ra, 88($a0)
+ addiu $v0, $zero, 1
+ movn $v0, $a1, $a1
+ move $v1, $zero
+ jr $ra
+ nop
diff --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S
index f6e4905e2..8799fa133 100644
--- a/grub-core/lib/setjmp.S
+++ b/grub-core/lib/setjmp.S
@@ -5,7 +5,11 @@
#elif defined(__sparc__)
#include "./sparc64/setjmp.S"
#elif defined(__mips__)
+#if _MIPS_SIM == _ABI64
+#include "./mips64/setjmp.S"
+#else
#include "./mips/setjmp.S"
+#endif
#elif defined(__powerpc__) || defined(__PPC__)
#include "./powerpc/setjmp.S"
#elif defined(__ia64__)
diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c
index db80b3ba0..3b2e01c93 100644
--- a/grub-core/term/serial.c
+++ b/grub-core/term/serial.c
@@ -22,7 +22,7 @@
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/terminfo.h>
-#if !defined (GRUB_MACHINE_EMU) && (defined(__mips__) || defined (__i386__) ||
defined (__x86_64__))
+#if !defined (GRUB_MACHINE_EMU) && ((defined(__mips__) && _MIPS_SIM != _ABI64)
|| defined (__i386__) || defined (__x86_64__))
#include <grub/cpu/io.h>
#endif
#include <grub/extcmd.h>
@@ -151,7 +151,7 @@ grub_serial_find (const char *name)
if (grub_strcmp (port->name, name) == 0)
break;
-#if (defined(__mips__) || defined (__i386__) || defined (__x86_64__)) &&
!defined(GRUB_MACHINE_EMU) && !defined(GRUB_MACHINE_ARC)
+#if ((defined(__mips__) && _MIPS_SIM != _ABI64) || defined (__i386__) ||
defined (__x86_64__)) && !defined(GRUB_MACHINE_EMU) &&
!defined(GRUB_MACHINE_ARC)
if (!port && grub_memcmp (name, "port", sizeof ("port") - 1) == 0
&& grub_isxdigit (name [sizeof ("port") - 1]))
{
@@ -286,7 +286,7 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char
**args)
err = port->driver->configure (port, &config);
if (err)
return err;
-#if !defined (GRUB_MACHINE_EMU) && !defined(GRUB_MACHINE_ARC) &&
(defined(__mips__) || defined (__i386__) || defined (__x86_64__))
+#if !defined (GRUB_MACHINE_EMU) && !defined(GRUB_MACHINE_ARC) &&
((defined(__mips__) && _MIPS_SIM != _ABI64) || defined (__i386__) || defined
(__x86_64__))
/* Compatibility kludge. */
if (port->driver == &grub_ns8250_driver)
@@ -436,7 +436,7 @@ GRUB_MOD_INIT(serial)
&grub_serial_terminfo_input_template,
sizeof (grub_serial_terminfo_input));
-#if !defined (GRUB_MACHINE_EMU) && !defined(GRUB_MACHINE_ARC) &&
(defined(__mips__) || defined (__i386__) || defined (__x86_64__))
+#if !defined (GRUB_MACHINE_EMU) && !defined(GRUB_MACHINE_ARC) &&
((defined(__mips__) && _MIPS_SIM != _ABI64) || defined (__i386__) || defined
(__x86_64__))
grub_ns8250_init ();
#endif
#ifdef GRUB_MACHINE_IEEE1275
diff --git a/include/grub/cache.h b/include/grub/cache.h
index fc669dfd1..93583ea15 100644
--- a/include/grub/cache.h
+++ b/include/grub/cache.h
@@ -34,7 +34,7 @@ void EXPORT_FUNC(grub_arch_sync_caches) (void *address,
grub_size_t len);
#endif
#ifndef GRUB_MACHINE_EMU
-#ifdef _mips
+#if defined(__mips__) && (_MIPS_SIM != _ABI64)
void EXPORT_FUNC(grub_arch_sync_dma_caches) (volatile void *address,
grub_size_t len);
#else
diff --git a/include/grub/dl.h b/include/grub/dl.h
index 2bca56ce0..89216b175 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -187,7 +187,7 @@ struct grub_dl
void *tramp;
void *trampptr;
#endif
-#ifdef __mips__
+#if defined(__mips__) && (_MIPS_SIM != _ABI64)
grub_uint32_t *reginfo;
#endif
void *base;
@@ -252,7 +252,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
Elf_Shdr *s, grub_dl_segment_t seg);
#endif
-#if defined (_mips)
+#if defined (__mips__) && (_MIPS_SIM != _ABI64)
#define GRUB_LINKER_HAVE_INIT 1
void grub_arch_dl_init_linker (void);
#endif
@@ -279,12 +279,12 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr,
grub_size_t *tramp,
grub_size_t *got);
#endif
-#if defined (__powerpc__) || defined (__mips__) || defined (__arm__)
+#if defined (__powerpc__) || (defined (__mips__) && (_MIPS_SIM != _ABI64)) ||
defined (__arm__)
#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 (__mips__) &&
(_MIPS_SIM == _ABI64))
#define GRUB_ARCH_DL_TRAMP_ALIGN 8
#define GRUB_ARCH_DL_GOT_ALIGN 8
#endif
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index c7c9f0e1d..cb4848323 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -1686,7 +1686,7 @@ struct grub_efi_block_io
typedef struct grub_efi_block_io grub_efi_block_io_t;
#if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
- || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__)
+ || defined (__aarch64__) || defined(__mips__) || defined (__MINGW64__) ||
defined (__CYGWIN__)
#define efi_call_0(func) func()
#define efi_call_1(func, a) func(a)
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
index f79c36c02..a2bff174e 100644
--- a/include/grub/efi/pe32.h
+++ b/include/grub/efi/pe32.h
@@ -64,6 +64,7 @@ struct grub_pe32_coff_header
};
#define GRUB_PE32_MACHINE_I386 0x14c
+#define GRUB_PE32_MACHINE_MIPS 0x166
#define GRUB_PE32_MACHINE_IA64 0x200
#define GRUB_PE32_MACHINE_X86_64 0x8664
#define GRUB_PE32_MACHINE_ARMTHUMB_MIXED 0x01c2
@@ -278,6 +279,10 @@ struct grub_pe32_fixup_block
#define GRUB_PE32_REL_BASED_HIGHLOW 3
#define GRUB_PE32_REL_BASED_HIGHADJ 4
#define GRUB_PE32_REL_BASED_MIPS_JMPADDR 5
+#define GRUB_PE32_REL_BASED_MIPS_LOW 6
+#define GRUB_PE32_REL_BASED_MIPS_HIGH 4
+#define GRUB_PE32_REL_BASED_MIPS_HIGHER 7
+#define GRUB_PE32_REL_BASED_MIPS_HIGHEST 8
#define GRUB_PE32_REL_BASED_ARM_MOV32A 5
#define GRUB_PE32_REL_BASED_SECTION 6
#define GRUB_PE32_REL_BASED_REL 7
diff --git a/include/grub/mips64/asm.h b/include/grub/mips64/asm.h
new file mode 100644
index 000000000..062bdf5e9
--- /dev/null
+++ b/include/grub/mips64/asm.h
@@ -0,0 +1,10 @@
+#ifndef GRUB_MIPS64_ASM_HEADER
+#define GRUB_MIPS64_ASM_HEADER 1
+
+#define GRUB_ASM_T4 $a4
+#define GRUB_ASM_T5 $a5
+#define GRUB_ASM_SZREG 8
+#define GRUB_ASM_REG_S sd
+#define GRUB_ASM_REG_L ld
+
+#endif
diff --git a/include/grub/mips64/efi/boot.h b/include/grub/mips64/efi/boot.h
new file mode 100644
index 000000000..e69de29bb
diff --git a/include/grub/mips64/efi/loader.h b/include/grub/mips64/efi/loader.h
new file mode 100644
index 000000000..71a015977
--- /dev/null
+++ b/include/grub/mips64/efi/loader.h
@@ -0,0 +1,25 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2003,2004,2006,2007,2017 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_LOADER_MACHINE_HEADER
+#define GRUB_LOADER_MACHINE_HEADER 1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+
+#endif /* ! GRUB_LOADER_MACHINE_HEADER */
diff --git a/include/grub/mips64/efi/memory.h b/include/grub/mips64/efi/memory.h
new file mode 100644
index 000000000..52e6ae6eb
--- /dev/null
+++ b/include/grub/mips64/efi/memory.h
@@ -0,0 +1,6 @@
+#ifndef GRUB_MEMORY_CPU_HEADER
+#include <grub/efi/memory.h>
+
+#define GRUB_EFI_MAX_USABLE_ADDRESS 0x980000000fffffffUL
+
+#endif /* ! GRUB_MEMORY_CPU_HEADER */
diff --git a/include/grub/mips64/efi/time.h b/include/grub/mips64/efi/time.h
new file mode 100644
index 000000000..e69de29bb
diff --git a/include/grub/mips64/io.h b/include/grub/mips64/io.h
new file mode 100644
index 000000000..5f341037a
--- /dev/null
+++ b/include/grub/mips64/io.h
@@ -0,0 +1,62 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009,2017 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_IO_H
+#define GRUB_IO_H 1
+
+#include <grub/types.h>
+
+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/mips64/kernel.h b/include/grub/mips64/kernel.h
new file mode 100644
index 000000000..909d5397d
--- /dev/null
+++ b/include/grub/mips64/kernel.h
@@ -0,0 +1,24 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008,2009,2017 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_KERNEL_CPU_HEADER
+#define GRUB_KERNEL_CPU_HEADER 1
+
+#include <grub/symbol.h>
+
+#endif /* ! GRUB_KERNEL_MACHINE_HEADER */
diff --git a/include/grub/mips64/memory.h b/include/grub/mips64/memory.h
new file mode 100644
index 000000000..573a70f79
--- /dev/null
+++ b/include/grub/mips64/memory.h
@@ -0,0 +1,56 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2017 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_MEMORY_CPU_HEADER
+#define GRUB_MEMORY_CPU_HEADER 1
+
+#ifndef ASM_FILE
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/types.h>
+#endif
+
+#ifndef ASM_FILE
+
+typedef grub_addr_t grub_phys_addr_t;
+
+static inline grub_phys_addr_t
+grub_vtop (void *a)
+{
+ if (-1 == ((grub_int64_t) a >> 32))
+ return ((grub_phys_addr_t) a) & 0x1fffffffUL;
+ return ((grub_phys_addr_t) a) & 0xffffffffffffUL;
+}
+
+static inline void *
+grub_map_memory (grub_phys_addr_t a, grub_size_t size)
+{
+ if ((a + size) < 0x20000000UL)
+ return (void *) (a | 0xffffffff80000000UL);
+ return (void *) (a | 0x9800000000000000UL);
+}
+
+static inline void
+grub_unmap_memory (void *a __attribute__ ((unused)),
+ grub_size_t size __attribute__ ((unused)))
+{
+}
+
+#endif
+
+#endif
diff --git a/include/grub/mips64/mips.h b/include/grub/mips64/mips.h
new file mode 100644
index 000000000..a13c709e0
--- /dev/null
+++ b/include/grub/mips64/mips.h
@@ -0,0 +1,30 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010,2017 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_REGISTERS_CPU_HEADER
+#define GRUB_REGISTERS_CPU_HEADER 1
+
+#ifdef ASM_FILE
+#define GRUB_CPU_REGISTER_WRAP(x) x
+#else
+#define GRUB_CPU_REGISTER_WRAP(x) #x
+#endif
+
+#define GRUB_CPU_MIPS_COP0_TIMER_COUNT GRUB_CPU_REGISTER_WRAP($9)
+
+#endif
diff --git a/include/grub/mips64/setjmp.h b/include/grub/mips64/setjmp.h
new file mode 100644
index 000000000..d9a0776b6
--- /dev/null
+++ b/include/grub/mips64/setjmp.h
@@ -0,0 +1,27 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2004,2006,2007,2009,2017 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 grub_uint64_t grub_jmp_buf[12];
+
+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 */
diff --git a/include/grub/mips64/time.h b/include/grub/mips64/time.h
new file mode 100644
index 000000000..c9a733488
--- /dev/null
+++ b/include/grub/mips64/time.h
@@ -0,0 +1,39 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2004,2005,2007,2017 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
+
+#ifndef GRUB_UTIL
+
+#define GRUB_TICKS_PER_SECOND (grub_arch_cpuclock / 2)
+
+void grub_timer_init (grub_uint32_t cpuclock);
+
+/* Return the real time in ticks. */
+grub_uint64_t grub_get_rtc (void);
+
+extern grub_uint32_t grub_arch_cpuclock;
+#endif
+
+static inline void
+grub_cpu_idle(void)
+{
+}
+
+#endif
diff --git a/include/grub/mips64/types.h b/include/grub/mips64/types.h
new file mode 100644
index 000000000..fc896c83b
--- /dev/null
+++ b/include/grub/mips64/types.h
@@ -0,0 +1,38 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2006,2007,2009,2017 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
+
+#ifdef GRUB_CPU_MIPS64EL
+/* mips64EL is little-endian. */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+#elif defined (GRUB_CPU_MIPS64)
+/* mips64 is big-endian. */
+#define GRUB_TARGET_WORDS_BIGENDIAN
+#elif !defined (GRUB_SYMBOL_GENERATOR)
+#error Neither GRUB_CPU_MIPS64 nor GRUB_CPU_MIPS64EL is defined
+#endif
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
diff --git a/include/grub/misc.h b/include/grub/misc.h
index 2a9f87cc2..2ba97b493 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -410,7 +410,7 @@ void __attribute__ ((noreturn)) EXPORT_FUNC (abort) (void);
/* Halt the system, using APM if possible. If NO_APM is true, don't
* use APM even if it is available. */
void grub_halt (int no_apm) __attribute__ ((noreturn));
-#elif defined (__mips__) && !defined (GRUB_MACHINE_EMU)
+#elif (defined (__mips__) && (_MIPS_SIM != _ABI64)) && !defined
(GRUB_MACHINE_EMU)
void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn));
#else
void grub_halt (void) __attribute__ ((noreturn));
diff --git a/include/grub/serial.h b/include/grub/serial.h
index 67379de45..f8cc4612b 100644
--- a/include/grub/serial.h
+++ b/include/grub/serial.h
@@ -21,7 +21,7 @@
#define GRUB_SERIAL_HEADER 1
#include <grub/types.h>
-#if defined(__mips__) || defined (__i386__) || defined (__x86_64__)
+#if (defined(__mips__) && _MIPS_SIM != _ABI64) || defined (__i386__) ||
defined (__x86_64__)
#include <grub/cpu/io.h>
#endif
#include <grub/usb.h>
@@ -86,7 +86,7 @@ struct grub_serial_port
*/
union
{
-#if defined(__mips__) || defined (__i386__) || defined (__x86_64__)
+#if (defined(__mips__) && _MIPS_SIM != _ABI64) || defined (__i386__) ||
defined (__x86_64__)
grub_port_t port;
#endif
struct
@@ -175,7 +175,7 @@ grub_serial_config_defaults (struct grub_serial_port *port)
return port->driver->configure (port, &config);
}
-#if defined(__mips__) || defined (__i386__) || defined (__x86_64__)
+#if (defined(__mips__) && _MIPS_SIM != _ABI64) || defined (__i386__) ||
defined (__x86_64__)
void grub_ns8250_init (void);
char *grub_serial_ns8250_add_port (grub_port_t port);
#endif
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 5ca4811cd..00c6d64af 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -99,6 +99,7 @@ enum grub_install_plat
GRUB_INSTALL_PLATFORM_I386_XEN,
GRUB_INSTALL_PLATFORM_X86_64_XEN,
GRUB_INSTALL_PLATFORM_ARM64_EFI,
+ GRUB_INSTALL_PLATFORM_MIPS64EL_EFI,
GRUB_INSTALL_PLATFORM_MAX
};
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index 452b230da..871000449 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -665,6 +665,7 @@ static struct
[GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64", "efi" },
[GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm", "efi" },
[GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64", "efi" },
+ [GRUB_INSTALL_PLATFORM_MIPS64EL_EFI] = { "mips64el","efi" },
[GRUB_INSTALL_PLATFORM_ARM_UBOOT] = { "arm", "uboot" },
};
diff --git a/util/grub-install.c b/util/grub-install.c
index 6c89c2b0c..5fac6389b 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -313,7 +313,11 @@ get_default_platform (void)
#elif defined (__sparc__) || defined (__sparc64__)
return "sparc64-ieee1275";
#elif defined (__MIPSEL__)
+#if _MIPS_SIM == _ABI64
+ return "mips64el-efi";
+#else
return "mipsel-loongson";
+#endif
#elif defined (__MIPSEB__)
return "mips-arc";
#elif defined (__ia64__)
@@ -477,6 +481,7 @@ 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_MIPS64EL_EFI:
case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
@@ -898,6 +903,7 @@ 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_MIPS64EL_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
@@ -941,6 +947,7 @@ 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_MIPS64EL_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
@@ -992,6 +999,7 @@ 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_MIPS64EL_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
is_efi = 1;
break;
@@ -1105,6 +1113,9 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
efi_file = "BOOTAA64.EFI";
break;
+ case GRUB_INSTALL_PLATFORM_MIPS64EL_EFI:
+ efi_file = "BOOTMIPS64EL.EFI";
+ break;
default:
grub_util_error ("%s", _("You've found a bug"));
break;
@@ -1132,6 +1143,9 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
efi_file = "grubaa64.efi";
break;
+ case GRUB_INSTALL_PLATFORM_MIPS64EL_EFI:
+ efi_file = "grubmips64el.efi";
+ break;
default:
efi_file = "grub.efi";
break;
@@ -1434,6 +1448,7 @@ 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_MIPS64EL_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
g = grub_util_guess_efi_drive (*curdev);
break;
@@ -1524,6 +1539,7 @@ 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_MIPS64EL_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
core_name = "core.efi";
snprintf (mkimage_target, sizeof (mkimage_target),
@@ -1625,6 +1641,7 @@ main (int argc, char *argv[])
break;
case GRUB_INSTALL_PLATFORM_ARM_EFI:
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+ case GRUB_INSTALL_PLATFORM_MIPS64EL_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
@@ -1853,6 +1870,7 @@ main (int argc, char *argv[])
}
case GRUB_INSTALL_PLATFORM_ARM_EFI:
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+ case GRUB_INSTALL_PLATFORM_MIPS64EL_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 f8faae878..f70e98241 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -769,7 +769,11 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr
*sections,
offset = grub_target_to_host (r->r_offset);
target = SUFFIX (get_target_address) (e, target_section,
offset, image_target);
- info = grub_target_to_host (r->r_info);
+ if (image_target->elf_target == EM_MIPS &&
image_target->voidp_sizeof == 8)
+ info = ((grub_uint64_t) r->r_info << 32) |
+ (grub_uint32_t) grub_be_to_cpu64 (r->r_info);
+ else
+ info = grub_target_to_host (r->r_info);
sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
ELF_R_SYM (info),
image_target);
@@ -1051,6 +1055,66 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr
*sections,
}
break;
}
+ case EM_MIPS:
+ {
+ sym_addr += addend;
+ switch (ELF_R_TYPE (info))
+ {
+ case R_MIPS_NONE:
+ break;
+ case R_MIPS_64:
+ {
+ *target = grub_host_to_target64 (grub_target_to_host64
(*target) + sym_addr);
+ }
+ break;
+ case R_MIPS_32:
+ {
+ grub_uint32_t *t32 = (grub_uint32_t *) target;
+ *t32 = grub_host_to_target64 (grub_target_to_host32
(*t32) + sym_addr);
+ }
+ break;
+ case R_MIPS_26:
+ {
+ grub_uint32_t *t32 = (grub_uint32_t *) target;
+ grub_addr_t addr = grub_host_to_target64 (sym_addr);
+ *t32 = ((*t32) & 0xfc000000U) | ((addr >> 2) &
0x3ffffffUL);
+ }
+ break;
+ case R_MIPS_LO16:
+ {
+ grub_int16_t *t16 = (grub_int16_t *) target;
+ grub_addr_t addr = grub_host_to_target64 (sym_addr);
+ *t16 = (grub_int16_t) addr;
+ }
+ break;
+ case R_MIPS_HI16:
+ {
+ grub_int16_t *t16 = (grub_int16_t *) target;
+ grub_addr_t addr = grub_host_to_target64 (sym_addr);
+ *t16 = (grub_int16_t) ((addr + 0x8000UL) >> 16);
+ }
+ break;
+ case R_MIPS_HIGHER:
+ {
+ grub_int16_t *t16 = (grub_int16_t *) target;
+ grub_addr_t addr = grub_host_to_target64 (sym_addr);
+ *t16 = (grub_int16_t) ((addr + 0x80008000UL) >> 32);
+ }
+ break;
+ case R_MIPS_HIGHEST:
+ {
+ grub_uint16_t *t16 = (grub_uint16_t *) target;
+ grub_addr_t addr = grub_host_to_target64 (sym_addr);
+ *t16 = (grub_uint16_t) ((addr + 0x800080008000UL) >> 48);
+ }
+ break;
+ default:
+ grub_util_error (_("relocation 0x%x is not implemented
yet"),
+ (unsigned int) ELF_R_TYPE (info));
+ break;
+ }
+ break;
+ }
#endif
#if defined(MKIMAGE_ELF32)
case EM_ARM:
@@ -1176,7 +1240,7 @@ add_fixup_entry (struct fixup_block_list **cblock,
grub_uint16_t type,
/* First, check if it is necessary to write out the current block. */
if ((*cblock)->state)
{
- if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
+ if (flush || (type && (addr < b->page_rva || b->page_rva + 0x1000 <=
addr)))
{
grub_uint32_t size;
@@ -1239,7 +1303,8 @@ add_fixup_entry (struct fixup_block_list **cblock,
grub_uint16_t type,
/* The spec does not mention the requirement of a Page RVA.
Here, align the address with a 4K boundary for safety. */
- b->page_rva = (addr & ~(0x1000 - 1));
+ if (type)
+ b->page_rva = (addr & ~(0x1000 - 1));
b->block_size = sizeof (*b);
}
@@ -1249,7 +1314,7 @@ add_fixup_entry (struct fixup_block_list **cblock,
grub_uint16_t type,
/* Add a new entry. */
cur_index = ((b->block_size - sizeof (*b)) >> 1);
- entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
+ entry = GRUB_PE32_FIXUP_ENTRY (type, type ? (addr - b->page_rva) : addr);
b->entries[cur_index] = grub_host_to_target16 (entry);
b->block_size += 2;
}
@@ -1295,6 +1360,8 @@ static void
translate_relocation_pe (struct translate_context *ctx,
Elf_Addr addr,
Elf_Addr info,
+ Elf_Addr sym_addr,
+ Elf_Addr addend,
const struct grub_install_image_target_desc
*image_target)
{
/* Necessary to relocate only absolute addresses. */
@@ -1405,7 +1472,162 @@ translate_relocation_pe (struct translate_context *ctx,
break;
}
break;
+#if defined(MKIMAGE_ELF64)
+ case EM_MIPS:
+ switch (ELF_R_TYPE (info))
+ {
+ case R_MIPS_64:
+ {
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst,
+ GRUB_PE32_REL_BASED_DIR64,
+ addr, 0, ctx->current_address,
+ image_target);
+ }
+ break;
+ case R_MIPS_32:
+#if 0
+ {
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst,
+ GRUB_PE32_REL_BASED_HIGHLOW,
+ addr, 0, ctx->current_address,
+ image_target);
+ }
+#endif
+ break;
+ case R_MIPS_26:
+ {
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst,
+ GRUB_PE32_REL_BASED_MIPS_JMPADDR,
+ addr, 0, ctx->current_address,
+ image_target);
+ }
+ break;
+ case R_MIPS_LO16:
+ {
+ Elf_Addr target = sym_addr + addend;
+
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst,
+ GRUB_PE32_REL_BASED_MIPS_LOW,
+ addr, 0, ctx->current_address,
+ image_target);
+ /* Hi */
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst, 0,
+ (grub_int16_t) ((target & 0x8000UL) >> 16),
+ 0, ctx->current_address,
+ image_target);
+ /* Higher */
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst, 0,
+ (grub_int16_t) ((target & 0x80008000UL) >> 32),
+ 0, ctx->current_address,
+ image_target);
+ /* Highest */
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst, 0,
+ (grub_uint16_t) ((target & 0x800080008000UL)
>> 48),
+ 0, ctx->current_address,
+ image_target);
+ }
+ break;
+ case R_MIPS_HI16:
+ {
+ Elf_Addr target = sym_addr + addend;
+
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst,
+ GRUB_PE32_REL_BASED_MIPS_HIGH,
+ addr, 0, ctx->current_address,
+ image_target);
+ /* Lo */
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst, 0,
+ (grub_int16_t) target,
+ 0, ctx->current_address,
+ image_target);
+ /* Higher */
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst, 0,
+ (grub_int16_t) ((target & 0x80008000UL) >> 32),
+ 0, ctx->current_address,
+ image_target);
+ /* Highest */
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst, 0,
+ (grub_uint16_t) ((target & 0x800080008000UL)
>> 48),
+ 0, ctx->current_address,
+ image_target);
+ }
+ break;
+ case R_MIPS_HIGHER:
+ {
+ Elf_Addr target = sym_addr + addend;
+
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst,
+ GRUB_PE32_REL_BASED_MIPS_HIGHER,
+ addr, 0, ctx->current_address,
+ image_target);
+ /* Lo */
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst, 0,
+ (grub_int16_t) target,
+ 0, ctx->current_address,
+ image_target);
+ /* Hi */
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst, 0,
+ (grub_int16_t) ((target & 0x8000UL) >> 16),
+ 0, ctx->current_address,
+ image_target);
+ /* Highest */
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst, 0,
+ (grub_uint16_t) ((target & 0x800080008000UL)
>> 48),
+ 0, ctx->current_address,
+ image_target);
+ }
+ break;
+ case R_MIPS_HIGHEST:
+ {
+ Elf_Addr target = sym_addr + addend;
+
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst,
+ GRUB_PE32_REL_BASED_MIPS_HIGHEST,
+ addr, 0, ctx->current_address,
+ image_target);
+ /* Lo */
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst, 0,
+ (grub_int16_t) target,
+ 0, ctx->current_address,
+ image_target);
+ /* Hi */
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst, 0,
+ (grub_int16_t) ((target & 0x8000UL) >> 16),
+ 0, ctx->current_address,
+ image_target);
+ /* Higher */
+ ctx->current_address
+ = add_fixup_entry (&ctx->lst, 0,
+ (grub_int16_t) ((target & 0x80008000UL) >> 32),
+ 0, ctx->current_address,
+ image_target);
+ }
+ break;
+ default:
+ grub_util_error (_("relocation 0x%x is not implemented yet"),
+ (unsigned int) ELF_R_TYPE (info));
+ break;
+ }
break;
+#endif
#if defined(MKIMAGE_ELF32)
case EM_ARM:
switch (ELF_R_TYPE (info))
@@ -1494,10 +1716,12 @@ static void
translate_relocation (struct translate_context *ctx,
Elf_Addr addr,
Elf_Addr info,
+ Elf_Addr sym_addr,
+ Elf_Addr addend,
const struct grub_install_image_target_desc *image_target)
{
if (image_target->id == IMAGE_EFI)
- translate_relocation_pe (ctx, addr, info, image_target);
+ translate_relocation_pe (ctx, addr, info, sym_addr, addend, image_target);
else
translate_relocation_raw (ctx, addr, info, image_target);
}
@@ -1640,12 +1864,17 @@ make_reloc_section (Elf_Ehdr *e, struct
grub_mkimage_layout *layout,
if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
(grub_target_to_host32 (s->sh_type) == SHT_RELA))
{
- Elf_Rel *r;
+ Elf_Rela *r;
Elf_Word rtab_size, r_size, num_rs;
Elf_Off rtab_offset;
+ Elf_Shdr *symtab_section;
Elf_Addr section_address;
Elf_Word j;
+ symtab_section = (Elf_Shdr *) ((char *) sections
+ + (grub_target_to_host32 (s->sh_link)
+ * section_entsize));
+
grub_util_info ("translating the relocation section %s",
strtab + grub_le_to_cpu32 (s->sh_name));
@@ -1656,20 +1885,30 @@ make_reloc_section (Elf_Ehdr *e, struct
grub_mkimage_layout *layout,
section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
- for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
+ for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
j < num_rs;
- j++, r = (Elf_Rel *) ((char *) r + r_size))
+ j++, r = (Elf_Rela *) ((char *) r + r_size))
{
Elf_Addr info;
Elf_Addr offset;
Elf_Addr addr;
+ Elf_Addr sym_addr;
+ Elf_Addr addend;
offset = grub_target_to_host (r->r_offset);
- info = grub_target_to_host (r->r_info);
+ if (image_target->elf_target == EM_MIPS &&
image_target->voidp_sizeof == 8)
+ info = ((grub_uint64_t) r->r_info << 32) |
+ (grub_uint32_t) grub_be_to_cpu64 (r->r_info);
+ else
+ info = grub_target_to_host (r->r_info);
+ sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
+ ELF_R_SYM (info),
image_target);
+ addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
+ grub_target_to_host (r->r_addend) : 0;
addr = section_address + offset;
- translate_relocation (&ctx, addr, info, image_target);
+ translate_relocation (&ctx, addr, info, sym_addr, addend,
image_target);
}
}
diff --git a/util/grub-mknetdir.c b/util/grub-mknetdir.c
index 82073d5cc..5e9be8f2e 100644
--- a/util/grub-mknetdir.c
+++ b/util/grub-mknetdir.c
@@ -107,7 +107,8 @@ static const 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_MIPS64EL_EFI] = { "mips64el-efi", "efinet", ".efi" }
};
static void
diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c
index 238d4840e..f42a9c6a5 100644
--- a/util/grub-mkrescue.c
+++ b/util/grub-mkrescue.c
@@ -530,6 +530,7 @@ 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_MIPS64EL_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 +728,8 @@ 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_MIPS64EL_EFI])
{
char *efidir = grub_util_make_temporary_dir ();
char *efidir_efi = grub_util_path_concat (2, efidir, "efi");
@@ -762,6 +764,11 @@ main (int argc, char *argv[])
imgname);
free (imgname);
+ imgname = grub_util_path_concat (2, efidir_efi_boot, "bootmips64el.efi");
+ make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_MIPS64EL_EFI,
"mips64el-efi",
+ imgname);
+ free (imgname);
+
if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI])
{
imgname = grub_util_path_concat (2, efidir_efi_boot, "boot.efi");
diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c
index d0cf8176f..6b07631d6 100644
--- a/util/grub-module-verifier.c
+++ b/util/grub-module-verifier.c
@@ -118,6 +118,19 @@ struct grub_module_verifier_arch archs[] = {
-1
}
},
+ { "mips64el", 8, 0, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL |
GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
+ R_MIPS_64,
+ R_MIPS_32,
+ R_MIPS_26,
+ R_MIPS_LO16,
+ R_MIPS_HI16,
+ R_MIPS_HIGHER,
+ R_MIPS_HIGHEST,
+ -1
+ }, (int[]){
+ -1
+ }
+ },
};
struct platform_whitelist {
diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c
index 1feaafc9b..0b0446e98 100644
--- a/util/grub-module-verifierXX.c
+++ b/util/grub-module-verifierXX.c
@@ -296,7 +296,14 @@ section_check_relocations (const struct
grub_module_verifier_arch *arch, void *e
if (target_seg_size < grub_target_to_host (rel->r_offset))
grub_util_error ("reloc offset is out of the segment");
- grub_uint32_t type = ELF_R_TYPE (grub_target_to_host (rel->r_info));
+ grub_size_t r_info;
+ if (arch->machine == EM_MIPS && arch->voidp_sizeof == 8)
+ r_info = ((grub_uint64_t) rel->r_info << 32) |
+ (grub_uint32_t) grub_be_to_cpu64 (rel->r_info);
+ else
+ r_info = grub_target_to_host (rel->r_info);
+
+ grub_uint32_t type = ELF_R_TYPE (r_info);
if (arch->machine == EM_SPARCV9)
type &= 0xff;
@@ -313,7 +320,7 @@ section_check_relocations (const struct
grub_module_verifier_arch *arch, void *e
break;
if (arch->short_relocations[i] == -1)
grub_util_error ("unsupported relocation 0x%x", type);
- sym = (Elf_Sym *) ((char *) symtab + symtabentsize * ELF_R_SYM
(grub_target_to_host (rel->r_info)));
+ sym = (Elf_Sym *) ((char *) symtab + symtabentsize * ELF_R_SYM (r_info));
if (is_symbol_local (sym))
continue;
diff --git a/util/mkimage.c b/util/mkimage.c
index 9ad4cfe42..5ad214a17 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -570,6 +570,22 @@ static const struct grub_install_image_target_desc
image_targets[] =
.pe_target = GRUB_PE32_MACHINE_ARM64,
.elf_target = EM_AARCH64,
},
+ {
+ .dirname = "mips64el-efi",
+ .names = { "mips64el-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_MIPS,
+ .elf_target = EM_MIPS,
+ },
};
#include <grub/lib/LzmaEnc.h>
--
2.11.1
- [PATCH v2] mips64: Add support for 64-bit MIPS.,
wangr <=