dpdk/drivers/raw/ifpga/base/ifpga_fme_rsu.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2020 Intel Corporation
   3 */
   4
   5#include <fcntl.h>
   6#include <signal.h>
   7#include <unistd.h>
   8#include "ifpga_sec_mgr.h"
   9
  10static struct ifpga_sec_mgr *sec_mgr;
  11
  12static void set_rsu_control(struct ifpga_sec_mgr *smgr, uint32_t ctrl)
  13{
  14        if (smgr && smgr->rsu_control)
  15                *smgr->rsu_control = ctrl;
  16}
  17
  18static uint32_t get_rsu_control(struct ifpga_sec_mgr *smgr)
  19{
  20        if (smgr && smgr->rsu_control)
  21                return *smgr->rsu_control;
  22        return 0;
  23}
  24
  25static void set_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t status,
  26        uint32_t progress)
  27{
  28        if (smgr && smgr->rsu_status)
  29                *smgr->rsu_status = IFPGA_RSU_STATUS(status, progress);
  30}
  31
  32static void get_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t *status,
  33        uint32_t *progress)
  34{
  35        if (smgr && smgr->rsu_status) {
  36                if (status)
  37                        *status = IFPGA_RSU_GET_STAT(*smgr->rsu_status);
  38                if (progress)
  39                        *progress = IFPGA_RSU_GET_PROG(*smgr->rsu_status);
  40        }
  41}
  42
  43static void sig_handler(int sig, siginfo_t *info, void *data)
  44{
  45        (void)(info);
  46        (void)(data);
  47
  48        switch (sig) {
  49        case SIGINT:
  50                if (sec_mgr) {
  51                        dev_info(sec_mgr, "Interrupt secure flash update"
  52                                " by keyboard\n");
  53                        set_rsu_control(sec_mgr, IFPGA_RSU_ABORT);
  54                }
  55                break;
  56        default:
  57                break;
  58        }
  59}
  60
  61static void log_time(time_t t, const char *msg)
  62{
  63        uint32_t h = 0;
  64        uint32_t m = 0;
  65        uint32_t s = 0;
  66
  67        if (t < 60) {
  68                s = (uint32_t)t;
  69        } else if (t < 3600) {
  70                s = (uint32_t)(t % 60);
  71                m = (uint32_t)(t / 60);
  72        } else {
  73                s = (uint32_t)(t % 60);
  74                m = (uint32_t)((t % 3600) / 60);
  75                h = (uint32_t)(t / 3600);
  76        }
  77        printf("%s - %02u:%02u:%02u\n", msg, h, m, s);
  78}
  79
  80static int start_flash_update(struct ifpga_sec_mgr *smgr)
  81{
  82        if (!smgr)
  83                return -ENODEV;
  84
  85        if (!smgr->ops || !smgr->ops->prepare)
  86                return -EINVAL;
  87
  88        return smgr->ops->prepare(smgr);
  89}
  90
  91static int write_flash_image(struct ifpga_sec_mgr *smgr, const char *image,
  92        uint32_t offset)
  93{
  94        void *buf = NULL;
  95        int retry = 0;
  96        uint32_t length = 0;
  97        uint32_t to_transfer = 0;
  98        uint32_t one_percent = 0;
  99        uint32_t prog = 0;
 100        uint32_t old_prog = -1;
 101        ssize_t read_size = 0;
 102        int fd = -1;
 103        int ret = 0;
 104
 105        if (!smgr)
 106                return -ENODEV;
 107
 108        if (!smgr->ops || !smgr->ops->write_blk)
 109                return -EINVAL;
 110
 111        fd = open(image, O_RDONLY);
 112        if (fd < 0) {
 113                dev_err(smgr,
 114                        "Failed to open \'%s\' for RD [e:%s]\n",
 115                        image, strerror(errno));
 116                return -EIO;
 117        }
 118
 119        buf = malloc(IFPGA_RSU_DATA_BLK_SIZE);
 120        if (!buf) {
 121                dev_err(smgr, "Failed to allocate memory for flash update\n");
 122                close(fd);
 123                return -ENOMEM;
 124        }
 125
 126        length = smgr->rsu_length;
 127        one_percent = length / 100;
 128        do {
 129                to_transfer = (length > IFPGA_RSU_DATA_BLK_SIZE) ?
 130                        IFPGA_RSU_DATA_BLK_SIZE : length;
 131                if (lseek(fd, offset, SEEK_SET) < 0) {
 132                        dev_err(smgr, "Failed to seek in \'%s\' [e:%s]\n",
 133                                image, strerror(errno));
 134                        ret = -EIO;
 135                        goto end;
 136                }
 137                read_size = read(fd, buf, to_transfer);
 138                if (read_size < 0) {
 139                        dev_err(smgr, "Failed to read from \'%s\' [e:%s]\n",
 140                                image, strerror(errno));
 141                        ret = -EIO;
 142                        goto end;
 143                }
 144                if ((uint32_t)read_size != to_transfer) {
 145                        dev_err(smgr,
 146                                "Read length %zd is not expected [e:%u]\n",
 147                                read_size, to_transfer);
 148                        ret = -EIO;
 149                        goto end;
 150                }
 151
 152                retry = 0;
 153                do {
 154                        if (get_rsu_control(smgr) == IFPGA_RSU_ABORT) {
 155                                ret = -EAGAIN;
 156                                goto end;
 157                        }
 158                        ret = smgr->ops->write_blk(smgr, buf, offset,
 159                                to_transfer);
 160                        if (ret == 0)
 161                                break;
 162                        sleep(1);
 163                } while (++retry <= IFPGA_RSU_WRITE_RETRY);
 164                if (retry > IFPGA_RSU_WRITE_RETRY) {
 165                        dev_err(smgr, "Failed to write to staging area 0x%x\n",
 166                                offset);
 167                        ret = -EAGAIN;
 168                        goto end;
 169                }
 170
 171                length -= to_transfer;
 172                offset += to_transfer;
 173                prog = offset / one_percent;
 174                if (prog != old_prog) {
 175                        printf("\r%d%%", prog);
 176                        fflush(stdout);
 177                        set_rsu_status(smgr, IFPGA_RSU_READY, prog);
 178                        old_prog = prog;
 179                }
 180        } while (length > 0);
 181        set_rsu_status(smgr, IFPGA_RSU_READY, 100);
 182        printf("\n");
 183
 184end:
 185        free(buf);
 186        close(fd);
 187        return ret;
 188}
 189
 190static int apply_flash_update(struct ifpga_sec_mgr *smgr)
 191{
 192        uint32_t one_percent = 0;
 193        uint32_t one_percent_time = 0;
 194        uint32_t prog = 0;
 195        uint32_t old_prog = -1;
 196        uint32_t copy_time = 0;
 197        int ret = 0;
 198
 199        if (!smgr)
 200                return -ENODEV;
 201
 202        if (!smgr->ops || !smgr->ops->write_done || !smgr->ops->check_complete)
 203                return -EINVAL;
 204
 205        if (smgr->ops->write_done(smgr) < 0) {
 206                dev_err(smgr, "Failed to apply flash update\n");
 207                return -EAGAIN;
 208        }
 209
 210        one_percent = (smgr->rsu_length + 99) / 100;
 211        if (smgr->copy_speed == 0)   /* avoid zero divide fault */
 212                smgr->copy_speed = 1;
 213        one_percent_time = (one_percent + smgr->copy_speed - 1) /
 214                smgr->copy_speed;
 215        if (one_percent_time == 0)   /* avoid zero divide fault */
 216                one_percent_time = 1;
 217
 218        do {
 219                ret = smgr->ops->check_complete(smgr);
 220                if (ret != -EAGAIN)
 221                        break;
 222                sleep(1);
 223                copy_time += 1;
 224                prog = copy_time / one_percent_time;
 225                if (prog >= 100)
 226                        prog = 99;
 227                if (prog != old_prog) {
 228                        printf("\r%d%%", prog);
 229                        fflush(stdout);
 230                        set_rsu_status(smgr, IFPGA_RSU_COPYING, prog);
 231                        old_prog = prog;
 232                }
 233        } while (true);
 234
 235        if (ret < 0) {
 236                printf("\n");
 237                dev_err(smgr, "Failed to complete secure flash update\n");
 238        } else {
 239                printf("\r100%%\n");
 240                set_rsu_status(smgr, IFPGA_RSU_COPYING, 100);
 241        }
 242
 243        return ret;
 244}
 245
 246static int secure_update_cancel(struct ifpga_sec_mgr *smgr)
 247{
 248        if (!smgr)
 249                return -ENODEV;
 250
 251        if (!smgr->ops || !smgr->ops->cancel)
 252                return -EINVAL;
 253
 254        return smgr->ops->cancel(smgr);
 255}
 256
 257static int secure_update_status(struct ifpga_sec_mgr *smgr, uint64_t *status)
 258{
 259        if (!smgr)
 260                return -ENODEV;
 261
 262        if (!smgr->ops || !smgr->ops->get_hw_errinfo)
 263                return -EINVAL;
 264
 265        if (status)
 266                *status = smgr->ops->get_hw_errinfo(smgr);
 267
 268        return 0;
 269}
 270
 271int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,
 272        uint64_t *status)
 273{
 274        struct ifpga_hw *hw = NULL;
 275        struct ifpga_sec_mgr *smgr = NULL;
 276        uint32_t rsu_stat = 0;
 277        int fd = -1;
 278        off_t len = 0;
 279        struct sigaction old_sigint_action;
 280        struct sigaction sa;
 281        time_t start;
 282        int ret = 0;
 283
 284        if (!fme || !image || !status) {
 285                dev_err(fme, "Input parameter of %s is invalid\n", __func__);
 286                return -EINVAL;
 287        }
 288
 289        hw = (struct ifpga_hw *)fme->parent;
 290        if (!hw) {
 291                dev_err(fme, "Parent of FME not found\n");
 292                return -ENODEV;
 293        }
 294
 295        smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
 296        if (!smgr || !smgr->max10_dev) {
 297                dev_err(smgr, "Security manager not initialized\n");
 298                return -ENODEV;
 299        }
 300
 301        opae_adapter_lock(hw->adapter, -1);
 302        get_rsu_status(smgr, &rsu_stat, NULL);
 303        if (rsu_stat != IFPGA_RSU_IDLE) {
 304                opae_adapter_unlock(hw->adapter);
 305                if (rsu_stat == IFPGA_RSU_REBOOT)
 306                        dev_info(smgr, "Reboot is in progress\n");
 307                else
 308                        dev_info(smgr, "Update is in progress\n");
 309                return -EAGAIN;
 310        }
 311        set_rsu_control(smgr, 0);
 312        set_rsu_status(smgr, IFPGA_RSU_PREPARE, 0);
 313        opae_adapter_unlock(hw->adapter);
 314
 315        fd = open(image, O_RDONLY);
 316        if (fd < 0) {
 317                dev_err(smgr,
 318                        "Failed to open \'%s\' for RD [e:%s]\n",
 319                        image, strerror(errno));
 320                return -EIO;
 321        }
 322        len = lseek(fd, 0, SEEK_END);
 323        close(fd);
 324
 325        if (len < 0) {
 326                dev_err(smgr,
 327                        "Failed to get file length of \'%s\' [e:%s]\n",
 328                        image, strerror(errno));
 329                return -EIO;
 330        }
 331        if (len == 0) {
 332                dev_err(smgr, "Length of file \'%s\' is invalid\n", image);
 333                return -EINVAL;
 334        }
 335        smgr->rsu_length = len;
 336
 337        if (smgr->max10_dev->staging_area_size < smgr->rsu_length) {
 338                dev_err(dev, "Size of staging area is small than image length "
 339                        "[%u<%u]\n", smgr->max10_dev->staging_area_size,
 340                        smgr->rsu_length);
 341                return -EINVAL;
 342        }
 343
 344        printf("Updating from file \'%s\' with size %u\n",
 345                image, smgr->rsu_length);
 346
 347        sec_mgr = smgr;
 348        memset(&sa, 0, sizeof(struct sigaction));
 349        sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
 350        sa.sa_sigaction = sig_handler;
 351        ret = sigaction(SIGINT, &sa, &old_sigint_action);
 352        if (ret < 0) {
 353                dev_warn(dev, "Failed to register signal handler"
 354                        " [e:%d]\n", ret);
 355                sec_mgr = NULL;
 356        }
 357
 358        start = time(NULL);
 359        log_time(time(NULL) - start, "Starting secure flash update");
 360        ret = start_flash_update(smgr);
 361        if (ret < 0)
 362                goto end;
 363
 364        set_rsu_status(smgr, IFPGA_RSU_READY, 0);
 365        log_time(time(NULL) - start, "Writing to staging area");
 366        ret = write_flash_image(smgr, image, 0);
 367        if (ret < 0)
 368                goto end;
 369
 370        set_rsu_status(smgr, IFPGA_RSU_COPYING, 0);
 371        log_time(time(NULL) - start, "Applying secure flash update");
 372        ret = apply_flash_update(smgr);
 373
 374end:
 375        if (sec_mgr) {
 376                sec_mgr = NULL;
 377                if (sigaction(SIGINT, &old_sigint_action, NULL) < 0)
 378                        dev_err(smgr, "Failed to unregister signal handler\n");
 379        }
 380
 381        secure_update_status(smgr, status);
 382        if (ret < 0) {
 383                log_time(time(NULL) - start, "Secure flash update ERROR");
 384                if (ret == -EAGAIN)
 385                        secure_update_cancel(smgr);
 386        } else {
 387                log_time(time(NULL) - start, "Secure flash update OK");
 388        }
 389        set_rsu_status(smgr, IFPGA_RSU_IDLE, 0);
 390
 391        return ret;
 392}
 393
 394int fpga_stop_flash_update(struct ifpga_fme_hw *fme, int force)
 395{
 396        struct ifpga_sec_mgr *smgr = NULL;
 397        uint32_t status = 0;
 398        int retry = IFPGA_RSU_CANCEL_RETRY;
 399        int ret = 0;
 400
 401        if (!fme) {
 402                dev_err(fme, "Input parameter of %s is invalid\n", __func__);
 403                return -EINVAL;
 404        }
 405        smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
 406
 407        get_rsu_status(smgr, &status, NULL);
 408        if (status != IFPGA_RSU_IDLE) {
 409                dev_info(smgr, "Cancel secure flash update\n");
 410                set_rsu_control(smgr, IFPGA_RSU_ABORT);
 411        }
 412
 413        if (force) {
 414                sleep(2);
 415                do {
 416                        get_rsu_status(smgr, &status, NULL);
 417                        if (status == IFPGA_RSU_IDLE)
 418                                break;
 419                        if (secure_update_cancel(smgr) == 0)
 420                                set_rsu_status(smgr, IFPGA_RSU_IDLE, 0);
 421                        sleep(1);
 422                } while (--retry > 0);
 423                if (retry <= 0) {
 424                        dev_err(smgr, "Failed to stop flash update\n");
 425                        ret = -EAGAIN;
 426                }
 427        }
 428
 429        return ret;
 430}
 431
 432int fpga_reload(struct ifpga_fme_hw *fme, int type, int page)
 433{
 434        struct ifpga_sec_mgr *smgr = NULL;
 435
 436        if (!fme) {
 437                dev_err(fme, "Input parameter of %s is invalid\n", __func__);
 438                return -EINVAL;
 439        }
 440        smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
 441
 442        if (!smgr || !smgr->ops || !smgr->ops->reload)
 443                return -EINVAL;
 444
 445        return smgr->ops->reload(smgr, type, page);
 446}
 447