/* Copyright (C) 2021,2022 fef . All rights reserved. */ #include #include #include #include #include #include #include #include #include #include enum vga_color { VGA_COLOR_BLACK = 0, VGA_COLOR_BLUE = 1, VGA_COLOR_GREEN = 2, VGA_COLOR_CYAN = 3, VGA_COLOR_RED = 4, VGA_COLOR_MAGENTA = 5, VGA_COLOR_BROWN = 6, VGA_COLOR_LIGHT_GREY = 7, VGA_COLOR_DARK_GREY = 8, VGA_COLOR_LIGHT_BLUE = 9, VGA_COLOR_LIGHT_GREEN = 10, VGA_COLOR_LIGHT_CYAN = 11, VGA_COLOR_LIGHT_RED = 12, VGA_COLOR_LIGHT_MAGENTA = 13, VGA_COLOR_LIGHT_BROWN = 14, VGA_COLOR_WHITE = 15, }; /* * The character framebuffer sits at physical address 0x000b8000. * The entire low memory is always mapped to KERNBASE upwards. */ #define FB_ADDRESS (0x000b8000 + KERNBASE) #define FB_LINES 24 #define FB_COLS 80 struct fb_cell { u8 c; enum vga_color fg:4; enum vga_color bg:4; } __packed; /** @brief BIOS provided character framebuffer */ static volatile struct fb_cell *const framebuffer = (volatile struct fb_cell *)FB_ADDRESS; /** @brief current line in the framebuffer */ static unsigned int fb_line; /** @brief current column in the framebuffer */ static unsigned int fb_col; /** @brief current background color */ enum vga_color fb_background; /** @brief current foreground color */ enum vga_color fb_foreground; #define cell_at(line, col) ( &framebuffer[(line) * FB_COLS + (col)] ) #define current_cell (cell_at(fb_line, fb_col)) static isize fb_write(struct kprintf_printer *printer, const void *buf, usize size); static isize fb_flush(struct kprintf_printer *printer); static struct kprintf_printer fb_kprintf_printer = { .write = fb_write, .flush = fb_flush, }; static void fb_newline(void); static void fb_clear(void); static void fb_init(enum vga_color fg, enum vga_color bg); static void print_gay_propaganda(void); static struct mb2_tag *next_tag(struct mb2_tag *tag); static void handle_tag(struct mb2_tag *tag); extern int main(int argc, char *argv[]); __asmlink void _boot(void *address) { volatile int x = 69420; while (x == 69420); kprintf_set_printer(&fb_kprintf_printer); fb_init(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); x86_setup_interrupts(); print_gay_propaganda(); /* the +8 for the address has something to do with the tags * being embedded in another struct iirc, but i have no idea what * that was and quite honestly i'm just glad it works at all. */ for (struct mb2_tag *tag = address + 8; tag != NULL; tag = next_tag(tag)) handle_tag(tag); main(0, nil); } static inline void handle_tag(struct mb2_tag *tag) { switch (tag->type) { case MB2_TAG_TYPE_END: break; case MB2_TAG_TYPE_CMDLINE: kprintf("Kernel command line: %s\n", ((struct mb2_tag_string *)tag)->string); break; case MB2_TAG_TYPE_MMAP: x86_paging_init((struct mb2_tag_mmap *)tag); break; default: //kprintf("Unknown tag %u\n", tag->type); break; } } static inline struct mb2_tag *next_tag(struct mb2_tag *tag) { if (tag->type == MB2_TAG_TYPE_END) return NULL; else return (void *)tag + ( (tag->size + 7) & ~7 ); } static void fb_newline(void) { fb_col = 0; if (fb_line == FB_LINES - 1) { void *first_row = (void *)cell_at(0, 0); void *second_row = (void *)cell_at(1, 0); void *last_row_end = (void *)cell_at(FB_LINES, FB_COLS); memmove(first_row, second_row, last_row_end - second_row); } else { fb_line++; } } static isize fb_write(struct kprintf_printer *printer, const void *buf, usize size) { isize ret = 0; const u8 *s = buf; while (size > s - (const u8 *)buf) { u8 c = *s++; ret++; if (fb_col == FB_COLS) fb_newline(); if (c == '\n') { fb_newline(); continue; } current_cell->c = c; current_cell->fg = fb_foreground; current_cell->bg = fb_background; fb_col++; } return ret; } static isize fb_flush(struct kprintf_printer *printer) { return 0; } static void fb_clear(void) { for (unsigned int l = 0; l < FB_LINES; l++) { for (unsigned int c = 0; c < FB_COLS; c++) { cell_at(l, c)->c = ' '; cell_at(l, c)->fg = fb_foreground; cell_at(l, c)->bg = fb_background; } } } static void fb_init(enum vga_color fg, enum vga_color bg) { fb_line = 0; fb_col = 0; fb_foreground = fg; fb_background = bg; /* disable cursor */ x86_outb(0x3D4, 0x0A); x86_outb(0x3D5, 0x20); fb_clear(); } static void print_gay_propaganda(void) { static const enum vga_color rainbow[] = { VGA_COLOR_RED, VGA_COLOR_LIGHT_RED, VGA_COLOR_LIGHT_BROWN, VGA_COLOR_GREEN, VGA_COLOR_BLUE, VGA_COLOR_MAGENTA, }; static char line[FB_COLS]; memset(line, ' ', FB_COLS); enum vga_color bg_before = fb_background; enum vga_color fg_before = fb_foreground; for (int i = 0; i < ARRAY_SIZE(rainbow); i++) { fb_background = rainbow[i]; fb_write(NULL, line, FB_COLS); } fb_background = bg_before; kprintf("\nWelcome to "); const char *gaybsd = "GayBSD"; for (const char *tmp = gaybsd; *tmp != '\0'; tmp++) { fb_foreground = rainbow[tmp - gaybsd]; kprintf("%c", *tmp); } fb_foreground = fg_before; kprintf(", be gay do crime!\n\n"); }