IBNOS
main.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Michael Müller
3  * Copyright (c) 2014, Sebastian Lackner
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #include <multiboot/multiboot.h>
29 #include <console/console.h>
30 
31 #include <memory/physmem.h>
32 #include <memory/paging.h>
33 #include <memory/allocator.h>
34 
35 #include <hardware/gdt.h>
36 #include <hardware/pic.h>
37 #include <hardware/keyboard.h>
38 #include <hardware/pit.h>
39 
40 #include <process/object.h>
41 #include <process/process.h>
42 #include <process/thread.h>
43 #include <process/pipe.h>
44 #include <process/timer.h>
45 #include <process/filesystem.h>
46 #include <process/handle.h>
47 #include <process/timer.h>
48 
49 #include <loader/elf.h>
50 
51 #include <util/list.h>
52 #include <util/util.h>
53 
54 uint32_t __getCR0();
55 asm(".text\n.align 4\n"
56 "__getCR0:\n"
57 " movl %cr0, %eax\n"
58 " ret\n"
59 );
60 
61 uint32_t __setCR0(uint32_t value);
62 asm(".text\n.align 4\n"
63 "__setCR0:\n"
64 " movl 4(%esp), %eax\n"
65 " movl %eax, %cr0\n"
66 " ret\n"
67 );
68 
72 void fpuInit()
73 {
74  uint32_t cr0 = __getCR0();
75  cr0 &= ~(1 << 2); /* disable EMuleration */
76  cr0 |= (1 << 5); /* enable Native Exception */
77  cr0 |= (1 << 3); /* enable TS bit (kernel shouldn't use FPU) */
78  cr0 |= (1 << 1); /* enable MP */
79  __setCR0(cr0);
80 }
81 
95 struct process *loadELFModule(void *addr, uint32_t length)
96 {
97  struct process *p;
98  struct thread *t = NULL;
99 
100  p = processCreate(NULL);
101  if (p)
102  {
103  /* load ELF executable */
104  assert(elfLoadBinary(p, addr, length));
105 
106  t = threadCreate(p, NULL, p->entryPoint);
107  if (t) objectRelease(t);
108 
109  objectRelease(p);
110  }
111 
112  return (t != NULL) ? p : NULL;
113 }
114 
126 {
127  multiboot_module_t *module;
128  struct process *initProcess;
129  struct stdout *stdout;
130  struct pipe *stdin;
131 
132  consoleClear();
133 
134  assert(sizeof(struct taskContext) == 0x68);
135  assert(sizeof(struct fpuContext) == 0x6C);
136  assert(offsetof(struct taskContext, eip) == 0x20);
137 
138  /* ensure that GRUB loaded a usermode process */
139  assert((bootInfo->flags & MULTIBOOT_INFO_MODS));
140  assert(bootInfo->mods_count >= 2);
141 
142  /* ensure that entry is valid */
143  module = (multiboot_module_t *)bootInfo->mods_addr;
144  assert(module[0].mod_start && module[0].mod_start < module[0].mod_end);
145  assert(module[1].mod_start && module[1].mod_start < module[1].mod_end);
146 
147  /* Initialize kernel modules - NOTE: the order is important */
148  physMemInit(bootInfo);
149  consoleInit();
150  consoleSetFont();
152  pagingInit();
153  gdtInit();
154  fpuInit();
155 
156  /* initialize stdin & stdout */
157  stdout = stdoutCreate();
158  stdin = pipeCreate();
159 
160  picInit(0x20);
161  keyboardInit(&stdin->obj);
162  timerInit();
163  fileSystemInit((void*)module[1].mod_start, module[1].mod_end - module[1].mod_start);
164 
165  /* load init process */
166  initProcess = loadELFModule((void*)module[0].mod_start, module[0].mod_end - module[0].mod_start);
167  assert(initProcess);
168 
169  /* initialize stdout, stdin & stderr handles */
170  handleSet(&initProcess->handles, 0, &stdin->obj);
171  handleSet(&initProcess->handles, 1, &stdout->obj);
172  handleSet(&initProcess->handles, 2, &stdout->obj);
173 
174  /* schedule threads */
175  threadSchedule();
176 
177  /* the last process was terminated */
178  consoleWriteString("\n\nThe last process was terminated. You can now safely reboot your computer.\n");
179  debugHalt();
180 }
void * entryPoint
Definition: process.h:79
bool handleSet(struct handleTable *table, uint32_t handle, struct object *object)
Associates a handle (index) with a kernel object.
Definition: handle.c:168
struct thread * threadCreate(struct process *p, struct thread *original, void *eip)
Creates a new kernel thread object.
Definition: thread.c:80
void debugHalt()
Definition: util.h:53
uint32_t __getCR0()
struct process * processCreate(struct process *original)
Creates a new kernel process object.
Definition: process.c:77
void pagingInit()
Initializes paging.
Definition: paging.c:467
#define assert(ex)
Definition: util.h:61
void consoleSetFont()
Load a custom font supporting latin1 characters.
Definition: console.c:526
#define PAGE_SIZE
Definition: physmem.h:35
void physMemProtectBootEntry(uint32_t addr, uint32_t length)
Marks all pages within a memory range as reserved and adds them to the boot map.
Definition: physmem.c:259
void threadSchedule()
Schedules threads until all process have been terminated.
Definition: thread.c:355
void fpuInit()
Initializes the FPU related bits in the CR0 register.
Definition: main.c:72
void consoleInit()
Initializes the console.
Definition: console.c:79
#define MULTIBOOT_INFO_MODS
Definition: multiboot.h:64
struct pipe * pipeCreate()
Creates a new kernel pipe object.
Definition: pipe.c:88
Definition: thread.h:47
void physMemInit(multiboot_info_t *bootInfo)
Initializes the physical memory management.
Definition: physmem.c:116
Definition: pipe.h:41
multiboot_uint32_t flags
Definition: multiboot.h:147
uint32_t __setCR0(uint32_t value)
bool elfLoadBinary(struct process *p, void *addr, uint32_t length)
Loads an ELF executable stored in the memory into a process.
Definition: elf.c:104
void fileSystemInit(void *addr, uint32_t length)
Initializes the root file system.
Definition: filesystem.c:858
void keyboardInit(struct object *obj)
Initializes the keyboard.
Definition: keyboard.c:282
multiboot_uint32_t mods_count
Definition: multiboot.h:160
uint32_t eip
Definition: context.h:186
void consoleClear()
Clear the screen contents.
Definition: console.c:90
struct object obj
Definition: pipe.h:57
struct object obj
Definition: pipe.h:43
void picInit(uint32_t interruptOffset)
Initializes the programmable interrupt controller.
Definition: pic.c:103
void consoleWriteString(const char *str)
Write a C string to the console.
Definition: console.c:240
struct handleTable handles
Definition: process.h:90
#define objectRelease(p)
Definition: object.h:97
struct process * loadELFModule(void *addr, uint32_t length)
Spawns a new process, and afterwards loads the ELF module into it.
Definition: main.c:95
void timerInit()
Initializes the system timer.
Definition: timer.c:313
Definition: pipe.h:55
multiboot_uint32_t mods_addr
Definition: multiboot.h:161
void gdtInit()
Initializes the GDT, task registers, and sets up everything required for multiprocessing.
Definition: gdt.c:432
void kernel_main(multiboot_info_t *bootInfo)
Kernel main entry point.
Definition: main.c:125
uint32_t value
Definition: paging.h:55
struct stdout * stdoutCreate()
Creates a new kernel stdout object.
Definition: pipe.c:380