1/** 2 * \file 3 * \brief Bootstrap the bootloader. 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <multiboot.h> 16 17#define STACK_SIZE 4096 18 19#define MSR_IA32_EFER 0xc0000080 ///< Extended features enables 20#define PAGING_ENABLE 31 21#define LONG_MODE_CS 0x0008 22#define PAE 0x20 23#define LME 8 24 25/* The flags for the Multiboot header */ 26#define MB_FLAGS (MULTIBOOT_HEADER_FLAG_MODS_PGALIGNED | MULTIBOOT_HEADER_FLAG_NEED_MEMINFO) 27 28.code32 29.text 30.globl start, halt 31 32/* Multiboot header, 4-byte aligned */ 33 .align 4 34 .long MULTIBOOT_HEADER_MAGIC /* magic */ 35 .long MB_FLAGS /* flags */ 36 .long -(MULTIBOOT_HEADER_MAGIC + MB_FLAGS) /* checksum */ 37 38start: 39 /* Initialize the stack pointer */ 40 movl $(stack + STACK_SIZE), %esp 41 42 /* Reset EFLAGS */ 43 pushl $0 44 popf 45 46 /* Enter main -- this should never return */ 47 push %ebp 48 mov %esp, %ebp 49 push %ebx /* Pointer to multiboot info struct */ 50 push %eax /* Multiboot magic value */ 51 call startup 52 53 // Load 64-bit GDT 54 mov $gdt_ptr, %esi 55 lgdt (%esi) 56 57 // enable page address extension 58 mov %cr4,%eax 59 or $PAE,%eax 60 mov %eax,%cr4 61 62 // set PML4 pointer to cr3 63 mov $boot_pml4, %eax 64 mov %eax,%cr3 65 66 // enable long-mode by setting EFER.LME 67 mov $MSR_IA32_EFER,%ecx 68 rdmsr 69 bts $LME,%eax 70 wrmsr 71 72 // enable paging 73 mov %cr0,%eax 74 bts $PAGING_ENABLE,%eax 75 mov %eax,%cr0 76 77 // Setup multiboot registers 78 mov eax, %eax 79 mov multiboot_info, %ebx 80 mov kernel_entry, %ecx 81 82 // jmp to long-mode to the linear address corresponding the 83 // real mode segment REAL_MODE_SEGMENT 84 // jmp LONG_MODE_CS:start_64 85 .byte 0xea 86 .long start_64 87 .word LONG_MODE_CS 88 89/* start the 64bit long-mode code here */ 90.code64 91start_64: 92 93 // initialize bootup stack for the 64bit long mode 94 lea (start_64_stack)(%rip), %rsp 95 // Jump to kernel image entry 96 jmp *%rcx 97 98/* Halt -- this should never be reached */ 99halt: 100 hlt 101 jmp halt 102 103/* Stack for 64bit mode */ 104 .comm stack, STACK_SIZE 105 .align 16 106 .fill STACK_SIZE,1,0 107start_64_stack: 108 109/* Global descriptor table */ 110.align 16 111gdt: 112 .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 113 .byte 0xff,0xff,0x00,0x00,0x00,0x9a,0xaf,0x00 // 64bit code segment, D _cleared_ => "16bit" 114 .byte 0xff,0xff,0x00,0x00,0x00,0x92,0xcf,0x00 // data 115 .byte 0xff,0xff,0x00,0x00,0x00,0x9a,0xcf,0x00 // 32bit code segment for protected-mode 116 .byte 0xff,0xff,0x00,0x80,0x0b,0x92,0xff,0x00 // screen 117 .byte 0xff,0xff,0x00,0x60,0x00,0x9a,0xcf,0x00 // segment at linear address 0x6000 118 .byte 0xff,0xff,0x00,0x00,0x00,0x92,0xaf,0x00 // stack segment in 64bit mode 119 120gdt_ptr: 121 .word gdt_ptr - gdt 122 .long gdt 123 .long 0 124