1/*
2 * Multiboot Entry
3 */
4
5#define STACK_SIZE 0x4000
6
7#define MULTIBOOT_HEADER_MAGIC  0x1BADB002
8#define MULTIBOOT_HEADER_FLAGS  0x00010003
9//#define KERNEL_BASE 0x0000000000000000
10#define KERNEL_BASE 0xFFFF800000000000
11#define LOWMEM(_x) (_x - KERNEL_BASE)
12
13.extern mb_entry
14
15.text
16
17/**
18 * _start --
19 *
20 *	ELF entry point.
21 */
22.globl _start
23_start: .code32
24    jmp     multiboot_entry
25
26/**
27 * This header needs to be present near the start of the ELF binary that
28 * describes how the loader should load the operating system image into memory.
29 */
30.align  4
31multiboot_header: .code32
32.long   MULTIBOOT_HEADER_MAGIC
33.long   MULTIBOOT_HEADER_FLAGS
34.long   -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
35.long   LOWMEM(multiboot_header)
36.long   LOWMEM(_start)
37.long   LOWMEM(_edata)
38.long   LOWMEM(_end)
39.long   LOWMEM(multiboot_entry)
40
41//
42// Multiboot entry
43// %eax: Magic (0x2BADB002)
44// %ebx: multiboot info structure
45//
46multiboot_entry: .code32
47    // Save multiboot magic
48    movl    %eax, %edx
49
50    // Setup the stack pointer
51    movl    $LOWMEM(lmfarptr), %edi
52    movw    $(0x7000 + 'A'), (0xB8000)
53    movl    $LOWMEM(stack + STACK_SIZE), %esp
54
55    // Reset EFLAGS to a known state
56    movw    $(0x7000 + 'B'), (0xB8002)
57    pushl   $0
58    popf
59
60    // Configure the CPU control register cr4
61    movw    $(0x7000 + 'C'), (0xB8004)
62    movl    %cr4, %eax
63    orl     $0x0000006A0, %eax
64    movl    %eax, %cr4
65
66    // Load the 32-bit page table
67    movw    $(0x7000 + 'D'), (0xB8006)
68    movl    $LOWMEM(bootpgtbl1), %eax
69    movl    %eax, %cr3
70
71    // Enable 64-bit mode (long mode) and no-execute (NX) support
72    movw    $(0x7000 + 'E'), (0xB8008)
73    movl    $0xC0000080, %ecx
74    rdmsr
75    orl     $0x0900, %eax
76    wrmsr
77
78    // Load the GDT that contains segment descriptors.
79    movw    $(0x7000 + 'E'), (0xB800A)
80    movl    $LOWMEM(bootgdtdesc), %eax
81    lgdt    (%eax)
82
83    // Configure cr0
84    movw    $(0x7000 + 'F'), (0xB800C)
85    movl    %cr0, %eax
86    orl     $0x8005002B, %eax
87    movl    %eax, %cr0
88
89    // Long jump into 64-bit mode
90    movw    $(0x7000 + '0'), (0xB800E)
91    ljmp    *(%edi)
92
93    // No we're playing with power
94lmenter: .code64
95    movw    $(0x7000 + '1'), (0xB8010)
96    xorw    %ax, %ax
97    movw    %ax, %ss
98    movw    %ax, %ds
99    movw    %ax, %es
100    movw    %ax, %fs
101    movw    %ax, %gs
102
103    movq    $LOWMEM(stack + STACK_SIZE), %rax
104    movq    $0xFFFF8000, %rcx
105    shlq    $32, %rcx
106    orq     %rcx, %rax
107    movq    %rax, %rsp
108
109    // Long jump into the high memory address where the kernel executes in
110    movq    $LOWMEM(lmhighptr), %rdi
111    jmp    *(%rdi)
112
113lmhigh:
114    movw    $(0x7000 + '2'), (0xB8012)
115
116    movq    %rdx, %rdi // Magic
117    movq    %rbx, %rsi // Multiboot info pointer
118
119    call    MachineBoot_Entry
120
121    # Print halt to the graphics memory if we return
122    movw    $(0x5000 + 'H'), (0xB8098)
123    movw    $(0x5000 + 'A'), (0xB809A)
124    movw    $(0x5000 + 'L'), (0xB809C)
125    movw    $(0x5000 + 'T'), (0xB809E)
126loop:
127    hlt
128    jmp     loop
129
130.p2align 4
131lmfarptr:
132.long   LOWMEM(lmenter)
133.word   0x08
134
135.p2align 4
136lmhighptr:
137.quad   lmhigh
138
139.p2align 12
140bootgdt:
141.quad   0x0000000000000000 /* Null */
142.quad   0x00AF9A000000FFFF /* Kernel CS */
143.quad   0x00CF92000000FFFF /* Kernel DS */
144.quad   0x0000000000000000
145.quad   0x0000000000000000
146.quad   0x0000000000000000
147.quad   0x0000000000000000
148.quad   0x0000000000000000
149
150.p2align 4
151.globl bootgdtdesc
152bootgdtdesc:
153.word   0x003F
154.quad   LOWMEM(bootgdt)
155
156// Boot stack
157.p2align 12
158.globl stack
159.comm   stack, STACK_SIZE
160
161