separating: there will be libk and libc

This commit is contained in:
2025-01-07 15:23:14 +01:00
parent b3687d20ee
commit a8582ba343
32 changed files with 29 additions and 31 deletions

131
drivers/framebuffer.c Normal file
View File

@@ -0,0 +1,131 @@
// Framebuffer driver
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include <stdint.h>
#include "framebuffer.h"
#include "serial.h"
#include "../kernel/system.h"
#include "../kernel/kheap.h"
extern char* framebuffer;
void psf_init()
{
uint16_t glyph = 0;
PSF_font *font = (PSF_font*)&FONT_START;
if (font->flags)
{
unicode = NULL;
return;
}
char* s = (char*)((unsigned char*)&FONT_START + font->headersize + font->numglyph * font->bytesperglyph);
unicode = calloc(USHRT_MAX, 2);
while((uintptr_t)s>(uintptr_t)FONT_END){
uint16_t uc = (uint16_t)((unsigned char)s[0]);
if(uc == 0xFF) {
glyph++;
s++;
continue;
} else if(uc & 128) {
/* UTF-8 to unicode */
if((uc & 32) == 0 ) {
uc = ((s[0] & 0x1F)<<6)+(s[1] & 0x3F);
s++;
} else
if((uc & 16) == 0 ) {
uc = ((((s[0] & 0xF)<<6)+(s[1] & 0x3F))<<6)+(s[2] & 0x3F);
s+=2;
} else
if((uc & 8) == 0 ) {
uc = ((((((s[0] & 0x7)<<6)+(s[1] & 0x3F))<<6)+(s[2] & 0x3F))<<6)+(s[3] & 0x3F);
s+=3;
} else
uc = 0;
}
/* save translation */
unicode[uc] = glyph;
s++;
}
}
void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color)
{
uint32_t* pixel_addr = (uint32_t*)((uint8_t*)fb + y * pitch + x *(bpp / 8));
*pixel_addr = color;
}
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg)
{
PSF_font *font = (PSF_font*)&FONT_START;
int bytesperline=(font->width+7)/8;
if (unicode != NULL) {
c = unicode[c];
}
unsigned char* glyph = (unsigned char*)&FONT_START + font->headersize + (c>0&&c<font->numglyph?c:0)*font->bytesperglyph;
int offs =
(cy * font->height * scanline) +
(cx * (font->width) * sizeof(PIXEL));
unsigned int x, y;
int line, mask;
for (y=0; y<font->height; y++)
{
line=offs;
mask=1<<(font->width-1);
for (x=0; x<font->width; x++)
{
*((PIXEL*)(framebuffer + line)) = *((unsigned int*)glyph) & mask ? fg : bg;
mask >>= 1;
line += sizeof(PIXEL);
}
glyph += bytesperline;
offs += scanline;
}
}
void scroll()
{
serial_printf(3, "Scrolling...\r");
uint32_t bg_color = 0x00000000;
PSF_font *font = (PSF_font*)&FONT_START;
int line_size = font->height * scanline;
int framebuffer_size = scanline * font->height * (1080/font->height);
// Erasing first line
for (uint32_t y=0; y<font->height; y++)
{
for (uint32_t x=0; x<scanline/sizeof(PIXEL); x++)
{
*((PIXEL*)(framebuffer + y * scanline + x * sizeof(PIXEL))) = bg_color;
}
}
// Moving all lines up by 1 line
for (int y=1; y<(framebuffer_size/line_size); y++)
{
void* src = framebuffer + y*line_size;
void* dst = framebuffer + (y-1)*line_size;
memmove(dst, src, line_size);
}
// Erasing last line
int last_line_start = (framebuffer_size/line_size-1) * line_size;
for (uint32_t y=0; y<font->height; y++)
{
for (uint32_t x=0; x<scanline/sizeof(PIXEL); x++)
{
*((PIXEL*)(framebuffer + last_line_start + y * scanline + x * sizeof(PIXEL))) = bg_color;
}
}
}

48
drivers/framebuffer.h Normal file
View File

@@ -0,0 +1,48 @@
// Framebuffer driver header
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#ifndef FRAMEBUFFER_H
#define FRAMEBUFFER_H
#include <stdint.h>
extern int scanline;
#define FONT_START _binary_include_fonts_viscii10_8x16_psfu_start
#define FONT_END _binary_include_fonts_viscii10_8x16_psfu_start
extern char FONT_START;
extern char FONT_END;
uint16_t* unicode;
#define PIXEL uint32_t
#define USHRT_MAX 10000
#define PSF1_FONT_MAGIC 0x0436
typedef struct {
uint16_t magic; // Magic bytes for identification.
uint8_t fontMode; // PSF font mode.
uint8_t characterSize; // PSF character size.
} PSF1_Header;
#define PSF_FONT_MAGIC 0x864ab572
typedef struct {
uint32_t magic; /* magic bytes to identify PSF */
uint32_t version; /* zero */
uint32_t headersize; /* offset of bitmaps in file, 32 */
uint32_t flags; /* 0 if there's no unicode table */
uint32_t numglyph; /* number of glyphs */
uint32_t bytesperglyph; /* size of each glyph */
uint32_t height; /* height in pixels */
uint32_t width; /* width in pixels */
} PSF_font;
void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color);
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg);
void scroll();
void psf_init();
#endif

286
drivers/serial.c Normal file
View File

@@ -0,0 +1,286 @@
// Serial I/O driver
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "../kernel/io.h"
#include "serial.h"
#include "../libk/stdio.h"
int init_serial()
{
outb(PORT+1, 0x00);
outb(PORT+3, 0x80);
outb(PORT+0, 0x03);
outb(PORT+1, 0x00);
outb(PORT+3, 0x03);
outb(PORT+2, 0xC7);
outb(PORT+4, 0x0B);
outb(PORT+4, 0x1E);
outb(PORT+0, 0xAE);
if (inb(PORT+0) != 0xAE) {
return 1;
}
outb(PORT+4, 0x0F);
puts("[serial] initialized i/o on port COM1\n");
return 0;
}
int is_transmit_empty()
{
return inb(PORT+5) & 0x20;
}
void write_serial(const char a)
{
while (is_transmit_empty() == 0);
outb(PORT, a);
}
void serial_puts(const char* str)
{
unsigned int i = 0;
write_serial(str[0]); // Transmit first byte 2 times
while (*str++)
{
write_serial(str[i]);
}
}
void log(const char* str, const int errlevel)
{
switch (errlevel)
{
case 0:
serial_puts("[ERROR] ");
break;
case 1:
serial_puts("[WARNING] ");
break;
case 2:
serial_puts("[INFO] ");
break;
case 3:
serial_puts("[DEBUG] ");
break;
}
serial_puts(str);
}
const char serial_charset[] = "0123456789abcdef";
int* serial_printf_number(int* argp, int length, bool sign, int radix)
{
char buffer[32];
unsigned long long number;
int number_sign = 1;
int pos = 0;
switch(length)
{
case PRINTF_LENGTH_SHORT_SHORT:
case PRINTF_LENGTH_SHORT:
case PRINTF_LENGTH_START:
if (sign)
{
int n = *argp;
if (n < 0)
{
n = -n;
number_sign = -1;
}
number = (unsigned long long) n;
}
else {
number = *(unsigned int*) argp;
}
argp++;
break;
case PRINTF_LENGTH_LONG:
if (sign)
{
long int n = *(long int*)argp;
if (n < 0)
{
n = -n;
number_sign = -1;
}
number = (unsigned long long) n;
}
else {
number = *(unsigned long int*) argp;
}
argp += 2;
break;
case PRINTF_LENGTH_LONG_LONG:
if (sign)
{
long long int n = *(long long int*)argp;
if (n < 0)
{
n = -n;
number_sign = -1;
}
number = (unsigned long long) n;
}
else {
number = *(unsigned long long int*) argp;
}
argp += 4;
break;
}
do {
uint32_t rem;
x86_div64_32(number, radix, &number, &rem);
buffer[pos++] = serial_charset[rem];
} while (number > 0);
if (sign && number_sign < 0)
{
buffer[pos++] = '-';
}
while (--pos >= 0)
{
write_serial(buffer[pos]);
}
return argp;
}
void serial_printf(int errlevel, const char* fmt, ...)
{
switch (errlevel)
{
case 0:
serial_puts("[ERROR] ");
break;
case 1:
serial_puts("[WARNING] ");
break;
case 2:
serial_puts("[INFO] ");
break;
case 3:
serial_puts("[DEBUG] ");
break;
}
int* argp = (int*) &fmt;
int state = PRINTF_STATE_START;
int length = PRINTF_LENGTH_START;
int radix = 10;
bool sign = false;
argp++;
while (*fmt)
{
switch(state) {
case PRINTF_STATE_START:
if (*fmt == '%')
{
state = PRINTF_STATE_LENGTH;
}
else {
write_serial(*fmt);
}
break;
case PRINTF_STATE_LENGTH:
if (*fmt == 'h')
{
length = PRINTF_LENGTH_SHORT;
state = PRINTF_STATE_SHORT;
}
else if (*fmt == 'l')
{
length = PRINTF_LENGTH_LONG;
state = PRINTF_STATE_LONG;
}
else {
goto PRINTF_STATE_SPEC_;
}
break;
case PRINTF_STATE_SHORT:
if (*fmt == 'h')
{
length = PRINTF_LENGTH_SHORT_SHORT;
state = PRINTF_STATE_SPEC;
}
else {
goto PRINTF_STATE_SPEC_;
}
break;
case PRINTF_STATE_LONG:
if (*fmt == 'l')
{
length = PRINTF_LENGTH_LONG_LONG;
state = PRINTF_STATE_SPEC;
}
else {
goto PRINTF_STATE_SPEC_;
}
break;
case PRINTF_STATE_SPEC:
PRINTF_STATE_SPEC_:
switch(*fmt)
{
case 'c':
serial_puts(*(const char **)argp);
argp++;
break;
case 's':
serial_puts(*(const char **)argp);
argp++;
break;
case '%':
putc('%');
break;
case 'd':
case 'i':
radix = 10;
sign = true;
argp = serial_printf_number(argp, length, sign, radix);
break;
case 'u':
radix = 10;
sign = false;
argp = serial_printf_number(argp, length, sign, radix);
break;
case 'X':
case 'x':
case 'p':
radix = 16;
sign = false;
argp = serial_printf_number(argp, length, sign, radix);
break;
case 'o':
radix = 8;
sign = false;
argp = serial_printf_number(argp, length, sign, radix);
break;
case 'f': {
// Handle floating-point numbers
double* dargp = (double*)argp;
double d = *(double*)dargp;
char buffer[64];
dtostrf(d, buffer, 6); // Default precision: 6
serial_puts(buffer);
argp += 2; // Incrementing by 2 to move past the double argument
break;
}
default:
break;
}
state = PRINTF_STATE_START;
length = PRINTF_LENGTH_START;
radix = 10;
sign = false;
break;
}
fmt++;
}
serial_puts("\r\n");
}

18
drivers/serial.h Normal file
View File

@@ -0,0 +1,18 @@
// Serial I/O driver header
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#ifndef SERIAL_H
#define SERIAL_H
#define PORT 0x3f8 //COM1
int init_serial();
int is_transmit_empty();
void write_serial(const char a);
void serial_puts(const char* str);
void log(const char* str, const int errlevel);
void serial_printf(int errlevel, const char* fmt, ...);
#endif

38
drivers/timer.c Normal file
View File

@@ -0,0 +1,38 @@
// Programmable Interval Timer channel 0 driver
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "../kernel/system.h"
#include "../libk/stdio.h"
volatile unsigned long global_ticks = 0;
void timer_handler()
{
global_ticks++;
if (global_ticks % 20 == 0)
{
draw_cursor(white);
} else if (global_ticks % 20 == 10) {
erase_cursor();
}
}
void timer_install()
{
irq_install_handler(0, timer_handler);
printf("[timer] initialized, starting g_ticks...\n");
}
void delay(int ticks)
{
unsigned long eticks;
eticks = global_ticks + ticks;
while (global_ticks < eticks);
}
int uptime()
{
return global_ticks;
}