From: Wei Huang <wei.huang@intel.com>
To: dev@dpdk.org, thomas@monjalon.net, nipun.gupta@nxp.com,
hemant.agrawal@nxp.com
Cc: stable@dpdk.org, rosen.xu@intel.com, tianfei.zhang@intel.com,
qi.z.zhang@intel.com, Wei Huang <wei.huang@intel.com>
Subject: [PATCH v1 2/2] raw/ifpga: update secure rsu
Date: Tue, 24 May 2022 21:51:23 -0400 [thread overview]
Message-ID: <1653443483-30971-3-git-send-email-wei.huang@intel.com> (raw)
In-Reply-To: <1653443483-30971-1-git-send-email-wei.huang@intel.com>
Update secure RSU (Remote System Update) driver to adapt the changes
introduced by OFS.
Signed-off-by: Wei Huang <wei.huang@intel.com>
Acked-by: Tianfei Zhang <tianfei.zhang@intel.com>
---
drivers/raw/ifpga/base/ifpga_api.c | 39 +-
drivers/raw/ifpga/base/ifpga_feature_dev.h | 2 +
drivers/raw/ifpga/base/ifpga_fme.c | 8 +
drivers/raw/ifpga/base/ifpga_fme_rsu.c | 546 ++++++++-----
drivers/raw/ifpga/base/ifpga_sec_mgr.c | 1156 ++++++++++++++++++++--------
drivers/raw/ifpga/base/ifpga_sec_mgr.h | 115 ++-
drivers/raw/ifpga/base/opae_hw_api.c | 84 +-
drivers/raw/ifpga/base/opae_hw_api.h | 14 +-
drivers/raw/ifpga/rte_pmd_ifpga.c | 104 ++-
drivers/raw/ifpga/rte_pmd_ifpga.h | 117 +++
drivers/raw/ifpga/version.map | 11 +
11 files changed, 1649 insertions(+), 547 deletions(-)
diff --git a/drivers/raw/ifpga/base/ifpga_api.c b/drivers/raw/ifpga/base/ifpga_api.c
index f19cc26..c187f94 100644
--- a/drivers/raw/ifpga/base/ifpga_api.c
+++ b/drivers/raw/ifpga/base/ifpga_api.c
@@ -261,11 +261,42 @@ static int ifpga_mgr_stop_flash_update(struct opae_manager *mgr, int force)
return fpga_stop_flash_update(fme, force);
}
-static int ifpga_mgr_reload(struct opae_manager *mgr, int type, int page)
+static int ifpga_mgr_reload(struct opae_manager *mgr, char *str)
{
struct ifpga_fme_hw *fme = mgr->data;
- return fpga_reload(fme, type, page);
+ return fpga_reload(fme, str);
+}
+
+static int ifpga_available_images(struct opae_manager *mgr, char *buf,
+ size_t size)
+{
+ struct ifpga_fme_hw *fme = mgr->data;
+
+ return fpga_available_images(fme, buf, size);
+}
+
+static int ifpga_mgr_set_poc_image(struct opae_manager *mgr, char *str)
+{
+ struct ifpga_fme_hw *fme = mgr->data;
+
+ return fpga_set_poc_image(fme, str);
+}
+
+static int ifpga_mgr_get_poc_images(struct opae_manager *mgr, char *buf,
+ size_t size)
+{
+ struct ifpga_fme_hw *fme = mgr->data;
+
+ return fpga_get_poc_images(fme, buf, size);
+}
+
+static int ifpga_mgr_read_flash(struct opae_manager *mgr, u32 address,
+ u32 size, void *buf)
+{
+ struct ifpga_fme_hw *fme = mgr->data;
+
+ return fme_mgr_read_flash(fme, address, size, buf);
}
struct opae_manager_ops ifpga_mgr_ops = {
@@ -277,6 +308,10 @@ struct opae_manager_ops ifpga_mgr_ops = {
.update_flash = ifpga_mgr_update_flash,
.stop_flash_update = ifpga_mgr_stop_flash_update,
.reload = ifpga_mgr_reload,
+ .available_images = ifpga_available_images,
+ .get_poc_images = ifpga_mgr_get_poc_images,
+ .set_poc_image = ifpga_mgr_set_poc_image,
+ .read_flash = ifpga_mgr_read_flash
};
static int ifpga_mgr_read_mac_rom(struct opae_manager *mgr, int offset,
diff --git a/drivers/raw/ifpga/base/ifpga_feature_dev.h b/drivers/raw/ifpga/base/ifpga_feature_dev.h
index a637eb5..7a2f2e5 100644
--- a/drivers/raw/ifpga/base/ifpga_feature_dev.h
+++ b/drivers/raw/ifpga/base/ifpga_feature_dev.h
@@ -223,4 +223,6 @@ int fme_mgr_get_retimer_status(struct ifpga_fme_hw *fme,
int fme_mgr_get_sensor_value(struct ifpga_fme_hw *fme,
struct opae_sensor_info *sensor,
unsigned int *value);
+int fme_mgr_read_flash(struct ifpga_fme_hw *fme, u32 address,
+ u32 size, void *buf);
#endif /* _IFPGA_FEATURE_DEV_H_ */
diff --git a/drivers/raw/ifpga/base/ifpga_fme.c b/drivers/raw/ifpga/base/ifpga_fme.c
index 1b9a922..1f54680 100644
--- a/drivers/raw/ifpga/base/ifpga_fme.c
+++ b/drivers/raw/ifpga/base/ifpga_fme.c
@@ -1658,3 +1658,11 @@ struct ifpga_feature_ops fme_pmci_ops = {
.init = fme_pmci_init,
.uinit = fme_pmci_uinit,
};
+
+int fme_mgr_read_flash(struct ifpga_fme_hw *fme, u32 address,
+ u32 size, void *buf)
+{
+ struct intel_max10_device *max10 = fme->max10_dev;
+
+ return opae_read_flash(max10, address, size, buf);
+}
diff --git a/drivers/raw/ifpga/base/ifpga_fme_rsu.c b/drivers/raw/ifpga/base/ifpga_fme_rsu.c
index f147aaa..88a19fa 100644
--- a/drivers/raw/ifpga/base/ifpga_fme_rsu.c
+++ b/drivers/raw/ifpga/base/ifpga_fme_rsu.c
@@ -9,6 +9,28 @@
static struct ifpga_sec_mgr *sec_mgr;
+static void lock(struct ifpga_sec_mgr *smgr)
+{
+ struct ifpga_hw *hw = NULL;
+
+ if (smgr && smgr->fme) {
+ hw = (struct ifpga_hw *)smgr->fme->parent;
+ if (hw)
+ opae_adapter_lock(hw->adapter, -1);
+ }
+}
+
+static void unlock(struct ifpga_sec_mgr *smgr)
+{
+ struct ifpga_hw *hw = NULL;
+
+ if (smgr && smgr->fme) {
+ hw = (struct ifpga_hw *)smgr->fme->parent;
+ if (hw)
+ opae_adapter_unlock(hw->adapter);
+ }
+}
+
static void set_rsu_control(struct ifpga_sec_mgr *smgr, uint32_t ctrl)
{
if (smgr && smgr->rsu_control)
@@ -22,6 +44,16 @@ static uint32_t get_rsu_control(struct ifpga_sec_mgr *smgr)
return 0;
}
+static void cancel_rsu(struct ifpga_sec_mgr *smgr)
+{
+ uint32_t ctrl = IFPGA_RSU_CANCEL;
+
+ lock(smgr);
+ ctrl |= get_rsu_control(smgr);
+ set_rsu_control(smgr, ctrl);
+ unlock(smgr);
+}
+
static void set_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t status,
uint32_t progress)
{
@@ -40,6 +72,26 @@ static void get_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t *status,
}
}
+static void update_rsu_stat(struct ifpga_sec_mgr *smgr, uint32_t stat)
+{
+ uint32_t prog = 0;
+
+ lock(smgr);
+ get_rsu_status(smgr, NULL, &prog);
+ set_rsu_status(smgr, stat, prog);
+ unlock(smgr);
+}
+
+static void update_rsu_prog(struct ifpga_sec_mgr *smgr, uint32_t prog)
+{
+ uint32_t stat = 0;
+
+ lock(smgr);
+ get_rsu_status(smgr, &stat, NULL);
+ set_rsu_status(smgr, stat, prog);
+ unlock(smgr);
+}
+
static void sig_handler(int sig, siginfo_t *info, void *data)
{
(void)(info);
@@ -50,7 +102,7 @@ static void sig_handler(int sig, siginfo_t *info, void *data)
if (sec_mgr) {
dev_info(sec_mgr, "Interrupt secure flash update"
" by keyboard\n");
- set_rsu_control(sec_mgr, IFPGA_RSU_ABORT);
+ cancel_rsu(sec_mgr);
}
break;
default:
@@ -77,149 +129,152 @@ static void log_time(time_t t, const char *msg)
printf("%s - %02u:%02u:%02u\n", msg, h, m, s);
}
-static int start_flash_update(struct ifpga_sec_mgr *smgr)
+static enum ifpga_sec_err fpga_sec_dev_prepare(struct ifpga_sec_mgr *smgr)
{
if (!smgr)
- return -ENODEV;
+ return IFPGA_SEC_ERR_HW_ERROR;
- if (!smgr->ops || !smgr->ops->prepare)
- return -EINVAL;
+ if (!smgr->sops || !smgr->sops->prepare)
+ return IFPGA_SEC_ERR_NO_FUNC;
+
+ return smgr->sops->prepare(smgr);
+}
+
+static int fill_buf(int fd, uint32_t offset, void *buf, uint32_t size)
+{
+ ssize_t read_size = 0;
+
+ if (lseek(fd, offset, SEEK_SET) < 0)
+ return -EIO;
+
+ read_size = read(fd, buf, size);
+ if (read_size < 0)
+ return -EIO;
- return smgr->ops->prepare(smgr);
+ if ((uint32_t)read_size != size) {
+ dev_err(smgr,
+ "Read length %zd is not expected [e:%u]\n",
+ read_size, size);
+ return -EIO;
+ }
+
+ return 0;
}
-static int write_flash_image(struct ifpga_sec_mgr *smgr, const char *image,
- uint32_t offset)
+static enum ifpga_sec_err fpga_sec_dev_write(struct ifpga_sec_mgr *smgr)
{
void *buf = NULL;
- int retry = 0;
- uint32_t length = 0;
- uint32_t to_transfer = 0;
- uint32_t one_percent = 0;
+ int fd = -1;
+ uint32_t blk_size = 0;
+ uint32_t offset = 0;
uint32_t prog = 0;
uint32_t old_prog = -1;
- ssize_t read_size = 0;
- int fd = -1;
- int ret = 0;
+ enum ifpga_sec_err ret = 0;
if (!smgr)
- return -ENODEV;
+ return IFPGA_SEC_ERR_HW_ERROR;
- if (!smgr->ops || !smgr->ops->write_blk)
- return -EINVAL;
+ if (!smgr->sops || !smgr->sops->write_blk)
+ return IFPGA_SEC_ERR_NO_FUNC;
+
+ buf = malloc(IFPGA_RSU_DATA_BLK_SIZE);
+ if (!buf) {
+ dev_err(smgr, "Failed to allocate memory for flash update\n");
+ return IFPGA_SEC_ERR_NO_MEM;
+ }
+ smgr->data = buf;
- fd = open(image, O_RDONLY);
+ fd = open(smgr->filename, O_RDONLY);
if (fd < 0) {
dev_err(smgr,
"Failed to open \'%s\' for RD [e:%s]\n",
- image, strerror(errno));
- return -EIO;
+ smgr->filename, strerror(errno));
+ return IFPGA_SEC_ERR_FILE_READ;
}
- 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;
- if (lseek(fd, offset, SEEK_SET) < 0) {
- dev_err(smgr, "Failed to seek in \'%s\' [e:%s]\n",
- image, strerror(errno));
- ret = -EIO;
- goto end;
- }
- 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;
+ while (smgr->remaining_size) {
+ if (get_rsu_control(smgr) & IFPGA_RSU_CANCEL) {
+ ret = IFPGA_SEC_ERR_CANCELED;
+ break;
}
- 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;
+ blk_size = (smgr->remaining_size > IFPGA_RSU_DATA_BLK_SIZE) ?
+ IFPGA_RSU_DATA_BLK_SIZE : smgr->remaining_size;
+ if (fill_buf(fd, offset, buf, blk_size)) {
+ ret = IFPGA_SEC_ERR_FILE_READ;
+ break;
}
- length -= to_transfer;
- offset += to_transfer;
- prog = offset / one_percent;
+ ret = smgr->sops->write_blk(smgr, offset, blk_size);
+ if (ret != IFPGA_SEC_ERR_NONE)
+ break;
+
+ smgr->remaining_size -= blk_size;
+ offset += blk_size;
+
+ /* output progress percent */
+ prog = offset / smgr->one_percent;
if (prog != old_prog) {
printf("\r%d%%", prog);
fflush(stdout);
- set_rsu_status(smgr, IFPGA_RSU_READY, prog);
+ update_rsu_prog(smgr, prog);
old_prog = prog;
}
- } while (length > 0);
- set_rsu_status(smgr, IFPGA_RSU_READY, 100);
- printf("\n");
+ }
+
+ if (ret == IFPGA_SEC_ERR_NONE) {
+ update_rsu_prog(smgr, 100);
+ printf("\r100%%\n");
+ } else {
+ printf("\n");
+ }
-end:
- free(buf);
close(fd);
+ smgr->data = NULL;
+ free(buf);
return ret;
}
-static int apply_flash_update(struct ifpga_sec_mgr *smgr)
+static enum ifpga_sec_err fpga_sec_dev_poll_complete(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;
+ int timeout = 2400; /* 2400 seconds */
+ enum ifpga_sec_err ret = 0;
if (!smgr)
- return -ENODEV;
+ return IFPGA_SEC_ERR_HW_ERROR;
- if (!smgr->ops || !smgr->ops->write_done || !smgr->ops->check_complete)
- return -EINVAL;
+ if (!smgr->sops || !smgr->sops->write_done ||
+ !smgr->sops->check_complete)
+ return IFPGA_SEC_ERR_NO_FUNC;
- if (smgr->ops->write_done(smgr) < 0) {
+ if (smgr->sops->write_done(smgr) != IFPGA_SEC_ERR_NONE) {
dev_err(smgr, "Failed to apply flash update\n");
- return -EAGAIN;
+ return IFPGA_SEC_ERR_HW_ERROR;
}
- one_percent = (smgr->rsu_length + 99) / 100;
+ /* calculate time period of one percent */
if (smgr->copy_speed == 0) /* avoid zero divide fault */
smgr->copy_speed = 1;
- one_percent_time = (one_percent + smgr->copy_speed - 1) /
+ one_percent_time = (smgr->one_percent + smgr->copy_speed) /
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;
+ while (true) {
sleep(1);
+ ret = smgr->sops->check_complete(smgr);
+ if (ret != IFPGA_SEC_ERR_BUSY)
+ break;
+ if (--timeout < 0) {
+ ret = IFPGA_SEC_ERR_TIMEOUT;
+ break;
+ }
+
+ /* output progress percent */
copy_time += 1;
prog = copy_time / one_percent_time;
if (prog >= 100)
@@ -227,96 +282,90 @@ static int apply_flash_update(struct ifpga_sec_mgr *smgr)
if (prog != old_prog) {
printf("\r%d%%", prog);
fflush(stdout);
- set_rsu_status(smgr, IFPGA_RSU_COPYING, prog);
+ update_rsu_prog(smgr, prog);
old_prog = prog;
}
- } while (true);
+ }
- if (ret < 0) {
- printf("\n");
- dev_err(smgr, "Failed to complete secure flash update\n");
- } else {
+ if (ret == IFPGA_SEC_ERR_NONE) {
+ update_rsu_prog(smgr, 100);
printf("\r100%%\n");
- set_rsu_status(smgr, IFPGA_RSU_COPYING, 100);
+ } else {
+ printf("\n");
}
return ret;
}
-static int secure_update_cancel(struct ifpga_sec_mgr *smgr)
+static enum ifpga_sec_err fpga_sec_dev_cancel(struct ifpga_sec_mgr *smgr)
{
if (!smgr)
- return -ENODEV;
+ return IFPGA_SEC_ERR_HW_ERROR;
- if (!smgr->ops || !smgr->ops->cancel)
- return -EINVAL;
+ if (!smgr->sops || !smgr->sops->cancel)
+ return IFPGA_SEC_ERR_NO_FUNC;
- return smgr->ops->cancel(smgr);
+ return smgr->sops->cancel(smgr);
}
-static int secure_update_status(struct ifpga_sec_mgr *smgr, uint64_t *status)
+static void set_error(struct ifpga_sec_mgr *smgr, enum ifpga_sec_err err_code)
{
- if (!smgr)
- return -ENODEV;
+ uint32_t stat = 0;
- if (!smgr->ops || !smgr->ops->get_hw_errinfo)
- return -EINVAL;
+ lock(smgr);
+ get_rsu_status(smgr, &stat, NULL);
+ set_rsu_status(smgr, stat, stat);
+ smgr->err_code = err_code;
+ unlock(smgr);
+}
- if (status)
- *status = smgr->ops->get_hw_errinfo(smgr);
+static int progress_transition(struct ifpga_sec_mgr *smgr,
+ uint32_t new_progress)
+{
+ if (get_rsu_control(smgr) & IFPGA_RSU_CANCEL) {
+ set_error(smgr, IFPGA_SEC_ERR_CANCELED);
+ smgr->sops->cancel(smgr);
+ return -ECANCELED;
+ }
+ set_rsu_status(smgr, new_progress, 0);
return 0;
}
-int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,
- uint64_t *status)
+static void progress_complete(struct ifpga_sec_mgr *smgr)
+{
+ update_rsu_stat(smgr, IFPGA_RSU_IDLE);
+}
+
+static void fpga_sec_dev_error(struct ifpga_sec_mgr *smgr,
+ enum ifpga_sec_err err_code)
+{
+ set_error(smgr, err_code);
+ if (smgr->sops->get_hw_errinfo)
+ smgr->hw_errinfo = smgr->sops->get_hw_errinfo(smgr);
+ if (smgr->sops->cancel)
+ smgr->sops->cancel(smgr);
+}
+
+static int fpga_sec_mgr_update(struct ifpga_sec_mgr *smgr)
{
- struct ifpga_hw *hw = NULL;
- struct ifpga_sec_mgr *smgr = NULL;
- uint32_t rsu_stat = 0;
int fd = -1;
off_t len = 0;
struct sigaction old_sigint_action;
struct sigaction sa;
time_t start;
- int ret = 0;
+ enum ifpga_sec_err ret = 0;
- if (!fme || !image || !status) {
- dev_err(fme, "Input parameter of %s is invalid\n", __func__);
+ if (!smgr) {
+ dev_err(smgr, "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);
+ fd = open(smgr->filename, O_RDONLY);
if (fd < 0) {
dev_err(smgr,
"Failed to open \'%s\' for RD [e:%s]\n",
- image, strerror(errno));
+ smgr->filename, strerror(errno));
return -EIO;
}
len = lseek(fd, 0, SEEK_END);
@@ -325,25 +374,22 @@ int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,
if (len < 0) {
dev_err(smgr,
"Failed to get file length of \'%s\' [e:%s]\n",
- image, strerror(errno));
+ smgr->filename, strerror(errno));
return -EIO;
}
if (len == 0) {
- dev_err(smgr, "Length of file \'%s\' is invalid\n", image);
- return -EINVAL;
- }
- smgr->rsu_length = len;
-
- 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);
+ dev_err(smgr, "Length of file \'%s\' is invalid\n",
+ smgr->filename);
+ set_error(smgr, IFPGA_SEC_ERR_INVALID_SIZE);
return -EINVAL;
}
+ smgr->remaining_size = len;
+ smgr->one_percent = smgr->remaining_size / 100;
printf("Updating from file \'%s\' with size %u\n",
- image, smgr->rsu_length);
+ smgr->filename, smgr->remaining_size);
+ /* setup signal handler */
sec_mgr = smgr;
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
@@ -354,39 +400,106 @@ int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,
" [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;
+ if (progress_transition(smgr, IFPGA_RSU_PREPARING)) {
+ ret = smgr->err_code;
+ goto exit;
+ }
+
+ ret = fpga_sec_dev_prepare(smgr);
+ if (ret != IFPGA_SEC_ERR_NONE) {
+ fpga_sec_dev_error(smgr, ret);
+ goto exit;
+ }
- 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;
+ if (progress_transition(smgr, IFPGA_RSU_WRITING)) {
+ ret = smgr->err_code;
+ goto done;
+ }
+
+ ret = fpga_sec_dev_write(smgr);
+ if (ret != IFPGA_SEC_ERR_NONE) {
+ fpga_sec_dev_error(smgr, ret);
+ goto done;
+ }
- set_rsu_status(smgr, IFPGA_RSU_COPYING, 0);
log_time(time(NULL) - start, "Applying secure flash update");
- ret = apply_flash_update(smgr);
+ if (progress_transition(smgr, IFPGA_RSU_PROGRAMMING)) {
+ ret = smgr->err_code;
+ goto done;
+ }
+
+ ret = fpga_sec_dev_poll_complete(smgr);
+ if (ret != IFPGA_SEC_ERR_NONE)
+ fpga_sec_dev_error(smgr, ret);
+
+done:
+ if (smgr->sops->cleanup)
+ smgr->sops->cleanup(smgr);
+
+exit:
+ if (ret != IFPGA_SEC_ERR_NONE)
+ log_time(time(NULL) - start, "Secure flash update ERROR");
+ else
+ log_time(time(NULL) - start, "Secure flash update OK");
-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");
- if (ret == -EAGAIN)
- secure_update_cancel(smgr);
- } else {
- log_time(time(NULL) - start, "Secure flash update OK");
+ progress_complete(smgr);
+
+ dev_info(smgr, "Return %d\n", ret);
+ return ret == IFPGA_SEC_ERR_NONE ? 0 : -1;
+}
+
+int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,
+ uint64_t *status)
+{
+ struct ifpga_sec_mgr *smgr = NULL;
+ uint32_t rsu_stat = 0;
+ int ret = 0;
+
+ if (!fme || !image || !status) {
+ dev_err(fme, "Input parameter of %s is invalid\n", __func__);
+ return -EINVAL;
+ }
+
+ smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
+ if (!smgr) {
+ dev_err(smgr, "Security manager not initialized\n");
+ return -ENODEV;
+ }
+ if (!smgr->sops) {
+ dev_err(smgr, "Security manager not support flash update\n");
+ return -EOPNOTSUPP;
+ }
+
+ lock(smgr);
+ get_rsu_status(smgr, &rsu_stat, NULL);
+ if (rsu_stat != IFPGA_RSU_IDLE) {
+ unlock(smgr);
+ 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_status(smgr, IFPGA_RSU_IDLE, 0);
+ set_rsu_control(smgr, 0);
+ set_rsu_status(smgr, IFPGA_RSU_PREPARING, 0);
+
+ smgr->filename = image;
+ smgr->err_code = IFPGA_SEC_ERR_NONE;
+ smgr->hw_errinfo = 0;
+ unlock(smgr);
+
+ ret = fpga_sec_mgr_update(smgr);
+ *status = smgr->hw_errinfo;
return ret;
}
@@ -407,7 +520,7 @@ int fpga_stop_flash_update(struct ifpga_fme_hw *fme, int force)
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);
+ cancel_rsu(smgr);
}
if (force) {
@@ -416,8 +529,8 @@ int fpga_stop_flash_update(struct ifpga_fme_hw *fme, int force)
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);
+ if (fpga_sec_dev_cancel(smgr) == IFPGA_SEC_ERR_NONE)
+ update_rsu_stat(smgr, IFPGA_RSU_IDLE);
sleep(1);
} while (--retry > 0);
if (retry <= 0) {
@@ -429,9 +542,11 @@ int fpga_stop_flash_update(struct ifpga_fme_hw *fme, int force)
return ret;
}
-int fpga_reload(struct ifpga_fme_hw *fme, int type, int page)
+int fpga_reload(struct ifpga_fme_hw *fme, char *str)
{
struct ifpga_sec_mgr *smgr = NULL;
+ const struct image_load *hndlr = NULL;
+ int ret = -EOPNOTSUPP;
if (!fme) {
dev_err(fme, "Input parameter of %s is invalid\n", __func__);
@@ -439,8 +554,73 @@ int fpga_reload(struct ifpga_fme_hw *fme, int type, int page)
}
smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
- if (!smgr || !smgr->ops || !smgr->ops->reload)
+ if (!smgr)
+ return -ENODEV;
+
+ if (!smgr->sops || !smgr->sops->image_load)
+ return -EOPNOTSUPP;
+
+ for (hndlr = smgr->sops->image_load; hndlr->name; hndlr++) {
+ if (!strcmp(str, hndlr->name)) {
+ ret = hndlr->load_image(smgr);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int fpga_available_images(struct ifpga_fme_hw *fme, char *buf, size_t size)
+{
+ struct ifpga_sec_mgr *smgr = NULL;
+ const struct image_load *hndlr = NULL;
+ size_t count = 0;
+
+ 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)
+ return -ENODEV;
+
+ if (!smgr->sops || !smgr->sops->image_load)
+ return 0;
+
+ if (buf) {
+ for (hndlr = smgr->sops->image_load; hndlr->name; hndlr++) {
+ if ((size > count) &&
+ ((size - count) > strlen(hndlr->name))) {
+ count += snprintf(buf + count, size - count,
+ "%s ", hndlr->name);
+ }
+ }
+ buf[count - 1] = '\0';
+ } else {
+ for (hndlr = smgr->sops->image_load; hndlr->name; hndlr++)
+ count += strlen(hndlr->name) + 1;
+ }
+
+ return count;
+}
+
+int fpga_set_poc_image(struct ifpga_fme_hw *fme, char *buf)
+{
+ struct ifpga_sec_mgr *smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
+
+ if (!smgr)
+ return -ENODEV;
+
+ return pmci_set_poc_image(smgr, buf);
+}
+
+int fpga_get_poc_images(struct ifpga_fme_hw *fme, char *buf, size_t size)
+{
+ struct ifpga_sec_mgr *smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
+
+ if (!smgr)
+ return -ENODEV;
- return smgr->ops->reload(smgr, type, page);
+ return pmci_get_poc_images(smgr, buf, size);
}
diff --git a/drivers/raw/ifpga/base/ifpga_sec_mgr.c b/drivers/raw/ifpga/base/ifpga_sec_mgr.c
index 557c4e3..3250da1 100644
--- a/drivers/raw/ifpga/base/ifpga_sec_mgr.c
+++ b/drivers/raw/ifpga/base/ifpga_sec_mgr.c
@@ -4,9 +4,128 @@
#include <fcntl.h>
#include <signal.h>
+#include <stdint.h>
#include <unistd.h>
#include "ifpga_sec_mgr.h"
+#include "opae_intel_max10.h"
+#include "opae_osdep.h"
+
+static const char * const rsu_stat_string[] = {
+ [SEC_STATUS_NORMAL] = "Initial normal status",
+ [SEC_STATUS_TIMEOUT] = "Host timeout",
+ [SEC_STATUS_AUTH_FAIL] = "Authentication failure",
+ [SEC_STATUS_COPY_FAIL] = "Image copy failure",
+ [SEC_STATUS_FATAL] = "Fatal error, Nios boot-up failure",
+ [SEC_STATUS_PKVL_REJECT] = "pkvl reject",
+ [SEC_STATUS_NON_INC] = "Staging area non-incremental write fail",
+ [SEC_STATUS_ERASE_FAIL] = "Staging area erase fail",
+ [SEC_STATUS_WEAROUT] = "Staging area write wearout",
+ [SEC_STATUS_PMCI_SS_FAIL] = "PMCI SS Access fail",
+ [SEC_STATUS_FLASH_CMD] = "Unsupported flash command",
+ [SEC_STATUS_FACTORY_UNVERITY] = "factory image is unverified",
+ [SEC_STATUS_FACTORY_ACTIVE] = "current active image is factory",
+ [SEC_STATUS_POWER_DOWN] = "FPGA/Board powered down",
+ [SEC_STATUS_CANCELLATION] = "Cancellation not supported",
+ [SEC_STATUS_HASH] = "Hash Programming not supported",
+ [SEC_STATUS_FLASH_ACCESS] = "FPGA Flash Access Error",
+ [SEC_STATUS_SDM_PR_CERT] = "PR: cert not programmed to SDM",
+ [SEC_STATUS_SDM_PR_NIOS_BUSY] = "PR: Nios Busy waiting for SDM",
+ [SEC_STATUS_SDM_PR_TIMEOUT] = "PR: SDM Response timed out",
+ [SEC_STATUS_SDM_PR_FAILED] = "PR Key Hash program failed",
+ [SEC_STATUS_SDM_PR_MISMATCH] = "PR: SDM Response mismatched",
+ [SEC_STATUS_SDM_PR_FLUSH] = "PR: SDM Buffer Flushing failed",
+ [SEC_STATUS_SDM_SR_CERT] = "SR: cert is not programmed to SDM",
+ [SEC_STATUS_SDM_SR_NIOS_BUSY] = "SR: Nios Busy waiting for SDM",
+ [SEC_STATUS_SDM_SR_TIMEOUT] = "SR: SDM Response timed out",
+ [SEC_STATUS_SDM_SR_FAILED] = "SR Key Hash program failed",
+ [SEC_STATUS_SDM_SR_MISMATCH] = "SR: SDM Response mismatched",
+ [SEC_STATUS_SDM_SR_FLUSH] = "SR: SDM Buffer Flushing failed",
+ [SEC_STATUS_SDM_KEY_CERT] = "KEY: cert is not programmed to SDM",
+ [SEC_STATUS_SDM_KEY_NIOS_BUSY] = "KEY: Nios Busy waiting for SDM",
+ [SEC_STATUS_SDM_KEY_TIMEOUT] = "KEY: SDM Response timed out",
+ [SEC_STATUS_SDM_KEY_FAILED] = "KEY: Key Hash program failed",
+ [SEC_STATUS_SDM_KEY_MISMATCH] = "KEY: SDM Response mismatched",
+ [SEC_STATUS_SDM_KEY_FLUSH] = "KEY: SDM Buffer Flushing failed",
+ [SEC_STATUS_USER_FAIL] = "Update Failure",
+ [SEC_STATUS_FACTORY_FAIL] = "Factory Failure",
+ [SEC_STATUS_NIOS_FLASH_ERR] = "NIOS Flash Open Error",
+ [SEC_STATUS_FPGA_FLASH_ERR] = "FPGA Flash Open Error",
+};
+
+static const char * const auth_stat_string[] = {
+ [AUTH_STAT_PASS] = "Authenticate Pass",
+ [AUTH_STAT_B0_MAGIC] = "Block0 Magic value error",
+ [AUTH_STAT_CONLEN] = "Block0 ConLen error",
+ [AUTH_STAT_CONTYPE] = "Block0 ConType B[7:0] > 2",
+ [AUTH_STAT_B1_MAGIC] = "Block1 Magic value error",
+ [AUTH_STAT_ROOT_MAGIC] = "Root Entry Magic value error",
+ [AUTH_STAT_CURVE_MAGIC] = "Root Entry Curve Magic value error",
+ [AUTH_STAT_PERMISSION] = "Root Entry Permission error",
+ [AUTH_STAT_KEY_ID] = "Root Entry Key ID error",
+ [AUTH_STAT_CSK_MAGIC] = "CSK Entry Magic value error",
+ [AUTH_STAT_CSK_CURVE] = "CSK Entry Curve Magic value error",
+ [AUTH_STAT_CSK_PERMISSION] = "CSK Entry Permission error",
+ [AUTH_STAT_CSK_ID] = "CSK Entry Key ID error",
+ [AUTH_STAT_CSK_SM] = "CSK Entry Signature Magic value error",
+ [AUTH_STAT_B0_E_MAGIC] = "Block0 Entry Magic value error",
+ [AUTH_STAT_B0_E_SIGN] = "Block0 Entry Signature Magic value error",
+ [AUTH_STAT_RK_P] = "Root Key Hash not programmed for RSU",
+ [AUTH_STAT_RE_SHA] = "Root Entry verify SHA failed",
+ [AUTH_STAT_CSK_SHA] = "CSK Entry verify ECDSA and SHA failed",
+ [AUTH_STAT_B0_SHA] = "Block0 Entry verify ECDSA and SHA failed",
+ [AUTH_STAT_KEY_INV] = "KEY ID of authenticate blob is invalid",
+ [AUTH_STAT_KEY_CAN] = "KEY ID is cancelled",
+ [AUTH_STAT_UP_SHA] = "Update content SHA verify failed",
+ [AUTH_STAT_CAN_SHA] = "Cancellation content SHA verify failed",
+ [AUTH_STAT_HASH] = "HASH Programming content SHA verify failed",
+ [AUTH_STAT_INV_ID] = "Invalid cancellation ID of cancellation cert",
+ [AUTH_STAT_KEY_PROG] = "KEY hash programmed for KEY hash programming cert",
+ [AUTH_STAT_INV_BC] = "Invalid operation of Block0 ConType",
+ [AUTH_STAT_INV_SLOT] = "Invalid slot in Block0 ConType",
+ [AUTH_STAT_IN_OP] = "Incompatible operation of Block0 ConType",
+ [AUTH_STAT_TIME_OUT] = "Flash transfer to staging area timed out",
+ [AUTH_STAT_SHA_TO] = "Root Entry verify SHA timeout",
+ [AUTH_STAT_CSK_TO] = "CSK Entry verify ECDSA and SHA timeout",
+ [AUTH_STAT_B0_TO] = "Block0 Entry verify ECDSA and SHA timeout",
+ [AUTH_STAT_UP_TO] = "Update content SHA verify timeout",
+ [AUTH_STAT_CAN_TO] = "Cancellation content SHA verify timeout",
+ [AUTH_STAT_HASH_TO] = "HASH Programming content SHA verify timeout",
+ [AUTH_STAT_AUTH_IDLE] = "Authentication engine Idle",
+ [AUTH_STAT_GA_FAIL] = "Generic Authentication Failure",
+ [AUTH_STAT_S_ERR] = "Sensor Blob Generic Error",
+ [AUTH_STAT_S_MN] = "Sensor Blob Magic number error",
+ [AUTH_STAT_SH_CRC] = "Sensor Blob Header CRC error",
+ [AUTH_STAT_SD_CRC] = "Sensor Blob Data CRC error",
+ [AUTH_STAT_SD_LEN] = "Sensor Blob Data Length error",
+ [AUTH_STAT_S_ID] = "Sensor Blob Sensor ID not supported",
+ [AUTH_STAT_S_THR] = "Sensor Blob Invalid threshold type",
+ [AUTH_STAT_S_TO] = "Sensor Blob threshold out of bounds",
+ [AUTH_STAT_S_EN] = "Sensor Blob exceeds number of sensor count",
+ [AUTH_STAT_SF] = "only FPGA thermal Sensor Thresholds are allowed",
+};
+static const char * const sdm_stat_string[] = {
+ [SDM_STAT_DONE] = "SR Key Hash program successful",
+ [SDM_STAT_PROV] = "ignored,SR Hash is already provisioned to SDM",
+ [SDM_STAT_BUSY] = "Ignored; Configuration Module Busy",
+ [SDM_STAT_INV] = "Invalid configuration Status from Configuration",
+ [SDM_STAT_FAIL] = "SDM Flush Buffer failed",
+ [SDM_STAT_BMC_BUSY] = "BMC Busy waiting for another SDM command response",
+ [SDM_STAT_TO] = "SDM Response timed out during SDM Provisioning",
+ [SDM_STAT_DB] = "SDM device busy during SDM Provisioning",
+ [SDM_STAT_CON_R] = "Config Status retry count exceeded",
+ [SDM_STAT_CON_E] = "Config status command returned error",
+ [SDM_STAT_WAIT] = "BMC Busy waiting for another SDM command response",
+ [SDM_STAT_RTO] = "timed out during PUBKEY_PROGRAM command to SDM",
+ [SDM_STAT_SB] = "busy during PUBKEY_PROGRAM command to SDM",
+ [SDM_STAT_RE] = "SR Key Hash program failed with recoverable error",
+ [SDM_STAT_PDD] = "SR Key Hash program failed permanent device damage",
+ [SDM_STAT_ISC] = "SR Key program failed by invalid SDM command",
+ [SDM_STAT_SIC] = "SDM Congiguration failed by Shell Image configured",
+ [SDM_STAT_NO_PROV] = "SR Key Hash not provisioned to BMC",
+ [SDM_STAT_CS_MIS] = "failed by SDM CONFIG_STATUS response mismatch",
+ [SDM_STAT_PR_MIS] = "failed by SDM PUBKEY_PROGRAM Response mismatch",
+};
static const char * const rsu_prog[] = {"IDLE", "PREPARING", "SLEEPING",
"READY", "AUTHENTICATING", "COPYING", "CANCELLATION", "PROGRAMMING_KEY",
@@ -17,6 +136,160 @@
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 * const fpga_image_names[] = {
+ [FPGA_FACTORY] = "fpga_factory",
+ [FPGA_USER1] = "fpga_user1",
+ [FPGA_USER2] = "fpga_user2"
+};
+
+static enum fpga_image
+fpga_image_by_name(char *image_name)
+{
+ enum fpga_image i;
+
+ for (i = 0; i < FPGA_MAX; i++)
+ if (!strcmp(image_name, fpga_image_names[i]))
+ return i;
+
+ return FPGA_MAX;
+}
+
+static int
+fpga_images(struct ifpga_sec_mgr *smgr, char *names, enum fpga_image images[])
+{
+ u32 image_mask = smgr->poc->avail_image_mask;
+ enum fpga_image image;
+ char *image_name;
+ int i = 0;
+
+ while ((image_name = strsep(&names, "\n"))) {
+ image = fpga_image_by_name(image_name);
+ if (image >= FPGA_MAX || !(image_mask & BIT(image)))
+ return -EINVAL;
+
+ images[i++] = image;
+ image_mask &= ~BIT(image);
+ }
+
+ return (i == 0) ? -EINVAL : 0;
+}
+
+int pmci_set_poc_image(struct ifpga_sec_mgr *smgr, char *buf)
+{
+ enum fpga_image images[FPGA_MAX] = { [0 ... FPGA_MAX - 1] = FPGA_MAX };
+ int ret;
+
+ if (!smgr)
+ return -ENODEV;
+
+ ret = fpga_images(smgr, buf, images);
+ if (ret)
+ return -EINVAL;
+
+ return smgr->poc->set_sequence(smgr, images);
+}
+
+int pmci_get_poc_images(struct ifpga_sec_mgr *smgr, char *buf, size_t size)
+{
+ if (!smgr)
+ return -ENODEV;
+
+ return smgr->poc->get_sequence(smgr, buf, size);
+}
+
+static int pmci_get_power_on_image(struct ifpga_sec_mgr *smgr,
+ char *buf, size_t size)
+{
+ const char *image_names[FPGA_MAX] = { 0 };
+ int ret, i = 0;
+ int j;
+ u32 poc;
+ size_t count = 0;
+
+ if (!smgr->max10_dev)
+ return -ENODEV;
+
+ if (!buf)
+ return -EINVAL;
+
+ ret = max10_sys_read(smgr->max10_dev, M10BMC_PMCI_FPGA_POC, &poc);
+ if (ret)
+ return ret;
+
+ if (poc & PMCI_FACTORY_IMAGE_SEL)
+ image_names[i++] = fpga_image_names[FPGA_FACTORY];
+
+ if (GET_FIELD(PMCI_USER_IMAGE_PAGE, poc) == POC_USER_IMAGE_1) {
+ image_names[i++] = fpga_image_names[FPGA_USER1];
+ image_names[i++] = fpga_image_names[FPGA_USER2];
+ } else {
+ image_names[i++] = fpga_image_names[FPGA_USER2];
+ image_names[i++] = fpga_image_names[FPGA_USER1];
+ }
+
+ if (!(poc & PMCI_FACTORY_IMAGE_SEL))
+ image_names[i] = fpga_image_names[FPGA_FACTORY];
+
+ for (j = 0; j < FPGA_MAX; j++) {
+ if ((size > count) &&
+ ((size - count) > strlen(image_names[j])))
+ count += snprintf(buf + count, size - count,
+ "%s ", image_names[j]);
+ }
+ buf[count - 1] = '\0';
+
+ return count;
+}
+
+static int
+pmci_set_power_on_image(struct ifpga_sec_mgr *smgr, enum fpga_image images[])
+{
+ struct intel_max10_device *dev = smgr->max10_dev;
+ u32 poc_mask = PMCI_FACTORY_IMAGE_SEL;
+ int ret, first_user = 0;
+ u32 poc = 0;
+
+ if (!dev)
+ return -ENODEV;
+
+ if (images[1] == FPGA_FACTORY)
+ return -EINVAL;
+
+ if (images[0] == FPGA_FACTORY) {
+ poc = PMCI_FACTORY_IMAGE_SEL;
+ first_user = 1;
+ }
+
+ if (images[first_user] == FPGA_USER1 ||
+ images[first_user] == FPGA_USER2) {
+ poc_mask |= PMCI_USER_IMAGE_PAGE;
+ if (images[first_user] == FPGA_USER1)
+ poc |= SET_FIELD(PMCI_USER_IMAGE_PAGE,
+ POC_USER_IMAGE_1);
+ else
+ poc |= SET_FIELD(PMCI_USER_IMAGE_PAGE,
+ POC_USER_IMAGE_2);
+ }
+
+ ret = max10_sys_update_bits(dev,
+ m10bmc_base(dev) + M10BMC_PMCI_FPGA_POC,
+ poc_mask | PMCI_FPGA_POC, poc | PMCI_FPGA_POC);
+ if (ret)
+ return ret;
+
+ ret = opae_max10_read_poll_timeout(dev,
+ m10bmc_base(dev) + M10BMC_PMCI_FPGA_POC,
+ poc,
+ (!(poc & PMCI_FPGA_POC)),
+ IFPGA_NIOS_HANDSHAKE_INTERVAL_US,
+ IFPGA_NIOS_HANDSHAKE_TIMEOUT_US);
+
+ if (ret || (GET_FIELD(PMCI_NIOS_STATUS, poc) != NIOS_STATUS_SUCCESS))
+ return -EIO;
+
+ return 0;
+}
+
static const char *rsu_progress_name(uint32_t prog)
{
if (prog > SEC_PROGRESS_PKVL_PROM_DONE)
@@ -40,377 +313,527 @@ static const char *rsu_status_name(uint32_t stat)
}
}
-static bool secure_start_done(uint32_t doorbell)
+static void print_sdm_status(struct intel_max10_device *dev)
{
- 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));
+ u32 val, sdm_stat;
+
+ const char *sdm_string;
+
+ if (dev->type == M10_N6000) {
+ if (!max10_sys_read(dev, m10bmc_base(dev) +
+ M10BMC_PMCI_SDM_CTRL_STS, &val))
+ dev_err(dev, "sdm ctrl reg: 0x%08x\n", val);
+
+ sdm_stat = GET_FIELD(val, PMCI_SDM_STAT);
+ if (sdm_stat > SDM_STAT_MAX)
+ dev_err(dev, "unknown sdm stat: 0x%08x\n", sdm_stat);
+
+ sdm_string = sdm_stat_string[sdm_stat];
+ if (sdm_string)
+ dev_err(dev, "sdm stat: %s\n", sdm_string);
+ else
+ dev_err(dev, "unknown sdm stat\n");
+ }
}
-static bool secure_prog_ready(uint32_t doorbell)
+static void print_error_regs(struct intel_max10_device *dev)
{
- return (SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_READY);
+ u32 auth_result, doorbell, rsu_stat, auth_stat;
+
+ const char *rsu_string, *auth_string;
+
+ if (!max10_sys_read(dev, doorbell_reg(dev), &doorbell))
+ dev_err(dev, "RSU doorbell reg: 0x%08x\n", doorbell);
+
+ if (!max10_sys_read(dev, auth_result_reg(dev), &auth_result))
+ dev_err(dev, "RSU auth result reg: 0x%08x\n", auth_result);
+
+ rsu_stat = SEC_STATUS_G(auth_result);
+ if (rsu_stat > SEC_STATUS_MAX)
+ dev_err(dev, "unknown rsu stat, error code exceed: 0x%08x\n", rsu_stat);
+
+ rsu_string = rsu_stat_string[rsu_stat];
+ if (rsu_string)
+ dev_err(dev, "rsu stat: %s\n", rsu_string);
+ else
+ dev_err(dev, "unknown rsu stat\n");
+
+ if (rsu_stat == SEC_STATUS_SDM_PR_FAILED ||
+ rsu_stat == SEC_STATUS_SDM_SR_FAILED)
+ print_sdm_status(dev);
+
+ auth_stat = SEC_AUTH_G(auth_result);
+ if (auth_stat > AUTH_STAT_MAX)
+ dev_err(dev, "unknown Authentication status, code exceed: 0x%08x\n", rsu_stat);
+
+ auth_string = auth_stat_string[auth_stat];
+ if (auth_string)
+ dev_err(dev, "auth stat: %s\n", auth_string);
+ else
+ dev_err(dev, "unknown auth stat\n");
}
-static int poll_timeout(struct intel_max10_device *dev, uint32_t offset,
- bool (*cond)(uint32_t), uint32_t interval_ms, uint32_t timeout_ms)
+static bool rsu_status_ok(u32 status)
{
- 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;
- }
+ return (status == SEC_STATUS_NORMAL ||
+ status == SEC_STATUS_NIOS_OK ||
+ status == SEC_STATUS_USER_OK ||
+ status == SEC_STATUS_FACTORY_OK);
+}
- 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);
- }
+static bool rsu_progress_done(u32 progress)
+{
+ return (progress == SEC_PROGRESS_IDLE ||
+ progress == SEC_PROGRESS_RSU_DONE);
+}
- return ret;
+static bool rsu_progress_busy(u32 progress)
+{
+ return (progress == SEC_PROGRESS_AUTHENTICATING ||
+ progress == SEC_PROGRESS_COPYING ||
+ progress == SEC_PROGRESS_UPDATE_CANCEL ||
+ progress == SEC_PROGRESS_PROGRAM_KEY_HASH);
}
-static int n3000_secure_update_start(struct intel_max10_device *dev)
+static enum ifpga_sec_err rsu_check_idle(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) {
+ ret = max10_sys_read(dev, doorbell_reg(dev), &doorbell);
+ if (ret) {
dev_err(dev,
"Failed to read max10 doorbell register [e:%d]\n",
ret);
- return ret;
+ return IFPGA_SEC_ERR_RW_ERROR;
}
prog = SEC_PROGRESS_G(doorbell);
- if ((prog != SEC_PROGRESS_IDLE) && (prog != SEC_PROGRESS_RSU_DONE)) {
- dev_debug(dev, "Current RSU progress is %s\n",
+ if (!rsu_progress_done(prog)) {
+ dev_info(dev, "Current RSU progress is %s\n",
rsu_progress_name(prog));
- return -EBUSY;
+ return IFPGA_SEC_ERR_BUSY;
+ }
+
+ return IFPGA_SEC_ERR_NONE;
+}
+
+static bool cond_start_done(uint32_t doorbell, uint32_t progress,
+ uint32_t status)
+{
+ if (doorbell & RSU_REQUEST)
+ return false;
+
+ if (status == SEC_STATUS_ERASE_FAIL ||
+ status == SEC_STATUS_WEAROUT)
+ return true;
+
+ if (!rsu_progress_done(progress))
+ return true;
+
+ return false;
+}
+
+static int
+m10bmc_sec_status(struct intel_max10_device *dev, u32 *status)
+{
+ u32 reg_offset, reg_value;
+ int ret;
+
+ reg_offset = (dev->type == M10_N6000) ?
+ auth_result_reg(dev) : doorbell_reg(dev);
+
+ ret = max10_sys_read(dev, reg_offset, ®_value);
+ if (ret)
+ return ret;
+
+ *status = SEC_STATUS_G(reg_value);
+
+ return 0;
+}
+
+static int
+m10bmc_sec_progress_status(struct intel_max10_device *dev, u32 *doorbell,
+ u32 *progress, u32 *status)
+{
+ u32 auth_reg;
+ int ret;
+
+ ret = max10_sys_read(dev,
+ doorbell_reg(dev),
+ doorbell);
+ if (ret)
+ return ret;
+
+ *progress = SEC_PROGRESS_G(*doorbell);
+
+ if (dev->type == M10_N6000) {
+ ret = max10_sys_read(dev,
+ auth_result_reg(dev),
+ &auth_reg);
+ if (ret)
+ return ret;
+ *status = SEC_STATUS_G(auth_reg);
+ } else {
+ *status = SEC_STATUS_G(*doorbell);
}
- ret = max10_sys_update_bits(dev, MAX10_DOORBELL,
+ return 0;
+}
+
+static int rsu_poll_start_done(struct intel_max10_device *dev, u32 *doorbell,
+ u32 *progress, u32 *status)
+{
+ unsigned long time = 0;
+ int ret;
+
+ do {
+ if (time > IFPGA_NIOS_HANDSHAKE_TIMEOUT_US)
+ return -ETIMEDOUT;
+
+ ret = m10bmc_sec_progress_status(dev, doorbell,
+ progress, status);
+ if (ret)
+ return ret;
+ usleep(IFPGA_NIOS_HANDSHAKE_INTERVAL_US);
+ time += IFPGA_NIOS_HANDSHAKE_INTERVAL_US;
+
+ } while (!cond_start_done(*doorbell, *progress, *status));
+
+ return 0;
+}
+
+static enum ifpga_sec_err rsu_update_init(struct intel_max10_device *dev)
+{
+ uint32_t doorbell, progress, status;
+ int ret = 0;
+
+ ret = max10_sys_update_bits(dev, doorbell_reg(dev),
RSU_REQUEST | HOST_STATUS, RSU_REQUEST);
- if (ret < 0) {
+ if (ret) {
dev_err(dev,
"Failed to updt max10 doorbell register [e:%d]\n",
ret);
- return ret;
+ return IFPGA_SEC_ERR_RW_ERROR;
}
- ret = poll_timeout(dev, MAX10_DOORBELL, secure_start_done,
- IFPGA_SEC_START_INTERVAL_MS, IFPGA_SEC_START_TIMEOUT_MS);
- if (ret < 0) {
+ ret = rsu_poll_start_done(dev, &doorbell, &progress, &status);
+ if (ret == -ETIMEDOUT) {
+ print_error_regs(dev);
+ return IFPGA_SEC_ERR_TIMEOUT;
+ } else if (ret) {
dev_err(dev,
"Failed to poll max10 doorbell register [e:%d]\n",
ret);
- return ret;
+ return IFPGA_SEC_ERR_RW_ERROR;
}
- 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) {
+ dev_err(dev, "Excessive flash update count detected\n");
+ return IFPGA_SEC_ERR_WEAROUT;
+ } else if (status == SEC_STATUS_ERASE_FAIL) {
+ print_error_regs(dev);
+ return IFPGA_SEC_ERR_HW_ERROR;
}
- status = SEC_STATUS_G(doorbell);
- if (status == SEC_STATUS_WEAROUT)
- return -EAGAIN;
+ dev_info(dev, "Current RSU progress is %s\n",
+ rsu_progress_name(SEC_PROGRESS_G(doorbell)));
- if (status == SEC_STATUS_ERASE_FAIL)
- return -EIO;
+ return IFPGA_SEC_ERR_NONE;
+}
- return 0;
+static bool cond_prepare_done(uint32_t doorbell)
+{
+ return (SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_PREPARE);
}
-static int n3000_cancel(struct ifpga_sec_mgr *smgr)
+static enum ifpga_sec_err rsu_prog_ready(struct intel_max10_device *dev)
{
- 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) {
+ ret = opae_max10_read_poll_timeout(dev, doorbell_reg(dev),
+ doorbell, cond_prepare_done(doorbell),
+ IFPGA_RSU_PREP_INTERVAL_US,
+ IFPGA_RSU_PREP_TIMEOUT_US);
+ if (ret == -ETIMEDOUT) {
+ print_error_regs(dev);
+ return IFPGA_SEC_ERR_TIMEOUT;
+ } else if (ret) {
dev_err(dev,
- "Failed to read max10 doorbell register [e:%d]\n",
+ "Failed to poll max10 prog [e:%d]\n",
ret);
- return ret;
+ return IFPGA_SEC_ERR_RW_ERROR;
}
prog = SEC_PROGRESS_G(doorbell);
- if (prog == SEC_PROGRESS_IDLE)
- return 0;
- if (prog != SEC_PROGRESS_READY)
- return -EBUSY;
+ if (prog == SEC_PROGRESS_PREPARE) {
+ print_error_regs(dev);
+ return IFPGA_SEC_ERR_TIMEOUT;
+ } else if (prog != SEC_PROGRESS_READY) {
+ return IFPGA_SEC_ERR_HW_ERROR;
+ }
- return max10_sys_update_bits(dev, MAX10_DOORBELL, HOST_STATUS,
- HOST_STATUS_S(HOST_STATUS_ABORT_RSU));
+ dev_info(dev, "Current RSU progress is %s\n",
+ rsu_progress_name(SEC_PROGRESS_G(doorbell)));
+
+ return IFPGA_SEC_ERR_NONE;
}
-static int n3000_prepare(struct ifpga_sec_mgr *smgr)
+static enum ifpga_sec_err m10bmc_sec_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;
+ return IFPGA_SEC_ERR_HW_ERROR;
- ret = n3000_secure_update_start(dev);
- if (ret == -EBUSY)
- n3000_cancel(smgr);
+ dev = smgr->max10_dev;
- 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;
+ if (smgr->remaining_size > dev->staging_area_size) {
+ dev_err(smgr, "Size of staging area is smaller than image "
+ "length [%u<%u]\n", smgr->max10_dev->staging_area_size,
+ smgr->remaining_size);
+ return IFPGA_SEC_ERR_INVALID_SIZE;
}
- 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;
- }
+ ret = rsu_check_idle(dev);
+ if (ret != IFPGA_SEC_ERR_NONE)
+ return ret;
- n = len >> 2;
- for (i = 0; i < n; i++) {
- p = i << 2;
- v = *(uint32_t *)(buf + p);
- ret = max10_sys_raw_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);
- }
+ ret = rsu_update_init(dev);
+ if (ret != IFPGA_SEC_ERR_NONE)
+ return ret;
- return 0;
+ return rsu_prog_ready(dev);
}
-static int n3000_write_blk(struct ifpga_sec_mgr *smgr, char *buf,
+
+static enum ifpga_sec_err m10bmc_sec_write_blk(struct ifpga_sec_mgr *smgr,
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;
+ return IFPGA_SEC_ERR_HW_ERROR;
+
+ dev = smgr->max10_dev;
+ if (!dev || !dev->bmc_ops.flash_write)
+ return IFPGA_SEC_ERR_HW_ERROR;
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;
+ return IFPGA_SEC_ERR_INVALID_SIZE;
}
- ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
+ ret = max10_sys_read(dev, doorbell_reg(dev), &doorbell);
if (ret < 0) {
dev_err(dev,
"Failed to read max10 doorbell register [e:%d]\n",
ret);
- return ret;
+ return IFPGA_SEC_ERR_RW_ERROR;
}
- prog = SEC_PROGRESS_G(doorbell);
- if (prog == SEC_PROGRESS_PREPARE)
- return -EAGAIN;
- else if (prog != SEC_PROGRESS_READY)
- return -EBUSY;
+ if (SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_READY)
+ return IFPGA_SEC_ERR_HW_ERROR;
- m = len & 0x3;
- if (m != 0)
- len += 4 - m; /* make length to 4 bytes align */
+ ret = dev->bmc_ops.flash_write(dev, dev->staging_area_base + offset,
+ smgr->data, len);
- return n3000_bulk_write(dev, dev->staging_area_base + offset, buf, len);
+ return ret ? IFPGA_SEC_ERR_RW_ERROR : IFPGA_SEC_ERR_NONE;
}
-static int n3000_write_done(struct ifpga_sec_mgr *smgr)
+static enum ifpga_sec_err pmci_sec_write_blk(struct ifpga_sec_mgr *smgr,
+ uint32_t offset, uint32_t len)
{
- struct intel_max10_device *dev = NULL;
+ struct intel_max10_device *dev;
uint32_t doorbell = 0;
- uint32_t prog = 0;
- uint32_t status = 0;
int ret = 0;
+ UNUSED(offset);
if (!smgr || !smgr->max10_dev)
- return -ENODEV;
- dev = (struct intel_max10_device *)smgr->max10_dev;
+ return IFPGA_SEC_ERR_HW_ERROR;
- ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
+ dev = smgr->max10_dev;
+ if (!dev || !dev->bmc_ops.flash_write)
+ return IFPGA_SEC_ERR_HW_ERROR;
+
+ ret = max10_sys_read(dev, doorbell_reg(dev), &doorbell);
if (ret < 0) {
dev_err(dev,
"Failed to read max10 doorbell register [e:%d]\n",
ret);
- return ret;
+ return IFPGA_SEC_ERR_RW_ERROR;
}
- prog = SEC_PROGRESS_G(doorbell);
- if (prog != SEC_PROGRESS_READY)
- return -EBUSY;
+ if (SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_READY)
+ return IFPGA_SEC_ERR_HW_ERROR;
+
+ ret = dev->bmc_ops.flash_write(dev, 0, smgr->data, len);
+
+ return ret ? IFPGA_SEC_ERR_RW_ERROR : IFPGA_SEC_ERR_NONE;
+}
- ret = max10_sys_update_bits(dev, MAX10_DOORBELL, HOST_STATUS,
+static bool cond_prog_ready(uint32_t doorbell)
+{
+ return (SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_READY);
+}
+
+static enum ifpga_sec_err m10bmc_sec_write_done(struct ifpga_sec_mgr *smgr)
+{
+ struct intel_max10_device *dev = NULL;
+ uint32_t doorbell, status;
+ int ret = 0;
+
+ if (!smgr || !smgr->max10_dev)
+ return IFPGA_SEC_ERR_HW_ERROR;
+
+ dev = smgr->max10_dev;
+
+ ret = max10_sys_update_bits(dev, doorbell_reg(dev), 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;
+ return IFPGA_SEC_ERR_RW_ERROR;
}
- 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 = opae_max10_read_poll_timeout(dev, doorbell_reg(dev),
+ doorbell, cond_prog_ready(doorbell),
+ IFPGA_NIOS_HANDSHAKE_INTERVAL_US,
+ IFPGA_NIOS_HANDSHAKE_TIMEOUT_US);
+ if (ret == -ETIMEDOUT) {
+ print_error_regs(dev);
+ return IFPGA_SEC_ERR_TIMEOUT;
+ } else if (ret) {
+ return IFPGA_SEC_ERR_RW_ERROR;
}
- 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;
+ ret = m10bmc_sec_status(dev, &status);
+ if (ret)
+ return IFPGA_SEC_ERR_RW_ERROR;
+
+ if (!rsu_status_ok(status)) {
+ print_error_regs(dev);
+ return IFPGA_SEC_ERR_HW_ERROR;
}
- 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 IFPGA_SEC_ERR_NONE;
+}
+
+static enum ifpga_sec_err m10bmc_sec_check_complete(struct ifpga_sec_mgr *smgr)
+{
+ struct intel_max10_device *dev = NULL;
+ uint32_t doorbell, status, progress;
+
+ if (!smgr || !smgr->max10_dev)
+ return IFPGA_SEC_ERR_HW_ERROR;
+
+ dev = smgr->max10_dev;
+
+ if (m10bmc_sec_progress_status(dev, &doorbell, &progress, &status)) {
+ print_error_regs(dev);
+ return IFPGA_SEC_ERR_RW_ERROR;
}
- return ret;
+ if (!rsu_status_ok(status)) {
+ print_error_regs(dev);
+ return IFPGA_SEC_ERR_HW_ERROR;
+ }
+
+ if (rsu_progress_done(progress))
+ return IFPGA_SEC_ERR_NONE;
+
+ if (rsu_progress_busy(progress))
+ return IFPGA_SEC_ERR_BUSY;
+
+ return IFPGA_SEC_ERR_HW_ERROR;
}
-static int n3000_check_complete(struct ifpga_sec_mgr *smgr)
+static enum ifpga_sec_err m10bmc_sec_cancel(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;
+ return IFPGA_SEC_ERR_HW_ERROR;
- ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
+ dev = smgr->max10_dev;
+
+ ret = max10_sys_read(dev, doorbell_reg(dev), &doorbell);
if (ret < 0) {
dev_err(dev,
"Failed to read max10 doorbell register [e:%d]\n",
ret);
- return ret;
+ return IFPGA_SEC_ERR_RW_ERROR;
}
- 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;
+ if (SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_READY)
+ return IFPGA_SEC_ERR_BUSY;
+
+ ret = max10_sys_update_bits(dev, doorbell_reg(dev), HOST_STATUS,
+ HOST_STATUS_S(HOST_STATUS_ABORT_RSU));
+
+ return ret ? IFPGA_SEC_ERR_RW_ERROR : IFPGA_SEC_ERR_NONE;
+}
+
+static uint64_t m10bmc_sec_hw_errinfo(struct ifpga_sec_mgr *smgr)
+{
+ struct intel_max10_device *dev = NULL;
+ uint32_t doorbell = IFPGA_HW_ERRINFO_POISON;
+ uint32_t auth_result = IFPGA_HW_ERRINFO_POISON;
+ uint32_t stat = 0;
+ uint32_t prog = 0;
+
+ if (smgr && smgr->max10_dev) {
+ dev = smgr->max10_dev;
+ switch (smgr->err_code) {
+ case IFPGA_SEC_ERR_HW_ERROR:
+ case IFPGA_SEC_ERR_TIMEOUT:
+ case IFPGA_SEC_ERR_BUSY:
+ case IFPGA_SEC_ERR_WEAROUT:
+ if (max10_sys_read(dev, doorbell_reg(dev),
+ &doorbell))
+ doorbell = IFPGA_HW_ERRINFO_POISON;
+ if (max10_sys_read(dev, auth_result_reg(dev),
+ &auth_result))
+ auth_result = IFPGA_HW_ERRINFO_POISON;
+ break;
+ default:
+ doorbell = 0;
+ auth_result = 0;
+ break;
+ }
}
+ stat = SEC_STATUS_G(doorbell);
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;
- }
+ dev_info(dev, "Current RSU status is %s, progress is %s\n",
+ rsu_status_name(stat), rsu_progress_name(prog));
- return 0;
+ return (uint64_t)doorbell << 32 | (uint64_t)auth_result;
}
-static int n3000_reload_fpga(struct intel_max10_device *dev, int page)
+static int m10bmc_sec_fpga_image_load(struct ifpga_sec_mgr *smgr, int page)
{
+ struct intel_max10_device *dev = NULL;
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 (!smgr || !smgr->max10_dev)
+ return -ENODEV;
+
+ dev = smgr->max10_dev;
if (dev->flags & MAX10_FLAGS_SECURE) {
ret = max10_sys_update_bits(dev, FPGA_RECONF_REG,
@@ -471,117 +894,210 @@ static int n3000_reload_fpga(struct intel_max10_device *dev, int page)
return ret;
}
-static int n3000_reload_bmc(struct intel_max10_device *dev, int page)
+static int m10bmc_sec_bmc_image_load(struct ifpga_sec_mgr *smgr, int page)
{
- uint32_t val = 0;
+ struct intel_max10_device *dev = NULL;
+ uint32_t doorbell = 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 (!smgr || !smgr->max10_dev)
+ return -ENODEV;
- 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;
- ret = max10_sys_raw_write(dev, IFPGA_DUAL_CFG_CTRL1, val);
- if (ret < 0) {
- dev_err(dev,
- "Failed to write to dual config1 register [e:%d]\n",
- ret);
- goto end;
- }
+ dev = smgr->max10_dev;
- ret = max10_sys_raw_write(dev, IFPGA_DUAL_CFG_CTRL0, 0x1);
- if (ret < 0) {
- if (ret == -EIO) {
- ret = 0;
- goto end;
- }
- dev_err(dev,
- "Failed to write to dual config0 register [e:%d]\n",
+ ret = max10_sys_read(dev, doorbell_reg(dev), &doorbell);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read max10 doorbell register [e:%d]\n",
ret);
- }
+ return ret;
}
-end:
- if (ret < 0)
- dev_err(dev, "Failed to reload BMC\n");
+ switch (dev->type) {
+ case N3000BMC_SEC:
+ if (doorbell & REBOOT_DISABLED)
+ return -EBUSY;
+
+ ret = max10_sys_update_bits(dev, doorbell_reg(dev),
+ CONFIG_SEL | REBOOT_REQ,
+ CONFIG_SEL_S(page) | REBOOT_REQ);
+ break;
+ case N6000BMC_SEC:
+ if (doorbell & PMCI_DRBL_REBOOT_DISABLED)
+ return -EBUSY;
+
+ ret = max10_sys_update_bits(dev, m10bmc_base(dev) +
+ M10BMC_PMCI_MAX10_RECONF,
+ PMCI_MAX10_REBOOT_REQ | PMCI_MAX10_REBOOT_PAGE,
+ SET_FIELD(PMCI_MAX10_REBOOT_PAGE, page) |
+ PMCI_MAX10_REBOOT_REQ);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
return ret;
}
-static int n3000_reload(struct ifpga_sec_mgr *smgr, int type, int page)
+static int pmci_sec_fpga_image_load(struct ifpga_sec_mgr *smgr,
+ unsigned int val)
{
- int psel = 0;
- int ret = 0;
+ struct intel_max10_device *dev;
+ int ret;
if (!smgr || !smgr->max10_dev)
return -ENODEV;
- if (type == IFPGA_BOOT_TYPE_FPGA) {
- psel = (page == IFPGA_BOOT_PAGE_FACTORY ? 0 : 1);
- ret = n3000_reload_fpga(smgr->max10_dev, psel);
- } else if (type == IFPGA_BOOT_TYPE_BMC) {
- psel = (page == IFPGA_BOOT_PAGE_FACTORY ? 1 : 0);
- ret = n3000_reload_bmc(smgr->max10_dev, psel);
- } else {
- ret = -EINVAL;
+ dev = smgr->max10_dev;
+
+ if (val > 2) {
+ dev_err(dev, "%s invalid reload val = %d\n",
+ __func__, val);
+ return -EINVAL;
}
- return ret;
+ ret = max10_sys_update_bits(dev,
+ M10BMC_PMCI_FPGA_RECONF,
+ PMCI_FPGA_RP_LOAD, 0);
+ if (ret)
+ return ret;
+
+ return max10_sys_update_bits(dev,
+ M10BMC_PMCI_FPGA_RECONF,
+ PMCI_FPGA_RECONF_PAGE | PMCI_FPGA_RP_LOAD,
+ SET_FIELD(PMCI_FPGA_RECONF_PAGE, val) |
+ PMCI_FPGA_RP_LOAD);
}
-static uint64_t n3000_get_hw_errinfo(struct ifpga_sec_mgr *smgr)
+static int n3000_sec_fpga_image_load_0(struct ifpga_sec_mgr *smgr)
{
- struct intel_max10_device *dev = NULL;
- uint32_t doorbell = 0;
- uint32_t stat = 0;
- uint32_t prog = 0;
- uint32_t auth_result = 0;
- int ret = 0;
+ return m10bmc_sec_fpga_image_load(smgr, 0);
+}
- if (!smgr || !smgr->max10_dev)
- return -ENODEV;
- dev = (struct intel_max10_device *)smgr->max10_dev;
+static int n3000_sec_fpga_image_load_1(struct ifpga_sec_mgr *smgr)
+{
+ return m10bmc_sec_fpga_image_load(smgr, 1);
+}
- 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 -1;
- }
- stat = SEC_STATUS_G(doorbell);
- prog = SEC_PROGRESS_G(doorbell);
- dev_debug(dev, "Current RSU status is %s, progress is %s\n",
- rsu_status_name(stat), rsu_progress_name(prog));
+static int n3000_sec_bmc_image_load_0(struct ifpga_sec_mgr *smgr)
+{
+ return m10bmc_sec_bmc_image_load(smgr, 0);
+}
- ret = max10_sys_read(dev, MAX10_AUTH_RESULT, &auth_result);
- if (ret < 0) {
- dev_err(dev,
- "Failed to read authenticate result register [e:%d]\n",
- ret);
- return -1;
- }
+static int n3000_sec_bmc_image_load_1(struct ifpga_sec_mgr *smgr)
+{
+ return m10bmc_sec_bmc_image_load(smgr, 1);
+}
- return (uint64_t)doorbell << 32 | (uint64_t)auth_result;
+static int pmci_sec_bmc_image_load_0(struct ifpga_sec_mgr *smgr)
+{
+ return m10bmc_sec_bmc_image_load(smgr, 0);
+}
+
+static int pmci_sec_bmc_image_load_1(struct ifpga_sec_mgr *smgr)
+{
+ return m10bmc_sec_bmc_image_load(smgr, 1);
+}
+
+static int pmci_sec_fpga_image_load_0(struct ifpga_sec_mgr *smgr)
+{
+ return pmci_sec_fpga_image_load(smgr, 0);
+}
+
+static int pmci_sec_fpga_image_load_1(struct ifpga_sec_mgr *smgr)
+{
+ return pmci_sec_fpga_image_load(smgr, 1);
+}
+
+static int pmci_sec_fpga_image_load_2(struct ifpga_sec_mgr *smgr)
+{
+ return pmci_sec_fpga_image_load(smgr, 2);
+}
+
+static int pmci_sec_sdm_image_load(struct ifpga_sec_mgr *smgr)
+{
+ struct intel_max10_device *dev = smgr->max10_dev;
+
+ return max10_sys_update_bits(dev,
+ m10bmc_base(dev) + M10BMC_PMCI_SDM_CTRL_STS,
+ PMCI_SDM_IMG_REQ, PMCI_SDM_IMG_REQ);
}
-static const struct ifpga_sec_ops n3000_sec_ops = {
- .prepare = n3000_prepare,
- .write_blk = n3000_write_blk,
- .write_done = n3000_write_done,
- .check_complete = n3000_check_complete,
- .reload = n3000_reload,
- .cancel = n3000_cancel,
- .cleanup = NULL,
- .get_hw_errinfo = n3000_get_hw_errinfo,
+static struct image_load n3000_image_load_hndlrs[] = {
+ {
+ .name = "fpga_factory",
+ .load_image = n3000_sec_fpga_image_load_0,
+ },
+ {
+ .name = "fpga_user",
+ .load_image = n3000_sec_fpga_image_load_1,
+ },
+ {
+ .name = "bmc_factory",
+ .load_image = n3000_sec_bmc_image_load_1,
+ },
+ {
+ .name = "bmc_user",
+ .load_image = n3000_sec_bmc_image_load_0,
+ },
+ {}
+};
+
+static struct image_load pmci_image_load_hndlrs[] = {
+ {
+ .name = "bmc_factory",
+ .load_image = pmci_sec_bmc_image_load_0,
+ },
+ {
+ .name = "bmc_user",
+ .load_image = pmci_sec_bmc_image_load_1,
+ },
+ {
+ .name = "fpga_factory",
+ .load_image = pmci_sec_fpga_image_load_0,
+ },
+ {
+ .name = "fpga_user1",
+ .load_image = pmci_sec_fpga_image_load_1,
+ },
+ {
+ .name = "fpga_user2",
+ .load_image = pmci_sec_fpga_image_load_2,
+ },
+ {
+ .name = "sdm",
+ .load_image = pmci_sec_sdm_image_load,
+ },
+ {}
+};
+
+static const struct ifpga_sec_mgr_ops n3000_sec_ops = {
+ .prepare = m10bmc_sec_prepare,
+ .write_blk = m10bmc_sec_write_blk,
+ .write_done = m10bmc_sec_write_done,
+ .check_complete = m10bmc_sec_check_complete,
+ .cancel = m10bmc_sec_cancel,
+ .get_hw_errinfo = m10bmc_sec_hw_errinfo,
+ .image_load = n3000_image_load_hndlrs,
+};
+
+static const struct ifpga_sec_mgr_ops pmci_sec_ops = {
+ .prepare = m10bmc_sec_prepare,
+ .write_blk = pmci_sec_write_blk,
+ .write_done = m10bmc_sec_write_done,
+ .check_complete = m10bmc_sec_check_complete,
+ .cancel = m10bmc_sec_cancel,
+ .get_hw_errinfo = m10bmc_sec_hw_errinfo,
+ .image_load = pmci_image_load_hndlrs,
+};
+
+static const struct fpga_power_on pmci_power_on_image = {
+ .avail_image_mask = BIT(FPGA_FACTORY) |
+ BIT(FPGA_USER1) | BIT(FPGA_USER2),
+ .set_sequence = pmci_set_power_on_image,
+ .get_sequence = pmci_get_power_on_image,
};
int init_sec_mgr(struct ifpga_fme_hw *fme, enum fpga_sec_type type)
@@ -610,19 +1126,25 @@ int init_sec_mgr(struct ifpga_fme_hw *fme, enum fpga_sec_type type)
smgr->rsu_status = NULL;
}
- if (hw && (hw->pci_data->device_id == IFPGA_N3000_DID) &&
- (hw->pci_data->vendor_id == IFPGA_N3000_VID)) {
- smgr->ops = &n3000_sec_ops;
- smgr->copy_speed = IFPGA_N3000_COPY_SPEED;
- } else {
- dev_err(NULL, "No operation for security manager\n");
- smgr->ops = NULL;
- }
-
smgr->fme = fme;
smgr->max10_dev = fme->max10_dev;
smgr->type = type;
+ switch (type) {
+ case N3000BMC_SEC:
+ smgr->sops = &n3000_sec_ops;
+ smgr->copy_speed = IFPGA_N3000_COPY_SPEED;
+ break;
+ case N6000BMC_SEC:
+ smgr->sops = &pmci_sec_ops;
+ smgr->copy_speed = IFPGA_N3000_COPY_SPEED;
+ smgr->poc = &pmci_power_on_image;
+ break;
+ default:
+ dev_err(NULL, "No operation for security manager\n");
+ smgr->sops = NULL;
+ }
+
return 0;
}
diff --git a/drivers/raw/ifpga/base/ifpga_sec_mgr.h b/drivers/raw/ifpga/base/ifpga_sec_mgr.h
index 09cc038..0b2e1ac 100644
--- a/drivers/raw/ifpga/base/ifpga_sec_mgr.h
+++ b/drivers/raw/ifpga/base/ifpga_sec_mgr.h
@@ -25,35 +25,44 @@
#define IFPGA_N3000_COPY_SPEED 42700
/* status */
-#define IFPGA_RSU_IDLE 0
-#define IFPGA_RSU_PREPARE 1
-#define IFPGA_RSU_READY 2
-#define IFPGA_RSU_COPYING 3
-#define IFPGA_RSU_REBOOT 4
+#define IFPGA_RSU_IDLE 0
+#define IFPGA_RSU_PREPARING 1
+#define IFPGA_RSU_WRITING 2
+#define IFPGA_RSU_PROGRAMMING 3
+#define IFPGA_RSU_REBOOT 4
-#define IFPGA_RSU_GET_STAT(v) (((v) >> 16) & 0xffff)
-#define IFPGA_RSU_GET_PROG(v) ((v) & 0xffff)
-#define IFPGA_RSU_STATUS(s, p) ((((s) << 16) & 0xffff0000) | ((p) & 0xffff))
+#define IFPGA_RSU_GET_STAT(v) (((v) >> 16) & 0xff)
+#define IFPGA_RSU_GET_PROG(v) ((v) & 0xff)
+#define IFPGA_RSU_STATUS(s, p) ((((s) << 16) & 0xff0000) | ((p) & 0xff))
/* control */
-#define IFPGA_RSU_ABORT 1
+#define IFPGA_RSU_CANCEL 1
+
+#define IFPGA_HW_ERRINFO_POISON 0xffffffff
#define IFPGA_DUAL_CFG_CTRL0 0x200020
#define IFPGA_DUAL_CFG_CTRL1 0x200024
-#define IFPGA_SEC_START_INTERVAL_MS 100
-#define IFPGA_SEC_START_TIMEOUT_MS 20000
-#define IFPGA_NIOS_HANDSHAKE_INTERVAL_MS 100
-#define IFPGA_NIOS_HANDSHAKE_TIMEOUT_MS 5000
-
-#define IFPGA_RSU_ERR_HW_ERROR -1
-#define IFPGA_RSU_ERR_TIMEOUT -2
-#define IFPGA_RSU_ERR_CANCELED -3
-#define IFPGA_RSU_ERR_BUSY -4
-#define IFPGA_RSU_ERR_INVALID_SIZE -5
-#define IFPGA_RSU_ERR_RW_ERROR -6
-#define IFPGA_RSU_ERR_WEAROUT -7
-#define IFPGA_RSU_ERR_FILE_READ -8
+#define IFPGA_NIOS_HANDSHAKE_INTERVAL_US (100 * 1000)
+#define IFPGA_NIOS_HANDSHAKE_TIMEOUT_US (5000 * 1000)
+/* Wait about 2 minutes to erase flash staging area */
+#define IFPGA_RSU_PREP_INTERVAL_US (100 * 1000)
+#define IFPGA_RSU_PREP_TIMEOUT_US (120000 * 1000)
+
+enum ifpga_sec_err {
+ IFPGA_SEC_ERR_NONE = 0,
+ IFPGA_SEC_ERR_HW_ERROR,
+ IFPGA_SEC_ERR_TIMEOUT,
+ IFPGA_SEC_ERR_CANCELED,
+ IFPGA_SEC_ERR_BUSY,
+ IFPGA_SEC_ERR_INVALID_SIZE,
+ IFPGA_SEC_ERR_RW_ERROR,
+ IFPGA_SEC_ERR_WEAROUT,
+ IFPGA_SEC_ERR_FILE_READ,
+ IFPGA_SEC_ERR_NO_MEM,
+ IFPGA_SEC_ERR_NO_FUNC,
+ IFPGA_SEC_ERR_MAX
+};
/* Supported fpga secure manager types */
enum fpga_sec_type {
@@ -61,32 +70,57 @@ enum fpga_sec_type {
N6000BMC_SEC
};
+/* Supported names for power-on images */
+enum fpga_image {
+ FPGA_FACTORY,
+ FPGA_USER1,
+ FPGA_USER2,
+ FPGA_MAX
+};
+
struct ifpga_sec_mgr;
-struct ifpga_sec_ops {
- int (*prepare)(struct ifpga_sec_mgr *smgr);
- int (*write_blk)(struct ifpga_sec_mgr *smgr, char *buf, uint32_t offset,
- uint32_t size);
- int (*write_done)(struct ifpga_sec_mgr *smgr);
- int (*check_complete)(struct ifpga_sec_mgr *smgr);
- int (*reload)(struct ifpga_sec_mgr *smgr, int type, int page);
- int (*cancel)(struct ifpga_sec_mgr *smgr);
+struct image_load {
+ const char *name;
+ int (*load_image)(struct ifpga_sec_mgr *smgr);
+};
+
+struct fpga_power_on {
+ u32 avail_image_mask;
+ int (*get_sequence)(struct ifpga_sec_mgr *smgr, char *buf,
+ size_t size);
+ int (*set_sequence)(struct ifpga_sec_mgr *smgr,
+ enum fpga_image images[]);
+};
+
+struct ifpga_sec_mgr_ops {
+ enum ifpga_sec_err (*prepare)(struct ifpga_sec_mgr *smgr);
+ enum ifpga_sec_err (*write_blk)(struct ifpga_sec_mgr *smgr,
+ uint32_t offset, uint32_t size);
+ enum ifpga_sec_err (*write_done)(struct ifpga_sec_mgr *smgr);
+ enum ifpga_sec_err (*check_complete)(struct ifpga_sec_mgr *smgr);
+ enum ifpga_sec_err (*cancel)(struct ifpga_sec_mgr *smgr);
void (*cleanup)(struct ifpga_sec_mgr *smgr);
u64 (*get_hw_errinfo)(struct ifpga_sec_mgr *smgr);
+ struct image_load *image_load; /* terminated with { } member */
};
struct ifpga_sec_mgr {
struct ifpga_fme_hw *fme;
struct intel_max10_device *max10_dev;
- unsigned int rsu_length;
- /* number of bytes that copied from staging area to working area
- * in one second, which is calculated by experiment
- */
- unsigned int copy_speed;
- unsigned int *rsu_control;
unsigned int *rsu_status;
- const struct ifpga_sec_ops *ops;
+ unsigned int *rsu_control;
+ unsigned int one_percent; /* use to calculate progress value */
+ unsigned int copy_speed; /* flash copy speed in bytes/second */
+
+ const struct ifpga_sec_mgr_ops *sops;
+ const char *filename;
+ char *data; /* pointer to update data */
+ u32 remaining_size; /* size remaining to transfer */
+ enum ifpga_sec_err err_code;
+ u64 hw_errinfo; /* 64 bits of HW specific error info */
enum fpga_sec_type type;
+ const struct fpga_power_on *poc; /* power on image configuration */
};
int init_sec_mgr(struct ifpga_fme_hw *fme, enum fpga_sec_type type);
@@ -94,7 +128,12 @@ struct ifpga_sec_mgr {
int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,
uint64_t *status);
int fpga_stop_flash_update(struct ifpga_fme_hw *fme, int force);
-int fpga_reload(struct ifpga_fme_hw *fme, int type, int page);
+int fpga_reload(struct ifpga_fme_hw *fme, char *str);
+int fpga_available_images(struct ifpga_fme_hw *fme, char *buf, size_t size);
+int fpga_set_poc_image(struct ifpga_fme_hw *fme, char *buf);
+int fpga_get_poc_images(struct ifpga_fme_hw *fme, char *buf, size_t size);
+int pmci_set_poc_image(struct ifpga_sec_mgr *smgr, char *buf);
+int pmci_get_poc_images(struct ifpga_sec_mgr *smgr, char *buf, size_t size);
#endif /* _IFPGA_FME_RSU_H_ */
diff --git a/drivers/raw/ifpga/base/opae_hw_api.c b/drivers/raw/ifpga/base/opae_hw_api.c
index 6b78094..ada3d29 100644
--- a/drivers/raw/ifpga/base/opae_hw_api.c
+++ b/drivers/raw/ifpga/base/opae_hw_api.c
@@ -1055,18 +1055,94 @@ int opae_mgr_stop_flash_update(struct opae_manager *mgr, int force)
/**
* opae_mgr_reload - reload FPGA.
* @mgr: targeted manager
- * @type: FPGA type
- * @page: reload from which page
+ * @str: name of reload image type
*
* Return: 0 on success, otherwise error code.
*/
-int opae_mgr_reload(struct opae_manager *mgr, int type, int page)
+int opae_mgr_reload(struct opae_manager *mgr, char *str)
{
if (!mgr)
return -EINVAL;
if (mgr->ops && mgr->ops->reload)
- return mgr->ops->reload(mgr, type, page);
+ return mgr->ops->reload(mgr, str);
+
+ return -ENOENT;
+}
+
+/**
+ * opae_mgr_available_images - get available load image types.
+ * @mgr: targeted manager
+ * @buf: buffer to fill with image type list
+ * @size: size of the buffer
+ *
+ * Return: 0 or positive value on success, otherwise error code.
+ */
+int opae_mgr_available_images(struct opae_manager *mgr, char *buf, size_t size)
+{
+ if (!mgr)
+ return -EINVAL;
+
+ if (mgr->ops && mgr->ops->available_images)
+ return mgr->ops->available_images(mgr, buf, size);
+
+ return -ENOENT;
+}
+
+/**
+ * opae_mgr_get_poc_images - get available power_on_images.
+ * @mgr: targeted manager
+ * @buf: buffer to fill with image type list
+ * @size: size of the buffer
+ *
+ * Return: 0 or positive value on success, otherwise error code.
+ */
+int opae_mgr_get_poc_images(struct opae_manager *mgr, char *buf, size_t size)
+{
+ if (!mgr)
+ return -EINVAL;
+
+ if (mgr->ops && mgr->ops->get_poc_images)
+ return mgr->ops->get_poc_images(mgr, buf, size);
+
+ return -ENOENT;
+}
+
+/**
+ * opae_mgr_set_poc_image - configure the FPGA power_on_image.
+ * @mgr: targeted manager
+ * @str: name of power_on_image
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_mgr_set_poc_image(struct opae_manager *mgr, char *str)
+{
+ if (!mgr)
+ return -EINVAL;
+
+ if (mgr->ops && mgr->ops->set_poc_image)
+ return mgr->ops->set_poc_image(mgr, str);
+
+ return -ENOENT;
+}
+
+/**
+ * opae_mgr_read_flash - read flash content
+ * @mgr: targeted manager
+ * @address: the start address of flash
+ * @size: the size of flash
+ * @buf: the read buffer
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_mgr_read_flash(struct opae_manager *mgr, u32 address,
+ u32 size, void *buf)
+{
+ if (!mgr)
+ return -EINVAL;
+
+ if (mgr->ops && mgr->ops->read_flash)
+ return mgr->ops->read_flash(mgr, address, size, buf);
return -ENOENT;
}
diff --git a/drivers/raw/ifpga/base/opae_hw_api.h b/drivers/raw/ifpga/base/opae_hw_api.h
index 8aead4d..1e31d1e 100644
--- a/drivers/raw/ifpga/base/opae_hw_api.h
+++ b/drivers/raw/ifpga/base/opae_hw_api.h
@@ -59,7 +59,13 @@ struct opae_manager_ops {
int (*update_flash)(struct opae_manager *mgr, const char *image,
u64 *status);
int (*stop_flash_update)(struct opae_manager *mgr, int force);
- int (*reload)(struct opae_manager *mgr, int type, int page);
+ int (*reload)(struct opae_manager *mgr, char *str);
+ int (*available_images)(struct opae_manager *mgr, char *buf,
+ size_t size);
+ int (*get_poc_images)(struct opae_manager *mgr, char *buf,
+ size_t size);
+ int (*set_poc_image)(struct opae_manager *mgr, char *str);
+ int (*read_flash)(struct opae_manager *mgr, u32 address, u32 size, void *buf);
};
/* networking management ops in FME */
@@ -368,5 +374,9 @@ int opae_mgr_get_board_info(struct opae_manager *mgr,
int opae_mgr_update_flash(struct opae_manager *mgr, const char *image,
uint64_t *status);
int opae_mgr_stop_flash_update(struct opae_manager *mgr, int force);
-int opae_mgr_reload(struct opae_manager *mgr, int type, int page);
+int opae_mgr_reload(struct opae_manager *mgr, char *str);
+int opae_mgr_available_images(struct opae_manager *mgr, char *buf, size_t size);
+int opae_mgr_set_poc_image(struct opae_manager *mgr, char *str);
+int opae_mgr_get_poc_images(struct opae_manager *mgr, char *buf, size_t size);
+int opae_mgr_read_flash(struct opae_manager *mgr, u32 address, u32 size, void *buf);
#endif /* _OPAE_HW_API_H_*/
diff --git a/drivers/raw/ifpga/rte_pmd_ifpga.c b/drivers/raw/ifpga/rte_pmd_ifpga.c
index 2314643..fda7cae 100644
--- a/drivers/raw/ifpga/rte_pmd_ifpga.c
+++ b/drivers/raw/ifpga/rte_pmd_ifpga.c
@@ -6,6 +6,7 @@
#include <rte_bus_pci.h>
#include <rte_rawdev.h>
#include <rte_rawdev_pmd.h>
+#include "base/opae_hw_api.h"
#include "rte_pmd_ifpga.h"
#include "ifpga_rawdev.h"
#include "base/ifpga_api.h"
@@ -390,16 +391,104 @@
return 0;
}
+static int
+get_image_load_string(struct opae_adapter *adapter, int type, int page,
+ char *str, size_t size)
+{
+ struct opae_adapter_data_pci *pci_data = NULL;
+
+ pci_data = (struct opae_adapter_data_pci *)adapter->data;
+ if (!pci_data || (pci_data->type != OPAE_FPGA_PCI))
+ return -EINVAL;
+
+ if (type == 0) {
+ if (pci_data->device_id == IFPGA_N3000_ID) {
+ if (page == 0)
+ snprintf(str, size, "fpga_factory");
+ else
+ snprintf(str, size, "fpga_user");
+ } else if (pci_data->device_id == IFPGA_N6000_ID) {
+ if (page == 0)
+ snprintf(str, size, "fpga_factory");
+ else if (page == 1)
+ snprintf(str, size, "fpga_user1");
+ else if (page == 2)
+ snprintf(str, size, "fpga_user2");
+ else
+ snprintf(str, size, "sdm");
+ }
+ } else {
+ if (page == 0)
+ snprintf(str, size, "bmc_factory");
+ else
+ snprintf(str, size, "bmc_user");
+ }
+
+ return 0;
+}
+
int
rte_pmd_ifpga_reload(uint16_t dev_id, int type, int page)
{
struct opae_adapter *adapter = NULL;
+ char str[RTE_RAWDEV_NAME_MAX_LEN] = {0};
+
+ adapter = get_opae_adapter(dev_id);
+ if (!adapter)
+ return -ENODEV;
+
+ if (get_image_load_string(adapter, type, page, str, sizeof(str)))
+ return -EINVAL;
+
+ return opae_mgr_reload(adapter->mgr, str);
+}
+
+int
+rte_pmd_ifpga_image_load(uint16_t dev_id, char *str)
+{
+ struct opae_adapter *adapter = NULL;
+
+ adapter = get_opae_adapter(dev_id);
+ if (!adapter)
+ return -ENODEV;
+
+ return opae_mgr_reload(adapter->mgr, str);
+}
+
+int
+rte_pmd_ifpga_get_available_images(uint16_t dev_id, char *buf, size_t size)
+{
+ struct opae_adapter *adapter = NULL;
+
+ adapter = get_opae_adapter(dev_id);
+ if (!adapter)
+ return -ENODEV;
+
+ return opae_mgr_available_images(adapter->mgr, buf, size);
+}
+
+int
+rte_pmd_ifpga_set_poc_image(uint16_t dev_id, char *str)
+{
+ struct opae_adapter *adapter = NULL;
adapter = get_opae_adapter(dev_id);
if (!adapter)
return -ENODEV;
- return opae_mgr_reload(adapter->mgr, type, page);
+ return opae_mgr_set_poc_image(adapter->mgr, str);
+}
+
+int
+rte_pmd_ifpga_get_poc_images(uint16_t dev_id, char *buf, size_t size)
+{
+ struct opae_adapter *adapter = NULL;
+
+ adapter = get_opae_adapter(dev_id);
+ if (!adapter)
+ return -ENODEV;
+
+ return opae_mgr_get_poc_images(adapter->mgr, buf, size);
}
const struct rte_pci_bus *
@@ -422,6 +511,19 @@
return ifpga_rawdev_partial_reconfigure(dev, port, file);
}
+int
+rte_pmd_ifpga_read_flash(uint16_t dev_id, uint32_t address, uint32_t size,
+ void *buf)
+{
+ struct opae_adapter *adapter;
+
+ adapter = get_opae_adapter(dev_id);
+ if (!adapter)
+ return -ENODEV;
+
+ return opae_mgr_read_flash(adapter->mgr, address, size, buf);
+}
+
void
rte_pmd_ifpga_cleanup(void)
{
diff --git a/drivers/raw/ifpga/rte_pmd_ifpga.h b/drivers/raw/ifpga/rte_pmd_ifpga.h
index 3fa5d34..2a6a502 100644
--- a/drivers/raw/ifpga/rte_pmd_ifpga.h
+++ b/drivers/raw/ifpga/rte_pmd_ifpga.h
@@ -21,6 +21,8 @@
#include <stdint.h>
#define IFPGA_MAX_PORT_NUM 4
+#define IFPGA_N3000_ID 0x0B30
+#define IFPGA_N6000_ID 0xBCCE
/**
* UUID data structure.
@@ -216,6 +218,7 @@
* - (-ENODEV) if dev_id is invalid.
* - (-EINVAL) if bad parameter.
* - (-EBUSY) if failed to access BMC register.
+ * - (-EOPNOTSUPP) if the specific image load not supported.
*/
int
rte_pmd_ifpga_reload(uint16_t dev_id, int type, int page);
@@ -253,6 +256,120 @@
void
rte_pmd_ifpga_cleanup(void);
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set which image to load for specified Intel FPGA device at power on
+ *
+ * @param dev_id
+ * The raw device ID of specified Intel FPGA device.
+ * @param str
+ * name of the image to load from flash.
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if dev_id is invalid.
+ * - (-EINVAL) if bad parameter.
+ * - (-EBUSY) if failed to access BMC register.
+ * - (-EOPNOTSUPP) if the specific image load not supported.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_set_poc_image(uint16_t dev_id, char *str);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get available load image supported by specified Intel FPGA device
+ *
+ * @param dev_id
+ * The raw device ID of specified Intel FPGA device.
+ * @param buf
+ * a space separated list of image type name will be filled in this buffer.
+ * buffer pointer can be NULL.
+ * @param size
+ * when buf pointer is not NULL, indicate the size of the buffer.
+ * @return
+ * - (0) no available load image type.
+ * - (>0) string length of the list including the terminating null character.
+ * - (-ENODEV) if dev_id is invalid.
+ * - (-EINVAL) if bad parameter.
+ * - (-EBUSY) if failed to access BMC register.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_get_poc_images(uint16_t dev_id, char *buf, size_t size);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Trigger image load of specified Intel FPGA device
+ *
+ * @param dev_id
+ * The raw device ID of specified Intel FPGA device.
+ * @param str
+ * name of the image to load from flash.
+ * @return
+ * - (0) if successful.
+ * - (-ENODEV) if dev_id is invalid.
+ * - (-EINVAL) if bad parameter.
+ * - (-EBUSY) if failed to access BMC register.
+ * - (-EOPNOTSUPP) if the specific image load not supported.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_image_load(uint16_t dev_id, char *str);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get available load image supported by specified Intel FPGA device
+ *
+ * @param dev_id
+ * The raw device ID of specified Intel FPGA device.
+ * @param buf
+ * a space separated list of image type name will be filled in this buffer.
+ * buffer pointer can be NULL.
+ * @param size
+ * when buf pointer is not NULL, indicate the size of the buffer.
+ * @return
+ * - (0) no available load image type.
+ * - (>0) string length of the list including the terminating null character.
+ * - (-ENODEV) if dev_id is invalid.
+ * - (-EINVAL) if bad parameter.
+ * - (-EBUSY) if failed to access BMC register.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_get_available_images(uint16_t dev_id, char *buf, size_t size);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Read out flash content on specified Intel FPGA device
+ *
+ * @param dev_id
+ * The raw device ID of specified Intel FPGA device.
+ * @param address
+ * The start address of the flash.
+ * @param size
+ * The size of flash which want to read out.
+ * @param buf
+ * The read buffer.
+ * @return
+ * - (0) if successful.
+ * - (-EINVAL) if bad parameter or operation failed.
+ * - (-ENOMEM) if no available flash memory to access.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_read_flash(uint16_t dev_id, uint32_t address, uint32_t size,
+ void *buf);
+
#ifdef __cplusplus
}
#endif
diff --git a/drivers/raw/ifpga/version.map b/drivers/raw/ifpga/version.map
index ff71a45..a201124 100644
--- a/drivers/raw/ifpga/version.map
+++ b/drivers/raw/ifpga/version.map
@@ -16,3 +16,14 @@ DPDK_22 {
local: *;
};
+
+EXPERIMENTAL {
+ global:
+
+ # added in 22.07
+ rte_pmd_ifpga_image_load;
+ rte_pmd_ifpga_get_available_images;
+ rte_pmd_ifpga_set_poc_image;
+ rte_pmd_ifpga_get_poc_images;
+ rte_pmd_ifpga_read_flash;
+};
--
1.8.3.1
next prev parent reply other threads:[~2022-05-25 1:44 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-25 1:51 [PATCH v1 0/2] Update rsu implementation Wei Huang
2022-05-25 1:51 ` [PATCH v1 1/2] raw/ifpga/base: add pmci driver Wei Huang
2022-05-25 1:51 ` Wei Huang [this message]
2022-06-10 2:24 ` [PATCH v2 0/2] update rsu implementation Wei Huang
2022-06-10 2:24 ` [PATCH v2 1/2] raw/ifpga/base: add pmci driver Wei Huang
2022-06-13 7:01 ` Zhang, Tianfei
2022-06-13 7:29 ` Huang, Wei
2022-06-10 2:25 ` [PATCH v2 2/2] raw/ifpga: update secure rsu Wei Huang
2022-06-17 7:19 ` [PATCH v3 0/4] introduce PMCI driver Wei Huang
2022-06-17 7:19 ` [PATCH v3 1/4] raw/ifpga/base: add PMCI base driver Wei Huang
2022-06-17 8:57 ` Zhang, Tianfei
2022-06-17 14:41 ` Xu, Rosen
2022-06-17 7:19 ` [PATCH v3 2/4] raw/ifpga/base: update board information Wei Huang
2022-06-17 8:57 ` Zhang, Tianfei
2022-06-17 14:42 ` Xu, Rosen
2022-06-17 7:19 ` [PATCH v3 3/4] raw/ifpga/base: update flash operation interface Wei Huang
2022-06-17 8:58 ` Zhang, Tianfei
2022-06-17 14:42 ` Xu, Rosen
2022-06-17 7:19 ` [PATCH v3 4/4] raw/ifpga/base: add PMCI sensor driver Wei Huang
2022-06-17 8:58 ` Zhang, Tianfei
2022-06-17 14:43 ` Xu, Rosen
2022-06-20 15:35 ` [PATCH v3 0/4] introduce PMCI driver Thomas Monjalon
2023-09-29 15:31 ` [PATCH v2 0/2] update rsu implementation David Marchand
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=1653443483-30971-3-git-send-email-wei.huang@intel.com \
--to=wei.huang@intel.com \
--cc=dev@dpdk.org \
--cc=hemant.agrawal@nxp.com \
--cc=nipun.gupta@nxp.com \
--cc=qi.z.zhang@intel.com \
--cc=rosen.xu@intel.com \
--cc=stable@dpdk.org \
--cc=thomas@monjalon.net \
--cc=tianfei.zhang@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).