2 * Copyright (c) 2008 Joshua Phillips. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
34 #include "multiboot.h"
36 #include "interrupt.h"
38 #include "mm/allocation.h"
39 #include "mm/paging.h"
40 #include "mm/region.h"
48 static void read_mmap_info(struct mb_info
*mbi
)
50 struct mb_mmap
*region
; // current memory region
51 struct mb_mmap
*end
; // end of memory region array
52 region
= (struct mb_mmap
*) mbi
->mmap_addr
;
53 end
= (struct mb_mmap
*) (mbi
->mmap_addr
+ mbi
->mmap_length
);
54 TRACE("Memory map from bootloader, at address %.8X:", mbi
->mmap_addr
);
56 TRACE(" Region(%.8X .. %.8X (type %d)",
57 (unsigned long) region
->base_addr
,
58 (unsigned long) (region
->base_addr
+ region
->length
- 1),
60 if (region
->type
== 1){
61 pmem_init_mark_free(region
->base_addr
, region
->base_addr
+ region
->length
);
64 region
= (struct mb_mmap
*) (((char *) region
) + region
->size
+ 4);
68 static void read_multiboot_info(struct mb_info
*mbi
)
70 if (mbi
->flags
& MBI_BOOT_LOADER_NAME
){
71 // Bootloader has given us a name. Why not print it?
73 if (mbi
->flags
& MBI_MMAP_XXX
){
74 // read the memory map
76 } else if (mbi
->flags
& MBI_MEM_XXX
){
77 // Use the more basic memory information
78 console_printf(&tty1
, "Upper memory (mbi->mem_upper): %d kiB\n", mbi
->mem_upper
);
79 pmem_init_mark_free(KERNEL_PHYS_BASE
, KERNEL_PHYS_BASE
+ mbi
->mem_upper
* 1024);
81 panic("The bootloader gave us no memory information!");
86 static void read_multiboot_modules(struct mb_info
*mbi
)
88 // XXX: we're assuming the first 4 MiB is identity-mapped!
89 struct mb_module
*mod
;
91 if (mbi
->flags
& MBI_MODS_XXX
){
92 // find address of first module structure from the multiboot info
93 mod
= (struct mb_module
*) mbi
->mods_addr
;
94 count
= mbi
->mods_count
;
95 for (i
=0; i
<count
; ++i
,++mod
){
96 // print info about each module
97 TRACE("Module: %s at 0x%.8X (%d kiB)\n", (char *) mod
->string
, mod
->mod_start
,
98 uldivru(mod
->mod_end
- mod
->mod_start
, 1024));
99 // load the elf module
100 load_elf_module((void *) mod
->mod_start
, mod
->mod_start
, mod
->mod_end
- mod
->mod_start
);
103 TRACE("No multiboot modules found.\n");
106 TRACE("No multiboot module information.\n");
107 TRACE("Either the bootloader doesn't support modules,\n");
108 TRACE("or no modules were loaded.\n");
125 void kmain(uint32_t freemem_base
, struct mb_info
*mbi
, unsigned int magic
)
127 static struct pagedir init_pagedir
;
129 console_init(&tty1
); // init the text console
130 serial_init(&com1
, 1, 9600); // try to init ttyS0 (first serial port)
131 if (magic
!= MB_BOOT_MAGIC
){
132 console_colour_fg(&tty1
, COLOUR_BRIGHT_RED
);
133 console_printf(&tty1
, "Bootloader gave us an invalid magic number: 0x%.8X\n", magic
);
134 console_colour_default(&tty1
);
136 pmem_init_set_freemem_base(freemem_base
);
137 read_multiboot_info(mbi
);
138 console_printf(&tty1
, "Free memory: %d MiB\n", uldivru(pmem_get_size(), 1024 * 1024));
139 mm_allocation_init();
140 create_init_pagedir(&init_pagedir
);
142 map_mem(&init_pagedir
, 0xF0000000, 0x00000000, 4096, PTE_PRESENT
| PTE_WRITABLE
);
143 TRACE("map_mem returned! Check the mapping!");
145 static struct pagedir second_pagedir
;
146 pagedir_create(&second_pagedir
);
147 map_mem(&second_pagedir
, 0x00000000, 0x40000000, 4096, PTE_PRESENT
| PTE_WRITABLE
);
148 pagedir_switch(&second_pagedir
);
149 TRACE("Well I seem to be still alive!");
151 asm volatile ("cli ; hlt");
153 // allocate a page for the IDT, GDT and TSS
156 intptr_t page_paddr
, page_vaddr
;
158 size_t n_pages_phys
, n_pages_virt
;
159 n_pages_phys
= ppalloc(1, 1, &page_paddr
);
160 if (n_pages_phys
== 0){
161 panic("cannot allocate physical page for IDT/GDT/TSS");
163 n_pages_virt
= vpalloc(&kvpa
, 1, 1, &page_vaddr
);
164 if (n_pages_virt
== 0){
165 panic("cannot allocate virtual page for IDT/GDT/TSS");
167 map_mem(page_paddr
, page_vaddr
, 1, PTE_PRESENT
| PTE_USER
);
168 page
= (void *) page_vaddr
;
170 interrupt_init(&page
);
174 // test interrupt handling
175 asm volatile ("int $0x81");
179 set_pagefault_handler();
182 // Map VRAM to a suitable place
183 map_mem(0xB8000, 0xFFBFF000, 1, PTE_PRESENT
| PTE_WRITABLE
);
184 tty1
.vram
= (void *) 0xFFBFF000; // TODO: don't probe into other modules' structures
188 read_multiboot_modules(mbi
);
190 asm volatile ("sti");
192 // enter an idle loop, so we can see the effects of interrupts
194 asm volatile ("hlt");