summaryrefslogtreecommitdiff
path: root/kernel/kernel.c
blob: cf65e1848b68aaa5f4a776ee92e625caa494d47f (plain)
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#include "kernel.h"

#include "log.h"
#include "serial.h"

#include "asm_pic.h"
#include "multiboot.h"
#include "acpi.h"
#include "gdt.h"
#include "interrupts.h"

#include "mem.h"
#include "vmem.h"

//-- clean below headers --//
#include "asm_start.h"
#include "compositor.h"
#include "sysfs.h"
#include "pci.h"
#include "e1000.h"
#include "pipe.h"
#include "testing/testing.h"
#include "ext2.h"
#include "apic.h"
#include "kernel/scheduler.h"

#include "driver/timer.h"
#include "driver/keyboard.h"
#include "driver/mouse.h"

#include "syscalls.h"
#include "fifo.h"
#include "asm_smp.h"
#include "asm_x86.h"
#include "ringbuffer.h"
#include "driver/screen.h"
#include "smp.h"

#include "fs/elf.h"
#include "kmalloc.h"
#include "driver/vesa.h"
#include "asm_pit.h"

/** F00L 0S Entry point (called directly from asm/multiboot.asm)
 *
 *  After this procedure completes we are in a well defined state.
 *
 *  * All Processors are up and running in 32bit protected mode.
 *  * Interrupts are installed and enabled:
 *
 *      - PS/2 Keyboard CPU0
 *      - PS/2 Mouse    CPU0
 *      - PIT  Timer (20Hz) (DISABLED in apic.c) CPU0
 *      - APIC Timer (Frequency defined in kernel.h) ALL CPUS
 *      - E1000         CPU0
 *
 *  * Software Interrupts:
 *
 *      - Syscalls
 *      - IPI
 *
 *  * Framebuffer is in a known state.
 *  * Paging is enabled.
 *  * Each CPU runs on its own stack at VMEM_CPU_STACK 
 *  * Each CPU has its own private page at VMEM_CPU_PRIVATE
 *  * We are ready to start scheduling on the next interrupt.
 *
 */

void kernel_main(uint32_t eax,uint32_t ebx)
{
    // -- COM1 -- //
    serial_init();
    klog("Communication Port (COM1) initialized.");

    // -- PR & VERSION BANNER -- //
    klog("======================================");
    klog("F00L- 0S / The Fool's Operating System");
    klog("(C) 2018 / Michal Idziorek (m.i@gmx.at)");
    klog("Compiled on: %s at %s",__DATE__,__TIME__);
    klog("Version: git-commit: %s",GIT_REVISION);
    klog("======================================");

    uint32_t *top_kernel_vmem=VMEM_KERNEL+VMEM_KERNEL_PAGES*4096;
    klog("The Kernel was loaded at: 0x%08X - 0x%08X",get_kernel_start(),get_kernel_end());
    klog("0x00000000 - 0x%08X will get identity mapped", VMEM_KERNEL_PAGES*4096);
    if(kernel_end>=top_kernel_vmem)kpanic("kernel to big. increase VMEM_KERNEL_PAGES");
    fixme("still fear overrun of stack");

    // -- DISABLE LEGACY PIC -- //
    klog("Remapping & Disabling Programmable Interrupt Controller (PIC) ...");
    fixme("io_wait & spurious interrupts");
    asm_pic_setup();

    // -- GET CONFIGS -- //
    klog("Read Multiboot Structures ...");
    multiboot_information *cfg_multiboot;
    cfg_multiboot=multiboot_read(eax, ebx,false); // true for silent
    // elf_multiboot_read(cfg_multiboot); // just show kernel section headers
    
    klog("Read Advanced Power Configuration Interface (ACPI) Structures ...");
    acpi_information cfg_acpi;    
    bool acpi_found=acpi_fill(&cfg_acpi);
    fixme("Try to read (legacy) multiprocessor mp strucutres as well (see: xxx/mp.c)");
    if(!acpi_found) kpanic("We Currently rely on ACPI Structures Sorry!");

    // -- GDT -- //
    klog("Global Descriptor Table (GDT) init ...");
    gdt_init();

    // -- IVT -- //
    klog("Interrupt Vector Table (IVT) init ...");
    interrupts_init(0x08);
    interrupts_install();

    // -- PCI SCAN --/
    klog("PCI init ...");
    uint32_t e1000_addr=pci_init();
    klog("E1000 addr=0x%08X",e1000_addr);

    // -- MEMORY MANAGEMENT -- //
    klog("Memory init ... ");
    mem_init(cfg_multiboot);
    
    klog("Vritual Memory / Paging init ... ");
    fixme("do not disable anymore on context switching!");
    fixme("write convenneint management funcs as: mapCPU, mapKErnel, map USerspace..");
    fixme("move stack and guard with empty pages!");
    vmem_init(cfg_multiboot,&cfg_acpi,e1000_addr);

    struct pdirectory_struct *dir=vmem_kernel_dir();
    x86_set_page_directory(dir);
    x86_paging_enable();

    // -- MOUNTS -- //
    klog("Mounting ... ");
    ext2_dump_info(VMEM_EXT2_RAMIMAGE);
    ext2_mount("/");
    sysfs_mount("/sys/");

    // -- APIC -- //
    klog("Advanced Programmable Interrupt Controller (APIC) config ...");
    apic_init(&cfg_acpi);
    ioapic_config();

    // -- VESA -- //
    /* 
    fixme("tell terminal syscall somehow if we are vga or textmode");
    klog("Video Electronics Standards Association (VESA) init ... ");
    
    // binfont has to fit in ONE ext2 block // 
    
    fixme("support binfonts spanning multiple blocks?");
    uint32_t inode= ext2_filename_to_inode(VMEM_EXT2_RAMIMAGE,VESA_FONT_PATH);
    uint32_t addr= ext2_inode_blockstart( VMEM_EXT2_RAMIMAGE,inode,0);
    vesa_init(cfg_multiboot,addr); // this only sets some internal static variables


    // -- STD STREAMS -- //
    klog("Standard Streams init ...");
    fd_init_std_streams(0,cfg_multiboot->framebuffer_type!=2);
    */

    klog("Compositor init ...");
    compositor_init(cfg_multiboot->framebuffer_width,cfg_multiboot->framebuffer_height,cfg_multiboot->framebuffer_pitch);
    compositor_set_background("/home/miguel/bg.ppm");

    // -- KB -- //
    klog("Keyboard init ...");
    keyboard_init();

    // -- MOUSE -- //
    klog("Mouse init ...");
    mouse_init();

    // -- E1000 INIT (TODO: only if present!) --/
    if(e1000_addr)
    {
        #ifndef DISABLE_E1000
        klog("E1000 init ...");
        e1000_init(e1000_addr);
        #endif
    }

    // we wait until the end since the time will only start ticking once
    // we enable interrupts.
    klog("Programmable Interval Timer (PIT) init ...");
    klog("Reading CMOS Clock ...");
    uint64_t unixtime=timer_init();
    klog("Unix Time = %u seconds",unixtime);

    klog("Symmetric Multi Processing (SMP) start ... ");
    for(int i=1;i<cfg_acpi.processors;i++)apic_sipi(i,0x7);

    smp_bsp(); // start base processor
}