123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- /* vim: tabstop=4 shiftwidth=4 noexpandtab
- * This file is part of ToaruOS and is released under the terms
- * of the NCSA / University of Illinois License - see LICENSE.md
- * Copyright (C) 2018 K. Lange
- *
- * splash-log - Display startup messages before UI has started.
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdint.h>
- #include <string.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <kernel/video.h>
- #include <toaru/pex.h>
- #include "terminal-font.h"
- /**
- * For legacy backwards-compatibility reasons, the VGA
- * text-mode window is normalled mapped 1:1. If this
- * ever changes, a few applications will need to be updated.
- */
- static unsigned short * textmemptr = (unsigned short *)0xB8000;
- static void placech(unsigned char c, int x, int y, int attr) {
- unsigned short *where;
- unsigned att = attr << 8;
- where = textmemptr + (y * 80 + x);
- *where = c | att;
- }
- /**
- * Graphical framebuffer is a bit more straightforward.
- */
- static int framebuffer_fd = -1;
- static int width, height, depth;
- static char * framebuffer;
- static void set_point(int x, int y, uint32_t value) {
- uint32_t * disp = (uint32_t *)framebuffer;
- uint32_t * cell = &disp[y * width + x];
- *cell = value;
- }
- #define BG_COLOR 0xFF050505
- #define FG_COLOR 0xFFCCCCCC
- #define char_width 9
- #define char_height 20
- static void write_char(int x, int y, int val, uint32_t color) {
- if (val > 128) {
- val = 4;
- }
- uint16_t * c = large_font[val];
- for (uint8_t i = 0; i < char_height; ++i) {
- for (uint8_t j = 0; j < char_width; ++j) {
- if (c[i] & (1 << (15-j))) {
- set_point(x+j,y+i,color);
- } else {
- set_point(x+j,y+i,BG_COLOR);
- }
- }
- }
- }
- static void update_message(char * c, int line) {
- if (framebuffer_fd != -1) {
- int x = 20;
- int y = 20 + char_height * line;
- while (*c) {
- write_char(x, y, *c, FG_COLOR);
- c++;
- x += char_width;
- }
- while (x < width - char_width) {
- write_char(x, y, ' ', FG_COLOR);
- x += char_width;
- }
- } else {
- int x = 2;
- int y = 2 + line;
- while (*c) {
- placech(*c, x, y, 0x7);
- c++;
- x++;
- }
- while (x < 80) {
- placech(' ', x, y, 0x7);
- x++;
- }
- }
- }
- static void clear_screen(void) {
- if (framebuffer_fd != -1) {
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x) {
- set_point(x,y,BG_COLOR);
- }
- }
- } else {
- for (int y = 0; y < 24; ++y) {
- for (int x = 0; x < 80; ++x) {
- placech(' ', x, y, 0); /* Clear */
- }
- }
- }
- }
- static void check_framebuffer(void) {
- int tmpfd = open("/proc/framebuffer", O_RDONLY);
- if (tmpfd > 0) {
- framebuffer_fd = open("/dev/fb0", O_RDONLY);
- ioctl(framebuffer_fd, IO_VID_WIDTH, &width);
- ioctl(framebuffer_fd, IO_VID_HEIGHT, &height);
- ioctl(framebuffer_fd, IO_VID_DEPTH, &depth);
- ioctl(framebuffer_fd, IO_VID_ADDR, &framebuffer);
- ioctl(framebuffer_fd, IO_VID_SIGNAL, NULL);
- } else {
- framebuffer_fd = -1;
- }
- }
- static FILE * pex_endpoint = NULL;
- static void open_socket(void) {
- pex_endpoint = pex_bind("splash");
- if (!pex_endpoint) exit(1);
- }
- int main(int argc, char * argv[]) {
- if (getuid() != 0) {
- fprintf(stderr, "%s: only root should run this\n", argv[0]);
- return 1;
- }
- open_socket();
- if (!fork()) {
- check_framebuffer();
- clear_screen();
- update_message("ToaruOS is starting up...", 0);
- while (1) {
- pex_packet_t * p = calloc(PACKET_SIZE, 1);
- pex_listen(pex_endpoint, p);
- if (p->size < 4) continue; /* Ignore blank messages, erroneous line feeds, etc. */
- if (p->size > 80) continue; /* Ignore overly large messages */
- if (!strncmp((char*)p->data, "!quit", 5)) {
- /* Use the special message !quit to exit. */
- fclose(pex_endpoint);
- return 0;
- } else if (p->data[0] == ':') {
- /* Make sure message is nil terminated (it should be...) */
- char * tmp = malloc(p->size + 1);
- memcpy(tmp, p->data, p->size);
- tmp[p->size] = '\0';
- update_message(tmp+1, 1);
- free(tmp);
- } else {
- /* Make sure message is nil terminated (it should be...) */
- char * tmp = malloc(p->size + 1);
- memcpy(tmp, p->data, p->size);
- tmp[p->size] = '\0';
- update_message(tmp, 0);
- update_message("", 1);
- free(tmp);
- }
- }
- }
- return 0;
- }
|