Welcome to The Fiwix Project
A UNIX-like kernel for the i386 architecture
1 /* 2 * fiwix/kernel/main.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/limits.h> 11 #include <fiwix/fs.h> 12 #include <fiwix/system.h> 13 #include <fiwix/version.h> 14 #include <fiwix/utsname.h> 15 #include <fiwix/stdio.h> 16 #include <fiwix/string.h> 17 #include <fiwix/video.h> 18 #include <fiwix/console.h> 19 #include <fiwix/pic.h> 20 #include <fiwix/segments.h> 21 #include <fiwix/devices.h> 22 #include <fiwix/cpu.h> 23 #include <fiwix/timer.h> 24 #include <fiwix/sleep.h> 25 #include <fiwix/keyboard.h> 26 #include <fiwix/sched.h> 27 #include <fiwix/mm.h> 28 29 unsigned int _last_data_addr; 30 int _memsize; 31 int _extmemsize; 32 int _rootdev; 33 int _noramdisk; 34 int _ramdisksize; 35 char _rootfstype[10]; 36 char _rootdevname[DEVNAME_MAX + 1]; 37 char _initrd[DEVNAME_MAX + 1]; 38 int _syscondev; 39 char *init_args; 40 41 char cmdline[NAME_MAX + 1]; 42 43 struct new_utsname sys_utsname = { 44 UTS_SYSNAME, 45 UTS_NODENAME, 46 UTS_RELEASE, 47 UTS_VERSION, 48 "", 49 UTS_DOMAINNAME, 50 }; 51 52 struct kernel_stat kstat; 53 54 void start_kernel(unsigned long magic, unsigned long info, unsigned int stack) 55 { 56 struct proc *init; 57 58 _last_data_addr = stack - KERNEL_BASE_ADDR; 59 memset_b(&kstat, NULL, sizeof(kstat)); 60 61 /* default kernel values */ 62 strcpy(_rootfstype, "ext2"); /* filesystem is ext2 */ 63 _syscondev = MKDEV(VCONSOLES_MAJOR, 0); /* console is /dev/tty0 */ 64 65 pic_init(); 66 idt_init(); 67 dev_init(); 68 tty_init(); 69 70 printk(" Welcome to %s\n", UTS_SYSNAME); 71 printk(" Copyright (c) 2018-2021, Jordi Sanfeliu\n"); 72 printk("\n"); 73 printk(" kernel v%s for i386 architecture\n", UTS_RELEASE); 74 printk(" (GCC %s, built on %s)\n", __VERSION__, UTS_VERSION); 75 printk("\n"); 76 printk("DEVICE ADDRESS IRQ COMMENT\n"); 77 printk("--------------------------------------------------------------------------------\n"); 78 79 cpu_init(); 80 multiboot(magic, info); 81 mem_init(); 82 video_init(); 83 console_init(); 84 timer_init(); 85 keyboard_init(); 86 proc_init(); 87 88 /* 89 * IDLE is now the current process (created manually as PID 0), 90 * it won't be placed in the running queue. 91 */ 92 current = get_proc_free(); 93 proc_slot_init(current); 94 set_tss(current); 95 load_tr(TSS); 96 current->tss.cr3 = (unsigned int)kpage_dir; 97 current->flags |= PF_KPROC; 98 sprintk(current->argv0, "%s", "idle"); 99 100 /* PID 1 is for the INIT process */ 101 init = get_proc_free(); 102 proc_slot_init(init); 103 init->pid = get_unused_pid(); 104 105 /* PID 2 is for the kswapd process */ 106 kernel_process("kswapd", kswapd); 107 108 /* kswapd will take over the rest of the kernel initialization */ 109 need_resched = 1; 110 111 STI(); /* let's rock! */ 112 cpu_idle(); 113 } 114 115 void stop_kernel(void) 116 { 117 struct proc *p; 118 int n; 119 120 /* stop and disable all interrupts! */ 121 CLI(); 122 for(n = 0; n < NR_IRQS; n++) { 123 disable_irq(n); 124 } 125 126 printk("\n"); 127 printk("** Safe to Power Off **\n"); 128 printk(" -or-\n"); 129 printk("** Press Any Key to Reboot **\n"); 130 any_key_to_reboot = 1; 131 132 /* put all processes to sleep and reset all pending signals */ 133 FOR_EACH_PROCESS_RUNNING(p) { 134 not_runnable(p, PROC_SLEEPING); 135 p->sigpending = 0; 136 p = p->next_run; 137 } 138 139 /* enable keyboard only */ 140 STI(); 141 enable_irq(KEYBOARD_IRQ); 142 143 /* switch to IDLE process */ 144 if(current) { 145 do_sched(); 146 } 147 148 cpu_idle(); 149 } 150 151 void cpu_idle() 152 { 153 for(;;) { 154 if(need_resched) { 155 do_sched(); 156 } 157 HLT(); 158 } 159 }