#include #include #include "multiboot.h" #include "sys.h" #include #include #include #include #include #include #include #include #include #include #include #include /* The kernel's main procedure. This function is called in loader_.asm. This function calls the initializer functions for all system parts. It then loads the modules the kernel was given by the bootloader. This function never returns : once multitasking is started for good, the execution flow of this function is never returned to. */ extern "C" void kmain(multiboot_info_t* mbd, int32_t magic) { ASSERT(magic == MULTIBOOT_BOOTLOADER_MAGIC); mem_placementAddr = ((size_t)&end & 0xFFFFF000) + 0x1000; mbd->cmdline += K_HIGHHALF_ADDR; mbd->mods_addr += K_HIGHHALF_ADDR; module_t *mods = (module_t*)mbd->mods_addr; for (unsigned i = 0; i < mbd->mods_count; i++) { mods[i].mod_start += K_HIGHHALF_ADDR; mods[i].mod_end += K_HIGHHALF_ADDR; mods[i].string += K_HIGHHALF_ADDR; if (mods[i].mod_end > mem_placementAddr) mem_placementAddr = (mods[i].mod_end & 0xFFFFF000) + 0x1000; } // Init memory managment functions idt_init(); size_t totalRam = ((mbd->mem_upper + mbd->mem_lower) * 1024); paging_init(totalRam); gdt_init(); paging_cleanup(); _no_more_ksbrk = true; // Init higher level stuff timer_init(100); tasking_init(); vfs_setup(); // Init display devices text_display = new vgatxt(dot_dev); dot_dev->add_child("vgatxt", text_display); ke_vt = new vt(dot_ui, 80, 25); dot_ui->add_child("klog", ke_vt); ke_vt->outputTo(text_display); home_vt = new vt(dot_ui, 80, 25); dot_ui->add_child("home", home_vt); dot_ui->add_child("vt1", new vt(dot_ui, 80, 25)); dot_ui->add_child("vt2", new vt(dot_ui, 80, 25)); dot_ui->add_child("vt3", new vt(dot_ui, 80, 25)); dot_ui->add_child("vt4", new vt(dot_ui, 80, 25)); // Say hello ke_vt->fgcolor = TC_LIGHTGRAY; *ke_vt << "Hello. This is "; ke_vt->fgcolor = TC_WHITE; *ke_vt << K_OS_NAME; ke_vt->fgcolor = TC_LIGHTGRAY; *ke_vt << " version "; ke_vt->fgcolor = TC_WHITE; *ke_vt << K_OS_VER; ke_vt->fgcolor = TC_LIGHTGRAY; *ke_vt << " codename '"; ke_vt->fgcolor = TC_WHITE; *ke_vt << K_OS_CODENAME; ke_vt->fgcolor = TC_LIGHTGRAY; *ke_vt << "'. Enjoy!\n"; // Init devices kbd = new ps2kbd(dot_dev); dot_dev->add_child("ps2kbd", kbd); kbd->outputTo(ke_vt); // Load modules *ke_vt << "Loading modules :\n"; for (unsigned i = 0; i < mbd->mods_count; i++) { char* cmd = (char*)mods[i].string; *ke_vt << " * " << cmd << " \t"; if (elf_check((uint8_t*)mods[i].mod_start) == 0) { char *args[16] = { cmd, 0 }; int a = 1; for (char* c = cmd; c != 0; c++) { if (*c == ' ') { *c = 0; args[a] = c + 1; a++; if (a == 15) { args[a] = 0; break; } } else if (*c == 0) { args[a] = 0; break; } } process *pr = elf_exec((uint8_t*)mods[i].mod_start, PL_USER, args); // todo add args if (pr == 0) { *ke_vt << "Error loading\n"; } else { pr->fd.set(0, ke_vt); *ke_vt << "OK, pid=" << (int)pr->pid << "\n"; } } else if (initrd_check((uint8_t*)mods[i].mod_start) == 0) { vdir* fs = new vdir(root); int e = initrd_load((uint8_t*)mods[i].mod_start, fs); if (e == 0) { char* name = cmd; for (char* i = name; *i != 0; i++) { if (*i == '/' || *i == ' ') name = i + 1; } root->add_child(name, fs); *ke_vt << "OK, initrd as /" << name << "/\n"; } else { *ke_vt << "initrd but error " << e << "\n"; } } else { *ke_vt << "Invalid file, neither ELF nor initrd.\n"; } } *ke_vt << "Giving control to userland processes.\n\n"; sti(); schedule(); PANIC("Should never happen. Something probably went wrong with multitasking."); }