2 global _start
; making entry point visible to linker
3 extern kmain
; kmain is defined elsewhere
4 extern _text_start
, _edata
, _end
; defined in linker script
5 extern _phys_base
, _virt_base
; defined in linker script
7 ; setting up the Multiboot header - see GRUB docs for details
8 MODULEALIGN
equ 1<<0 ; align loaded modules on page boundaries
9 MEMINFO
equ 1<<1 ; provide memory map
10 LOADINFO
equ 1<<16 ; load addresses are provided
11 FLAGS
equ MODULEALIGN | MEMINFO | LOADINFO
; this is the Multiboot 'flag' field
12 MAGIC
equ 0x1BADB002 ; 'magic number' lets bootloader find the header
13 CHECKSUM
equ -(MAGIC
+ FLAGS
) ; checksum required
21 dd multiboot_header
; header_addr
22 dd _text_start
; load_addr
23 dd _edata
; load_end_addr
24 dd _end
; bss_end_addr
25 dd _start
; entry_addr
29 ; reserve initial kernel stack space
30 STACKSIZE
equ 0x4000 ; that's 16k.
33 ; return the start address of free memory, after kernel image and modules
36 ; find the end of the kernel image, rounded up to the next page boundary
38 test eax,0xFFF ; need to round up?
40 add eax,0x1000 ; round up
43 push eax ; store end of kernel image
47 test edx,0x08 ; test MBI_MODS_XXX for modules support
51 mov ecx,[ebx+20] ; mods_count
52 mov edx,[ebx+24] ; mods_addr
58 ; loop through multiboot modules list
59 mov eax,[edx+4] ; mod_end
60 test eax,0xFFF ; need to round up to nearest page?
62 add eax,0x1000 ; round mod_end up to page bourdany
65 ; find highest mod_end we've found so far
68 ; this one's the highest
69 mov [esp],eax ; store the rounded mod_end
71 ; move on to next mb_module
77 ; return highest address
82 mov esp, stack
+STACKSIZE
; set up the stack
83 sub esp,_virt_base
; must use physical address for stack
84 add esp,_phys_base
; until we enable paging!
85 push eax ; pass Multiboot magic number
86 push ebx ; pass Multiboot info structure
87 cld ; make sure direction flag is clear
88 ; (the calling convention is to keep it clear)
90 ; find the start of free memory, after the kernel image and
91 ; modules, in order to allocate space for page directory and
93 call get_freemem_start
94 push eax ; push the address
96 ; allocate a page directory
99 ; allocate two page tables
106 ; clear the page directory
115 ; NOTE: we set the user bit in the page directory entries.
116 ; This doesn't allow userspace code to read or write from/to
117 ; the memory here, since it requires the user bit in the
118 ; page table entry, too.
120 ; point pagedir[0] -> one of our page tables
121 ; this maps addresses 0x00000000 .. 0x00400000
122 mov eax,[esp+12] ; page directory
123 mov edx,[esp+8] ; page table address
124 or edx,byte 7 ; present, writable, user
125 mov [eax],edx ; put the entry in the table
127 ; point pagedir[768] -> page table
128 ; for addresses 0xC0000000 .. 0xC0400000
130 or edx,byte 7 ; present, writable, user
131 mov [eax+(768*4)],edx ; put the entry in the table
133 ; identity map the first page table, so that when we enable
134 ; paging, our kernel can keep on running (and not hit a
135 ; brick wall) - when we enable paging, we can't jump at the
136 ; same time, so if we don't map something to our current eip,
137 ; we'll page-fault (and without an IDT, we'll double-fault and
138 ; triple-fault, and the computer will restart.)
140 xor eax,eax ; count page tables
141 mov ecx,[esp+8] ; page table address
144 shl edx,12 ; (page table entry number) * (page size)
145 or edx,byte 3 ; present, writable, supervisor
146 mov [ecx],edx ; put the entry in the table
147 add ecx,byte 4 ; move on to next entry
152 ; map the second page table:
153 ; point 0xC0000000 .. 0xC0400000 to physical addresses 0x00100000 .. 0x00500000
154 ; this should be enough for our entire kernel image (it's 4 mebibytes)
157 mov ecx,[esp+4] ; address of our other page table
160 shl edx,12 ; (page table entry number) * (page size)
162 or edx,byte 3 ; present, writable, supervisor
163 mov [ecx],edx ; put the entry in the table
164 add ecx,byte 4 ; move on to the next entry
169 ; now that we've set up our page tables and a page directory, we can tell the CPU
170 ; where to find the page directory
174 ; and we can turn on paging
178 ; we're still alive? Good.
180 ; Store the start of free memory after the kernel image and modules,
181 ; and now our page directory and page tables.
183 add esp,byte 16 ; pop our page table addresses - no longer needed
184 push eax ; push the start of free mem
186 ; reload the stack pointer to use virtual addresses > 0xC0000000
187 ; our stuff on the stack will still be there, because it's mapped
188 ; to the same physical address.
194 call kmain
; call kernel proper
195 cli ; halt machine should kernel return
202 resb STACKSIZE
; reserve 16k stack on a quadword boundary