⬢ DragonFlyBSD Kernel Audit
DF-4542 / scprobe.c
← back to finding ↓ download raw
/*
 * scprobe.c - sequential reachability probe for syscons sc_vid_ioctl paths
 * (scvidctl.c). Documents which KD_x / CONS_X ioctls succeed on the guest
 * /dev/ttyvN and which are gated (VESA absent, ISTEXTSC, ...).
 */
#include <sys/ioctl.h>
#include <sys/consio.h>
#include <sys/fbio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>

static void perr(const char *what, int r)
{
	printf("%-34s r=%d errno=%d (%s)\n", what, r, errno, strerror(errno));
	errno = 0;
}

int main(int argc, char **argv)
{
	const char *dev = argc > 1 ? argv[1] : "/dev/ttyv1";
	int fd, r, v;
	video_adapter_info_t ai;
	scr_size_t sz;

	fd = open(dev, O_RDWR | O_NONBLOCK);
	if (fd < 0) { perror("open"); return 1; }
	printf("device %s fd=%d\n", dev, fd);

	v = -1;
	r = ioctl(fd, CONS_GET, &v);
	printf("%-34s -> mode=%d\n", "CONS_GET", v); perr("CONS_GET", r);

	{ int m = M_VGA_C80x25; errno = 0; r = ioctl(fd, CONS_SET, &m);
	  perr("CONS_SET M_VGA_C80x25", r); }
	{ int m = M_VGA_C80x50; errno = 0; r = ioctl(fd, CONS_SET, &m);
	  perr("CONS_SET M_VGA_C80x50", r); }
	{ int m = M_VGA_C80x30; errno = 0; r = ioctl(fd, CONS_SET, &m);
	  perr("CONS_SET M_VGA_C80x30", r); }
	{ int m = M_VGA_C80x60; errno = 0; r = ioctl(fd, CONS_SET, &m);
	  perr("CONS_SET M_VGA_C80x60", r); }
#ifdef M_VGA_C80x43
	{ int m = M_VGA_C80x43; errno = 0; r = ioctl(fd, CONS_SET, &m);
	  perr("CONS_SET M_VGA_C80x43", r); }
#endif
#ifdef M_VESA_CG640x480
	{ int m = M_VESA_CG640x480; errno = 0; r = ioctl(fd, CONS_SET, &m);
	  perr("CONS_SET M_VESA_CG640x480", r); }
#endif
#ifdef M_VESA_CG800x600
	{ int m = M_VESA_CG800x600; errno = 0; r = ioctl(fd, CONS_SET, &m);
	  perr("CONS_SET M_VESA_CG800x600", r); }
#endif

	/* KDSETMODE is _IO: the kernel reads *(int*)data == low 32 bits of
	 * the user pointer we pass. */
	errno = 0; r = ioctl(fd, KDSETMODE, (void *)(uintptr_t)KD_TEXT);
	perr("KDSETMODE KD_TEXT", r);
	errno = 0; r = ioctl(fd, KDSETMODE, (void *)(uintptr_t)KD_TEXT1);
	perr("KDSETMODE KD_TEXT1", r);
	errno = 0; r = ioctl(fd, KDSETMODE, (void *)(uintptr_t)KD_GRAPHICS);
	perr("KDSETMODE KD_GRAPHICS", r);
	errno = 0; r = ioctl(fd, KDSETMODE, (void *)(uintptr_t)KD_PIXEL);
	perr("KDSETMODE KD_PIXEL", r);

	memset(&sz, 0, sizeof(sz));
	sz.scr_size[0] = 80; sz.scr_size[1] = 25; sz.scr_size[2] = 16;
	errno = 0; r = ioctl(fd, KDRASTER, &sz);
	perr("KDRASTER 80x25x16", r);

	v = 0; errno = 0; r = ioctl(fd, KDGETMODE, &v);
	printf("%-34s -> kdmode=%d\n", "KDGETMODE", v); perr("KDGETMODE", r);

	errno = 0; r = ioctl(fd, KDSBORDER, (void *)(uintptr_t)5);
	perr("KDSBORDER 5", r);
	errno = 0; r = ioctl(fd, KDSBORDER, (void *)(uintptr_t)99);
	perr("KDSBORDER 99 (want EINVAL)", r);

	memset(&ai, 0, sizeof(ai));
	ai.va_index = -1;
	errno = 0; r = ioctl(fd, CONS_ADPINFO, &ai);
	printf("%-34s -> va_index=%d va_name=%s\n", "CONS_ADPINFO(-1)", ai.va_index, ai.va_name);
	perr("CONS_ADPINFO(-1)", r);

	memset(&ai, 0, sizeof(ai));
	ai.va_index = 9999;
	errno = 0; r = ioctl(fd, CONS_ADPINFO, &ai);
	perr("CONS_ADPINFO(9999) (want ENODEV)", r);

	errno = 0; r = ioctl(fd, VT_ACTIVATE, (void *)(uintptr_t)2);
	perr("VT_ACTIVATE 2", r);

	return 0;
}