cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gpio-watch.c (2165B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * gpio-watch - monitor unrequested lines for property changes using the
      4 *              character device
      5 *
      6 * Copyright (C) 2019 BayLibre SAS
      7 * Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
      8 */
      9
     10#include <ctype.h>
     11#include <errno.h>
     12#include <fcntl.h>
     13#include <inttypes.h>
     14#include <linux/gpio.h>
     15#include <poll.h>
     16#include <stdbool.h>
     17#include <stdio.h>
     18#include <stdlib.h>
     19#include <string.h>
     20#include <sys/ioctl.h>
     21#include <unistd.h>
     22
     23int main(int argc, char **argv)
     24{
     25	struct gpio_v2_line_info_changed chg;
     26	struct gpio_v2_line_info req;
     27	struct pollfd pfd;
     28	int fd, i, j, ret;
     29	char *event, *end;
     30	ssize_t rd;
     31
     32	if (argc < 3)
     33		goto err_usage;
     34
     35	fd = open(argv[1], O_RDWR | O_CLOEXEC);
     36	if (fd < 0) {
     37		perror("unable to open gpiochip");
     38		return EXIT_FAILURE;
     39	}
     40
     41	for (i = 0, j = 2; i < argc - 2; i++, j++) {
     42		memset(&req, 0, sizeof(req));
     43
     44		req.offset = strtoul(argv[j], &end, 0);
     45		if (*end != '\0')
     46			goto err_usage;
     47
     48		ret = ioctl(fd, GPIO_V2_GET_LINEINFO_WATCH_IOCTL, &req);
     49		if (ret) {
     50			perror("unable to set up line watch");
     51			return EXIT_FAILURE;
     52		}
     53	}
     54
     55	pfd.fd = fd;
     56	pfd.events = POLLIN | POLLPRI;
     57
     58	for (;;) {
     59		ret = poll(&pfd, 1, 5000);
     60		if (ret < 0) {
     61			perror("error polling the linechanged fd");
     62			return EXIT_FAILURE;
     63		} else if (ret > 0) {
     64			memset(&chg, 0, sizeof(chg));
     65			rd = read(pfd.fd, &chg, sizeof(chg));
     66			if (rd < 0 || rd != sizeof(chg)) {
     67				if (rd != sizeof(chg))
     68					errno = EIO;
     69
     70				perror("error reading line change event");
     71				return EXIT_FAILURE;
     72			}
     73
     74			switch (chg.event_type) {
     75			case GPIO_V2_LINE_CHANGED_REQUESTED:
     76				event = "requested";
     77				break;
     78			case GPIO_V2_LINE_CHANGED_RELEASED:
     79				event = "released";
     80				break;
     81			case GPIO_V2_LINE_CHANGED_CONFIG:
     82				event = "config changed";
     83				break;
     84			default:
     85				fprintf(stderr,
     86					"invalid event type received from the kernel\n");
     87				return EXIT_FAILURE;
     88			}
     89
     90			printf("line %u: %s at %" PRIu64 "\n",
     91			       chg.info.offset, event, (uint64_t)chg.timestamp_ns);
     92		}
     93	}
     94
     95	return 0;
     96
     97err_usage:
     98	printf("%s: <gpiochip> <line0> <line1> ...\n", argv[0]);
     99	return EXIT_FAILURE;
    100}