0

I'm writing a 'fake' framebuffer device so I can use my e-reader as an external screen for my raspberry pi. The e-reader part is working fine (https://github.com/llandsmeer/inkvt), but now I want to make it appear as a external screen for linux.

I though a virtual linux framebuffer is 'easiest', but maybe there are other options for adding a fake screen to linux (which shows up in xrandr)?

Anyway, here is the current kernel module. It creates a /dev/fbX device, which after being queried with fbset seems to be configured right. However, when I try to use it, it fails and I get fbcat: Corrupted page table at address 7fd7d5c90000 from dmesg.

I think it's because I misconfigure the memory region (char mem[]) wrong. I've tried using kalloc instread, but that didn't work either. How should I be doing things?

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fb.h>

#define WIDTH 256
#define HEIGHT 256

static char mem[WIDTH*HEIGHT*3];

static void op_fillrect(struct fb_info * info, const struct fb_fillrect * rect) {
    printk(KERN_ALERT "fillrect\n");
}

static void op_copyarea(struct fb_info * info, const struct fb_copyarea * area) {
    printk(KERN_ALERT "copyarea\n");
}

static void op_imageblit(struct fb_info * info, const struct fb_image * image) {
    printk(KERN_ALERT "imageblit\n");
}

static struct fb_info * info;

static struct fb_ops ops = {
    .owner = THIS_MODULE,
    .fb_fillrect = op_fillrect,
    .fb_copyarea = op_copyarea,
    .fb_imageblit = op_imageblit,
};

static const struct fb_fix_screeninfo fix = {
    .id = "LennartFB",
    .smem_start = (unsigned long)mem,
    .smem_len = sizeof(mem),
    .type = FB_TYPE_PACKED_PIXELS,
    .visual = FB_VISUAL_TRUECOLOR,
    .line_length = 256,
};

static const struct fb_var_screeninfo var = {
    .xres = WIDTH,
    .yres = HEIGHT,
    .xres_virtual = WIDTH,
    .yres_virtual = HEIGHT,
    .bits_per_pixel = 24,
    .height = 256,
    .width = 256,
    .vmode = FB_VMODE_NONINTERLACED,
    .red = { .length = 8, .offset = 16, },
    .green = { .length = 8, .offset = 8, },
    .blue = { .length = 8, .offset = 0, }
};

static int mod_init(void) {
    int err;
    info = framebuffer_alloc(0, 0);
    if (!info) return -1;
    info->fbops = &ops;
    info->fix = fix;
    info->var = var;
    info->screen_base = mem;
    err = fb_alloc_cmap(&info->cmap, 2, 0);
    if (err < 0) return -2;
    err = register_framebuffer(info);
    if (err < 0) return -3;
    return 0;
}

static void mod_exit(void) {
    return;
}

module_init(mod_init);
module_exit(mod_exit);
MODULE_LICENSE("GPL v3");

dmesg:

[ 4984.929380] fbcat: Corrupted page table at address 7fd7d5c90000
[ 4984.929385] PGD 8000000277709067 P4D 8000000277709067 PUD 3eb108067 PMD 2c732e067 PTE 800fffffc0f5d235
[ 4984.929391] Bad pagetable: 000d [#1] SMP PTI
[ 4984.929396] CPU: 11 PID: 8076 Comm: fbcat Tainted: P           OE     5.3.0-46-generic #38~18.04.1-Ubuntu
[ 4984.929398] Hardware name: Acer Aspire A715-72G/Charmeleon_CFS, BIOS V1.19 07/13/2018
[ 4984.929403] RIP: 0033:0x55fa6cb22e98
5
  • 1
    There's a virtual fb driver vfb.c that seems to use vmalloc_32_user() of the size rounded up to a multiple of page size. Commented Apr 11, 2020 at 20:25
  • @meuh Thanks, vfb seems be be doing approximately the same thing I want to happen :). I still couldn't get it to work with vmalloc_user()/vmalloc_32_user(), but just copying the vfb.c source + setting vbf_enable = 1 creates a nice working virtual framebuffer. Thanks! Commented Apr 12, 2020 at 11:12
  • @meuh How did you know that anyway? :) Is that standard kernel knowledge? Or did I miss some kind of documentation where this is all written down? Commented Apr 12, 2020 at 11:19
  • 1
    There's no easy way to find out how to do things in the Linux kernel. Although there are books on the subject, they are rapidly outdated as the kernel API changes rapidly. At best they provide a sort of background knowledge that can help, but basically you have to search the sources for examples of what you are trying to do, then try to understand how they work. It is more and more complicated as the kernel grows, so unless you do it full-time it is best to restrict yourself to some very small subsection of it. Commented Apr 12, 2020 at 12:06
  • Great, that sounds like fun :) Guess that explains why there are so much sites online that just grep the linux sourcecode for your search terms. Thanks for taking the time to explain that :) Commented Apr 13, 2020 at 13:53

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.