Simple Operating System
kernel.c
Go to the documentation of this file.
1 
12 #include <io.h>
13 #include "../include/string.h"
14 #include "../include/stdlib.h"
15 #include <conio.h>
16 
17 #define KERNEL 1
18 #ifndef KERNEL_ADDRESS
19 #define KERNEL_ADDRESS 0
20 #endif
21 
22 #include "interrupts.h"
23 #include "fs.h"
24 
25 extern int load(Byte beginSector, Byte track, int parameter, int size, int segment);
26 int gets(char *str, int size);
27 
32 #define PROGRAMS_MAX 7
33 
34 bool programsMap[PROGRAMS_MAX];
35 
36 #pragma GCC diagnostic push
37 #pragma GCC diagnostic ignored "-Wunused-parameter"
38 
42 void reset() {
43  puts("Exiting...");
44  asm("mov ds, ax\n"
45  "mov ss, ax\n"
46  "mov es, ax\n"
47  "mov fs, ax\n"
48  "mov gs, ax\n"
49  "mov esp, 0xfff0\n"
50  "push cx\n"
51  "push ax\n"
52  "push dx\n"
53  "iretw\n"::"a"(KERNEL_ADDRESS), "d"(0x200), "c"(IF));
54 }
55 
61 __int void timer(struct interruptFrame * frame) {
62 //https://wiki.osdev.org/Processes_and_Threads
63  asm("pushw ds\nmov ds, ax"::"a"(KERNEL_ADDRESS));
64  static int counter = 0;
65  static int lastReset = 100;
66  lastReset++;
67 
68  EOI();
69  Word special = 0;
70  //handle Ctrl+Alt+L
71  asm("int 0x16":"=a"(special):"a"(0x1200));
72  if(special == 0x30C && lastReset >= 100) { //CTRL + ALT
73  Key key;
74  for(int i = 0; i < 0x1f; i += 2) {
75  asm("pushw ds\n"
76  "xor bx, bx\n"
77  "mov ds, bx\n"
78  "mov ax, WORD ptr [0x41E+si]\n"
79  "popw ds":"=a"(key):"S"(i));
80  if(key.scancode == 38 && key.character == 0) {
81  //clear buffer
82  for(int i = 0; i < 0x1f; i += 2)
83  asm("pushw ds\n"
84  "xor bx, bx\n"
85  "mov ds, bx\n"
86  "mov WORD ptr [0x41E+si],bx\n"
87  "popw ds"::"S"(i));
88  lastReset = 0;
89  reset();
90  }
91  }
92  }
93 
94  int seg;
95  asm("mov %0, ss":"=r"(seg));
96  if(seg == KERNEL_ADDRESS)
97  return;
98  if(counter >= 1000) {
99  counter = 0;
100  putc('X');
101  }
102  counter++;
103 
104  asm("popw ds");
105 }
106 
112 __int void shiftPrtSc(struct interruptFrame * frame) {
113  putc('B');
114  asm("hlt");
115 }
116 
123 __int void ctrlBreak(struct interruptFrame * frame) {
124  asm("pushw ds\n mov ds, bx\nmov [0x471],ax\n popw ds"::"a"(0), "b"(0));
125  EOI();
126  reset();
127 }
128 
129 #pragma GCC diagnostic pop
130 
131 __start void main() {
132  setVideoMode(TextMode);
133  setColorPalette(DarkGrey);
134  setInterrupts();
135  addInterrupt(0x21, int0x21);
136  asm("sti");
137  addInterrupt(0x1c, timer);
138  addInterrupt(0x1b, ctrlBreak);
140  int bufferSize = 0;
141  asm("int 0x21":"=a"(bufferSize):"a"(0));
142  printf("Kernel loaded.\nVersion: "__DATE__" "__TIME__"\nMemory size: %ikB\nLoaded %i files\n>", getMemorySize(), bufferSize);
143 
144  char command[100];
145  char parameter[100];
146  int retVal;
147 
148  for(;;) {
149  bufferSize = gets(command, 98);
150  if(strchr(command, ' ') == NULL)
151  parameter[0] = 0;
152  else {
153  strcpy(parameter, strchr(command, ' ') + 1);
154  *(char *)strchr(command, ' ') = 0;
155  }
156 
157  if(bufferSize == 0) {
158 
159  }
160  else if(strcmp(command, "cls")) {
161  cls();
162  }
163  else if(strcmp(command, "pos")) {
164  Cursor cursor = getCursorPosition();
165  printf("%i:%i", cursor.x, cursor.y);
166  }
167  else if(strcmp(command, "key")) {
168  Key key = getc();
169  Word special = 0;
170  asm("int 0x16":"=a"(special):"a"(0x1200));
171  printf("character=%i,scancode=%i,special=%b,color=", key.character, key.scancode, special);
172  //get attribute
173  int a = 0;
174  asm("int 0x10":"=a"(a):"a"(0x0800), "b"(0x0000));
175  puti(a >> 8);
176  }
177  else if(strcmp(command, "mode")) {
178  setVideoMode(stoi(parameter));
179  short col, size;
180  asm("pushw ds\n xor bx,bx\nmov ds, bx\nmov ax, [0x44a]\n popw ds":"=a"(col));
181  asm("pushw ds\n xor bx,bx\nmov ds, bx\nmov ax, [0x44c]\n popw ds":"=a"(size));
182  printf("Mode: %i, columns/row: %i, size %i", stoi(parameter), col, size);
183  }
184  else if(strcmp(command, "mem")) {
185  Byte val;
186  for(int i = 0; i < 1024; i++) {
187  asm("mov ds, si\n"
188  "mov al, byte ptr ds:[bx]\n"
189  "mov ds, di":"=a"(val):"b"(i), "S"(stoi(parameter)), "D"(KERNEL_ADDRESS));
190  putc(val);
191  }
192  }
193  else if(strcmp(command, "ls")) {
194  size_t i = 0;
195  size_t sum = 0;
196  cputs("NAME TRACK:SECTOR SIZE", Cyan);
197  putc('\n');
198  for(; i < numberOfFiles; i++) {
199  puts(files[i].name);
200  for(size_t j = 0; j < FILENAME_MAX - strlen(files[i].name); j++)putc(' ');
201  printf("%s%i:%s%i %s%i\n", (files[i].track / 10 >= 1 ? "" : "0"), files[i].track, (files[i].beginSector / 10 >= 1 ? "" : "0"), files[i].beginSector, ((files[i].size / 10) >= 1 ? "" : "0"), files[i].size);
202  sum += files[i].size;
203  }
204  printf("\n%i file(s) %s%i sector(s)\n", i, (sum / 10 >= 1 ? "" : "0"), sum);
205  }
206  else if(strcmp(command, "map")) {
207  for(int i = 1; i < SECTORS_PER_TRACK; i++)putc((i % 10 + '0'));
208  putc('\n');
209  for(int j = 0; j < TRACKS_MAX; j++) {
210  for(int i = 1; i < SECTORS_PER_TRACK; i++) {
211  puti(map[j][i]);
212  }
213  putc('\n');
214  }
215  }
216  else if(strcmp(command, "rm")) {
217  if(parameter[0] == 0) {
218  retVal = -1;
219  goto afterCOM;//simulate rm as com command
220  }
221  asm("int 0x21":"=a"(retVal):"a"(0x0500), "b"(parameter));
222  goto afterCOM;
223  }
224  else {
225  //remove whitespace from command beginning
226  int i = 1;
227  for(; i < 96 && command[i] != 0 && command[i] == ' '; i++) {
228  }
229  if(command[0] == 0)
230  strcpy(command, command + i);
231 
232  //check if there is program called command+".com"
233  short id = 0;
234  strncpy(command + strlen(command), ".com", 5);
235  id = sys_open(command);
236  if(id > 0) {
237  id = (Byte)id;
238 
239  //find free segment
240  char freeSegment = -ENOMEM;
241  for(int j = 0; j < PROGRAMS_MAX; j++) {
242  if(!programsMap[j]) {
243  programsMap[j] = true;
244  freeSegment = j;
245  break;
246  }
247  }
248  if(freeSegment == -ENOMEM) {
249  retVal = -ENOMEM;
250  goto afterCOM;
251  }
252  freeSegment += 1;//0x1000 segment is kernel
253  retVal = load(files[id].beginSector, files[id].track, parameter, files[id].size, KERNEL_ADDRESS + 0x1000 * freeSegment);
254 afterCOM:
255  if(retVal != 0) {
256  cputs("Error:", Red);
257  printf(" \"%s\" returned %i\n", command, retVal);
258  }
259  }
260  else {
261  cputs("Error:", Red);
262  if(id == -ENOENT)
263  printf(" \"%s\" is unknown command!\n", command);
264  }
265  }
266  putc('>');
267  }
268 
269  asm("hlt");
270 }
271 
272 int gets(char *str, int size) {
273  Key key;
274  int ptr = 0;
275  int oldPtr = 0;
276  for(; ptr < size;) {
277  key = getc();
278  if(key.character == 13) {
279  str[ptr] = 0;
280  break;
281  }
282  if(key.character == 8 && ptr >= 0) { //backspace
283  if(ptr > 0) {
284  str[ptr] = 0;
285  ptr--;
286  putc(8);
287  putc(' ');
288  putc(8);
289  }
290  continue;
291  }
292  else if(key.character == 0 && key.scancode == 72) {
293  asm("int 0x10"::"a"(0x0601), "b"(0x0000), "c"(0x0000), "d"(0xffff));
294  ptr = 0;
295  continue;
296  }
297  else if(key.character == 0 && key.scancode == 80) {
298  asm("int 0x10"::"a"(0x0701), "b"(0x0000), "c"(0x0000), "d"(0xffff));
299  ptr = 0;
300  continue;
301  }
302  else if(key.character == 0 && key.scancode == 75) {
303  if(ptr > 0) {
304  //move cursor by -1
305  asm("int 0x10\n\
306  mov ah,02\n\
307  dec dl\n\
308  int 0x10"
309  ::"a" (0x0300), "b" (0x0));
310  if(oldPtr < ptr)
311  oldPtr = ptr;
312  ptr--;
313  }
314  continue;
315  }
316  else if(key.character == 0 && key.scancode == 77) {
317  if(ptr < oldPtr) {
318  //move cursor by 1
319  asm("int 0x10\n\
320  mov ah,02\n\
321  inc dl\n\
322  int 0x10"
323  ::"a" (0x0300), "b" (0x0));
324  if(ptr < size) {
325  ptr++;
326  if(ptr == oldPtr)
327  oldPtr = 0;
328  }
329  }
330  continue;
331  }
332  putc(key.character);
333  str[ptr++] = key.character;
334  }
335  str[oldPtr < ptr ? ptr : oldPtr] = 0; //end string with null
336  putc('\n');
337  return ptr;
338 }
339 
346 void __printf(int a) {
347  char* ptr = *(int *)a;
348  int iterator = 1;
349  while(*ptr != 0) {
350  if(*ptr == '%') {
351  //I know it should be done with switch-case but it gives strange and bad assembly
352  char specifier = *(ptr + 1);
353  if(specifier == 'i' || specifier == 'd')
354  puti(*(int *)(a + 4 * iterator++));
355  else if(specifier == 'u')
356  asm("int 0x20"::"a"(0x200), "b"(*(int *)(a + 4 * iterator++)));
357  else if(specifier == 'b') {
358  char num[17];
359  int par = *(int *)(a + 4 * iterator++);
360  for(int i = 0; i < 16; i++) {
361  num[15 - i] = par % 2 + '0';
362  par /= 2;
363  }
364  num[16] = 0;
365  asm("int 0x20"::"a"(0x100), "b"(num));
366  }
367  else if(specifier == 'c')
368  asm("xor ah, ah\n"
369  "int 0x20"::"a"(*(char *)(a + 4 * iterator++)));
370  else if(specifier == 's')
371  asm("int 0x20"::"a"(0x100), "b"(*(int *)(a + 4 * iterator++)));
372  else {
373  asm("xor ah,ah\n"
374  "int 0x20"::"a"(*ptr));
375  ptr--;
376  }
377  ptr++;
378  }
379  else
380  putc(*ptr);
381  ptr++;
382  }
383 
384  return;
385 }
Console input output control.
void cputs(int str, Color color)
Color put string.
Definition: conio.h:118
void setVideoMode(Mode mode)
Set the video mode of screen.
Definition: conio.h:41
Cursor getCursorPosition(void)
Get position of Cursor.
Definition: conio.h:58
void cls(void)
Clear screen.
Definition: conio.h:80
File system, adds file system interruption in int0x21()
__int void int0x21(interruptFrame *frame)
interruption for file system
Definition: fs.h:310
bool map[TRACKS_MAX][SECTORS_PER_TRACK]
Map of used sectors in tracks.
Definition: fs.h:49
int sys_open(const int filename)
Open file.
Definition: fs.h:101
#define SECTORS_PER_TRACK
Number of sectors per track.
Definition: fs.h:30
#define FILENAME_MAX
Maximal size of file name.
Definition: fs.h:24
#define TRACKS_MAX
Maximal number of tracks in OS.
Definition: fs.h:36
void setInterrupts(void)
Set system interruptions.
void addInterrupt(number, function)
add interruption
Setting system interruptions, see interrupts.asm.
#define IF
Interruption flag.
Definition: interrupts.h:42
#define EOI()
End of interruption.
Definition: interrupts.h:51
Standard input output library.
void puti(int num)
Put int.
Definition: io.h:52
Key getc(void)
Wait for key in buffer, get it and clear buffer.
Definition: io.h:83
void printf(const int str,...)
C-like printf function.
Definition: io.h:72
void puts(const int string)
Put string.
Definition: io.h:42
void putc(Byte character)
Put character.
Definition: io.h:31
#define PROGRAMS_MAX
Maximal number of programs running simultaneously.
Definition: kernel.c:32
__start void main()
Definition: kernel.c:131
void __printf(int a)
Function for int 0x20 AH=3 see io.h printf()
Definition: kernel.c:346
__int void timer(struct interruptFrame *frame)
Interruption is called 18 times per second.
Definition: kernel.c:61
void reset()
Reset OS to kernel.
Definition: kernel.c:42
__int void ctrlBreak(struct interruptFrame *frame)
Ctrl + Break handler.
Definition: kernel.c:123
__int void shiftPrtSc(struct interruptFrame *frame)
Shift + PrintScreen handler.
Definition: kernel.c:112
int load(beginSector, track, parameter, size, segment)
load program to segment and executes it
Definition: loader-asm.c:27
Word getMemorySize(void)
Get RAM size in first 1MB.
Definition: stdlib.h:16
size_t strlen(const char *str)
Returns length of string.
Definition: string.h:44
int strncpy(int destination, int source, size_t num)
Copy num Bytes from source to destination until \0 appears.
Definition: string.h:131
bool strcmp(int str1, int str2)
Compares two string until \0 appears.
Definition: string.h:20
int stoi(const char *str)
Convert string to int.
Definition: string.h:80
char * strcpy(char *destination, const char *source)
Copy from source to destination until \0 appears.
Definition: string.h:113
const char * strchr(const char *str, int character)
Find first appearance of character.
Definition: string.h:64
Position of cursor.
Definition: conio.h:20
frame for interruption, required by gcc for __int
Definition: interrupts.h:29
#define NULL
pointer to NULL
Definition: types.h:22
#define __start
Must be before main function of program to put this function as first in binary file.
Definition: types.h:35
Key information, got from buffer.
Definition: io.h:14