// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
/*
 * Sample code to test firmware-management protocol
 *
 * Copyright(c) 2016 Google Inc. All rights reserved.
 * Copyright(c) 2016 Linaro Ltd. All rights reserved.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "../../greybus_firmware.h"

#define FW_DEV_DEFAULT		"/dev/gb-fw-mgmt-0"
#define FW_TAG_INT_DEFAULT	"s3f"
#define FW_TAG_BCND_DEFAULT	"bf_01"
#define FW_UPDATE_TYPE_DEFAULT	0
#define FW_TIMEOUT_DEFAULT	10000

static const char *firmware_tag;
static const char *fwdev = FW_DEV_DEFAULT;
static unsigned int fw_update_type = FW_UPDATE_TYPE_DEFAULT;
static unsigned int fw_timeout = FW_TIMEOUT_DEFAULT;

static struct fw_mgmt_ioc_get_intf_version intf_fw_info;
static struct fw_mgmt_ioc_get_backend_version backend_fw_info;
static struct fw_mgmt_ioc_intf_load_and_validate intf_load;
static struct fw_mgmt_ioc_backend_fw_update backend_update;

static void usage(void)
{
	printf("\nUsage: ./firmware <gb-fw-mgmt-X (default: gb-fw-mgmt-0)> <interface: 0, backend: 1 (default: 0)> <firmware-tag> (default: \"s3f\"/\"bf_01\") <timeout (default: 10000 ms)>\n");
}

static int update_intf_firmware(int fd)
{
	int ret;

	/* Get Interface Firmware Version */
	printf("Get Interface Firmware Version\n");

	ret = ioctl(fd, FW_MGMT_IOC_GET_INTF_FW, &intf_fw_info);
	if (ret < 0) {
		printf("Failed to get interface firmware version: %s (%d)\n",
			fwdev, ret);
		return -1;
	}

	printf("Interface Firmware tag (%s), major (%d), minor (%d)\n",
		intf_fw_info.firmware_tag, intf_fw_info.major,
		intf_fw_info.minor);

	/* Try Interface Firmware load over Unipro */
	printf("Loading Interface Firmware\n");

	intf_load.load_method = GB_FW_U_LOAD_METHOD_UNIPRO;
	intf_load.status = 0;
	intf_load.major = 0;
	intf_load.minor = 0;

	strncpy((char *)&intf_load.firmware_tag, firmware_tag,
		GB_FIRMWARE_U_TAG_MAX_SIZE);

	ret = ioctl(fd, FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE, &intf_load);
	if (ret < 0) {
		printf("Failed to load interface firmware: %s (%d)\n", fwdev,
			ret);
		return -1;
	}

	if (intf_load.status != GB_FW_U_LOAD_STATUS_VALIDATED &&
	    intf_load.status != GB_FW_U_LOAD_STATUS_UNVALIDATED) {
		printf("Load status says loading failed: %d\n",
			intf_load.status);
		return -1;
	}

	printf("Interface Firmware (%s) Load done: major: %d, minor: %d, status: %d\n",
		firmware_tag, intf_load.major, intf_load.minor,
		intf_load.status);

	/* Initiate Mode-switch to the newly loaded firmware */
	printf("Initiate Mode switch\n");

	ret = ioctl(fd, FW_MGMT_IOC_MODE_SWITCH);
	if (ret < 0)
		printf("Failed to initiate mode-switch (%d)\n", ret);

	return ret;
}

static int update_backend_firmware(int fd)
{
	int ret;

	/* Get Backend Firmware Version */
	printf("Getting Backend Firmware Version\n");

	strncpy((char *)&backend_fw_info.firmware_tag, firmware_tag,
		GB_FIRMWARE_U_TAG_MAX_SIZE);

retry_fw_version:
	ret = ioctl(fd, FW_MGMT_IOC_GET_BACKEND_FW, &backend_fw_info);
	if (ret < 0) {
		printf("Failed to get backend firmware version: %s (%d)\n",
			fwdev, ret);
		return -1;
	}

	printf("Backend Firmware tag (%s), major (%d), minor (%d), status (%d)\n",
		backend_fw_info.firmware_tag, backend_fw_info.major,
		backend_fw_info.minor, backend_fw_info.status);

	if (backend_fw_info.status == GB_FW_U_BACKEND_VERSION_STATUS_RETRY)
		goto retry_fw_version;

	if ((backend_fw_info.status != GB_FW_U_BACKEND_VERSION_STATUS_SUCCESS)
	    && (backend_fw_info.status != GB_FW_U_BACKEND_VERSION_STATUS_NOT_AVAILABLE)) {
		printf("Failed to get backend firmware version: %s (%d)\n",
			fwdev, backend_fw_info.status);
		return -1;
	}

	/* Try Backend Firmware Update over Unipro */
	printf("Updating Backend Firmware\n");

	strncpy((char *)&backend_update.firmware_tag, firmware_tag,
		GB_FIRMWARE_U_TAG_MAX_SIZE);

retry_fw_update:
	backend_update.status = 0;

	ret = ioctl(fd, FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE, &backend_update);
	if (ret < 0) {
		printf("Failed to load backend firmware: %s (%d)\n", fwdev, ret);
		return -1;
	}

	if (backend_update.status == GB_FW_U_BACKEND_FW_STATUS_RETRY) {
		printf("Retrying firmware update: %d\n", backend_update.status);
		goto retry_fw_update;
	}

	if (backend_update.status != GB_FW_U_BACKEND_FW_STATUS_SUCCESS) {
		printf("Load status says loading failed: %d\n",
			backend_update.status);
	} else {
		printf("Backend Firmware (%s) Load done: status: %d\n",
				firmware_tag, backend_update.status);
	}

	return 0;
}

int main(int argc, char *argv[])
{
	int fd, ret;
	char *endptr;

	if (argc > 1 &&
	    (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
		usage();
		return -1;
	}

	if (argc > 1)
		fwdev = argv[1];

	if (argc > 2)
		fw_update_type = strtoul(argv[2], &endptr, 10);

	if (argc > 3)
		firmware_tag = argv[3];
	else if (!fw_update_type)
		firmware_tag = FW_TAG_INT_DEFAULT;
	else
		firmware_tag = FW_TAG_BCND_DEFAULT;

	if (argc > 4)
		fw_timeout = strtoul(argv[4], &endptr, 10);

	printf("Trying Firmware update: fwdev: %s, type: %s, tag: %s, timeout: %u\n",
		fwdev, fw_update_type == 0 ? "interface" : "backend",
		firmware_tag, fw_timeout);

	printf("Opening %s firmware management device\n", fwdev);

	fd = open(fwdev, O_RDWR);
	if (fd < 0) {
		printf("Failed to open: %s\n", fwdev);
		return -1;
	}

	/* Set Timeout */
	printf("Setting timeout to %u ms\n", fw_timeout);

	ret = ioctl(fd, FW_MGMT_IOC_SET_TIMEOUT_MS, &fw_timeout);
	if (ret < 0) {
		printf("Failed to set timeout: %s (%d)\n", fwdev, ret);
		ret = -1;
		goto close_fd;
	}

	if (!fw_update_type)
		ret = update_intf_firmware(fd);
	else
		ret = update_backend_firmware(fd);

close_fd:
	close(fd);

	return ret;
}
