Initial project.
[marionette.git] / kernel / start.S
blob64007ee90089a7158ed7f37a115b5fcb345c433c
1 /*
2  *    Copyright (c) 2008 Joshua Phillips. All rights reserved.
3  *  
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions are
6  *  met:
7  *  
8  *    1. Redistributions of source code must retain the above copyright
9  *       notice, this list of conditions and the following disclaimer.
10  *    2. Redistributions in binary form must reproduce the above copyright
11  *       notice, this list of conditions and the following disclaimer in
12  *       the documentation and/or other materials provided with the
13  *       distribution.
14  *  
15  *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
16  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  *  DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
19  *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  *  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  *  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  *  This file contains the multiboot header and the startup code
28  *  that is called by the bootloader.
29  */
31 .global _start
33 STACK_SIZE = 0x4000
35 .section multiboot, "a"
37 /* multiboot header */
38 mb_header:
39 .int 0x1BADB002   /* magic */
40 .int 0x00010003   /* flags */
41 .int 0xE4514FFB   /* checksum */
42 .int mb_header    /* header_addr */
43 .int _text_start  /* load_addr */
44 .int _edata       /* load_end_addr */
45 .int _end         /* bss_end_addr */
46 .int _start       /* entry_addr */
47 .int 1            /* mode_type (EGA text) */
48 .int 80           /* width */
49 .int 25           /* height */
50 .int 0            /* depth */
52 .section startup, "ax"
54 get_freemem_start:
55     /* return start of free memory, after kernel image and modules */
56     /* mb_info in %ebx */
57     
58     /* find end of kernel image, rounded up to page boundary */
59     movl $_end,%eax
60     testl $0xFFF,%eax
61     jz 1f
62     addl $0x1000,%eax /* round up */
63     andl $(~0xFFF),%eax
65     pushl %eax /* store end of kernel image */
67     /* get multiboot flags */
68     movl 0(%ebx),%edx
69     testl $0x08,%edx /* test MBI_MODS_XXX for modules support */
70     jz 9f /* mods_XXX fields are not valid - skip */
72     /* get multiboot header fields */
73     movl 20(%ebx),%ecx /* mods_count */
74     movl 24(%ebx),%edx /* mods_addr */
76     test %ecx,%ecx /* end of module list? */
77     jz 1f
79     /* loop through module list */
80     movl 4(%edx),%eax /* mod_end */
81     testl $0xFFF,%eax
82     jz 3f
83     addl $0x1000,%eax /* round mod_end up to page boundary */
84     andl $(~0xFFF),%eax
86     /* find highest address so far */
87     cmpl %eax,(%esp)
88     ja 3f
89     movl %eax,(%esp)
91     /* next module */
92     addl $16,%edx
93     decl %ecx
94     jnz 2b
97     /* return highest address */
98     popl %eax
99     ret
101 _start:
102     /* set up stack */
103     movl $(stack + STACK_SIZE),%esp
104     subl $_virt_base,%esp
105     addl $_phys_base,%esp
106     /* clear flags */
107     pushl $0
108     popf
109     pushl %ebx /* mb_info */
110     pushl %eax /* magic */
112     /* get start of free memory, after kernel image and modules */
113     call get_freemem_start
114     pushl %eax
116     /* allocate page directory */
117     addl $0x1000,%eax
119     /* allocate two page tables */
120     pushl %eax
121     addl $0x1000,%eax
122     pushl %eax
123     addl $0x1000,%eax
125     pushl %eax
127     /* clear pagedir */
128     movl 12(%esp),%eax
129     movl $1024,%ecx
130 1:    movl $0,(%eax)
131     addl $4,%eax
132     decl %ecx
133     jnz 1b
134     
135     /* point pagedir[0] -> page table
136        for addresses 0x00000000 .. 0x00400000 */
137     movl 12(%esp),%eax
138     movl 8(%esp),%edx
139     orl $7,%edx /* present, r/w, user */
140     movl %edx,(%eax) /* -> pd[0] */
142     /* point pagedir[768] -> page table
143        for addresses 0xC0000000 .. 0xC0400000 */
144     movl 4(%esp),%edx
145     orl $7,%edx /* present, r/w */
146     movl %edx,768*4(%eax)
148     /* identity map the first page table */
149     movl $0,%eax
150     movl 8(%esp),%ecx
151 1:    movl %eax,%edx
152     shll $12,%edx
153     orl $3,%edx
154     movl %edx,(%ecx)
155     addl $4,%ecx
156     incl %eax
157     cmpl $1024,%eax
158     jb 1b
160     /* map the second page table
161        0xC0000000 -> 0x00100000 */
162     movl $0,%eax
163     movl 4(%esp),%ecx
164 1:    movl %eax,%edx
165     shll $12,%edx
166     addl $0x00100000,%edx
167     orl $3,%edx
168     movl %edx,(%ecx)
169     addl $4,%ecx
170     incl %eax
171     cmpl $1024,%eax
172     jb 1b
174     /* load page directory */
175     movl 12(%esp),%eax
176     movl %eax,%cr3
178     /* turn on paging */
179     movl %cr0,%eax
180     orl $0x80000000,%eax
181     movl %eax,%cr0
183     movl (%esp),%eax /* lower_limit */
184     addl $16,%esp
185     pushl %eax
187     /* reload stack pointer to use higher
188        virtual addresses */
189     movl %esp,%eax
190     subl $_phys_base,%eax
191     addl $_virt_base,%eax
192     movl %eax,%esp
194     call kmain
196 hang:
197     cli
198     hlt
199     jmp hang
201 .comm stack, STACK_SIZE