diff --git a/src/hulk/hippo.d b/src/hulk/hippo.d new file mode 100644 index 0000000..e1ea2ee --- /dev/null +++ b/src/hulk/hippo.d @@ -0,0 +1,106 @@ +/** + * HIPPO, the HOS In-place Physical Page Organizer. + */ +module hulk.hippo; + +import hulk.header; +import hulk.bootinfo; +import hulk.klog; + +extern extern(C) ubyte * _hulk_bss_size; + +struct hippo +{ + /** + * Linked list node entry for a physical page. + */ + private struct PhysicalPage + { + PhysicalPage * next; + } + + /** + * Linked list of free physical pages. + */ + private static __gshared PhysicalPage * free_pages; + + /** + * Number of free physical pages. + */ + private static __gshared size_t n_free_pages; + + /** + * Initialize HIPPO. + * + * Ok, what we do here is iterate through all of the memory map regions in + * the bootinfo memory_map array, and create a linked list of all free + * physical pages that are available. Within the available memory regions, + * we have to watch out for the following items: + * 1) HULK binary (text + data) + * - This includes the HULK header and bootinfo structures + * 2) HULK bss + * 3) HULK stack + * 4) Framebuffer + * 5) Page tables + * + * @param bootinfo HULK boot information structure. + */ + public static void initialize(HulkHeader * header) + { + size_t usable_memory; + ulong[2][5] reserved = [ + [header.bootinfo.hulk_phys, cast(ulong)header.total_size], + [header.bootinfo.bss_phys, cast(ulong)&_hulk_bss_size], + [header.bootinfo.stack_phys, header.stack_size], + [cast(ulong)header.bootinfo.fb.buffer, header.bootinfo.fb.height * header.bootinfo.fb.stride], + [header.bootinfo.pt_phys, header.bootinfo.pt_size], + ]; + for (size_t ri = 0u; ri < reserved.length; ri++) + { + reserved[ri][1] += reserved[ri][0]; + } + for (size_t bii = 0u; bii < header.bootinfo.memory_map_count; bii++) + { + if (header.bootinfo.memory_map[bii].type == BootInfo.MemoryRegion.Type.Conventional) + { + ulong phys = header.bootinfo.memory_map[bii].base; + ulong phys_end = phys + header.bootinfo.memory_map[bii].size; + usable_memory += header.bootinfo.memory_map[bii].size; + phys_loop: while (phys < phys_end) + { + bool is_reserved = false; + for (size_t ri = 0u; ri < reserved.length; ri++) + { + if ((reserved[ri][0] <= phys) && (phys < reserved[ri][1])) + { + is_reserved = true; + break; + } + } + if (!is_reserved) + { + free_page(phys); + } + phys += 4096u; + } + } + } + size_t usable_kb = usable_memory >> 10u; + size_t usable_mb = usable_kb >> 10u; + size_t frac_mb = ((1000u * (usable_kb & 0x3FFu)) + 512u) >> 10u; + klog.writefln("Found %u.%03uMB of usable RAM", usable_mb, frac_mb); + } + + /** + * Free a physical page. + * + * @param phys Physical page address. + */ + private static void free_page(ulong phys) + { + PhysicalPage * pp = cast(PhysicalPage *)phys; + pp.next = free_pages; + free_pages = pp; + n_free_pages++; + } +} diff --git a/src/hulk/hulk.d b/src/hulk/hulk.d index 5452e00..4b10572 100644 --- a/src/hulk/hulk.d +++ b/src/hulk/hulk.d @@ -11,6 +11,7 @@ import ldc.attributes; import hulk.kfont; import hulk.klog; import hulk.hurl; +import hulk.hippo; extern extern(C) __gshared ubyte _hulk_total_size; @@ -36,6 +37,8 @@ void hulk_start() klog.writefln("Welcome to HULK, the HOS UltraLight Kernel!"); + hippo.initialize(&hulk_header); + for (;;) { } diff --git a/src/hulk/hulk.ld b/src/hulk/hulk.ld index f27db3b..8ea1054 100644 --- a/src/hulk/hulk.ld +++ b/src/hulk/hulk.ld @@ -26,9 +26,11 @@ SECTIONS .bss BLOCK(4K) : ALIGN(4K) { + _hulk_bss_start = .; *(COMMON) *(.bss) } + _hulk_bss_size = . - _hulk_bss_start; . = ALIGN(4K);