#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static zn_status_t load_server( struct boot_file* file, const char** argv, const char** envp, struct namespace_desc* init_handle, struct task** out ) { struct vas* space; zn_status_t status = vas_new(&space); if (status != ZN_OK) return status; struct paged_vmo* file_vmo; status = vmo_new_phys(&file_vmo); if (status != ZN_OK) return status; vmo_write(&file_vmo->object, 0, HHDM_PTR(file->data), file->length, nullptr); struct namespace* ns; status = namespace_new(&ns); if (status != ZN_OK) return status; struct exec_info info = { .file_obj = &file_vmo->object, .ns = ns, .space = space, .argv = argv, .envp = envp, .init_handle = init_handle, }; kprintf("Loading executable \"%s\"\n", file->path); return elf_load(&info, out); } static const char zinnia_banner[] = "Zinnia " ZINNIA_VERSION " (" ZINNIA_ARCH ", " ZINNIA_COMPILER_ID ", " ZINNIA_LINKER_ID ")"; static void kernel_main_task(uintptr_t arg0) { struct boot_info* info = (struct boot_info*)arg0; kprintf("%s\n", zinnia_banner); // Say hello! assert(info->num_files >= 1, "No init executable provided\n"); struct channel* init_ep; struct channel* other_ep; assert(channel_create(&init_ep, &other_ep) == ZN_OK, "Failed to create init channel\n"); struct vas* init_space; assert(vas_new(&init_space) == ZN_OK, ""); struct boot_file* file_data = &info->files[0]; struct paged_vmo* init_file; assert(vmo_new_phys(&init_file) == ZN_OK, ""); vmo_write(&init_file->object, 0, HHDM_PTR(file_data->data), file_data->length, nullptr); struct namespace* ns; assert(namespace_new(&ns) == ZN_OK, ""); struct namespace_desc init_ch_desc = { .type = NAMESPACE_DESC_CHANNEL, .rights = ZN_RIGHTS_ALL, .value.channel = init_ep, }; // Load init. const char* init_argv[] = {"init", nullptr}; const char* init_envp[] = {nullptr}; struct task* init_task; zn_status_t status = load_server(&info->files[0], init_argv, init_envp, &init_ch_desc, &init_task); assert(status == ZN_OK, "Failed to load init process (%i)\n", status); sched_add_task(&percpu_get()->sched, init_task); // Load other daemons. for (size_t i = 1; i < info->num_files; i++) { struct namespace_desc ch_desc = { .type = NAMESPACE_DESC_CHANNEL, .rights = ZN_RIGHTS_ALL, .value.channel = other_ep, }; const char* argv[] = {info->files[i].path, nullptr}; const char* envp[] = {nullptr}; struct task* task; status = load_server(&info->files[i], argv, envp, &ch_desc, &task); assert(status == ZN_OK, "Failed to load server \"%s\": (%i)\n", info->files[i].path, status); sched_add_task(&percpu_get()->sched, task); } while (true) { arch_irq_wait(); } } [[noreturn]] void kernel_main(struct boot_info* info) { cmdline_parse(info->cmdline); console_init(); mem_init(info->mem_map, info->num_mem_maps, info->virt_base, info->phys_base, info->hhdm_base); rsdp_addr = info->rsdp; // TODO percpu_init(); sched_init(&percpu_get()->sched); futex_init(); struct task* main_task; task_create("main", &kernel_vas, nullptr, kernel_main_task, (uintptr_t)info, &main_task); sched_add_task(&percpu_get()->sched, main_task); irq_unlock(); sched_yield(&percpu_get()->sched); unreachable(); } [[__init]] void kernel_early_init() { percpu_bsp_init(); percpu_get()->online = true; irq_lock(); }