diff --git a/conf/mips.rmk b/conf/mips.rmk
new file mode 100644
index 000000000..6d8df9e4e
--- /dev/null
+++ b/conf/mips.rmk
@@ -0,0 +1,125 @@
+
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc
+COMMON_CFLAGS =
+COMMON_LDFLAGS += -nostdlib
+
+# Used by various components. These rules need to precede them.
+script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Images.
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+ env.h err.h file.h fs.h kernel.h misc.h mm.h net.h parser.h reader.h \
+ symbol.h term.h time.h types.h loader.h partition.h \
+ msdos_partition.h machine/kernel.h handler.h list.h \
+ command.h
+
+symlist.c: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h gensymlist.sh
+ /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h genkernsyms.sh
+ /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# Programs
+pkglib_PROGRAMS = kernel.img
+
+# Utilities.
+sbin_UTILITIES = grub-mkdevicemap
+ifeq ($(enable_grub_emu), yes)
+sbin_UTILITIES += grub-emu
+endif
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/deviceiter.c \
+ util/devicemap.c util/misc.c
+
+# For grub-emu
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \
+ commands/configfile.c commands/help.c \
+ commands/search.c commands/handler.c commands/test.c \
+ commands/ls.c commands/blocklist.c commands/hexdump.c \
+ lib/hexdump.c commands/reboot.c \
+ lib/envblk.c commands/loadenv.c \
+ commands/gptsync.c commands/probe.c commands/xnu_uuid.c \
+ commands/password.c commands/keystatus.c \
+ disk/loopback.c \
+ \
+ fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c \
+ fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \
+ fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c \
+ fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c fs/afs_be.c \
+ fs/befs.c fs/befs_be.c fs/tar.c \
+ \
+ io/gzio.c \
+ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \
+ kern/err.c kern/file.c kern/fs.c commands/boot.c kern/main.c \
+ kern/misc.c kern/parser.c kern/partition.c kern/reader.c \
+ kern/rescue_reader.c kern/rescue_parser.c \
+ kern/term.c kern/list.c kern/handler.c fs/fshelp.c \
+ kern/command.c kern/corecmd.c commands/extcmd.c \
+ lib/arg.c normal/cmdline.c normal/datetime.c \
+ normal/completion.c normal/misc.c \
+ normal/handler.c normal/auth.c normal/autofs.c normal/main.c \
+ normal/menu.c \
+ normal/menu_text.c \
+ normal/menu_entry.c normal/menu_viewer.c \
+ normal/color.c \
+ script/sh/main.c script/sh/execute.c script/sh/function.c \
+ script/sh/lexer.c script/sh/script.c \
+ partmap/amiga.c partmap/apple.c partmap/msdos.c partmap/sun.c \
+ partmap/acorn.c \
+ util/console.c util/hostfs.c util/grub-emu.c util/misc.c \
+ util/hostdisk.c util/getroot.c \
+ \
+ disk/raid.c disk/raid5_recover.c disk/raid6_recover.c \
+ disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \
+ commands/parttool.c parttool/msdospart.c \
+ grub_script.tab.c grub_emu_init.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+kernel_img_SOURCES = kern/mipsel/qemu-r4k/startup.S \
+ kern/main.c kern/device.c kern/$(target_cpu)/$(target_machine)/init.c \
+ kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \
+ kern/misc.c kern/mm.c kern/reader.c kern/term.c \
+ kern/rescue_parser.c kern/rescue_reader.c \
+ kern/list.c kern/handler.c kern/command.c kern/corecmd.c \
+ kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \
+ kern/generic/millisleep.c kern/time.c \
+ symlist.c kern/$(target_cpu)/cache.S
+kernel_img_CFLAGS = $(COMMON_CFLAGS)
+kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -static-libgcc -lgcc \
+ -Wl,-N,-S,-Ttext,$(LINK_BASE),-Bstatic
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+bin_SCRIPTS = grub-mkrescue
+
+# Modules.
+pkglib_MODULES = memdisk.mod \
+ lsmmap.mod
+
+# For boot.mod.
+pkglib_MODULES += boot.mod
+boot_mod_SOURCES = commands/boot.c lib/i386/pc/biosnum.c
+boot_mod_CFLAGS = $(COMMON_CFLAGS)
+boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lsmmap.mod
+lsmmap_mod_SOURCES = commands/lsmmap.c
+lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
+lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/common.mk
diff --git a/conf/mipsel-qemu-r4k.rmk b/conf/mipsel-qemu-r4k.rmk
new file mode 100644
index 000000000..3ff36c472
--- /dev/null
+++ b/conf/mipsel-qemu-r4k.rmk
@@ -0,0 +1,4 @@
+# -*- makefile -*-
+LINK_BASE = 0x80010000
+target_machine=qemu-r4k
+include $(srcdir)/conf/mips.mk
diff --git a/configure.ac b/configure.ac
index 3e4da66c8..74dcc5dd4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -89,6 +89,7 @@ case "$target_cpu"-"$platform" in
i386-qemu) ;;
powerpc-ieee1275) ;;
sparc64-ieee1275) ;;
+ mipsel-qemu-r4k) ;;
*) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;;
esac
diff --git a/include/grub/mipsel/kernel.h b/include/grub/mipsel/kernel.h
new file mode 100644
index 000000000..326f1244d
--- /dev/null
+++ b/include/grub/mipsel/kernel.h
@@ -0,0 +1,32 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_KERNEL_CPU_HEADER
+#define GRUB_KERNEL_CPU_HEADER 1
+
+#define GRUB_MOD_ALIGN 0x1000
+
+/* Minimal gap between _end and the start of the modules. It's a hack
+ for PowerMac to prevent "CLAIM failed" error. The real fix is to
+ rewrite grub-mkimage to generate valid ELF files. */
+#define GRUB_MOD_GAP 0x8000
+
+#define GRUB_KERNEL_CPU_PREFIX 0x8
+#define GRUB_KERNEL_CPU_DATA_END 0x48
+
+#endif
diff --git a/include/grub/mipsel/qemu-r4k/kernel.h b/include/grub/mipsel/qemu-r4k/kernel.h
new file mode 100644
index 000000000..6a10f2df1
--- /dev/null
+++ b/include/grub/mipsel/qemu-r4k/kernel.h
@@ -0,0 +1,35 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_KERNEL_MACHINE_HEADER
+#define GRUB_KERNEL_MACHINE_HEADER 1
+
+#include
+
+#ifndef ASM_FILE
+
+void EXPORT_FUNC (grub_reboot) (void);
+void EXPORT_FUNC (grub_halt) (void);
+
+/* The prefix which points to the directory where GRUB modules and its
+ configuration file are located. */
+extern char grub_prefix[];
+
+#endif
+
+#endif /* ! GRUB_KERNEL_MACHINE_HEADER */
diff --git a/include/grub/mipsel/qemu-r4k/machine.h b/include/grub/mipsel/qemu-r4k/machine.h
new file mode 100644
index 000000000..9bad5dca9
--- /dev/null
+++ b/include/grub/mipsel/qemu-r4k/machine.h
@@ -0,0 +1,24 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_MACHINE_MACHINE_HEADER
+#define GRUB_MACHINE_MACHINE_HEADER 1
+
+#define GRUB_MACHINE_MIPS_QEMU 1
+
+#endif /* ! GRUB_MACHINE_MACHINE_HEADER */
diff --git a/include/grub/mipsel/qemu-r4k/memory.h b/include/grub/mipsel/qemu-r4k/memory.h
new file mode 100644
index 000000000..6021bab04
--- /dev/null
+++ b/include/grub/mipsel/qemu-r4k/memory.h
@@ -0,0 +1,35 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_MEMORY_MACHINE_HEADER
+#define GRUB_MEMORY_MACHINE_HEADER 1
+
+#ifndef ASM_FILE
+#include
+#include
+#include
+#endif
+
+#define GRUB_MACHINE_MEMORY_STACK_HIGH 0x81000000
+
+#ifndef ASM_FILE
+grub_err_t EXPORT_FUNC (grub_machine_mmap_iterate)
+(int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
+#endif
+
+#endif
diff --git a/include/grub/mipsel/qemu-r4k/time.h b/include/grub/mipsel/qemu-r4k/time.h
new file mode 100644
index 000000000..a73f64dea
--- /dev/null
+++ b/include/grub/mipsel/qemu-r4k/time.h
@@ -0,0 +1,34 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2004,2005,2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef KERNEL_MACHINE_TIME_HEADER
+#define KERNEL_MACHINE_TIME_HEADER 1
+
+#include
+
+#define GRUB_TICKS_PER_SECOND 1000
+
+/* Return the real time in ticks. */
+grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void);
+
+static inline void
+grub_cpu_idle(void)
+{
+}
+
+#endif /* ! KERNEL_MACHINE_TIME_HEADER */
diff --git a/include/grub/mipsel/time.h b/include/grub/mipsel/time.h
new file mode 100644
index 000000000..e69de29bb
diff --git a/include/grub/mipsel/types.h b/include/grub/mipsel/types.h
new file mode 100644
index 000000000..94a35be6e
--- /dev/null
+++ b/include/grub/mipsel/types.h
@@ -0,0 +1,31 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2006,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 .
+ */
+
+#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
+
+/* mipsEL is little-endian. */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
diff --git a/kern/mipsel/cache.S b/kern/mipsel/cache.S
new file mode 100644
index 000000000..5341f07a2
--- /dev/null
+++ b/kern/mipsel/cache.S
@@ -0,0 +1,5 @@
+#include
+
+FUNCTION (grub_arch_sync_caches)
+FUNCTION (_flush_cache)
+ j $31
diff --git a/kern/mipsel/dl.c b/kern/mipsel/dl.c
new file mode 100644
index 000000000..57854964b
--- /dev/null
+++ b/kern/mipsel/dl.c
@@ -0,0 +1,109 @@
+/* dl-386.c - arch-dependent part of loadable module support */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2005,2007,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+
+/* 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_CLASS] != ELFCLASS32
+ || e->e_ident[EI_DATA] != ELFDATA2LSB
+ || e->e_machine != EM_386)
+ return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic");
+
+ return GRUB_ERR_NONE;
+}
+
+/* Relocate symbols. */
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+{
+ Elf_Ehdr *e = ehdr;
+ Elf_Shdr *s;
+ Elf_Word entsize;
+ unsigned i;
+
+ /* Find a symbol table. */
+ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
+ i < e->e_shnum;
+ i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
+ if (s->sh_type == SHT_SYMTAB)
+ break;
+
+ if (i == e->e_shnum)
+ return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
+
+ entsize = s->sh_entsize;
+
+ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
+ i < e->e_shnum;
+ i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
+ if (s->sh_type == SHT_REL)
+ {
+ grub_dl_segment_t seg;
+
+ /* Find the target segment. */
+ for (seg = mod->segment; seg; seg = seg->next)
+ if (seg->section == s->sh_info)
+ break;
+
+ if (seg)
+ {
+ Elf_Rel *rel, *max;
+
+ for (rel = (Elf_Rel *) ((char *) e + s->sh_offset),
+ max = rel + s->sh_size / s->sh_entsize;
+ rel < max;
+ rel++)
+ {
+ Elf_Word *addr;
+ Elf_Sym *sym;
+
+ if (seg->size < rel->r_offset)
+ return grub_error (GRUB_ERR_BAD_MODULE,
+ "reloc offset is out of the segment");
+
+ addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset);
+ sym = (Elf_Sym *) ((char *) mod->symtab
+ + entsize * ELF_R_SYM (rel->r_info));
+
+ switch (ELF_R_TYPE (rel->r_info))
+ {
+ case R_386_32:
+ *addr += sym->st_value;
+ break;
+
+ case R_386_PC32:
+ *addr += (sym->st_value - (Elf_Word) seg->addr
+ - rel->r_offset);
+ break;
+ }
+ }
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
diff --git a/kern/mipsel/qemu-r4k/init.c b/kern/mipsel/qemu-r4k/init.c
new file mode 100644
index 000000000..0600a345f
--- /dev/null
+++ b/kern/mipsel/qemu-r4k/init.c
@@ -0,0 +1,58 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+grub_uint32_t
+grub_get_rtc (void)
+{
+ static int calln = 0;
+ return calln++;
+}
+
+void
+grub_machine_init (void)
+{
+}
+
+void
+grub_machine_fini (void)
+{
+}
+
+void
+grub_exit (void)
+{
+ while (1);
+}
+
+void
+grub_halt (void)
+{
+ while (1);
+}
+
+void
+grub_reboot (void)
+{
+ while (1);
+}
+
+void
+grub_machine_set_prefix (void)
+{
+ grub_env_set ("prefix", grub_prefix);
+}
+
+extern char _start[];
+extern char _end[];
+
+grub_addr_t
+grub_arch_modules_addr (void)
+{
+ return ALIGN_UP((grub_addr_t) _end + GRUB_MOD_GAP, GRUB_MOD_ALIGN);
+}
diff --git a/kern/mipsel/qemu-r4k/startup.S b/kern/mipsel/qemu-r4k/startup.S
new file mode 100644
index 000000000..19de4779d
--- /dev/null
+++ b/kern/mipsel/qemu-r4k/startup.S
@@ -0,0 +1,55 @@
+/* startup.S - Startup code for the MIPS. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+
+.extern __bss_start
+.extern _end
+
+ .globl __start, _start, start
+__start:
+_start:
+start:
+ b codestart
+ . = _start + GRUB_KERNEL_CPU_PREFIX
+
+VARIABLE(grub_prefix)
+ /* to be filled by grub-mkelfimage */
+
+ /*
+ * Leave some breathing room for the prefix.
+ */
+
+ . = _start + GRUB_KERNEL_CPU_DATA_END
+codestart:
+ lui $t1, %hi(__bss_start)
+ addiu $t1, %lo(__bss_start)
+ lui $t2, %hi(_end)
+ addiu $t2, %lo(_end)
+
+bsscont:
+ sb $0,0($t1)
+ addiu $t1,$t1,1
+ sltu $t3,$t1,$t2
+ bne $3, $0, bsscont
+
+ li $sp, GRUB_MACHINE_MEMORY_STACK_HIGH
+ b grub_main
\ No newline at end of file
diff --git a/lib/mipsel/setjmp.S b/lib/mipsel/setjmp.S
new file mode 100644
index 000000000..e69de29bb