Update secure RSU (Remote System Update) driver to adapt the changes
introduced by OFS.

Signed-off-by: Wei Huang <wei.hu...@intel.com>
Acked-by: Tianfei Zhang <tianfei.zh...@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, &reg_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

Reply via email to