This repository has been archived by the owner on Jun 4, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
kernel.c
103 lines (89 loc) · 3.11 KB
/
kernel.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
// GCC provides these header files automatically
// They give us access to useful things like fixed-width types
#include <stddef.h>
#include <stdint.h>
// First, let's do some basic checks to make sure we are using our x86-elf cross-compiler correctly
#if defined(__linux__)
#error "This code must be compiled with a cross-compiler"
#elif !defined(__i386__)
#error "This code must be compiled with an x86-elf compiler"
#endif
// This is the x86's VGA textmode buffer. To display text, we write data to this memory location
volatile uint16_t* vga_buffer = (uint16_t*)0xB8000;
// By default, the VGA textmode buffer has a size of 80x25 characters
const int cols = 80;
const int rows = 25;
// We start displaying text in the top-left of the screen (column = 0, row = 0)
int term_col = 0;
int term_row = 0;
uint8_t term_color = 0x0F; // Black background, White foreground
// This function initiates the terminal by clearing it
void term_init()
{
// Clear the textmode buffer
for (int col = 0; col < cols; col ++)
{
for (int row = 0; row < rows; row ++)
{
// The VGA textmode buffer has size (cols * rows).
// Given this, we find an index into the buffer for our character
const size_t index = (cols * row) + col;
// Entries in the VGA buffer take the binary form BBBBFFFFCCCCCCCC, where:
// - B is the background color
// - F is the foreground color
// - C is the ASCII character
vga_buffer[index] = ((uint16_t)term_color << 8) | ' '; // Set the character to blank (a space character)
}
}
}
// This function places a single character onto the screen
void term_putc(char c)
{
// Remember - we don't want to display ALL characters!
switch (c)
{
case '\n': // Newline characters should return the column to 0, and increment the row
{
term_col = 0;
term_row ++;
break;
}
default: // Normal characters just get displayed and then increment the column
{
const size_t index = (cols * term_row) + term_col; // Like before, calculate the buffer index
vga_buffer[index] = ((uint16_t)term_color << 8) | c;
term_col ++;
break;
}
}
// What happens if we get past the last column? We need to reset the column to 0, and increment the row to get to a new line
if (term_col >= cols)
{
term_col = 0;
term_row ++;
}
// What happens if we get past the last row? We need to reset both column and row to 0 in order to loop back to the top of the screen
if (term_row >= rows)
{
term_col = 0;
term_row = 0;
}
}
// This function prints an entire string onto the screen
void printf(const char* str)
{
for (size_t i = 0; str[i] != '\0'; i ++) // Keep placing characters until we hit the null-terminating character ('\0')
term_putc(str[i]);
}
// This is our kernel's main function
void main()
{
// We're here! Let's initiate the terminal and display a message to show we got here.
// Initiate terminal
term_init();
// Display some messages
printf("Hello, World!\n");
printf("Welcome to the kernel.\n");
printf("\n");
printf("This is xeonos v0.5 Pre-Release Alpha Version (0.5-PR-A)");
}