lfbvideo: allow display initialize to be triggered by ioctl

This commit is contained in:
K. Lange 2018-10-27 16:18:09 +09:00
parent e3fd396897
commit 4d854b156c
3 changed files with 86 additions and 49 deletions

View File

@ -22,7 +22,7 @@
int main(int argc, char * argv[]) { int main(int argc, char * argv[]) {
if (argc < 3) { if (argc < 3) {
fprintf(stderr, "Usage: %s width height\n", argv[0]); fprintf(stderr, "Usage: %s [--initialize DRIVER] WIDTH HEIGHT\n", argv[0]);
} }
/* Open framebuffer */ /* Open framebuffer */
@ -33,15 +33,34 @@ int main(int argc, char * argv[]) {
return 1; return 1;
} }
int i = 1;
int init = 0;
char * driver = NULL;
if (argc > 4 && !strcmp(argv[1],"--initialize")) {
init = 1;
driver = argv[2];
i += 2;
}
/* Prepare ioctl from arguments */ /* Prepare ioctl from arguments */
struct vid_size s; struct vid_size s;
s.width = atoi(argv[1]); s.width = atoi(argv[i]);
s.height = atoi(argv[2]); s.height = atoi(argv[i+1]);
/* Send ioctl */ /* Send ioctl */
if (ioctl(fd, IO_VID_SET, &s) < 0) { if (init) {
perror("ioctl"); char tmp[100];
return 1; sprintf(tmp, "%s,%lu,%lu", driver, s.width, s.height);
if (ioctl(fd, IO_VID_REINIT, tmp) < 0) {
perror("ioctl");
return 1;
}
} else {
if (ioctl(fd, IO_VID_SET, &s) < 0) {
perror("ioctl");
return 1;
}
} }
return 0; return 0;

View File

@ -7,7 +7,8 @@
#define IO_VID_SIGNAL 0x5005 #define IO_VID_SIGNAL 0x5005
#define IO_VID_SET 0x5006 #define IO_VID_SET 0x5006
#define IO_VID_STRIDE 0x5007 #define IO_VID_STRIDE 0x5007
#define IO_VID_DRIVER 0x6008 #define IO_VID_DRIVER 0x5008
#define IO_VID_REINIT 0x5009
struct vid_size { struct vid_size {
uint32_t width; uint32_t width;

View File

@ -37,6 +37,9 @@ uint32_t lfb_resolution_s = 0;
uint8_t * lfb_vid_memory = (uint8_t *)0xE0000000; uint8_t * lfb_vid_memory = (uint8_t *)0xE0000000;
const char * lfb_driver_name = NULL; const char * lfb_driver_name = NULL;
static fs_node_t * lfb_device = NULL;
static int lfb_init(char * c);
/* Where to send display size change signals */ /* Where to send display size change signals */
static pid_t display_change_recipient = 0; static pid_t display_change_recipient = 0;
@ -99,6 +102,12 @@ static int ioctl_vid(fs_node_t * node, int request, void * argp) {
validate(argp); validate(argp);
memcpy(argp, lfb_driver_name, strlen(lfb_driver_name)); memcpy(argp, lfb_driver_name, strlen(lfb_driver_name));
return 0; return 0;
case IO_VID_REINIT:
if (current_process->user != 0) {
return -EPERM;
}
validate(argp);
return lfb_init(argp);
default: default:
return -EINVAL; return -EINVAL;
} }
@ -109,7 +118,7 @@ static fs_node_t * lfb_video_device_create(void /* TODO */) {
fs_node_t * fnode = malloc(sizeof(fs_node_t)); fs_node_t * fnode = malloc(sizeof(fs_node_t));
memset(fnode, 0x00, sizeof(fs_node_t)); memset(fnode, 0x00, sizeof(fs_node_t));
sprintf(fnode->name, "fb0"); /* TODO */ sprintf(fnode->name, "fb0"); /* TODO */
fnode->length = lfb_resolution_s * lfb_resolution_y; /* Size is framebuffer size in bytes */ fnode->length = 0;
fnode->flags = FS_BLOCKDEVICE; /* Framebuffers are block devices */ fnode->flags = FS_BLOCKDEVICE; /* Framebuffers are block devices */
fnode->mask = 0660; /* Only accessible to root user/group */ fnode->mask = 0660; /* Only accessible to root user/group */
fnode->ioctl = ioctl_vid; /* control function defined above */ fnode->ioctl = ioctl_vid; /* control function defined above */
@ -254,8 +263,7 @@ static struct procfs_entry framebuffer_entry = {
/* Install framebuffer device */ /* Install framebuffer device */
static void finalize_graphics(const char * driver) { static void finalize_graphics(const char * driver) {
lfb_driver_name = driver; lfb_driver_name = driver;
fs_node_t * fb_device = lfb_video_device_create(); lfb_device->length = lfb_resolution_s * lfb_resolution_y; /* Size is framebuffer size in bytes */
vfs_mount("/dev/fb0", fb_device);
debug_video_crash = lfb_video_panic; debug_video_crash = lfb_video_panic;
int (*procfs_install)(struct procfs_entry *) = (int (*)(struct procfs_entry *))(uintptr_t)hashmap_get(modules_get_symbols(),"procfs_install"); int (*procfs_install)(struct procfs_entry *) = (int (*)(struct procfs_entry *))(uintptr_t)hashmap_get(modules_get_symbols(),"procfs_install");
@ -527,54 +535,63 @@ static void auto_scan_pci(uint32_t device, uint16_t v, uint16_t d, void * extra)
} }
} }
static int lfb_init(char * c) {
char * arg = strdup(c);
char * argv[10];
int argc = tokenize(arg, ",", argv);
uint16_t x, y;
if (argc < 3) {
x = PREFERRED_W;
y = PREFERRED_H;
} else {
x = atoi(argv[1]);
y = atoi(argv[2]);
}
int ret_val = 0;
if (!strcmp(argv[0], "auto")) {
/* Attempt autodetection */
debug_print(NOTICE, "Automatically detecting display driver...");
struct disp_mode mode = {x,y,0};
pci_scan(auto_scan_pci, -1, &mode);
if (!mode.set) {
graphics_install_preset(x,y);
}
} else if (!strcmp(argv[0], "qemu")) {
/* Bochs / Qemu Video Device */
graphics_install_bochs(x,y);
} else if (!strcmp(argv[0],"vmware")) {
/* VMware SVGA */
graphics_install_vmware(x,y);
} else if (!strcmp(argv[0],"preset")) {
/* Set by bootloader (UEFI) */
graphics_install_preset(x,y);
} else if (!strcmp(argv[0],"kludge")) {
/* Old hack to find vid memory from the VGA window */
graphics_install_kludge(x,y);
} else {
debug_print(WARNING, "Unrecognized video adapter: %s", argv[0]);
ret_val = 1;
}
free(arg);
return ret_val;
}
static int init(void) { static int init(void) {
if (mboot_ptr->vbe_mode_info) { if (mboot_ptr->vbe_mode_info) {
lfb_vid_memory = (uint8_t *)((vbe_info_t *)(mboot_ptr->vbe_mode_info))->physbase; lfb_vid_memory = (uint8_t *)((vbe_info_t *)(mboot_ptr->vbe_mode_info))->physbase;
} }
lfb_device = lfb_video_device_create();
vfs_mount("/dev/fb0", lfb_device);
char * c; char * c;
if ((c = args_value("vid"))) { if ((c = args_value("vid"))) {
debug_print(NOTICE, "Video mode requested: %s", c); debug_print(NOTICE, "Video mode requested: %s", c);
lfb_init(c);
char * arg = strdup(c);
char * argv[10];
int argc = tokenize(arg, ",", argv);
uint16_t x, y;
if (argc < 3) {
x = PREFERRED_W;
y = PREFERRED_H;
} else {
x = atoi(argv[1]);
y = atoi(argv[2]);
}
if (!strcmp(argv[0], "auto")) {
/* Attempt autodetection */
debug_print(NOTICE, "Automatically detecting display driver...");
struct disp_mode mode = {x,y,0};
pci_scan(auto_scan_pci, -1, &mode);
if (!mode.set) {
graphics_install_preset(x,y);
}
} else if (!strcmp(argv[0], "qemu")) {
/* Bochs / Qemu Video Device */
graphics_install_bochs(x,y);
} else if (!strcmp(argv[0],"vmware")) {
/* VMware SVGA */
graphics_install_vmware(x,y);
} else if (!strcmp(argv[0],"preset")) {
/* Set by bootloader (UEFI) */
graphics_install_preset(x,y);
} else if (!strcmp(argv[0],"kludge")) {
/* Old hack to find vid memory from the VGA window */
graphics_install_kludge(x,y);
} else {
debug_print(WARNING, "Unrecognized video adapter: %s", argv[0]);
}
free(arg);
} }
return 0; return 0;