This repository has been archived by the owner on Nov 4, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ckernel.c
executable file
·173 lines (147 loc) · 6.16 KB
/
ckernel.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
This file is part of VK.
Copyright (C) 2017 Valentin Haudiquet
VK is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
VK is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with VK. If not, see <http://www.gnu.org/licenses/>.
*/
#include "system.h"
#include "util/util.h"
#include "cpu/cpu.h"
#include "video/video.h"
#include "memory/mem.h"
#include "internal/internal.h"
#include "storage/storage.h"
#include "error/error.h"
#include "filesystem/fs.h"
#include "filesystem/devfs.h"
#include "tasking/task.h"
#include "time/time.h"
#include "io/io.h"
void args_parse(char* cmdline);
void kmain(multiboot_info_t* mbt, void* stack_pointer)
{
//Current status : 32 bits, protected mode, interrupts off, paging on (0-4MiB mapped to 0xC0000000)
//getting command line and parsing arguments
if((mbt->flags & 0b100))
args_parse((char*) mbt->cmdline+KERNEL_VIRTUAL_BASE);
//init
vga_setup(); //Setup VGA : set video_mode to 80x25 TEXT, get display type, set and clean VRAM, disable cursor
kprintf("Setting up CPU...");
gdt_install(stack_pointer); //Install GDT : Null segment, Kernel code, Kernel data, User code, User data, TSS
idt_install(); //TODO : ISRs ! (actually the handle isn't that bad but could be reaaally better)
cpu_detect(); //TODO : Special handle INVALID_OPCODE
vga_text_okmsg();
kprintf("Setting up memory...");
kheap_install(); //Install kernel heap (allows kmalloc(), kfree(), krealloc())
physmem_get(mbt); //Setup physical memory map
install_page_heap(); //Install page heap (allows pt_alloc(), pt_free()) (page tables / directories must be 4096 aligned)
finish_paging(); //Enables page size extension
kvmheap_install(); //Install Virtual Memory heap
vga_text_okmsg();
pic_install(); //Install PIC : remaps IRQ
pci_install(); //Setup PCI devices
install_block_devices(); //Setup block devices (ATA, ATAPI,...)
process_init(); //Init process array
scheduler_start();
//DEBUG : printing kernel stack bottom / top ; code start/end
//kprintf("%lKernel stack : 0x%X - 0x%X\n", 3, stack_pointer-8192, stack_pointer);
//kprintf("%lKernel code : 0x%X - 0x%X\n", 3, &_kernel_start, &_kernel_end);
kprintf("Getting kernel execution context...");
//kprintf("%lARGS : m=%u, r=%s\n", 3, aboot_hint_present, aroot_dir);
//getting live / root dir infos
int8_t root_drive = -1;
int8_t part_index = -1;
//first if we need to check if we want LIVE boot or INSTALLED boot
u8 mode = aboot_hint_present;
//if there were no boot args, we try to guess kernel context depending on boot_device
if(!mode)
{
//the kernel will try to guess what mode is needed (relatively to boot_device)
if(mbt->flags & 0b10)
{
if((mbt->boot_device >> 24 == 0x0) | (mbt->boot_device >> 24 == 0x1)) mode = 0;
else if((mbt->boot_device >> 24 == 0x80) | (mbt->boot_device >> 24 == 0x81))
{
mode = KERNEL_MODE_INSTALLED;
}
else if(mbt->boot_device >> 24 == 0xE0)
{
mode = KERNEL_MODE_LIVE;
}
else if(mbt->boot_device >> 24 == 0xA0)
{
mode = KERNEL_MODE_LIVE;
}
else mode = 0;
}
if(!mode) {vga_text_failmsg(); fatal_kernel_error("Could not guess kernel context...", "KERNEL_CONTEXT_GUESSING");}
}
//now let's check for root drive
if(root_drive == -1)
{
if(mode == KERNEL_MODE_LIVE)
{
//root_drive is the first CD drive we find
int8_t drive = 0;
while(block_devices[(u8) drive]->device_class != CD_DRIVE)
{
drive++;
if(drive == block_device_count) fatal_kernel_error("Could not find any CD Drive...", "KERNEL_ROOT_GUESSING");
}
root_drive = drive;
//assume the CD has no partitions
part_index = 0;
}
else if(mode == KERNEL_MODE_INSTALLED)
{
//root_drive is the first HDD we find
int8_t drive = 0;
while(block_devices[(u8) drive]->device_class != HARD_DISK_DRIVE)
{
drive++;
if(drive == block_device_count) fatal_kernel_error("Could not find any Hard Disk...", "KERNEL_ROOT_GUESSING");
}
root_drive = drive;
//assume the drive is partitionned and the first part is root
part_index = 1;
}
}
//printing kernel context
char* context = (mode == KERNEL_MODE_LIVE ? "LIVE\n" : mode == KERNEL_MODE_INSTALLED ? "INSTALLED\n" : "FAILED\n");
u8 color = (mode == KERNEL_MODE_LIVE ? 0b00001111 : mode == KERNEL_MODE_INSTALLED ? 0b00001111 : 0b00001100);
vga_text_spemsg(context, color);
//mounting root drive/part on /
kprintf("Mounting root directory...");
block_device_t* dev = block_devices[(u8) root_drive];
if(!dev) fatal_kernel_error("Could not find root drive !", "KERNEL_LOADING");
if(!mount_volume("/", dev, (u8) (part_index)))
{
vga_text_failmsg();
fatal_kernel_error("Could not mount root directory.", "KERNEL_LOADING");
}
vga_text_okmsg();
//initializing/mounting devfs
devfs_init();
//initializing ttys
ttys_init();
//switching video output to tty1
vga_text_tty_switch(current_tty);
//create init process
error_t init = spawn_init_process();
if(init != ERROR_NONE)
{
kprintf("%lCould not run init process : %d\n", 2, init);
fatal_kernel_error("Could not run init", "INIT_RUN");
}
scheduler_remove_process(kernel_process);
//loop infinetely
//(actually this is dead code, because kernel process is removed, and the scheduler switch to init process)
while(1) asm("hlt");
}