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-hammer.c (3876B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * gpio-hammer - example swiss army knife to shake GPIO lines on a system
      4 *
      5 * Copyright (C) 2016 Linus Walleij
      6 *
      7 * Usage:
      8 *	gpio-hammer -n <device-name> -o <offset1> -o <offset2>
      9 */
     10
     11#include <unistd.h>
     12#include <stdlib.h>
     13#include <stdbool.h>
     14#include <stdio.h>
     15#include <dirent.h>
     16#include <errno.h>
     17#include <string.h>
     18#include <poll.h>
     19#include <fcntl.h>
     20#include <getopt.h>
     21#include <sys/ioctl.h>
     22#include <linux/gpio.h>
     23#include "gpio-utils.h"
     24
     25int hammer_device(const char *device_name, unsigned int *lines, int num_lines,
     26		  unsigned int loops)
     27{
     28	struct gpio_v2_line_values values;
     29	struct gpio_v2_line_config config;
     30	char swirr[] = "-\\|/";
     31	int fd;
     32	int ret;
     33	int i, j;
     34	unsigned int iteration = 0;
     35
     36	memset(&config, 0, sizeof(config));
     37	config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
     38
     39	ret = gpiotools_request_line(device_name, lines, num_lines,
     40				     &config, "gpio-hammer");
     41	if (ret < 0)
     42		goto exit_error;
     43	else
     44		fd = ret;
     45
     46	values.mask = 0;
     47	values.bits = 0;
     48	for (i = 0; i < num_lines; i++)
     49		gpiotools_set_bit(&values.mask, i);
     50
     51	ret = gpiotools_get_values(fd, &values);
     52	if (ret < 0)
     53		goto exit_close_error;
     54
     55	fprintf(stdout, "Hammer lines [");
     56	for (i = 0; i < num_lines; i++) {
     57		fprintf(stdout, "%d", lines[i]);
     58		if (i != (num_lines - 1))
     59			fprintf(stdout, ", ");
     60	}
     61	fprintf(stdout, "] on %s, initial states: [", device_name);
     62	for (i = 0; i < num_lines; i++) {
     63		fprintf(stdout, "%d", gpiotools_test_bit(values.bits, i));
     64		if (i != (num_lines - 1))
     65			fprintf(stdout, ", ");
     66	}
     67	fprintf(stdout, "]\n");
     68
     69	/* Hammertime! */
     70	j = 0;
     71	while (1) {
     72		/* Invert all lines so we blink */
     73		for (i = 0; i < num_lines; i++)
     74			gpiotools_change_bit(&values.bits, i);
     75
     76		ret = gpiotools_set_values(fd, &values);
     77		if (ret < 0)
     78			goto exit_close_error;
     79
     80		/* Re-read values to get status */
     81		ret = gpiotools_get_values(fd, &values);
     82		if (ret < 0)
     83			goto exit_close_error;
     84
     85		fprintf(stdout, "[%c] ", swirr[j]);
     86		j++;
     87		if (j == sizeof(swirr) - 1)
     88			j = 0;
     89
     90		fprintf(stdout, "[");
     91		for (i = 0; i < num_lines; i++) {
     92			fprintf(stdout, "%d: %d", lines[i],
     93				gpiotools_test_bit(values.bits, i));
     94			if (i != (num_lines - 1))
     95				fprintf(stdout, ", ");
     96		}
     97		fprintf(stdout, "]\r");
     98		fflush(stdout);
     99		sleep(1);
    100		iteration++;
    101		if (loops && iteration == loops)
    102			break;
    103	}
    104	fprintf(stdout, "\n");
    105	ret = 0;
    106
    107exit_close_error:
    108	gpiotools_release_line(fd);
    109exit_error:
    110	return ret;
    111}
    112
    113void print_usage(void)
    114{
    115	fprintf(stderr, "Usage: gpio-hammer [options]...\n"
    116		"Hammer GPIO lines, 0->1->0->1...\n"
    117		"  -n <name>  Hammer GPIOs on a named device (must be stated)\n"
    118		"  -o <n>     Offset[s] to hammer, at least one, several can be stated\n"
    119		" [-c <n>]    Do <n> loops (optional, infinite loop if not stated)\n"
    120		"  -?         This helptext\n"
    121		"\n"
    122		"Example:\n"
    123		"gpio-hammer -n gpiochip0 -o 4\n"
    124	);
    125}
    126
    127int main(int argc, char **argv)
    128{
    129	const char *device_name = NULL;
    130	unsigned int lines[GPIOHANDLES_MAX];
    131	unsigned int loops = 0;
    132	int num_lines;
    133	int c;
    134	int i;
    135
    136	i = 0;
    137	while ((c = getopt(argc, argv, "c:n:o:?")) != -1) {
    138		switch (c) {
    139		case 'c':
    140			loops = strtoul(optarg, NULL, 10);
    141			break;
    142		case 'n':
    143			device_name = optarg;
    144			break;
    145		case 'o':
    146			/*
    147			 * Avoid overflow. Do not immediately error, we want to
    148			 * be able to accurately report on the amount of times
    149			 * '-o' was given to give an accurate error message
    150			 */
    151			if (i < GPIOHANDLES_MAX)
    152				lines[i] = strtoul(optarg, NULL, 10);
    153
    154			i++;
    155			break;
    156		case '?':
    157			print_usage();
    158			return -1;
    159		}
    160	}
    161
    162	if (i >= GPIOHANDLES_MAX) {
    163		fprintf(stderr,
    164			"Only %d occurrences of '-o' are allowed, %d were found\n",
    165			GPIOHANDLES_MAX, i + 1);
    166		return -1;
    167	}
    168
    169	num_lines = i;
    170
    171	if (!device_name || !num_lines) {
    172		print_usage();
    173		return -1;
    174	}
    175	return hammer_device(device_name, lines, num_lines, loops);
    176}