1/*
2 * Copyright (c) 2009 Corey Tabaka
3 * Copyright (c) 2015 Intel Corporation
4 * Copyright (c) 2016 Travis Geiselbrecht
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction,
9 * including without limitation the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25#include <asm.h>
26#include <arch/x86/descriptor.h>
27#include <arch/x86/mmu.h>
28
29/* The magic number for the Multiboot header. */
30#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
31
32/* The flags for the Multiboot header. */
33#if defined(__ELF__) && 0
34#define MULTIBOOT_HEADER_FLAGS 0x00000002
35#else
36#define MULTIBOOT_HEADER_FLAGS 0x00010002
37#endif
38
39/* The magic number passed by a Multiboot-compliant boot loader. */
40#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
41
42#define PHYS_LOAD_ADDRESS (MEMBASE + KERNEL_LOAD_OFFSET)
43#define PHYS_ADDR_DELTA (KERNEL_BASE + KERNEL_LOAD_OFFSET - PHYS_LOAD_ADDRESS)
44#define PHYS(x) ((x) - PHYS_ADDR_DELTA)
45
46.section ".text.boot"
47.global _start
48_start:
49    jmp real_start
50
51.align 4
52
53.type multiboot_header,STT_OBJECT
54multiboot_header:
55    /* magic */
56    .int MULTIBOOT_HEADER_MAGIC
57    /* flags */
58    .int MULTIBOOT_HEADER_FLAGS
59    /* checksum */
60    .int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
61
62#if !defined(__ELF__) || 1
63    /* header_addr */
64    .int PHYS(multiboot_header)
65    /* load_addr */
66    .int PHYS(_start)
67    /* load_end_addr */
68    .int PHYS(__data_end)
69    /* bss_end_addr */
70    .int PHYS(__bss_end)
71    /* entry_addr */
72    .int PHYS(real_start)
73#endif
74
75real_start:
76    cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
77    jne 0f
78    movl %ebx, PHYS(_multiboot_info)
79
800:
81    /* load our new gdt by physical pointer */
82    lgdt PHYS(_gdtr_phys)
83
84    movw $DATA_SELECTOR, %ax
85    movw %ax, %ds
86    movw %ax, %es
87    movw %ax, %fs
88    movw %ax, %ss
89    movw %ax, %gs
90    movw %ax, %ss
91
92    /* load initial stack pointer */
93    movl $PHYS(_kstack + 4096), %esp
94
95    /*We jumped here in protected mode in a code segment that migh not longer
96      be valid , do a long jump to our code segment, we use retf instead of
97      ljmp to be able to use relative labels */
98    pushl $CODE_SELECTOR     /*Pushing our code segment */
99    pushl $PHYS(.Lfarjump)   /*and jump address */
100    retf    /*This instruction will jump to codesel:farjump */
101
102.Lfarjump:
103
104    /* zero the bss section */
105bss_setup:
106    movl $PHYS(__bss_start), %edi /* starting address of the bss */
107    movl $PHYS(__bss_end), %ecx   /* find the length of the bss in bytes */
108    subl %edi, %ecx
109    shrl $2, %ecx       /* convert to 32 bit words, since the bss is aligned anyway */
1102:
111    movl $0, (%edi)
112    addl $4, %edi
113    loop 2b
114
115paging_setup:
116#ifdef PAE_MODE_ENABLED
117#error broken for now
118    /* Preparing PAE paging, we will use 2MB pages covering 1GB
119    for initial bootstrap, this page table will be 1 to 1 */
120
121    /* Setting the First PDPTE with a PD table reference*/
122    movl $pdp,   %eax
123    orl  $0x01, %eax
124    movl %eax, (pdpt)
125
126    movl $pdp, %esi
127    movl $0x1ff, %ecx
128
129fill_pdp:
130    movl $0x1ff, %eax
131    subl %ecx, %eax
132    shll $21,%eax
133    orl  $0x83, %eax
134    movl %eax, (%esi)
135    addl $8,%esi
136    loop fill_pdp
137
138    /* Set PDPT in CR3 */
139    movl $pdpt, %eax
140    mov %eax, %cr3
141
142    /* Enabling PAE*/
143    mov %cr4, %eax
144    btsl $(5), %eax
145    mov %eax, %cr4
146
147    /* Enabling Paging and from this point we are in
148    32 bit compatibility mode */
149    mov %cr0,  %eax
150    btsl $(31), %eax
151    mov %eax,  %cr0
152
153#else
154    /* map the first 1GB 1:1 */
155    movl $PHYS(pd), %esi
156    movl $0x100, %ecx
157    xor  %eax, %eax
158
159.Lfill_pd:
160    mov  %eax, %edx
161    orl  $X86_KERNEL_PD_LP_FLAGS, %edx
162    movl %edx, (%esi)
163    addl $4, %esi
164    addl $0x00400000, %eax
165    loop .Lfill_pd
166
167    /* map the first 1GB to KERNEL_ASPACE_BASE */
168    movl $(PHYS(pd) + 0x800), %esi
169    movl $0x100, %ecx
170    xor  %eax, %eax
171
172.Lfill_pd2:
173    mov  %eax, %edx
174    orl  $X86_KERNEL_PD_LP_FLAGS, %edx
175    movl %edx, (%esi)
176    addl $4, %esi
177    addl $0x00400000, %eax
178    loop .Lfill_pd2
179
180    /* Set PD in CR3 */
181    movl $PHYS(pd), %eax
182    mov %eax, %cr3
183
184    /* Enabling Paging and from this point we are in */
185    mov %cr4, %eax
186    orl $0x10, %eax
187    mov %eax, %cr4
188
189    mov %cr0,  %eax
190    btsl $(31), %eax
191    mov %eax, %cr0
192#endif
193
194    /* load the high kernel stack */
195    movl $(_kstack + 4096), %esp
196
197    /* reload the high gdtr */
198    lgdt PHYS(_gdtr)
199
200    /* branch to the high address */
201    movl $main_lk, %eax
202    jmp *%eax
203
204main_lk:
205    /* set up the idt */
206    call setup_idt
207
208    /* call the main module */
209    call lk_main
2100:                          /* just sit around waiting for interrupts */
211    hlt                     /* interrupts will unhalt the processor */
212    pause
213    jmp 0b                  /* so jump back to halt to conserve power */
214