Blame tools/fpgaconf/fpgaconf.c

Packit 534379
// Copyright(c) 2017-2020, Intel Corporation
Packit 534379
//
Packit 534379
// Redistribution  and  use  in source  and  binary  forms,  with  or  without
Packit 534379
// modification, are permitted provided that the following conditions are met:
Packit 534379
//
Packit 534379
// * Redistributions of  source code  must retain the  above copyright notice,
Packit 534379
//   this list of conditions and the following disclaimer.
Packit 534379
// * Redistributions in binary form must reproduce the above copyright notice,
Packit 534379
//   this list of conditions and the following disclaimer in the documentation
Packit 534379
//   and/or other materials provided with the distribution.
Packit 534379
// * Neither the name  of Intel Corporation  nor the names of its contributors
Packit 534379
//   may be used to  endorse or promote  products derived  from this  software
Packit 534379
//   without specific prior written permission.
Packit 534379
//
Packit 534379
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 534379
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,  BUT NOT LIMITED TO,  THE
Packit 534379
// IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 534379
// ARE DISCLAIMED.  IN NO EVENT  SHALL THE COPYRIGHT OWNER  OR CONTRIBUTORS BE
Packit 534379
// LIABLE  FOR  ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
Packit 534379
// CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT LIMITED  TO,  PROCUREMENT  OF
Packit 534379
// SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
Packit 534379
// INTERRUPTION)  HOWEVER CAUSED  AND ON ANY THEORY  OF LIABILITY,  WHETHER IN
Packit 534379
// CONTRACT,  STRICT LIABILITY,  OR TORT  (INCLUDING NEGLIGENCE  OR OTHERWISE)
Packit 534379
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
Packit 534379
// POSSIBILITY OF SUCH DAMAGE.
Packit 534379
Packit 534379
/*
Packit 534379
 * @file fpgaconf.c
Packit 534379
 *
Packit 534379
 * @brief FPGA configure command line tool
Packit 534379
 *
Packit 534379
 * fpgaconf allows you to program green bitstream files to an FPGA supported by
Packit 534379
 * the intel-fpga driver and API.
Packit 534379
 *
Packit 534379
 * Features:
Packit 534379
 *   * Auto-discovery of compatible slots for supplied bitstream
Packit 534379
 *   * Dry-run mode ("what would happen if...?")
Packit 534379
 */
Packit 534379
#define _GNU_SOURCE
Packit 534379
#ifdef HAVE_CONFIG_H
Packit 534379
#include <config.h>
Packit 534379
#endif // HAVE_CONFIG_H
Packit 534379
#include <errno.h>
Packit 534379
#include <getopt.h>
Packit 534379
#include <stdio.h>
Packit 534379
#include <stdlib.h>
Packit 534379
#include <string.h>
Packit 534379
#include <stdbool.h>
Packit 534379
#include <sys/stat.h>
Packit 534379
Packit 534379
#include <uuid/uuid.h>
Packit 534379
Packit 534379
#include <opae/fpga.h>
Packit 534379
#include <libbitstream/bitstream.h>
Packit 534379
Packit 534379
/*
Packit 534379
 * macro to check FPGA return codes, print error message, and goto cleanup label
Packit 534379
 * NOTE: this changes the program flow (uses goto)!
Packit 534379
 */
Packit 534379
#define ON_ERR_GOTO(res, label, desc)                                          \
Packit 534379
	do {                                                                   \
Packit 534379
		if ((res) != FPGA_OK) {                                        \
Packit 534379
			print_err((desc), (res));                              \
Packit 534379
			goto label;                                            \
Packit 534379
		}                                                              \
Packit 534379
	} while (0)
Packit 534379
/*
Packit 534379
 * Global configuration, set during parse_args()
Packit 534379
 */
Packit 534379
#define MAX_FILENAME_LEN 256
Packit 534379
struct config {
Packit 534379
	unsigned int verbosity;
Packit 534379
	bool dry_run;
Packit 534379
	enum { INTERACTIVE, /* ask if ambiguous */
Packit 534379
	       NORMAL,      /* stop if ambiguous */
Packit 534379
	       AUTOMATIC    /* choose if ambiguous */
Packit 534379
	} mode;
Packit 534379
	int flags;
Packit 534379
	struct target {
Packit 534379
		int segment;
Packit 534379
		int bus;
Packit 534379
		int device;
Packit 534379
		int function;
Packit 534379
		int socket;
Packit 534379
	} target;
Packit 534379
	char *filename;
Packit 534379
} config = {.verbosity = 0,
Packit 534379
	    .dry_run = false,
Packit 534379
	    .mode = NORMAL,
Packit 534379
	    .flags = 0,
Packit 534379
	    .target = {.segment = -1, .bus = -1, .device = -1, .function = -1, .socket = -1},
Packit 534379
	    .filename = NULL };
Packit 534379
Packit 534379
/*
Packit 534379
 * Print readable error message for fpga_results
Packit 534379
 */
Packit 534379
void print_err(const char *s, fpga_result res)
Packit 534379
{
Packit 534379
	fprintf(stderr, "Error %s: %s\n", s, fpgaErrStr(res));
Packit 534379
}
Packit 534379
Packit 534379
/*
Packit 534379
 * Print message depending on verbosity
Packit 534379
 */
Packit 534379
void print_msg(unsigned int verbosity, const char *s)
Packit 534379
{
Packit 534379
	if (config.verbosity >= verbosity)
Packit 534379
		printf("%s\n", s);
Packit 534379
}
Packit 534379
Packit 534379
/*
Packit 534379
 * Print help
Packit 534379
 * TODO: uncomment options as they are implemented
Packit 534379
 */
Packit 534379
void help(void)
Packit 534379
{
Packit 534379
	printf("\n"
Packit 534379
	       "fpgaconf\n"
Packit 534379
	       "FPGA configuration utility\n"
Packit 534379
	       "\n"
Packit 534379
	       "Usage:\n"
Packit 534379
	       //"        fpgaconf [-hvnAIQ] [-B <bus>] [-D <device>] [-F
Packit 534379
	       //<function>] [-S <socket-id>] <gbs>\n"
Packit 534379
	       "        fpgaconf [-hvn] [-B <bus>] [-D <device>] [-F <function>] [-S <socket-id>] <gbs>\n"
Packit 534379
	       "\n"
Packit 534379
	       "                -h,--help           Print this help\n"
Packit 534379
	       "                -V,--verbose        Increase verbosity\n"
Packit 534379
	       "                -n,--dry-run        Don't actually perform actions\n"
Packit 534379
	       "                --force             Don't try to open accelerator resource\n"
Packit 534379
	       "                --segment           Set target segment number\n"
Packit 534379
	       "                -B,--bus            Set target bus number\n"
Packit 534379
	       "                -D,--device         Set target device number\n"
Packit 534379
	       "                -F,--function       Set target function number\n"
Packit 534379
	       "                -S,--socket-id      Set target socket number\n"
Packit 534379
	       "                 -v,--version       Print version info and exit\n"
Packit 534379
	       /* "                -A,--auto           Automatically choose
Packit 534379
		  target slot if\n" */
Packit 534379
	       /* "                                    multiple valid slots are
Packit 534379
		  available\n" */
Packit 534379
	       /* "                -I,--interactive    Prompt user to choose
Packit 534379
		  target slot if\n" */
Packit 534379
	       /* "                                    multiple valid slots are
Packit 534379
		  available\n" */
Packit 534379
	       /* "                -Q,--quiet          Don't print any messages
Packit 534379
		  except errors\n" */
Packit 534379
	       "\n");
Packit 534379
}
Packit 534379
Packit 534379
/*
Packit 534379
 * Parse command line arguments
Packit 534379
 * TODO: uncomment options as they are implemented
Packit 534379
 */
Packit 534379
#define GETOPT_STRING ":hVnB:D:F:S:AIQv"
Packit 534379
int parse_args(int argc, char *argv[])
Packit 534379
{
Packit 534379
	struct option longopts[] = {
Packit 534379
		{"help",      no_argument,       NULL, 'h'},
Packit 534379
		{"verbose",   no_argument,       NULL, 'V'},
Packit 534379
		{"dry-run",   no_argument,       NULL, 'n'},
Packit 534379
		{"segment",   required_argument, NULL, 0xe},
Packit 534379
		{"bus",       required_argument, NULL, 'B'},
Packit 534379
		{"device",    required_argument, NULL, 'D'},
Packit 534379
		{"function",  required_argument, NULL, 'F'},
Packit 534379
		{"socket-id", required_argument, NULL, 'S'},
Packit 534379
		{"force",     no_argument,       NULL, 0xf},
Packit 534379
		{"version",   no_argument,       NULL, 'v'},
Packit 534379
		/* {"auto",          no_argument,       NULL, 'A'}, */
Packit 534379
		/* {"interactive",   no_argument,       NULL, 'I'}, */
Packit 534379
		/* {"quiet",         no_argument,       NULL, 'Q'}, */
Packit 534379
		{0, 0, 0, 0} };
Packit 534379
Packit 534379
	int getopt_ret;
Packit 534379
	int option_index;
Packit 534379
	char *endptr = NULL;
Packit 534379
Packit 534379
	while (-1
Packit 534379
	       != (getopt_ret = getopt_long(argc, argv, GETOPT_STRING, longopts,
Packit 534379
					    &option_index))) {
Packit 534379
		const char *tmp_optarg = optarg;
Packit 534379
Packit 534379
		if ((optarg) && ('=' == *tmp_optarg)) {
Packit 534379
			++tmp_optarg;
Packit 534379
		}
Packit 534379
Packit 534379
		switch (getopt_ret) {
Packit 534379
		case 'h': /* help */
Packit 534379
			help();
Packit 534379
			return -1;
Packit 534379
Packit 534379
		case 'V': /* verbose */
Packit 534379
			config.verbosity++;
Packit 534379
			break;
Packit 534379
Packit 534379
		case 'n': /* dry-run */
Packit 534379
			config.dry_run = true;
Packit 534379
			break;
Packit 534379
Packit 534379
		case 0xf: /* force */
Packit 534379
			config.flags |= FPGA_RECONF_FORCE;
Packit 534379
			break;
Packit 534379
Packit 534379
		case 0xe: /* segment */
Packit 534379
			if (NULL == tmp_optarg)
Packit 534379
				break;
Packit 534379
			endptr = NULL;
Packit 534379
			config.target.segment =
Packit 534379
				(int)strtoul(tmp_optarg, &endptr, 0);
Packit 534379
			if (endptr != tmp_optarg + strlen(tmp_optarg)) {
Packit 534379
				fprintf(stderr, "invalid segment: %s\n",
Packit 534379
					tmp_optarg);
Packit 534379
				return -1;
Packit 534379
			}
Packit 534379
			break;
Packit 534379
Packit 534379
		case 'B': /* bus */
Packit 534379
			if (NULL == tmp_optarg)
Packit 534379
				break;
Packit 534379
			endptr = NULL;
Packit 534379
			config.target.bus =
Packit 534379
				(int)strtoul(tmp_optarg, &endptr, 0);
Packit 534379
			if (endptr != tmp_optarg + strlen(tmp_optarg)) {
Packit 534379
				fprintf(stderr, "invalid bus: %s\n",
Packit 534379
					tmp_optarg);
Packit 534379
				return -1;
Packit 534379
			}
Packit 534379
			break;
Packit 534379
Packit 534379
		case 'D': /* device */
Packit 534379
			if (NULL == tmp_optarg)
Packit 534379
				break;
Packit 534379
			endptr = NULL;
Packit 534379
			config.target.device =
Packit 534379
				(int)strtoul(tmp_optarg, &endptr, 0);
Packit 534379
			if (endptr != tmp_optarg + strlen(tmp_optarg)) {
Packit 534379
				fprintf(stderr, "invalid device: %s\n",
Packit 534379
					tmp_optarg);
Packit 534379
				return -1;
Packit 534379
			}
Packit 534379
			break;
Packit 534379
Packit 534379
		case 'F': /* function */
Packit 534379
			if (NULL == tmp_optarg)
Packit 534379
				break;
Packit 534379
			endptr = NULL;
Packit 534379
			config.target.function =
Packit 534379
				(int)strtoul(tmp_optarg, &endptr, 0);
Packit 534379
			if (endptr != tmp_optarg + strlen(tmp_optarg)) {
Packit 534379
				fprintf(stderr, "invalid function: %s\n",
Packit 534379
					tmp_optarg);
Packit 534379
				return -1;
Packit 534379
			}
Packit 534379
			break;
Packit 534379
Packit 534379
		case 'S': /* socket */
Packit 534379
			if (NULL == tmp_optarg)
Packit 534379
				break;
Packit 534379
			endptr = NULL;
Packit 534379
			config.target.socket =
Packit 534379
				(int)strtoul(tmp_optarg, &endptr, 0);
Packit 534379
			if (endptr != tmp_optarg + strlen(tmp_optarg)) {
Packit 534379
				fprintf(stderr, "invalid socket: %s\n",
Packit 534379
					tmp_optarg);
Packit 534379
				return -1;
Packit 534379
			}
Packit 534379
			break;
Packit 534379
Packit 534379
		case 'A': /* auto */
Packit 534379
			config.mode = AUTOMATIC;
Packit 534379
			break;
Packit 534379
Packit 534379
		case 'I': /* interactive */
Packit 534379
			config.mode = INTERACTIVE;
Packit 534379
			break;
Packit 534379
Packit 534379
		case 'Q': /* quiet */
Packit 534379
			config.verbosity = 0;
Packit 534379
			break;
Packit 534379
Packit 534379
		case 'v': /* version */
Packit 534379
			fprintf(stdout, "fpgaconf %s %s%s\n",
Packit 534379
					OPAE_VERSION,
Packit 534379
					OPAE_GIT_COMMIT_HASH,
Packit 534379
					OPAE_GIT_SRC_TREE_DIRTY ? "*":"");
Packit 534379
			return -1;
Packit 534379
Packit 534379
		case ':': /* missing option argument */
Packit 534379
			fprintf(stderr, "Missing option argument\n");
Packit 534379
			return -1;
Packit 534379
Packit 534379
		case '?':
Packit 534379
		default: /* invalid option */
Packit 534379
			fprintf(stderr, "Invalid cmdline options\n");
Packit 534379
			return -1;
Packit 534379
		}
Packit 534379
	}
Packit 534379
Packit 534379
	/* use first non-option argument as GBS filename */
Packit 534379
	if (optind == argc) {
Packit 534379
		fprintf(stderr, "No GBS file\n");
Packit 534379
		return -1;
Packit 534379
	}
Packit 534379
	config.filename = canonicalize_file_name(argv[optind]);
Packit 534379
	if (config.filename) {
Packit 534379
		return 0;
Packit 534379
	} else {
Packit 534379
		fprintf(stderr, "Error locating GBS file specified: \"%s\"\n", strerror(errno));
Packit 534379
		return -1;
Packit 534379
	}
Packit 534379
}
Packit 534379
Packit 534379
fpga_result get_fpga_interface_id(fpga_token token, fpga_guid interface_id)
Packit 534379
{
Packit 534379
	fpga_result result = FPGA_OK;
Packit 534379
	fpga_result resval = FPGA_OK;
Packit 534379
	fpga_properties filter = NULL;
Packit 534379
	fpga_objtype objtype;
Packit 534379
	fpga_guid guid;
Packit 534379
Packit 534379
	result = fpgaGetProperties(token, &filter);
Packit 534379
	if (result != FPGA_OK) {
Packit 534379
		OPAE_ERR("Failed to get Token Properties Object");
Packit 534379
		goto out;
Packit 534379
	}
Packit 534379
Packit 534379
	result = fpgaPropertiesGetObjectType(filter, &objtype);
Packit 534379
	if (result != FPGA_OK) {
Packit 534379
		OPAE_ERR("Failed to get Token Properties Object");
Packit 534379
		goto out_destroy;
Packit 534379
	}
Packit 534379
Packit 534379
	if (objtype != FPGA_DEVICE) {
Packit 534379
		OPAE_ERR("Invalid FPGA object type");
Packit 534379
		result = FPGA_EXCEPTION;
Packit 534379
		goto out_destroy;
Packit 534379
	}
Packit 534379
Packit 534379
	result = fpgaPropertiesGetGUID(filter, &guid);
Packit 534379
	if (result != FPGA_OK) {
Packit 534379
		OPAE_ERR("Failed to get PR guid");
Packit 534379
		goto out_destroy;
Packit 534379
	}
Packit 534379
Packit 534379
	memcpy(interface_id, guid, sizeof(fpga_guid));
Packit 534379
Packit 534379
out_destroy:
Packit 534379
	resval = (result != FPGA_OK) ? result : resval;
Packit 534379
	result = fpgaDestroyProperties(&filter);
Packit 534379
	if (result != FPGA_OK) {
Packit 534379
		OPAE_ERR("Failed to destroy properties");
Packit 534379
	}
Packit 534379
Packit 534379
out:
Packit 534379
	resval = (result != FPGA_OK) ? result : resval;
Packit 534379
	return resval;
Packit 534379
}
Packit 534379
Packit 534379
/*
Packit 534379
 * Prints Actual and Expected Interface id
Packit 534379
 */
Packit 534379
int print_interface_id(fpga_guid actual_interface_id)
Packit 534379
{
Packit 534379
	fpga_properties filter = NULL;
Packit 534379
	uint32_t num_matches = 0;
Packit 534379
	int retval = -1;
Packit 534379
	fpga_handle fpga_handle = NULL;
Packit 534379
	fpga_result res = -1;
Packit 534379
	fpga_token fpga_token = NULL;
Packit 534379
	fpga_guid expt_interface_id = {0};
Packit 534379
	char guid_str[37] = {0};
Packit 534379
Packit 534379
	res = fpgaGetProperties(NULL, &filter);
Packit 534379
	ON_ERR_GOTO(res, out_err, "creating properties object");
Packit 534379
Packit 534379
	res = fpgaPropertiesSetObjectType(filter, FPGA_DEVICE);
Packit 534379
	ON_ERR_GOTO(res, out_destroy, "setting object type");
Packit 534379
Packit 534379
	if (-1 != config.target.segment) {
Packit 534379
		res = fpgaPropertiesSetSegment(filter, config.target.segment);
Packit 534379
		ON_ERR_GOTO(res, out_destroy, "setting segment");
Packit 534379
	}
Packit 534379
Packit 534379
	if (-1 != config.target.bus) {
Packit 534379
		res = fpgaPropertiesSetBus(filter, config.target.bus);
Packit 534379
		ON_ERR_GOTO(res, out_destroy, "setting bus");
Packit 534379
	}
Packit 534379
Packit 534379
	if (-1 != config.target.device) {
Packit 534379
		res = fpgaPropertiesSetDevice(filter, config.target.device);
Packit 534379
		ON_ERR_GOTO(res, out_destroy, "setting device");
Packit 534379
	}
Packit 534379
Packit 534379
	if (-1 != config.target.function) {
Packit 534379
		res = fpgaPropertiesSetFunction(filter, config.target.function);
Packit 534379
		ON_ERR_GOTO(res, out_destroy, "setting function");
Packit 534379
	}
Packit 534379
Packit 534379
	if (-1 != config.target.socket) {
Packit 534379
		res = fpgaPropertiesSetSocketID(filter, config.target.socket);
Packit 534379
		ON_ERR_GOTO(res, out_destroy, "setting socket id");
Packit 534379
	}
Packit 534379
Packit 534379
	res = fpgaEnumerate(&filter, 1, &fpga_token, 1, &num_matches);
Packit 534379
	ON_ERR_GOTO(res, out_destroy, "enumerating FPGAs");
Packit 534379
Packit 534379
	if (num_matches > 0) {
Packit 534379
		retval = (int)num_matches; /* FPGA found */
Packit 534379
	} else {
Packit 534379
		retval = 0; /* no FPGA found */
Packit 534379
		goto out_destroy;
Packit 534379
	}
Packit 534379
Packit 534379
	res = fpgaOpen(fpga_token, &fpga_handle, 0);
Packit 534379
	ON_ERR_GOTO(res, out_destroy, "opening fpga");
Packit 534379
Packit 534379
	res = get_fpga_interface_id(fpga_token, expt_interface_id);
Packit 534379
	ON_ERR_GOTO(res, out_close, "interfaceid get");
Packit 534379
Packit 534379
	uuid_unparse(expt_interface_id, guid_str);
Packit 534379
	printf("Expected Interface id:  %s\n", guid_str);
Packit 534379
Packit 534379
	uuid_unparse(actual_interface_id, guid_str);
Packit 534379
	printf("Actual Interface id:    %s\n", guid_str);
Packit 534379
Packit 534379
Packit 534379
out_close:
Packit 534379
	res = fpgaClose(fpga_handle);
Packit 534379
	ON_ERR_GOTO(res, out_destroy, "closing fme");
Packit 534379
Packit 534379
out_destroy:
Packit 534379
	if (fpga_token)
Packit 534379
		fpgaDestroyToken(&fpga_token);
Packit 534379
	res = fpgaDestroyProperties(&filter); /* not needed anymore */
Packit 534379
	ON_ERR_GOTO(res, out_err, "destroying properties object");
Packit 534379
out_err:
Packit 534379
	return retval;
Packit 534379
}
Packit 534379
Packit 534379
/*
Packit 534379
 * Find first FPGA matching the interface ID of the GBS
Packit 534379
 *
Packit 534379
 * @returns the total number of FPGAs matching the interface ID
Packit 534379
 */
Packit 534379
int find_fpga(fpga_guid interface_id, fpga_token *fpga)
Packit 534379
{
Packit 534379
	fpga_properties filter = NULL;
Packit 534379
	uint32_t num_matches;
Packit 534379
	fpga_result res;
Packit 534379
	int retval = -1;
Packit 534379
Packit 534379
	/* Get number of FPGAs in system */
Packit 534379
	res = fpgaGetProperties(NULL, &filter);
Packit 534379
	ON_ERR_GOTO(res, out_err, "creating properties object");
Packit 534379
Packit 534379
	res = fpgaPropertiesSetObjectType(filter, FPGA_DEVICE);
Packit 534379
	ON_ERR_GOTO(res, out_destroy, "setting object type");
Packit 534379
Packit 534379
	res = fpgaPropertiesSetGUID(filter, interface_id);
Packit 534379
	ON_ERR_GOTO(res, out_destroy, "setting interface ID");
Packit 534379
Packit 534379
	if (-1 != config.target.segment) {
Packit 534379
		res = fpgaPropertiesSetSegment(filter, config.target.segment);
Packit 534379
		ON_ERR_GOTO(res, out_destroy, "setting segment");
Packit 534379
	}
Packit 534379
Packit 534379
	if (-1 != config.target.bus) {
Packit 534379
		res = fpgaPropertiesSetBus(filter, config.target.bus);
Packit 534379
		ON_ERR_GOTO(res, out_destroy, "setting bus");
Packit 534379
	}
Packit 534379
Packit 534379
	if (-1 != config.target.device) {
Packit 534379
		res = fpgaPropertiesSetDevice(filter, config.target.device);
Packit 534379
		ON_ERR_GOTO(res, out_destroy, "setting device");
Packit 534379
	}
Packit 534379
Packit 534379
	if (-1 != config.target.function) {
Packit 534379
		res = fpgaPropertiesSetFunction(filter, config.target.function);
Packit 534379
		ON_ERR_GOTO(res, out_destroy, "setting function");
Packit 534379
	}
Packit 534379
Packit 534379
	if (-1 != config.target.socket) {
Packit 534379
		res = fpgaPropertiesSetSocketID(filter, config.target.socket);
Packit 534379
		ON_ERR_GOTO(res, out_destroy, "setting socket id");
Packit 534379
	}
Packit 534379
Packit 534379
	res = fpgaEnumerate(&filter, 1, fpga, 1, &num_matches);
Packit 534379
	ON_ERR_GOTO(res, out_destroy, "enumerating FPGAs");
Packit 534379
Packit 534379
	if (num_matches > 0) {
Packit 534379
		retval = (int)num_matches; /* FPGA found */
Packit 534379
	} else {
Packit 534379
		retval = 0; /* no FPGA found */
Packit 534379
	}
Packit 534379
Packit 534379
out_destroy:
Packit 534379
	res = fpgaDestroyProperties(&filter); /* not needed anymore */
Packit 534379
	ON_ERR_GOTO(res, out_err, "destroying properties object");
Packit 534379
out_err:
Packit 534379
	return retval;
Packit 534379
}
Packit 534379
Packit 534379
int program_bitstream(fpga_token token, uint32_t slot_num,
Packit 534379
		      opae_bitstream_info *info, int flags)
Packit 534379
{
Packit 534379
	fpga_handle handle;
Packit 534379
	fpga_result res;
Packit 534379
Packit 534379
	print_msg(2, "Opening FPGA");
Packit 534379
	res = fpgaOpen(token, &handle, 0);
Packit 534379
	ON_ERR_GOTO(res, out_err, "opening FPGA");
Packit 534379
Packit 534379
	print_msg(1, "Writing bitstream");
Packit 534379
	if (config.dry_run) {
Packit 534379
		print_msg(1, "[--dry-run] Skipping reconfiguration");
Packit 534379
	} else {
Packit 534379
		res = fpgaReconfigureSlot(handle, slot_num, info->data,
Packit 534379
					  info->data_len, flags);
Packit 534379
		ON_ERR_GOTO(res, out_close, "writing bitstream to FPGA");
Packit 534379
	}
Packit 534379
Packit 534379
	print_msg(2, "Closing FPGA");
Packit 534379
	res = fpgaClose(handle);
Packit 534379
	ON_ERR_GOTO(res, out_err, "closing FPGA");
Packit 534379
	return 1;
Packit 534379
Packit 534379
out_close:
Packit 534379
	res = fpgaClose(handle);
Packit 534379
	ON_ERR_GOTO(res, out_err, "closing FPGA");
Packit 534379
out_err:
Packit 534379
	return -1;
Packit 534379
}
Packit 534379
Packit 534379
Packit 534379
int main(int argc, char *argv[])
Packit 534379
{
Packit 534379
	int res;
Packit 534379
	fpga_result result;
Packit 534379
	int retval = 0;
Packit 534379
	opae_bitstream_info info;
Packit 534379
	fpga_token token;
Packit 534379
	uint32_t slot_num = 0; /* currently, we don't support multiple slots */
Packit 534379
Packit 534379
	/* parse command line arguments */
Packit 534379
	res = parse_args(argc, argv);
Packit 534379
	if (res < 0) {
Packit 534379
		retval = 1;
Packit 534379
		goto out_exit;
Packit 534379
	}
Packit 534379
Packit 534379
	if (config.dry_run)
Packit 534379
		printf("--dry-run is set\n");
Packit 534379
Packit 534379
	/* allocate memory and read bitstream data */
Packit 534379
	print_msg(1, "Reading bitstream");
Packit 534379
	result = opae_load_bitstream(config.filename, &info;;
Packit 534379
	if (result != FPGA_OK) {
Packit 534379
		retval = 2;
Packit 534379
		goto out_exit;
Packit 534379
	}
Packit 534379
Packit 534379
	/* find suitable slot */
Packit 534379
	print_msg(1, "Looking for slot");
Packit 534379
	res = find_fpga(info.pr_interface_id, &token);
Packit 534379
	if (res < 0) {
Packit 534379
		retval = 3;
Packit 534379
		goto out_free;
Packit 534379
	}
Packit 534379
	if (res == 0) {
Packit 534379
		fprintf(stderr, "No suitable slots found.\n");
Packit 534379
		retval = 4;
Packit 534379
		if (config.verbosity > 0)
Packit 534379
			print_interface_id(info.pr_interface_id);
Packit 534379
		goto out_free;
Packit 534379
	}
Packit 534379
	if (res > 1) {
Packit 534379
		fprintf(stderr,
Packit 534379
			"Found more than one suitable slot, please be more specific.\n");
Packit 534379
		retval = 5;
Packit 534379
		goto out_destroy;
Packit 534379
	}
Packit 534379
	print_msg(1, "Found slot");
Packit 534379
Packit 534379
	/* program bitstream */
Packit 534379
	print_msg(1, "Programming bitstream");
Packit 534379
	res = program_bitstream(token, slot_num, &info, config.flags);
Packit 534379
	if (res < 0) {
Packit 534379
		retval = 5;
Packit 534379
		goto out_destroy;
Packit 534379
	}
Packit 534379
	print_msg(1, "Done");
Packit 534379
Packit 534379
	/* clean up */
Packit 534379
out_destroy:
Packit 534379
	fpgaDestroyToken(&token);
Packit 534379
out_free:
Packit 534379
	opae_unload_bitstream(&info;;
Packit 534379
out_exit:
Packit 534379
	if (config.filename) {
Packit 534379
		free(config.filename);
Packit 534379
		config.filename = NULL;
Packit 534379
	}
Packit 534379
	return retval;
Packit 534379
}