From 8251da342161767fe203627223ccd4a7026701c6 Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Fri, 4 Sep 2026 11:31:40 -0400 Subject: initial commit. working on tasking --- lib/panic.c | 18 ++++++++ lib/panic.h | 8 ++++ lib/printf.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/printf.h | 12 +++++ lib/psf.c | 8 ++++ lib/psf.h | 19 ++++++++ lib/string.c | 50 +++++++++++++++++++++ lib/string.h | 16 +++++++ lib/tar.c | 16 +++++++ lib/tar.h | 25 +++++++++++ lib/virtterm.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/virtterm.h | 19 ++++++++ 12 files changed, 460 insertions(+) create mode 100644 lib/panic.c create mode 100644 lib/panic.h create mode 100644 lib/printf.c create mode 100644 lib/printf.h create mode 100644 lib/psf.c create mode 100644 lib/psf.h create mode 100644 lib/string.c create mode 100644 lib/string.h create mode 100644 lib/tar.c create mode 100644 lib/tar.h create mode 100644 lib/virtterm.c create mode 100644 lib/virtterm.h (limited to 'lib') diff --git a/lib/panic.c b/lib/panic.c new file mode 100644 index 0000000..3b39fbf --- /dev/null +++ b/lib/panic.c @@ -0,0 +1,18 @@ +#include "panic.h" +#include "lib/printf.h" + +int _kernel_panic_unlock = 0; + +void +kpanic(const char *fmt, ...) +{ + _kernel_panic_unlock = 1; + + va_list ap; + va_start(ap, fmt); + + kvprintf(fmt, ap); + + va_end(ap); + hcf(); +} diff --git a/lib/panic.h b/lib/panic.h new file mode 100644 index 0000000..8f3b409 --- /dev/null +++ b/lib/panic.h @@ -0,0 +1,8 @@ +#ifndef _JOVE_LIB_PANIC_H +#define _JOVE_LIB_PANIC_H 1 + +#include "jove.h" + +NORETURN void kpanic(const char *fmt, ...); + +#endif diff --git a/lib/printf.c b/lib/printf.c new file mode 100644 index 0000000..4c26fe4 --- /dev/null +++ b/lib/printf.c @@ -0,0 +1,138 @@ +#include "printf.h" +#include "string.h" +#include "init.h" +#include "hal/obj.h" +#include + +int kprintf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int r = kvprintf(fmt, ap); + va_end(ap); + return r; +} + +#define SPRINTF_PUTC(str, size, i, c) \ + if(str && i < size) str[i] = (c); \ + i++ + +static int +convert_as_int( + char *str, + size_t size, + int stri, + int field_width, + uintmax_t value, + int radix, + int unsign) +{ + unsigned digits = 0; + int ostri = stri; + if((intmax_t)value < 0 && !unsign) { + SPRINTF_PUTC(str, size, stri, '-'); + value = 0 - (intmax_t)value; + } + + for(uintmax_t i = value; i != 0; i /= radix) digits++; + if(value == 0) digits++; + + if(field_width < digits) field_width = digits; + for(uintmax_t i = value, digiti = 0; digiti < digits; i /= radix) { + char i_mod = (char)(i % radix); + int stri_digiti = stri + (field_width - digiti) - 1; + + SPRINTF_PUTC(str, size, stri_digiti, + (i_mod > 9 ? (i_mod + 'a' - 10) : (i_mod + '0'))); + digiti++; + } + + return field_width + (stri - ostri) + 1; +} + +int +vsnprintf( + char *str, size_t size, + const char *fmt, va_list ap) +{ + int stri = 0; + for(const char *fmtc = fmt; *fmtc; fmtc++) { + if(*fmtc != '%') { + SPRINTF_PUTC(str, size, stri, *fmtc); + continue; + } + fmtc++; + + //TODO: other format specifiers. + int field_width = 0; + char field_pad = ' '; + + int lenspec = 4; + + int radix = 10; + int unsign = 0; + int caps = 0; + switch(*fmtc) { + case 's': + goto string_conversion; + case 'b': + radix = 2; + goto int_conversion; + break; + case 'o': + radix = 8; + goto int_conversion; + break; + case 'p': + lenspec = sizeof(uintptr_t); + field_width = lenspec * 2; + field_pad = '0'; + case 'X': + caps = 1; + case 'x': + unsign = 1; + radix = 16; + goto int_conversion; + break; + case 'u': + unsign = 1; + case 'd': + case 'i': + goto int_conversion; + break; + } +string_conversion: + { + const char *strarg = va_arg(ap, const char*); + for(const char *strargc = strarg; *strargc; strargc++) { + SPRINTF_PUTC(str, size, stri, *strargc); + } + } continue; +int_conversion: + { + uintmax_t value = 0; + switch(lenspec) { + case 1: value = (uintmax_t)(int8_t)va_arg(ap, int); break; + case 2: value = (uintmax_t)(int16_t)va_arg(ap, int); break; + default: + case 4: value = (uintmax_t)va_arg(ap, unsigned int); break; + case 8: value = (uintmax_t)va_arg(ap, uintmax_t); break; + } + size_t pad_stri = stri; + for(size_t i = 0; i < field_width; i++) { + SPRINTF_PUTC(str, size, pad_stri, field_pad); + } + + int advance = convert_as_int(str, size, stri, field_width, value, radix, unsign); + if(caps && str) { + for(int i = 0; i < advance; i++) { + int stra = stri + i; + if(stra < size) str[stra] = c_toupper(str[stra]); + } + } + stri += advance; + } continue; + } + if(str && stri < size) str[stri] = 0; + return stri; +} diff --git a/lib/printf.h b/lib/printf.h new file mode 100644 index 0000000..a132b39 --- /dev/null +++ b/lib/printf.h @@ -0,0 +1,12 @@ +#ifndef _JOVE_LIB_PRINTF_H +#define _JOVE_LIB_PRINTF_H 1 + +#include +#include + +int kprintf(const char *fmt, ...); +int kvprintf(const char *fmt, va_list ap); + +int vsnprintf(char *str, size_t size, const char *fmt, va_list ap); + +#endif diff --git a/lib/psf.c b/lib/psf.c new file mode 100644 index 0000000..407420e --- /dev/null +++ b/lib/psf.c @@ -0,0 +1,8 @@ +#include "psf.h" + +uint8_t* +psf_glyph(struct psf1_header *header, uint8_t glyph) +{ + uint8_t *glyph_bitmap = header->bitmap; + return &glyph_bitmap[(size_t)glyph * header->char_height]; +} diff --git a/lib/psf.h b/lib/psf.h new file mode 100644 index 0000000..b6b8cec --- /dev/null +++ b/lib/psf.h @@ -0,0 +1,19 @@ +#ifndef _JOVE_LIB_PSF_H +#define _JOVE_LIB_PSF_H 1 + +#include +#include + +#define PSF1_FONT_MAGIC 0x0436 + +struct psf1_header +{ + uint16_t magic; + uint8_t mode; + uint8_t char_height; + uint8_t bitmap[]; +}; + +uint8_t *psf_glyph(struct psf1_header *header, uint8_t glyph); + +#endif diff --git a/lib/string.c b/lib/string.c new file mode 100644 index 0000000..28436d5 --- /dev/null +++ b/lib/string.c @@ -0,0 +1,50 @@ +#include "string.h" + +void *memset(void *s, int c, size_t n) +{ + for(size_t i = 0; i < n; i++) { + ((char*)s)[i] = c; + } + return s; +} +void *memcpy(void *a, const void *b, size_t n) +{ + for(size_t i = 0; i < n; i++) { + ((char*)a)[i] = ((const char*)b)[i]; + } + return a; +} + +int memcmp(const void *a, const void *b, size_t n) +{ + const char *ca = a; + const char *cb = b; + for(size_t i = 0; i < n; i++) { + if(ca[i] != cb[i]) return ca[i] - cb[i]; + } + return 0; +} + +size_t strlen(const char *s) +{ + size_t i = 0; + for(; s[i]; i++); + return i; +} + +char c_toupper(char c) { + return (c > 0x60 && c < 0x7B) ? (c - 0x20) : c; +} + +char *str_toupper(char *s, size_t n) +{ + for(size_t i = 0; i < n; i++) { + s[i] = c_toupper(s[i]); + } + return s; +} + +int strncmp(const char *s1, const char *s2, size_t n) +{ + return memcmp(s1, s2, n); +} diff --git a/lib/string.h b/lib/string.h new file mode 100644 index 0000000..bdcb0dd --- /dev/null +++ b/lib/string.h @@ -0,0 +1,16 @@ +#ifndef _JOVE_STRING_H +#define _JOVE_STRING_H 1 + +#include + +void *memset(void *s, int c, size_t n); +void *memcpy(void *a, const void *b, size_t n); +int memcmp(const void *a, const void *b, size_t n); + +size_t strlen(const char *s); +char c_toupper(char c); +char *str_toupper(char *s, size_t n); + +int strncmp(const char *s1, const char *s2, size_t n); + +#endif diff --git a/lib/tar.c b/lib/tar.c new file mode 100644 index 0000000..58b94b4 --- /dev/null +++ b/lib/tar.c @@ -0,0 +1,16 @@ +#include "tar.h" + +const char* +tar_filename(struct tar_header *file) +{ + return file->filename; +} + +int +tar_filesize(struct tar_header *file) +{ + int r = 0; + const char *oct = file->size; + for(; *oct; oct++) r = (r * 8) + (*oct - '0'); + return r; +} diff --git a/lib/tar.h b/lib/tar.h new file mode 100644 index 0000000..d2435ac --- /dev/null +++ b/lib/tar.h @@ -0,0 +1,25 @@ +#ifndef _JOVE_HAL_TAR_H +#define _JOVE_HAL_TAR_H 1 + +struct tar_header +{ + char filename[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char modtime[12]; + char checksum[8]; + char type; +}; + +union tar_block +{ + struct tar_header header; + char data[512]; +}; + +const char *tar_filename(struct tar_header *header); +int tar_filesize(struct tar_header *header); + +#endif diff --git a/lib/virtterm.c b/lib/virtterm.c new file mode 100644 index 0000000..de43c51 --- /dev/null +++ b/lib/virtterm.c @@ -0,0 +1,131 @@ +#include "virtterm.h" +#include "boot/cmdline.h" +#include "boot/initrd.h" +#include "hal/obj.h" +#include "init.h" +#include "jove.h" +#include "hal/framebuffer.h" +#include "lib/printf.h" +#include "lib/psf.h" +#include "lib/string.h" + +struct psf1_header *s_font = NULL; + +struct virtterm s_init_vtty = { 0 }; + +static void +vt_blit(struct virtterm *vtty, jove_owned_obj_t *fb, const uint8_t *glyph) +{ + uint32_t buffer[s_font->char_height << 3]; + size_t cursor_x = vtty->cursor_col * 9; + size_t cursor_y = vtty->cursor_row * s_font->char_height; + + for(size_t y = 0; y < s_font->char_height; y++) { + uint8_t mask = 1 << 7; + for(size_t x = 0; x < 8; x++) { + buffer[x + (y << 3)] = glyph[y] & mask ? vtty->cursor_fg : vtty->cursor_bg; + mask >>=1; + } + } + fb_blit(fb, buffer, cursor_x, cursor_y, 8, s_font->char_height); + vtty->cursor_col++; +} + +static void +vt_putc(struct virtterm *vtty, jove_owned_obj_t *fb, char c) +{ + const uint8_t *glyph = &s_font->bitmap[(size_t)c * s_font->char_height]; + + switch(c) { + case '\n': + vtty->cursor_col = 0; + vtty->cursor_row++; + break; + default: + vt_blit(vtty, fb, glyph); + break; + } + + if(vtty->cursor_col >= vtty->width) { + vtty->cursor_col = 0; + vtty->cursor_row++; + } + if(vtty->cursor_row >= vtty->height) { + vtty->cursor_row = 0; + } +} + +int +vt_write(jove_owned_obj_t *obj, const char *s, size_t n) +{ + if(obj_gettype(obj) != JOVE_OBJ_VIRTTERM) { + reterr(EBADOBJ); + } + + struct virtterm *vtty = obj_deref(obj); + jove_owned_obj_t *fb_obj = obj_take(objdir_getlocal(_rootdir_obj, vtty->fb_obj)); + if(obj_gettype(fb_obj) != JOVE_OBJ_FRAMEBUFFER) { + obj_release(fb_obj); + reterr(EBADOBJ); + } + + for(size_t i = 0; i < n; i++) { + vt_putc(vtty, fb_obj, s[i]); + } + + obj_release(fb_obj); + return 0; +} + +void +vt_init() +{ + const char *font_path = cmdline_getarg("font"); + if(font_path == NULL) { + kprintf("Kernel commandline is missing 'font' argument. VTT is disabled."); + return; + } + + jove_owned_obj_t *initrd_obj = obj_take(objdir_getlocal(_rootdir_obj, ROOTDIR_INITRD_I)); + if(obj_gettype(initrd_obj) != JOVE_OBJ_OBJDIR) { + kprintf("Initrd is not present. VTT is disabled.\n"); + obj_release(initrd_obj); + return; + } + + jove_owned_obj_t *file_obj; + size_t file_i = 0; + while((file_obj = obj_take(objdir_getlocal(initrd_obj, file_i++)))) { + const char *filename = NULL; + if(initrd_file_name(file_obj, &filename) != 0) { + break; + } + if(strncmp(font_path, filename, strlen(font_path)) == 0) { + initrd_file_data(file_obj, (uintptr_t*)&s_font); + break; + } + obj_release(file_obj); + } + obj_release(file_obj); + obj_release(initrd_obj); + + if(s_font == NULL) { + kprintf("Could not find file %s in initrd. VTT is disabled.\n", font_path); + return; + } + s_init_vtty.fb_obj = ROOTDIR_FRAMEBUFFER_I; + s_init_vtty.cursor_fg = 0x00FFFFFF; + + + { + jove_owned_obj_t *fb_obj = obj_take(objdir_getlocal(_rootdir_obj, ROOTDIR_FRAMEBUFFER_I)); + s_init_vtty.width = fb_width(fb_obj) / 9; + s_init_vtty.height = fb_height(fb_obj) / s_font->char_height; + obj_release(fb_obj); + + jove_owned_obj_t *vt_obj = obj_take(objdir_getlocal(_rootdir_obj, ROOTDIR_VIRTTERM_I)); + obj_settype(vt_obj, JOVE_OBJ_VIRTTERM); + obj_setvalue(vt_obj, (uintmax_t)&s_init_vtty); + obj_release(vt_obj); + } +} diff --git a/lib/virtterm.h b/lib/virtterm.h new file mode 100644 index 0000000..08e22e9 --- /dev/null +++ b/lib/virtterm.h @@ -0,0 +1,19 @@ +#ifndef _JOVE_LIB_VIRTTERM_H +#define _JOVE_LIB_VIRTTERM_H 1 + +#include +#include "hal/obj.h" + +struct virtterm +{ + size_t fb_obj; + size_t cursor_col, cursor_row; + size_t width, height; + uint32_t cursor_fg, cursor_bg; +}; + +int vt_write(jove_owned_obj_t *obj, const char *s, size_t n); + +void vt_init(void); + +#endif -- cgit v1.2.3