2022-04-25 19:16:07 +00:00
|
|
|
#include "multiboot.h"
|
|
|
|
#include "psf.h"
|
|
|
|
#include <stdint.h>
|
2022-05-02 21:59:24 +00:00
|
|
|
#include <stdarg.h>
|
2022-04-25 19:16:07 +00:00
|
|
|
|
|
|
|
#if defined (__linux__)
|
|
|
|
#error "You are not using a cross-compiler, you will most certainly run into trouble"
|
|
|
|
#endif
|
|
|
|
|
2022-05-02 14:26:07 +00:00
|
|
|
#if !defined (__x86_64__)
|
|
|
|
#error "The kernel needs to be compiled with a x86_64-elf compiler"
|
2022-04-25 19:16:07 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* graphics framebuffer */
|
|
|
|
char *fb;
|
|
|
|
/* number of bytes in each line */
|
|
|
|
int scanline;
|
|
|
|
/* extern the symbols in the psf object */
|
|
|
|
extern char consolefonts_binary__start;
|
|
|
|
extern char consolefonts_binary__end;
|
|
|
|
|
|
|
|
multiboot_info_t *mbi;
|
|
|
|
uint32_t console_y;
|
|
|
|
uint32_t console_x;
|
|
|
|
|
2022-05-02 21:59:24 +00:00
|
|
|
uint32_t console_max_y;
|
|
|
|
uint32_t console_max_x;
|
|
|
|
|
2022-04-25 19:16:07 +00:00
|
|
|
#define PIXEL uint32_t
|
|
|
|
|
2022-05-02 19:56:36 +00:00
|
|
|
#define CONSOLE_BG 0
|
|
|
|
#define CONSOLE_FG 0xFFFFFFFF
|
|
|
|
|
2022-04-25 19:16:07 +00:00
|
|
|
void putchar (uint16_t c, int32_t cx, int32_t cy, uint32_t fg, uint32_t bg)
|
|
|
|
{
|
|
|
|
psf_font_t *font = (psf_font_t *)&consolefonts_binary__start;
|
|
|
|
uint32_t bytesperline = (font->width + 7) / 8;
|
|
|
|
|
|
|
|
unsigned char *glyph = (unsigned char *)&consolefonts_binary__start + font->headersize +
|
|
|
|
(c > 0 && c < font->numglyphs ? c : 0) * font->bytesperglyph;
|
|
|
|
|
2022-05-03 18:27:52 +00:00
|
|
|
uint32_t offs = (cy * font->height * scanline) + (cx * (font->width) * sizeof (PIXEL));
|
2022-04-25 19:16:07 +00:00
|
|
|
|
|
|
|
uint32_t x, y, line, mask;
|
|
|
|
for (y = 0; y < font->height; y++) {
|
|
|
|
line = offs;
|
|
|
|
mask = 1 << (font->width -1);
|
|
|
|
for (x = 0; x < font->width; x++) {
|
|
|
|
*((PIXEL *)(fb+line)) = *((uint32_t *)glyph) & mask ? fg : bg;
|
|
|
|
mask >>= 1;
|
|
|
|
line += sizeof (PIXEL);
|
|
|
|
}
|
|
|
|
glyph += bytesperline;
|
|
|
|
offs += scanline;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-05-02 21:59:24 +00:00
|
|
|
void console_push()
|
|
|
|
{
|
|
|
|
// TODO: implement console pushing
|
|
|
|
}
|
|
|
|
|
|
|
|
void console_puts(uint16_t ch)
|
|
|
|
{
|
2022-05-03 18:27:52 +00:00
|
|
|
if (ch == '\n') {
|
2022-05-02 21:59:24 +00:00
|
|
|
console_x = 0;
|
|
|
|
console_y++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-03 18:27:52 +00:00
|
|
|
if (console_x >= console_max_x) {
|
|
|
|
console_x = 0;
|
|
|
|
console_y++;
|
|
|
|
}
|
|
|
|
|
2022-05-02 21:59:24 +00:00
|
|
|
if (console_y > console_max_y)
|
|
|
|
console_push();
|
|
|
|
|
|
|
|
putchar((uint16_t) ch, console_x, console_y, CONSOLE_FG, CONSOLE_BG);
|
|
|
|
console_x++;
|
|
|
|
}
|
|
|
|
|
2022-05-02 19:56:36 +00:00
|
|
|
void console_write(char *str)
|
|
|
|
{
|
|
|
|
for (int idx = 0; str[idx] != '\0'; idx++ ) {
|
2022-05-02 21:59:24 +00:00
|
|
|
console_puts(str[idx]);
|
2022-05-02 19:56:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-02 21:59:24 +00:00
|
|
|
void console_init(multiboot_info_t *mbi)
|
2022-05-02 19:56:36 +00:00
|
|
|
{
|
2022-05-02 21:59:24 +00:00
|
|
|
psf_font_t *font = (psf_font_t *)&consolefonts_binary__start;
|
|
|
|
|
|
|
|
console_max_y = mbi->framebuffer_height / font->height - 1;
|
|
|
|
console_max_x = mbi->framebuffer_width / font->width - 1;
|
|
|
|
|
2022-05-02 19:56:36 +00:00
|
|
|
console_x = 0;
|
|
|
|
console_y = 0;
|
|
|
|
}
|
|
|
|
|
2022-05-02 21:59:24 +00:00
|
|
|
void convert(int num, int base, char *buf, int bufsize)
|
|
|
|
{
|
|
|
|
int idx = 0;
|
|
|
|
buf[idx] = '\0';
|
|
|
|
|
|
|
|
do {
|
|
|
|
/* Avoid buffer overrun */
|
|
|
|
if (idx == bufsize - 1)
|
|
|
|
break;
|
|
|
|
|
2022-05-03 20:24:05 +00:00
|
|
|
int remainder = num % base;
|
|
|
|
|
|
|
|
if (remainder > 9)
|
|
|
|
buf[idx] = remainder - 10 + 'A';
|
|
|
|
else
|
|
|
|
buf[idx] = remainder + '0';
|
|
|
|
|
2022-05-02 21:59:24 +00:00
|
|
|
num /= base;
|
|
|
|
idx++;
|
|
|
|
} while(num != 0);
|
|
|
|
|
|
|
|
buf[idx] = '\0';
|
|
|
|
|
|
|
|
for (int i = 0; i < idx / 2; i++) {
|
|
|
|
int tmp = buf[i];
|
2022-05-03 18:47:18 +00:00
|
|
|
buf[i] = buf[idx-1-i];
|
|
|
|
buf[idx-1-i] = tmp;
|
2022-05-02 21:59:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void kprintf(char *format, ...)
|
|
|
|
{
|
|
|
|
va_list arg;
|
|
|
|
va_start(arg, format);
|
|
|
|
|
|
|
|
char buffer[50];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (int idx = 0; format[idx] != '\0'; idx++) {
|
|
|
|
while (format[idx] != '%') {
|
2022-05-03 20:01:43 +00:00
|
|
|
|
|
|
|
/* Never overrun the buffer */
|
2022-05-02 21:59:24 +00:00
|
|
|
if (format[idx] == '\0')
|
2022-05-03 20:01:43 +00:00
|
|
|
return;
|
2022-05-02 21:59:24 +00:00
|
|
|
|
|
|
|
console_puts(format[idx]);
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
idx++;
|
|
|
|
switch (format[idx]) {
|
|
|
|
case 'd':
|
|
|
|
i = va_arg(arg, int);
|
|
|
|
if (i < 0) {
|
|
|
|
i = -i;
|
|
|
|
console_puts('-');
|
|
|
|
}
|
|
|
|
|
|
|
|
convert(i, 10, buffer, 50);
|
|
|
|
console_write(buffer);
|
|
|
|
break;
|
2022-05-03 20:24:05 +00:00
|
|
|
case 'X':
|
|
|
|
i = va_arg(arg, int);
|
|
|
|
|
|
|
|
convert(i, 16, buffer, 50);
|
|
|
|
console_write(buffer);
|
|
|
|
break;
|
2022-05-02 21:59:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
va_end(arg);
|
|
|
|
}
|
|
|
|
|
2022-04-25 20:48:28 +00:00
|
|
|
void kernel_main (uint32_t multiboot_struct_addr)
|
2022-04-25 19:16:07 +00:00
|
|
|
{
|
|
|
|
mbi = (multiboot_info_t *)multiboot_struct_addr;
|
|
|
|
fb = (char *)mbi->framebuffer_addr;
|
|
|
|
scanline = mbi->framebuffer_pitch;
|
|
|
|
|
2022-05-02 21:59:24 +00:00
|
|
|
console_init(mbi);
|
|
|
|
kprintf("Console width is %d\n", mbi->framebuffer_width);
|
2022-04-25 19:16:07 +00:00
|
|
|
}
|