summaryrefslogtreecommitdiffstats
path: root/grub-core/lib/i386/relocator_common.S
diff options
context:
space:
mode:
Diffstat (limited to 'grub-core/lib/i386/relocator_common.S')
-rw-r--r--grub-core/lib/i386/relocator_common.S111
1 files changed, 111 insertions, 0 deletions
diff --git a/grub-core/lib/i386/relocator_common.S b/grub-core/lib/i386/relocator_common.S
new file mode 100644
index 0000000..1b5210d
--- /dev/null
+++ b/grub-core/lib/i386/relocator_common.S
@@ -0,0 +1,111 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009,2010 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/i386/memory.h>
+
+#ifdef __x86_64__
+#define RAX %rax
+#define RSI %rsi
+#else
+#define RAX %eax
+#define RSI %esi
+#endif
+
+ .macro DISABLE_PAGING
+
+ movl %cr0, %eax
+ andl $(~GRUB_MEMORY_CPU_CR0_PAGING_ON), %eax
+ movl %eax, %cr0
+ .endm
+
+ .macro PREAMBLE
+LOCAL(base):
+ /* %rax contains now our new 'base'. */
+ mov RAX, RSI
+
+#if defined (__APPLE__) && defined (__x86_64__)
+ leaq LOCAL(cont0) (%rip), RAX
+#elif defined (__APPLE__)
+ LOCAL(cont0_offset) = LOCAL(cont0) - LOCAL(base)
+ add $LOCAL(cont0_offset), RAX
+#else
+ add $(LOCAL(cont0) - LOCAL(base)), RAX
+#endif
+ jmp *RAX
+LOCAL(cont0):
+ .endm
+
+ .macro RELOAD_GDT
+#ifdef __APPLE__
+ LOCAL(cont1_offset) = LOCAL(cont1) - LOCAL(base)
+ LOCAL(jump_vector_offset) = LOCAL(jump_vector) - LOCAL(base)
+ LOCAL(gdt_offset) = LOCAL(gdt) - LOCAL(base)
+ LOCAL(gdt_addr_offset) = LOCAL(gdt_addr) - LOCAL(base)
+ LOCAL(gdtdesc_offset) = LOCAL(gdtdesc) - LOCAL(base)
+
+ lea LOCAL(cont1_offset) (RSI, 1), RAX
+ movl %eax, LOCAL(jump_vector_offset) (RSI, 1)
+
+ lea LOCAL(gdt_offset) (RSI, 1), RAX
+ mov RAX, (LOCAL(gdt_addr_offset)) (RSI, 1)
+
+ /* Switch to compatibility mode. */
+ lgdt (LOCAL(gdtdesc_offset)) (RSI, 1)
+
+ /* Update %cs. */
+ ljmp *(LOCAL(jump_vector_offset)) (RSI, 1)
+ .p2align 4
+LOCAL(gdtdesc):
+ LOCAL(gdtsize) = LOCAL(gdt_end) - LOCAL(gdt)
+ .word LOCAL(gdtsize)
+#else
+ lea (LOCAL(cont1) - LOCAL(base)) (RSI, 1), RAX
+ movl %eax, (LOCAL(jump_vector) - LOCAL(base)) (RSI, 1)
+
+ lea (LOCAL(gdt) - LOCAL(base)) (RSI, 1), RAX
+ mov RAX, (LOCAL(gdt_addr) - LOCAL(base)) (RSI, 1)
+
+ /* Switch to compatibility mode. */
+ lgdt (LOCAL(gdtdesc) - LOCAL(base)) (RSI, 1)
+
+ /* Update %cs. */
+ ljmp *(LOCAL(jump_vector) - LOCAL(base)) (RSI, 1)
+
+ .p2align 4
+LOCAL(gdtdesc):
+ .word LOCAL(gdt_end) - LOCAL(gdt)
+#endif
+LOCAL(gdt_addr):
+#ifdef __x86_64__
+ /* Filled by the code. */
+ .quad 0
+#else
+ /* Filled by the code. */
+ .long 0
+#endif
+
+ .p2align 4
+LOCAL(jump_vector):
+ /* Jump location. Is filled by the code */
+ .long 0
+ .long CODE_SEGMENT
+
+LOCAL(cont1):
+ .endm