199 lines
6.0 KiB
C
199 lines
6.0 KiB
C
#include "atapio.h"
|
|
#include "screenstuff.h"
|
|
#include "paging.h"
|
|
|
|
typedef struct {
|
|
uint32_t base_low;
|
|
uint32_t base_high;
|
|
uint32_t length_low;
|
|
uint32_t length_high;
|
|
uint32_t type;
|
|
uint32_t acpi3_extended;
|
|
}__attribute__((packed)) e820entry;
|
|
|
|
uint8_t* bitmap = 0x100000;
|
|
|
|
void set_bit(uint32_t offset, uint8_t* buffer) {
|
|
uint32_t index = offset / 8;
|
|
uint32_t bit = offset % 8;
|
|
|
|
buffer[index] |= (1<<(7 - bit));
|
|
}
|
|
|
|
void unset_bit(uint32_t offset, uint8_t* buffer) {
|
|
uint32_t index = offset / 8;
|
|
uint32_t bit = offset % 8;
|
|
|
|
buffer[index] &= (255 - (1<<(7 - bit)));
|
|
}
|
|
|
|
void memset(uint8_t* base, uint32_t count, uint8_t to) {
|
|
for (int i=0; i<count; i++) {
|
|
base[i] = to;
|
|
}
|
|
}
|
|
|
|
void mark_unavailble(uint32_t address, uint32_t size, uint8_t* buffer) {
|
|
// This function takes an address and length and marks the corresponding pages as unavailable.
|
|
address -= address % 4096;
|
|
if (size % 4096)
|
|
size += 4096 - (size % 4096);
|
|
|
|
address /= 4096;
|
|
size /= 4096;
|
|
|
|
for (int i=0; i<size; i++) {
|
|
unset_bit(address + i, buffer);
|
|
}
|
|
}
|
|
|
|
char* stringify_type(uint32_t type) {
|
|
switch (type) {
|
|
case 1:
|
|
return "Usable";
|
|
case 3:
|
|
return "ACPI Reclaimable";
|
|
case 4:
|
|
return "ACPI NVS";
|
|
case 5:
|
|
return "Bad memory";
|
|
default:
|
|
return "Reserved";
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
init_term();
|
|
init_atapio();
|
|
|
|
// e820 memory map exists at 0x20000
|
|
e820entry* e820_entries = 0x20000;
|
|
|
|
// Zero out the bitmap.
|
|
memset(bitmap, 0x20000, 0);
|
|
// Ensure the bitmap data is clear
|
|
|
|
for (int i=0; i<0x20000; i++)
|
|
if (bitmap[i])
|
|
printf("Found data in bitmap at %x!\n", (bitmap+i));
|
|
|
|
for (int i=0; e820_entries[i].length_low != 0 || e820_entries[i].length_high != 0; i++) {
|
|
e820entry entry = e820_entries[i];
|
|
printf("BIOS-e820: Starting %x%x, length %x%x is %s\n", entry.base_high, entry.base_low, entry.length_high, entry.length_low, stringify_type(entry.type));
|
|
|
|
if (entry.type != 1)
|
|
continue;
|
|
|
|
uint32_t base = entry.base_low;
|
|
uint32_t length = entry.length_low;
|
|
|
|
if (base % 4096) {
|
|
// Memory isn't page aligned, we need to fix that.
|
|
uint32_t add_offset = 4096 - (base % 4096);
|
|
if (length > add_offset) {
|
|
base += add_offset;
|
|
length -= add_offset;
|
|
}
|
|
}
|
|
uint32_t page_index = base / 4096;
|
|
|
|
printf("Page Index: %d\nLength (Pages): %d\n", page_index, length / 4096);
|
|
|
|
for (int j=0; length > 4096; length -= 4096, j++) {
|
|
set_bit(page_index + j, bitmap);
|
|
}
|
|
}
|
|
|
|
mark_unavailble(bitmap, 0x20000, bitmap);
|
|
|
|
// Page Directory
|
|
PDE* kernel_page_directory = bitmap + 0x20000;
|
|
|
|
// Clear the PD
|
|
memset((uint8_t*)kernel_page_directory, 4096, 0);
|
|
|
|
// Clear 4MB of RAM from 0x121000 to 0x521000 for the 1024 page tables
|
|
memset((uint8_t*)0x121000, 0x400000, 0);
|
|
|
|
// Construct a 1024 long PTE** at 0x521000
|
|
for (int i=0; i<1024; i++) {
|
|
((uint32_t*)0x521000)[i] = 0x121000 + 0x1000*i;
|
|
}
|
|
|
|
PTE** kernel_page_tables = 0x521000;
|
|
|
|
for (int i = 0; i < 1023; i++) {
|
|
kernel_page_directory[i] = (PDE){
|
|
.address = (uint32_t)(kernel_page_tables[i]) >> 12,
|
|
.available = 0,
|
|
.page_4mb = 0,
|
|
.accessed = 0,
|
|
.disable_cache = 0,
|
|
.write_through_cache = 0,
|
|
.privilege = 0,
|
|
.present = 1,
|
|
.read_write = 1,
|
|
|
|
.ignored = 0,
|
|
.ignored2 = 0
|
|
};
|
|
}
|
|
|
|
// Mark unavailable bitmap to 0x522000
|
|
mark_unavailble(bitmap, 0x4000000, bitmap);
|
|
|
|
// Now we want to map some stuff.
|
|
// But first, we should load the kernel somewhere
|
|
|
|
uint8_t* kernel_location = 0x542000; // Just load it at 0x524000 for now
|
|
mark_unavailble(kernel_location, 0x10000, bitmap); // Just treat the kernel as not growing beyond 32k for now.
|
|
|
|
map_many_4k_phys_to_virt(kernel_location, 0xc0000000, kernel_page_directory, kernel_page_tables, 0x10); // Map 16 pages from 0x522000 to 0xc0000000;
|
|
map_4k_phys_to_virt((uint32_t)kernel_page_directory, 0xc0100000, kernel_page_directory, kernel_page_tables); // Map the page directory to 0xc0100000
|
|
map_many_4k_phys_to_virt(0x121000, 0xc0101000, kernel_page_directory, kernel_page_tables, 1024); // Map 1024 pages from 0x121000 to 0xc0101000
|
|
map_4k_phys_to_virt(0xb8000, 0xc0501000, kernel_page_directory, kernel_page_tables); // Map 0xb8000 (video) to 0xc0501000
|
|
map_4k_phys_to_virt(0x521000, 0xc0502000, kernel_page_directory, kernel_page_tables); // Map the PTE** data, we'll need to convert the pointers to point at kernel space at some point.
|
|
|
|
map_many_4k_phys_to_virt(0xa0000, 0xc07a0000, kernel_page_directory, kernel_page_tables, 0x20); // Map 32 pages from 0xa0000 to 0xa0000
|
|
mark_unavailble(0xa0000, 0x20000, bitmap);
|
|
|
|
|
|
uint8_t* vm_bitmap = 0x522000;
|
|
mark_unavailble(vm_bitmap, 0x20000, bitmap);
|
|
|
|
memset(vm_bitmap, 0x20000, 0xff);
|
|
mark_unavailble(0xc07a0000, 0x20000, vm_bitmap);
|
|
mark_unavailble(0xc0000000, 0x10000, vm_bitmap);
|
|
mark_unavailble(0xc0100000, 0x1000, vm_bitmap);
|
|
mark_unavailble(0xc0101000, 0x400000, vm_bitmap);
|
|
mark_unavailble(0xc0501000, 0x1000, vm_bitmap);
|
|
mark_unavailble(0xc0502000, 0x1000, vm_bitmap);
|
|
mark_unavailble(0xc0600000, 0x20000, vm_bitmap);
|
|
mark_unavailble(0xc0620000, 0x20000, vm_bitmap);
|
|
mark_unavailble(0xc1000000, 0x6000, vm_bitmap);
|
|
|
|
// Map the bitmap
|
|
map_many_4k_phys_to_virt(0x100000, 0xc0600000, kernel_page_directory, kernel_page_tables, 32);
|
|
// Map the virtual memory bitmap
|
|
map_many_4k_phys_to_virt(0x522000, 0xc0620000, kernel_page_directory, kernel_page_tables, 32);
|
|
|
|
map_4k_phys_to_virt(0x8000, 0x8000, kernel_page_directory, kernel_page_tables);
|
|
// Map the stack
|
|
map_many_4k_phys_to_virt(0x8a000, 0x8a000, kernel_page_directory, kernel_page_tables, 16);
|
|
map_many_4k_phys_to_virt(0x8a000, 0xc1000000, kernel_page_directory, kernel_page_tables, 16);
|
|
mark_unavailble(0x8a000, 0x10000, bitmap);
|
|
|
|
load_file("KERNEL BIN", kernel_location);
|
|
|
|
printf("Stage2 success!\n");
|
|
|
|
//while (1);
|
|
|
|
asm volatile("mov %0, %%eax;"
|
|
"mov %%eax, %%cr3;"
|
|
"mov %%cr0, %%eax;"
|
|
"or $0x80000000, %%eax;"
|
|
"mov %%eax, %%cr0" : : "m" (kernel_page_directory));
|
|
|
|
((void(*)(void))0xc0000000)();
|
|
} |