summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/panic.c18
-rw-r--r--lib/panic.h8
-rw-r--r--lib/printf.c138
-rw-r--r--lib/printf.h12
-rw-r--r--lib/psf.c8
-rw-r--r--lib/psf.h19
-rw-r--r--lib/string.c50
-rw-r--r--lib/string.h16
-rw-r--r--lib/tar.c16
-rw-r--r--lib/tar.h25
-rw-r--r--lib/virtterm.c131
-rw-r--r--lib/virtterm.h19
12 files changed, 460 insertions, 0 deletions
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 <stdint.h>
+
+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 <stdarg.h>
+#include <stddef.h>
+
+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 <stddef.h>
+#include <stdint.h>
+
+#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 <stddef.h>
+
+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 <stddef.h>
+#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