aboutsummaryrefslogtreecommitdiff
path: root/i686/boot.s
blob: 40b03892b08eff84f8787e90bda97f29831dcee8 (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
/* The magic field should contain this.  */
.set MULTIBOOT2_HEADER_MAGIC,           0xe85250d6
/* This should be in %eax.  */
.set MULTIBOOT2_BOOTLOADER_MAGIC,       0x36d76289
.set MULTIBOOT_ARCHITECTURE_I386,       0
.set MULTIBOOT_HEADER_TAG_END,          0
.set MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST, 1
.set MULTIBOOT_TAG_TYPE_MMAP,           6

.set PAGE_RO, 0x001
.set PAGE_RW, 0x003

/* write section to page table macro
 *
 * Registers used:
 * %ecx: loop counter   [ set to $1024 ]
 * %edx: temporary
 * %esi: current page being mapped
 * %edi: page entry     [ set to $page_addr ]
 */
.macro mmap_section begin, end, access
    mov  $\begin, %esi  # from $begin
1:  cmpl $\end, %esi    # until $end
    jge  2f

    movl %esi, %edx
    orl  $\access, %edx
    movl %edx, (%edi)

    addl $4096, %esi    # move to next page
    addl $4, %edi       # size of page entry is 4 bytes
    loop 1b             # loop according to %ecx
2:
.endm

/* Declare a multiboot header that marks this program as a kernel */
.section .multiboot.header, "a"
header_begin:
.align 8
    .int MULTIBOOT2_HEADER_MAGIC
    .int MULTIBOOT_ARCHITECTURE_I386
    .int header_end - header_begin
    .int -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + (header_end - header_begin))

.align 8
header_info_begin:
    .short MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
    .short 0 # flags
    .int header_info_end - header_info_begin
    .int MULTIBOOT_TAG_TYPE_MMAP
header_info_end:

.align 8
    .short MULTIBOOT_HEADER_TAG_END
    .short 0
    .int 8
header_end:

.section .multiboot.pages, "aw", @nobits
.align 4096
bootstrap_page0:
    .skip 1024 * 4

.section .multiboot.text, "ax"
.extern k_pagedir
.extern k_stack
.extern k_init

#.global __vaddr_base
#.set __vaddr_base, 0xc0000000
#.global __vaddr_offset
.set __vaddr_offset, 0xc0000000 - 0x2000

.global _start
.type _start, @function
_start:
    cli

    # check multiboot header
    cmp $MULTIBOOT2_BOOTLOADER_MAGIC, %eax
    jz c
    hlt

c:  mov $k_stack - __vaddr_offset, %esp

    push %ebx  # pointer to multiboot structure
    call __multiboot2

    # mmap multiboot section into bootstrap page
    movl $bootstrap_page0, %edi
    movl $1024, %ecx
    mmap_section __multiboot_begin, __multiboot_end, PAGE_RW
    mmap_section (__text_begin - __vaddr_offset), (__text_end - __vaddr_offset), PAGE_RO
    mmap_section (__rodata_begin - __vaddr_offset), (__rodata_end - __vaddr_offset), PAGE_RO
    mmap_section (__bss_begin - __vaddr_offset), (__bss_end - __vaddr_offset), PAGE_RW
    mmap_section (__data_begin - __vaddr_offset), (__data_end - __vaddr_offset), PAGE_RW

    # mmap all the other section into k_ptable0x300
    movl $(k_ptable0x300 - __vaddr_offset), %edi
    movl $1024, %ecx
    mmap_section (__text_begin - __vaddr_offset),   (__text_end - __vaddr_offset),   PAGE_RO
    mmap_section (__rodata_begin - __vaddr_offset), (__rodata_end - __vaddr_offset), PAGE_RO
    mmap_section (__bss_begin - __vaddr_offset),    (__bss_end - __vaddr_offset),    PAGE_RW
    mmap_section (__data_begin - __vaddr_offset),   (__data_end - __vaddr_offset),   PAGE_RW

    movl $(bootstrap_page0 + PAGE_RW), k_pagedir - __vaddr_offset + 0 * 4
    movl $(k_ptable0x300 - __vaddr_offset + PAGE_RW), k_pagedir - __vaddr_offset + 768 * 4

    movl $(k_pagedir - __vaddr_offset), %ecx
    movl %ecx, %cr3

    # enable paging and the write-protect bit
    movl %cr0, %ecx
    orl  $0x80010000, %ecx
    movl %ecx, %cr0

    # jump to higher half with an absolute jump
    lea (k_init), %ecx
    jmp *%ecx