forked from pool/grub2
202 lines
5.4 KiB
Diff
202 lines
5.4 KiB
Diff
|
From dc0b31e8fe09b4143488e85a7aeb7c532e48f81d Mon Sep 17 00:00:00 2001
|
||
|
From: Anton Blanchard <anton@samba.org>
|
||
|
Date: Wed, 29 Jan 2014 10:40:17 +1100
|
||
|
Subject: [PATCH 14/23] Add powerpc64 ieee1275 trampoline
|
||
|
|
||
|
Add a trampoline so a 64bit grub can call a 32 bit OF
|
||
|
|
||
|
Signed-off-by: Ram Pai <linuxram@us.ibm.com>
|
||
|
From: Anton Blanchard <anton@samba.org>
|
||
|
---
|
||
|
grub-core/Makefile.core.def | 1 +
|
||
|
grub-core/kern/powerpc/ieee1275/entry.S | 150 +++++++++++++++++++++++++++++++
|
||
|
include/grub/powerpc/ieee1275/ieee1275.h | 6 ++
|
||
|
3 files changed, 157 insertions(+)
|
||
|
create mode 100644 grub-core/kern/powerpc/ieee1275/entry.S
|
||
|
|
||
|
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||
|
index 42443bc..9563eeb 100644
|
||
|
--- a/grub-core/Makefile.core.def
|
||
|
+++ b/grub-core/Makefile.core.def
|
||
|
@@ -252,6 +252,7 @@ kernel = {
|
||
|
|
||
|
powerpc_ieee1275 = kern/powerpc/cache.S;
|
||
|
powerpc_ieee1275 = kern/powerpc/dl.c;
|
||
|
+ powerpc_ieee1275 = kern/powerpc/ieee1275/entry.S;
|
||
|
|
||
|
sparc64_ieee1275 = kern/sparc64/cache.S;
|
||
|
sparc64_ieee1275 = kern/sparc64/dl.c;
|
||
|
diff --git a/grub-core/kern/powerpc/ieee1275/entry.S b/grub-core/kern/powerpc/ieee1275/entry.S
|
||
|
new file mode 100644
|
||
|
index 0000000..5d58149
|
||
|
--- /dev/null
|
||
|
+++ b/grub-core/kern/powerpc/ieee1275/entry.S
|
||
|
@@ -0,0 +1,150 @@
|
||
|
+/* entry.S - open firmware call entry and return */
|
||
|
+/*
|
||
|
+ * GRUB -- GRand Unified Bootloader
|
||
|
+ * Copyright (C) 2004,2007,2010,2014 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 <ppc-asm.h>
|
||
|
+
|
||
|
+#define STACK_FRAME_SIZE (48 + 64 + 16 + 144)
|
||
|
+#define MSR_OFFSET (48 + 64)
|
||
|
+#define R13_OFFSET (MSR_OFFSET + 8)
|
||
|
+#define NVREG_OFFSET(i) (STACK_FRAME_SIZE - (32-(i))*8)
|
||
|
+#define SAVE_NVGPR(A) std (A),NVREG_OFFSET(A)(r1)
|
||
|
+#define REST_NVGPR(A) ld (A),NVREG_OFFSET(A)(r1)
|
||
|
+#define SPRN_SRR0 0x01A
|
||
|
+#define SPRN_SRR1 0x01B
|
||
|
+#define r1 sp
|
||
|
+
|
||
|
+
|
||
|
+#if defined(_CALL_ELF) && _CALL_ELF == 1 /* BIG ENDIAN */
|
||
|
+#define TOC_OFFSET 40
|
||
|
+#define r2 toc
|
||
|
+#endif
|
||
|
+
|
||
|
+/*
|
||
|
+ * OF runs in 32 bit mode so it clobbers the high 32 bits of all registers
|
||
|
+ * it saves. We save and restore all the non volatile registers to avoid
|
||
|
+ * this issue.
|
||
|
+ *
|
||
|
+ * unsigned int ieee1275_call_entry_fn(void *args, unsigned long entry);
|
||
|
+ */
|
||
|
+FUNC_START(ieee1275_call_entry_fn)
|
||
|
+ mflr r0
|
||
|
+ std r0,16(r1)
|
||
|
+ stdu r1,-STACK_FRAME_SIZE(r1)
|
||
|
+
|
||
|
+#if defined(_CALL_ELF) && _CALL_ELF == 1 /* BIG ENDIAN */
|
||
|
+ std r2,TOC_OFFSET(r1)
|
||
|
+#endif
|
||
|
+ std r13,R13_OFFSET(r1)
|
||
|
+
|
||
|
+ SAVE_NVGPR(r14)
|
||
|
+ SAVE_NVGPR(r15)
|
||
|
+ SAVE_NVGPR(r16)
|
||
|
+ SAVE_NVGPR(r17)
|
||
|
+ SAVE_NVGPR(r18)
|
||
|
+ SAVE_NVGPR(r19)
|
||
|
+ SAVE_NVGPR(r20)
|
||
|
+ SAVE_NVGPR(r21)
|
||
|
+ SAVE_NVGPR(r22)
|
||
|
+ SAVE_NVGPR(r23)
|
||
|
+ SAVE_NVGPR(r24)
|
||
|
+ SAVE_NVGPR(r25)
|
||
|
+ SAVE_NVGPR(r26)
|
||
|
+ SAVE_NVGPR(r27)
|
||
|
+ SAVE_NVGPR(r28)
|
||
|
+ SAVE_NVGPR(r29)
|
||
|
+ SAVE_NVGPR(r30)
|
||
|
+ SAVE_NVGPR(r31)
|
||
|
+
|
||
|
+ mfmsr r31
|
||
|
+ std r31, MSR_OFFSET(r1)
|
||
|
+
|
||
|
+ /* Clear 64bit mode */
|
||
|
+ rldicl r31,r31,0,1
|
||
|
+
|
||
|
+#if defined(_CALL_ELF) && _CALL_ELF == 2 /* LITTLE ENDIAN */
|
||
|
+ /* Clear LE mode */
|
||
|
+ rldicr r31,r31,0,62
|
||
|
+#endif
|
||
|
+
|
||
|
+ mtspr SPRN_SRR0,r4
|
||
|
+ mtspr SPRN_SRR1,r31
|
||
|
+
|
||
|
+ /* Point the LR at our return code */
|
||
|
+ bl 1f
|
||
|
+1: mflr r30
|
||
|
+ addi r30,r30,(2f - 1b)
|
||
|
+ mtlr r30
|
||
|
+
|
||
|
+ /* Call OF */
|
||
|
+ rfid
|
||
|
+
|
||
|
+#if defined(_CALL_ELF) && _CALL_ELF == 2 /* LITTLE ENDIAN */
|
||
|
+2: .long 0x05009f42 /* bcl 20,31,$+4 */
|
||
|
+ .long 0xa602487d /* mflr r10 */
|
||
|
+ .long 0x1c004a39 /* addi r10,r10,28 */
|
||
|
+ .long 0xa6035a7d /* mtsrr0 r10 */
|
||
|
+ .long 0xa600407d /* mfmsr r10 */
|
||
|
+ .long 0x01004a69 /* xori r10,r10,1 */
|
||
|
+ .long 0xa6035b7d /* mtsrr1 r10 */
|
||
|
+ .long 0x2400004c /* rfid */
|
||
|
+#endif
|
||
|
+
|
||
|
+ /* Clear the top 32 bits of r1, just in case */
|
||
|
+2: rldicl r1,r1,0,32
|
||
|
+
|
||
|
+ /* Reset our MSR */
|
||
|
+ ld r31,MSR_OFFSET(r1)
|
||
|
+ mtspr SPRN_SRR1,r31
|
||
|
+
|
||
|
+ bl 3f
|
||
|
+3: mflr r30
|
||
|
+ addi r30,r30,(4f - 3b)
|
||
|
+ mtspr SPRN_SRR0,r30
|
||
|
+
|
||
|
+ rfid
|
||
|
+
|
||
|
+#if defined(_CALL_ELF) && _CALL_ELF == 1 /* BIG ENDIAN */
|
||
|
+4: ld r2,TOC_OFFSET(r1)
|
||
|
+#endif
|
||
|
+4: ld r13,R13_OFFSET(r1)
|
||
|
+
|
||
|
+ REST_NVGPR(r14)
|
||
|
+ REST_NVGPR(r15)
|
||
|
+ REST_NVGPR(r16)
|
||
|
+ REST_NVGPR(r17)
|
||
|
+ REST_NVGPR(r18)
|
||
|
+ REST_NVGPR(r19)
|
||
|
+ REST_NVGPR(r20)
|
||
|
+ REST_NVGPR(r21)
|
||
|
+ REST_NVGPR(r22)
|
||
|
+ REST_NVGPR(r23)
|
||
|
+ REST_NVGPR(r24)
|
||
|
+ REST_NVGPR(r25)
|
||
|
+ REST_NVGPR(r26)
|
||
|
+ REST_NVGPR(r27)
|
||
|
+ REST_NVGPR(r28)
|
||
|
+ REST_NVGPR(r29)
|
||
|
+ REST_NVGPR(r30)
|
||
|
+ REST_NVGPR(r31)
|
||
|
+
|
||
|
+ addi r1,r1,STACK_FRAME_SIZE
|
||
|
+ ld r0,16(r1)
|
||
|
+ mtlr r0
|
||
|
+ blr
|
||
|
+FUNC_END(ieee1275_call_entry_fn)
|
||
|
diff --git a/include/grub/powerpc/ieee1275/ieee1275.h b/include/grub/powerpc/ieee1275/ieee1275.h
|
||
|
index 3c7683f..14bdc43 100644
|
||
|
--- a/include/grub/powerpc/ieee1275/ieee1275.h
|
||
|
+++ b/include/grub/powerpc/ieee1275/ieee1275.h
|
||
|
@@ -25,4 +25,10 @@
|
||
|
#define GRUB_IEEE1275_CELL_SIZEOF 4
|
||
|
typedef grub_uint32_t grub_ieee1275_cell_t;
|
||
|
|
||
|
+#ifdef __powerpc64__
|
||
|
+int EXPORT_FUNC(ieee1275_call_entry_fn)(void *args, void *entry);
|
||
|
+#define IEEE1275_CALL_ENTRY_FN(args) \
|
||
|
+ ieee1275_call_entry_fn((args), grub_ieee1275_entry_fn)
|
||
|
+#endif
|
||
|
+
|
||
|
#endif /* ! GRUB_IEEE1275_MACHINE_HEADER */
|
||
|
--
|
||
|
1.8.3.1
|