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[]) {
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 */
@ -33,15 +33,34 @@ int main(int argc, char * argv[]) {
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 */
struct vid_size s;
s.width = atoi(argv[1]);
s.height = atoi(argv[2]);
s.width = atoi(argv[i]);
s.height = atoi(argv[i+1]);
/* Send ioctl */
if (ioctl(fd, IO_VID_SET, &s) < 0) {
perror("ioctl");
return 1;
if (init) {
char tmp[100];
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;

View File

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

View File

@ -37,6 +37,9 @@ uint32_t lfb_resolution_s = 0;
uint8_t * lfb_vid_memory = (uint8_t *)0xE0000000;
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 */
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);
memcpy(argp, lfb_driver_name, strlen(lfb_driver_name));
return 0;
case IO_VID_REINIT:
if (current_process->user != 0) {
return -EPERM;
}
validate(argp);
return lfb_init(argp);
default:
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));
memset(fnode, 0x00, sizeof(fs_node_t));
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->mask = 0660; /* Only accessible to root user/group */
fnode->ioctl = ioctl_vid; /* control function defined above */
@ -254,8 +263,7 @@ static struct procfs_entry framebuffer_entry = {
/* Install framebuffer device */
static void finalize_graphics(const char * driver) {
lfb_driver_name = driver;
fs_node_t * fb_device = lfb_video_device_create();
vfs_mount("/dev/fb0", fb_device);
lfb_device->length = lfb_resolution_s * lfb_resolution_y; /* Size is framebuffer size in bytes */
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");
@ -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) {
if (mboot_ptr->vbe_mode_info) {
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;
if ((c = args_value("vid"))) {
debug_print(NOTICE, "Video mode requested: %s", 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);
lfb_init(c);
}
return 0;