Welcome to The Fiwix Project
A UNIX-like kernel for the i386 architecture
1 /* 2 * fiwix/kernel/init.c 3 * 4 * Copyright 2018-2021, Jordi Sanfeliu. All rights reserved. 5 * Distributed under the terms of the Fiwix License. 6 */ 7 8 #include <fiwix/asm.h> 9 #include <fiwix/kernel.h> 10 #include <fiwix/system.h> 11 #include <fiwix/mm.h> 12 #include <fiwix/timer.h> 13 #include <fiwix/sched.h> 14 #include <fiwix/sleep.h> 15 #include <fiwix/fcntl.h> 16 #include <fiwix/stat.h> 17 #include <fiwix/process.h> 18 #include <fiwix/syscalls.h> 19 #include <fiwix/unistd.h> 20 #include <fiwix/stdio.h> 21 #include <fiwix/string.h> 22 23 #define INIT_TRAMPOLINE_SIZE 128 /* max. size of init_trampoline() */ 24 25 char *init_argv[] = { INIT_PROGRAM, NULL, NULL }; 26 char *init_envp[] = { "HOME=/", "TERM=linux", NULL }; 27 28 static void init_trampoline(void) 29 { 30 USER_SYSCALL(SYS_open, "/dev/console", O_RDWR, 0); /* stdin */ 31 USER_SYSCALL(SYS_dup, 0, NULL, NULL); /* stdout */ 32 USER_SYSCALL(SYS_dup, 0, NULL, NULL); /* stderr */ 33 USER_SYSCALL(SYS_execve, INIT_PROGRAM, init_argv, init_envp); 34 35 /* only reached in case of error in sys_execve() */ 36 USER_SYSCALL(SYS_exit, NULL, NULL, NULL); 37 } 38 39 void init_init(void) 40 { 41 int n; 42 unsigned int page; 43 struct inode *i; 44 unsigned int *pgdir; 45 struct proc *init; 46 47 if(namei(INIT_PROGRAM, &i, NULL, FOLLOW_LINKS)) { 48 PANIC("can't find %s.\n", INIT_PROGRAM); 49 } 50 if(!S_ISREG(i->i_mode)) { 51 PANIC("%s is not a regular file.\n", INIT_PROGRAM); 52 } 53 iput(i); 54 55 /* INIT slot was already created in main.c */ 56 init = &proc_table[INIT]; 57 58 /* INIT process starts with the current (kernel) Page Directory */ 59 if(!(pgdir = (void *)kmalloc())) { 60 goto init_init__die; 61 } 62 init->rss++; 63 memcpy_b(pgdir, kpage_dir, PAGE_SIZE); 64 init->tss.cr3 = V2P((unsigned int)pgdir); 65 66 memset_b(init->vma, NULL, sizeof(init->vma)); 67 init->ppid = 0; 68 init->pgid = 0; 69 init->sid = 0; 70 init->flags = 0; 71 init->children = 0; 72 init->priority = DEF_PRIORITY; 73 init->start_time = CURRENT_TICKS; 74 init->sleep_address = NULL; 75 init->uid = init->gid = 0; 76 init->euid = init->egid = 0; 77 init->suid = init->sgid = 0; 78 memset_b(init->fd, NULL, sizeof(init->fd)); 79 memset_b(init->fd_flags, NULL, sizeof(init->fd_flags)); 80 init->root = current->root; 81 init->pwd = current->pwd; 82 strcpy(init->argv0, init_argv[0]); 83 init_argv[1] = init_args; 84 sprintk(init->pidstr, "%d", init->pid); 85 init->sigpending = 0; 86 init->sigblocked = 0; 87 init->sigexecuting = 0; 88 memset_b(init->sigaction, NULL, sizeof(init->sigaction)); 89 memset_b(&init->usage, NULL, sizeof(struct rusage)); 90 memset_b(&init->cusage, NULL, sizeof(struct rusage)); 91 init->timeout = 0; 92 for(n = 0; n < RLIM_NLIMITS; n++) { 93 init->rlim[n].rlim_cur = init->rlim[n].rlim_max = RLIM_INFINITY; 94 } 95 init->rlim[RLIMIT_NOFILE].rlim_cur = OPEN_MAX; 96 init->rlim[RLIMIT_NOFILE].rlim_max = NR_OPENS; 97 init->rlim[RLIMIT_NPROC].rlim_cur = CHILD_MAX; 98 init->rlim[RLIMIT_NPROC].rlim_cur = NR_PROCS; 99 init->umask = 0022; 100 101 /* setup the stack */ 102 if(!(init->tss.esp0 = kmalloc())) { 103 goto init_init__die; 104 } 105 init->tss.esp0 += PAGE_SIZE - 4; 106 init->rss++; 107 init->tss.ss0 = KERNEL_DS; 108 109 /* setup the init_trampoline */ 110 page = map_page(init, KERNEL_BASE_ADDR - PAGE_SIZE, 0, PROT_READ | PROT_WRITE); 111 memcpy_b((void *)page, init_trampoline, INIT_TRAMPOLINE_SIZE); 112 113 init->tss.eip = (unsigned int)switch_to_user_mode; 114 init->tss.esp = page + PAGE_SIZE - 4; 115 116 runnable(init); 117 nr_processes++; 118 return; 119 120 init_init__die: 121 PANIC("unable to run init process.\n"); 122 }