patches for DPDK stable branches
 help / color / mirror / Atom feed
From: "Zhang, Tianfei" <tianfei.zhang@intel.com>
To: "Huang, Wei" <wei.huang@intel.com>, "dev@dpdk.org" <dev@dpdk.org>,
	"Xu, Rosen" <rosen.xu@intel.com>,
	"Zhang, Qi Z" <qi.z.zhang@intel.com>
Cc: "stable@dpdk.org" <stable@dpdk.org>
Subject: Re: [dpdk-stable] [PATCH v1 1/4] raw/ifpga: add fpga rsu function
Date: Wed, 30 Dec 2020 03:04:38 +0000	[thread overview]
Message-ID: <DM6PR11MB3131DFC5D2182FD0C175F0C7E3D70@DM6PR11MB3131.namprd11.prod.outlook.com> (raw)
In-Reply-To: <1609293255-2781-2-git-send-email-wei.huang@intel.com>



> -----Original Message-----
> From: Huang, Wei <wei.huang@intel.com>
> Sent: 2020年12月30日 9:54
> To: dev@dpdk.org; Xu, Rosen <rosen.xu@intel.com>; Zhang, Qi Z
> <qi.z.zhang@intel.com>
> Cc: stable@dpdk.org; Zhang, Tianfei <tianfei.zhang@intel.com>; Huang, Wei
> <wei.huang@intel.com>
> Subject: [PATCH v1 1/4] raw/ifpga: add fpga rsu function
> 
> RSU (Remote System Update) depends on secure manager which may be
> different on various implementations, so a new secure manager device is
> implemented for adapting such difference.
> There are three major functions added:
> 1. ifpga_rawdev_update_flash() updates flash with specific image file.
> 2. ifpga_rawdev_stop_flash_update() aborts flash update process.
> 3. ifpga_rawdev_reload() reloads FPGA from updated flash.
> 
> Signed-off-by: Wei Huang <wei.huang@intel.com>
> ---
>  drivers/raw/ifpga/base/ifpga_api.c        |  26 +
>  drivers/raw/ifpga/base/ifpga_fme.c        |   8 +
>  drivers/raw/ifpga/base/ifpga_fme_rsu.c    | 437 +++++++++++++++
>  drivers/raw/ifpga/base/ifpga_hw.h         |   1 +
>  drivers/raw/ifpga/base/ifpga_sec_mgr.c    | 639
> ++++++++++++++++++++++
>  drivers/raw/ifpga/base/ifpga_sec_mgr.h    |  89 +++
>  drivers/raw/ifpga/base/meson.build        |   2 +
>  drivers/raw/ifpga/base/opae_hw_api.c      |  59 ++
>  drivers/raw/ifpga/base/opae_hw_api.h      |  11 +
>  drivers/raw/ifpga/base/opae_intel_max10.c |  51 ++
> drivers/raw/ifpga/base/opae_intel_max10.h |  44 ++
>  drivers/raw/ifpga/ifpga_rawdev.c          |  55 ++
>  drivers/raw/ifpga/ifpga_rawdev.h          |   7 +-
>  13 files changed, 1428 insertions(+), 1 deletion(-)  create mode 100644
> drivers/raw/ifpga/base/ifpga_fme_rsu.c
>  create mode 100644 drivers/raw/ifpga/base/ifpga_sec_mgr.c
>  create mode 100644 drivers/raw/ifpga/base/ifpga_sec_mgr.h
> 
> diff --git a/drivers/raw/ifpga/base/ifpga_api.c
> b/drivers/raw/ifpga/base/ifpga_api.c
> index 1ff57fa18..1aedf150b 100644
> --- a/drivers/raw/ifpga/base/ifpga_api.c
> +++ b/drivers/raw/ifpga/base/ifpga_api.c
> @@ -5,6 +5,7 @@
>  #include "ifpga_api.h"
>  #include "ifpga_enumerate.h"
>  #include "ifpga_feature_dev.h"
> +#include "ifpga_sec_mgr.h"
> 
>  #include "opae_hw_api.h"
> 
> @@ -228,11 +229,36 @@ static int ifpga_mgr_get_board_info(struct
> opae_manager *mgr,
>  	return 0;
>  }
> 
> +static int ifpga_mgr_update_flash(struct opae_manager *mgr, const char
> *image,
> +	u64 *status)
> +{
> +	struct ifpga_fme_hw *fme = mgr->data;
> +
> +	return fpga_update_flash(fme, image, status); }
> +
> +static int ifpga_mgr_stop_flash_update(struct opae_manager *mgr, int
> +force) {
> +	struct ifpga_fme_hw *fme = mgr->data;
> +
> +	return fpga_stop_flash_update(fme, force); }
> +
> +static int ifpga_mgr_reload(struct opae_manager *mgr, int type, int
> +page) {
> +	struct ifpga_fme_hw *fme = mgr->data;
> +
> +	return fpga_reload(fme, type, page);
> +}
> +
>  struct opae_manager_ops ifpga_mgr_ops = {
>  	.flash = ifpga_mgr_flash,
>  	.get_eth_group_region_info = ifpga_mgr_get_eth_group_region_info,
>  	.get_sensor_value = ifpga_mgr_get_sensor_value,
>  	.get_board_info = ifpga_mgr_get_board_info,
> +	.update_flash = ifpga_mgr_update_flash,
> +	.stop_flash_update = ifpga_mgr_stop_flash_update,
> +	.reload = ifpga_mgr_reload,
>  };
> 
>  static int ifpga_mgr_read_mac_rom(struct opae_manager *mgr, int offset,
> diff --git a/drivers/raw/ifpga/base/ifpga_fme.c
> b/drivers/raw/ifpga/base/ifpga_fme.c
> index f29ff3159..34fd9a818 100644
> --- a/drivers/raw/ifpga/base/ifpga_fme.c
> +++ b/drivers/raw/ifpga/base/ifpga_fme.c
> @@ -7,6 +7,7 @@
>  #include "opae_intel_max10.h"
>  #include "opae_i2c.h"
>  #include "opae_at24_eeprom.h"
> +#include "ifpga_sec_mgr.h"
> 
>  #define PWR_THRESHOLD_MAX       0x7F
> 
> @@ -1152,6 +1153,12 @@ static int fme_nios_spi_init(struct ifpga_feature
> *feature)
>  	if (spi_self_checking(max10))
>  		goto spi_fail;
> 
> +	ret = init_sec_mgr(fme);
> +	if (ret) {
> +		dev_err(fme, "security manager init fail\n");
> +		goto spi_fail;
> +	}
> +
>  	return ret;
> 
>  spi_fail:
> @@ -1165,6 +1172,7 @@ static void fme_nios_spi_uinit(struct ifpga_feature
> *feature)  {
>  	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
> 
> +	release_sec_mgr(fme);
>  	if (fme->max10_dev)
>  		intel_max10_device_remove(fme->max10_dev);
>  }
> diff --git a/drivers/raw/ifpga/base/ifpga_fme_rsu.c
> b/drivers/raw/ifpga/base/ifpga_fme_rsu.c
> new file mode 100644
> index 000000000..dfeb3a698
> --- /dev/null
> +++ b/drivers/raw/ifpga/base/ifpga_fme_rsu.c
> @@ -0,0 +1,437 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2020 Intel Corporation
> + */
> +
> +#include <fcntl.h>
> +#include <signal.h>
> +#include <unistd.h>
> +#include "ifpga_sec_mgr.h"
> +
> +

Pls remove one blank line.

> +static struct ifpga_sec_mgr *sec_mgr;
> +
> +static void set_rsu_control(struct ifpga_sec_mgr *smgr, uint32_t ctrl)
> +{
> +	if (smgr && smgr->rsu_control)
> +		*smgr->rsu_control = ctrl;
> +}
> +
> +static uint32_t get_rsu_control(struct ifpga_sec_mgr *smgr) {
> +	if (smgr && smgr->rsu_control)
> +		return *smgr->rsu_control;
> +	return 0;
> +}
> +
> +static void set_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t status,
> +	uint32_t progress)
> +{
> +	if (smgr && smgr->rsu_status)
> +		*smgr->rsu_status = ((status << 16) & 0xffff0000) |
> +			(progress & 0xffff);
> +}
> +
> +static void get_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t *status,
> +	uint32_t *progress)
> +{
> +	if (smgr && smgr->rsu_status) {
> +		if (status)
> +			*status = (*smgr->rsu_status >> 16) & 0xffff;
> +		if (progress)
> +			*progress = *smgr->rsu_status & 0xffff;
> +	}
> +	if (smgr && smgr->rsu_status) {
> +		if (status)
> +			*status = (*smgr->rsu_status >> 16) & 0xffff;
> +		if (progress)
> +			*progress = *smgr->rsu_status & 0xffff;
> +	}
> +}
> +
> +static void sig_handler(int sig, siginfo_t *info, void *data) {
> +	(void)(info);
> +	(void)(data);
> +
> +	switch (sig) {
> +	case SIGINT:
> +		if (sec_mgr) {
> +			dev_info(sec_mgr, "Interrupt secure flash update"
> +				" by keyboard\n");
> +			set_rsu_control(sec_mgr, IFPGA_RSU_ABORT);
> +		}
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +static void log_time(time_t t, const char *msg) {
> +	uint32_t h = 0;
> +	uint32_t m = 0;
> +	uint32_t s = 0;
> +
> +	if (t < 60) {
> +		s = (uint32_t)t;
> +	} else if (t < 3600) {
> +		s = (uint32_t)(t % 60);
> +		m = (uint32_t)(t / 60);
> +	} else {
> +		s = (uint32_t)(t % 60);
> +		m = (uint32_t)((t % 3600) / 60);
> +		h = (uint32_t)(t / 3600);
> +	}
> +	printf("%s - %02u:%02u:%02u\n", msg, h, m, s); }
> +
> +static int start_flash_update(struct ifpga_sec_mgr *smgr) {
> +	if (!smgr)
> +		return -ENODEV;
> +
> +	if (!smgr->ops || !smgr->ops->prepare)
> +		return -EINVAL;
> +
> +	return smgr->ops->prepare(smgr);
> +}
> +
> +static int write_flash_image(struct ifpga_sec_mgr *smgr, const char *image,
> +	uint32_t offset)
> +{
> +	void *buf = NULL;
> +	int retry = 0;
> +	uint32_t length = 0;
> +	uint32_t to_transfer = 0;
> +	uint32_t one_percent = 0;
> +	uint32_t prog = 0;
> +	uint32_t old_prog = -1;
> +	ssize_t read_size = 0;
> +	int fd = -1;
> +	int ret = 0;
> +
> +	if (!smgr)
> +		return -ENODEV;
> +
> +	if (!smgr->ops || !smgr->ops->write_blk)
> +		return -EINVAL;
> +
> +	fd = open(image, O_RDONLY);
> +	if (fd < 0) {
> +		dev_err(smgr,
> +			"Failed to open \'%s\' for RD [e:%s]\n",
> +			image, strerror(errno));
> +		return -EIO;
> +	}
> +
> +	buf = malloc(IFPGA_RSU_DATA_BLK_SIZE);
> +	if (!buf) {
> +		dev_err(smgr, "Failed to allocate memory for flash update\n");
> +		close(fd);
> +		return -ENOMEM;
> +	}
> +
> +	length = smgr->rsu_length;
> +	one_percent = length / 100;
> +	do {
> +		to_transfer = length > IFPGA_RSU_DATA_BLK_SIZE ?
> +			IFPGA_RSU_DATA_BLK_SIZE : length;

Add parentheses is better, like "(length > IFPGA_RSU_DATA_BLK_SIZE ) ? "

> +		lseek(fd, offset, SEEK_SET);
> +		read_size = read(fd, buf, to_transfer);
> +		if (read_size < 0) {
> +			dev_err(smgr, "Failed to read from \'%s\' [e:%s]\n",
> +				image, strerror(errno));
> +			ret = -EIO;
> +			goto end;
> +		}
> +		if ((uint32_t)read_size != to_transfer) {
> +			dev_err(smgr,
> +				"Read length %zd is not expected [e:%u]\n",
> +				read_size, to_transfer);
> +			ret = -EIO;
> +			goto end;
> +		}
> +
> +		retry = 0;
> +		do {
> +			if (get_rsu_control(smgr) == IFPGA_RSU_ABORT) {
> +				ret = -EAGAIN;
> +				goto end;
> +			}
> +			ret = smgr->ops->write_blk(smgr, buf, offset,
> +				to_transfer);
> +			if (ret == 0)
> +				break;
> +			sleep(1);
> +		} while (++retry <= IFPGA_RSU_WRITE_RETRY);
> +		if (retry > IFPGA_RSU_WRITE_RETRY) {
> +			dev_err(smgr, "Failed to write to staging area 0x%x\n",
> +				offset);
> +			ret = -EAGAIN;
> +			goto end;
> +		}
> +
> +		length -= to_transfer;
> +		offset += to_transfer;
> +		prog = offset / one_percent;
> +		if (prog != old_prog) {
> +			printf("\r%d%%", prog);
> +			fflush(stdout);
> +			set_rsu_status(smgr, IFPGA_RSU_READY, prog);
> +			old_prog = prog;
> +		}
> +	} while (length > 0);
> +	set_rsu_status(smgr, IFPGA_RSU_READY, 100);
> +	printf("\n");
> +
> +end:
> +	free(buf);
> +	close(fd);
> +	return ret;
> +}
> +
> +static int apply_flash_update(struct ifpga_sec_mgr *smgr) {
> +	uint32_t one_percent = 0;
> +	uint32_t one_percent_time = 0;
> +	uint32_t prog = 0;
> +	uint32_t old_prog = -1;
> +	uint32_t copy_time = 0;
> +	int ret = 0;
> +
> +	if (!smgr)
> +		return -ENODEV;
> +
> +	if (!smgr->ops || !smgr->ops->write_done
> || !smgr->ops->check_complete)
> +		return -EINVAL;
> +
> +	if (smgr->ops->write_done(smgr) < 0) {
> +		dev_err(smgr, "Failed to apply flash update\n");
> +		return -EAGAIN;
> +	}
> +
> +	one_percent = (smgr->rsu_length + 99) / 100;
> +	if (smgr->copy_speed == 0)   /* avoid zero divide fault */
> +		smgr->copy_speed = 1;
> +	one_percent_time = (one_percent + smgr->copy_speed - 1) /
> +		smgr->copy_speed;
> +	if (one_percent_time == 0)   /* avoid zero divide fault */
> +		one_percent_time = 1;
> +
> +	do {
> +		ret = smgr->ops->check_complete(smgr);
> +		if (ret != -EAGAIN)
> +			break;
> +		sleep(1);
> +		copy_time += 1;
> +		prog = copy_time / one_percent_time;
> +		if (prog >= 100)
> +			prog = 99;
> +		if (prog != old_prog) {
> +			printf("\r%d%%", prog);
> +			fflush(stdout);
> +			set_rsu_status(smgr, IFPGA_RSU_COPYING, prog);
> +			old_prog = prog;
> +		}
> +	} while (true);
> +
> +	if (ret < 0) {
> +		printf("\n");
> +		dev_err(smgr, "Failed to complete secure flash update\n");
> +	} else {
> +		printf("\r100%%\n");
> +		set_rsu_status(smgr, IFPGA_RSU_COPYING, 100);
> +	}
> +
> +	return ret;
> +}
> +
> +static int secure_update_cancel(struct ifpga_sec_mgr *smgr) {
> +	if (!smgr)
> +		return -ENODEV;
> +
> +	if (!smgr->ops || !smgr->ops->cancel)
> +		return -EINVAL;
> +
> +	return smgr->ops->cancel(smgr);
> +}
> +
> +static int secure_update_status(struct ifpga_sec_mgr *smgr, uint64_t
> +*status) {
> +	if (!smgr)
> +		return -ENODEV;
> +
> +	if (!smgr->ops || !smgr->ops->get_hw_errinfo)
> +		return -EINVAL;
> +
> +	if (status)
> +		*status = smgr->ops->get_hw_errinfo(smgr);
> +
> +	return 0;
> +}
> +
> +int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,
> +	uint64_t *status)
> +{
> +	struct ifpga_hw *hw = NULL;
> +	struct ifpga_sec_mgr *smgr = NULL;
> +	uint32_t rsu_stat = 0;
> +	int fd = -1;
> +	struct sigaction old_sigint_action;
> +	struct sigaction sa;
> +	time_t start;
> +	int ret = 0;
> +
> +	if (!fme || !image || !status) {
> +		dev_err(fme, "Input parameter of %s is invalid\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	hw = (struct ifpga_hw *)fme->parent;
> +	if (!hw) {
> +		dev_err(fme, "Parent of FME not found\n");
> +		return -ENODEV;
> +	}
> +
> +	smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
> +	if (!smgr || !smgr->max10_dev) {
> +		dev_err(smgr, "Security manager not initialized\n");
> +		return -ENODEV;
> +	}
> +
> +	opae_adapter_lock(hw->adapter, -1);
> +	get_rsu_status(smgr, &rsu_stat, NULL);
> +	if (rsu_stat != IFPGA_RSU_IDLE) {
> +		opae_adapter_unlock(hw->adapter);
> +		if (rsu_stat == IFPGA_RSU_REBOOT)
> +			dev_info(smgr, "Reboot is in progress\n");
> +		else
> +			dev_info(smgr, "Update is in progress\n");
> +		return -EAGAIN;
> +	}
> +	set_rsu_control(smgr, 0);
> +	set_rsu_status(smgr, IFPGA_RSU_PREPARE, 0);
> +	opae_adapter_unlock(hw->adapter);
> +
> +	fd = open(image, O_RDONLY);
> +	if (fd < 0) {
> +		dev_err(smgr,
> +			"Failed to open \'%s\' for RD [e:%s]\n",
> +			image, strerror(errno));
> +		return -EIO;
> +	}
> +	smgr->rsu_length = lseek(fd, 0, SEEK_END);
> +	close(fd);
> +
> +	if (smgr->max10_dev->staging_area_size < smgr->rsu_length) {
> +		dev_err(dev, "Size of staging area is small than image length "
> +			"[%u<%u]\n", smgr->max10_dev->staging_area_size,
> +			smgr->rsu_length);
> +		return -EINVAL;
> +	}
> +
> +	printf("Updating from file \'%s\' with size %u\n",
> +		image, smgr->rsu_length);
> +
> +	sec_mgr = smgr;
> +	memset(&sa, 0, sizeof(struct sigaction));
> +	sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
> +	sa.sa_sigaction = sig_handler;
> +	ret = sigaction(SIGINT, &sa, &old_sigint_action);
> +	if (ret < 0) {
> +		dev_warn(dev, "Failed to register signal handler"
> +			" [e:%d]\n", ret);
> +		sec_mgr = NULL;
> +	}
> +
> +	start = time(NULL);
> +	log_time(time(NULL) - start, "Starting secure flash update");
> +	ret = start_flash_update(smgr);
> +	if (ret < 0)
> +		goto end;
> +
> +	set_rsu_status(smgr, IFPGA_RSU_READY, 0);
> +	log_time(time(NULL) - start, "Writing to staging area");
> +	ret = write_flash_image(smgr, image, 0);
> +	if (ret < 0)
> +		goto end;
> +
> +	set_rsu_status(smgr, IFPGA_RSU_COPYING, 0);
> +	log_time(time(NULL) - start, "Applying secure flash update");
> +	ret = apply_flash_update(smgr);
> +
> +end:
> +	if (sec_mgr) {
> +		sec_mgr = NULL;
> +		if (sigaction(SIGINT, &old_sigint_action, NULL) < 0)
> +			dev_err(smgr, "Failed to unregister signal handler\n");
> +	}
> +
> +	secure_update_status(smgr, status);
> +	if (ret < 0) {
> +		log_time(time(NULL) - start, "Secure flash update ERROR");
> +		printf("Error status code is %zx\n", *status);
> +		if (ret == -EAGAIN)
> +			secure_update_cancel(smgr);
> +	} else {
> +		log_time(time(NULL) - start, "Secure flash update OK");
> +	}
> +	set_rsu_status(smgr, IFPGA_RSU_IDLE, 0);
> +
> +	return ret;
> +}
> +
> +int fpga_stop_flash_update(struct ifpga_fme_hw *fme, int force) {
> +	struct ifpga_sec_mgr *smgr = NULL;
> +	uint32_t status = 0;
> +	int retry = IFPGA_RSU_CANCEL_RETRY;
> +	int ret = 0;
> +
> +	if (!fme) {
> +		dev_err(fme, "Input parameter of %s is invalid\n", __func__);
> +		return -EINVAL;
> +	}
> +	smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
> +
> +	get_rsu_status(smgr, &status, NULL);
> +	if (status != IFPGA_RSU_IDLE) {
> +		dev_info(smgr, "Cancel secure flash update\n");
> +		set_rsu_control(smgr, IFPGA_RSU_ABORT);
> +	}
> +
> +	if (force) {
> +		sleep(2);
> +		do {
> +			get_rsu_status(smgr, &status, NULL);
> +			if (status == IFPGA_RSU_IDLE)
> +				break;
> +			if (secure_update_cancel(smgr) == 0)
> +				set_rsu_status(smgr, IFPGA_RSU_IDLE, 0);
> +			sleep(1);
> +		} while (--retry > 0);
> +		if (retry <= 0) {
> +			dev_err(smgr, "Failed to stop flash update\n");
> +			ret = -EAGAIN;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +int fpga_reload(struct ifpga_fme_hw *fme, int type, int page) {
> +	struct ifpga_sec_mgr *smgr = NULL;
> +
> +	if (!fme) {
> +		dev_err(fme, "Input parameter of %s is invalid\n", __func__);
> +		return -EINVAL;
> +	}
> +	smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
> +
> +	if (!smgr || !smgr->ops || !smgr->ops->reload)
> +		return -EINVAL;
> +
> +	return smgr->ops->reload(smgr, type, page); }
> diff --git a/drivers/raw/ifpga/base/ifpga_hw.h
> b/drivers/raw/ifpga/base/ifpga_hw.h
> index 7c3307fe7..ed5edc601 100644
> --- a/drivers/raw/ifpga/base/ifpga_hw.h
> +++ b/drivers/raw/ifpga/base/ifpga_hw.h
> @@ -91,6 +91,7 @@ struct ifpga_fme_hw {
>  	struct opae_board_info board_info;
>  	int nums_eth_dev;
>  	unsigned int nums_acc_region;
> +	void *sec_mgr;
>  };
> 
>  enum ifpga_port_state {
> diff --git a/drivers/raw/ifpga/base/ifpga_sec_mgr.c
> b/drivers/raw/ifpga/base/ifpga_sec_mgr.c
> new file mode 100644
> index 000000000..6f039f5fa
> --- /dev/null
> +++ b/drivers/raw/ifpga/base/ifpga_sec_mgr.c
> @@ -0,0 +1,639 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2020 Intel Corporation
> + */
> +
> +#include <fcntl.h>
> +#include <signal.h>
> +#include <unistd.h>
> +#include "ifpga_sec_mgr.h"
> +
> +
> +static const char * const rsu_prog[] = {"IDLE", "PREPARING", "SLEEPING",
> +	"READY", "AUTHENTICATING", "COPYING", "CANCELLATION",
> "PROGRAMMING_KEY",
> +	"DONE", "PKVL_DONE"};
> +static const char * const rsu_statl[] = {"NORMAL", "TIMEOUT",
> "AUTH_FAIL",
> +	"COPY_FAIL", "FATAL", "PKVL_REJECT", "NON_INCR", "ERASE_FAIL",
> +	"WEAROUT"};
> +static const char * const rsu_stath[] = {"NIOS_OK", "USER_OK",
> "FACTORY_OK",
> +	"USER_FAIL", "FACTORY_FAIL", "NIOS_FLASH_ERR",
> "FPGA_FLASH_ERR"};
> +
> +static const char *rsu_progress_name(uint32_t prog) {
> +	if (prog > SEC_PROGRESS_PKVL_PROM_DONE)
> +		return "UNKNOWN";
> +	else
> +		return rsu_prog[prog];
> +}
> +
> +static const char *rsu_status_name(uint32_t stat) {
> +	if (stat >= SEC_STATUS_NIOS_OK) {
> +		if (stat > SEC_STATUS_FPGA_FLASH_ERR)
> +			return "UNKNOWN";
> +		else
> +			return rsu_stath[stat-SEC_STATUS_NIOS_OK];
> +	} else {
> +		if (stat > SEC_STATUS_WEAROUT)
> +			return "UNKNOWN";
> +		else
> +			return rsu_statl[stat];
> +	}
> +}
> +
> +static bool secure_start_done(uint32_t doorbell) {
> +	return (SEC_STATUS_G(doorbell) == SEC_STATUS_ERASE_FAIL ||
> +		SEC_STATUS_G(doorbell) == SEC_STATUS_WEAROUT ||
> +		(SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_IDLE &&
> +		SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_RSU_DONE)); }
> +
> +static bool secure_prog_ready(uint32_t doorbell) {
> +	return (SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_READY); }
> +
> +static int poll_timeout(struct intel_max10_device *dev, uint32_t offset,
> +	bool (*cond)(uint32_t), uint32_t interval_ms, uint32_t timeout_ms) {
> +	uint32_t val = 0;
> +	int ret = 0;
> +
> +	for (;;) {
> +		ret = max10_sys_read(dev, offset, &val);
> +		if (ret < 0) {
> +			dev_err(dev,
> +				"Failed to read max10 register 0x%x [e:%d]\n",
> +				offset, ret);
> +			break;
> +		}
> +
> +		if (cond(val)) {
> +			dev_debug(dev,
> +				"Read 0x%08x from max10 register 0x%x "
> +				"[poll success]\n", val, offset);
> +			ret = 0;
> +			break;
> +		}
> +		if (timeout_ms > interval_ms)
> +			timeout_ms -= interval_ms;
> +		else
> +			timeout_ms = 0;
> +		if (timeout_ms == 0) {
> +			dev_debug(dev,
> +				"Read 0x%08x from max10 register 0x%x "
> +				"[poll timeout]\n", val, offset);
> +			ret = -ETIMEDOUT;
> +			break;
> +		}
> +		msleep(interval_ms);
> +	}
> +
> +	return ret;
> +}
> +
> +static int n3000_secure_update_start(struct intel_max10_device *dev) {
> +	uint32_t doorbell = 0;
> +	uint32_t prog = 0;
> +	uint32_t status = 0;
> +	int ret = 0;
> +
> +	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to read max10 doorbell register [e:%d]\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	prog = SEC_PROGRESS_G(doorbell);
> +	if ((prog != SEC_PROGRESS_IDLE) && (prog !=
> SEC_PROGRESS_RSU_DONE)) {
> +		dev_debug(dev, "Current RSU progress is %s\n",
> +			rsu_progress_name(prog));
> +		return -EBUSY;
> +	}
> +
> +	ret = max10_sys_update_bits(dev, MAX10_DOORBELL,
> +		RSU_REQUEST | HOST_STATUS, RSU_REQUEST);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to updt max10 doorbell register [e:%d]\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	ret = poll_timeout(dev, MAX10_DOORBELL, secure_start_done,
> +		IFPGA_SEC_START_INTERVAL_MS,
> IFPGA_SEC_START_TIMEOUT_MS);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to poll max10 doorbell register [e:%d]\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to read max10 doorbell register [e:%d]\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	status = SEC_STATUS_G(doorbell);
> +	if (status == SEC_STATUS_WEAROUT)
> +		return -EAGAIN;
> +
> +	if (status == SEC_STATUS_ERASE_FAIL)
> +		return -EIO;
> +
> +	return 0;
> +}
> +
> +static int n3000_cancel(struct ifpga_sec_mgr *smgr) {
> +	struct intel_max10_device *dev = NULL;
> +	uint32_t doorbell = 0;
> +	uint32_t prog = 0;
> +	int ret = 0;
> +
> +	if (!smgr || !smgr->max10_dev)
> +		return -ENODEV;
> +	dev = (struct intel_max10_device *)smgr->max10_dev;
> +
> +	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to read max10 doorbell register [e:%d]\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	prog = SEC_PROGRESS_G(doorbell);
> +	if (prog == SEC_PROGRESS_IDLE)
> +		return 0;
> +	if (prog != SEC_PROGRESS_READY)
> +		return -EBUSY;
> +
> +	return max10_sys_update_bits(dev, MAX10_DOORBELL, HOST_STATUS,
> +		HOST_STATUS_S(HOST_STATUS_ABORT_RSU));
> +}
> +
> +static int n3000_prepare(struct ifpga_sec_mgr *smgr) {
> +	struct intel_max10_device *dev = NULL;
> +	int retry = 0;
> +	int ret = 0;
> +
> +	if (!smgr || !smgr->max10_dev)
> +		return -ENODEV;
> +	dev = (struct intel_max10_device *)smgr->max10_dev;
> +
> +	ret = n3000_secure_update_start(dev);
> +	if (ret == -EBUSY)
> +		n3000_cancel(smgr);
> +
> +	while (ret) {
> +		if (++retry > IFPGA_RSU_START_RETRY)
> +			break;
> +		msleep(1000);
> +		ret = n3000_secure_update_start(dev);
> +	}
> +	if (retry > IFPGA_RSU_START_RETRY) {
> +		dev_err(dev, "Failed to start secure flash update\n");
> +		ret = -EAGAIN;
> +	}
> +
> +	return ret;
> +}
> +
> +static int n3000_bulk_write(struct intel_max10_device *dev, uint32_t addr,
> +	char *buf, uint32_t len)
> +{
> +	uint32_t i = 0;
> +	uint32_t n = 0;
> +	uint32_t v = 0;
> +	uint32_t p = 0;
> +	int ret = 0;
> +
> +	if (len & 0x3) {
> +		dev_err(dev,
> +			"Length of data block is not 4 bytes aligned [e:%u]\n",
> +			len);
> +		return -EINVAL;
> +	}
> +
> +	n = len >> 2;
> +	for (i = 0; i < n; i++) {
> +		p = i << 2;
> +		v = *(uint32_t *)(buf + p);
> +		ret = max10_reg_write(dev, addr + p, v);
> +		if (ret < 0) {
> +			dev_err(dev,
> +				"Failed to write to staging area 0x%08x [e:%d]\n",
> +				addr + p, ret);
> +			return ret;
> +		}
> +		usleep(1);
> +	}
> +
> +	return 0;
> +}
> +
> +static int n3000_write_blk(struct ifpga_sec_mgr *smgr, char *buf,
> +	uint32_t offset, uint32_t len)
> +{
> +	struct intel_max10_device *dev = NULL;
> +	uint32_t doorbell = 0;
> +	uint32_t prog = 0;
> +	uint32_t m = 0;
> +	int ret = 0;
> +
> +	if (!smgr || !smgr->max10_dev)
> +		return -ENODEV;
> +	dev = (struct intel_max10_device *)smgr->max10_dev;
> +
> +	if (offset + len > dev->staging_area_size) {
> +		dev_err(dev,
> +			"Write position would be out of staging area [e:%u]\n",
> +			dev->staging_area_size);
> +		return -ENOMEM;
> +	}
> +
> +	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to read max10 doorbell register [e:%d]\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	prog = SEC_PROGRESS_G(doorbell);
> +	if (prog == SEC_PROGRESS_PREPARE)
> +		return -EAGAIN;
> +	else if (prog != SEC_PROGRESS_READY)
> +		return -EBUSY;
> +
> +	m = len & 0x3;
> +	if (m != 0)
> +		len += 4 - m;   /* make length to 4 bytes align */
> +
> +	return n3000_bulk_write(dev, dev->staging_area_base + offset, buf,
> +len); }
> +
> +static int n3000_write_done(struct ifpga_sec_mgr *smgr) {
> +	struct intel_max10_device *dev = NULL;
> +	uint32_t doorbell = 0;
> +	uint32_t prog = 0;
> +	uint32_t status = 0;
> +	int ret = 0;
> +
> +	if (!smgr || !smgr->max10_dev)
> +		return -ENODEV;
> +	dev = (struct intel_max10_device *)smgr->max10_dev;
> +
> +	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to read max10 doorbell register [e:%d]\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	prog = SEC_PROGRESS_G(doorbell);
> +	if (prog != SEC_PROGRESS_READY)
> +		return -EBUSY;
> +
> +	ret = max10_sys_update_bits(dev, MAX10_DOORBELL, HOST_STATUS,
> +		HOST_STATUS_S(HOST_STATUS_WRITE_DONE));
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to update max10 doorbell register [e:%d]\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	ret = poll_timeout(dev, MAX10_DOORBELL, secure_prog_ready,
> +		IFPGA_NIOS_HANDSHAKE_INTERVAL_MS,
> +		IFPGA_NIOS_HANDSHAKE_TIMEOUT_MS);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to poll max10 doorbell register [e:%d]\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to read max10 doorbell register [e:%d]\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	status = SEC_STATUS_G(doorbell);
> +	switch (status) {
> +	case SEC_STATUS_NORMAL:
> +	case SEC_STATUS_NIOS_OK:
> +	case SEC_STATUS_USER_OK:
> +	case SEC_STATUS_FACTORY_OK:
> +		ret = 0;
> +		break;
> +	default:
> +		ret = -EIO;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static int n3000_check_complete(struct ifpga_sec_mgr *smgr) {
> +	struct intel_max10_device *dev = NULL;
> +	uint32_t doorbell = 0;
> +	uint32_t status = 0;
> +	uint32_t prog = 0;
> +	int ret = 0;
> +
> +	if (!smgr || !smgr->max10_dev)
> +		return -ENODEV;
> +	dev = (struct intel_max10_device *)smgr->max10_dev;
> +
> +	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to read max10 doorbell register [e:%d]\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	status = SEC_STATUS_G(doorbell);
> +	switch (status) {
> +	case SEC_STATUS_NORMAL:
> +	case SEC_STATUS_NIOS_OK:
> +	case SEC_STATUS_USER_OK:
> +	case SEC_STATUS_FACTORY_OK:
> +	case SEC_STATUS_WEAROUT:
> +		break;
> +	default:
> +		return -EIO;
> +	}
> +
> +	prog = SEC_PROGRESS_G(doorbell);
> +	switch (prog) {
> +	case SEC_PROGRESS_IDLE:
> +	case SEC_PROGRESS_RSU_DONE:
> +		return 0;
> +	case SEC_PROGRESS_AUTHENTICATING:
> +	case SEC_PROGRESS_COPYING:
> +	case SEC_PROGRESS_UPDATE_CANCEL:
> +	case SEC_PROGRESS_PROGRAM_KEY_HASH:
> +		return -EAGAIN;
> +	case SEC_PROGRESS_PREPARE:
> +	case SEC_PROGRESS_READY:
> +		return -EBUSY;
> +	default:
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static int n3000_reload_fpga(struct intel_max10_device *dev, int page)
> +{
> +	int ret = 0;
> +
> +	dev_info(dev, "Reload FPGA\n");
> +
> +	if (!dev || ((page != 0) && (page != 1))) {
> +		dev_err(dev, "Input parameter of %s is invalid\n", __func__);
> +		ret = -EINVAL;
> +		goto end;
> +	}
> +
> +	if (dev->flags & MAX10_FLAGS_SECURE) {
> +		ret = max10_sys_update_bits(dev, FPGA_RECONF_REG,
> +			SFPGA_RP_LOAD, 0);
> +		if (ret < 0) {
> +			dev_err(dev,
> +				"Failed to update max10 reconfig register [e:%d]\n",
> +				ret);
> +			goto end;
> +		}
> +		ret = max10_sys_update_bits(dev, FPGA_RECONF_REG,
> +			SFPGA_RP_LOAD | SFPGA_RECONF_PAGE,
> +			SFPGA_RP_LOAD | SFPGA_PAGE(page));
> +		if (ret < 0) {
> +			dev_err(dev,
> +				"Failed to update max10 reconfig register [e:%d]\n",
> +				ret);
> +			goto end;
> +		}
> +	} else {
> +		ret = max10_sys_update_bits(dev, RSU_REG, FPGA_RP_LOAD, 0);
> +		if (ret < 0) {
> +			dev_err(dev,
> +				"Failed to update max10 rsu register [e:%d]\n",
> +				ret);
> +			goto end;
> +		}
> +		ret = max10_sys_update_bits(dev, RSU_REG,
> +			FPGA_RP_LOAD | FPGA_RECONF_PAGE,
> +			FPGA_RP_LOAD | FPGA_PAGE(page));
> +		if (ret < 0) {
> +			dev_err(dev,
> +				"Failed to update max10 rsu register [e:%d]\n",
> +				ret);
> +			goto end;
> +		}
> +	}
> +
> +	ret = max10_sys_update_bits(dev, FPGA_RECONF_REG,
> COUNTDOWN_START, 0);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to update max10 reconfig register [e:%d]\n",
> +			ret);
> +		goto end;
> +	}
> +
> +	ret = max10_sys_update_bits(dev, FPGA_RECONF_REG,
> COUNTDOWN_START,
> +		COUNTDOWN_START);
> +	if (ret < 0) {
> +		dev_err(dev,
> +			"Failed to update max10 reconfig register [e:%d]\n",
> +			ret);
> +	}
> +end:
> +	if (ret < 0)
> +		dev_err(dev, "Failed to reload FPGA\n");
> +
> +	return ret;
> +}
> +
> +static int n3000_reload_bmc(struct intel_max10_device *dev, int page) {
> +	uint32_t val = 0;
> +	int ret = 0;
> +
> +	dev_info(dev, "Reload BMC\n");
> +
> +	if (!dev || ((page != 0) && (page != 1))) {
> +		dev_err(dev, "Input parameter of %s is invalid\n", __func__);
> +		ret = -EINVAL;
> +		goto end;
> +	}
> +
> +	if (dev->flags & MAX10_FLAGS_SECURE) {
> +		ret = max10_sys_update_bits(dev, MAX10_DOORBELL,
> +			CONFIG_SEL | REBOOT_REQ,
> +			CONFIG_SEL_S(page) | REBOOT_REQ);
> +	} else {
> +		val = page == 0 ? 0x1 : 0x3;

Add parentheses is better, like "val = (page == 0) ? 0x1 : 0x3 "




  reply	other threads:[~2020-12-30  3:04 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-30  1:54 [dpdk-stable] [PATCH v1 0/4] raw/ifpga: add extra OPAE APIs Wei Huang
2020-12-30  1:54 ` [dpdk-stable] [PATCH v1 1/4] raw/ifpga: add fpga rsu function Wei Huang
2020-12-30  3:04   ` Zhang, Tianfei [this message]
2020-12-30  1:54 ` [dpdk-stable] [PATCH v1 2/4] raw/ifpga: add fpga property get function Wei Huang
2020-12-30  1:54 ` [dpdk-stable] [PATCH v1 3/4] raw/ifpga: add opae API for Cyborg Wei Huang
2020-12-30  1:54 ` [dpdk-stable] [PATCH v1 4/4] examples/ifpga: add example for opae ifpga API Wei Huang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DM6PR11MB3131DFC5D2182FD0C175F0C7E3D70@DM6PR11MB3131.namprd11.prod.outlook.com \
    --to=tianfei.zhang@intel.com \
    --cc=dev@dpdk.org \
    --cc=qi.z.zhang@intel.com \
    --cc=rosen.xu@intel.com \
    --cc=stable@dpdk.org \
    --cc=wei.huang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).