Compare commits
5 Commits
2a49da9d5f
...
5224d33fb4
Author | SHA1 | Date |
---|---|---|
Victor Timofei | 5224d33fb4 | |
Victor Timofei | 3392bda28d | |
Victor Timofei | 47a80204a5 | |
Victor Timofei | 2a45bc4b20 | |
Victor Timofei | ba3c0964a0 |
|
@ -2,8 +2,8 @@
|
|||
SOURCES_S := boot.s boot64.s
|
||||
OBJECTS_S := $(patsubst %.s, $(BUILD_DIR)/kernel/%.o, $(SOURCES_S))
|
||||
|
||||
SOURCES_C := kernel.c
|
||||
HEADERS_C := multiboot.h psf.h
|
||||
SOURCES_C := kernel.c kprintf.c console.c
|
||||
HEADERS_C := multiboot.h psf.h kprintf.h console.h
|
||||
OBJECTS_C := $(patsubst %.c, $(BUILD_DIR)/kernel/%.o, $(SOURCES_C))
|
||||
|
||||
LINKER_LD := linker.ld
|
||||
|
|
|
@ -92,8 +92,6 @@ page_table_l3:
|
|||
.skip 4096
|
||||
page_table_l2:
|
||||
.skip 4096
|
||||
page_table_l3_framebuffer:
|
||||
.skip 4096
|
||||
page_table_l2_framebuffer:
|
||||
.skip 4096
|
||||
stack_bottom:
|
||||
|
@ -106,11 +104,6 @@ gdt64:
|
|||
.quad GDT_ZERO_ENTRY
|
||||
.set gdt64_code_segment, . - gdt64
|
||||
.quad GDT_FLAGS
|
||||
/*
|
||||
gdt64_data_entry:
|
||||
.set gdt64_data_segment, gdt64_data_entry - gdt64
|
||||
.quad (1<<44) | (1<<46) | (1<<41)
|
||||
*/
|
||||
gdt64_pointer:
|
||||
.word . - gdt64 - 1
|
||||
.quad gdt64
|
||||
|
|
|
@ -12,7 +12,6 @@ long_mode_start:
|
|||
movw %ax, %gs
|
||||
|
||||
/* We should keep the pointer to mb, debug needed */
|
||||
push %rbx /* Multiboot struct pointer */
|
||||
mov %rbx, %rdi
|
||||
call kernel_main
|
||||
hlt
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
#include "console.h"
|
||||
#include "psf.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* graphics framebuffer */
|
||||
char *fb;
|
||||
/* number of bytes in each line */
|
||||
int scanline;
|
||||
|
||||
uint32_t console_y;
|
||||
uint32_t console_x;
|
||||
|
||||
uint32_t console_rows;
|
||||
uint32_t console_cols;
|
||||
|
||||
multiboot_info_t *mbi;
|
||||
|
||||
psf_font_t *font;
|
||||
|
||||
/*
|
||||
* We write a character on the screen using the psf font.
|
||||
* This function is not meant for external usage as it does not
|
||||
* handle line breaking, scrolling, and special characters such
|
||||
* as linefeed.
|
||||
*/
|
||||
void putchar (uint16_t c, int32_t cx, int32_t cy, uint32_t fg, uint32_t bg)
|
||||
{
|
||||
uint32_t bytesperline = (font->width + 7) / 8;
|
||||
|
||||
unsigned char *glyph = (unsigned char *)font + font->headersize +
|
||||
(c > 0 && c < font->numglyphs ? c : 0) * font->bytesperglyph;
|
||||
|
||||
uint32_t offs = (cy * font->height * scanline) + (cx * (font->width) * sizeof (PIXEL));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void set_pixel(uint64_t x, uint64_t y, PIXEL color)
|
||||
{
|
||||
uint32_t pos = (y * sizeof (PIXEL) * mbi->framebuffer_width) + (x * sizeof (PIXEL));
|
||||
*((PIXEL *)(fb+pos)) = color;
|
||||
}
|
||||
|
||||
PIXEL get_pixel(uint64_t x, uint64_t y)
|
||||
{
|
||||
uint32_t pos = (y * sizeof (PIXEL) * mbi->framebuffer_width) + (x * sizeof (PIXEL));
|
||||
return *((PIXEL *)(fb+pos));
|
||||
}
|
||||
|
||||
/*
|
||||
* Move all characters one row above.
|
||||
*/
|
||||
void console_scroll()
|
||||
{
|
||||
const uint32_t width = mbi->framebuffer_width;
|
||||
const uint32_t font_height = font->height;
|
||||
|
||||
/* Move each row to the previous one */
|
||||
for (uint32_t row = 1; row < console_rows; row++) {
|
||||
for (uint32_t y = 0; y < font_height; y++ ) {
|
||||
for (uint32_t x = 0; x < width; x++ ) {
|
||||
PIXEL p = get_pixel(x, (row * font_height) + y);
|
||||
set_pixel(x, ((row - 1) * font_height) + y, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset bottom row*/
|
||||
for (uint32_t y = 0; y < font_height; y++ ) {
|
||||
for (uint32_t x = 0; x < width; x++ ) {
|
||||
set_pixel(x, ((console_rows - 1) * font_height) + y, CONSOLE_BG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a single character the console.
|
||||
* The console is a share resource, a syncing mechanism must be used.
|
||||
* The console scrolling and line wrapping is handled.
|
||||
*/
|
||||
void console_puts(uint16_t ch)
|
||||
{
|
||||
if (ch == '\n') {
|
||||
console_x = 0;
|
||||
console_y++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (console_x >= console_cols) {
|
||||
console_x = 0;
|
||||
console_y++;
|
||||
}
|
||||
|
||||
if (console_y >= console_rows)
|
||||
console_scroll();
|
||||
|
||||
putchar((uint16_t) ch, console_x, console_y, CONSOLE_FG, CONSOLE_BG);
|
||||
console_x++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a character array to the console.
|
||||
* The console is a share resource, a syncing mechanism must be used.
|
||||
*/
|
||||
void console_write(char *str)
|
||||
{
|
||||
for (int idx = 0; str[idx] != '\0'; idx++ ) {
|
||||
console_puts(str[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the console.
|
||||
*/
|
||||
void console_init(multiboot_info_t *multiboot_struct)
|
||||
{
|
||||
mbi = multiboot_struct;
|
||||
fb = (char *)mbi->framebuffer_addr;
|
||||
scanline = mbi->framebuffer_pitch;
|
||||
|
||||
font = (psf_font_t *)&consolefonts_binary__start;
|
||||
|
||||
console_rows = mbi->framebuffer_height / font->height;
|
||||
console_cols = mbi->framebuffer_width / font->width;
|
||||
|
||||
console_x = 0;
|
||||
console_y = 0;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#include "multiboot.h"
|
||||
|
||||
#ifndef CONSOLE_HEADER
|
||||
#define CONSOLE_HEADER 1
|
||||
|
||||
#define PIXEL uint32_t
|
||||
|
||||
#define CONSOLE_BG 0
|
||||
#define CONSOLE_FG 0xFFFFFFFF
|
||||
|
||||
void console_init(multiboot_info_t *mbi);
|
||||
|
||||
void console_write(char *str);
|
||||
|
||||
void console_puts(uint16_t ch);
|
||||
|
||||
#endif
|
175
kernel/kernel.c
175
kernel/kernel.c
|
@ -1,7 +1,6 @@
|
|||
#include "multiboot.h"
|
||||
#include "psf.h"
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include "console.h"
|
||||
#include "kprintf.h"
|
||||
|
||||
#if defined (__linux__)
|
||||
#error "You are not using a cross-compiler, you will most certainly run into trouble"
|
||||
|
@ -11,172 +10,8 @@
|
|||
#error "The kernel needs to be compiled with a x86_64-elf compiler"
|
||||
#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;
|
||||
|
||||
uint32_t console_max_y;
|
||||
uint32_t console_max_x;
|
||||
|
||||
#define PIXEL uint32_t
|
||||
|
||||
#define CONSOLE_BG 0
|
||||
#define CONSOLE_FG 0xFFFFFFFF
|
||||
|
||||
void putchar (uint16_t c, int32_t cx, int32_t cy, uint32_t fg, uint32_t bg)
|
||||
void kernel_main (multiboot_info_t *multiboot_struct_addr)
|
||||
{
|
||||
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;
|
||||
|
||||
uint32_t offs = (cy * font->height * scanline) + (cx * (font->width) * sizeof (PIXEL));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void console_push()
|
||||
{
|
||||
// TODO: implement console pushing
|
||||
}
|
||||
|
||||
void console_puts(uint16_t ch)
|
||||
{
|
||||
if (ch == '\n') {
|
||||
console_x = 0;
|
||||
console_y++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (console_x >= console_max_x) {
|
||||
console_x = 0;
|
||||
console_y++;
|
||||
}
|
||||
|
||||
if (console_y > console_max_y)
|
||||
console_push();
|
||||
|
||||
putchar((uint16_t) ch, console_x, console_y, CONSOLE_FG, CONSOLE_BG);
|
||||
console_x++;
|
||||
}
|
||||
|
||||
void console_write(char *str)
|
||||
{
|
||||
for (int idx = 0; str[idx] != '\0'; idx++ ) {
|
||||
console_puts(str[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
void console_init(multiboot_info_t *mbi)
|
||||
{
|
||||
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;
|
||||
|
||||
console_x = 0;
|
||||
console_y = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
int remainder = num % base;
|
||||
|
||||
if (remainder > 9)
|
||||
buf[idx] = remainder - 10 + 'A';
|
||||
else
|
||||
buf[idx] = remainder + '0';
|
||||
|
||||
num /= base;
|
||||
idx++;
|
||||
} while(num != 0);
|
||||
|
||||
buf[idx] = '\0';
|
||||
|
||||
for (int i = 0; i < idx / 2; i++) {
|
||||
int tmp = buf[i];
|
||||
buf[i] = buf[idx-1-i];
|
||||
buf[idx-1-i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
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] != '%') {
|
||||
|
||||
/* Never overrun the buffer */
|
||||
if (format[idx] == '\0')
|
||||
return;
|
||||
|
||||
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;
|
||||
case 'X':
|
||||
i = va_arg(arg, int);
|
||||
|
||||
convert(i, 16, buffer, 50);
|
||||
console_write(buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
void kernel_main (uint32_t multiboot_struct_addr)
|
||||
{
|
||||
mbi = (multiboot_info_t *)multiboot_struct_addr;
|
||||
fb = (char *)mbi->framebuffer_addr;
|
||||
scanline = mbi->framebuffer_pitch;
|
||||
|
||||
console_init(mbi);
|
||||
kprintf("Console width is %d\n", mbi->framebuffer_width);
|
||||
console_init(multiboot_struct_addr);
|
||||
kprintf("Hello World");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
#include "console.h"
|
||||
#include "kprintf.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Converts a decimal number to a different base.
|
||||
*/
|
||||
void convert(uint64_t num, int base, char *buf, int bufsize)
|
||||
{
|
||||
int idx = 0;
|
||||
buf[idx] = '\0';
|
||||
|
||||
do {
|
||||
/* Avoid buffer overrun */
|
||||
if (idx == bufsize - 1)
|
||||
break;
|
||||
|
||||
int remainder = num % base;
|
||||
|
||||
if (remainder > 9)
|
||||
buf[idx] = remainder - 10 + 'A';
|
||||
else
|
||||
buf[idx] = remainder + '0';
|
||||
|
||||
num /= base;
|
||||
idx++;
|
||||
} while(num != 0);
|
||||
|
||||
buf[idx] = '\0';
|
||||
|
||||
for (int i = 0; i < idx / 2; i++) {
|
||||
int tmp = buf[i];
|
||||
buf[i] = buf[idx-1-i];
|
||||
buf[idx-1-i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print formatted string.
|
||||
*/
|
||||
void kprintf(char *format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
|
||||
char buffer[50];
|
||||
long i;
|
||||
|
||||
for (int idx = 0; format[idx] != '\0'; idx++) {
|
||||
while (format[idx] != '%') {
|
||||
|
||||
/* Never overrun the buffer */
|
||||
if (format[idx] == '\0')
|
||||
return;
|
||||
|
||||
console_puts(format[idx]);
|
||||
idx++;
|
||||
}
|
||||
idx++;
|
||||
switch (format[idx]) {
|
||||
case 'd':
|
||||
i = va_arg(arg, long);
|
||||
if (i < 0) {
|
||||
i = -i;
|
||||
console_puts('-');
|
||||
}
|
||||
|
||||
convert(i, 10, buffer, 50);
|
||||
console_write(buffer);
|
||||
break;
|
||||
case 'X':
|
||||
i = va_arg(arg, long);
|
||||
|
||||
convert(i, 16, buffer, 50);
|
||||
console_write(buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(arg);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef KPRINTF_HEADER
|
||||
#define KPRINTF_HEADER 1
|
||||
|
||||
void kprintf(char *format, ...);
|
||||
|
||||
#endif
|
|
@ -5,6 +5,10 @@
|
|||
|
||||
#define PSF_FONT_MAGIC 0x864ab572
|
||||
|
||||
/* extern the symbols in the psf object */
|
||||
extern char consolefonts_binary__start;
|
||||
extern char consolefonts_binary__end;
|
||||
|
||||
struct psf_font {
|
||||
uint32_t magic; /* magic bytes to identify psf */
|
||||
uint32_t version; /* zero */
|
||||
|
|
Loading…
Reference in New Issue