summaryrefslogtreecommitdiff
path: root/src/kernel/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/main.c')
-rw-r--r--src/kernel/main.c194
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)