⬢ DragonFlyBSD Kernel Audit
DF-2314 / pnphctl.c
← back to finding ↓ download raw
/*
 * pnphctl.c -- userland driver for the pnp.c verification harness
 * (/dev/pnph0).  Runs scenarios and prints results.
 *
 * Build: cc -O -Wall -o pnphctl pnphctl.c
 * Run:   ./pnphctl <scenario#> [arg]
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <err.h>
#include "pnph.h"

static void
hexdump_desc(const struct pnph_req *r)
{
	int i;

	printf("  desc len=%u child=%s\n", r->o_desc_len, r->o_child);
	printf("  desc ascii: <%s>\n", r->o_desc);
	printf("  desc hex  :");
	for (i = 0; i < (int)sizeof(r->o_desc) && r->o_desc[i]; i++) {
		if (i && (i % 32) == 0)
			printf("\n             ");
		printf(" %02x", (unsigned char)r->o_desc[i]);
	}
	printf("\n");
}

static void
dump_2315(const struct pnph_req *r)
{
	printf("  nport: before=%u after=%#x\n", r->o_nport0, r->o_nportF);
	printf("  irqmask before/after: {%#x,%#x} -> {%#x,%#x}\n",
	    r->o_irqmask0[0], r->o_irqmask0[1],
	    r->o_irqmaskF[0], r->o_irqmaskF[1]);
	printf("  drqmask before/after: {%#x,%#x} -> {%#x,%#x}\n",
	    r->o_drqmask0[0], r->o_drqmask0[1],
	    r->o_drqmaskF[0], r->o_drqmaskF[1]);
	printf("  counters(nmem,nport,nirq,ndrq) before: {%#x,%#x,%#x,%#x}\n",
	    r->o_cnt0[0], r->o_cnt0[1], r->o_cnt0[2], r->o_cnt0[3]);
	printf("  counters(nmem,nport,nirq,ndrq) after : {%#x,%#x,%#x,%#x}\n",
	    r->o_cntF[0], r->o_cntF[1], r->o_cntF[2], r->o_cntF[3]);
	if (r->o_alloc_size)
		printf("  configs alloc=%u bytes, last quirk write "
		    "ic_port[%u]=configs+%u -> escape=%s\n",
		    r->o_alloc_size, r->o_max_index, r->o_max_off,
		    r->o_max_off >= r->o_alloc_size ? "YES" : "no");
}

int
main(int argc, char **argv)
{
	struct pnph_req r;
	int fd, sc;
	const char *what;

	if (argc < 2)
		errx(1, "usage: %s <scenario#> [arg]", argv[0]);
	sc = atoi(argv[1]);
	fd = open("/dev/pnph0", O_RDWR);
	if (fd < 0)
		err(1, "open /dev/pnph0");
	memset(&r, 0, sizeof(r));
	r.scenario = (uint32_t)sc;
	if (argc > 2)
		r.arg = (uint32_t)atoi(argv[2]);
	if (ioctl(fd, PNPHIOC_RUN, &r) < 0)
		err(1, "ioctl");
	switch (sc) {
	case PNPH_SC_LAYOUT:
		what = "layout";
		break;
	case PNPH_SC_2314_WALK:
		what = "DF-2314 walk (groomed 0x20 stack residue, len-0 ANSI)";
		break;
	case PNPH_SC_2314_CTRL:
		what = "DF-2314 control (non-space residue)";
		break;
	case PNPH_SC_2314_SANE:
		what = "DF-2314 sanity (normal ANSI string)";
		break;
	case PNPH_SC_2315_D49:
	case PNPH_SC_2315_D50:
	case PNPH_SC_2315_P17:
	case PNPH_SC_2315_P18:
	case PNPH_SC_2315_PN:
		what = "DF-2315";
		break;
	default:
		what = "?";
	}
	printf("== scenario %d (%s) rc=%u\n", sc, what, r.o_rc);
	if ((sc >= 1 && sc <= 3) || sc == 10)
		hexdump_desc(&r);
	if (sc >= 4 && sc <= 8)
		dump_2315(&r);
	if (sc == PNPH_SC_2314_WALK || sc == 10)
		printf("  tries=%u nul_found=%u nul at pad+%lld "
		    "(kva %p; pad [%p,%p))\n",
		    r.o_tries, r.o_nul_found,
		    (long long)r.o_nul_off, (void *)r.o_nul_addr,
		    (void *)r.o_pad_lo, (void *)r.o_pad_hi);
	return (0);
}