2026-07-08 21:15:30 -05:00
|
|
|
#include <unistd.h>
|
2026-07-16 23:19:54 -05:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdio.h>
|
2026-07-08 21:15:30 -05:00
|
|
|
|
2026-07-16 14:44:08 -05:00
|
|
|
#include <sys/video.h>
|
|
|
|
|
|
2026-07-16 16:09:12 -05:00
|
|
|
typedef struct {
|
2026-07-16 23:19:54 -05:00
|
|
|
uint8_t magic[2];
|
|
|
|
|
uint8_t mode;
|
|
|
|
|
uint8_t charsz;
|
|
|
|
|
} psf_hdr_t;
|
2026-07-12 04:37:46 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
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);
|
2026-07-16 16:09:12 -05:00
|
|
|
|
|
|
|
|
void term_write_char(char c);
|
2026-07-16 23:19:54 -05:00
|
|
|
void render_char(char c);
|
|
|
|
|
void clear(uint32_t color);
|
|
|
|
|
void spawn_shell();
|
|
|
|
|
|
|
|
|
|
void start_terminal();
|
2026-07-16 16:09:12 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
static int ptys;
|
|
|
|
|
static int ptym;
|
|
|
|
|
static int vga_fd;
|
2026-07-08 21:15:30 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
static void* fb = NULL;
|
|
|
|
|
static fb_info_t fb_info;
|
2026-07-07 00:13:24 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
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;
|
2026-07-16 14:44:08 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
static int shell_pid;
|
2026-07-16 14:44:08 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
psf_font_t* terminal_font = NULL;
|
2026-07-16 14:44:08 -05:00
|
|
|
|
2026-07-07 00:13:24 -05:00
|
|
|
int main(int argc, char *argv[]) {
|
2026-07-08 21:15:30 -05:00
|
|
|
(void)argc;
|
|
|
|
|
(void)argv;
|
|
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
ptym = pty(&ptys);
|
2026-07-08 21:15:30 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
vga_fd = open("/dev/vga");
|
|
|
|
|
if (vga_fd == -1) return 1;
|
2026-07-08 21:15:30 -05:00
|
|
|
|
2026-07-16 14:44:08 -05:00
|
|
|
int res = ioctl(vga_fd, FBIOGET_INFO, &fb_info);
|
|
|
|
|
if (!res) {
|
|
|
|
|
return 1;
|
2026-07-12 04:37:46 -05:00
|
|
|
}
|
|
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
fb = mmap(vga_fd);
|
2026-07-16 14:44:08 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
terminal_font = load_font("/usr/fonts/kernel_font.psf");
|
|
|
|
|
if (!terminal_font) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2026-07-16 14:44:08 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
console_height = fb_info.height / terminal_font->hdr.charsz;
|
|
|
|
|
console_width = fb_info.width / 8;
|
|
|
|
|
console_text_color = 0xFFFFFFFF;
|
|
|
|
|
console_backgrnd_color = 0xFF6c7482;
|
2026-07-16 16:09:12 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
start_terminal();
|
2026-07-16 16:09:12 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
free_font(terminal_font);
|
|
|
|
|
close(vga_fd);
|
|
|
|
|
close(ptym);
|
2026-07-16 16:09:12 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
return 0;
|
2026-07-16 16:09:12 -05:00
|
|
|
}
|
|
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-07-16 16:09:12 -05:00
|
|
|
|
2026-07-16 23:19:54 -05:00
|
|
|
void spawn_shell() {
|
|
|
|
|
if ((shell_pid = fork()) == 0) {
|
2026-07-16 16:09:12 -05:00
|
|
|
close(ptym);
|
2026-07-16 23:19:54 -05:00
|
|
|
close(vga_fd);
|
|
|
|
|
|
2026-07-16 16:09:12 -05:00
|
|
|
dup2(ptys, 0);
|
|
|
|
|
dup2(0, 1);
|
|
|
|
|
dup2(0, 2);
|
2026-07-16 23:19:54 -05:00
|
|
|
if (!exec("/usr/bin/rocksh")) exit(1);
|
2026-07-16 16:09:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
close(ptys);
|
|
|
|
|
dup2(ptym, 0);
|
|
|
|
|
dup2(0, 1);
|
|
|
|
|
dup2(0, 2);
|
2026-07-16 23:19:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-07-07 00:13:24 -05:00
|
|
|
}
|