#include #include #include #include #include typedef struct { uint8_t magic[2]; uint8_t mode; uint8_t charsz; } psf_hdr_t; typedef struct { int fd; psf_hdr_t hdr; void* glyphs; } psf_font_t; psf_font_t* load_font(const char* path); void free_font(psf_font_t* font); void term_write_char(char c); void render_char(char c); void clear(uint32_t color); void spawn_shell(); void start_terminal(); static int ptys; static int ptym; static int vga_fd; static void* fb = NULL; static fb_info_t fb_info; static uint32_t console_row = 0; static uint32_t console_col = 0; static uint32_t console_width = 0; static uint32_t console_height = 0; static uint32_t console_text_color = 0; static uint32_t console_backgrnd_color = 0; static int shell_pid; psf_font_t* terminal_font = NULL; int main(int argc, char *argv[]) { (void)argc; (void)argv; ptym = pty(&ptys); vga_fd = open("/dev/vga"); if (vga_fd == -1) return 1; int res = ioctl(vga_fd, FBIOGET_INFO, &fb_info); if (!res) { return 1; } fb = mmap(vga_fd); terminal_font = load_font("/usr/fonts/kernel_font.psf"); if (!terminal_font) { return 1; } console_height = fb_info.height / terminal_font->hdr.charsz; console_width = fb_info.width / 8; console_text_color = 0xFFFFFFFF; console_backgrnd_color = 0xFF6c7482; start_terminal(); free_font(terminal_font); close(vga_fd); close(ptym); return 0; } void render_char(char c) { if (!terminal_font) return; uint32_t vga_pitch = fb_info.pitch; uint8_t* glyph = (uint8_t*)terminal_font->glyphs + (c * terminal_font->hdr.charsz); uint32_t pixel_y_start = console_row * terminal_font->hdr.charsz; uint32_t pixel_x_start = console_col * 8; for (uint32_t y = 0; y < terminal_font->hdr.charsz; y++) { uint8_t bits = glyph[y]; uint8_t* row_bytes = (uint8_t*)fb + ((pixel_y_start + y) * vga_pitch); uint32_t* pixel_row = (uint32_t*)row_bytes; for (int x = 0; x < 8; x++) { if (bits & (0b10000000 >> x)) { pixel_row[pixel_x_start + x] = console_text_color; } else { pixel_row[pixel_x_start + x] = console_backgrnd_color; } } } } void spawn_shell() { if ((shell_pid = fork()) == 0) { close(ptym); close(vga_fd); dup2(ptys, 0); dup2(0, 1); dup2(0, 2); if (!exec("/usr/bin/rocksh")) exit(1); } close(ptys); dup2(ptym, 0); dup2(0, 1); dup2(0, 2); } void clear(uint32_t color) { for (uint32_t i = 0; i < fb_info.fb_size; i++) { ((uint32_t*)fb)[i] = color; } } psf_font_t* load_font(const char* path) { int fd = open(path); if (fd == -1) { return NULL; } psf_hdr_t header; int rd = read(fd, &header, sizeof(psf_hdr_t)); if (rd <= 0) { return NULL; } uint32_t num_glyphs = (header.mode & (1 << 0)) ? 512 : 256; uint32_t glyph_sz = header.charsz; size_t glyph_buf_sz = num_glyphs * glyph_sz; void* glyphs = malloc(glyph_buf_sz); rd = 0; rd = read(fd, glyphs, glyph_buf_sz); if (rd <= 0) { free(glyphs); return NULL; } psf_font_t* font = (psf_font_t*)malloc(sizeof(psf_font_t)); font->fd = fd; font->hdr = header; font->glyphs = glyphs; return font; } void free_font(psf_font_t* font) { close(font->fd); free(font->glyphs); free(font); } void term_write_char(char c) { if (!terminal_font) return; if (c == '\n') { console_col = 0; console_row++; if (console_row >= console_height) { console_row = 0; } return; } render_char(c); console_col++; if (console_col >= console_width) { console_col = 0; console_row++; } if (console_row >= console_height) { console_row = 0; } } void start_terminal() { spawn_shell(); clear(console_backgrnd_color); int kbd_fd = open("/dev/kbd"); if (kbd_fd == -1) return; while (1) { char c; int rd = read(STDIN_FILENO, &c, 1); if (rd > 0) { term_write_char(c); continue; } rd = 0; c = 0; rd = read(kbd_fd, &c, 1); if (rd > 0) { write(STDOUT_FILENO, &c, 1); } } }