]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
relocator dor mips
authorphcoder <phcoder@debian.bg45.phnet>
Sun, 11 Oct 2009 21:00:22 +0000 (23:00 +0200)
committerphcoder <phcoder@debian.bg45.phnet>
Sun, 11 Oct 2009 21:00:22 +0000 (23:00 +0200)
conf/mips.rmk
include/grub/mips/relocator.h [new file with mode: 0644]
kern/mips/qemu-mipssim/startup.S
lib/mips/relocator.c [new file with mode: 0644]
lib/mips/relocator_asm.S [new file with mode: 0644]

index 6ebd7d665b56c06228a7fa6cf6cd3af077811404..46b74d68f4e2f0598c5845cc024755eb78d179ab 100644 (file)
@@ -140,4 +140,11 @@ pci_mod_SOURCES = bus/pci.c
 pci_mod_CFLAGS = $(COMMON_CFLAGS)
 pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For relocator.mod.
+pkglib_MODULES += relocator.mod
+relocator_mod_SOURCES = lib/$(target_cpu)/relocator.c lib/$(target_cpu)/relocator_asm.S
+relocator_mod_CFLAGS = $(COMMON_CFLAGS)
+relocator_mod_ASFLAGS = $(COMMON_ASFLAGS)
+relocator_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff --git a/include/grub/mips/relocator.h b/include/grub/mips/relocator.h
new file mode 100644 (file)
index 0000000..838ef83
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_RELOCATOR_CPU_HEADER
+#define GRUB_RELOCATOR_CPU_HEADER      1
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+struct grub_relocator32_state
+{
+  /* gpr[0] is ignored since it's hardwired to 0.  */
+  grub_uint32_t gpr[32];
+  /* Register holding target $pc.  */
+  int jumpreg;
+};
+
+void *grub_relocator32_alloc (grub_size_t size);
+grub_err_t grub_relocator32_boot (void *relocator, grub_uint32_t dest,
+                                 struct grub_relocator32_state state);
+void *grub_relocator32_realloc (void *relocator, grub_size_t size);
+void grub_relocator32_free (void *relocator);
+
+#endif /* ! GRUB_RELOCATOR_CPU_HEADER */
index 19de4779dc4b547700a678fdad39df5cdcfa5026..36c5fabd7a6d042923912243a13edabbc91163ee 100644 (file)
@@ -49,7 +49,7 @@ bsscont:
        sb $0,0($t1)
        addiu $t1,$t1,1
        sltu $t3,$t1,$t2
-       bne $3, $0, bsscont
+       bne $t3, $t0, bsscont
 
        li $sp, GRUB_MACHINE_MEMORY_STACK_HIGH
        b grub_main
\ No newline at end of file
diff --git a/lib/mips/relocator.c b/lib/mips/relocator.c
new file mode 100644 (file)
index 0000000..4ec7f6c
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+#include <grub/types.h>
+#include <grub/types.h>
+#include <grub/err.h>
+
+#include <grub/mips/relocator.h>
+
+/* Remark: doesn't work with source outside of 4G.
+   Use relocator64 in this case. 
+ */
+
+extern grub_uint8_t grub_relocator32_forward_start;
+extern grub_uint8_t grub_relocator32_forward_end;
+extern grub_uint8_t grub_relocator32_backward_start;
+extern grub_uint8_t grub_relocator32_backward_end;
+
+#define REGW_SIZEOF (2 * sizeof (grub_uint32_t))
+#define JUMP_SIZEOF (sizeof (grub_uint32_t))
+
+#define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator32_##x##_end \
+                                - &grub_relocator32_##x##_start)
+#define RELOCATOR_SIZEOF(x)    (RELOCATOR_SRC_SIZEOF(x) \
+                                + REGW_SIZEOF * (31 + 3) + JUMP_SIZEOF)
+#define RELOCATOR_ALIGN 16
+
+#define PREFIX(x) grub_relocator32_ ## x
+
+static void
+write_reg (int regn, grub_uint32_t val, void **target)
+{
+  /* lui $r, (val+0x8000).  */
+  *(grub_uint32_t *) *target = ((0x3c00 | regn) << 16) | ((val + 0x8000) >> 16);
+  *target = ((grub_uint32_t *) *target) + 1;
+  /* addiu $r, $r, val. */
+  *(grub_uint32_t *) *target = (((0x2400 | regn << 5 | regn) << 16)
+                               | ((val + 0x8000) >> 16));
+  *target = ((grub_uint32_t *) *target) + 1;
+}
+
+static void
+write_jump (int regn, void **target)
+{
+  /* j $r.  */
+  *(grub_uint32_t *) *target = (regn<<21) | 0x8;
+  *target = ((grub_uint32_t *) *target) + 1;
+}
+
+static void
+write_call_relocator_bw (void *ptr0, void *src, grub_uint32_t dest,
+                        grub_size_t size, struct grub_relocator32_state state)
+{
+  void *ptr = ptr0;
+  int i;
+  write_reg (1, (grub_uint32_t) src, &ptr);
+  write_reg (2, dest, &ptr);
+  write_reg (3, size, &ptr);
+  grub_memcpy (ptr, &grub_relocator32_backward_start,
+              RELOCATOR_SRC_SIZEOF (backward));
+  for (i = 1; i < 32; i++)
+    write_reg (i, state.gpr[i], &ptr);
+  write_jump (state.jumpreg, &ptr);
+  ((void (*) ())ptr0) ();
+}
+
+static void
+write_call_relocator_fw (void *ptr0, void *src, grub_uint32_t dest,
+                        grub_size_t size, struct grub_relocator32_state state)
+{
+  void *ptr = ptr0;
+  int i;
+  write_reg (1, (grub_uint32_t) src, &ptr);
+  write_reg (2, dest, &ptr);
+  write_reg (3, size, &ptr);
+  grub_memcpy (ptr, &grub_relocator32_forward_start,
+              RELOCATOR_SRC_SIZEOF (forward));
+  for (i = 1; i < 32; i++)
+    write_reg (i, state.gpr[i], &ptr);
+  write_jump (state.jumpreg, &ptr);
+  ((void (*) ())ptr0) ();
+}
+
+#include "../relocator.c"
diff --git a/lib/mips/relocator_asm.S b/lib/mips/relocator_asm.S
new file mode 100644 (file)
index 0000000..607a463
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+
+#ifdef BACKWARD
+#define RELOCATOR_VARIABLE(x) VARIABLE(grub_relocator32_backward_ ## x)
+#else
+#define RELOCATOR_VARIABLE(x) VARIABLE(grub_relocator32_forward_ ## x)
+#endif
+       
+       .p2align        4       /* force 16-byte alignment */
+
+VARIABLE (grub_relocator32_forward_start)
+copycont1:     
+       lb $4,0($1)
+       sb $4,0($2)
+       addiu $3, $3, 0xffff
+       subu $4,$3,$0
+       bne $4, $0, copycont1
+VARIABLE (grub_relocator32_forward_end)
+
+VARIABLE (grub_relocator32_backward_start)
+       addu $2, $2, $3
+       addu $1, $1, $3
+       /* Backward movsl is implicitly off-by-one.  compensate that.  */
+       addiu $2, $2, 0xffff
+       addiu $1, $1, 0xffff
+copycont2:     
+       lb $4,0($1)
+       sb $4,0($2)
+       addiu $3, 0xffff
+       subu $4,$3,$0
+       bne $4, $0, copycont2
+VARIABLE (grub_relocator32_backward_end)