aboutsummaryrefslogtreecommitdiff
path: root/kernel/boot/boot.S
blob: bb3cbef9cd4b9e288e9b9ecaf11090650ec948dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
.file "boot.S"

#define ASM_FILE 1
#include "multiboot.h"
#include "boot/config.h"
#undef ASM_FILE
#define AOUT_KLUDGE MULTIBOOT_AOUT_KLUDGE
#define PHYSADDR(x) (x - 0xffff800000000000)

.global entry, _start, initial_page_table

.code32
.set ARCH, 0
.set CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + ARCH + (multiboot_header_end - multiboot_header))

/* This header tells GRUB we can be run */
.section .multiboot
.align 8
multiboot_header:
    .long MULTIBOOT2_HEADER_MAGIC
    .long ARCH
    .long multiboot_header_end - multiboot_header
    .long CHECKSUM


.align 8
address_tag_start:
    .short MULTIBOOT_HEADER_TAG_ADDRESS
    .short MULTIBOOT_HEADER_TAG_OPTIONAL
    .long address_tag_end - address_tag_start
    .long PHYSADDR(multiboot_header) /*  header_addr = beginning of MB header */
    .long PHYSADDR(k_start) /*  load_addr = beginning of .text */
    .long PHYSADDR(_edata)  /*  load_end_addr = end of .data */
    .long PHYSADDR(_end)  /*  bss_end_addr = end of .bss */
address_tag_end:

.align 8
entry_address_tag_start:
    .short MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS
    .short MULTIBOOT_HEADER_TAG_OPTIONAL
    .long entry_address_tag_end - entry_address_tag_start
    .long PHYSADDR(_start) /*  entry_addr */
entry_address_tag_end:

#if 0
.align 8
framebuffer_tag_start:
    .short 5
    .short 0
    .long frame_buffer_tag_end - framebuffer_tag_start
    .long 0 // 1280
    .long 0 // 720
    .long 0 // 32
frame_buffer_tag_end:
#endif

.align 8
.short MULTIBOOT_HEADER_TAG_END
    .short 0
    .long 8
multiboot_header_end:


_start:
    // disable interrupts during boot
    cli

    // Take the multiboot information and store it somewhere.
    movl    $PHYSADDR(sys_stack_bottom), %esp

    // reset the stack flags
    pushl $0
    popf

    // set base pointer
    movl    %esp, %ebp

    // pushl   %eax
    pushl   $0x0
    pushl   %ebx /* Stash the meminfo for later */

    // Set up the gdt
    lgdt PHYSADDR(GDTPointer)

    // set cr3 = start of PML4
    mov $PHYSADDR(pml4), %eax
    mov %eax, %cr3

    // enable PAE
    mov %cr4, %eax
    or $0x20, %eax
    mov %eax, %cr4

    // enter long mode
    mov $0xC0000080, %ecx
    rdmsr
    or $0x101, %eax
    wrmsr

    // Enable paging
    movl    %cr0, %eax
    or     $0x80000000, %eax
    movl    %eax, %cr0

    // jump into 64 bit code
    ljmp $0x08, $PHYSADDR(_trampoline)

.code64

// for some god-knows why reason, GDB wont set up breakpoints correctly without this trampoline
// even though Weenix still runs if you ljmp directly into _start64 -_-
_trampoline:
    // paging is at this point enabled, so no more need more PHYSADDR() wrappers
    movabsq $_start64, %rax
    jmp *%rax

_start64:
    // move the stack pointer to himem so that it is valid once we delete the low map
    movq $KERNEL_VMA, %rax
    addq %rax, %rsp
    addq %rax, %rbp
    
    popq %rbx
    movq %rbx, %r11

    // set up sregs
    movq $0x0, %rax
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %ss
    mov %ax, %fs
    mov %ax, %gs

    mov %r11, %rdi
    // now we jump into the C entrypoint.
    call entry
    cli
    hlt // when its done, we are done
// [+] TODO we dont actually set the stack pointer anywhere here???

.align 16
GDT64:
    GDTNull:
        .quad 0
    GDTKernelCode:
        // base = 0x0, limit = 0x0
        // flags: present, ring 0, executable, readable, 64bit
        .word 0, 0
        .byte 0, 0x9a, 0x20, 0
    GDTEnd:
    GDTPointer:
        .word GDTEnd - GDT64 - 1 // size of gdt - 1
        .long PHYSADDR(GDT64) // pointer to gdt

.code32
.data
sys_stack: // set up 1KB stack
    .align 4
    .skip 0x1000
sys_stack_bottom:

.align 0x1000
initial_page_table: // maps first 1GB of RAM to both 0x0000000000000000 and 0xffff800000000000
pml4:
    .quad PHYSADDR(pdpt) + 3 // 0x0000000000000000
    .fill 255,8,0
    .quad PHYSADDR(pdpt) + 3 // 0xffff800000000000
    .fill 255,8,0
pdpt:
    .quad 0x0000000000000083 // 0
    .fill 511,8,0