diff --git a/common/console.c b/common/console.c index adf924b8..7447eef5 100644 --- a/common/console.c +++ b/common/console.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -98,6 +99,10 @@ void vga_console_write(void *vga_memory, const char *buf, size_t len) { vga_write(vga_memory, buf, len, VGA_WHITE); } +void fb_console_write(void *fb_memory, const char *buf, size_t len) { + fb_write(fb_memory, buf, len, FB_WHITE); +} + void register_console_callback(console_callback_t cb, void *arg) { console_callbacks[num_console_callbacks].cb = cb; console_callbacks[num_console_callbacks++].arg = arg; diff --git a/drivers/fb/fb.c b/drivers/fb/fb.c index 8a68a54c..5e47c2e8 100644 --- a/drivers/fb/fb.c +++ b/drivers/fb/fb.c @@ -22,11 +22,15 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include #include #include +#include + +extern uint64_t fonts[]; static uint32_t width; static uint32_t height; @@ -111,9 +115,21 @@ bool init_framebuffer(const multiboot_info_t *mbi) { map_fb_area(mbi->framebuffer_addr, buffer_size); memset(video_memory, 0, buffer_size); + register_console_callback(fb_console_write, video_memory); return true; } +void put_char(char c, uint32_t x, uint32_t y, uint32_t color) { + uint64_t font = fonts[(uint8_t) c]; + + for (int yy = 0; yy < 8; yy++) { + for (int xx = 0; xx < 8; xx++, font >>= 1) { + if (font & 1) + put_pixel(x + xx, y + yy, color); + } + } +} + void draw_line(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2, uint32_t color) { while (x1 <= x2 || y1 <= y2) { put_pixel(x1, y1, color); @@ -138,3 +154,28 @@ void draw_logo(void) { static void clear_screen(void *fb_addr) { memset((uint8_t *) video_memory + banner_size, 0, buffer_size - banner_size); } + +void fb_write(void *fb_addr, const char *buf, size_t len, uint32_t color) { + static uint32_t row = LOGO_HEIGHT + 8, col = 0; + + for (unsigned int i = 0; i < len; i++) { + char c = buf[i]; + + if ((col + 8) > width || c == '\n') { + row += sizeof(fonts[0]); + col = 0; + } + + if ((row + 8) > height) { + clear_screen(fb_addr); + row = LOGO_HEIGHT + 8; + col = 0; + } + + if (c == '\n') + continue; + + put_char(c, col, row, color); + col += sizeof(fonts[0]); + } +} diff --git a/include/console.h b/include/console.h index 0d62b77c..c9b07f47 100644 --- a/include/console.h +++ b/include/console.h @@ -46,6 +46,7 @@ extern void printk(const char *fmt, ...); extern void serial_console_write(void *arg, const char *buf, size_t len); extern void qemu_console_write(void *arg, const char *buf, size_t len); extern void vga_console_write(void *arg, const char *buf, size_t len); +extern void fb_console_write(void *arg, const char *buf, size_t len); extern void register_console_callback(console_callback_t func, void *arg); diff --git a/include/drivers/fb.h b/include/drivers/fb.h index 2f3a7e81..e0920f8c 100644 --- a/include/drivers/fb.h +++ b/include/drivers/fb.h @@ -31,7 +31,9 @@ #define FB_WHITE 0xFFFFFFFF extern bool init_framebuffer(const multiboot_info_t *mbi); +extern void put_char(char c, uint32_t x, uint32_t y, uint32_t color); extern void draw_line(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2, uint32_t color); extern void draw_logo(void); +extern void fb_write(void *fb_addr, const char *buf, size_t len, uint32_t color); #endif /* KTF_DRV_FB_H */