Skip to content

Instantly share code, notes, and snippets.

@halferty
Last active July 15, 2022 11:57
Show Gist options
  • Save halferty/17c2c347be49a1ad96a4d05572da3d3f to your computer and use it in GitHub Desktop.
Save halferty/17c2c347be49a1ad96a4d05572da3d3f to your computer and use it in GitHub Desktop.
init process that draws to framebuffer
#include <errno.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include <linux/limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
void exit_handler();
void mount_proc();
void mount_sys();
void mount_dev();
int open_dev_fb();
int open_dev_tty();
void run_terminal();
uint32_t pixel_color(uint8_t r, uint8_t g, uint8_t b, struct fb_var_screeninfo *vinfo);
void exit_handler() {
#if 1
run_terminal();
#else
exit(1);
#endif
}
void mount_proc() {
printf("Mounting /proc...");
if (0 != mount("none", "/proc", "proc", 0, "")) {
printf("\nFailed to mount /proc!\n");
exit_handler();
}
printf("Done!\n");
}
void mount_sys() {
printf("Mounting /sys...");
if (0 != mount("none", "/sys", "sysfs", 0, "")) {
printf("\nFailed to mount /proc!\n");
exit_handler();
}
printf("Done!\n");
}
void mount_dev() {
printf("Mounting /dev...");
if (0 != mount("none", "/dev", "devtmpfs", 0, "")) {
int errno2 = errno;
// Error code 16 ("device or resource busy") is spurrious and doesn't really matter. Ignore it.
if (errno2 != 16) {
printf("\nFailed to mount /dev! errno=%d strerror=%s\n", errno, strerror(errno));
exit_handler();
}
}
printf("Done!\n");
}
int open_dev_fb() {
int fb_fd = open("/dev/fb0",O_RDWR);
if (fb_fd == -1) {
int errno2 = errno;
printf("Failed to open /dev/fb0! errno=%d strerror=%s\n", errno, strerror(errno));
exit_handler();
}
return fb_fd;
}
void run_terminal() {
execl("busybox-x86_64", "busybox-x86_64", "ash", NULL);
}
uint32_t pixel_color(uint8_t r, uint8_t g, uint8_t b, struct fb_var_screeninfo *vinfo) {
return (r<<vinfo->red.offset) | (g<<vinfo->green.offset) | (b<<vinfo->blue.offset);
}
int main(int argc, char *argv[]) {
printf("Hello from the init system\n");
int parent_pid = getpid();
mount_proc();
mount_sys();
mount_dev();
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
int fb_fd = open_dev_fb();
//Get variable screen information
ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo);
vinfo.grayscale=0;
vinfo.bits_per_pixel=32;
ioctl(fb_fd, FBIOPUT_VSCREENINFO, &vinfo);
ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo);
ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo);
long screensize = vinfo.yres_virtual * finfo.line_length;
uint8_t *fbp = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, (off_t)0);
int x,y;
printf("Should be rendering on monitor now...\n");
int val = 0;
for (y=0;y<vinfo.yres;y++) {
for (x=0;x<vinfo.xres;x++){
val++;
if (val > 0xFF) {
val = 0;
}
long location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y+vinfo.yoffset) * finfo.line_length;
*((uint32_t*)(fbp + location)) = pixel_color(
(x > y) ? val : 0xFF - val,
(y > x) ? val : 0xFF - val,
(x == y) ? val : 0xFF - val,
&vinfo);
}
}
sleep(60);
run_terminal();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment