2N/A/*
2N/A * GRUB -- GRand Unified Bootloader
2N/A * Copyright (C) 2009,2010 Free Software Foundation, Inc.
2N/A *
2N/A * GRUB is free software: you can redistribute it and/or modify
2N/A * it under the terms of the GNU General Public License as published by
2N/A * the Free Software Foundation, either version 3 of the License, or
2N/A * (at your option) any later version.
2N/A *
2N/A * GRUB is distributed in the hope that it will be useful,
2N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of
2N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2N/A * GNU General Public License for more details.
2N/A *
2N/A * You should have received a copy of the GNU General Public License
2N/A * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
2N/A */
2N/A
2N/A#define CODE32_SEGMENT 0x18
2N/A#define CODE_SEGMENT 0x08
2N/A
2N/A/* The data segment of the protected mode. */
2N/A#define DATA_SEGMENT 0x10
2N/A
2N/A#include "relocator_common.S"
2N/A
2N/A .p2align 4 /* force 16-byte alignment */
2N/A
2N/AVARIABLE(grub_relocator64_start)
2N/A PREAMBLE
2N/A#ifndef __x86_64__
2N/A DISABLE_PAGING
2N/A
2N/A /* Turn on PAE. */
2N/A movl %cr4, %eax
2N/A orl $(GRUB_MEMORY_CPU_CR4_PAE_ON | GRUB_MEMORY_CPU_CR4_PSE_ON), %eax
2N/A movl %eax, %cr4
2N/A
2N/A /* mov imm32, %eax */
2N/A .byte 0xb8
2N/AVARIABLE(grub_relocator64_cr3)
2N/A .long 0
2N/A movl %eax, %cr3
2N/A
2N/A /* Turn on amd64. */
2N/A movl $GRUB_MEMORY_CPU_AMD64_MSR, %ecx
2N/A rdmsr
2N/A orl $GRUB_MEMORY_CPU_AMD64_MSR_ON, %eax
2N/A wrmsr
2N/A
2N/A /* Enable paging. */
2N/A movl %cr0, %eax
2N/A orl $GRUB_MEMORY_CPU_CR0_PAGING_ON, %eax
2N/A movl %eax, %cr0
2N/A
2N/A RELOAD_GDT
2N/A#else
2N/A /* mov imm64, %rax */
2N/A .byte 0x48
2N/A .byte 0xb8
2N/AVARIABLE(grub_relocator64_cr3)
2N/A .quad 0
2N/A movq %rax, %cr3
2N/A#endif
2N/A
2N/A .code64
2N/A
2N/A /* mov imm64, %rax */
2N/A .byte 0x48
2N/A .byte 0xb8
2N/AVARIABLE(grub_relocator64_rsp)
2N/A .quad 0
2N/A
2N/A movq %rax, %rsp
2N/A
2N/A /* mov imm64, %rax */
2N/A .byte 0x48
2N/A .byte 0xb8
2N/AVARIABLE(grub_relocator64_rsi)
2N/A .quad 0
2N/A
2N/A movq %rax, %rsi
2N/A
2N/A /* mov imm64, %rax */
2N/A .byte 0x48
2N/A .byte 0xb8
2N/AVARIABLE(grub_relocator64_rax)
2N/A .quad 0
2N/A
2N/A /* mov imm64, %rbx */
2N/A .byte 0x48
2N/A .byte 0xbb
2N/AVARIABLE(grub_relocator64_rbx)
2N/A .quad 0
2N/A
2N/A /* mov imm64, %rcx */
2N/A .byte 0x48
2N/A .byte 0xb9
2N/AVARIABLE(grub_relocator64_rcx)
2N/A .quad 0
2N/A
2N/A /* mov imm64, %rdx */
2N/A .byte 0x48
2N/A .byte 0xba
2N/AVARIABLE(grub_relocator64_rdx)
2N/A .quad 0
2N/A
2N/A /* Cleared direction flag is of no problem with any current
2N/A payload and makes this implementation easier. */
2N/A cld
2N/A
2N/A jmp *LOCAL(jump_addr) (%rip)
2N/A
2N/ALOCAL(jump_addr):
2N/AVARIABLE(grub_relocator64_rip)
2N/A .quad 0
2N/A
2N/A#ifndef __x86_64__
2N/A .p2align 4
2N/ALOCAL(gdt):
2N/A /* NULL. */
2N/A .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2N/A
2N/A /* 64-bit segment. */
2N/A .word 0xffff /* Limit xffff. */
2N/A .word 0x0000 /* Base xxxx0000. */
2N/A .byte 0x00 /* Base xx00xxxx. */
2N/A .byte (0x8 /* Type 8. */ | (1 << 4) /* Code. */ \
2N/A | (0 << 5) /* Ring 0. */ | (1 << 7) /* Present. */)
2N/A .byte (0xf /* Limit fxxxx. */ | (0 << 4) /* AVL flag. */ \
2N/A | (1 << 5) /* 64-bit. */ | (0 << 6) \
2N/A | (1 << 7) /* 4K granular. */)
2N/A .byte 0x00 /* Base 00xxxxxx. */
2N/A
2N/A /* Data segment*/
2N/A .word 0xffff /* Limit xffff. */
2N/A .word 0x0000 /* Base xxxx0000. */
2N/A .byte 0x00 /* Base xx00xxxx. */
2N/A .byte (0x0 /* Type 0. */ | (0 << 4) /* Data. */ \
2N/A | (0 << 5) /* Ring 0. */ | (1 << 7) /* Present. */)
2N/A .byte (0xf /* Limit fxxxx. */ | (0 << 4) /* AVL flag. */ \
2N/A | (0 << 5) /* Data. */ | (0 << 6) \
2N/A | (1 << 7) /* 4K granular. */)
2N/A .byte 0x00 /* Base 00xxxxxx. */
2N/A
2N/A /* Compatibility segment. */
2N/A .word 0xffff /* Limit xffff. */
2N/A .word 0x0000 /* Base xxxx0000. */
2N/A .byte 0x00 /* Base xx00xxxx. */
2N/A .byte (0x8 /* Type 8. */ | (1 << 4) /* Code. */ \
2N/A | (0 << 5) /* Ring 0. */ | (1 << 7) /* Present. */)
2N/A .byte (0xf /* Limit fxxxx. */ | (0 << 4) /* AVL flag. */ \
2N/A | (0 << 5) /* 32-bit. */ | (1 << 6) /* 32-bit. */ \
2N/A | (1 << 7) /* 4K granular. */)
2N/A .byte 0x00 /* Base 00xxxxxx. */
2N/A
2N/ALOCAL(gdt_end):
2N/A#endif
2N/A
2N/AVARIABLE(grub_relocator64_end)