[dpdk-dev] [PATCH v18 13/19] raw/ifpga/base: add secure support
Zhang, Tianfei
tianfei.zhang at intel.com
Fri Nov 15 13:40:39 CET 2019
> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Friday, November 15, 2019 5:54 PM
> To: Zhang, Tianfei <tianfei.zhang at intel.com>; Xu, Rosen <rosen.xu at intel.com>;
> dev at dpdk.org
> Cc: Pei, Andy <andy.pei at intel.com>; Ye, Xiaolong <xiaolong.ye at intel.com>
> Subject: Re: [PATCH v18 13/19] raw/ifpga/base: add secure support
>
> On 11/14/2019 11:05 PM, Zhang, Tianfei wrote:
> >
> >> -----Original Message-----
> >> From: Xu, Rosen
> >> Sent: Thursday, November 14, 2019 5:03 PM
> >> To: dev at dpdk.org
> >> Cc: Xu, Rosen <rosen.xu at intel.com>; Zhang, Tianfei
> >> <tianfei.zhang at intel.com>; Pei, Andy <andy.pei at intel.com>; Ye,
> >> Xiaolong <xiaolong.ye at intel.com>; Yigit, Ferruh
> >> <ferruh.yigit at intel.com>
> >> Subject: [PATCH v18 13/19] raw/ifpga/base: add secure support
> >>
> >> From: Tianfei zhang <tianfei.zhang at intel.com>
> >>
> >> Add secure max10 device support.
> >
> > In PAC N3000 Card, it implements the secure functionality on the MAX10
> Board Management Controller (BMC) as Root of Trust (RoT). It changes to
> MAX10 (RTL and Nios FW) to enable secure RSU (Remote System Update)
> authentication and integrity checks for FPGA Flat image, and FW updates to the
> card. The card's BMC continues to support features such as power sequence
> management, board monitoring via sensors, JTAG management and in-band SPI
> interface access. The external Flash on the card shall be programmed with the
> Intel root public key hash (for BMC images and FW) and Customer/User key (for
> FPGA Flat image) during manufacturing, so the image updates (RSU) shall be
> verified using ECDSA-256 P-256 and SHA2-256 before being written to the
> MAX10 Image Flash or FPGA Image Flash.
> >
> > This patch add RoT support for MAX10 because some registers and the content
> of Device Tree have changed between RoT solution and Non-RoT solution.
>
> Thanks Tianfei for the additional information, I will update commit as following,
> please let me know if you have any objection:
>
> raw/ifpga/base: support max10 security feature
>
> In PAC N3000 Card, MAX10 Board Management Controller (BMC) implements
> the security functionality.
>
> Security functionality adds secure Remote System Update (RSU) authentication
> and integrity checks for FPGA flat image, and FW updates to the card.
>
> This patch adds security feature support for MAX10, in secure solution some
> registers and the content of the Device Tree changes.
It looks good for me, thanks a lot!
>
> >
> >
> >>
> >> Signed-off-by: Tianfei zhang <tianfei.zhang at intel.com>
> >> Signed-off-by: Andy Pei <andy.pei at intel.com>
> >> ---
> >> drivers/raw/ifpga/base/ifpga_defines.h | 2 +
> >> drivers/raw/ifpga/base/ifpga_fme.c | 26 ++++--
> >> drivers/raw/ifpga/base/opae_intel_max10.c | 137
> >> +++++++++++++++++++++++++-----
> >> drivers/raw/ifpga/base/opae_intel_max10.h | 80 ++++++++++++-----
> >> 4 files changed, 198 insertions(+), 47 deletions(-)
> >>
> >> diff --git a/drivers/raw/ifpga/base/ifpga_defines.h
> >> b/drivers/raw/ifpga/base/ifpga_defines.h
> >> index 8993cc6..1e84b15 100644
> >> --- a/drivers/raw/ifpga/base/ifpga_defines.h
> >> +++ b/drivers/raw/ifpga/base/ifpga_defines.h
> >> @@ -1698,6 +1698,8 @@ struct ifpga_fme_board_info {
> >> u32 patch_version;
> >> u32 minor_version;
> >> u32 major_version;
> >> + u32 max10_version;
> >> + u32 nios_fw_version;
> >> u32 nums_of_retimer;
> >> u32 ports_per_retimer;
> >> u32 nums_of_fvl;
> >> diff --git a/drivers/raw/ifpga/base/ifpga_fme.c
> >> b/drivers/raw/ifpga/base/ifpga_fme.c
> >> index 794ca09..87fa596 100644
> >> --- a/drivers/raw/ifpga/base/ifpga_fme.c
> >> +++ b/drivers/raw/ifpga/base/ifpga_fme.c
> >> @@ -825,6 +825,7 @@ static int board_type_to_info(u32 type, static
> >> int fme_get_board_interface(struct ifpga_fme_hw *fme) {
> >> struct fme_bitstream_id id;
> >> + u32 val;
> >>
> >> if (fme_hdr_get_bitstream_id(fme, &id.id))
> >> return -EINVAL;
> >> @@ -850,6 +851,18 @@ static int fme_get_board_interface(struct
> >> ifpga_fme_hw *fme)
> >> fme->board_info.nums_of_fvl,
> >> fme->board_info.ports_per_fvl);
> >>
> >> + if (max10_sys_read(MAX10_BUILD_VER, &val))
> >> + return -EINVAL;
> >> + fme->board_info.max10_version = val & 0xffffff;
> >> +
> >> + if (max10_sys_read(NIOS2_FW_VERSION, &val))
> >> + return -EINVAL;
> >> + fme->board_info.nios_fw_version = val & 0xffffff;
> >> +
> >> + dev_info(fme, "max10 version 0x%x, nios fw version 0x%x\n",
> >> + fme->board_info.max10_version,
> >> + fme->board_info.nios_fw_version);
> >> +
> >> return 0;
> >> }
> >>
> >> @@ -858,16 +871,11 @@ static int spi_self_checking(void)
> >> u32 val;
> >> int ret;
> >>
> >> - ret = max10_reg_read(0x30043c, &val);
> >> + ret = max10_sys_read(MAX10_TEST_REG, &val);
> >> if (ret)
> >> return -EIO;
> >>
> >> - if (val != 0x87654321) {
> >> - dev_err(NULL, "Read MAX10 test register fail: 0x%x\n", val);
> >> - return -EIO;
> >> - }
> >> -
> >> - dev_info(NULL, "Read MAX10 test register success, SPI self-test done\n");
> >> + dev_info(NULL, "Read MAX10 test register 0x%x\n", val);
> >>
> >> return 0;
> >> }
> >> @@ -1283,7 +1291,7 @@ int fme_mgr_get_retimer_status(struct
> >> ifpga_fme_hw *fme,
> >> if (!dev)
> >> return -ENODEV;
> >>
> >> - if (max10_reg_read(PKVL_LINK_STATUS, &val)) {
> >> + if (max10_sys_read(PKVL_LINK_STATUS, &val)) {
> >> dev_err(dev, "%s: read pkvl status fail\n", __func__);
> >> return -EINVAL;
> >> }
> >> @@ -1311,7 +1319,7 @@ int fme_mgr_get_sensor_value(struct
> >> ifpga_fme_hw *fme,
> >> if (!dev)
> >> return -ENODEV;
> >>
> >> - if (max10_reg_read(sensor->value_reg, value)) {
> >> + if (max10_sys_read(sensor->value_reg, value)) {
> >> dev_err(dev, "%s: read sensor value register 0x%x fail\n",
> >> __func__, sensor->value_reg);
> >> return -EINVAL;
> >> diff --git a/drivers/raw/ifpga/base/opae_intel_max10.c
> >> b/drivers/raw/ifpga/base/opae_intel_max10.c
> >> index ae7a8df..748ab56 100644
> >> --- a/drivers/raw/ifpga/base/opae_intel_max10.c
> >> +++ b/drivers/raw/ifpga/base/opae_intel_max10.c
> >> @@ -30,6 +30,22 @@ int max10_reg_write(unsigned int reg, unsigned int
> val)
> >> reg, 4, (unsigned char *)&tmp);
> >> }
> >>
> >> +int max10_sys_read(unsigned int offset, unsigned int *val) {
> >> + if (!g_max10)
> >> + return -ENODEV;
> >> +
> >> + return max10_reg_read(g_max10->base + offset, val); }
> >> +
> >> +int max10_sys_write(unsigned int offset, unsigned int val) {
> >> + if (!g_max10)
> >> + return -ENODEV;
> >> +
> >> + return max10_reg_write(g_max10->base + offset, val); }
> >> +
> >> static struct max10_compatible_id max10_id_table[] = {
> >> {.compatible = MAX10_PAC,},
> >> {.compatible = MAX10_PAC_N3000,},
> >> @@ -66,7 +82,8 @@ static void max10_check_capability(struct
> >> intel_max10_device *max10)
> >> max10->flags |= MAX10_FLAGS_NO_I2C2 |
> >> MAX10_FLAGS_NO_BMCIMG_FLASH;
> >> dev_info(max10, "found %s card\n", max10->id->compatible);
> >> - }
> >> + } else
> >> + max10->flags |= MAX10_FLAGS_MAC_CACHE;
> >> }
> >>
> >> static int altera_nor_flash_read(u32 offset, @@ -100,7 +117,7 @@
> >> static int enable_nor_flash(bool on)
> >> unsigned int val = 0;
> >> int ret;
> >>
> >> - ret = max10_reg_read(RSU_REG_OFF, &val);
> >> + ret = max10_sys_read(RSU_REG, &val);
> >> if (ret) {
> >> dev_err(NULL "enabling flash error\n");
> >> return ret;
> >> @@ -111,7 +128,7 @@ static int enable_nor_flash(bool on)
> >> else
> >> val &= ~RSU_ENABLE;
> >>
> >> - return max10_reg_write(RSU_REG_OFF, val);
> >> + return max10_sys_write(RSU_REG, val);
> >> }
> >>
> >> static int init_max10_device_table(struct intel_max10_device *max10)
> >> @@
> >> -123,7 +140,7 @@ static int init_max10_device_table(struct
> >> intel_max10_device *max10)
> >> u32 dt_size, dt_addr, val;
> >> int ret;
> >>
> >> - ret = max10_reg_read(DT_AVAIL_REG_OFF, &val);
> >> + ret = max10_sys_read(DT_AVAIL_REG, &val);
> >> if (ret) {
> >> dev_err(max10 "cannot read DT_AVAIL_REG\n");
> >> return ret;
> >> @@ -134,7 +151,7 @@ static int init_max10_device_table(struct
> >> intel_max10_device *max10)
> >> return -EINVAL;
> >> }
> >>
> >> - ret = max10_reg_read(DT_BASE_ADDR_REG_OFF, &dt_addr);
> >> + ret = max10_sys_read(DT_BASE_ADDR_REG, &dt_addr);
> >> if (ret) {
> >> dev_info(max10 "cannot get base addr of device table\n");
> >> return ret;
> >> @@ -315,7 +332,7 @@ static int max10_add_sensor(struct
> >> raw_sensor_info *info,
> >> if (!sensor_reg_valid(&info->regs[i]))
> >> continue;
> >>
> >> - ret = max10_reg_read(info->regs[i].regoff, &val);
> >> + ret = max10_sys_read(info->regs[i].regoff, &val);
> >> if (ret)
> >> break;
> >>
> >> @@ -355,7 +372,8 @@ static int max10_add_sensor(struct
> >> raw_sensor_info *info,
> >> return ret;
> >> }
> >>
> >> -static int max10_sensor_init(struct intel_max10_device *dev)
> >> +static int
> >> +max10_sensor_init(struct intel_max10_device *dev, int parent)
> >> {
> >> int i, ret = 0, offset = 0;
> >> const fdt32_t *num;
> >> @@ -370,7 +388,7 @@ static int max10_sensor_init(struct
> >> intel_max10_device
> >> *dev)
> >> return 0;
> >> }
> >>
> >> - fdt_for_each_subnode(offset, fdt_root, 0) {
> >> + fdt_for_each_subnode(offset, fdt_root, parent) {
> >> ptr = fdt_get_name(fdt_root, offset, NULL);
> >> if (!ptr) {
> >> dev_err(dev, "failed to fdt get name\n"); @@ -417,7
> +435,16 @@
> >> static int max10_sensor_init(struct intel_max10_device *dev)
> >> continue;
> >> }
> >>
> >> - raw->regs[i].regoff = start;
> >> + /* This is a hack to compatible with non-secure
> >> + * solution. If sensors are included in root node,
> >> + * then it's non-secure dtb, which use absolute addr
> >> + * of non-secure solution.
> >> + */
> >> + if (parent)
> >> + raw->regs[i].regoff = start;
> >> + else
> >> + raw->regs[i].regoff = start -
> >> + MAX10_BASE_ADDR;
> >> raw->regs[i].size = size;
> >> }
> >>
> >> @@ -469,6 +496,63 @@ static int max10_sensor_init(struct
> >> intel_max10_device *dev)
> >> return ret;
> >> }
> >>
> >> +static int check_max10_version(struct intel_max10_device *dev) {
> >> + unsigned int v;
> >> +
> >> + if (!max10_reg_read(MAX10_SEC_BASE_ADDR + MAX10_BUILD_VER,
> >> + &v)) {
> >> + if (v != 0xffffffff) {
> >> + dev_info(dev, "secure MAX10 detected\n");
> >> + dev->base = MAX10_SEC_BASE_ADDR;
> >> + dev->flags |= MAX10_FLAGS_SECURE;
> >> + } else {
> >> + dev_info(dev, "non-secure MAX10 detected\n");
> >> + dev->base = MAX10_BASE_ADDR;
> >> + }
> >> + return 0;
> >> + }
> >> +
> >> + return -ENODEV;
> >> +}
> >> +
> >> +static int
> >> +max10_secure_hw_init(struct intel_max10_device *dev) {
> >> + int offset, sysmgr_offset = 0;
> >> + char *fdt_root;
> >> +
> >> + fdt_root = dev->fdt_root;
> >> + if (!fdt_root) {
> >> + dev_debug(dev, "skip init as not find Device Tree\n");
> >> + return 0;
> >> + }
> >> +
> >> + fdt_for_each_subnode(offset, fdt_root, 0) {
> >> + if (!fdt_node_check_compatible(fdt_root, offset,
> >> + "intel-max10,system-manager")) {
> >> + sysmgr_offset = offset;
> >> + break;
> >> + }
> >> + }
> >> +
> >> + max10_check_capability(dev);
> >> +
> >> + max10_sensor_init(dev, sysmgr_offset);
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static int
> >> +max10_non_secure_hw_init(struct intel_max10_device *dev) {
> >> + max10_check_capability(dev);
> >> +
> >> + max10_sensor_init(dev, 0);
> >> +
> >> + return 0;
> >> +}
> >> +
> >> struct intel_max10_device *
> >> intel_max10_device_probe(struct altera_spi_device *spi,
> >> int chipselect)
> >> @@ -492,32 +576,47 @@ struct intel_max10_device *
> >> /* set the max10 device firstly */
> >> g_max10 = dev;
> >>
> >> - /* init the MAX10 device table */
> >> + /* check the max10 version */
> >> + ret = check_max10_version(dev);
> >> + if (ret) {
> >> + dev_err(dev, "Failed to find max10 hardware!\n");
> >> + goto free_dev;
> >> + }
> >> +
> >> + /* load the MAX10 device table */
> >> ret = init_max10_device_table(dev);
> >> if (ret) {
> >> - dev_err(dev, "init max10 device table fail\n");
> >> + dev_err(dev, "Init max10 device table fail\n");
> >> goto free_dev;
> >> }
> >>
> >> - max10_check_capability(dev);
> >> + /* init max10 devices, like sensor*/
> >> + if (dev->flags & MAX10_FLAGS_SECURE)
> >> + ret = max10_secure_hw_init(dev);
> >> + else
> >> + ret = max10_non_secure_hw_init(dev);
> >> + if (ret) {
> >> + dev_err(dev, "Failed to init max10 hardware!\n");
> >> + goto free_dtb;
> >> + }
> >>
> >> /* read FPGA loading information */
> >> - ret = max10_reg_read(FPGA_PAGE_INFO_OFF, &val);
> >> + ret = max10_sys_read(FPGA_PAGE_INFO, &val);
> >> if (ret) {
> >> dev_err(dev, "fail to get FPGA loading info\n");
> >> - goto spi_tran_fail;
> >> + goto release_max10_hw;
> >> }
> >> dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" :
> >> "Factory");
> >>
> >> -
> >> - max10_sensor_init(dev);
> >> -
> >> return dev;
> >>
> >> -spi_tran_fail:
> >> +release_max10_hw:
> >> + max10_sensor_uinit();
> >> +free_dtb:
> >> if (dev->fdt_root)
> >> opae_free(dev->fdt_root);
> >> - spi_transaction_remove(dev->spi_tran_dev);
> >> + if (dev->spi_tran_dev)
> >> + spi_transaction_remove(dev->spi_tran_dev);
> >> free_dev:
> >> g_max10 = NULL;
> >> opae_free(dev);
> >> diff --git a/drivers/raw/ifpga/base/opae_intel_max10.h
> >> b/drivers/raw/ifpga/base/opae_intel_max10.h
> >> index 90bf098..e632941 100644
> >> --- a/drivers/raw/ifpga/base/opae_intel_max10.h
> >> +++ b/drivers/raw/ifpga/base/opae_intel_max10.h
> >> @@ -23,6 +23,8 @@ struct max10_compatible_id {
> >> #define MAX10_FLAGS_SPI BIT(3)
> >> #define MAX10_FLGAS_NIOS_SPI BIT(4)
> >> #define MAX10_FLAGS_PKVL BIT(5)
> >> +#define MAX10_FLAGS_SECURE BIT(6)
> >> +#define MAX10_FLAGS_MAC_CACHE BIT(7)
> >>
> >> struct intel_max10_device {
> >> unsigned int flags; /*max10 hardware capability*/ @@ -30,6 +32,7
> @@
> >> struct intel_max10_device {
> >> struct spi_transaction_dev *spi_tran_dev;
> >> struct max10_compatible_id *id; /*max10 compatible*/
> >> char *fdt_root;
> >> + unsigned int base; /* max10 base address */
> >> };
> >>
> >> /* retimer speed */
> >> @@ -74,30 +77,69 @@ struct opae_retimer_status { #define FLASH_BASE
> >> 0x10000000 #define FLASH_OPTION_BITS 0x10000
> >>
> >> -#define NIOS2_FW_VERSION_OFF 0x300400
> >> -#define RSU_REG_OFF 0x30042c
> >> -#define FPGA_RP_LOAD BIT(3)
> >> -#define NIOS2_PRERESET BIT(4)
> >> -#define NIOS2_HANG BIT(5)
> >> -#define RSU_ENABLE BIT(6)
> >> -#define NIOS2_RESET BIT(7)
> >> -#define NIOS2_I2C2_POLL_STOP BIT(13)
> >> -#define FPGA_RECONF_REG_OFF 0x300430
> >> -#define COUNTDOWN_START BIT(18)
> >> -#define MAX10_BUILD_VER_OFF 0x300468
> >> -#define PCB_INFO GENMASK(31, 24)
> >> -#define MAX10_BUILD_VERION GENMASK(23, 0)
> >> -#define FPGA_PAGE_INFO_OFF 0x30046c
> >> -#define DT_AVAIL_REG_OFF 0x300490
> >> -#define DT_AVAIL BIT(0)
> >> -#define DT_BASE_ADDR_REG_OFF 0x300494
> >> -#define PKVL_POLLING_CTRL 0x300480
> >> -#define PKVL_LINK_STATUS 0x300564
> >> +/* System Registers */
> >> +#define MAX10_BASE_ADDR 0x300400
> >> +#define MAX10_SEC_BASE_ADDR 0x300800
> >> +/* Register offset of system registers */
> >> +#define NIOS2_FW_VERSION 0x0
> >> +#define MAX10_MACADDR1 0x10
> >> +#define MAX10_MAC_BYTE4 GENMASK(7, 0)
> >> +#define MAX10_MAC_BYTE3 GENMASK(15, 8)
> >> +#define MAX10_MAC_BYTE2 GENMASK(23, 16)
> >> +#define MAX10_MAC_BYTE1 GENMASK(31, 24)
> >> +#define MAX10_MACADDR2 0x14
> >> +#define MAX10_MAC_BYTE6 GENMASK(7, 0)
> >> +#define MAX10_MAC_BYTE5 GENMASK(15, 8)
> >> +#define MAX10_MAC_COUNT GENMASK(23, 16)
> >> +#define RSU_REG 0x2c
> >> +#define FPGA_RECONF_PAGE GENMASK(2, 0)
> >> +#define FPGA_RP_LOAD BIT(3)
> >> +#define NIOS2_PRERESET BIT(4)
> >> +#define NIOS2_HANG BIT(5)
> >> +#define RSU_ENABLE BIT(6)
> >> +#define NIOS2_RESET BIT(7)
> >> +#define NIOS2_I2C2_POLL_STOP BIT(13)
> >> +#define PKVL_EEPROM_LOAD BIT(31)
> >> +#define FPGA_RECONF_REG 0x30
> >> +#define MAX10_TEST_REG 0x3c
> >> +#define COUNTDOWN_START BIT(18)
> >> +#define MAX10_BUILD_VER 0x68
> >> +#define MAX10_VERSION_MAJOR GENMASK(23, 16)
> >> +#define PCB_INFO GENMASK(31, 24)
> >> +#define FPGA_PAGE_INFO 0x6c
> >> +#define DT_AVAIL_REG 0x90
> >> +#define DT_AVAIL BIT(0)
> >> +#define DT_BASE_ADDR_REG 0x94
> >> +#define MAX10_DOORBELL 0x400
> >> +#define RSU_REQUEST BIT(0)
> >> +#define SEC_PROGRESS GENMASK(7, 4)
> >> +#define HOST_STATUS GENMASK(11, 8)
> >> +#define SEC_STATUS GENMASK(23, 16)
> >> +
> >> +/* PKVL related registers, in system register region */
> >> +#define PKVL_POLLING_CTRL 0x80
> >> +#define POLLING_MODE GENMASK(15, 0)
> >> +#define PKVL_A_PRELOAD BIT(16)
> >> +#define PKVL_A_PRELOAD_TIMEOUT BIT(17)
> >> +#define PKVL_A_DATA_TOO_BIG BIT(18)
> >> +#define PKVL_A_HDR_CHECKSUM BIT(20)
> >> +#define PKVL_B_PRELOAD BIT(24)
> >> +#define PKVL_B_PRELOAD_TIMEOUT BIT(25)
> >> +#define PKVL_B_DATA_TOO_BIG BIT(26)
> >> +#define PKVL_B_HDR_CHECKSUM BIT(28)
> >> +#define PKVL_EEPROM_UPG_STATUS GENMASK(31, 16)
> >> +#define PKVL_LINK_STATUS 0x164
> >> +#define PKVL_A_VERSION 0x254
> >> +#define PKVL_B_VERSION 0x258
> >> +#define SERDES_VERSION GENMASK(15, 0)
> >> +#define SBUS_VERSION GENMASK(31, 16)
> >>
> >> #define DFT_MAX_SIZE 0x7e0000
> >>
> >> int max10_reg_read(unsigned int reg, unsigned int *val); int
> >> max10_reg_write(unsigned int reg, unsigned int val);
> >> +int max10_sys_read(unsigned int offset, unsigned int *val); int
> >> +max10_sys_write(unsigned int offset, unsigned int val);
> >> struct intel_max10_device *
> >> intel_max10_device_probe(struct altera_spi_device *spi,
> >> int chipselect);
> >> --
> >> 1.8.3.1
> >
More information about the dev
mailing list