diff options
Diffstat (limited to 'src/kernel/main.c')
-rw-r--r-- | src/kernel/main.c | 194 |
1 files changed, 169 insertions, 25 deletions
diff --git a/src/kernel/main.c b/src/kernel/main.c index 9ad9d1c..74fd8bf 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -21,33 +21,177 @@ OF THIS SOFTWARE. #include "files.h" #include "mem.h" #include "proc.h" -#include "misc.h" - -void _start(void) { - *(uint16_t *)0x0000200e = 0x0000; - - *(uint32_t *)0x0000050c = (uint32_t)allocate_pages(16 * sizeof(struct file_handle_info), 2); - for (struct file_handle_info *i = FILE_HANDLES, *l = FILE_HANDLES + 65536; i < l; ++i) - i->first_sector = 0; - - *(uint32_t *)0x00000510 = (uint32_t)allocate_pages(16 * sizeof(struct proc_info), 2); - for (struct proc_info *i = PROCS, *l = PROCS + 65536; i < l; ++i) - i->memory_start = 0; - - uint16_t pages_free = 0, pages_total = 0; - for (uint16_t *i = MMAP; i < MMAP + 0x1000; ++i) - switch (*i) { - case 1: - continue; - case 0: - ++pages_free; +#include <stdbool.h> + +extern uint32_t info_pointer; + +enum tag_type { + BOOT_COMMAND = 1, + LOADER_NAME = 2, + BOOT_MODULES = 3, + MEMORY_INFO = 4, + BOOT_DEVICE = 5, + MEMORY_MAP = 6, + VBE_INFO = 7, + FBUF_INFO = 8, + ELF_SYMBOLS = 9, + APM_TABLE = 10, + EFI_I386_TABLE = 11, + EFI_AMD64_TABLE = 12, + SMBIOS_TABLE = 13, + RSDP_ACPI1 = 14, + RSDP_ACPI2 = 15, + NETWORK_INFO = 16, + EFI_MEMORY_MAP = 17, + EFI_SERVICES = 18, + EFI_I386_HANDLE = 19, + EFI_AMD64_HANDLE = 20, + IMAGE_BASE_ADDR = 21 +}; + +struct tag_start { + uint32_t type; + uint32_t size; + uint8_t rest; +} __attribute__ ((__packed__)); + +struct boot_device_tag { + uint32_t bios_device; + uint32_t partition; + uint32_t subpartition; +} __attribute__ ((__packed__)); + +enum mem_type { + AVAILABLE = 1, + ACPI = 3, + PRESERVE = 4, + DEFECTIVE = 5 +}; + +struct boot_device_tag boot_device; +bool have_boot_device = false; +bool have_mmap = false; + +enum error_codes { + NO_BOOT_DEVICE = 0, + NO_MMAP = 1, + INSUFF_MEMORY = 2 +}; + +uint32_t main(void) { + uint32_t info_size = *(uint32_t *)info_pointer; + struct tag_start *tag_pointer = (struct tag_start *)(info_pointer + 2); + + while (tag_pointer->type) { + switch (tag_pointer->type) { + + case BOOT_DEVICE: + boot_device = *(struct boot_device_tag *)&tag_pointer->rest; + have_boot_device = true; + put_sz("Boot device: 0x"); + put_32_hex(boot_device.bios_device); + if (boot_device.partition != 0xffffffff) { + put_sz(", 0x"); + put_32_hex(boot_device.partition); + if (boot_device.subpartition != 0xffffffff) { + put_sz(", 0x"); + put_32_hex(boot_device.subpartition); + } + } + put_char('\n'); + break; + + case MEMORY_MAP: + mmap_start = (struct mmap_entry *)((uint32_t)&tag_pointer->rest + 8); + uint32_t size = *(uint32_t *)&tag_pointer->rest; + struct mmap_entry *next = mmap_start; + struct mmap_entry **fill_last = &mmap_start; + uint32_t usable = 0; + while (next) { + if (!(next->base & 0xffffffff00000000)) { + *fill_last = next; + fill_last = &next->next; + if ((next->base + next->length - 1) & 0xffffffff00000000) + next->length = 1 + ~(next->base); + put_sz("Memory: 0x"); + put_32_hex((uint32_t)(next->base >> 32)); + put_char('_'); + put_32_hex((uint32_t)next->base); + put_sz(" - "); + put_32_hex((uint32_t)(next->length >> 32)); + put_char('_'); + put_32_hex((uint32_t)next->length); + switch (next->whose) { + case AVAILABLE: + put_sz(": usable\n"); + next->whose = FREE; + usable += next->length; + break; + case ACPI: + put_sz(": ACPI info\n"); + next->whose = HARDWARE; + break; + case PRESERVE: + put_sz(": hardware use\n"); + next->whose = HARDWARE; + break; + case DEFECTIVE: + put_sz(": defective\n"); + next->whose = HARDWARE; + break; + default: + put_sz(": unrecognized type, assuming hardware use\n"); + next->whose = HARDWARE; + break; + } + } + next = next->next = (struct mmap_entry *)((uint32_t)next + size); + } + + put_sz("Total usable memory: 0x"); + put_32_hex(usable); + put_char('\n'); + + bool clean; + do { + clean = true; + for (struct mmap_entry *current = mmap_start; current; current = current->next) + for (struct mmap_entry *against = mmap_start; against; against = against->next) + if ((current->base + current->length == against->base) && + (current->whose == against->whose)) { + current->length += against->length; + if (against == mmap_start) + mmap_start = against->next; + else { + for (current = mmap_start; current->next != against; current = current->next) + ; + current->next = against->next; + } + clean = false; + } + } while (clean); + + have_mmap = true; + break; + default: - ++pages_total; + put_sz("Ignoring multiboot tag 0x"); + put_32_hex(tag_pointer->type); + put_char('\n'); + } - put_16(pages_free); - put_sz(" of "); - put_16(pages_total); - put_sz(" pages free.\n"); + tag_pointer = (struct tag_start *)((uint8_t *)tag_pointer + tag_pointer->size); + }; + + if (!have_boot_device) + return NO_BOOT_DEVICE; + if (!have_mmap) + return NO_MMAP; + + if (!((proc_table = allocate_block(sizeof(struct proc_info) * 65536, KERNEL)) && + (file_table = allocate_block(sizeof(struct file_info) * 65536, KERNEL)))) + return INSUFF_MEMORY; + ; put_sz("Welcome to Portland version 0.0.8!\n"); while (1) |