tape-kernel 1.0
a modular modern independent kernel
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1//main.c - main kernel codebase
2#include "../usr/shell.h" //shell
3#include "../io/vga.h" //vga functions
4#include "../io/cm.h" //for init
5#include "../lib/utils.h" //for general purpose
6#include "../mem/heap.h" //for init and for malloc wrapper when using gdb, comment the function if not debugging or having issues with allocation
7//use alc for writing native code
8#include "../fs/ide.h" //for init
9#include "../fs/ffs.h" //for init
10#include "../fs/fs.h" //for init
11#include "../lib/err.h" //for init
12#include "../io/io.h" //for init
13#include "../lib/pit.h" //for delay and init
14#include "../mem/mem.h" //mem functions
15
16#define KHEAP_SIZE (1024 * 1024) //1mb main heap
17#define FS_ARENA_SIZE (256 * 1024) //256kb for filesystem
18#define CMD_ARENA_SIZE (128 * 1024) //128kb for shell commands
19
20void ___init(void); //prototypes
21void* malloc(uint32_t size);
22NORETURN void ___kmain(uint32_t magic, void *mb_info);
23
24/**
25 * @brief description of heap sizes in src/kernel/main.c
26 *
27 * there are 3 heaps in the kernel, kheap (kernel heap)
28 * with childs of fs_arena (filesystem arena) and cmd_arena (command arena)
29 * kheap is 1mb total
30 * fs_arena is 256kb from kheap
31 * cmd_arena is 128kb from kheap
32 *
33 * this leaves 640kb~ of space in kheap
34 *
35 * @see hinit(), anew(), res(), and alc()
36*/
37/**
38 * @brief the main kernel heap
39 *
40 * kheap is the primary 1mb arena that all kernel allocations
41 * come from, child arenas are carved out of this heap
42 *
43 * @see fs_arena, cmd_arena, hinit(), alc()
44 */
47
48/**
49 * @brief the filesystem child arena
50 *
51 * fs_arena is a 256kb arena allocated from kheap and used for
52 * filesystem operations like storing filenames and file data
53 *
54 * @see kheap, cmd_arena, anew()
55 */
57
58/**
59 * @brief the command processing child arena
60 *
61 * cmd_arena is a 128kb arena allocated from kheap and reset
62 * before each shell command to provide temporary scratch space
63 *
64 * @see kheap, fs_arena, res()
65 */
67
68static int ___init_called = 0;
69
70/**
71 * @brief ___init initializes all kernel subsystems
72 *
73 * ___init is a function that sets up the kernel heap, child arenas,
74 * pit timer, ide disk controller, flat filesystem, and filesystem
75 * tooling, then runs a full sanity check suite before returning
76 *
77 * ___init is called once at boot time and will panic if called twice
78 *
79 * using ___init is done with
80 * @code{.c}
81 * ___init();
82 * @endcode
83 *
84 * @see kmain(), hinit(), ideinit(), fsinit()
85 */
86void ___init(void) {
87 if (___init_called) {
88 panic("init: called twice");
89 }
90 //ensure init is guarded
92
93 hcur();
94 clscr();
95 int row = 0;
96
97 //main heap initialization (1mb)
98 hinit(&kheap, kmem, sizeof(kmem));
99 //sanity check: try a small allocation
100 void *test = alc(&kheap, 16);
101 assert(test != NULL, "init: heap allocation failed");
102 assert((uint32_t)test >= (uint32_t)kmem, "init: heap returned address outside bounds");
103 prt(0, row++, "[ OK ] main heap (1mb)", 0x0A);
104
105 //create filesystem arena (256kb from main heap)
107 assert(fs_arena != NULL, "init: failed to create fs arena");
108 prt(0, row++, "[ OK ] fs arena (256kb)", 0x0A);
109
110 //create command arena (128kb from main heap)
112 assert(cmd_arena != NULL, "init: failed to create command arena");
113 prt(0, row++, "[ OK ] cmd arena (128kb)", 0x0A);
114
115 //pit initialization
116 pinit();
117 prt(0, row++, "[ OK ] pit timer", 0x0A);
118
119 //ide initialization
120 ideinit();
121 //sanity check: try reading disk signature
122 uint8_t test_sector[512];
123 irsec(0, test_sector); //irsec returns void, just call it
124 //check if sector has any data (non-zero)
125 int empty = 1;
126 for (int i = 0; i < 512; i++) {
127 if (test_sector[i] != 0) {
128 empty = 0;
129 break;
130 }
131 }
132 if (empty) {
133 prt(0, row++, "[WARN] ide - sector 0 all zeros, disk may be empty", 0x06);
134 } else {
135 prt(0, row++, "[ OK ] ide ", 0x0A);
136 }
137
138 //ffs initialization
139 ffsinit();
140 //sanity check: verify filesystem signature
141 uint8_t magic[512];
142 irsec(1, magic);
143 if (magic[0] == 'F' && magic[1] == 'S') {
144 prt(0, row++, "[ OK ] ffs", 0x0A);
145 } else {
146 prt(0, row++, "[WARN] ffs - no valid filesystem, will create new one", 0x06);
147 }
148
149 //fs initialization
151 //sanity check: verify we can read file count
152 int check_lba = (int)fsfind(""); //will return 0 if nothing exists
153 if (check_lba == 0) {
154 prt(0, row++, "[ OK ] fs (empty)", 0x0A);
155 } else {
156 prt(0, row++, "[ OK ] fs", 0x0A);
157 }
158
159 //final sanity check suite - init doesnt complete until everything proves it works
160 int sanity_passed = 1;
161
162 //heap test - allocate, write, read, verify
163 void *htest = alc(&kheap, 64);
164 assert(htest != NULL, "sanity: heap allocation failed");
165 uint8_t *hbytes = (uint8_t*)htest;
166 for (int i = 0; i < 64; i++) {
167 hbytes[i] = (uint8_t)(i & 0xFF);
168 }
169 for (int i = 0; i < 64; i++) {
170 if (hbytes[i] != (i & 0xFF)) {
171 panic("sanity: heap memory corruption");
172 }
173 }
174 prt(0, row++, "[ OK ] heap read/write", 0x0A);
175
176 //disk test - write a test sector, read it back, verify
177 uint8_t wsector[512];
178 uint8_t rsector[512];
179 for (int i = 0; i < 512; i++) wsector[i] = (uint8_t)(i & 0xFF);
180 uint32_t tlba = 200; //use lba far from filesystem area
181 iwrt(tlba, wsector);
182 irsec(tlba, rsector);
183 for (int i = 0; i < 512; i++) {
184 if (rsector[i] != (i & 0xFF)) {
185 panic("sanity: disk write/read mismatch");
186 }
187 }
188 prt(0, row++, "[ OK ] disk write/read", 0x0A);
189
190 //fs test - create, write, read, delete
191 const char *tname = ".sanity_test";
192 const char *tcontent = "this is a sanity check file if you can read this, the fs works.";
193 fswrite(fs_arena, tname, tcontent);
194 char *rback = fsread(tname);
195 assert(rback != NULL, "sanity: fsread returned NULL");
196 if (strcmp(tcontent, rback) != 0) {
197 panic("sanity: file content mismatch");
198 }
199 fsdelete(tname);
200 uint32_t dlba = fsfind(tname);
201 assert(dlba == 0, "sanity: file still exists after delete");
202 prt(0, row++, "[ OK ] filesystem operations", 0x0A);
203
204 //interrupt test verify keyboard controller responds
205 uint8_t kbtest = inb(0x64); //read controller status
206 if ((kbtest & 0x01) == 0) {
207 //keyboard buffer empty still okay - controller alive
208 prt(0, row++, "[ OK ] keyboard controller", 0x0A);
209 } else {
210 prt(0, row++, "[ OK ] keyboard controller", 0x0A); //still passes, just has data
211 }
212
213 //cursor test
214 //just verify cursor movement works
215 int tcx, tcy;
216 scur();
217 cob(10, 10);
218 cnb(&tcx, &tcy);
219 hcur();
220 if (tcx != 10 || tcy != 10) {
221 panic("sanity: cursor positioning failed");
222 }
223 prt(0, row++, "[ OK ] cursor positioning", 0x0A);
224
225 //all checks passed
226 if (sanity_passed) {
227 //do none
228 }
229
230 scur();
231
232 int crow = row + 2; //we need row = row + 2 but that causes issues, better solution is to use a cursor row
233 cob(0, crow);
234 prt(0, row++, "[ OK ] init complete", 0x0A);
235}
236
237/**
238 * @brief malloc is a gdb friendly wrapper around alc
239 *
240 * malloc is a function that allocates memory from the main kernel
241 * heap, it exists primarily for gdb compatibility
242 * @param size, the number of bytes to allocate
243 *
244 * @warning when writing kernel code, use alc directly instead of
245 * malloc, since malloc is only a thin wrapper for debugging
246 *
247 * @see alc(), kheap
248 */
249void* malloc(uint32_t size) {
250 return alc(&kheap, size); //use alc in actual kernel code, DO NOT use malloc
251}
252
253/**
254 * @brief ___kmain is the main kernel entry point after boot
255 *
256 * ___kmain is a function called by the multiboot bootloader that
257 * verifies the multiboot magic, runs kernel initialization, and
258 * enters the infinite interactive shell loop
259 * @param magic, the multiboot magic number (should be 0x2BADB002)
260 * @param mb_info, a pointer to the multiboot information structure
261 *
262 * using ___kmain is done with
263 * @code{.c}
264 * //called from boot.s with multiboot info:
265 * ___kmain(0x2BADB002, multiboot_info_ptr);
266 * @endcode
267 *
268 * @see ___init(), boot.s, shell()
269 */
270NORETURN void ___kmain(uint32_t magic, void *mb_info) {
271 //verify magic num
272 if (magic != 0x2BADB002) panic("kmain: invalid multiboot magic");
273
274 ___init(); //init system
275
276 while(1) {
277 shell(mb_info);
278 }
279}
280
#define cnb
Definition cm.h:6
#define cob
Definition cm.h:7
#define scur
Definition cm.h:8
#define hcur
Definition cm.h:9
#define panic
Definition err.h:5
#define assert
Definition err.h:4
#define ffsinit
Definition ffs.h:6
#define fsread
Definition fs.h:14
#define fsfind
Definition fs.h:11
#define fswrite
Definition fs.h:15
#define fsdelete
Definition fs.h:16
#define fsinit
Definition fs.h:9
#define hinit
Definition heap.h:24
#define alc
Definition heap.h:25
#define anew
Definition heap.h:27
#define iwrt
Definition ide.h:19
#define ideinit
Definition ide.h:17
#define irsec
Definition ide.h:18
#define inb
Definition io.h:6
arena_t * fs_arena
the filesystem child arena
Definition main.c:56
#define KHEAP_SIZE
Definition main.c:16
void ___kmain(uint32_t magic, void *mb_info)
___kmain is the main kernel entry point after boot
Definition main.c:270
#define CMD_ARENA_SIZE
Definition main.c:18
static uint8_t kmem[(1024 *1024)]
description of heap sizes in src/kernel/main.c
Definition main.c:45
void * malloc(uint32_t size)
malloc is a gdb friendly wrapper around alc
Definition main.c:249
arena_t * cmd_arena
the command processing child arena
Definition main.c:66
#define FS_ARENA_SIZE
Definition main.c:17
void ___init(void)
___init initializes all kernel subsystems
Definition main.c:86
static int ___init_called
Definition main.c:68
arena_t kheap
Definition main.c:46
#define pinit
Definition pit.h:7
#define shell
Definition shell.h:4
the arena_t type
Definition heap.h:17
#define NULL
Definition types.h:38
unsigned int uint32_t
Definition types.h:30
#define NORETURN
Definition types.h:40
unsigned char uint8_t
Definition types.h:28
int strcmp(const char *a, const char *b)
Definition utils.c:15
#define prt
Definition vga.h:6
#define clscr
Definition vga.h:7