[PATCH v11 5/7] fpga: sec-mgr: expose sec-mgr update size

2021-04-12 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an update/remaining_size sysfs node that can be read to
determine how much data remains to be transferred to the
secure update engine. This file can be used to monitor
progress during the "writing" phase of an update.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v11:
  - No change
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the remaining_size_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: imgr -> smgr, ifpga_ to fpga_
v3:
  - No change
v2:
  - Bumped documentation date and version
---
 Documentation/ABI/testing/sysfs-class-fpga-sec-mgr | 11 +++
 drivers/fpga/fpga-sec-mgr.c| 10 ++
 2 files changed, 21 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 77738577b2c3..2e1f60edf546 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -28,6 +28,17 @@ Description: Read-only. Returns a string describing the 
current
as it will be signaled by sysfs_notify() on each
state change.
 
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/remaining_size
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read-only. Returns the size of data that remains to
+   be written to the secure update engine. The size
+   value is initialized to the full size of the file
+   image and the value is updated periodically during
+   the "writing" phase of the update.
+   Format: "%u".
+
 What:  /sys/class/fpga_sec_mgr/fpga_secX/update/error
 Date:  April 2021
 KernelVersion:  5.13
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 1b827bf196d5..15bf19f9e83b 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -204,6 +204,15 @@ error_show(struct device *dev, struct device_attribute 
*attr, char *buf)
 }
 static DEVICE_ATTR_RO(error);
 
+static ssize_t remaining_size_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
+
+   return sysfs_emit(buf, "%u\n", smgr->remaining_size);
+}
+static DEVICE_ATTR_RO(remaining_size);
+
 static ssize_t filename_store(struct device *dev, struct device_attribute 
*attr,
  const char *buf, size_t count)
 {
@@ -240,6 +249,7 @@ static struct attribute *sec_mgr_update_attrs[] = {
_attr_filename.attr,
_attr_status.attr,
_attr_error.attr,
+   _attr_remaining_size.attr,
NULL,
 };
 
-- 
2.25.1



[PATCH v11 7/7] fpga: sec-mgr: expose hardware error info

2021-04-12 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an optional update/hw_errinfo sysfs node that can be used
to retrieve 64 bits of device specific error information
following a secure update failure.

The underlying driver must provide a get_hw_errinfo() callback
function to enable this feature. This data is treated as
opaque by the class driver. It is left to user-space software
or support personnel to interpret this data.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v11:
  - No change
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - No change
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - No change
v2:
  - Bumped documentation date and version
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 14 +++
 drivers/fpga/fpga-sec-mgr.c   | 38 +++
 include/linux/fpga/fpga-sec-mgr.h |  5 +++
 3 files changed, 57 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index fba3066e2b69..ff1458701def 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -65,3 +65,17 @@ Description: Read-only. Returns a string describing the 
failure
idle state. If this file is read while a secure
update is in progress, then the read will fail with
EBUSY.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/hw_errinfo
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read-only. Returns a 64 bit error value providing
+   hardware specific information that may be useful in
+   debugging errors that occur during FPGA image updates.
+   This file is only visible if the underlying device
+   supports it. The hw_errinfo value is only accessible
+   when the secure update engine is in the idle state.
+   If this file is read while a secure update is in
+   progress, then the read will fail with EBUSY.
+   Format: "0x%llx".
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 215631b40381..1bec6f1173ab 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -38,10 +38,17 @@ static void set_error(struct fpga_sec_mgr *smgr, enum 
fpga_sec_err err_code)
smgr->err_code = err_code;
 }
 
+static void set_hw_errinfo(struct fpga_sec_mgr *smgr)
+{
+   if (smgr->sops->get_hw_errinfo)
+   smgr->hw_errinfo = smgr->sops->get_hw_errinfo(smgr);
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
set_error(smgr, err_code);
+   set_hw_errinfo(smgr);
smgr->sops->cancel(smgr);
 }
 
@@ -227,6 +234,23 @@ error_show(struct device *dev, struct device_attribute 
*attr, char *buf)
 }
 static DEVICE_ATTR_RO(error);
 
+static ssize_t
+hw_errinfo_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
+   int ret;
+
+   mutex_lock(>lock);
+   if (smgr->progress != FPGA_SEC_PROG_IDLE)
+   ret = -EBUSY;
+   else
+   ret = sysfs_emit(buf, "0x%llx\n", smgr->hw_errinfo);
+   mutex_unlock(>lock);
+
+   return ret;
+}
+static DEVICE_ATTR_RO(hw_errinfo);
+
 static ssize_t remaining_size_show(struct device *dev,
   struct device_attribute *attr, char *buf)
 {
@@ -258,6 +282,7 @@ static ssize_t filename_store(struct device *dev, struct 
device_attribute *attr,
}
 
smgr->err_code = FPGA_SEC_ERR_NONE;
+   smgr->hw_errinfo = 0;
smgr->request_cancel = false;
smgr->progress = FPGA_SEC_PROG_READING;
reinit_completion(>update_done);
@@ -292,18 +317,31 @@ static ssize_t cancel_store(struct device *dev, struct 
device_attribute *attr,
 }
 static DEVICE_ATTR_WO(cancel);
 
+static umode_t
+sec_mgr_update_visible(struct kobject *kobj, struct attribute *attr, int n)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(kobj_to_dev(kobj));
+
+   if (attr == _attr_hw_errinfo.attr && !smgr->sops->get_hw_errinfo)
+   return 0;
+
+   return attr->mode;
+}
+
 static struct attribute *sec_mgr_update_attrs[] = {
_attr_filename.attr,
_attr_cancel.attr,
_attr_status.attr,
_attr_error.attr,
_attr_remain

[PATCH v11 6/7] fpga: sec-mgr: enable cancel of secure update

2021-04-12 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an update/cancel sysfs file that can be written to request
that an update be canceled. The write may return EBUSY if
the update has progressed to the point that it cannot be
canceled by software or ENODEV if there is no update in
progress.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v11:
  - No change
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - No change
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - No change
v2:
  - Bumped documentation date and version
  - Minor code cleanup per review comments 
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 10 
 drivers/fpga/fpga-sec-mgr.c   | 59 +--
 include/linux/fpga/fpga-sec-mgr.h |  1 +
 3 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 2e1f60edf546..fba3066e2b69 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -17,6 +17,16 @@ Description: Write only. Write the filename of an image
and Root Entry Hashes, and to cancel Code Signing
Keys (CSK).
 
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/cancel
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Write-only. Write a "1" to this file to request
+   that a current update be canceled. This request
+   will be rejected (EBUSY) if the programming phase
+   has already started or (ENODEV) if there is no
+   update in progress.
+
 What:  /sys/class/fpga_sec_mgr/fpga_secX/update/status
 Date:  April 2021
 KernelVersion:  5.13
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 15bf19f9e83b..215631b40381 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -45,6 +45,23 @@ static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
smgr->sops->cancel(smgr);
 }
 
+static int progress_transition(struct fpga_sec_mgr *smgr,
+  enum fpga_sec_prog new_progress)
+{
+   int ret = 0;
+
+   mutex_lock(>lock);
+   if (smgr->request_cancel) {
+   set_error(smgr, FPGA_SEC_ERR_CANCELED);
+   smgr->sops->cancel(smgr);
+   ret = -ECANCELED;
+   } else {
+   update_progress(smgr, new_progress);
+   }
+   mutex_unlock(>lock);
+   return ret;
+}
+
 static void progress_complete(struct fpga_sec_mgr *smgr)
 {
mutex_lock(>lock);
@@ -76,16 +93,20 @@ static void fpga_sec_mgr_update(struct work_struct *work)
goto release_fw_exit;
}
 
-   update_progress(smgr, FPGA_SEC_PROG_PREPARING);
+   if (progress_transition(smgr, FPGA_SEC_PROG_PREPARING))
+   goto modput_exit;
+
ret = smgr->sops->prepare(smgr);
if (ret != FPGA_SEC_ERR_NONE) {
fpga_sec_dev_error(smgr, ret);
goto modput_exit;
}
 
-   update_progress(smgr, FPGA_SEC_PROG_WRITING);
+   if (progress_transition(smgr, FPGA_SEC_PROG_WRITING))
+   goto done;
+
size = smgr->remaining_size;
-   while (size) {
+   while (size && !smgr->request_cancel) {
blk_size = min_t(u32, size, WRITE_BLOCK_SIZE);
size -= blk_size;
ret = smgr->sops->write_blk(smgr, offset, blk_size);
@@ -98,7 +119,9 @@ static void fpga_sec_mgr_update(struct work_struct *work)
offset += blk_size;
}
 
-   update_progress(smgr, FPGA_SEC_PROG_PROGRAMMING);
+   if (progress_transition(smgr, FPGA_SEC_PROG_PROGRAMMING))
+   goto done;
+
ret = smgr->sops->poll_complete(smgr);
if (ret != FPGA_SEC_ERR_NONE)
fpga_sec_dev_error(smgr, ret);
@@ -235,6 +258,7 @@ static ssize_t filename_store(struct device *dev, struct 
device_attribute *attr,
}
 
smgr->err_code = FPGA_SEC_ERR_NONE;
+   smgr->request_cancel = false;
smgr->progress = FPGA_SEC_PROG_READING;
reinit_completion(>update_done);
schedule_work(>work);
@@ -245,8 +269,32 @@ static ssize_t filename_store(struct device *dev, struct 
device_attribute *attr,
 }
 static DEVICE_ATTR_WO(filename);
 
+static ssize_t cancel_store(struct device *dev, struct device_attribute *attr,
+  

[PATCH v11 2/7] fpga: sec-mgr: enable secure updates

2021-04-12 Thread Russ Weight
Extend the FPGA Security Manager class driver to
include an update/filename sysfs node that can be used
to initiate a secure update.  The filename of a secure
update file (BMC image, FPGA image, Root Entry Hash image,
or Code Signing Key cancellation image) can be written to
this sysfs entry to cause a secure update to occur.

The write of the filename will return immediately, and the
update will begin in the context of a kernel worker thread.
This tool utilizes the request_firmware framework, which
requires that the image file reside under /lib/firmware.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v11:
  - Fixed a spelling error in a comment
  - Initialize smgr->err_code and smgr->progress explicitly in
fpga_sec_mgr_create() instead of accepting the default 0 value.
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
  - Changed filename_store() to use kmemdup_nul() instead of
kstrndup() and changed the count to not assume a line-return.
v6:
  - Changed "security update" to "secure update" in commit message
v5:
  - When checking the return values for functions of type enum
fpga_sec_err err_code, test for FPGA_SEC_ERR_NONE instead of 0
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Removed unnecessary "goto done"
  - Added a comment to explain imgr->driver_unload in
ifpga_sec_mgr_unregister()
v2:
  - Bumped documentation date and version
  - Removed explicit value assignments in enums
  - Other minor code cleanup per review comments 
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  |  13 ++
 drivers/fpga/fpga-sec-mgr.c   | 166 ++
 include/linux/fpga/fpga-sec-mgr.h |  49 ++
 3 files changed, 228 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 0dda4604c178..4c0bdfd25553 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -3,3 +3,16 @@ Date:  April 2021
 KernelVersion:  5.13
 Contact:   Russ Weight 
 Description:   Name of low level fpga security manager driver.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/filename
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Write only. Write the filename of an image
+   file to this sysfs file to initiate a secure
+   update. The file must have an appropriate header
+   which, among other things, identifies the target
+   for the update. This mechanism is used to update
+   BMC images, BMC firmware, Static Region images,
+   and Root Entry Hashes, and to cancel Code Signing
+   Keys (CSK).
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 468379e0c825..f2f87a48adbf 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -5,8 +5,11 @@
  * Copyright (C) 2019-2020 Intel Corporation, Inc.
  */
 
+#include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -18,8 +21,140 @@ struct fpga_sec_mgr_devres {
struct fpga_sec_mgr *smgr;
 };
 
+#define WRITE_BLOCK_SIZE 0x4000/* Update remaining_size every 0x4000 
bytes */
+
 #define to_sec_mgr(d) container_of(d, struct fpga_sec_mgr, dev)
 
+static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
+  enum fpga_sec_err err_code)
+{
+   smgr->err_code = err_code;
+   smgr->sops->cancel(smgr);
+}
+
+static void progress_complete(struct fpga_sec_mgr *smgr)
+{
+   mutex_lock(>lock);
+   smgr->progress = FPGA_SEC_PROG_IDLE;
+   complete_all(>update_done);
+   mutex_unlock(>lock);
+}
+
+static void fpga_sec_mgr_update(struct work_struct *work)
+{
+   u32 size, blk_size, offset = 0;
+   struct fpga_sec_mgr *smgr;
+   const struct firmware *fw;
+   enum fpga_sec_err ret;
+
+   smgr = container_of(work, struct fpga_sec_mgr, work);
+
+   get_device(>dev);
+   if (request_firmware(, smgr->filename, >dev)) {
+   smgr->err_code = FPGA_SEC_ERR_FILE_READ;
+   goto idle_exit;
+   }
+
+   smgr->data = fw->data;
+   smgr->remaining_size = fw->size;
+
+   if (!try_module_get(smgr->dev.parent->driver->owner)) {
+   smgr->err_code = FPGA_SEC_ERR_BUSY;
+   goto release_fw_exit;
+   }
+
+   smgr->progress = FPGA_SEC_PROG_PREPARING;
+   ret = smgr->sops

[PATCH v11 3/7] fpga: sec-mgr: expose sec-mgr update status

2021-04-12 Thread Russ Weight
Extend the FPGA Security Manager class driver to
include an update/status sysfs node that can be polled
and read to monitor the progress of an ongoing secure
update. Sysfs_notify() is used to signal transitions
between different phases of the update process.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v11:
  - No change
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the status_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Use a local variable to read progress once in status_show()
  - Use dev_err to report invalid progress status
v2:
  - Bumped documentation date and version
  - Changed progress state "read_file" to "reading"
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 11 +
 drivers/fpga/fpga-sec-mgr.c   | 42 +--
 2 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 4c0bdfd25553..64420c101626 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -16,3 +16,14 @@ Description: Write only. Write the filename of an image
BMC images, BMC firmware, Static Region images,
and Root Entry Hashes, and to cancel Code Signing
Keys (CSK).
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/status
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read-only. Returns a string describing the current
+   status of an update. The string will be one of the
+   following: idle, reading, preparing, writing,
+   programming. Userspace code can poll on this file,
+   as it will be signaled by sysfs_notify() on each
+   state change.
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index f2f87a48adbf..11050d07422a 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -25,6 +25,13 @@ struct fpga_sec_mgr_devres {
 
 #define to_sec_mgr(d) container_of(d, struct fpga_sec_mgr, dev)
 
+static void update_progress(struct fpga_sec_mgr *smgr,
+   enum fpga_sec_prog new_progress)
+{
+   smgr->progress = new_progress;
+   sysfs_notify(>dev.kobj, "update", "status");
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
@@ -35,7 +42,7 @@ static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
 static void progress_complete(struct fpga_sec_mgr *smgr)
 {
mutex_lock(>lock);
-   smgr->progress = FPGA_SEC_PROG_IDLE;
+   update_progress(smgr, FPGA_SEC_PROG_IDLE);
complete_all(>update_done);
mutex_unlock(>lock);
 }
@@ -63,14 +70,14 @@ static void fpga_sec_mgr_update(struct work_struct *work)
goto release_fw_exit;
}
 
-   smgr->progress = FPGA_SEC_PROG_PREPARING;
+   update_progress(smgr, FPGA_SEC_PROG_PREPARING);
ret = smgr->sops->prepare(smgr);
if (ret != FPGA_SEC_ERR_NONE) {
fpga_sec_dev_error(smgr, ret);
goto modput_exit;
}
 
-   smgr->progress = FPGA_SEC_PROG_WRITING;
+   update_progress(smgr, FPGA_SEC_PROG_WRITING);
size = smgr->remaining_size;
while (size) {
blk_size = min_t(u32, size, WRITE_BLOCK_SIZE);
@@ -85,7 +92,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
offset += blk_size;
}
 
-   smgr->progress = FPGA_SEC_PROG_PROGRAMMING;
+   update_progress(smgr, FPGA_SEC_PROG_PROGRAMMING);
ret = smgr->sops->poll_complete(smgr);
if (ret != FPGA_SEC_ERR_NONE)
fpga_sec_dev_error(smgr, ret);
@@ -113,6 +120,32 @@ static void fpga_sec_mgr_update(struct work_struct *work)
progress_complete(smgr);
 }
 
+static const char * const sec_mgr_prog_str[] = {
+   "idle", /* FPGA_SEC_PROG_IDLE */
+   "reading",  /* FPGA_SEC_PROG_READING */
+   "preparing",/* FPGA_SEC_PROG_PREPARING */
+   "writing",  /* FPGA_SEC_PROG_WRITING */
+   "programming"   /* FPGA_SEC_PROG_PROGRAMMING */
+};
+
+static ssize_t
+status_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr 

[PATCH v11 4/7] fpga: sec-mgr: expose sec-mgr update errors

2021-04-12 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an update/error sysfs node that can be read for error
information when a secure update fails.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v11:
  - No change
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the error_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Use dev_err() for invalid error code in sec_error()
v2:
  - Bumped documentation date and version
  - Added warning to sec_progress() for invalid progress status
  - Added sec_error() function (similar to sec_progress())
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 17 
 drivers/fpga/fpga-sec-mgr.c   | 83 ---
 include/linux/fpga/fpga-sec-mgr.h |  1 +
 3 files changed, 89 insertions(+), 12 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 64420c101626..77738577b2c3 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -27,3 +27,20 @@ Description: Read-only. Returns a string describing the 
current
programming. Userspace code can poll on this file,
as it will be signaled by sysfs_notify() on each
state change.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/error
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read-only. Returns a string describing the failure
+   of a secure update. This string will be in the form
+   of :, where  will be one of
+   the status strings described for the status sysfs
+   file and  will be one of the following:
+   hw-error, timeout, user-abort, device-busy,
+   invalid-file-size, read-write-error, flash-wearout,
+   file-read-error.  The error sysfs file is only
+   meaningful when the secure update engine is in the
+   idle state. If this file is read while a secure
+   update is in progress, then the read will fail with
+   EBUSY.
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 11050d07422a..1b827bf196d5 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -32,10 +32,16 @@ static void update_progress(struct fpga_sec_mgr *smgr,
sysfs_notify(>dev.kobj, "update", "status");
 }
 
+static void set_error(struct fpga_sec_mgr *smgr, enum fpga_sec_err err_code)
+{
+   smgr->err_state = smgr->progress;
+   smgr->err_code = err_code;
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
-   smgr->err_code = err_code;
+   set_error(smgr, err_code);
smgr->sops->cancel(smgr);
 }
 
@@ -58,7 +64,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
 
get_device(>dev);
if (request_firmware(, smgr->filename, >dev)) {
-   smgr->err_code = FPGA_SEC_ERR_FILE_READ;
+   set_error(smgr, FPGA_SEC_ERR_FILE_READ);
goto idle_exit;
}
 
@@ -66,7 +72,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
smgr->remaining_size = fw->size;
 
if (!try_module_get(smgr->dev.parent->driver->owner)) {
-   smgr->err_code = FPGA_SEC_ERR_BUSY;
+   set_error(smgr, FPGA_SEC_ERR_BUSY);
goto release_fw_exit;
}
 
@@ -128,24 +134,76 @@ static const char * const sec_mgr_prog_str[] = {
"programming"   /* FPGA_SEC_PROG_PROGRAMMING */
 };
 
-static ssize_t
-status_show(struct device *dev, struct device_attribute *attr, char *buf)
+static const char * const sec_mgr_err_str[] = {
+   "none", /* FPGA_SEC_ERR_NONE */
+   "hw-error", /* FPGA_SEC_ERR_HW_ERROR */
+   "timeout",  /* FPGA_SEC_ERR_TIMEOUT */
+   "user-abort",   /* FPGA_SEC_ERR_CANCELED */
+   "device-busy",  /* FPGA_SEC_ERR_BUSY */
+   "invalid-file-size",/* FPGA_SEC_ERR_INVALID_SIZE */
+   "read-write-error", /* FPGA_SEC_ERR_RW_ERROR */
+   "flash-wearout",/* FPGA_SEC_ERR_WEAROUT */
+   "file-read-error"   /* FPGA_SEC_ERR_FILE_READ */
+};
+
+static con

[PATCH v11 1/7] fpga: sec-mgr: fpga security manager class driver

2021-04-12 Thread Russ Weight
Create the FPGA Security Manager class driver. The security
manager provides interfaces to manage secure updates for the
FPGA and BMC images that are stored in FLASH. The driver can
also be used to update root entry hashes and to cancel code
signing keys. The image type is encoded in the image file
and is decoded by the HW/FW secure update engine.

Signed-off-by: Russ Weight 
Signed-off-by: Xu Yilun 
Reviewed-by: Tom Rix 
---
v11:
  - No change
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Fixed grammatical error in Documentation/fpga/fpga-sec-mgr.rst
v7:
  - Changed Date in documentation file to December 2020
v6:
  - Removed sysfs support and documentation for the display of the
flash count, root entry hashes, and code-signing-key cancelation
vectors.
v5:
  - Added the devm_fpga_sec_mgr_unregister() function, following recent
changes to the fpga_manager() implementation.
  - Changed some *_show() functions to use sysfs_emit() instead of sprintf(
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Modified sysfs handler check in check_sysfs_handler() to make
it more readable.
v2:
  - Bumped documentation dates and versions
  - Added Documentation/fpga/ifpga-sec-mgr.rst 
  - Removed references to bmc_flash_count & smbus_flash_count (not supported)
  - Split ifpga_sec_mgr_register() into create() and register() functions
  - Added devm_ifpga_sec_mgr_create()
  - Removed typedefs for imgr ops
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  |   5 +
 Documentation/fpga/fpga-sec-mgr.rst   |  44 +++
 Documentation/fpga/index.rst  |   1 +
 MAINTAINERS   |   9 +
 drivers/fpga/Kconfig  |   9 +
 drivers/fpga/Makefile |   3 +
 drivers/fpga/fpga-sec-mgr.c   | 296 ++
 include/linux/fpga/fpga-sec-mgr.h |  44 +++
 8 files changed, 411 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
 create mode 100644 Documentation/fpga/fpga-sec-mgr.rst
 create mode 100644 drivers/fpga/fpga-sec-mgr.c
 create mode 100644 include/linux/fpga/fpga-sec-mgr.h

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
new file mode 100644
index ..0dda4604c178
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -0,0 +1,5 @@
+What:  /sys/class/fpga_sec_mgr/fpga_secX/name
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Name of low level fpga security manager driver.
diff --git a/Documentation/fpga/fpga-sec-mgr.rst 
b/Documentation/fpga/fpga-sec-mgr.rst
new file mode 100644
index ..9f74c29fe63d
--- /dev/null
+++ b/Documentation/fpga/fpga-sec-mgr.rst
@@ -0,0 +1,44 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+
+FPGA Security Manager Class Driver
+
+
+The FPGA Security Manager class driver provides a common
+API for user-space tools to manage updates for secure FPGA
+devices. Device drivers that instantiate the Security
+Manager class driver will interact with a HW secure update
+engine in order to transfer new FPGA and BMC images to FLASH so
+that they will be automatically loaded when the FPGA card reboots.
+
+A significant difference between the FPGA Manager and the FPGA
+Security Manager is that the FPGA Manager does a live update (Partial
+Reconfiguration) to a device, whereas the FPGA Security Manager
+updates the FLASH images for the Static Region and the BMC so that
+they will be loaded the next time the FPGA card boots. Security is
+enforced by hardware and firmware. The security manager interacts
+with the firmware to initiate an update, pass in the necessary data,
+and collect status on the update.
+
+In addition to managing secure updates of the FPGA and BMC images,
+the FPGA Security Manager update process may also be used to
+program root entry hashes and cancellation keys for the FPGA static
+region, the FPGA partial reconfiguration region, and the BMC.
+
+Secure updates make use of the request_firmware framework, which
+requires that image files are accessible under /lib/firmware. A request
+for a secure update returns immediately, while the update itself
+proceeds in the context of a kernel worker thread. Sysfs files provide
+a means for monitoring the progress of a secure update and for
+retrieving error information in the event of a failure.
+
+Sysfs Attributes
+
+
+The API includes a sysfs entry *name* to export the name of the parent
+driver. It also includes an *update* sub-dire

[PATCH v11 0/7] FPGA Security Manager Class Driver

2021-04-12 Thread Russ Weight
The FPGA Security Manager class driver provides a common
API for user-space tools to manage updates for secure FPGA
devices. Device drivers that instantiate the FPGA Security
Manager class driver will interact with a HW secure update
engine in order to transfer new FPGA and BMC images to FLASH so
that they will be automatically loaded when the FPGA card reboots.

A significant difference between the FPGA Manager and the FPGA 
Security Manager is that the FPGA Manager does a live update (Partial
Reconfiguration) to a device whereas the FPGA Security Manager
updates the FLASH images for the Static Region and the BMC so that
they will be loaded the next time the FPGA card boots. Security is
enforced by hardware and firmware. The security manager interacts
with the firmware to initiate an update, pass in the necessary data,
and collect status on the update.

The n3000bmc-secure driver is the first driver to use the FPGA
Security Manager. This driver was previously submitted in the same
patch set, but has been split out into a separate patch set starting
with V2. Future devices will also make use of this common API for
secure updates.

In addition to managing secure updates of the FPGA and BMC images,
the FPGA Security Manager update process may also be used to
program root entry hashes and cancellation keys for the FPGA static
region, the FPGA partial reconfiguration region, and the BMC.
The image files are self-describing, and contain a header describing
the image type.

Secure updates make use of the request_firmware framework, which
requires that image files are accessible under /lib/firmware. A request
for a secure update returns immediately, while the update itself
proceeds in the context of a kernel worker thread. Sysfs files provide
a means for monitoring the progress of a secure update and for
retrieving error information in the event of a failure.

The API includes a "name" sysfs file to export the name of the parent
driver. It also includes an "update" sub-directory containing files that
that can be used to instantiate and monitor a secure update.

Changelog v10 -> v11:
  - Fixed a spelling error in a comment
  - Initialize smgr->err_code and smgr->progress explicitly in
fpga_sec_mgr_create() instead of accepting the default 0 value.
Changelog v9 -> v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation

Changelog v8 -> v9:
  - Rebased patches for 5.11-rc2
  - Updated Date and KernelVersion in ABI documentation

Changelog v7 -> v8:
  - Fixed grammatical error in Documentation/fpga/fpga-sec-mgr.rst

Changelog v6 -> v7:
  - Changed dates in documentation file to December 2020
  - Changed filename_store() to use kmemdup_nul() instead of
kstrndup() and changed the count to not assume a line-return.

Changelog v5 -> v6:
  - Removed sysfs support and documentation for the display of the
flash count, root entry hashes, and code-signing-key cancelation
vectors from the class driver. This information can vary by device
and will instead be displayed by the device-specific parent driver.

Changelog v4 -> v5:
  - Added the devm_fpga_sec_mgr_unregister() function, following recent
changes to the fpga_manager() implementation.
  - Changed most of the *_show() functions to use sysfs_emit()
instead of sprintf(
  - When checking the return values for functions of type enum
fpga_sec_err err_code, test for FPGA_SEC_ERR_NONE instead of 0

Changelog v3 -> v4:
  - This driver is generic enough that it could be used for non Intel
FPGA devices. Changed from "Intel FPGA Security Manager" to FPGA
Security Manager" and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
Note that this also affects some filenames.

Changelog v2 -> v3:
  - Use dev_err() to report invalid progress in sec_progress()
  - Use dev_err() to report invalid error code in sec_error()
  - Modified sysfs handler check in check_sysfs_handler() to make
it more readable.
  - Removed unnecessary "goto done"
  - Added a comment to explain imgr->driver_unload in
ifpga_sec_mgr_unregister()

Changelog v1 -> v2:
  - Separated out the MAX10 BMC Security Engine to be submitted in
a separate patch-set.
  - Bumped documentation dates and versions
  - Split ifpga_sec_mgr_register() into create() and register() functions
  - Added devm_ifpga_sec_mgr_create()
  - Added Documentation/fpga/ifpga-sec-mgr.rst 
  - Changed progress state "read_file" to "reading"
  - Added sec_error() function (similar to sec_progress())
  - Removed references to bmc_flash_count & smbus_flash_count (not supported)
  - Removed typedefs for imgr ops
  - Removed explicit value assignments in enums
  - Other minor code cleanup per review comments 

Russ Weight (7):
  fpga: sec-mgr: fpga security manager class driver
  f

[PATCH v9 1/1] mfd: intel-m10-bmc: support for MAX10 BMC Secure Updates

2021-04-12 Thread Russ Weight
Add macros and definitions required by the MAX10 BMC
Secure Update driver.

Signed-off-by: Russ Weight 
Acked-by: Lee Jones 
---
v9:
  - Rebased on next-20210412
v8:
  - Previously patch 1/6 in "Intel MAX10 BMC Secure Update Driver"
  - Rebased on next-20210121
v7:
  - No change
v6:
  - No change
v5:
  - Renamed USER_FLASH_COUNT to STAGING_FLASH_COUNT
v4:
  - No change
v3:
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure
Update driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions will be called directly.
v2:
  - These functions and macros were previously distributed among
the patches that needed them. They are now grouped together
in a single patch containing changes to the Intel MAX10 BMC
driver.
  - Added DRBL_ prefix to some definitions
  - Some address definitions were moved here from the .c files that
use them.
---
 include/linux/mfd/intel-m10-bmc.h | 85 +++
 1 file changed, 85 insertions(+)

diff --git a/include/linux/mfd/intel-m10-bmc.h 
b/include/linux/mfd/intel-m10-bmc.h
index c4eb38c13eda..f0044b14136e 100644
--- a/include/linux/mfd/intel-m10-bmc.h
+++ b/include/linux/mfd/intel-m10-bmc.h
@@ -16,6 +16,9 @@
 #define M10BMC_FLASH_END   0x1fff
 #define M10BMC_MEM_END M10BMC_FLASH_END
 
+#define M10BMC_STAGING_BASE0x1800
+#define M10BMC_STAGING_SIZE0x380
+
 /* Register offset of system registers */
 #define NIOS2_FW_VERSION   0x0
 #define M10BMC_MAC_LOW 0x10
@@ -33,6 +36,88 @@
 #define M10BMC_VER_PCB_INFO_MSKGENMASK(31, 24)
 #define M10BMC_VER_LEGACY_INVALID  0x
 
+/* Secure update doorbell register, in system register region */
+#define M10BMC_DOORBELL0x400
+
+/* Authorization Result register, in system register region */
+#define M10BMC_AUTH_RESULT 0x404
+
+/* Doorbell register fields */
+#define DRBL_RSU_REQUEST   BIT(0)
+#define DRBL_RSU_PROGRESS  GENMASK(7, 4)
+#define DRBL_HOST_STATUS   GENMASK(11, 8)
+#define DRBL_RSU_STATUSGENMASK(23, 16)
+#define DRBL_PKVL_EEPROM_LOAD_SEC  BIT(24)
+#define DRBL_PKVL1_POLL_EN BIT(25)
+#define DRBL_PKVL2_POLL_EN BIT(26)
+#define DRBL_CONFIG_SELBIT(28)
+#define DRBL_REBOOT_REQBIT(29)
+#define DRBL_REBOOT_DISABLED   BIT(30)
+
+/* Progress states */
+#define RSU_PROG_IDLE  0x0
+#define RSU_PROG_PREPARE   0x1
+#define RSU_PROG_READY 0x3
+#define RSU_PROG_AUTHENTICATING0x4
+#define RSU_PROG_COPYING   0x5
+#define RSU_PROG_UPDATE_CANCEL 0x6
+#define RSU_PROG_PROGRAM_KEY_HASH  0x7
+#define RSU_PROG_RSU_DONE  0x8
+#define RSU_PROG_PKVL_PROM_DONE0x9
+
+/* Device and error states */
+#define RSU_STAT_NORMAL0x0
+#define RSU_STAT_TIMEOUT   0x1
+#define RSU_STAT_AUTH_FAIL 0x2
+#define RSU_STAT_COPY_FAIL 0x3
+#define RSU_STAT_FATAL 0x4
+#define RSU_STAT_PKVL_REJECT   0x5
+#define RSU_STAT_NON_INC   0x6
+#define RSU_STAT_ERASE_FAIL0x7
+#define RSU_STAT_WEAROUT   0x8
+#define RSU_STAT_NIOS_OK   0x80
+#define RSU_STAT_USER_OK   0x81
+#define RSU_STAT_FACTORY_OK0x82
+#define RSU_STAT_USER_FAIL 0x83
+#define RSU_STAT_FACTORY_FAIL  0x84
+#define RSU_STAT_NIOS_FLASH_ERR0x85
+#define RSU_STAT_FPGA_FLASH_ERR0x86
+
+#define HOST_STATUS_IDLE   0x0
+#define HOST_STATUS_WRITE_DONE 0x1
+#define HOST_STATUS_ABORT_RSU  0x2
+
+#define rsu_prog(doorbell) FIELD_GET(DRBL_RSU_PROGRESS, doorbell)
+#define rsu_stat(doorbell) FIELD_GET(DRBL_RSU_STATUS, doorbell)
+
+/* interval 100ms and timeout 5s */
+#define NIOS_HANDSHAKE_INTERVAL_US (100 * 1000)
+#define NIOS_HANDSHAKE_TIMEOUT_US  (5 * 1000 * 1000)
+
+/* RSU PREP Timeout (2 minutes) to erase flash staging area */
+#define RSU_PREP_INTERVAL_MS   100
+#define RSU_PREP_TIMEOUT_MS(2 * 60 * 1000)
+
+/* RSU Complete Timeout (40 minutes) for full flash update */
+#define RSU_COMPLETE_INTERVAL_MS   1000
+#define RSU_COMPLETE_TIMEOUT_MS(40 * 60 * 1000)
+
+/* Addresses for security related data in FLASH */
+#define BMC_REH_ADDR   0x17ffc004
+#define BMC_PROG_ADDR  0x17ffc000
+#define BMC_PROG_MAGIC 0x5746
+
+#define SR_REH_ADDR0x17ffd004
+#define SR_PROG_ADDR   0x17ffd000
+#define SR_PROG_MAGIC  0x5253
+
+#define PR_REH_ADDR0x17ffe004
+#define PR_PROG_ADDR   0x17ffe000
+#define PR_PROG_MAGIC  0x5250
+
+/* Address of 4KB inverted bit vector containing staging area FLASH count */
+#define STAGING_FLASH_COUNT  

[PATCH v9 0/1] Intel MAX10 BMC Macros for Secure Update

2021-04-12 Thread Russ Weight
This patch was previously patch 1 of 6 in the patch-series entitled
"Intel MAX10 BMC Secure Update Driver". This is the only patch in
the series that is subject to conflicts with other ongoing changes
and is separated here to simplify maintenance of the patchset.

This patch creates a number of macro definitions that are required
for the Intel MAX10 BMC Secure Update Driver.

Changelog v8 -> v9:
  - Rebased on next-20210412
Changelog v7 -> v8:
  - Rebased on next-20210121
  - Separated out from patchset: "Intel MAX10 BMC Secure Update Driver"
Changelog v6 -> v7:
  - No change
Changelog v5 -> v6:
  - No change
Changelog v4 -> v5:
  - Renamed USER_FLASH_COUNT to STAGING_FLASH_COUNT
Changelog v3 -> v4:
  - No change
Changelog v2 -> v3:
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure
Update driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions will be called directly.
Changelog v1 -> v2:
  - These functions and macros were previously distributed among
the patches that needed them. They are now grouped together
in a single patch containing changes to the Intel MAX10 BMC
driver.
  - Added DRBL_ prefix to some definitions
  - Some address definitions were moved here from the .c files that
use them.

Russ Weight (1):
  mfd: intel-m10-bmc: support for MAX10 BMC Secure Updates

 include/linux/mfd/intel-m10-bmc.h | 85 +++
 1 file changed, 85 insertions(+)

-- 
2.25.1



Re: [PATCHv5 0/7] Extend Intel service layer, FPGA manager and region

2021-04-07 Thread Russ Weight
Hi Moritz,

On 3/31/21 3:16 PM, Moritz Fischer wrote:
> Hi Russ,
> On Wed, Mar 31, 2021 at 11:47:26AM -0700, Russ Weight wrote:
>> Moritz,
>>
>> On 3/28/21 10:20 AM, Moritz Fischer wrote:
>>> Tom,
>>>
>>> On Sun, Mar 28, 2021 at 08:40:24AM -0700, Tom Rix wrote:
>>>> On 3/27/21 11:09 AM, Moritz Fischer wrote:
>>>>> Hi Richard, Russ,
>>>>>
>>>>> On Thu, Feb 25, 2021 at 01:07:14PM +, Gong, Richard wrote:
>>>>>> Hi Moritz,
>>>>>>
>>>>>> Sorry for asking.
>>>>>>
>>>>>> When you have chance, can you help review the version 5 patchset 
>>>>>> submitted on 02/09/21?
>>>>>>
>>>>>> Regards,
>>>>>> Richard
>>>>>>
>>>>>> -Original Message-
>>>>>> From: richard.g...@linux.intel.com  
>>>>>> Sent: Tuesday, February 9, 2021 4:20 PM
>>>>>> To: m...@kernel.org; t...@redhat.com; gre...@linuxfoundation.org; 
>>>>>> linux-f...@vger.kernel.org; linux-kernel@vger.kernel.org
>>>>>> Cc: Gong, Richard 
>>>>>> Subject: [PATCHv5 0/7] Extend Intel service layer, FPGA manager and 
>>>>>> region
>>>>>>
>>>>>> From: Richard Gong 
>>>>>>
>>>>>> This is 5th submission of Intel service layer and FPGA patches, which 
>>>>>> includes the missing standalone patch in the 4th submission.
>>>>>>
>>>>>> This submission includes additional changes for Intel service layer 
>>>>>> driver to get the firmware version running at FPGA SoC device. Then FPGA 
>>>>>> manager driver, one of Intel service layer driver's client, can decide 
>>>>>> whether to handle the newly added bitstream authentication function 
>>>>>> based on the retrieved firmware version. So that we can maintain FPGA 
>>>>>> manager driver the back compatible.
>>>>>>
>>>>>> Bitstream authentication makes sure a signed bitstream has valid 
>>>>>> signatures.
>>>>>>
>>>>>> The customer sends the bitstream via FPGA framework and overlay, the 
>>>>>> firmware will authenticate the bitstream but not program the bitstream 
>>>>>> to device. If the authentication passes, the bitstream will be 
>>>>>> programmed into QSPI flash and will be expected to boot without issues.
>>>>>>
>>>>>> Extend Intel service layer, FPGA manager and region drivers to support 
>>>>>> the bitstream authentication feature. 
>>>>>>
>>>>>> Richard Gong (7):
>>>>>>   firmware: stratix10-svc: reset COMMAND_RECONFIG_FLAG_PARTIAL to 0
>>>>>>   firmware: stratix10-svc: add COMMAND_AUTHENTICATE_BITSTREAM flag
>>>>>>   firmware: stratix10-svc: extend SVC driver to get the firmware version
>>>>>>   fpga: fpga-mgr: add FPGA_MGR_BITSTREAM_AUTHENTICATE flag
>>>>>>   fpga: of-fpga-region: add authenticate-fpga-config property
>>>>>>   dt-bindings: fpga: add authenticate-fpga-config property
>>>>>>   fpga: stratix10-soc: extend driver for bitstream authentication
>>>>>>
>>>>>>  .../devicetree/bindings/fpga/fpga-region.txt   | 10 
>>>>>>  drivers/firmware/stratix10-svc.c   | 12 -
>>>>>>  drivers/fpga/of-fpga-region.c  | 24 ++---
>>>>>>  drivers/fpga/stratix10-soc.c   | 62 
>>>>>> +++---
>>>>>>  include/linux/firmware/intel/stratix10-smc.h   | 21 +++-
>>>>>>  .../linux/firmware/intel/stratix10-svc-client.h| 11 +++-
>>>>>>  include/linux/fpga/fpga-mgr.h  |  3 ++
>>>>>>  7 files changed, 125 insertions(+), 18 deletions(-)
>>>>>>
>>>>>> --
>>>>>> 2.7.4
>>>>>>
>>>>> Apologies for the epic delay in getting back to this, I took another
>>>>> look at this patchset and Russ' patchset.
>>>>>
>>>>> TL;DR I'm not really a fan of using device-tree overlays for this (and
>>>>> again, apologies, I should've voiced this earlier ...).
>>>>>
>>>>> Anyways, let's find a common API for this and Russ' work, they're trying
>>>>> to achieve the same / similar thing, they should use the same API.
>>>>>
>>>>> I'd like to re-invetigate the possiblity to extend FPGA Manager with
>>>>> 'secure update' ops that work for both these use-cases (and I susspect
>>>>> hte XRT patchset will follow with a similar requirement, right after).
>> Richard and I had an initial conversation today. I'll start looking at how 
>> secure operations can be integrated into the fpga manager.
>>
>> More to come...
> Great, feel free to send RFCs ahead.
>
> Cheers,
> Moritz
I have completed a comparison of the security manager and the FPGA manager
to see how the secure update functions can be integrated into the FPGA
manager. I'll send that out separately as an RFC document (it is about 150
lines).

FYI: In my conversations with Richard, we have learned that what we are
trying to accomplish is not as similar as it seemed. Richard is effectively
wanting to do a "dry-run" of an existing FPGA Manager function to verify
authentication of an image. Based on the results, higher-level code may
choose to write the image to flash.

The security manager is all about providing a common user API (sysfs
interface) for tranferring an image to an FPGA card while managing a
completion time (including authentication and FLASH) of up to 40 minutes.

- Russ



Re: [PATCHv5 0/7] Extend Intel service layer, FPGA manager and region

2021-03-31 Thread Russ Weight
Moritz,

On 3/28/21 10:20 AM, Moritz Fischer wrote:
> Tom,
>
> On Sun, Mar 28, 2021 at 08:40:24AM -0700, Tom Rix wrote:
>> On 3/27/21 11:09 AM, Moritz Fischer wrote:
>>> Hi Richard, Russ,
>>>
>>> On Thu, Feb 25, 2021 at 01:07:14PM +, Gong, Richard wrote:
 Hi Moritz,

 Sorry for asking.

 When you have chance, can you help review the version 5 patchset submitted 
 on 02/09/21?

 Regards,
 Richard

 -Original Message-
 From: richard.g...@linux.intel.com  
 Sent: Tuesday, February 9, 2021 4:20 PM
 To: m...@kernel.org; t...@redhat.com; gre...@linuxfoundation.org; 
 linux-f...@vger.kernel.org; linux-kernel@vger.kernel.org
 Cc: Gong, Richard 
 Subject: [PATCHv5 0/7] Extend Intel service layer, FPGA manager and region

 From: Richard Gong 

 This is 5th submission of Intel service layer and FPGA patches, which 
 includes the missing standalone patch in the 4th submission.

 This submission includes additional changes for Intel service layer driver 
 to get the firmware version running at FPGA SoC device. Then FPGA manager 
 driver, one of Intel service layer driver's client, can decide whether to 
 handle the newly added bitstream authentication function based on the 
 retrieved firmware version. So that we can maintain FPGA manager driver 
 the back compatible.

 Bitstream authentication makes sure a signed bitstream has valid 
 signatures.

 The customer sends the bitstream via FPGA framework and overlay, the 
 firmware will authenticate the bitstream but not program the bitstream to 
 device. If the authentication passes, the bitstream will be programmed 
 into QSPI flash and will be expected to boot without issues.

 Extend Intel service layer, FPGA manager and region drivers to support the 
 bitstream authentication feature. 

 Richard Gong (7):
   firmware: stratix10-svc: reset COMMAND_RECONFIG_FLAG_PARTIAL to 0
   firmware: stratix10-svc: add COMMAND_AUTHENTICATE_BITSTREAM flag
   firmware: stratix10-svc: extend SVC driver to get the firmware version
   fpga: fpga-mgr: add FPGA_MGR_BITSTREAM_AUTHENTICATE flag
   fpga: of-fpga-region: add authenticate-fpga-config property
   dt-bindings: fpga: add authenticate-fpga-config property
   fpga: stratix10-soc: extend driver for bitstream authentication

  .../devicetree/bindings/fpga/fpga-region.txt   | 10 
  drivers/firmware/stratix10-svc.c   | 12 -
  drivers/fpga/of-fpga-region.c  | 24 ++---
  drivers/fpga/stratix10-soc.c   | 62 
 +++---
  include/linux/firmware/intel/stratix10-smc.h   | 21 +++-
  .../linux/firmware/intel/stratix10-svc-client.h| 11 +++-
  include/linux/fpga/fpga-mgr.h  |  3 ++
  7 files changed, 125 insertions(+), 18 deletions(-)

 --
 2.7.4

>>> Apologies for the epic delay in getting back to this, I took another
>>> look at this patchset and Russ' patchset.
>>>
>>> TL;DR I'm not really a fan of using device-tree overlays for this (and
>>> again, apologies, I should've voiced this earlier ...).
>>>
>>> Anyways, let's find a common API for this and Russ' work, they're trying
>>> to achieve the same / similar thing, they should use the same API.
>>>
>>> I'd like to re-invetigate the possiblity to extend FPGA Manager with
>>> 'secure update' ops that work for both these use-cases (and I susspect
>>> hte XRT patchset will follow with a similar requirement, right after).

Richard and I had an initial conversation today. I'll start looking at how 
secure operations can be integrated into the fpga manager.

More to come...

Thanks,
- Russ

>> The xrt patchset makes heavy use of device trees.
>>
>> What is the general guidance for device tree usage ?
> I'm not generally against using device tree, it has its place. To
> describe hardware (and hardware *changes* with overlays) :)
>
> What I don't like about this particular implementation w.r.t device-tree
> usage is that it uses DT overlays as a mechanism to program the flash --
> in place of having an API to do so.
>
> One could add device-nodes during the DT overlay application, while the
> FPGA doesn't actually get programmed with a new runtime image -- meaning
> live DT and actual hardware state diverged -- worst case it'd crash.
>
> So when roughly at the same time (from the same company even) we have two
> patchsets that do similar things with radically different APIs I think
> we should pause, and reflect on whether we can come up with something
> that works for both :)
>
> TL;DR the firmware parts to authenticate the bitstream look fine to me, the
> way we tie it into the FPGA region I'm not a fan of.
>
> - Moritz



[PATCH v9 1/1] fpga: dfl: afu: harden port enable logic

2021-03-23 Thread Russ Weight
Port enable is not complete until ACK = 0. Change
__afu_port_enable() to guarantee that the enable process
is complete by polling for ACK == 0.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
Reviewed-by: Matthew Gerlach 
Acked-by: Wu Hao 
---
v9:
  - Fix the sense of the if condition in __port_reset()
v8:
  - Rebased to 5.12-rc1 (there were no conflicts)
v7:
  - Added Acked-by tag from Wu Hao
v6:
  - Fixed the dev_warn statement, which had "__func__" embedded in the
string instead of treated as a parameter to the format string.
v5:
  - Added Reviewed-by tag to commit message
v4:
  - Added a dev_warn() call for the -EINVAL case of afu_port_err_clear()
  - Modified dev_err() message in __afu_port_disable() to say "disable"
instead of "reset"
v3:
  - afu_port_err_clear() changed to prioritize port_enable failure over
other a detected mismatch in port errors.
  - reorganized code in port_reset() to be more readable.
v2:
  - Fixed typo in commit message
---
 drivers/fpga/dfl-afu-error.c | 10 ++
 drivers/fpga/dfl-afu-main.c  | 35 ---
 drivers/fpga/dfl-afu.h   |  2 +-
 3 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
index c4691187cca9..ab7be6217368 100644
--- a/drivers/fpga/dfl-afu-error.c
+++ b/drivers/fpga/dfl-afu-error.c
@@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 err)
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
struct platform_device *pdev = to_platform_device(dev);
void __iomem *base_err, *base_hdr;
-   int ret = -EBUSY;
+   int enable_ret = 0, ret = -EBUSY;
u64 v;
 
base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
@@ -96,18 +96,20 @@ static int afu_port_err_clear(struct device *dev, u64 err)
v = readq(base_err + PORT_FIRST_ERROR);
writeq(v, base_err + PORT_FIRST_ERROR);
} else {
+   dev_warn(dev, "%s: received 0x%llx, expected 0x%llx\n",
+__func__, v, err);
ret = -EINVAL;
}
 
/* Clear mask */
__afu_port_err_mask(dev, false);
 
-   /* Enable the Port by clear the reset */
-   __afu_port_enable(pdev);
+   /* Enable the Port by clearing the reset */
+   enable_ret = __afu_port_enable(pdev);
 
 done:
mutex_unlock(>lock);
-   return ret;
+   return enable_ret ? enable_ret : ret;
 }
 
 static ssize_t errors_show(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 753cda4b2568..7f621e96d3b8 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -21,6 +21,9 @@
 
 #include "dfl-afu.h"
 
+#define RST_POLL_INVL 10 /* us */
+#define RST_POLL_TIMEOUT 1000 /* us */
+
 /**
  * __afu_port_enable - enable a port by clear reset
  * @pdev: port platform device.
@@ -32,7 +35,7 @@
  *
  * The caller needs to hold lock for protection.
  */
-void __afu_port_enable(struct platform_device *pdev)
+int __afu_port_enable(struct platform_device *pdev)
 {
struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
void __iomem *base;
@@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
WARN_ON(!pdata->disable_count);
 
if (--pdata->disable_count != 0)
-   return;
+   return 0;
 
base = dfl_get_feature_ioaddr_by_id(>dev, PORT_FEATURE_ID_HEADER);
 
@@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
v = readq(base + PORT_HDR_CTRL);
v &= ~PORT_CTRL_SFTRST;
writeq(v, base + PORT_HDR_CTRL);
-}
 
-#define RST_POLL_INVL 10 /* us */
-#define RST_POLL_TIMEOUT 1000 /* us */
+   /*
+* HW clears the ack bit to indicate that the port is fully out
+* of reset.
+*/
+   if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
+  !(v & PORT_CTRL_SFTRST_ACK),
+  RST_POLL_INVL, RST_POLL_TIMEOUT)) {
+   dev_err(>dev, "timeout, failure to enable device\n");
+   return -ETIMEDOUT;
+   }
+
+   return 0;
+}
 
 /**
  * __afu_port_disable - disable a port by hold reset
@@ -86,7 +99,7 @@ int __afu_port_disable(struct platform_device *pdev)
if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
   v & PORT_CTRL_SFTRST_ACK,
   RST_POLL_INVL, RST_POLL_TIMEOUT)) {
-   dev_err(>dev, "timeout, fail to reset device\n");
+   dev_err(>dev, "timeout, failure to disable device\n");
return -ETIMEDOUT;
}
 
@@ -110,10 +123,10 @@ static int __port_reset(struct platform_device *pdev)
int ret;
 
ret = __afu_port_d

Re: [PATCH v8 1/1] fpga: dfl: afu: harden port enable logic

2021-03-23 Thread Russ Weight



On 3/2/21 5:45 PM, Russ Weight wrote:
> Port enable is not complete until ACK = 0. Change
> __afu_port_enable() to guarantee that the enable process
> is complete by polling for ACK == 0.
>
> Signed-off-by: Russ Weight 
> Reviewed-by: Tom Rix 
> Reviewed-by: Matthew Gerlach 
> Acked-by: Wu Hao 
> ---
> v8:
>   - Rebased to 5.12-rc1 (there were no conflicts)
> v7:
>   - Added Acked-by tag from Wu Hao
> v6:
>   - Fixed the dev_warn statement, which had "__func__" embedded in the
> string instead of treated as a parameter to the format string.
> v5:
>   - Added Reviewed-by tag to commit message
> v4:
>   - Added a dev_warn() call for the -EINVAL case of afu_port_err_clear()
>   - Modified dev_err() message in __afu_port_disable() to say "disable"
> instead of "reset"
> v3:
>   - afu_port_err_clear() changed to prioritize port_enable failure over
> other a detected mismatch in port errors.
>   - reorganized code in port_reset() to be more readable.
> v2:
>   - Fixed typo in commit message
> ---
>  drivers/fpga/dfl-afu-error.c | 10 ++
>  drivers/fpga/dfl-afu-main.c  | 33 +++--
>  drivers/fpga/dfl-afu.h   |  2 +-
>  3 files changed, 30 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
> index c4691187cca9..ab7be6217368 100644
> --- a/drivers/fpga/dfl-afu-error.c
> +++ b/drivers/fpga/dfl-afu-error.c
> @@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 err)
>   struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
>   struct platform_device *pdev = to_platform_device(dev);
>   void __iomem *base_err, *base_hdr;
> - int ret = -EBUSY;
> + int enable_ret = 0, ret = -EBUSY;
>   u64 v;
>  
>   base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
> @@ -96,18 +96,20 @@ static int afu_port_err_clear(struct device *dev, u64 err)
>   v = readq(base_err + PORT_FIRST_ERROR);
>   writeq(v, base_err + PORT_FIRST_ERROR);
>   } else {
> + dev_warn(dev, "%s: received 0x%llx, expected 0x%llx\n",
> +  __func__, v, err);
>   ret = -EINVAL;
>   }
>  
>   /* Clear mask */
>   __afu_port_err_mask(dev, false);
>  
> - /* Enable the Port by clear the reset */
> - __afu_port_enable(pdev);
> + /* Enable the Port by clearing the reset */
> + enable_ret = __afu_port_enable(pdev);
>  
>  done:
>   mutex_unlock(>lock);
> - return ret;
> + return enable_ret ? enable_ret : ret;
>  }
>  
>  static ssize_t errors_show(struct device *dev, struct device_attribute *attr,
> diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
> index 753cda4b2568..77dadaae5b8f 100644
> --- a/drivers/fpga/dfl-afu-main.c
> +++ b/drivers/fpga/dfl-afu-main.c
> @@ -21,6 +21,9 @@
>  
>  #include "dfl-afu.h"
>  
> +#define RST_POLL_INVL 10 /* us */
> +#define RST_POLL_TIMEOUT 1000 /* us */
> +
>  /**
>   * __afu_port_enable - enable a port by clear reset
>   * @pdev: port platform device.
> @@ -32,7 +35,7 @@
>   *
>   * The caller needs to hold lock for protection.
>   */
> -void __afu_port_enable(struct platform_device *pdev)
> +int __afu_port_enable(struct platform_device *pdev)
>  {
>   struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
>   void __iomem *base;
> @@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
>   WARN_ON(!pdata->disable_count);
>  
>   if (--pdata->disable_count != 0)
> - return;
> + return 0;
>  
>   base = dfl_get_feature_ioaddr_by_id(>dev, PORT_FEATURE_ID_HEADER);
>  
> @@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
>   v = readq(base + PORT_HDR_CTRL);
>   v &= ~PORT_CTRL_SFTRST;
>   writeq(v, base + PORT_HDR_CTRL);
> -}
>  
> -#define RST_POLL_INVL 10 /* us */
> -#define RST_POLL_TIMEOUT 1000 /* us */
> + /*
> +  * HW clears the ack bit to indicate that the port is fully out
> +  * of reset.
> +  */
> + if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
> +!(v & PORT_CTRL_SFTRST_ACK),
> +RST_POLL_INVL, RST_POLL_TIMEOUT)) {
> + dev_err(>dev, "timeout, failure to enable device\n");
> + return -ETIMEDOUT;
> + }
> +
> + return 0;
> +}
>  
>  /**
>   * __afu_port_disable - disable a port by hold reset
> @@ -86,7 +99,7 @@ int __afu_port_disable(struct platform_d

[RESEND PATCH v10 4/7] fpga: sec-mgr: expose sec-mgr update errors

2021-03-22 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an update/error sysfs node that can be read for error
information when a secure update fails.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the error_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Use dev_err() for invalid error code in sec_error()
v2:
  - Bumped documentation date and version
  - Added warning to sec_progress() for invalid progress status
  - Added sec_error() function (similar to sec_progress())
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 17 
 drivers/fpga/fpga-sec-mgr.c   | 83 ---
 include/linux/fpga/fpga-sec-mgr.h |  1 +
 3 files changed, 89 insertions(+), 12 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 64420c101626..77738577b2c3 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -27,3 +27,20 @@ Description: Read-only. Returns a string describing the 
current
programming. Userspace code can poll on this file,
as it will be signaled by sysfs_notify() on each
state change.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/error
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read-only. Returns a string describing the failure
+   of a secure update. This string will be in the form
+   of :, where  will be one of
+   the status strings described for the status sysfs
+   file and  will be one of the following:
+   hw-error, timeout, user-abort, device-busy,
+   invalid-file-size, read-write-error, flash-wearout,
+   file-read-error.  The error sysfs file is only
+   meaningful when the secure update engine is in the
+   idle state. If this file is read while a secure
+   update is in progress, then the read will fail with
+   EBUSY.
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index dd60014b7511..3bd89598cccd 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -32,10 +32,16 @@ static void update_progress(struct fpga_sec_mgr *smgr,
sysfs_notify(>dev.kobj, "update", "status");
 }
 
+static void set_error(struct fpga_sec_mgr *smgr, enum fpga_sec_err err_code)
+{
+   smgr->err_state = smgr->progress;
+   smgr->err_code = err_code;
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
-   smgr->err_code = err_code;
+   set_error(smgr, err_code);
smgr->sops->cancel(smgr);
 }
 
@@ -58,7 +64,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
 
get_device(>dev);
if (request_firmware(, smgr->filename, >dev)) {
-   smgr->err_code = FPGA_SEC_ERR_FILE_READ;
+   set_error(smgr, FPGA_SEC_ERR_FILE_READ);
goto idle_exit;
}
 
@@ -66,7 +72,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
smgr->remaining_size = fw->size;
 
if (!try_module_get(smgr->dev.parent->driver->owner)) {
-   smgr->err_code = FPGA_SEC_ERR_BUSY;
+   set_error(smgr, FPGA_SEC_ERR_BUSY);
goto release_fw_exit;
}
 
@@ -128,24 +134,76 @@ static const char * const sec_mgr_prog_str[] = {
"programming"   /* FPGA_SEC_PROG_PROGRAMMING */
 };
 
-static ssize_t
-status_show(struct device *dev, struct device_attribute *attr, char *buf)
+static const char * const sec_mgr_err_str[] = {
+   "none", /* FPGA_SEC_ERR_NONE */
+   "hw-error", /* FPGA_SEC_ERR_HW_ERROR */
+   "timeout",  /* FPGA_SEC_ERR_TIMEOUT */
+   "user-abort",   /* FPGA_SEC_ERR_CANCELED */
+   "device-busy",  /* FPGA_SEC_ERR_BUSY */
+   "invalid-file-size",/* FPGA_SEC_ERR_INVALID_SIZE */
+   "read-write-error", /* FPGA_SEC_ERR_RW_ERROR */
+   "flash-wearout",/* FPGA_SEC_ERR_WEAROUT */
+   "file-read-error"   /* FPGA_SEC_ERR_FILE_READ */
+};
+
+static const char *sec_progress(struc

[RESEND PATCH v10 5/7] fpga: sec-mgr: expose sec-mgr update size

2021-03-22 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an update/remaining_size sysfs node that can be read to
determine how much data remains to be transferred to the
secure update engine. This file can be used to monitor
progress during the "writing" phase of an update.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the remaining_size_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: imgr -> smgr, ifpga_ to fpga_
v3:
  - No change
v2:
  - Bumped documentation date and version
---
 Documentation/ABI/testing/sysfs-class-fpga-sec-mgr | 11 +++
 drivers/fpga/fpga-sec-mgr.c| 10 ++
 2 files changed, 21 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 77738577b2c3..2e1f60edf546 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -28,6 +28,17 @@ Description: Read-only. Returns a string describing the 
current
as it will be signaled by sysfs_notify() on each
state change.
 
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/remaining_size
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read-only. Returns the size of data that remains to
+   be written to the secure update engine. The size
+   value is initialized to the full size of the file
+   image and the value is updated periodically during
+   the "writing" phase of the update.
+   Format: "%u".
+
 What:  /sys/class/fpga_sec_mgr/fpga_secX/update/error
 Date:  April 2021
 KernelVersion:  5.13
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 3bd89598cccd..951020942991 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -204,6 +204,15 @@ error_show(struct device *dev, struct device_attribute 
*attr, char *buf)
 }
 static DEVICE_ATTR_RO(error);
 
+static ssize_t remaining_size_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
+
+   return sysfs_emit(buf, "%u\n", smgr->remaining_size);
+}
+static DEVICE_ATTR_RO(remaining_size);
+
 static ssize_t filename_store(struct device *dev, struct device_attribute 
*attr,
  const char *buf, size_t count)
 {
@@ -240,6 +249,7 @@ static struct attribute *sec_mgr_update_attrs[] = {
_attr_filename.attr,
_attr_status.attr,
_attr_error.attr,
+   _attr_remaining_size.attr,
NULL,
 };
 
-- 
2.25.1



[RESEND PATCH v10 7/7] fpga: sec-mgr: expose hardware error info

2021-03-22 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an optional update/hw_errinfo sysfs node that can be used
to retrieve 64 bits of device specific error information
following a secure update failure.

The underlying driver must provide a get_hw_errinfo() callback
function to enable this feature. This data is treated as
opaque by the class driver. It is left to user-space software
or support personnel to interpret this data.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - No change
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - No change
v2:
  - Bumped documentation date and version
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 14 +++
 drivers/fpga/fpga-sec-mgr.c   | 38 +++
 include/linux/fpga/fpga-sec-mgr.h |  5 +++
 3 files changed, 57 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index fba3066e2b69..ff1458701def 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -65,3 +65,17 @@ Description: Read-only. Returns a string describing the 
failure
idle state. If this file is read while a secure
update is in progress, then the read will fail with
EBUSY.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/hw_errinfo
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read-only. Returns a 64 bit error value providing
+   hardware specific information that may be useful in
+   debugging errors that occur during FPGA image updates.
+   This file is only visible if the underlying device
+   supports it. The hw_errinfo value is only accessible
+   when the secure update engine is in the idle state.
+   If this file is read while a secure update is in
+   progress, then the read will fail with EBUSY.
+   Format: "0x%llx".
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index d354fe2ab582..aebe06d9a54a 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -38,10 +38,17 @@ static void set_error(struct fpga_sec_mgr *smgr, enum 
fpga_sec_err err_code)
smgr->err_code = err_code;
 }
 
+static void set_hw_errinfo(struct fpga_sec_mgr *smgr)
+{
+   if (smgr->sops->get_hw_errinfo)
+   smgr->hw_errinfo = smgr->sops->get_hw_errinfo(smgr);
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
set_error(smgr, err_code);
+   set_hw_errinfo(smgr);
smgr->sops->cancel(smgr);
 }
 
@@ -227,6 +234,23 @@ error_show(struct device *dev, struct device_attribute 
*attr, char *buf)
 }
 static DEVICE_ATTR_RO(error);
 
+static ssize_t
+hw_errinfo_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
+   int ret;
+
+   mutex_lock(>lock);
+   if (smgr->progress != FPGA_SEC_PROG_IDLE)
+   ret = -EBUSY;
+   else
+   ret = sysfs_emit(buf, "0x%llx\n", smgr->hw_errinfo);
+   mutex_unlock(>lock);
+
+   return ret;
+}
+static DEVICE_ATTR_RO(hw_errinfo);
+
 static ssize_t remaining_size_show(struct device *dev,
   struct device_attribute *attr, char *buf)
 {
@@ -258,6 +282,7 @@ static ssize_t filename_store(struct device *dev, struct 
device_attribute *attr,
}
 
smgr->err_code = FPGA_SEC_ERR_NONE;
+   smgr->hw_errinfo = 0;
smgr->request_cancel = false;
smgr->progress = FPGA_SEC_PROG_READING;
reinit_completion(>update_done);
@@ -292,18 +317,31 @@ static ssize_t cancel_store(struct device *dev, struct 
device_attribute *attr,
 }
 static DEVICE_ATTR_WO(cancel);
 
+static umode_t
+sec_mgr_update_visible(struct kobject *kobj, struct attribute *attr, int n)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(kobj_to_dev(kobj));
+
+   if (attr == _attr_hw_errinfo.attr && !smgr->sops->get_hw_errinfo)
+   return 0;
+
+   return attr->mode;
+}
+
 static struct attribute *sec_mgr_update_attrs[] = {
_attr_filename.attr,
_attr_cancel.attr,
_attr_status.attr,
_attr_error.attr,
_attr_remaining_size.attr,
+   _attr

[RESEND PATCH v10 3/7] fpga: sec-mgr: expose sec-mgr update status

2021-03-22 Thread Russ Weight
Extend the FPGA Security Manager class driver to
include an update/status sysfs node that can be polled
and read to monitor the progress of an ongoing secure
update. Sysfs_notify() is used to signal transitions
between different phases of the update process.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the status_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Use a local variable to read progress once in status_show()
  - Use dev_err to report invalid progress status
v2:
  - Bumped documentation date and version
  - Changed progress state "read_file" to "reading"
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 11 +
 drivers/fpga/fpga-sec-mgr.c   | 42 +--
 2 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 4c0bdfd25553..64420c101626 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -16,3 +16,14 @@ Description: Write only. Write the filename of an image
BMC images, BMC firmware, Static Region images,
and Root Entry Hashes, and to cancel Code Signing
Keys (CSK).
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/status
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read-only. Returns a string describing the current
+   status of an update. The string will be one of the
+   following: idle, reading, preparing, writing,
+   programming. Userspace code can poll on this file,
+   as it will be signaled by sysfs_notify() on each
+   state change.
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 7347ba1ba73e..dd60014b7511 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -25,6 +25,13 @@ struct fpga_sec_mgr_devres {
 
 #define to_sec_mgr(d) container_of(d, struct fpga_sec_mgr, dev)
 
+static void update_progress(struct fpga_sec_mgr *smgr,
+   enum fpga_sec_prog new_progress)
+{
+   smgr->progress = new_progress;
+   sysfs_notify(>dev.kobj, "update", "status");
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
@@ -35,7 +42,7 @@ static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
 static void progress_complete(struct fpga_sec_mgr *smgr)
 {
mutex_lock(>lock);
-   smgr->progress = FPGA_SEC_PROG_IDLE;
+   update_progress(smgr, FPGA_SEC_PROG_IDLE);
complete_all(>update_done);
mutex_unlock(>lock);
 }
@@ -63,14 +70,14 @@ static void fpga_sec_mgr_update(struct work_struct *work)
goto release_fw_exit;
}
 
-   smgr->progress = FPGA_SEC_PROG_PREPARING;
+   update_progress(smgr, FPGA_SEC_PROG_PREPARING);
ret = smgr->sops->prepare(smgr);
if (ret != FPGA_SEC_ERR_NONE) {
fpga_sec_dev_error(smgr, ret);
goto modput_exit;
}
 
-   smgr->progress = FPGA_SEC_PROG_WRITING;
+   update_progress(smgr, FPGA_SEC_PROG_WRITING);
size = smgr->remaining_size;
while (size) {
blk_size = min_t(u32, size, WRITE_BLOCK_SIZE);
@@ -85,7 +92,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
offset += blk_size;
}
 
-   smgr->progress = FPGA_SEC_PROG_PROGRAMMING;
+   update_progress(smgr, FPGA_SEC_PROG_PROGRAMMING);
ret = smgr->sops->poll_complete(smgr);
if (ret != FPGA_SEC_ERR_NONE)
fpga_sec_dev_error(smgr, ret);
@@ -113,6 +120,32 @@ static void fpga_sec_mgr_update(struct work_struct *work)
progress_complete(smgr);
 }
 
+static const char * const sec_mgr_prog_str[] = {
+   "idle", /* FPGA_SEC_PROG_IDLE */
+   "reading",  /* FPGA_SEC_PROG_READING */
+   "preparing",/* FPGA_SEC_PROG_PREPARING */
+   "writing",  /* FPGA_SEC_PROG_WRITING */
+   "programming"   /* FPGA_SEC_PROG_PROGRAMMING */
+};
+
+static ssize_t
+status_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(d

[RESEND PATCH v10 6/7] fpga: sec-mgr: enable cancel of secure update

2021-03-22 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an update/cancel sysfs file that can be written to request
that an update be canceled. The write may return EBUSY if
the update has progressed to the point that it cannot be
canceled by software or ENODEV if there is no update in
progress.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - No change
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - No change
v2:
  - Bumped documentation date and version
  - Minor code cleanup per review comments 
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 10 
 drivers/fpga/fpga-sec-mgr.c   | 59 +--
 include/linux/fpga/fpga-sec-mgr.h |  1 +
 3 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 2e1f60edf546..fba3066e2b69 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -17,6 +17,16 @@ Description: Write only. Write the filename of an image
and Root Entry Hashes, and to cancel Code Signing
Keys (CSK).
 
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/cancel
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Write-only. Write a "1" to this file to request
+   that a current update be canceled. This request
+   will be rejected (EBUSY) if the programming phase
+   has already started or (ENODEV) if there is no
+   update in progress.
+
 What:  /sys/class/fpga_sec_mgr/fpga_secX/update/status
 Date:  April 2021
 KernelVersion:  5.13
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 951020942991..d354fe2ab582 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -45,6 +45,23 @@ static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
smgr->sops->cancel(smgr);
 }
 
+static int progress_transition(struct fpga_sec_mgr *smgr,
+  enum fpga_sec_prog new_progress)
+{
+   int ret = 0;
+
+   mutex_lock(>lock);
+   if (smgr->request_cancel) {
+   set_error(smgr, FPGA_SEC_ERR_CANCELED);
+   smgr->sops->cancel(smgr);
+   ret = -ECANCELED;
+   } else {
+   update_progress(smgr, new_progress);
+   }
+   mutex_unlock(>lock);
+   return ret;
+}
+
 static void progress_complete(struct fpga_sec_mgr *smgr)
 {
mutex_lock(>lock);
@@ -76,16 +93,20 @@ static void fpga_sec_mgr_update(struct work_struct *work)
goto release_fw_exit;
}
 
-   update_progress(smgr, FPGA_SEC_PROG_PREPARING);
+   if (progress_transition(smgr, FPGA_SEC_PROG_PREPARING))
+   goto modput_exit;
+
ret = smgr->sops->prepare(smgr);
if (ret != FPGA_SEC_ERR_NONE) {
fpga_sec_dev_error(smgr, ret);
goto modput_exit;
}
 
-   update_progress(smgr, FPGA_SEC_PROG_WRITING);
+   if (progress_transition(smgr, FPGA_SEC_PROG_WRITING))
+   goto done;
+
size = smgr->remaining_size;
-   while (size) {
+   while (size && !smgr->request_cancel) {
blk_size = min_t(u32, size, WRITE_BLOCK_SIZE);
size -= blk_size;
ret = smgr->sops->write_blk(smgr, offset, blk_size);
@@ -98,7 +119,9 @@ static void fpga_sec_mgr_update(struct work_struct *work)
offset += blk_size;
}
 
-   update_progress(smgr, FPGA_SEC_PROG_PROGRAMMING);
+   if (progress_transition(smgr, FPGA_SEC_PROG_PROGRAMMING))
+   goto done;
+
ret = smgr->sops->poll_complete(smgr);
if (ret != FPGA_SEC_ERR_NONE)
fpga_sec_dev_error(smgr, ret);
@@ -235,6 +258,7 @@ static ssize_t filename_store(struct device *dev, struct 
device_attribute *attr,
}
 
smgr->err_code = FPGA_SEC_ERR_NONE;
+   smgr->request_cancel = false;
smgr->progress = FPGA_SEC_PROG_READING;
reinit_completion(>update_done);
schedule_work(>work);
@@ -245,8 +269,32 @@ static ssize_t filename_store(struct device *dev, struct 
device_attribute *attr,
 }
 static DEVICE_ATTR_WO(filename);
 
+static ssize_t cancel_store(struct device *dev, struct device_attribute *attr,
+   const ch

[RESEND PATCH v10 2/7] fpga: sec-mgr: enable secure updates

2021-03-22 Thread Russ Weight
Extend the FPGA Security Manager class driver to
include an update/filename sysfs node that can be used
to initiate a secure update.  The filename of a secure
update file (BMC image, FPGA image, Root Entry Hash image,
or Code Signing Key cancellation image) can be written to
this sysfs entry to cause a secure update to occur.

The write of the filename will return immediately, and the
update will begin in the context of a kernel worker thread.
This tool utilizes the request_firmware framework, which
requires that the image file reside under /lib/firmware.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
  - Changed filename_store() to use kmemdup_nul() instead of
kstrndup() and changed the count to not assume a line-return.
v6:
  - Changed "security update" to "secure update" in commit message
v5:
  - When checking the return values for functions of type enum
fpga_sec_err err_code, test for FPGA_SEC_ERR_NONE instead of 0
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Removed unnecessary "goto done"
  - Added a comment to explain imgr->driver_unload in
ifpga_sec_mgr_unregister()
v2:
  - Bumped documentation date and version
  - Removed explicit value assignments in enums
  - Other minor code cleanup per review comments 
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  |  13 ++
 drivers/fpga/fpga-sec-mgr.c   | 164 ++
 include/linux/fpga/fpga-sec-mgr.h |  49 ++
 3 files changed, 226 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 0dda4604c178..4c0bdfd25553 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -3,3 +3,16 @@ Date:      April 2021
 KernelVersion:  5.13
 Contact:   Russ Weight 
 Description:   Name of low level fpga security manager driver.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/filename
+Date:      April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Write only. Write the filename of an image
+   file to this sysfs file to initiate a secure
+   update. The file must have an appropriate header
+   which, among other things, identifies the target
+   for the update. This mechanism is used to update
+   BMC images, BMC firmware, Static Region images,
+   and Root Entry Hashes, and to cancel Code Signing
+   Keys (CSK).
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 468379e0c825..7347ba1ba73e 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -5,8 +5,11 @@
  * Copyright (C) 2019-2020 Intel Corporation, Inc.
  */
 
+#include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -18,8 +21,140 @@ struct fpga_sec_mgr_devres {
struct fpga_sec_mgr *smgr;
 };
 
+#define WRITE_BLOCK_SIZE 0x4000/* Update remaining_size every 0x4000 
bytes */
+
 #define to_sec_mgr(d) container_of(d, struct fpga_sec_mgr, dev)
 
+static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
+  enum fpga_sec_err err_code)
+{
+   smgr->err_code = err_code;
+   smgr->sops->cancel(smgr);
+}
+
+static void progress_complete(struct fpga_sec_mgr *smgr)
+{
+   mutex_lock(>lock);
+   smgr->progress = FPGA_SEC_PROG_IDLE;
+   complete_all(>update_done);
+   mutex_unlock(>lock);
+}
+
+static void fpga_sec_mgr_update(struct work_struct *work)
+{
+   u32 size, blk_size, offset = 0;
+   struct fpga_sec_mgr *smgr;
+   const struct firmware *fw;
+   enum fpga_sec_err ret;
+
+   smgr = container_of(work, struct fpga_sec_mgr, work);
+
+   get_device(>dev);
+   if (request_firmware(, smgr->filename, >dev)) {
+   smgr->err_code = FPGA_SEC_ERR_FILE_READ;
+   goto idle_exit;
+   }
+
+   smgr->data = fw->data;
+   smgr->remaining_size = fw->size;
+
+   if (!try_module_get(smgr->dev.parent->driver->owner)) {
+   smgr->err_code = FPGA_SEC_ERR_BUSY;
+   goto release_fw_exit;
+   }
+
+   smgr->progress = FPGA_SEC_PROG_PREPARING;
+   ret = smgr->sops->prepare(smgr);
+   if (ret != FPGA_SEC_ERR_NONE) {
+   fpga_sec_dev_error(smgr, ret);
+   goto modput_exit;
+   }
+
+   smgr->progress = FPGA_SE

[RESEND PATCH v10 1/7] fpga: sec-mgr: fpga security manager class driver

2021-03-22 Thread Russ Weight
Create the FPGA Security Manager class driver. The security
manager provides interfaces to manage secure updates for the
FPGA and BMC images that are stored in FLASH. The driver can
also be used to update root entry hashes and to cancel code
signing keys. The image type is encoded in the image file
and is decoded by the HW/FW secure update engine.

Signed-off-by: Russ Weight 
Signed-off-by: Xu Yilun 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Fixed grammatical error in Documentation/fpga/fpga-sec-mgr.rst
v7:
  - Changed Date in documentation file to December 2020
v6:
  - Removed sysfs support and documentation for the display of the
flash count, root entry hashes, and code-signing-key cancelation
vectors.
v5:
  - Added the devm_fpga_sec_mgr_unregister() function, following recent
changes to the fpga_manager() implementation.
  - Changed some *_show() functions to use sysfs_emit() instead of sprintf(
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Modified sysfs handler check in check_sysfs_handler() to make
it more readable.
v2:
  - Bumped documentation dates and versions
  - Added Documentation/fpga/ifpga-sec-mgr.rst 
  - Removed references to bmc_flash_count & smbus_flash_count (not supported)
  - Split ifpga_sec_mgr_register() into create() and register() functions
  - Added devm_ifpga_sec_mgr_create()
  - Removed typedefs for imgr ops
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  |   5 +
 Documentation/fpga/fpga-sec-mgr.rst   |  44 +++
 Documentation/fpga/index.rst  |   1 +
 MAINTAINERS   |   9 +
 drivers/fpga/Kconfig  |   9 +
 drivers/fpga/Makefile |   3 +
 drivers/fpga/fpga-sec-mgr.c   | 296 ++
 include/linux/fpga/fpga-sec-mgr.h |  44 +++
 8 files changed, 411 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
 create mode 100644 Documentation/fpga/fpga-sec-mgr.rst
 create mode 100644 drivers/fpga/fpga-sec-mgr.c
 create mode 100644 include/linux/fpga/fpga-sec-mgr.h

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
new file mode 100644
index ..0dda4604c178
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -0,0 +1,5 @@
+What:  /sys/class/fpga_sec_mgr/fpga_secX/name
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Name of low level fpga security manager driver.
diff --git a/Documentation/fpga/fpga-sec-mgr.rst 
b/Documentation/fpga/fpga-sec-mgr.rst
new file mode 100644
index ..9f74c29fe63d
--- /dev/null
+++ b/Documentation/fpga/fpga-sec-mgr.rst
@@ -0,0 +1,44 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+
+FPGA Security Manager Class Driver
+
+
+The FPGA Security Manager class driver provides a common
+API for user-space tools to manage updates for secure FPGA
+devices. Device drivers that instantiate the Security
+Manager class driver will interact with a HW secure update
+engine in order to transfer new FPGA and BMC images to FLASH so
+that they will be automatically loaded when the FPGA card reboots.
+
+A significant difference between the FPGA Manager and the FPGA
+Security Manager is that the FPGA Manager does a live update (Partial
+Reconfiguration) to a device, whereas the FPGA Security Manager
+updates the FLASH images for the Static Region and the BMC so that
+they will be loaded the next time the FPGA card boots. Security is
+enforced by hardware and firmware. The security manager interacts
+with the firmware to initiate an update, pass in the necessary data,
+and collect status on the update.
+
+In addition to managing secure updates of the FPGA and BMC images,
+the FPGA Security Manager update process may also be used to
+program root entry hashes and cancellation keys for the FPGA static
+region, the FPGA partial reconfiguration region, and the BMC.
+
+Secure updates make use of the request_firmware framework, which
+requires that image files are accessible under /lib/firmware. A request
+for a secure update returns immediately, while the update itself
+proceeds in the context of a kernel worker thread. Sysfs files provide
+a means for monitoring the progress of a secure update and for
+retrieving error information in the event of a failure.
+
+Sysfs Attributes
+
+
+The API includes a sysfs entry *name* to export the name of the parent
+driver. It also includes an *update* sub-directory that c

[RESEND PATCH v10 0/7] FPGA Security Manager Class Driver

2021-03-22 Thread Russ Weight
The FPGA Security Manager class driver provides a common
API for user-space tools to manage updates for secure FPGA
devices. Device drivers that instantiate the FPGA Security
Manager class driver will interact with a HW secure update
engine in order to transfer new FPGA and BMC images to FLASH so
that they will be automatically loaded when the FPGA card reboots.

A significant difference between the FPGA Manager and the FPGA 
Security Manager is that the FPGA Manager does a live update (Partial
Reconfiguration) to a device whereas the FPGA Security Manager
updates the FLASH images for the Static Region and the BMC so that
they will be loaded the next time the FPGA card boots. Security is
enforced by hardware and firmware. The security manager interacts
with the firmware to initiate an update, pass in the necessary data,
and collect status on the update.

The n3000bmc-secure driver is the first driver to use the FPGA
Security Manager. This driver was previously submitted in the same
patch set, but has been split out into a separate patch set starting
with V2. Future devices will also make use of this common API for
secure updates.

In addition to managing secure updates of the FPGA and BMC images,
the FPGA Security Manager update process may also be used to
program root entry hashes and cancellation keys for the FPGA static
region, the FPGA partial reconfiguration region, and the BMC.
The image files are self-describing, and contain a header describing
the image type.

Secure updates make use of the request_firmware framework, which
requires that image files are accessible under /lib/firmware. A request
for a secure update returns immediately, while the update itself
proceeds in the context of a kernel worker thread. Sysfs files provide
a means for monitoring the progress of a secure update and for
retrieving error information in the event of a failure.

The API includes a "name" sysfs file to export the name of the parent
driver. It also includes an "update" sub-directory containing files that
that can be used to instantiate and monitor a secure update.

Changelog v9 -> v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation

Changelog v8 -> v9:
  - Rebased patches for 5.11-rc2
  - Updated Date and KernelVersion in ABI documentation

Changelog v7 -> v8:
  - Fixed grammatical error in Documentation/fpga/fpga-sec-mgr.rst

Changelog v6 -> v7:
  - Changed dates in documentation file to December 2020
  - Changed filename_store() to use kmemdup_nul() instead of
kstrndup() and changed the count to not assume a line-return.

Changelog v5 -> v6:
  - Removed sysfs support and documentation for the display of the
flash count, root entry hashes, and code-signing-key cancelation
vectors from the class driver. This information can vary by device
and will instead be displayed by the device-specific parent driver.

Changelog v4 -> v5:
  - Added the devm_fpga_sec_mgr_unregister() function, following recent
changes to the fpga_manager() implementation.
  - Changed most of the *_show() functions to use sysfs_emit()
instead of sprintf(
  - When checking the return values for functions of type enum
fpga_sec_err err_code, test for FPGA_SEC_ERR_NONE instead of 0

Changelog v3 -> v4:
  - This driver is generic enough that it could be used for non Intel
FPGA devices. Changed from "Intel FPGA Security Manager" to FPGA
Security Manager" and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
Note that this also affects some filenames.

Changelog v2 -> v3:
  - Use dev_err() to report invalid progress in sec_progress()
  - Use dev_err() to report invalid error code in sec_error()
  - Modified sysfs handler check in check_sysfs_handler() to make
it more readable.
  - Removed unnecessary "goto done"
  - Added a comment to explain imgr->driver_unload in
ifpga_sec_mgr_unregister()

Changelog v1 -> v2:
  - Separated out the MAX10 BMC Security Engine to be submitted in
a separate patch-set.
  - Bumped documentation dates and versions
  - Split ifpga_sec_mgr_register() into create() and register() functions
  - Added devm_ifpga_sec_mgr_create()
  - Added Documentation/fpga/ifpga-sec-mgr.rst 
  - Changed progress state "read_file" to "reading"
  - Added sec_error() function (similar to sec_progress())
  - Removed references to bmc_flash_count & smbus_flash_count (not supported)
  - Removed typedefs for imgr ops
  - Removed explicit value assignments in enums
  - Other minor code cleanup per review comments 

Russ Weight (7):
  fpga: sec-mgr: fpga security manager class driver
  fpga: sec-mgr: enable secure updates
  fpga: sec-mgr: expose sec-mgr update status
  fpga: sec-mgr: expose sec-mgr update errors
  fpga: sec-mgr: expose sec-mgr update size
  fpga: sec-mgr: enable can

[PATCH v11 5/5] fpga: m10bmc-sec: add max10 get_hw_errinfo callback func

2021-03-15 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to include
a function that returns 64 bits of additional HW specific
data for errors that require additional information.
This callback function enables the hw_errinfo sysfs
node in the Intel Security Manager class driver.

Signed-off-by: Russ Weight 
---
v11:
  - No change
v10:
  - No change
v9:
  - No change
v8:
  - Previously patch 6/6, otherwise no change
v7:
  - No change
v6:
  - Initialized auth_result and doorbell to HW_ERRINFO_POISON
in m10bmc_sec_hw_errinfo() and removed unnecessary if statements.
v5:
  - No change
v4:
  - No change
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
v2:
  - Implemented HW_ERRINFO_POISON for m10bmc_sec_hw_errinfo() to
ensure that corresponding bits are set to 1 if we are unable
to read the doorbell or auth_result registers.
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 drivers/fpga/intel-m10-bmc-secure.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index a290fcc4df4a..3a049c98cf43 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -476,11 +476,33 @@ static enum fpga_sec_err m10bmc_sec_cancel(struct 
fpga_sec_mgr *smgr)
return ret ? FPGA_SEC_ERR_RW_ERROR : FPGA_SEC_ERR_NONE;
 }
 
+#define HW_ERRINFO_POISON  GENMASK(31, 0)
+static u64 m10bmc_sec_hw_errinfo(struct fpga_sec_mgr *smgr)
+{
+   struct m10bmc_sec *sec = smgr->priv;
+   u32 auth_result = HW_ERRINFO_POISON;
+   u32 doorbell = HW_ERRINFO_POISON;
+
+   switch (smgr->err_code) {
+   case FPGA_SEC_ERR_HW_ERROR:
+   case FPGA_SEC_ERR_TIMEOUT:
+   case FPGA_SEC_ERR_BUSY:
+   case FPGA_SEC_ERR_WEAROUT:
+   m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, );
+   m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, _result);
+
+   return (u64)doorbell << 32 | (u64)auth_result;
+   default:
+   return 0;
+   }
+}
+
 static const struct fpga_sec_mgr_ops m10bmc_sops = {
.prepare = m10bmc_sec_prepare,
.write_blk = m10bmc_sec_write_blk,
.poll_complete = m10bmc_sec_poll_complete,
.cancel = m10bmc_sec_cancel,
+   .get_hw_errinfo = m10bmc_sec_hw_errinfo,
 };
 
 static int m10bmc_secure_probe(struct platform_device *pdev)
-- 
2.25.1



[PATCH v11 2/5] fpga: m10bmc-sec: expose max10 flash update count

2021-03-15 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to provide a
sysfs file to expose the flash update count for the FPGA
user image.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v11:
  - No change
v10:
  - Changed the path expression in the sysfs documentation to
replace the n3000 reference with something more generic to
accomodate other devices that use the same driver.
v9:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Previously patch 3/6, otherwise no change
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Changed flash_count_show() parameter list to achieve
reverse-christmas tree format.
  - Added WARN_ON() call for (FLASH_COUNT_SIZE / stride) to ensure
that the proper count is passed to regmap_bulk_read().
v5:
  - Renamed sysfs node user_flash_count to flash_count and updated the
sysfs documentation accordingly.
v4:
  - Moved the sysfs file for displaying the flash count from the
FPGA Security Manager class driver to here. The
m10bmc_user_flash_count() function is removed and the
functionality is moved into a user_flash_count_show()
function.
  - Added ABI documentation for the new sysfs entry
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
v2:
  - Renamed get_qspi_flash_count() to m10bmc_user_flash_count()
  - Minor code cleanup per review comments
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 .../testing/sysfs-driver-intel-m10-bmc-secure |  8 
 drivers/fpga/intel-m10-bmc-secure.c   | 37 +++
 2 files changed, 45 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
index bd3ee9bc1a92..598db1116d34 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -27,3 +27,11 @@ Description: Read only. Returns the root entry hash for the 
BMC image
"hash not programmed".  This file is only visible if the
underlying device supports it.
Format: "0x%x".
+
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/flash_count
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns number of times the secure update
+   staging area has been flashed.
+   Format: "%u".
diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index 5ac5f59b5731..ecd63c13cb2d 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct m10bmc_sec {
struct device *dev;
@@ -78,7 +79,43 @@ DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, 
BMC_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
 
+#define FLASH_COUNT_SIZE 4096  /* count stored as inverted bit vector */
+
+static ssize_t flash_count_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct m10bmc_sec *sec = dev_get_drvdata(dev);
+   unsigned int stride, num_bits;
+   u8 *flash_buf;
+   int cnt, ret;
+
+   stride = regmap_get_reg_stride(sec->m10bmc->regmap);
+   num_bits = FLASH_COUNT_SIZE * 8;
+
+   flash_buf = kmalloc(FLASH_COUNT_SIZE, GFP_KERNEL);
+   if (!flash_buf)
+   return -ENOMEM;
+
+   WARN_ON(FLASH_COUNT_SIZE % stride);
+   ret = regmap_bulk_read(sec->m10bmc->regmap, STAGING_FLASH_COUNT,
+  flash_buf, FLASH_COUNT_SIZE / stride);
+   if (ret) {
+   dev_err(sec->dev,
+   "failed to read flash count: %x cnt %x: %d\n",
+   STAGING_FLASH_COUNT, FLASH_COUNT_SIZE / stride, ret);
+   goto exit_free;
+   }
+   cnt = num_bits - bitmap_weight((unsigned long *)flash_buf, num_bits);
+
+exit_free:
+   kfree(flash_buf);
+
+   return ret ? : sysfs_emit(buf, "%u\n", cnt);
+}
+static DEVICE_ATTR_RO(flash_count);
+
 static struct attribute *m10bmc_security_attrs[] = {
+   _attr_flash_count.attr,
_attr_bmc_root_entry_hash.attr,
_attr_sr_root_entry_hash.attr,
_attr_pr_root_entry_hash.attr,
-- 
2.25.1



[PATCH v11 3/5] fpga: m10bmc-sec: expose max10 canceled keys in sysfs

2021-03-15 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to provide sysfs
files to expose the canceled code signing key (CSK) bit
vectors. These use the standard bitmap list format
(e.g. 1,2-6,9).

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v11:
  - No change
v10:
  - Changed the path expressions in the sysfs documentation to
replace the n3000 reference with something more generic to
accomodate other devices that use the same driver.
v9:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Previously patch 4/6, otherwise no change
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Added WARN_ON() call for (size / stride) to ensure
that the proper count is passed to regmap_bulk_read().
v5:
  - No change
v4:
  - Moved sysfs files for displaying the code-signing-key (CSK)
cancellation vectors from the FPGA Security Manger class driver
to here. The m10bmc_csk_vector() and m10bmc_csk_cancel_nbits()
functions are removed and the functionality from these functions
is moved into a show_canceled_csk() function for for displaying
the CSK vectors.
  - Added ABI documentation for new sysfs entries
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Renamed get_csk_vector() to m10bmc_csk_vector()
v2:
  - Replaced small function-creation macros for explicit function
declarations.
  - Fixed get_csk_vector() function to properly apply the stride
variable in calls to m10bmc_raw_bulk_read()
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 .../testing/sysfs-driver-intel-m10-bmc-secure | 24 ++
 drivers/fpga/intel-m10-bmc-secure.c   | 48 +++
 2 files changed, 72 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
index 598db1116d34..93ad4de9b941 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -28,6 +28,30 @@ Description: Read only. Returns the root entry hash for the 
BMC image
underlying device supports it.
Format: "0x%x".
 
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/sr_canceled_csks
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the static region. The standard bitmap
+   list format is used (e.g. "1,2-6,9").
+
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/pr_canceled_csks
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the partial reconfiguration region. The
+   standard bitmap list format is used (e.g. "1,2-6,9").
+
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/bmc_canceled_csks
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the BMC.  The standard bitmap list format
+   is used (e.g. "1,2-6,9").
+
 What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/flash_count
 Date:  April 2021
 KernelVersion:  5.13
diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index ecd63c13cb2d..87e16c146569 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -79,6 +79,51 @@ DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, 
BMC_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
 
+#define CSK_BIT_LEN128U
+#define CSK_32ARRAY_SIZE   DIV_ROUND_UP(CSK_BIT_LEN, 32)
+
+static ssize_t
+show_canceled_csk(struct device *dev, u32 addr, char *buf)
+{
+   unsigned int i, stride, size = CSK_32ARRAY_SIZE * sizeof(u32);
+   struct m10bmc_sec *sec = dev_get_drvdata(dev);
+   DECLARE_BITMAP(csk_map, CSK_BIT_LEN);
+   __le32 csk_le32[CSK_32ARRAY_SIZE];
+   u32 csk32[CSK_32ARRAY_SIZE];
+   int ret;
+
+   stride = regmap_get_reg_stride(sec->m10bmc->regmap);
+
+   WARN_ON(size % stride);
+   ret = regmap_bulk_read(sec->m10bmc->regmap, addr, csk_le32,
+  size / stride);
+   if (ret) {
+   dev_err(sec->dev, "failed to read CSK vector: %x cnt

[PATCH v11 4/5] fpga: m10bmc-sec: add max10 secure update functions

2021-03-15 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to include
the functions that enable secure updates of BMC images,
FPGA images, etc.

Signed-off-by: Russ Weight 
---
v11:
  - No change
v10:
  - No change
v9:
  - No change
v8:
  - Previously patch 5/6, otherwise no change
v7:
  - No change
v6:
  - Changed (size / stride) calculation to ((size + stride - 1) / stride)
to ensure that the proper count is passed to regmap_bulk_write().
  - Removed unnecessary call to rsu_check_complete() in
m10bmc_sec_poll_complete() and changed while loop to
do/while loop.
v5:
  - No change
v4:
  - No change
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed calling functions of functions that return "enum fpga_sec_err"
to check for (ret != FPGA_SEC_ERR_NONE) instead of (ret)
v2:
  - Reworked the rsu_start_done() function to make it more readable
  - Reworked while-loop condition/content in rsu_prog_ready()
  - Minor code cleanup per review comments
  - Added a comment to the m10bmc_sec_poll_complete() function to
explain the context (could take 30+ minutes to complete).
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
  - Moved MAX10 BMC address and function definitions to a separate
patch.
---
 drivers/fpga/intel-m10-bmc-secure.c | 303 +++-
 1 file changed, 302 insertions(+), 1 deletion(-)

diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index 87e16c146569..a290fcc4df4a 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -180,7 +180,308 @@ static const struct attribute_group 
*m10bmc_sec_attr_groups[] = {
NULL,
 };
 
-static const struct fpga_sec_mgr_ops m10bmc_sops = { };
+static void log_error_regs(struct m10bmc_sec *sec, u32 doorbell)
+{
+   u32 auth_result;
+
+   dev_err(sec->dev, "RSU error status: 0x%08x\n", doorbell);
+
+   if (!m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, _result))
+   dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result);
+}
+
+static enum fpga_sec_err rsu_check_idle(struct m10bmc_sec *sec)
+{
+   u32 doorbell;
+   int ret;
+
+   ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, );
+   if (ret)
+   return FPGA_SEC_ERR_RW_ERROR;
+
+   if (rsu_prog(doorbell) != RSU_PROG_IDLE &&
+   rsu_prog(doorbell) != RSU_PROG_RSU_DONE) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_BUSY;
+   }
+
+   return FPGA_SEC_ERR_NONE;
+}
+
+static inline bool rsu_start_done(u32 doorbell)
+{
+   u32 status, progress;
+
+   if (doorbell & DRBL_RSU_REQUEST)
+   return false;
+
+   status = rsu_stat(doorbell);
+   if (status == RSU_STAT_ERASE_FAIL || status == RSU_STAT_WEAROUT)
+   return true;
+
+   progress = rsu_prog(doorbell);
+   if (progress != RSU_PROG_IDLE && progress != RSU_PROG_RSU_DONE)
+   return true;
+
+   return false;
+}
+
+static enum fpga_sec_err rsu_update_init(struct m10bmc_sec *sec)
+{
+   u32 doorbell, status;
+   int ret;
+
+   ret = regmap_update_bits(sec->m10bmc->regmap,
+M10BMC_SYS_BASE + M10BMC_DOORBELL,
+DRBL_RSU_REQUEST | DRBL_HOST_STATUS,
+DRBL_RSU_REQUEST |
+FIELD_PREP(DRBL_HOST_STATUS,
+   HOST_STATUS_IDLE));
+   if (ret)
+   return FPGA_SEC_ERR_RW_ERROR;
+
+   ret = regmap_read_poll_timeout(sec->m10bmc->regmap,
+  M10BMC_SYS_BASE + M10BMC_DOORBELL,
+  doorbell,
+  rsu_start_done(doorbell),
+  NIOS_HANDSHAKE_INTERVAL_US,
+  NIOS_HANDSHAKE_TIMEOUT_US);
+
+   if (ret == -ETIMEDOUT) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_TIMEOUT;
+   } else if (ret) {
+   return FPGA_SEC_ERR_RW_ERROR;
+   }
+
+   status = rsu_stat(doorbell);
+   if (status == RSU_STAT_WEAROUT) {
+   dev_warn(sec->dev, "Excessive flash update count detected\n");
+   return FPGA_SEC_ERR_WEAROUT;
+   } else if (status == RSU_STAT_ERASE_FAIL) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_HW_ERROR;
+   }
+
+   return FPGA_SEC_ERR_NONE;
+}
+
+static enum fpga_sec_err rsu_prog_ready(struct m10bmc_sec *sec)
+{
+   unsigned long poll_ti

[PATCH v11 1/5] fpga: m10bmc-sec: create max10 bmc secure update driver

2021-03-15 Thread Russ Weight
Create a platform driver that can be invoked as a sub
driver for the Intel MAX10 BMC in order to support
secure updates. This sub-driver will invoke an
instance of the FPGA Security Manager class driver
in order to expose sysfs interfaces for managing and
monitoring secure updates to FPGA and BMC images.

This patch creates the MAX10 BMC Secure Update driver and
provides sysfs files for displaying the current root entry hashes
for the FPGA static region, the FPGA PR region, and the MAX10
BMC.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v11:
  - Added Reviewed-by tag
v10:
  - Changed the path expressions in the sysfs documentation to
replace the n3000 reference with something more generic to
accomodate other devices that use the same driver.
v9:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Previously patch 2/6, otherwise no change
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Added WARN_ON() call for (sha_num_bytes / stride) to assert
that the proper count is passed to regmap_bulk_read().
v5:
  - No change
v4:
  - Moved sysfs files for displaying the root entry hashes (REH)
from the FPGA Security Manager class driver to here. The
m10bmc_reh() and m10bmc_reh_size() functions are removed and
the functionality from these functions is moved into a
show_root_entry_hash() function for displaying the REHs.
  - Added ABI documentation for the new sysfs entries:
sysfs-driver-intel-m10-bmc-secure
  - Updated the MAINTAINERS file to add the new ABI documentation
file: sysfs-driver-intel-m10-bmc-secure
  - Removed unnecessary ret variable from m10bmc_secure_probe()
  - Incorporated new devm_fpga_sec_mgr_register() function into
m10bmc_secure_probe() and removed the m10bmc_secure_remove()
function.
v3:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure
Update driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed "_root_entry_hash" to "_reh", with a comment explaining
what reh is.
v2:
  - Added drivers/fpga/intel-m10-bmc-secure.c file to MAINTAINERS.
  - Switched to GENMASK(31, 16) for a couple of mask definitions.
  - Moved MAX10 BMC address and function definitions to a separate
patch.
  - Replaced small function-creation macros with explicit function
declarations.
  - Removed ifpga_sec_mgr_init() and ifpga_sec_mgr_uinit() functions.
  - Adapted to changes in the Intel FPGA Security Manager by splitting
the single call to ifpga_sec_mgr_register() into two function
calls: devm_ifpga_sec_mgr_create() and ifpga_sec_mgr_register().
---
 .../testing/sysfs-driver-intel-m10-bmc-secure |  29 
 MAINTAINERS   |   2 +
 drivers/fpga/Kconfig  |  11 ++
 drivers/fpga/Makefile |   3 +
 drivers/fpga/intel-m10-bmc-secure.c   | 135 ++
 5 files changed, 180 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
 create mode 100644 drivers/fpga/intel-m10-bmc-secure.c

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
new file mode 100644
index ..bd3ee9bc1a92
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -0,0 +1,29 @@
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/sr_root_entry_hash
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the static
+   region if one is programmed, else it returns the
+   string: "hash not programmed".  This file is only
+   visible if the underlying device supports it.
+   Format: "0x%x".
+
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/pr_root_entry_hash
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the partial
+   reconfiguration region if one is programmed, else it
+   returns the string: "hash not programmed".  This file
+   is only visible if the underlying device supports it.
+   Format: "0x%x".
+
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/bmc_root_entry_hash
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the BMC image
+   if one is programmed, else it returns the string:
+  

[PATCH v11 0/5] Intel MAX10 BMC Secure Update Driver

2021-03-15 Thread Russ Weight
_vector() function to properly apply the
stride variable in calls to m10bmc_raw_bulk_read().
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
  - Implemented HW_ERRINFO_POISON for m10bmc_sec_hw_errinfo() to
ensure that corresponding bits are set to 1 if we are unable
to read the doorbell or auth_result registers.
  - Added comments and additional code cleanup per V1 review.


Russ Weight (5):
  fpga: m10bmc-sec: create max10 bmc secure update driver
  fpga: m10bmc-sec: expose max10 flash update count
  fpga: m10bmc-sec: expose max10 canceled keys in sysfs
  fpga: m10bmc-sec: add max10 secure update functions
  fpga: m10bmc-sec: add max10 get_hw_errinfo callback func

 .../testing/sysfs-driver-intel-m10-bmc-secure |  61 ++
 MAINTAINERS   |   2 +
 drivers/fpga/Kconfig  |  11 +
 drivers/fpga/Makefile |   3 +
 drivers/fpga/intel-m10-bmc-secure.c   | 543 ++
 5 files changed, 620 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
 create mode 100644 drivers/fpga/intel-m10-bmc-secure.c

-- 
2.25.1



[PATCH v10 3/5] fpga: m10bmc-sec: expose max10 canceled keys in sysfs

2021-03-12 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to provide sysfs
files to expose the canceled code signing key (CSK) bit
vectors. These use the standard bitmap list format
(e.g. 1,2-6,9).

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Changed the path expressions in the sysfs documentation to
replace the n3000 reference with something more generic to
accomodate other devices that use the same driver.
v9:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Previously patch 4/6, otherwise no change
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Added WARN_ON() call for (size / stride) to ensure
that the proper count is passed to regmap_bulk_read().
v5:
  - No change
v4:
  - Moved sysfs files for displaying the code-signing-key (CSK)
cancellation vectors from the FPGA Security Manger class driver
to here. The m10bmc_csk_vector() and m10bmc_csk_cancel_nbits()
functions are removed and the functionality from these functions
is moved into a show_canceled_csk() function for for displaying
the CSK vectors.
  - Added ABI documentation for new sysfs entries
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Renamed get_csk_vector() to m10bmc_csk_vector()
v2:
  - Replaced small function-creation macros for explicit function
declarations.
  - Fixed get_csk_vector() function to properly apply the stride
variable in calls to m10bmc_raw_bulk_read()
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 .../testing/sysfs-driver-intel-m10-bmc-secure | 24 ++
 drivers/fpga/intel-m10-bmc-secure.c   | 48 +++
 2 files changed, 72 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
index 598db1116d34..93ad4de9b941 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -28,6 +28,30 @@ Description: Read only. Returns the root entry hash for the 
BMC image
underlying device supports it.
Format: "0x%x".
 
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/sr_canceled_csks
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the static region. The standard bitmap
+   list format is used (e.g. "1,2-6,9").
+
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/pr_canceled_csks
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the partial reconfiguration region. The
+   standard bitmap list format is used (e.g. "1,2-6,9").
+
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/bmc_canceled_csks
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the BMC.  The standard bitmap list format
+   is used (e.g. "1,2-6,9").
+
 What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/flash_count
 Date:  April 2021
 KernelVersion:  5.13
diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index ecd63c13cb2d..87e16c146569 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -79,6 +79,51 @@ DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, 
BMC_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
 
+#define CSK_BIT_LEN128U
+#define CSK_32ARRAY_SIZE   DIV_ROUND_UP(CSK_BIT_LEN, 32)
+
+static ssize_t
+show_canceled_csk(struct device *dev, u32 addr, char *buf)
+{
+   unsigned int i, stride, size = CSK_32ARRAY_SIZE * sizeof(u32);
+   struct m10bmc_sec *sec = dev_get_drvdata(dev);
+   DECLARE_BITMAP(csk_map, CSK_BIT_LEN);
+   __le32 csk_le32[CSK_32ARRAY_SIZE];
+   u32 csk32[CSK_32ARRAY_SIZE];
+   int ret;
+
+   stride = regmap_get_reg_stride(sec->m10bmc->regmap);
+
+   WARN_ON(size % stride);
+   ret = regmap_bulk_read(sec->m10bmc->regmap, addr, csk_le32,
+  size / stride);
+   if (ret) {
+   dev_err(sec->dev, "failed to read CSK vector: %x cnt %x: %d\n",
+ 

[PATCH v10 2/5] fpga: m10bmc-sec: expose max10 flash update count

2021-03-12 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to provide a
sysfs file to expose the flash update count for the FPGA
user image.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Changed the path expression in the sysfs documentation to
replace the n3000 reference with something more generic to
accomodate other devices that use the same driver.
v9:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Previously patch 3/6, otherwise no change
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Changed flash_count_show() parameter list to achieve
reverse-christmas tree format.
  - Added WARN_ON() call for (FLASH_COUNT_SIZE / stride) to ensure
that the proper count is passed to regmap_bulk_read().
v5:
  - Renamed sysfs node user_flash_count to flash_count and updated the
sysfs documentation accordingly.
v4:
  - Moved the sysfs file for displaying the flash count from the
FPGA Security Manager class driver to here. The
m10bmc_user_flash_count() function is removed and the
functionality is moved into a user_flash_count_show()
function.
  - Added ABI documentation for the new sysfs entry
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
v2:
  - Renamed get_qspi_flash_count() to m10bmc_user_flash_count()
  - Minor code cleanup per review comments
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 .../testing/sysfs-driver-intel-m10-bmc-secure |  8 
 drivers/fpga/intel-m10-bmc-secure.c   | 37 +++
 2 files changed, 45 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
index bd3ee9bc1a92..598db1116d34 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -27,3 +27,11 @@ Description: Read only. Returns the root entry hash for the 
BMC image
"hash not programmed".  This file is only visible if the
underlying device supports it.
Format: "0x%x".
+
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/flash_count
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns number of times the secure update
+   staging area has been flashed.
+   Format: "%u".
diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index 5ac5f59b5731..ecd63c13cb2d 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct m10bmc_sec {
struct device *dev;
@@ -78,7 +79,43 @@ DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, 
BMC_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
 
+#define FLASH_COUNT_SIZE 4096  /* count stored as inverted bit vector */
+
+static ssize_t flash_count_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct m10bmc_sec *sec = dev_get_drvdata(dev);
+   unsigned int stride, num_bits;
+   u8 *flash_buf;
+   int cnt, ret;
+
+   stride = regmap_get_reg_stride(sec->m10bmc->regmap);
+   num_bits = FLASH_COUNT_SIZE * 8;
+
+   flash_buf = kmalloc(FLASH_COUNT_SIZE, GFP_KERNEL);
+   if (!flash_buf)
+   return -ENOMEM;
+
+   WARN_ON(FLASH_COUNT_SIZE % stride);
+   ret = regmap_bulk_read(sec->m10bmc->regmap, STAGING_FLASH_COUNT,
+  flash_buf, FLASH_COUNT_SIZE / stride);
+   if (ret) {
+   dev_err(sec->dev,
+   "failed to read flash count: %x cnt %x: %d\n",
+   STAGING_FLASH_COUNT, FLASH_COUNT_SIZE / stride, ret);
+   goto exit_free;
+   }
+   cnt = num_bits - bitmap_weight((unsigned long *)flash_buf, num_bits);
+
+exit_free:
+   kfree(flash_buf);
+
+   return ret ? : sysfs_emit(buf, "%u\n", cnt);
+}
+static DEVICE_ATTR_RO(flash_count);
+
 static struct attribute *m10bmc_security_attrs[] = {
+   _attr_flash_count.attr,
_attr_bmc_root_entry_hash.attr,
_attr_sr_root_entry_hash.attr,
_attr_pr_root_entry_hash.attr,
-- 
2.25.1



[PATCH v10 1/5] fpga: m10bmc-sec: create max10 bmc secure update driver

2021-03-12 Thread Russ Weight
Create a platform driver that can be invoked as a sub
driver for the Intel MAX10 BMC in order to support
secure updates. This sub-driver will invoke an
instance of the FPGA Security Manager class driver
in order to expose sysfs interfaces for managing and
monitoring secure updates to FPGA and BMC images.

This patch creates the MAX10 BMC Secure Update driver and
provides sysfs files for displaying the current root entry hashes
for the FPGA static region, the FPGA PR region, and the MAX10
BMC.

Signed-off-by: Russ Weight 
---
v10:
  - Changed the path expressions in the sysfs documentation to
replace the n3000 reference with something more generic to
accomodate other devices that use the same driver.
v9:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Previously patch 2/6, otherwise no change
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Added WARN_ON() call for (sha_num_bytes / stride) to assert
that the proper count is passed to regmap_bulk_read().
v5:
  - No change
v4:
  - Moved sysfs files for displaying the root entry hashes (REH)
from the FPGA Security Manager class driver to here. The
m10bmc_reh() and m10bmc_reh_size() functions are removed and
the functionality from these functions is moved into a
show_root_entry_hash() function for displaying the REHs.
  - Added ABI documentation for the new sysfs entries:
sysfs-driver-intel-m10-bmc-secure
  - Updated the MAINTAINERS file to add the new ABI documentation
file: sysfs-driver-intel-m10-bmc-secure
  - Removed unnecessary ret variable from m10bmc_secure_probe()
  - Incorporated new devm_fpga_sec_mgr_register() function into
m10bmc_secure_probe() and removed the m10bmc_secure_remove()
function.
v3:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure
Update driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed "_root_entry_hash" to "_reh", with a comment explaining
what reh is.
v2:
  - Added drivers/fpga/intel-m10-bmc-secure.c file to MAINTAINERS.
  - Switched to GENMASK(31, 16) for a couple of mask definitions.
  - Moved MAX10 BMC address and function definitions to a separate
patch.
  - Replaced small function-creation macros with explicit function
declarations.
  - Removed ifpga_sec_mgr_init() and ifpga_sec_mgr_uinit() functions.
  - Adapted to changes in the Intel FPGA Security Manager by splitting
the single call to ifpga_sec_mgr_register() into two function
calls: devm_ifpga_sec_mgr_create() and ifpga_sec_mgr_register().
---
 .../testing/sysfs-driver-intel-m10-bmc-secure |  29 
 MAINTAINERS   |   2 +
 drivers/fpga/Kconfig  |  11 ++
 drivers/fpga/Makefile |   3 +
 drivers/fpga/intel-m10-bmc-secure.c   | 135 ++
 5 files changed, 180 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
 create mode 100644 drivers/fpga/intel-m10-bmc-secure.c

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
new file mode 100644
index ..bd3ee9bc1a92
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -0,0 +1,29 @@
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/sr_root_entry_hash
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the static
+   region if one is programmed, else it returns the
+   string: "hash not programmed".  This file is only
+   visible if the underlying device supports it.
+   Format: "0x%x".
+
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/pr_root_entry_hash
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the partial
+   reconfiguration region if one is programmed, else it
+   returns the string: "hash not programmed".  This file
+   is only visible if the underlying device supports it.
+   Format: "0x%x".
+
+What:  
/sys/bus/platform/drivers/intel-m10bmc-secure/.../security/bmc_root_entry_hash
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the BMC image
+   if one is programmed, else it returns the string:
+   "hash not programmed".  This fil

[PATCH v10 4/5] fpga: m10bmc-sec: add max10 secure update functions

2021-03-12 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to include
the functions that enable secure updates of BMC images,
FPGA images, etc.

Signed-off-by: Russ Weight 
---
v10:
  - No change
v9:
  - No change
v8:
  - Previously patch 5/6, otherwise no change
v7:
  - No change
v6:
  - Changed (size / stride) calculation to ((size + stride - 1) / stride)
to ensure that the proper count is passed to regmap_bulk_write().
  - Removed unnecessary call to rsu_check_complete() in
m10bmc_sec_poll_complete() and changed while loop to
do/while loop.
v5:
  - No change
v4:
  - No change
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed calling functions of functions that return "enum fpga_sec_err"
to check for (ret != FPGA_SEC_ERR_NONE) instead of (ret)
v2:
  - Reworked the rsu_start_done() function to make it more readable
  - Reworked while-loop condition/content in rsu_prog_ready()
  - Minor code cleanup per review comments
  - Added a comment to the m10bmc_sec_poll_complete() function to
explain the context (could take 30+ minutes to complete).
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
  - Moved MAX10 BMC address and function definitions to a separate
patch.
---
 drivers/fpga/intel-m10-bmc-secure.c | 303 +++-
 1 file changed, 302 insertions(+), 1 deletion(-)

diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index 87e16c146569..a290fcc4df4a 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -180,7 +180,308 @@ static const struct attribute_group 
*m10bmc_sec_attr_groups[] = {
NULL,
 };
 
-static const struct fpga_sec_mgr_ops m10bmc_sops = { };
+static void log_error_regs(struct m10bmc_sec *sec, u32 doorbell)
+{
+   u32 auth_result;
+
+   dev_err(sec->dev, "RSU error status: 0x%08x\n", doorbell);
+
+   if (!m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, _result))
+   dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result);
+}
+
+static enum fpga_sec_err rsu_check_idle(struct m10bmc_sec *sec)
+{
+   u32 doorbell;
+   int ret;
+
+   ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, );
+   if (ret)
+   return FPGA_SEC_ERR_RW_ERROR;
+
+   if (rsu_prog(doorbell) != RSU_PROG_IDLE &&
+   rsu_prog(doorbell) != RSU_PROG_RSU_DONE) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_BUSY;
+   }
+
+   return FPGA_SEC_ERR_NONE;
+}
+
+static inline bool rsu_start_done(u32 doorbell)
+{
+   u32 status, progress;
+
+   if (doorbell & DRBL_RSU_REQUEST)
+   return false;
+
+   status = rsu_stat(doorbell);
+   if (status == RSU_STAT_ERASE_FAIL || status == RSU_STAT_WEAROUT)
+   return true;
+
+   progress = rsu_prog(doorbell);
+   if (progress != RSU_PROG_IDLE && progress != RSU_PROG_RSU_DONE)
+   return true;
+
+   return false;
+}
+
+static enum fpga_sec_err rsu_update_init(struct m10bmc_sec *sec)
+{
+   u32 doorbell, status;
+   int ret;
+
+   ret = regmap_update_bits(sec->m10bmc->regmap,
+M10BMC_SYS_BASE + M10BMC_DOORBELL,
+DRBL_RSU_REQUEST | DRBL_HOST_STATUS,
+DRBL_RSU_REQUEST |
+FIELD_PREP(DRBL_HOST_STATUS,
+   HOST_STATUS_IDLE));
+   if (ret)
+   return FPGA_SEC_ERR_RW_ERROR;
+
+   ret = regmap_read_poll_timeout(sec->m10bmc->regmap,
+  M10BMC_SYS_BASE + M10BMC_DOORBELL,
+  doorbell,
+  rsu_start_done(doorbell),
+  NIOS_HANDSHAKE_INTERVAL_US,
+  NIOS_HANDSHAKE_TIMEOUT_US);
+
+   if (ret == -ETIMEDOUT) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_TIMEOUT;
+   } else if (ret) {
+   return FPGA_SEC_ERR_RW_ERROR;
+   }
+
+   status = rsu_stat(doorbell);
+   if (status == RSU_STAT_WEAROUT) {
+   dev_warn(sec->dev, "Excessive flash update count detected\n");
+   return FPGA_SEC_ERR_WEAROUT;
+   } else if (status == RSU_STAT_ERASE_FAIL) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_HW_ERROR;
+   }
+
+   return FPGA_SEC_ERR_NONE;
+}
+
+static enum fpga_sec_err rsu_prog_ready(struct m10bmc_sec *sec)
+{
+   unsigned long poll_timeout;
+   u32 d

[PATCH v10 0/5] Intel MAX10 BMC Secure Update Driver

2021-03-12 Thread Russ Weight
n calls to m10bmc_raw_bulk_read().
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
  - Implemented HW_ERRINFO_POISON for m10bmc_sec_hw_errinfo() to
ensure that corresponding bits are set to 1 if we are unable
to read the doorbell or auth_result registers.
  - Added comments and additional code cleanup per V1 review.


Russ Weight (5):
  fpga: m10bmc-sec: create max10 bmc secure update driver
  fpga: m10bmc-sec: expose max10 flash update count
  fpga: m10bmc-sec: expose max10 canceled keys in sysfs
  fpga: m10bmc-sec: add max10 secure update functions
  fpga: m10bmc-sec: add max10 get_hw_errinfo callback func

 .../testing/sysfs-driver-intel-m10-bmc-secure |  61 ++
 MAINTAINERS   |   2 +
 drivers/fpga/Kconfig  |  11 +
 drivers/fpga/Makefile |   3 +
 drivers/fpga/intel-m10-bmc-secure.c   | 543 ++
 5 files changed, 620 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
 create mode 100644 drivers/fpga/intel-m10-bmc-secure.c

-- 
2.25.1



[PATCH v10 5/5] fpga: m10bmc-sec: add max10 get_hw_errinfo callback func

2021-03-12 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to include
a function that returns 64 bits of additional HW specific
data for errors that require additional information.
This callback function enables the hw_errinfo sysfs
node in the Intel Security Manager class driver.

Signed-off-by: Russ Weight 
---
v10:
  - No change
v9:
  - No change
v8:
  - Previously patch 6/6, otherwise no change
v7:
  - No change
v6:
  - Initialized auth_result and doorbell to HW_ERRINFO_POISON
in m10bmc_sec_hw_errinfo() and removed unnecessary if statements.
v5:
  - No change
v4:
  - No change
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
v2:
  - Implemented HW_ERRINFO_POISON for m10bmc_sec_hw_errinfo() to
ensure that corresponding bits are set to 1 if we are unable
to read the doorbell or auth_result registers.
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 drivers/fpga/intel-m10-bmc-secure.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index a290fcc4df4a..3a049c98cf43 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -476,11 +476,33 @@ static enum fpga_sec_err m10bmc_sec_cancel(struct 
fpga_sec_mgr *smgr)
return ret ? FPGA_SEC_ERR_RW_ERROR : FPGA_SEC_ERR_NONE;
 }
 
+#define HW_ERRINFO_POISON  GENMASK(31, 0)
+static u64 m10bmc_sec_hw_errinfo(struct fpga_sec_mgr *smgr)
+{
+   struct m10bmc_sec *sec = smgr->priv;
+   u32 auth_result = HW_ERRINFO_POISON;
+   u32 doorbell = HW_ERRINFO_POISON;
+
+   switch (smgr->err_code) {
+   case FPGA_SEC_ERR_HW_ERROR:
+   case FPGA_SEC_ERR_TIMEOUT:
+   case FPGA_SEC_ERR_BUSY:
+   case FPGA_SEC_ERR_WEAROUT:
+   m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, );
+   m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, _result);
+
+   return (u64)doorbell << 32 | (u64)auth_result;
+   default:
+   return 0;
+   }
+}
+
 static const struct fpga_sec_mgr_ops m10bmc_sops = {
.prepare = m10bmc_sec_prepare,
.write_blk = m10bmc_sec_write_blk,
.poll_complete = m10bmc_sec_poll_complete,
.cancel = m10bmc_sec_cancel,
+   .get_hw_errinfo = m10bmc_sec_hw_errinfo,
 };
 
 static int m10bmc_secure_probe(struct platform_device *pdev)
-- 
2.25.1



[PATCH v9 0/5] Intel MAX10 BMC Secure Update Driver

2021-03-08 Thread Russ Weight
The Intel MAX10 BMC Secure Update driver instantiates the FPGA
Security Manager class driver and provides the callback functions
required to support secure updates on Intel n3000 PAC devices.
This driver is implemented as a sub-driver of the Intel MAX10 BMC
mfd driver. Future instances of the MAX10 BMC will support other
devices as well (e.g. d5005) and this same MAX10 BMC Secure
Update driver will receive modifications to support that device.

This driver interacts with the HW secure update engine of the
BMC in order to transfer new FPGA and BMC images to FLASH so
that they will be automatically loaded when the FPGA card reboots.
Security is enforced by hardware and firmware. The MAX10 BMC
Secure Update driver interacts with the firmware to initiate
an update, pass in the necessary data, and collect status on
the update.

This driver provides sysfs files for displaying the flash count,
the root entry hashes (REH), and the code-signing-key (CSK)
cancellation vectors.

These patches are dependent on other patches that are under
review. If you want to apply and compile these patches on
linux-next, please apply these patches first:

(1 patch)   https://marc.info/?l=linux-kernel=161126987101096=2
(7 patches) https://marc.info/?l=linux-fpga=161525020621455=2

Changelog v8 -> v9:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation

Changelog v7 -> v8:
  - Spit out patch "mfd: intel-m10-bmc: support for MAX10 BMC Secure
Updates" and submitted it separately:
https://marc.info/?l=linux-kernel=161126987101096=2

Changelog v6 -> v7:
  - Rebased patches for 5.11-rc2
  - Updated Date and KernelVersion in ABI documentation

Changelog v5 -> v6:
  - Added WARN_ON() prior to several calls to regmap_bulk_read()
to assert that the (SIZE / stride) calculations did not result
in remainders.
  - Changed the (size / stride) calculation in regmap_bulk_write()
call to ensure that we don't write one less than intended.
  - Changed flash_count_show() parameter list to achieve
reverse-christmas tree format.
  - Removed unnecessary call to rsu_check_complete() in
m10bmc_sec_poll_complete() and changed while loop to
do/while loop.
  - Initialized auth_result and doorbell to HW_ERRINFO_POISON
in m10bmc_sec_hw_errinfo() and removed unnecessary if statements.

Changelog v4 -> v5:
  - Renamed sysfs node user_flash_count to flash_count and updated
the sysfs documentation accordingly to more accurately descirbe
the purpose of the count.

Changelog v3 -> v4:
  - Moved sysfs files for displaying the flash count, the root
entry hashes (REH), and the code-signing-key (CSK) cancellation
vectors from the FPGA Security Manager class driver to this
driver (as they are not generic enough for the class driver).
  - Added a new ABI documentation file with informtaion about the
new sysfs entries: sysfs-driver-intel-m10-bmc-secure
  - Updated the MAINTAINERS file to add the new ABI documentation
file: sysfs-driver-intel-m10-bmc-secure
  - Removed unnecessary ret variable from m10bmc_secure_probe()
  - Incorporated new devm_fpga_sec_mgr_register() function into
m10bmc_secure_probe() and removed the m10bmc_secure_remove()
function.

Changelog v2 -> v3:
  - Changed "MAX10 BMC Security Engine driver" to "MAX10 BMC Secure
Update driver"
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed "_root_entry_hash" to "_reh", with a comment explaining
what reh is.
  - Renamed get_csk_vector() to m10bmc_csk_vector()
  - Changed calling functions of functions that return "enum fpga_sec_err"
to check for (ret != FPGA_SEC_ERR_NONE) instead of (ret)

Changelog v1 -> v2:
  - These patches were previously submitted as part of a larger V1
patch set under the title "Intel FPGA Security Manager Class Driver".
  - Grouped all changes to include/linux/mfd/intel-m10-bmc.h into a
single patch: "mfd: intel-m10-bmc: support for MAX10 BMC Security
Engine".
  - Removed ifpga_sec_mgr_init() and ifpga_sec_mgr_uinit() functions.
  - Adapted to changes in the Intel FPGA Security Manager by splitting
the single call to ifpga_sec_mgr_register() into two function
calls: devm_ifpga_sec_mgr_create() and ifpga_sec_mgr_register().
  - Replaced small function-creation macros for explicit function
declarations.
  - Bug fix for the get_csk_vector() function to properly apply the
stride variable in calls to m10bmc_raw_bulk_read().
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
  - Implemented HW_ERRINFO_POISON for m10bmc_sec_hw_errinfo() to
ensure that corresponding bits are set to 1 if we ar

[PATCH v9 2/5] fpga: m10bmc-sec: expose max10 flash update count

2021-03-08 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to provide a
sysfs file to expose the flash update count for the FPGA
user image.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v9:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Previously patch 3/6, otherwise no change
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Changed flash_count_show() parameter list to achieve
reverse-christmas tree format.
  - Added WARN_ON() call for (FLASH_COUNT_SIZE / stride) to ensure
that the proper count is passed to regmap_bulk_read().
v5:
  - Renamed sysfs node user_flash_count to flash_count and updated the
sysfs documentation accordingly.
v4:
  - Moved the sysfs file for displaying the flash count from the
FPGA Security Manager class driver to here. The
m10bmc_user_flash_count() function is removed and the
functionality is moved into a user_flash_count_show()
function.
  - Added ABI documentation for the new sysfs entry
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
v2:
  - Renamed get_qspi_flash_count() to m10bmc_user_flash_count()
  - Minor code cleanup per review comments
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 .../testing/sysfs-driver-intel-m10-bmc-secure |  8 
 drivers/fpga/intel-m10-bmc-secure.c   | 37 +++
 2 files changed, 45 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
index aab2aac1586e..c98a9771896c 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -27,3 +27,11 @@ Description: Read only. Returns the root entry hash for the 
BMC image
"hash not programmed".  This file is only visible if the
underlying device supports it.
Format: "0x%x".
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/flash_count
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns number of times the secure update
+   staging area has been flashed.
+   Format: "%u".
diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index 5ac5f59b5731..ecd63c13cb2d 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct m10bmc_sec {
struct device *dev;
@@ -78,7 +79,43 @@ DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, 
BMC_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
 
+#define FLASH_COUNT_SIZE 4096  /* count stored as inverted bit vector */
+
+static ssize_t flash_count_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct m10bmc_sec *sec = dev_get_drvdata(dev);
+   unsigned int stride, num_bits;
+   u8 *flash_buf;
+   int cnt, ret;
+
+   stride = regmap_get_reg_stride(sec->m10bmc->regmap);
+   num_bits = FLASH_COUNT_SIZE * 8;
+
+   flash_buf = kmalloc(FLASH_COUNT_SIZE, GFP_KERNEL);
+   if (!flash_buf)
+   return -ENOMEM;
+
+   WARN_ON(FLASH_COUNT_SIZE % stride);
+   ret = regmap_bulk_read(sec->m10bmc->regmap, STAGING_FLASH_COUNT,
+  flash_buf, FLASH_COUNT_SIZE / stride);
+   if (ret) {
+   dev_err(sec->dev,
+   "failed to read flash count: %x cnt %x: %d\n",
+   STAGING_FLASH_COUNT, FLASH_COUNT_SIZE / stride, ret);
+   goto exit_free;
+   }
+   cnt = num_bits - bitmap_weight((unsigned long *)flash_buf, num_bits);
+
+exit_free:
+   kfree(flash_buf);
+
+   return ret ? : sysfs_emit(buf, "%u\n", cnt);
+}
+static DEVICE_ATTR_RO(flash_count);
+
 static struct attribute *m10bmc_security_attrs[] = {
+   _attr_flash_count.attr,
_attr_bmc_root_entry_hash.attr,
_attr_sr_root_entry_hash.attr,
_attr_pr_root_entry_hash.attr,
-- 
2.25.1



[PATCH v9 1/5] fpga: m10bmc-sec: create max10 bmc secure update driver

2021-03-08 Thread Russ Weight
Create a platform driver that can be invoked as a sub
driver for the Intel MAX10 BMC in order to support
secure updates. This sub-driver will invoke an
instance of the FPGA Security Manager class driver
in order to expose sysfs interfaces for managing and
monitoring secure updates to FPGA and BMC images.

This patch creates the MAX10 BMC Secure Update driver and
provides sysfs files for displaying the current root entry hashes
for the FPGA static region, the FPGA PR region, and the MAX10
BMC.

Signed-off-by: Russ Weight 
---
v9:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Previously patch 2/6, otherwise no change
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Added WARN_ON() call for (sha_num_bytes / stride) to assert
that the proper count is passed to regmap_bulk_read().
v5:
  - No change
v4:
  - Moved sysfs files for displaying the root entry hashes (REH)
from the FPGA Security Manager class driver to here. The
m10bmc_reh() and m10bmc_reh_size() functions are removed and
the functionality from these functions is moved into a
show_root_entry_hash() function for displaying the REHs.
  - Added ABI documentation for the new sysfs entries:
sysfs-driver-intel-m10-bmc-secure
  - Updated the MAINTAINERS file to add the new ABI documentation
file: sysfs-driver-intel-m10-bmc-secure
  - Removed unnecessary ret variable from m10bmc_secure_probe()
  - Incorporated new devm_fpga_sec_mgr_register() function into
m10bmc_secure_probe() and removed the m10bmc_secure_remove()
function.
v3:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure
Update driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed "_root_entry_hash" to "_reh", with a comment explaining
what reh is.
v2:
  - Added drivers/fpga/intel-m10-bmc-secure.c file to MAINTAINERS.
  - Switched to GENMASK(31, 16) for a couple of mask definitions.
  - Moved MAX10 BMC address and function definitions to a separate
patch.
  - Replaced small function-creation macros with explicit function
declarations.
  - Removed ifpga_sec_mgr_init() and ifpga_sec_mgr_uinit() functions.
  - Adapted to changes in the Intel FPGA Security Manager by splitting
the single call to ifpga_sec_mgr_register() into two function
calls: devm_ifpga_sec_mgr_create() and ifpga_sec_mgr_register().
---
 .../testing/sysfs-driver-intel-m10-bmc-secure |  29 
 MAINTAINERS   |   2 +
 drivers/fpga/Kconfig  |  11 ++
 drivers/fpga/Makefile |   3 +
 drivers/fpga/intel-m10-bmc-secure.c   | 135 ++
 5 files changed, 180 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
 create mode 100644 drivers/fpga/intel-m10-bmc-secure.c

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
new file mode 100644
index ..aab2aac1586e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -0,0 +1,29 @@
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/sr_root_entry_hash
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the static
+   region if one is programmed, else it returns the
+   string: "hash not programmed".  This file is only
+   visible if the underlying device supports it.
+   Format: "0x%x".
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/pr_root_entry_hash
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the partial
+   reconfiguration region if one is programmed, else it
+   returns the string: "hash not programmed".  This file
+   is only visible if the underlying device supports it.
+   Format: "0x%x".
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/bmc_root_entry_hash
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the BMC image
+   if one is programmed, else it returns the string:
+   "hash not programmed".  This file is only visible if the
+   underlying device supports it.
+   Format: "0x%x".
diff --git a/MAINTAINERS b/MAINTAINERS
index 4e9174eeec1b..0133c25ced78 1

[PATCH v9 5/5] fpga: m10bmc-sec: add max10 get_hw_errinfo callback func

2021-03-08 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to include
a function that returns 64 bits of additional HW specific
data for errors that require additional information.
This callback function enables the hw_errinfo sysfs
node in the Intel Security Manager class driver.

Signed-off-by: Russ Weight 
---
v9:
  - No change
v8:
  - Previously patch 6/6, otherwise no change
v7:
  - No change
v6:
  - Initialized auth_result and doorbell to HW_ERRINFO_POISON
in m10bmc_sec_hw_errinfo() and removed unnecessary if statements.
v5:
  - No change
v4:
  - No change
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
v2:
  - Implemented HW_ERRINFO_POISON for m10bmc_sec_hw_errinfo() to
ensure that corresponding bits are set to 1 if we are unable
to read the doorbell or auth_result registers.
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 drivers/fpga/intel-m10-bmc-secure.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index a290fcc4df4a..3a049c98cf43 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -476,11 +476,33 @@ static enum fpga_sec_err m10bmc_sec_cancel(struct 
fpga_sec_mgr *smgr)
return ret ? FPGA_SEC_ERR_RW_ERROR : FPGA_SEC_ERR_NONE;
 }
 
+#define HW_ERRINFO_POISON  GENMASK(31, 0)
+static u64 m10bmc_sec_hw_errinfo(struct fpga_sec_mgr *smgr)
+{
+   struct m10bmc_sec *sec = smgr->priv;
+   u32 auth_result = HW_ERRINFO_POISON;
+   u32 doorbell = HW_ERRINFO_POISON;
+
+   switch (smgr->err_code) {
+   case FPGA_SEC_ERR_HW_ERROR:
+   case FPGA_SEC_ERR_TIMEOUT:
+   case FPGA_SEC_ERR_BUSY:
+   case FPGA_SEC_ERR_WEAROUT:
+   m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, );
+   m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, _result);
+
+   return (u64)doorbell << 32 | (u64)auth_result;
+   default:
+   return 0;
+   }
+}
+
 static const struct fpga_sec_mgr_ops m10bmc_sops = {
.prepare = m10bmc_sec_prepare,
.write_blk = m10bmc_sec_write_blk,
.poll_complete = m10bmc_sec_poll_complete,
.cancel = m10bmc_sec_cancel,
+   .get_hw_errinfo = m10bmc_sec_hw_errinfo,
 };
 
 static int m10bmc_secure_probe(struct platform_device *pdev)
-- 
2.25.1



[PATCH v9 3/5] fpga: m10bmc-sec: expose max10 canceled keys in sysfs

2021-03-08 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to provide sysfs
files to expose the canceled code signing key (CSK) bit
vectors. These use the standard bitmap list format
(e.g. 1,2-6,9).

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v9:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Previously patch 4/6, otherwise no change
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Added WARN_ON() call for (size / stride) to ensure
that the proper count is passed to regmap_bulk_read().
v5:
  - No change
v4:
  - Moved sysfs files for displaying the code-signing-key (CSK)
cancellation vectors from the FPGA Security Manger class driver
to here. The m10bmc_csk_vector() and m10bmc_csk_cancel_nbits()
functions are removed and the functionality from these functions
is moved into a show_canceled_csk() function for for displaying
the CSK vectors.
  - Added ABI documentation for new sysfs entries
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Renamed get_csk_vector() to m10bmc_csk_vector()
v2:
  - Replaced small function-creation macros for explicit function
declarations.
  - Fixed get_csk_vector() function to properly apply the stride
variable in calls to m10bmc_raw_bulk_read()
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 .../testing/sysfs-driver-intel-m10-bmc-secure | 24 ++
 drivers/fpga/intel-m10-bmc-secure.c   | 48 +++
 2 files changed, 72 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
index c98a9771896c..ffaf513362fa 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -28,6 +28,30 @@ Description: Read only. Returns the root entry hash for the 
BMC image
underlying device supports it.
Format: "0x%x".
 
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/sr_canceled_csks
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the static region. The standard bitmap
+   list format is used (e.g. "1,2-6,9").
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/pr_canceled_csks
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the partial reconfiguration region. The
+   standard bitmap list format is used (e.g. "1,2-6,9").
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/bmc_canceled_csks
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the BMC.  The standard bitmap list format
+   is used (e.g. "1,2-6,9").
+
 What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/flash_count
 Date:  April 2021
 KernelVersion:  5.13
diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index ecd63c13cb2d..87e16c146569 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -79,6 +79,51 @@ DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, 
BMC_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
 
+#define CSK_BIT_LEN128U
+#define CSK_32ARRAY_SIZE   DIV_ROUND_UP(CSK_BIT_LEN, 32)
+
+static ssize_t
+show_canceled_csk(struct device *dev, u32 addr, char *buf)
+{
+   unsigned int i, stride, size = CSK_32ARRAY_SIZE * sizeof(u32);
+   struct m10bmc_sec *sec = dev_get_drvdata(dev);
+   DECLARE_BITMAP(csk_map, CSK_BIT_LEN);
+   __le32 csk_le32[CSK_32ARRAY_SIZE];
+   u32 csk32[CSK_32ARRAY_SIZE];
+   int ret;
+
+   stride = regmap_get_reg_stride(sec->m10bmc->regmap);
+
+   WARN_ON(size % stride);
+   ret = regmap_bulk_read(sec->m10bmc->regmap, addr, csk_le32,
+  size / stride);
+   if (ret) {
+   dev_err(sec->dev, "failed to read CSK vector: %x cnt %x: %d\n",
+   addr, size / stride, ret);
+   return ret;
+   }
+
+   for (i = 0; i < CSK_32ARRAY_SIZE; i++)
+   csk32[i] = le32_to_cpu(((csk_le32[i])));
+
+

[PATCH v9 4/5] fpga: m10bmc-sec: add max10 secure update functions

2021-03-08 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to include
the functions that enable secure updates of BMC images,
FPGA images, etc.

Signed-off-by: Russ Weight 
---
v9:
  - No change
v8:
  - Previously patch 5/6, otherwise no change
v7:
  - No change
v6:
  - Changed (size / stride) calculation to ((size + stride - 1) / stride)
to ensure that the proper count is passed to regmap_bulk_write().
  - Removed unnecessary call to rsu_check_complete() in
m10bmc_sec_poll_complete() and changed while loop to
do/while loop.
v5:
  - No change
v4:
  - No change
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed calling functions of functions that return "enum fpga_sec_err"
to check for (ret != FPGA_SEC_ERR_NONE) instead of (ret)
v2:
  - Reworked the rsu_start_done() function to make it more readable
  - Reworked while-loop condition/content in rsu_prog_ready()
  - Minor code cleanup per review comments
  - Added a comment to the m10bmc_sec_poll_complete() function to
explain the context (could take 30+ minutes to complete).
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
  - Moved MAX10 BMC address and function definitions to a separate
patch.
---
 drivers/fpga/intel-m10-bmc-secure.c | 303 +++-
 1 file changed, 302 insertions(+), 1 deletion(-)

diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index 87e16c146569..a290fcc4df4a 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -180,7 +180,308 @@ static const struct attribute_group 
*m10bmc_sec_attr_groups[] = {
NULL,
 };
 
-static const struct fpga_sec_mgr_ops m10bmc_sops = { };
+static void log_error_regs(struct m10bmc_sec *sec, u32 doorbell)
+{
+   u32 auth_result;
+
+   dev_err(sec->dev, "RSU error status: 0x%08x\n", doorbell);
+
+   if (!m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, _result))
+   dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result);
+}
+
+static enum fpga_sec_err rsu_check_idle(struct m10bmc_sec *sec)
+{
+   u32 doorbell;
+   int ret;
+
+   ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, );
+   if (ret)
+   return FPGA_SEC_ERR_RW_ERROR;
+
+   if (rsu_prog(doorbell) != RSU_PROG_IDLE &&
+   rsu_prog(doorbell) != RSU_PROG_RSU_DONE) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_BUSY;
+   }
+
+   return FPGA_SEC_ERR_NONE;
+}
+
+static inline bool rsu_start_done(u32 doorbell)
+{
+   u32 status, progress;
+
+   if (doorbell & DRBL_RSU_REQUEST)
+   return false;
+
+   status = rsu_stat(doorbell);
+   if (status == RSU_STAT_ERASE_FAIL || status == RSU_STAT_WEAROUT)
+   return true;
+
+   progress = rsu_prog(doorbell);
+   if (progress != RSU_PROG_IDLE && progress != RSU_PROG_RSU_DONE)
+   return true;
+
+   return false;
+}
+
+static enum fpga_sec_err rsu_update_init(struct m10bmc_sec *sec)
+{
+   u32 doorbell, status;
+   int ret;
+
+   ret = regmap_update_bits(sec->m10bmc->regmap,
+M10BMC_SYS_BASE + M10BMC_DOORBELL,
+DRBL_RSU_REQUEST | DRBL_HOST_STATUS,
+DRBL_RSU_REQUEST |
+FIELD_PREP(DRBL_HOST_STATUS,
+   HOST_STATUS_IDLE));
+   if (ret)
+   return FPGA_SEC_ERR_RW_ERROR;
+
+   ret = regmap_read_poll_timeout(sec->m10bmc->regmap,
+  M10BMC_SYS_BASE + M10BMC_DOORBELL,
+  doorbell,
+  rsu_start_done(doorbell),
+  NIOS_HANDSHAKE_INTERVAL_US,
+  NIOS_HANDSHAKE_TIMEOUT_US);
+
+   if (ret == -ETIMEDOUT) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_TIMEOUT;
+   } else if (ret) {
+   return FPGA_SEC_ERR_RW_ERROR;
+   }
+
+   status = rsu_stat(doorbell);
+   if (status == RSU_STAT_WEAROUT) {
+   dev_warn(sec->dev, "Excessive flash update count detected\n");
+   return FPGA_SEC_ERR_WEAROUT;
+   } else if (status == RSU_STAT_ERASE_FAIL) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_HW_ERROR;
+   }
+
+   return FPGA_SEC_ERR_NONE;
+}
+
+static enum fpga_sec_err rsu_prog_ready(struct m10bmc_sec *sec)
+{
+   unsigned long poll_timeout;
+   u32 doorbell, progress;
+

[PATCH v10 2/7] fpga: sec-mgr: enable secure updates

2021-03-08 Thread Russ Weight
Extend the FPGA Security Manager class driver to
include an update/filename sysfs node that can be used
to initiate a secure update.  The filename of a secure
update file (BMC image, FPGA image, Root Entry Hash image,
or Code Signing Key cancellation image) can be written to
this sysfs entry to cause a secure update to occur.

The write of the filename will return immediately, and the
update will begin in the context of a kernel worker thread.
This tool utilizes the request_firmware framework, which
requires that the image file reside under /lib/firmware.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
  - Changed filename_store() to use kmemdup_nul() instead of
kstrndup() and changed the count to not assume a line-return.
v6:
  - Changed "security update" to "secure update" in commit message
v5:
  - When checking the return values for functions of type enum
fpga_sec_err err_code, test for FPGA_SEC_ERR_NONE instead of 0
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Removed unnecessary "goto done"
  - Added a comment to explain imgr->driver_unload in
ifpga_sec_mgr_unregister()
v2:
  - Bumped documentation date and version
  - Removed explicit value assignments in enums
  - Other minor code cleanup per review comments 
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  |  13 ++
 drivers/fpga/fpga-sec-mgr.c   | 164 ++
 include/linux/fpga/fpga-sec-mgr.h |  49 ++
 3 files changed, 226 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 0dda4604c178..4c0bdfd25553 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -3,3 +3,16 @@ Date:      April 2021
 KernelVersion:  5.13
 Contact:   Russ Weight 
 Description:   Name of low level fpga security manager driver.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/filename
+Date:      April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Write only. Write the filename of an image
+   file to this sysfs file to initiate a secure
+   update. The file must have an appropriate header
+   which, among other things, identifies the target
+   for the update. This mechanism is used to update
+   BMC images, BMC firmware, Static Region images,
+   and Root Entry Hashes, and to cancel Code Signing
+   Keys (CSK).
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 468379e0c825..7347ba1ba73e 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -5,8 +5,11 @@
  * Copyright (C) 2019-2020 Intel Corporation, Inc.
  */
 
+#include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -18,8 +21,140 @@ struct fpga_sec_mgr_devres {
struct fpga_sec_mgr *smgr;
 };
 
+#define WRITE_BLOCK_SIZE 0x4000/* Update remaining_size every 0x4000 
bytes */
+
 #define to_sec_mgr(d) container_of(d, struct fpga_sec_mgr, dev)
 
+static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
+  enum fpga_sec_err err_code)
+{
+   smgr->err_code = err_code;
+   smgr->sops->cancel(smgr);
+}
+
+static void progress_complete(struct fpga_sec_mgr *smgr)
+{
+   mutex_lock(>lock);
+   smgr->progress = FPGA_SEC_PROG_IDLE;
+   complete_all(>update_done);
+   mutex_unlock(>lock);
+}
+
+static void fpga_sec_mgr_update(struct work_struct *work)
+{
+   u32 size, blk_size, offset = 0;
+   struct fpga_sec_mgr *smgr;
+   const struct firmware *fw;
+   enum fpga_sec_err ret;
+
+   smgr = container_of(work, struct fpga_sec_mgr, work);
+
+   get_device(>dev);
+   if (request_firmware(, smgr->filename, >dev)) {
+   smgr->err_code = FPGA_SEC_ERR_FILE_READ;
+   goto idle_exit;
+   }
+
+   smgr->data = fw->data;
+   smgr->remaining_size = fw->size;
+
+   if (!try_module_get(smgr->dev.parent->driver->owner)) {
+   smgr->err_code = FPGA_SEC_ERR_BUSY;
+   goto release_fw_exit;
+   }
+
+   smgr->progress = FPGA_SEC_PROG_PREPARING;
+   ret = smgr->sops->prepare(smgr);
+   if (ret != FPGA_SEC_ERR_NONE) {
+   fpga_sec_dev_error(smgr, ret);
+   goto modput_exit;
+   }
+
+   smgr->progress = FPGA_SE

[PATCH v10 7/7] fpga: sec-mgr: expose hardware error info

2021-03-08 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an optional update/hw_errinfo sysfs node that can be used
to retrieve 64 bits of device specific error information
following a secure update failure.

The underlying driver must provide a get_hw_errinfo() callback
function to enable this feature. This data is treated as
opaque by the class driver. It is left to user-space software
or support personnel to interpret this data.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - No change
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - No change
v2:
  - Bumped documentation date and version
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 14 +++
 drivers/fpga/fpga-sec-mgr.c   | 38 +++
 include/linux/fpga/fpga-sec-mgr.h |  5 +++
 3 files changed, 57 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index fba3066e2b69..ff1458701def 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -65,3 +65,17 @@ Description: Read-only. Returns a string describing the 
failure
idle state. If this file is read while a secure
update is in progress, then the read will fail with
EBUSY.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/hw_errinfo
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read-only. Returns a 64 bit error value providing
+   hardware specific information that may be useful in
+   debugging errors that occur during FPGA image updates.
+   This file is only visible if the underlying device
+   supports it. The hw_errinfo value is only accessible
+   when the secure update engine is in the idle state.
+   If this file is read while a secure update is in
+   progress, then the read will fail with EBUSY.
+   Format: "0x%llx".
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index d354fe2ab582..aebe06d9a54a 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -38,10 +38,17 @@ static void set_error(struct fpga_sec_mgr *smgr, enum 
fpga_sec_err err_code)
smgr->err_code = err_code;
 }
 
+static void set_hw_errinfo(struct fpga_sec_mgr *smgr)
+{
+   if (smgr->sops->get_hw_errinfo)
+   smgr->hw_errinfo = smgr->sops->get_hw_errinfo(smgr);
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
set_error(smgr, err_code);
+   set_hw_errinfo(smgr);
smgr->sops->cancel(smgr);
 }
 
@@ -227,6 +234,23 @@ error_show(struct device *dev, struct device_attribute 
*attr, char *buf)
 }
 static DEVICE_ATTR_RO(error);
 
+static ssize_t
+hw_errinfo_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
+   int ret;
+
+   mutex_lock(>lock);
+   if (smgr->progress != FPGA_SEC_PROG_IDLE)
+   ret = -EBUSY;
+   else
+   ret = sysfs_emit(buf, "0x%llx\n", smgr->hw_errinfo);
+   mutex_unlock(>lock);
+
+   return ret;
+}
+static DEVICE_ATTR_RO(hw_errinfo);
+
 static ssize_t remaining_size_show(struct device *dev,
   struct device_attribute *attr, char *buf)
 {
@@ -258,6 +282,7 @@ static ssize_t filename_store(struct device *dev, struct 
device_attribute *attr,
}
 
smgr->err_code = FPGA_SEC_ERR_NONE;
+   smgr->hw_errinfo = 0;
smgr->request_cancel = false;
smgr->progress = FPGA_SEC_PROG_READING;
reinit_completion(>update_done);
@@ -292,18 +317,31 @@ static ssize_t cancel_store(struct device *dev, struct 
device_attribute *attr,
 }
 static DEVICE_ATTR_WO(cancel);
 
+static umode_t
+sec_mgr_update_visible(struct kobject *kobj, struct attribute *attr, int n)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(kobj_to_dev(kobj));
+
+   if (attr == _attr_hw_errinfo.attr && !smgr->sops->get_hw_errinfo)
+   return 0;
+
+   return attr->mode;
+}
+
 static struct attribute *sec_mgr_update_attrs[] = {
_attr_filename.attr,
_attr_cancel.attr,
_attr_status.attr,
_attr_error.attr,
_attr_remaining_size.attr,
+   _attr

[PATCH v10 6/7] fpga: sec-mgr: enable cancel of secure update

2021-03-08 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an update/cancel sysfs file that can be written to request
that an update be canceled. The write may return EBUSY if
the update has progressed to the point that it cannot be
canceled by software or ENODEV if there is no update in
progress.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - No change
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - No change
v2:
  - Bumped documentation date and version
  - Minor code cleanup per review comments 
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 10 
 drivers/fpga/fpga-sec-mgr.c   | 59 +--
 include/linux/fpga/fpga-sec-mgr.h |  1 +
 3 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 2e1f60edf546..fba3066e2b69 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -17,6 +17,16 @@ Description: Write only. Write the filename of an image
and Root Entry Hashes, and to cancel Code Signing
Keys (CSK).
 
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/cancel
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Write-only. Write a "1" to this file to request
+   that a current update be canceled. This request
+   will be rejected (EBUSY) if the programming phase
+   has already started or (ENODEV) if there is no
+   update in progress.
+
 What:  /sys/class/fpga_sec_mgr/fpga_secX/update/status
 Date:  April 2021
 KernelVersion:  5.13
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 951020942991..d354fe2ab582 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -45,6 +45,23 @@ static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
smgr->sops->cancel(smgr);
 }
 
+static int progress_transition(struct fpga_sec_mgr *smgr,
+  enum fpga_sec_prog new_progress)
+{
+   int ret = 0;
+
+   mutex_lock(>lock);
+   if (smgr->request_cancel) {
+   set_error(smgr, FPGA_SEC_ERR_CANCELED);
+   smgr->sops->cancel(smgr);
+   ret = -ECANCELED;
+   } else {
+   update_progress(smgr, new_progress);
+   }
+   mutex_unlock(>lock);
+   return ret;
+}
+
 static void progress_complete(struct fpga_sec_mgr *smgr)
 {
mutex_lock(>lock);
@@ -76,16 +93,20 @@ static void fpga_sec_mgr_update(struct work_struct *work)
goto release_fw_exit;
}
 
-   update_progress(smgr, FPGA_SEC_PROG_PREPARING);
+   if (progress_transition(smgr, FPGA_SEC_PROG_PREPARING))
+   goto modput_exit;
+
ret = smgr->sops->prepare(smgr);
if (ret != FPGA_SEC_ERR_NONE) {
fpga_sec_dev_error(smgr, ret);
goto modput_exit;
}
 
-   update_progress(smgr, FPGA_SEC_PROG_WRITING);
+   if (progress_transition(smgr, FPGA_SEC_PROG_WRITING))
+   goto done;
+
size = smgr->remaining_size;
-   while (size) {
+   while (size && !smgr->request_cancel) {
blk_size = min_t(u32, size, WRITE_BLOCK_SIZE);
size -= blk_size;
ret = smgr->sops->write_blk(smgr, offset, blk_size);
@@ -98,7 +119,9 @@ static void fpga_sec_mgr_update(struct work_struct *work)
offset += blk_size;
}
 
-   update_progress(smgr, FPGA_SEC_PROG_PROGRAMMING);
+   if (progress_transition(smgr, FPGA_SEC_PROG_PROGRAMMING))
+   goto done;
+
ret = smgr->sops->poll_complete(smgr);
if (ret != FPGA_SEC_ERR_NONE)
fpga_sec_dev_error(smgr, ret);
@@ -235,6 +258,7 @@ static ssize_t filename_store(struct device *dev, struct 
device_attribute *attr,
}
 
smgr->err_code = FPGA_SEC_ERR_NONE;
+   smgr->request_cancel = false;
smgr->progress = FPGA_SEC_PROG_READING;
reinit_completion(>update_done);
schedule_work(>work);
@@ -245,8 +269,32 @@ static ssize_t filename_store(struct device *dev, struct 
device_attribute *attr,
 }
 static DEVICE_ATTR_WO(filename);
 
+static ssize_t cancel_store(struct device *dev, struct device_attribute *attr,
+   const ch

[PATCH v10 5/7] fpga: sec-mgr: expose sec-mgr update size

2021-03-08 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an update/remaining_size sysfs node that can be read to
determine how much data remains to be transferred to the
secure update engine. This file can be used to monitor
progress during the "writing" phase of an update.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the remaining_size_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: imgr -> smgr, ifpga_ to fpga_
v3:
  - No change
v2:
  - Bumped documentation date and version
---
 Documentation/ABI/testing/sysfs-class-fpga-sec-mgr | 11 +++
 drivers/fpga/fpga-sec-mgr.c| 10 ++
 2 files changed, 21 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 77738577b2c3..2e1f60edf546 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -28,6 +28,17 @@ Description: Read-only. Returns a string describing the 
current
as it will be signaled by sysfs_notify() on each
state change.
 
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/remaining_size
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read-only. Returns the size of data that remains to
+   be written to the secure update engine. The size
+   value is initialized to the full size of the file
+   image and the value is updated periodically during
+   the "writing" phase of the update.
+   Format: "%u".
+
 What:  /sys/class/fpga_sec_mgr/fpga_secX/update/error
 Date:  April 2021
 KernelVersion:  5.13
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 3bd89598cccd..951020942991 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -204,6 +204,15 @@ error_show(struct device *dev, struct device_attribute 
*attr, char *buf)
 }
 static DEVICE_ATTR_RO(error);
 
+static ssize_t remaining_size_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
+
+   return sysfs_emit(buf, "%u\n", smgr->remaining_size);
+}
+static DEVICE_ATTR_RO(remaining_size);
+
 static ssize_t filename_store(struct device *dev, struct device_attribute 
*attr,
  const char *buf, size_t count)
 {
@@ -240,6 +249,7 @@ static struct attribute *sec_mgr_update_attrs[] = {
_attr_filename.attr,
_attr_status.attr,
_attr_error.attr,
+   _attr_remaining_size.attr,
NULL,
 };
 
-- 
2.25.1



[PATCH v10 4/7] fpga: sec-mgr: expose sec-mgr update errors

2021-03-08 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an update/error sysfs node that can be read for error
information when a secure update fails.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the error_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Use dev_err() for invalid error code in sec_error()
v2:
  - Bumped documentation date and version
  - Added warning to sec_progress() for invalid progress status
  - Added sec_error() function (similar to sec_progress())
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 17 
 drivers/fpga/fpga-sec-mgr.c   | 83 ---
 include/linux/fpga/fpga-sec-mgr.h |  1 +
 3 files changed, 89 insertions(+), 12 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 64420c101626..77738577b2c3 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -27,3 +27,20 @@ Description: Read-only. Returns a string describing the 
current
programming. Userspace code can poll on this file,
as it will be signaled by sysfs_notify() on each
state change.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/error
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read-only. Returns a string describing the failure
+   of a secure update. This string will be in the form
+   of :, where  will be one of
+   the status strings described for the status sysfs
+   file and  will be one of the following:
+   hw-error, timeout, user-abort, device-busy,
+   invalid-file-size, read-write-error, flash-wearout,
+   file-read-error.  The error sysfs file is only
+   meaningful when the secure update engine is in the
+   idle state. If this file is read while a secure
+   update is in progress, then the read will fail with
+   EBUSY.
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index dd60014b7511..3bd89598cccd 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -32,10 +32,16 @@ static void update_progress(struct fpga_sec_mgr *smgr,
sysfs_notify(>dev.kobj, "update", "status");
 }
 
+static void set_error(struct fpga_sec_mgr *smgr, enum fpga_sec_err err_code)
+{
+   smgr->err_state = smgr->progress;
+   smgr->err_code = err_code;
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
-   smgr->err_code = err_code;
+   set_error(smgr, err_code);
smgr->sops->cancel(smgr);
 }
 
@@ -58,7 +64,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
 
get_device(>dev);
if (request_firmware(, smgr->filename, >dev)) {
-   smgr->err_code = FPGA_SEC_ERR_FILE_READ;
+   set_error(smgr, FPGA_SEC_ERR_FILE_READ);
goto idle_exit;
}
 
@@ -66,7 +72,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
smgr->remaining_size = fw->size;
 
if (!try_module_get(smgr->dev.parent->driver->owner)) {
-   smgr->err_code = FPGA_SEC_ERR_BUSY;
+   set_error(smgr, FPGA_SEC_ERR_BUSY);
goto release_fw_exit;
}
 
@@ -128,24 +134,76 @@ static const char * const sec_mgr_prog_str[] = {
"programming"   /* FPGA_SEC_PROG_PROGRAMMING */
 };
 
-static ssize_t
-status_show(struct device *dev, struct device_attribute *attr, char *buf)
+static const char * const sec_mgr_err_str[] = {
+   "none", /* FPGA_SEC_ERR_NONE */
+   "hw-error", /* FPGA_SEC_ERR_HW_ERROR */
+   "timeout",  /* FPGA_SEC_ERR_TIMEOUT */
+   "user-abort",   /* FPGA_SEC_ERR_CANCELED */
+   "device-busy",  /* FPGA_SEC_ERR_BUSY */
+   "invalid-file-size",/* FPGA_SEC_ERR_INVALID_SIZE */
+   "read-write-error", /* FPGA_SEC_ERR_RW_ERROR */
+   "flash-wearout",/* FPGA_SEC_ERR_WEAROUT */
+   "file-read-error"   /* FPGA_SEC_ERR_FILE_READ */
+};
+
+static const char *sec_progress(struc

[PATCH v10 0/7] FPGA Security Manager Class Driver

2021-03-08 Thread Russ Weight
The FPGA Security Manager class driver provides a common
API for user-space tools to manage updates for secure FPGA
devices. Device drivers that instantiate the FPGA Security
Manager class driver will interact with a HW secure update
engine in order to transfer new FPGA and BMC images to FLASH so
that they will be automatically loaded when the FPGA card reboots.

A significant difference between the FPGA Manager and the FPGA 
Security Manager is that the FPGA Manager does a live update (Partial
Reconfiguration) to a device whereas the FPGA Security Manager
updates the FLASH images for the Static Region and the BMC so that
they will be loaded the next time the FPGA card boots. Security is
enforced by hardware and firmware. The security manager interacts
with the firmware to initiate an update, pass in the necessary data,
and collect status on the update.

The n3000bmc-secure driver is the first driver to use the FPGA
Security Manager. This driver was previously submitted in the same
patch set, but has been split out into a separate patch set starting
with V2. Future devices will also make use of this common API for
secure updates.

In addition to managing secure updates of the FPGA and BMC images,
the FPGA Security Manager update process may also be used to
program root entry hashes and cancellation keys for the FPGA static
region, the FPGA partial reconfiguration region, and the BMC.
The image files are self-describing, and contain a header describing
the image type.

Secure updates make use of the request_firmware framework, which
requires that image files are accessible under /lib/firmware. A request
for a secure update returns immediately, while the update itself
proceeds in the context of a kernel worker thread. Sysfs files provide
a means for monitoring the progress of a secure update and for
retrieving error information in the event of a failure.

The API includes a "name" sysfs file to export the name of the parent
driver. It also includes an "update" sub-directory containing files that
that can be used to instantiate and monitor a secure update.

Changelog v9 -> v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation

Changelog v8 -> v9:
  - Rebased patches for 5.11-rc2
  - Updated Date and KernelVersion in ABI documentation

Changelog v7 -> v8:
  - Fixed grammatical error in Documentation/fpga/fpga-sec-mgr.rst

Changelog v6 -> v7:
  - Changed dates in documentation file to December 2020
  - Changed filename_store() to use kmemdup_nul() instead of
kstrndup() and changed the count to not assume a line-return.

Changelog v5 -> v6:
  - Removed sysfs support and documentation for the display of the
flash count, root entry hashes, and code-signing-key cancelation
vectors from the class driver. This information can vary by device
and will instead be displayed by the device-specific parent driver.

Changelog v4 -> v5:
  - Added the devm_fpga_sec_mgr_unregister() function, following recent
changes to the fpga_manager() implementation.
  - Changed most of the *_show() functions to use sysfs_emit()
instead of sprintf(
  - When checking the return values for functions of type enum
fpga_sec_err err_code, test for FPGA_SEC_ERR_NONE instead of 0

Changelog v3 -> v4:
  - This driver is generic enough that it could be used for non Intel
FPGA devices. Changed from "Intel FPGA Security Manager" to FPGA
Security Manager" and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
Note that this also affects some filenames.

Changelog v2 -> v3:
  - Use dev_err() to report invalid progress in sec_progress()
  - Use dev_err() to report invalid error code in sec_error()
  - Modified sysfs handler check in check_sysfs_handler() to make
it more readable.
  - Removed unnecessary "goto done"
  - Added a comment to explain imgr->driver_unload in
ifpga_sec_mgr_unregister()

Changelog v1 -> v2:
  - Separated out the MAX10 BMC Security Engine to be submitted in
a separate patch-set.
  - Bumped documentation dates and versions
  - Split ifpga_sec_mgr_register() into create() and register() functions
  - Added devm_ifpga_sec_mgr_create()
  - Added Documentation/fpga/ifpga-sec-mgr.rst 
  - Changed progress state "read_file" to "reading"
  - Added sec_error() function (similar to sec_progress())
  - Removed references to bmc_flash_count & smbus_flash_count (not supported)
  - Removed typedefs for imgr ops
  - Removed explicit value assignments in enums
  - Other minor code cleanup per review comments 

Russ Weight (7):
  fpga: sec-mgr: fpga security manager class driver
  fpga: sec-mgr: enable secure updates
  fpga: sec-mgr: expose sec-mgr update status
  fpga: sec-mgr: expose sec-mgr update errors
  fpga: sec-mgr: expose sec-mgr update size
  fpga: sec-mgr: enable can

[PATCH v10 3/7] fpga: sec-mgr: expose sec-mgr update status

2021-03-08 Thread Russ Weight
Extend the FPGA Security Manager class driver to
include an update/status sysfs node that can be polled
and read to monitor the progress of an ongoing secure
update. Sysfs_notify() is used to signal transitions
between different phases of the update process.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the status_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Use a local variable to read progress once in status_show()
  - Use dev_err to report invalid progress status
v2:
  - Bumped documentation date and version
  - Changed progress state "read_file" to "reading"
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 11 +
 drivers/fpga/fpga-sec-mgr.c   | 42 +--
 2 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 4c0bdfd25553..64420c101626 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -16,3 +16,14 @@ Description: Write only. Write the filename of an image
BMC images, BMC firmware, Static Region images,
and Root Entry Hashes, and to cancel Code Signing
Keys (CSK).
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/status
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Read-only. Returns a string describing the current
+   status of an update. The string will be one of the
+   following: idle, reading, preparing, writing,
+   programming. Userspace code can poll on this file,
+   as it will be signaled by sysfs_notify() on each
+   state change.
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 7347ba1ba73e..dd60014b7511 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -25,6 +25,13 @@ struct fpga_sec_mgr_devres {
 
 #define to_sec_mgr(d) container_of(d, struct fpga_sec_mgr, dev)
 
+static void update_progress(struct fpga_sec_mgr *smgr,
+   enum fpga_sec_prog new_progress)
+{
+   smgr->progress = new_progress;
+   sysfs_notify(>dev.kobj, "update", "status");
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
@@ -35,7 +42,7 @@ static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
 static void progress_complete(struct fpga_sec_mgr *smgr)
 {
mutex_lock(>lock);
-   smgr->progress = FPGA_SEC_PROG_IDLE;
+   update_progress(smgr, FPGA_SEC_PROG_IDLE);
complete_all(>update_done);
mutex_unlock(>lock);
 }
@@ -63,14 +70,14 @@ static void fpga_sec_mgr_update(struct work_struct *work)
goto release_fw_exit;
}
 
-   smgr->progress = FPGA_SEC_PROG_PREPARING;
+   update_progress(smgr, FPGA_SEC_PROG_PREPARING);
ret = smgr->sops->prepare(smgr);
if (ret != FPGA_SEC_ERR_NONE) {
fpga_sec_dev_error(smgr, ret);
goto modput_exit;
}
 
-   smgr->progress = FPGA_SEC_PROG_WRITING;
+   update_progress(smgr, FPGA_SEC_PROG_WRITING);
size = smgr->remaining_size;
while (size) {
blk_size = min_t(u32, size, WRITE_BLOCK_SIZE);
@@ -85,7 +92,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
offset += blk_size;
}
 
-   smgr->progress = FPGA_SEC_PROG_PROGRAMMING;
+   update_progress(smgr, FPGA_SEC_PROG_PROGRAMMING);
ret = smgr->sops->poll_complete(smgr);
if (ret != FPGA_SEC_ERR_NONE)
fpga_sec_dev_error(smgr, ret);
@@ -113,6 +120,32 @@ static void fpga_sec_mgr_update(struct work_struct *work)
progress_complete(smgr);
 }
 
+static const char * const sec_mgr_prog_str[] = {
+   "idle", /* FPGA_SEC_PROG_IDLE */
+   "reading",  /* FPGA_SEC_PROG_READING */
+   "preparing",/* FPGA_SEC_PROG_PREPARING */
+   "writing",  /* FPGA_SEC_PROG_WRITING */
+   "programming"   /* FPGA_SEC_PROG_PROGRAMMING */
+};
+
+static ssize_t
+status_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(d

[PATCH v10 1/7] fpga: sec-mgr: fpga security manager class driver

2021-03-08 Thread Russ Weight
Create the FPGA Security Manager class driver. The security
manager provides interfaces to manage secure updates for the
FPGA and BMC images that are stored in FLASH. The driver can
also be used to update root entry hashes and to cancel code
signing keys. The image type is encoded in the image file
and is decoded by the HW/FW secure update engine.

Signed-off-by: Russ Weight 
Signed-off-by: Xu Yilun 
Reviewed-by: Tom Rix 
---
v10:
  - Rebased to 5.12-rc2 next
  - Updated Date and KernelVersion in ABI documentation
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Fixed grammatical error in Documentation/fpga/fpga-sec-mgr.rst
v7:
  - Changed Date in documentation file to December 2020
v6:
  - Removed sysfs support and documentation for the display of the
flash count, root entry hashes, and code-signing-key cancelation
vectors.
v5:
  - Added the devm_fpga_sec_mgr_unregister() function, following recent
changes to the fpga_manager() implementation.
  - Changed some *_show() functions to use sysfs_emit() instead of sprintf(
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Modified sysfs handler check in check_sysfs_handler() to make
it more readable.
v2:
  - Bumped documentation dates and versions
  - Added Documentation/fpga/ifpga-sec-mgr.rst 
  - Removed references to bmc_flash_count & smbus_flash_count (not supported)
  - Split ifpga_sec_mgr_register() into create() and register() functions
  - Added devm_ifpga_sec_mgr_create()
  - Removed typedefs for imgr ops
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  |   5 +
 Documentation/fpga/fpga-sec-mgr.rst   |  44 +++
 Documentation/fpga/index.rst  |   1 +
 MAINTAINERS   |   9 +
 drivers/fpga/Kconfig  |   9 +
 drivers/fpga/Makefile |   3 +
 drivers/fpga/fpga-sec-mgr.c   | 296 ++
 include/linux/fpga/fpga-sec-mgr.h |  44 +++
 8 files changed, 411 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
 create mode 100644 Documentation/fpga/fpga-sec-mgr.rst
 create mode 100644 drivers/fpga/fpga-sec-mgr.c
 create mode 100644 include/linux/fpga/fpga-sec-mgr.h

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
new file mode 100644
index ..0dda4604c178
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -0,0 +1,5 @@
+What:  /sys/class/fpga_sec_mgr/fpga_secX/name
+Date:  April 2021
+KernelVersion:  5.13
+Contact:   Russ Weight 
+Description:   Name of low level fpga security manager driver.
diff --git a/Documentation/fpga/fpga-sec-mgr.rst 
b/Documentation/fpga/fpga-sec-mgr.rst
new file mode 100644
index ..9f74c29fe63d
--- /dev/null
+++ b/Documentation/fpga/fpga-sec-mgr.rst
@@ -0,0 +1,44 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+
+FPGA Security Manager Class Driver
+
+
+The FPGA Security Manager class driver provides a common
+API for user-space tools to manage updates for secure FPGA
+devices. Device drivers that instantiate the Security
+Manager class driver will interact with a HW secure update
+engine in order to transfer new FPGA and BMC images to FLASH so
+that they will be automatically loaded when the FPGA card reboots.
+
+A significant difference between the FPGA Manager and the FPGA
+Security Manager is that the FPGA Manager does a live update (Partial
+Reconfiguration) to a device, whereas the FPGA Security Manager
+updates the FLASH images for the Static Region and the BMC so that
+they will be loaded the next time the FPGA card boots. Security is
+enforced by hardware and firmware. The security manager interacts
+with the firmware to initiate an update, pass in the necessary data,
+and collect status on the update.
+
+In addition to managing secure updates of the FPGA and BMC images,
+the FPGA Security Manager update process may also be used to
+program root entry hashes and cancellation keys for the FPGA static
+region, the FPGA partial reconfiguration region, and the BMC.
+
+Secure updates make use of the request_firmware framework, which
+requires that image files are accessible under /lib/firmware. A request
+for a secure update returns immediately, while the update itself
+proceeds in the context of a kernel worker thread. Sysfs files provide
+a means for monitoring the progress of a secure update and for
+retrieving error information in the event of a failure.
+
+Sysfs Attributes
+
+
+The API includes a sysfs entry *name* to export the name of the parent
+driver. It also includes an *update* sub-directory that c

[PATCH v8 1/1] fpga: dfl: afu: harden port enable logic

2021-03-03 Thread Russ Weight
Port enable is not complete until ACK = 0. Change
__afu_port_enable() to guarantee that the enable process
is complete by polling for ACK == 0.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
Reviewed-by: Matthew Gerlach 
Acked-by: Wu Hao 
---
v8:
  - Rebased to 5.12-rc1 (there were no conflicts)
v7:
  - Added Acked-by tag from Wu Hao
v6:
  - Fixed the dev_warn statement, which had "__func__" embedded in the
string instead of treated as a parameter to the format string.
v5:
  - Added Reviewed-by tag to commit message
v4:
  - Added a dev_warn() call for the -EINVAL case of afu_port_err_clear()
  - Modified dev_err() message in __afu_port_disable() to say "disable"
instead of "reset"
v3:
  - afu_port_err_clear() changed to prioritize port_enable failure over
other a detected mismatch in port errors.
  - reorganized code in port_reset() to be more readable.
v2:
  - Fixed typo in commit message
---
 drivers/fpga/dfl-afu-error.c | 10 ++
 drivers/fpga/dfl-afu-main.c  | 33 +++--
 drivers/fpga/dfl-afu.h   |  2 +-
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
index c4691187cca9..ab7be6217368 100644
--- a/drivers/fpga/dfl-afu-error.c
+++ b/drivers/fpga/dfl-afu-error.c
@@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 err)
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
struct platform_device *pdev = to_platform_device(dev);
void __iomem *base_err, *base_hdr;
-   int ret = -EBUSY;
+   int enable_ret = 0, ret = -EBUSY;
u64 v;
 
base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
@@ -96,18 +96,20 @@ static int afu_port_err_clear(struct device *dev, u64 err)
v = readq(base_err + PORT_FIRST_ERROR);
writeq(v, base_err + PORT_FIRST_ERROR);
} else {
+   dev_warn(dev, "%s: received 0x%llx, expected 0x%llx\n",
+__func__, v, err);
ret = -EINVAL;
}
 
/* Clear mask */
__afu_port_err_mask(dev, false);
 
-   /* Enable the Port by clear the reset */
-   __afu_port_enable(pdev);
+   /* Enable the Port by clearing the reset */
+   enable_ret = __afu_port_enable(pdev);
 
 done:
mutex_unlock(>lock);
-   return ret;
+   return enable_ret ? enable_ret : ret;
 }
 
 static ssize_t errors_show(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 753cda4b2568..77dadaae5b8f 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -21,6 +21,9 @@
 
 #include "dfl-afu.h"
 
+#define RST_POLL_INVL 10 /* us */
+#define RST_POLL_TIMEOUT 1000 /* us */
+
 /**
  * __afu_port_enable - enable a port by clear reset
  * @pdev: port platform device.
@@ -32,7 +35,7 @@
  *
  * The caller needs to hold lock for protection.
  */
-void __afu_port_enable(struct platform_device *pdev)
+int __afu_port_enable(struct platform_device *pdev)
 {
struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
void __iomem *base;
@@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
WARN_ON(!pdata->disable_count);
 
if (--pdata->disable_count != 0)
-   return;
+   return 0;
 
base = dfl_get_feature_ioaddr_by_id(>dev, PORT_FEATURE_ID_HEADER);
 
@@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
v = readq(base + PORT_HDR_CTRL);
v &= ~PORT_CTRL_SFTRST;
writeq(v, base + PORT_HDR_CTRL);
-}
 
-#define RST_POLL_INVL 10 /* us */
-#define RST_POLL_TIMEOUT 1000 /* us */
+   /*
+* HW clears the ack bit to indicate that the port is fully out
+* of reset.
+*/
+   if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
+  !(v & PORT_CTRL_SFTRST_ACK),
+  RST_POLL_INVL, RST_POLL_TIMEOUT)) {
+   dev_err(>dev, "timeout, failure to enable device\n");
+   return -ETIMEDOUT;
+   }
+
+   return 0;
+}
 
 /**
  * __afu_port_disable - disable a port by hold reset
@@ -86,7 +99,7 @@ int __afu_port_disable(struct platform_device *pdev)
if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
   v & PORT_CTRL_SFTRST_ACK,
   RST_POLL_INVL, RST_POLL_TIMEOUT)) {
-   dev_err(>dev, "timeout, fail to reset device\n");
+   dev_err(>dev, "timeout, failure to disable device\n");
return -ETIMEDOUT;
}
 
@@ -111,9 +124,9 @@ static int __port_reset(struct platform_device *pdev)
 
ret = __afu_port_disable(pdev);
if (!ret)
-   __afu_port_enable(pdev);
+   

[PATCH v7 1/1] fpga: dfl: afu: harden port enable logic

2021-02-23 Thread Russ Weight
Port enable is not complete until ACK = 0. Change
__afu_port_enable() to guarantee that the enable process
is complete by polling for ACK == 0.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
Reviewed-by: Matthew Gerlach 
Acked-by: Wu Hao 
---
v7:
  - Added Acked-by tag from Wu Hao
v6:
  - Fixed the dev_warn statement, which had "__func__" embedded in the
string instead of treated as a parameter to the format string.
v5:
  - Added Reviewed-by tag to commit message
v4:
  - Added a dev_warn() call for the -EINVAL case of afu_port_err_clear()
  - Modified dev_err() message in __afu_port_disable() to say "disable"
instead of "reset"
v3:
  - afu_port_err_clear() changed to prioritize port_enable failure over
other a detected mismatch in port errors.
  - reorganized code in port_reset() to be more readable.
v2:
  - Fixed typo in commit message
---
 drivers/fpga/dfl-afu-error.c | 10 ++
 drivers/fpga/dfl-afu-main.c  | 33 +++--
 drivers/fpga/dfl-afu.h   |  2 +-
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
index c4691187cca9..ab7be6217368 100644
--- a/drivers/fpga/dfl-afu-error.c
+++ b/drivers/fpga/dfl-afu-error.c
@@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 err)
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
struct platform_device *pdev = to_platform_device(dev);
void __iomem *base_err, *base_hdr;
-   int ret = -EBUSY;
+   int enable_ret = 0, ret = -EBUSY;
u64 v;
 
base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
@@ -96,18 +96,20 @@ static int afu_port_err_clear(struct device *dev, u64 err)
v = readq(base_err + PORT_FIRST_ERROR);
writeq(v, base_err + PORT_FIRST_ERROR);
} else {
+   dev_warn(dev, "%s: received 0x%llx, expected 0x%llx\n",
+__func__, v, err);
ret = -EINVAL;
}
 
/* Clear mask */
__afu_port_err_mask(dev, false);
 
-   /* Enable the Port by clear the reset */
-   __afu_port_enable(pdev);
+   /* Enable the Port by clearing the reset */
+   enable_ret = __afu_port_enable(pdev);
 
 done:
mutex_unlock(>lock);
-   return ret;
+   return enable_ret ? enable_ret : ret;
 }
 
 static ssize_t errors_show(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 753cda4b2568..77dadaae5b8f 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -21,6 +21,9 @@
 
 #include "dfl-afu.h"
 
+#define RST_POLL_INVL 10 /* us */
+#define RST_POLL_TIMEOUT 1000 /* us */
+
 /**
  * __afu_port_enable - enable a port by clear reset
  * @pdev: port platform device.
@@ -32,7 +35,7 @@
  *
  * The caller needs to hold lock for protection.
  */
-void __afu_port_enable(struct platform_device *pdev)
+int __afu_port_enable(struct platform_device *pdev)
 {
struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
void __iomem *base;
@@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
WARN_ON(!pdata->disable_count);
 
if (--pdata->disable_count != 0)
-   return;
+   return 0;
 
base = dfl_get_feature_ioaddr_by_id(>dev, PORT_FEATURE_ID_HEADER);
 
@@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
v = readq(base + PORT_HDR_CTRL);
v &= ~PORT_CTRL_SFTRST;
writeq(v, base + PORT_HDR_CTRL);
-}
 
-#define RST_POLL_INVL 10 /* us */
-#define RST_POLL_TIMEOUT 1000 /* us */
+   /*
+* HW clears the ack bit to indicate that the port is fully out
+* of reset.
+*/
+   if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
+  !(v & PORT_CTRL_SFTRST_ACK),
+  RST_POLL_INVL, RST_POLL_TIMEOUT)) {
+   dev_err(>dev, "timeout, failure to enable device\n");
+   return -ETIMEDOUT;
+   }
+
+   return 0;
+}
 
 /**
  * __afu_port_disable - disable a port by hold reset
@@ -86,7 +99,7 @@ int __afu_port_disable(struct platform_device *pdev)
if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
   v & PORT_CTRL_SFTRST_ACK,
   RST_POLL_INVL, RST_POLL_TIMEOUT)) {
-   dev_err(>dev, "timeout, fail to reset device\n");
+   dev_err(>dev, "timeout, failure to disable device\n");
return -ETIMEDOUT;
}
 
@@ -111,9 +124,9 @@ static int __port_reset(struct platform_device *pdev)
 
ret = __afu_port_disable(pdev);
if (!ret)
-   __afu_port_enable(pdev);
+   return ret;
 
-   return ret;
+   return

[PATCH v6 1/1] fpga: dfl: afu: harden port enable logic

2021-02-22 Thread Russ Weight
Port enable is not complete until ACK = 0. Change
__afu_port_enable() to guarantee that the enable process
is complete by polling for ACK == 0.

Reviewed-by: Tom Rix 
Reviewed-by: Matthew Gerlach 
Signed-off-by: Russ Weight 
---
v6:
  - Fixed the dev_warn statement, which had "__func__" embedded in the
string instead of treated as a parameter to the format string.
v5:
  - Added Reviewed-by tag to commit message
v4:
  - Added a dev_warn() call for the -EINVAL case of afu_port_err_clear()
  - Modified dev_err() message in __afu_port_disable() to say "disable"
instead of "reset"
v3:
  - afu_port_err_clear() changed to prioritize port_enable failure over
other a detected mismatch in port errors.
  - reorganized code in port_reset() to be more readable.
v2:
  - Fixed typo in commit message
---
 drivers/fpga/dfl-afu-error.c | 10 ++
 drivers/fpga/dfl-afu-main.c  | 33 +++--
 drivers/fpga/dfl-afu.h   |  2 +-
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
index c4691187cca9..ab7be6217368 100644
--- a/drivers/fpga/dfl-afu-error.c
+++ b/drivers/fpga/dfl-afu-error.c
@@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 err)
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
struct platform_device *pdev = to_platform_device(dev);
void __iomem *base_err, *base_hdr;
-   int ret = -EBUSY;
+   int enable_ret = 0, ret = -EBUSY;
u64 v;
 
base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
@@ -96,18 +96,20 @@ static int afu_port_err_clear(struct device *dev, u64 err)
v = readq(base_err + PORT_FIRST_ERROR);
writeq(v, base_err + PORT_FIRST_ERROR);
} else {
+   dev_warn(dev, "%s: received 0x%llx, expected 0x%llx\n",
+__func__, v, err);
ret = -EINVAL;
}
 
/* Clear mask */
__afu_port_err_mask(dev, false);
 
-   /* Enable the Port by clear the reset */
-   __afu_port_enable(pdev);
+   /* Enable the Port by clearing the reset */
+   enable_ret = __afu_port_enable(pdev);
 
 done:
mutex_unlock(>lock);
-   return ret;
+   return enable_ret ? enable_ret : ret;
 }
 
 static ssize_t errors_show(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 753cda4b2568..77dadaae5b8f 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -21,6 +21,9 @@
 
 #include "dfl-afu.h"
 
+#define RST_POLL_INVL 10 /* us */
+#define RST_POLL_TIMEOUT 1000 /* us */
+
 /**
  * __afu_port_enable - enable a port by clear reset
  * @pdev: port platform device.
@@ -32,7 +35,7 @@
  *
  * The caller needs to hold lock for protection.
  */
-void __afu_port_enable(struct platform_device *pdev)
+int __afu_port_enable(struct platform_device *pdev)
 {
struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
void __iomem *base;
@@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
WARN_ON(!pdata->disable_count);
 
if (--pdata->disable_count != 0)
-   return;
+   return 0;
 
base = dfl_get_feature_ioaddr_by_id(>dev, PORT_FEATURE_ID_HEADER);
 
@@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
v = readq(base + PORT_HDR_CTRL);
v &= ~PORT_CTRL_SFTRST;
writeq(v, base + PORT_HDR_CTRL);
-}
 
-#define RST_POLL_INVL 10 /* us */
-#define RST_POLL_TIMEOUT 1000 /* us */
+   /*
+* HW clears the ack bit to indicate that the port is fully out
+* of reset.
+*/
+   if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
+  !(v & PORT_CTRL_SFTRST_ACK),
+  RST_POLL_INVL, RST_POLL_TIMEOUT)) {
+   dev_err(>dev, "timeout, failure to enable device\n");
+   return -ETIMEDOUT;
+   }
+
+   return 0;
+}
 
 /**
  * __afu_port_disable - disable a port by hold reset
@@ -86,7 +99,7 @@ int __afu_port_disable(struct platform_device *pdev)
if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
   v & PORT_CTRL_SFTRST_ACK,
   RST_POLL_INVL, RST_POLL_TIMEOUT)) {
-   dev_err(>dev, "timeout, fail to reset device\n");
+   dev_err(>dev, "timeout, failure to disable device\n");
return -ETIMEDOUT;
}
 
@@ -111,9 +124,9 @@ static int __port_reset(struct platform_device *pdev)
 
ret = __afu_port_disable(pdev);
if (!ret)
-   __afu_port_enable(pdev);
+   return ret;
 
-   return ret;
+   return __afu_port_enable(pdev);
 }
 
 static int port_reset(

Re: [PATCH v9 0/7] FPGA Security Manager Class Driver

2021-02-16 Thread Russ Weight
I believe all of the dependencies have been accepted now.

- Russ

On 2/15/21 6:56 AM, Tom Rix wrote:
> Russ, Moritz
>
> This patchset still applies.
>
> Updating the fpga is a fairly important feature.
>
> Are there any dependencies we are waiting on ?
>
> Tom
>
> On 1/5/21 2:59 PM, Russ Weight wrote:
>> The FPGA Security Manager class driver provides a common
>> API for user-space tools to manage updates for secure FPGA
>> devices. Device drivers that instantiate the FPGA Security
>> Manager class driver will interact with a HW secure update
>> engine in order to transfer new FPGA and BMC images to FLASH so
>> that they will be automatically loaded when the FPGA card reboots.
>>
>> A significant difference between the FPGA Manager and the FPGA 
>> Security Manager is that the FPGA Manager does a live update (Partial
>> Reconfiguration) to a device whereas the FPGA Security Manager
>> updates the FLASH images for the Static Region and the BMC so that
>> they will be loaded the next time the FPGA card boots. Security is
>> enforced by hardware and firmware. The security manager interacts
>> with the firmware to initiate an update, pass in the necessary data,
>> and collect status on the update.
>>
>> The n3000bmc-secure driver is the first driver to use the FPGA
>> Security Manager. This driver was previously submitted in the same
>> patch set, but has been split out into a separate patch set starting
>> with V2. Future devices will also make use of this common API for
>> secure updates.
>>
>> In addition to managing secure updates of the FPGA and BMC images,
>> the FPGA Security Manager update process may also be used to
>> program root entry hashes and cancellation keys for the FPGA static
>> region, the FPGA partial reconfiguration region, and the BMC.
>> The image files are self-describing, and contain a header describing
>> the image type.
>>
>> Secure updates make use of the request_firmware framework, which
>> requires that image files are accessible under /lib/firmware. A request
>> for a secure update returns immediately, while the update itself
>> proceeds in the context of a kernel worker thread. Sysfs files provide
>> a means for monitoring the progress of a secure update and for
>> retrieving error information in the event of a failure.
>>
>> The API includes a "name" sysfs file to export the name of the parent
>> driver. It also includes an "update" sub-directory containing files that
>> that can be used to instantiate and monitor a secure update.
>>
>> Changelog v8 -> v9:
>>   - Rebased patches for 5.11-rc2
>>   - Updated Date and KernelVersion in ABI documentation
>>
>> Changelog v7 -> v8:
>>   - Fixed grammatical error in Documentation/fpga/fpga-sec-mgr.rst
>>
>> Changelog v6 -> v7:
>>   - Changed dates in documentation file to December 2020
>>   - Changed filename_store() to use kmemdup_nul() instead of
>> kstrndup() and changed the count to not assume a line-return.
>>
>> Changelog v5 -> v6:
>>   - Removed sysfs support and documentation for the display of the
>> flash count, root entry hashes, and code-signing-key cancelation
>> vectors from the class driver. This information can vary by device
>> and will instead be displayed by the device-specific parent driver.
>>
>> Changelog v4 -> v5:
>>   - Added the devm_fpga_sec_mgr_unregister() function, following recent
>> changes to the fpga_manager() implementation.
>>   - Changed most of the *_show() functions to use sysfs_emit()
>> instead of sprintf(
>>   - When checking the return values for functions of type enum
>> fpga_sec_err err_code, test for FPGA_SEC_ERR_NONE instead of 0
>>
>> Changelog v3 -> v4:
>>   - This driver is generic enough that it could be used for non Intel
>> FPGA devices. Changed from "Intel FPGA Security Manager" to FPGA
>> Security Manager" and removed unnecessary references to "Intel".
>>   - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
>> Note that this also affects some filenames.
>>
>> Changelog v2 -> v3:
>>   - Use dev_err() to report invalid progress in sec_progress()
>>   - Use dev_err() to report invalid error code in sec_error()
>>   - Modified sysfs handler check in check_sysfs_handler() to make
>> it more readable.
>>   - Removed unnecessary "goto done"
>>   - Added a comment to explain imgr->driver_unload in
>> ifpga_sec_mgr_unreg

Re: [PATCH v5 1/1] fpga: dfl: afu: harden port enable logic

2021-02-08 Thread Russ Weight



On 2/6/21 12:46 PM, Moritz Fischer wrote:
> Russ,
>
> On Fri, Feb 05, 2021 at 10:25:21AM -0800, Russ Weight wrote:
>> Port enable is not complete until ACK = 0. Change
>> __afu_port_enable() to guarantee that the enable process
>> is complete by polling for ACK == 0.
>>
>> Reviewed-by: Tom Rix 
>> Reviewed-by: Matthew Gerlach 
>> Signed-off-by: Russ Weight 
>> ---
>> v5:
>>   - Added Reviewed-by tag to commit message
>> v4:
>>   - Added a dev_warn() call for the -EINVAL case of afu_port_err_clear()
>>   - Modified dev_err() message in __afu_port_disable() to say "disable"
>> instead of "reset"
>> v3:
>>   - afu_port_err_clear() changed to prioritize port_enable failure over
>> other a detected mismatch in port errors.
>>   - reorganized code in port_reset() to be more readable.
>> v2:
>>   - Fixed typo in commit message
>> ---
>>  drivers/fpga/dfl-afu-error.c | 10 ++
>>  drivers/fpga/dfl-afu-main.c  | 33 +++--
>>  drivers/fpga/dfl-afu.h   |  2 +-
>>  3 files changed, 30 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
>> index c4691187cca9..601e599fc33d 100644
>> --- a/drivers/fpga/dfl-afu-error.c
>> +++ b/drivers/fpga/dfl-afu-error.c
>> @@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 err)
>>  struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
>>  struct platform_device *pdev = to_platform_device(dev);
>>  void __iomem *base_err, *base_hdr;
>> -int ret = -EBUSY;
>> +int enable_ret = 0, ret = -EBUSY;
>>  u64 v;
>>  
>>  base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
>> @@ -96,18 +96,20 @@ static int afu_port_err_clear(struct device *dev, u64 
>> err)
>>  v = readq(base_err + PORT_FIRST_ERROR);
>>  writeq(v, base_err + PORT_FIRST_ERROR);
>>  } else {
>> +dev_warn(dev, "__func__: received 0x%llx, expected 0x%llx\n",
>> + v, err);
>>  ret = -EINVAL;
>>  }
>>  
>>  /* Clear mask */
>>  __afu_port_err_mask(dev, false);
>>  
>> -/* Enable the Port by clear the reset */
>> -__afu_port_enable(pdev);
>> +/* Enable the Port by clearing the reset */
>> +enable_ret = __afu_port_enable(pdev);
>>  
>>  done:
>>  mutex_unlock(>lock);
>> -return ret;
>> +return enable_ret ? enable_ret : ret;
> Help me understand (sorry if I'm slow here ...), you set ret to -EINVAL,
> but then we only care if enabling the port worked?
Port errors are represented in a bitmask. To clear the errors, the same bitmask 
is
expected to be written to the "errors" sysfs node. It is considered an error
(EINVAL) if the values do not match. This would most likely be a user error.

The second error case is that we fail to enable the port. This is a
critical/fatal HW error, indicating that the PR region can not be accessed.

The EINVAL still has meaning (I have added an informative warning message for 
this
case), but it is not as serious as the inability to re-enable the port. So we 
are
prioritizing the more critical error code.

- Russ
>
> I'm not sure I follow the logic (doesn't mean it's wrong :) ).
>>  }
>>  
>>  static ssize_t errors_show(struct device *dev, struct device_attribute 
>> *attr,
>> diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
>> index 753cda4b2568..77dadaae5b8f 100644
>> --- a/drivers/fpga/dfl-afu-main.c
>> +++ b/drivers/fpga/dfl-afu-main.c
>> @@ -21,6 +21,9 @@
>>  
>>  #include "dfl-afu.h"
>>  
>> +#define RST_POLL_INVL 10 /* us */
>> +#define RST_POLL_TIMEOUT 1000 /* us */
>> +
>>  /**
>>   * __afu_port_enable - enable a port by clear reset
>>   * @pdev: port platform device.
>> @@ -32,7 +35,7 @@
>>   *
>>   * The caller needs to hold lock for protection.
>>   */
>> -void __afu_port_enable(struct platform_device *pdev)
>> +int __afu_port_enable(struct platform_device *pdev)
>>  {
>>  struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
>>  void __iomem *base;
>> @@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
>>  WARN_ON(!pdata->disable_count);
>>  
>>  if (--pdata->disable_count != 0)
>> -return;
>> +return 0;
>>  
>>  base = dfl_get_feature_ioaddr_by_id(>dev, PORT_F

[PATCH v5 1/1] fpga: dfl: afu: harden port enable logic

2021-02-05 Thread Russ Weight
Port enable is not complete until ACK = 0. Change
__afu_port_enable() to guarantee that the enable process
is complete by polling for ACK == 0.

Reviewed-by: Tom Rix 
Reviewed-by: Matthew Gerlach 
Signed-off-by: Russ Weight 
---
v5:
  - Added Reviewed-by tag to commit message
v4:
  - Added a dev_warn() call for the -EINVAL case of afu_port_err_clear()
  - Modified dev_err() message in __afu_port_disable() to say "disable"
instead of "reset"
v3:
  - afu_port_err_clear() changed to prioritize port_enable failure over
other a detected mismatch in port errors.
  - reorganized code in port_reset() to be more readable.
v2:
  - Fixed typo in commit message
---
 drivers/fpga/dfl-afu-error.c | 10 ++
 drivers/fpga/dfl-afu-main.c  | 33 +++--
 drivers/fpga/dfl-afu.h   |  2 +-
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
index c4691187cca9..601e599fc33d 100644
--- a/drivers/fpga/dfl-afu-error.c
+++ b/drivers/fpga/dfl-afu-error.c
@@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 err)
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
struct platform_device *pdev = to_platform_device(dev);
void __iomem *base_err, *base_hdr;
-   int ret = -EBUSY;
+   int enable_ret = 0, ret = -EBUSY;
u64 v;
 
base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
@@ -96,18 +96,20 @@ static int afu_port_err_clear(struct device *dev, u64 err)
v = readq(base_err + PORT_FIRST_ERROR);
writeq(v, base_err + PORT_FIRST_ERROR);
} else {
+   dev_warn(dev, "__func__: received 0x%llx, expected 0x%llx\n",
+v, err);
ret = -EINVAL;
}
 
/* Clear mask */
__afu_port_err_mask(dev, false);
 
-   /* Enable the Port by clear the reset */
-   __afu_port_enable(pdev);
+   /* Enable the Port by clearing the reset */
+   enable_ret = __afu_port_enable(pdev);
 
 done:
mutex_unlock(>lock);
-   return ret;
+   return enable_ret ? enable_ret : ret;
 }
 
 static ssize_t errors_show(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 753cda4b2568..77dadaae5b8f 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -21,6 +21,9 @@
 
 #include "dfl-afu.h"
 
+#define RST_POLL_INVL 10 /* us */
+#define RST_POLL_TIMEOUT 1000 /* us */
+
 /**
  * __afu_port_enable - enable a port by clear reset
  * @pdev: port platform device.
@@ -32,7 +35,7 @@
  *
  * The caller needs to hold lock for protection.
  */
-void __afu_port_enable(struct platform_device *pdev)
+int __afu_port_enable(struct platform_device *pdev)
 {
struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
void __iomem *base;
@@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
WARN_ON(!pdata->disable_count);
 
if (--pdata->disable_count != 0)
-   return;
+   return 0;
 
base = dfl_get_feature_ioaddr_by_id(>dev, PORT_FEATURE_ID_HEADER);
 
@@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
v = readq(base + PORT_HDR_CTRL);
v &= ~PORT_CTRL_SFTRST;
writeq(v, base + PORT_HDR_CTRL);
-}
 
-#define RST_POLL_INVL 10 /* us */
-#define RST_POLL_TIMEOUT 1000 /* us */
+   /*
+* HW clears the ack bit to indicate that the port is fully out
+* of reset.
+*/
+   if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
+  !(v & PORT_CTRL_SFTRST_ACK),
+  RST_POLL_INVL, RST_POLL_TIMEOUT)) {
+   dev_err(>dev, "timeout, failure to enable device\n");
+   return -ETIMEDOUT;
+   }
+
+   return 0;
+}
 
 /**
  * __afu_port_disable - disable a port by hold reset
@@ -86,7 +99,7 @@ int __afu_port_disable(struct platform_device *pdev)
if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
   v & PORT_CTRL_SFTRST_ACK,
   RST_POLL_INVL, RST_POLL_TIMEOUT)) {
-   dev_err(>dev, "timeout, fail to reset device\n");
+   dev_err(>dev, "timeout, failure to disable device\n");
return -ETIMEDOUT;
}
 
@@ -111,9 +124,9 @@ static int __port_reset(struct platform_device *pdev)
 
ret = __afu_port_disable(pdev);
if (!ret)
-   __afu_port_enable(pdev);
+   return ret;
 
-   return ret;
+   return __afu_port_enable(pdev);
 }
 
 static int port_reset(struct platform_device *pdev)
@@ -872,11 +885,11 @@ static int afu_dev_destroy(struct platform_device *pdev)
 static int port_enable_set(struct plat

[PATCH v4 1/1] fpga: dfl: afu: harden port enable logic

2021-02-04 Thread Russ Weight
Port enable is not complete until ACK = 0. Change
__afu_port_enable() to guarantee that the enable process
is complete by polling for ACK == 0.

Reviewed-by: Tom Rix 
Signed-off-by: Russ Weight 
---
v4:
  - Added a dev_warn() call for the -EINVAL case of afu_port_err_clear()
  - Modified dev_err() message in __afu_port_disable() to say "disable"
instead of "reset"
v3:
  - afu_port_err_clear() changed to prioritize port_enable failure over
other a detected mismatch in port errors.
  - reorganized code in port_reset() to be more readable.
v2:
  - Fixed typo in commit message
---
 drivers/fpga/dfl-afu-error.c | 10 ++
 drivers/fpga/dfl-afu-main.c  | 33 +++--
 drivers/fpga/dfl-afu.h   |  2 +-
 3 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
index c4691187cca9..601e599fc33d 100644
--- a/drivers/fpga/dfl-afu-error.c
+++ b/drivers/fpga/dfl-afu-error.c
@@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 err)
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
struct platform_device *pdev = to_platform_device(dev);
void __iomem *base_err, *base_hdr;
-   int ret = -EBUSY;
+   int enable_ret = 0, ret = -EBUSY;
u64 v;
 
base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
@@ -96,18 +96,20 @@ static int afu_port_err_clear(struct device *dev, u64 err)
v = readq(base_err + PORT_FIRST_ERROR);
writeq(v, base_err + PORT_FIRST_ERROR);
} else {
+   dev_warn(dev, "__func__: received 0x%llx, expected 0x%llx\n",
+v, err);
ret = -EINVAL;
}
 
/* Clear mask */
__afu_port_err_mask(dev, false);
 
-   /* Enable the Port by clear the reset */
-   __afu_port_enable(pdev);
+   /* Enable the Port by clearing the reset */
+   enable_ret = __afu_port_enable(pdev);
 
 done:
mutex_unlock(>lock);
-   return ret;
+   return enable_ret ? enable_ret : ret;
 }
 
 static ssize_t errors_show(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 753cda4b2568..77dadaae5b8f 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -21,6 +21,9 @@
 
 #include "dfl-afu.h"
 
+#define RST_POLL_INVL 10 /* us */
+#define RST_POLL_TIMEOUT 1000 /* us */
+
 /**
  * __afu_port_enable - enable a port by clear reset
  * @pdev: port platform device.
@@ -32,7 +35,7 @@
  *
  * The caller needs to hold lock for protection.
  */
-void __afu_port_enable(struct platform_device *pdev)
+int __afu_port_enable(struct platform_device *pdev)
 {
struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
void __iomem *base;
@@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
WARN_ON(!pdata->disable_count);
 
if (--pdata->disable_count != 0)
-   return;
+   return 0;
 
base = dfl_get_feature_ioaddr_by_id(>dev, PORT_FEATURE_ID_HEADER);
 
@@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
v = readq(base + PORT_HDR_CTRL);
v &= ~PORT_CTRL_SFTRST;
writeq(v, base + PORT_HDR_CTRL);
-}
 
-#define RST_POLL_INVL 10 /* us */
-#define RST_POLL_TIMEOUT 1000 /* us */
+   /*
+* HW clears the ack bit to indicate that the port is fully out
+* of reset.
+*/
+   if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
+  !(v & PORT_CTRL_SFTRST_ACK),
+  RST_POLL_INVL, RST_POLL_TIMEOUT)) {
+   dev_err(>dev, "timeout, failure to enable device\n");
+   return -ETIMEDOUT;
+   }
+
+   return 0;
+}
 
 /**
  * __afu_port_disable - disable a port by hold reset
@@ -86,7 +99,7 @@ int __afu_port_disable(struct platform_device *pdev)
if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
   v & PORT_CTRL_SFTRST_ACK,
   RST_POLL_INVL, RST_POLL_TIMEOUT)) {
-   dev_err(>dev, "timeout, fail to reset device\n");
+   dev_err(>dev, "timeout, failure to disable device\n");
return -ETIMEDOUT;
}
 
@@ -111,9 +124,9 @@ static int __port_reset(struct platform_device *pdev)
 
ret = __afu_port_disable(pdev);
if (!ret)
-   __afu_port_enable(pdev);
+   return ret;
 
-   return ret;
+   return __afu_port_enable(pdev);
 }
 
 static int port_reset(struct platform_device *pdev)
@@ -872,11 +885,11 @@ static int afu_dev_destroy(struct platform_device *pdev)
 static int port_enable_set(struct platform_device *pdev, bool enable)
 {
struct dfl_feature_platform_data *pdata = dev

Re: [PATCH v3 1/1] fpga: dfl: afu: harden port enable logic

2021-02-04 Thread Russ Weight



On 2/3/21 5:38 PM, Wu, Hao wrote:
>> On 2/3/21 1:01 AM, Wu, Hao wrote:
>>>> Subject: [PATCH v3 1/1] fpga: dfl: afu: harden port enable logic
>>>>
>>>> Port enable is not complete until ACK = 0. Change
>>>> __afu_port_enable() to guarantee that the enable process
>>>> is complete by polling for ACK == 0.
>>>>
>>>> Signed-off-by: Russ Weight 
>>>> ---
>>>> v3:
>>>>   - afu_port_err_clear() changed to prioritize port_enable failure over
>>>> other a detected mismatch in port errors.
>>>>   - reorganized code in port_reset() to be more readable.
>>>> v2:
>>>>   - Fixed typo in commit message
>>>> ---
>>>>  drivers/fpga/dfl-afu-error.c |  8 
>>>>  drivers/fpga/dfl-afu-main.c  | 31 ++-
>>>>  drivers/fpga/dfl-afu.h   |  2 +-
>>>>  3 files changed, 27 insertions(+), 14 deletions(-)
>>>>
>>>> diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
>>>> index c4691187cca9..2ced610059cc 100644
>>>> --- a/drivers/fpga/dfl-afu-error.c
>>>> +++ b/drivers/fpga/dfl-afu-error.c
>>>> @@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 
>>>> err)
>>>>  struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
>>>>  struct platform_device *pdev = to_platform_device(dev);
>>>>  void __iomem *base_err, *base_hdr;
>>>> -int ret = -EBUSY;
>>>> +int enable_ret = 0, ret = -EBUSY;
>>>>  u64 v;
>>>>
>>>>  base_err = dfl_get_feature_ioaddr_by_id(dev,
>>>> PORT_FEATURE_ID_ERROR);
>>>> @@ -102,12 +102,12 @@ static int afu_port_err_clear(struct device *dev,
>> u64
>>>> err)
>>>>  /* Clear mask */
>>>>  __afu_port_err_mask(dev, false);
>>>>
>>>> -/* Enable the Port by clear the reset */
>>>> -__afu_port_enable(pdev);
>>>> +/* Enable the Port by clearing the reset */
>>>> +enable_ret = __afu_port_enable(pdev);
>>>>
>>>>  done:
>>>>  mutex_unlock(>lock);
>>>> -return ret;
>>>> +return enable_ret ? enable_ret : ret;
>>> Maybe we should add some error message to notify user, there are more
>> errors happened,
>>> as some ret value is not returned.
>> It is the -EINVAL error case that would get lost if there was a double error.
>> This error indicates that the value written to sysfs by the user does not
>> correspond to the current port errors. This is not a hardware error, and 
>> could
>> even be a user error. Do you think a warning in the error log is needed here?
> I think so, as there are actually two errors there, I feel it's better to let 
> user know
> their input is not accepted too than just keeping silence, right? as this 
> error
> should be triggered by user input?
In the single error case, the EINVAL would be returned to the user-space 
caller. That is
the common case. In the double error case, the EINVAL would be lost. Either 
way, it is
helpful to know what the expected/actual values are. I have added a warning 
message to
the kernel log for the next version of the patch which also shows the 
expected/actual
values.

- Russ
>
> Hao
>
>>>>  }
>>>>
>>>>  static ssize_t errors_show(struct device *dev, struct device_attribute 
>>>> *attr,
>>>> diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
>>>> index 753cda4b2568..729eb306062e 100644
>>>> --- a/drivers/fpga/dfl-afu-main.c
>>>> +++ b/drivers/fpga/dfl-afu-main.c
>>>> @@ -21,6 +21,9 @@
>>>>
>>>>  #include "dfl-afu.h"
>>>>
>>>> +#define RST_POLL_INVL 10 /* us */
>>>> +#define RST_POLL_TIMEOUT 1000 /* us */
>>>> +
>>>>  /**
>>>>   * __afu_port_enable - enable a port by clear reset
>>>>   * @pdev: port platform device.
>>>> @@ -32,7 +35,7 @@
>>>>   *
>>>>   * The caller needs to hold lock for protection.
>>>>   */
>>>> -void __afu_port_enable(struct platform_device *pdev)
>>>> +int __afu_port_enable(struct platform_device *pdev)
>>>>  {
>>>>  struct dfl_feature_platform_data *pdata = dev_get_platdata(
>>>>> dev);
>>>>  void __iomem *base;
>>>> @@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pde

Re: [PATCH v3 1/1] fpga: dfl: afu: harden port enable logic

2021-02-03 Thread Russ Weight



On 2/3/21 7:25 AM, Tom Rix wrote:
> ..snip..
>
> On 2/2/21 3:06 PM, Russ Weight wrote:
>> diff --git a/drivers/fpga/dfl-afu.h b/drivers/fpga/dfl-afu.h
>> index 576e94960086..e5020e2b1f3d 100644
>> --- a/drivers/fpga/dfl-afu.h
>> +++ b/drivers/fpga/dfl-afu.h
>> @@ -80,7 +80,7 @@ struct dfl_afu {
>>  };
>>  
>>  /* hold pdata->lock when call __afu_port_enable/disable */
>> -void __afu_port_enable(struct platform_device *pdev);
>> +int __afu_port_enable(struct platform_device *pdev);
>>  int __afu_port_disable(struct platform_device *pdev);
>>  
> Should the '__' prefix be removed from __afu_port* ?
>
> This would make the function names consistent with the other decls

The '__' prefix is used here to help highlight the fact that these functions go 
not manage
the locking themselves and must be called while holding the port mutex. There 
are additional
functions, such as__port_reset(), that are following this same convention. I 
think these
are OK as they are.

- Russ

>
> Tom
>
>>  void afu_mmio_region_init(struct dfl_feature_platform_data *pdata);



Re: [PATCH v3 1/1] fpga: dfl: afu: harden port enable logic

2021-02-03 Thread Russ Weight



On 2/3/21 1:01 AM, Wu, Hao wrote:
>> Subject: [PATCH v3 1/1] fpga: dfl: afu: harden port enable logic
>>
>> Port enable is not complete until ACK = 0. Change
>> __afu_port_enable() to guarantee that the enable process
>> is complete by polling for ACK == 0.
>>
>> Signed-off-by: Russ Weight 
>> ---
>> v3:
>>   - afu_port_err_clear() changed to prioritize port_enable failure over
>> other a detected mismatch in port errors.
>>   - reorganized code in port_reset() to be more readable.
>> v2:
>>   - Fixed typo in commit message
>> ---
>>  drivers/fpga/dfl-afu-error.c |  8 
>>  drivers/fpga/dfl-afu-main.c  | 31 ++-
>>  drivers/fpga/dfl-afu.h   |  2 +-
>>  3 files changed, 27 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
>> index c4691187cca9..2ced610059cc 100644
>> --- a/drivers/fpga/dfl-afu-error.c
>> +++ b/drivers/fpga/dfl-afu-error.c
>> @@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 err)
>>  struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
>>  struct platform_device *pdev = to_platform_device(dev);
>>  void __iomem *base_err, *base_hdr;
>> -int ret = -EBUSY;
>> +int enable_ret = 0, ret = -EBUSY;
>>  u64 v;
>>
>>  base_err = dfl_get_feature_ioaddr_by_id(dev,
>> PORT_FEATURE_ID_ERROR);
>> @@ -102,12 +102,12 @@ static int afu_port_err_clear(struct device *dev, u64
>> err)
>>  /* Clear mask */
>>  __afu_port_err_mask(dev, false);
>>
>> -/* Enable the Port by clear the reset */
>> -__afu_port_enable(pdev);
>> +/* Enable the Port by clearing the reset */
>> +enable_ret = __afu_port_enable(pdev);
>>
>>  done:
>>  mutex_unlock(>lock);
>> -return ret;
>> +return enable_ret ? enable_ret : ret;
> Maybe we should add some error message to notify user, there are more errors 
> happened,
> as some ret value is not returned.
It is the -EINVAL error case that would get lost if there was a double error.
This error indicates that the value written to sysfs by the user does not
correspond to the current port errors. This is not a hardware error, and could
even be a user error. Do you think a warning in the error log is needed here?

>
>>  }
>>
>>  static ssize_t errors_show(struct device *dev, struct device_attribute 
>> *attr,
>> diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
>> index 753cda4b2568..729eb306062e 100644
>> --- a/drivers/fpga/dfl-afu-main.c
>> +++ b/drivers/fpga/dfl-afu-main.c
>> @@ -21,6 +21,9 @@
>>
>>  #include "dfl-afu.h"
>>
>> +#define RST_POLL_INVL 10 /* us */
>> +#define RST_POLL_TIMEOUT 1000 /* us */
>> +
>>  /**
>>   * __afu_port_enable - enable a port by clear reset
>>   * @pdev: port platform device.
>> @@ -32,7 +35,7 @@
>>   *
>>   * The caller needs to hold lock for protection.
>>   */
>> -void __afu_port_enable(struct platform_device *pdev)
>> +int __afu_port_enable(struct platform_device *pdev)
>>  {
>>  struct dfl_feature_platform_data *pdata = dev_get_platdata(
>>> dev);
>>  void __iomem *base;
>> @@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
>>  WARN_ON(!pdata->disable_count);
>>
>>  if (--pdata->disable_count != 0)
>> -return;
>> +return 0;
>>
>>  base = dfl_get_feature_ioaddr_by_id(>dev,
>> PORT_FEATURE_ID_HEADER);
>>
>> @@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
>>  v = readq(base + PORT_HDR_CTRL);
>>  v &= ~PORT_CTRL_SFTRST;
>>  writeq(v, base + PORT_HDR_CTRL);
>> -}
>>
>> -#define RST_POLL_INVL 10 /* us */
>> -#define RST_POLL_TIMEOUT 1000 /* us */
>> +/*
>> + * HW clears the ack bit to indicate that the port is fully out
>> + * of reset.
>> + */
>> +if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
>> +   !(v & PORT_CTRL_SFTRST_ACK),
>> +   RST_POLL_INVL, RST_POLL_TIMEOUT)) {
>> +dev_err(>dev, "timeout, failure to enable device\n");
> Maybe we can change dev_err message in port disable to "disable device" as 
> well. : )
Thank you. I'll submit a new version of the patch with this fix.

- Russ
>
> Hao
>
>> +return -ETIMEDOUT;
>> +}
>> +
>> +return 0;
>> +}
>>
>>  /**
>>   * __afu_port_disable - disable a port by hold reset
>> @@ -111,9 +124,9 @@ static int __port_reset(struct platform_device *pdev)
>>
>>  r

Re: [PATCH v2 1/1] fpga: dfl: afu: harden port enable logic

2021-02-03 Thread Russ Weight



On 2/3/21 1:28 AM, Wu, Hao wrote:
>> Subject: Re: [PATCH v2 1/1] fpga: dfl: afu: harden port enable logic
>>
>> Sorry for the delay on this patch. It seemed like a lower priority patch than
>> others, since we haven't seen any issues with current products. Please my
>> responses inline.
>>
>> On 9/17/20 7:08 PM, Wu, Hao wrote:
>>>> -Original Message-
>>>> From: Russ Weight 
>>>> Sent: Friday, September 18, 2020 2:32 AM
>>>> To: m...@kernel.org; linux-f...@vger.kernel.org; linux-
>>>> ker...@vger.kernel.org
>>>> Cc: t...@redhat.com; lgonc...@redhat.com; Xu, Yilun ;
>>>> Wu, Hao ; Gerlach, Matthew
>>>> ; Weight, Russell H
>>>> 
>>>> Subject: [PATCH v2 1/1] fpga: dfl: afu: harden port enable logic
>>>>
>>>> Port enable is not complete until ACK = 0. Change
>>>> __afu_port_enable() to guarantee that the enable process
>>>> is complete by polling for ACK == 0.
>>> The description of this port reset ack bit is
>>>
>>> " After initiating a Port soft reset, SW should monitor this bit. HW
>>> will set this bit when all outstanding requests initiated by this port
>>> have been drained, and the minimum soft reset pulse width has
>>> elapsed. "
>>>
>>> But no description about what to do when clearing a Port soft reset
>>> to enable the port.
>>>
>>> So we need to understand clearly on why we need this change
>>> (e.g. what may happen without this change), and will it apply for all
>>> existing DFL devices and future ones, or just for one specific card.
>>> Could you please help? : )
>> I touched bases with the hardware engineers. The recommendation to wait
>> for ACK to be cleared is new with OFS and is documented in the latest
>> OFS specification as follows (see step #4):
>>
>>> 3.7.1 AFU Soft Resets
>>> Software may cause a soft reset to be issued to the AFU as follows:
>>> 1. Assert the PortSoftReset field of the PORT_CONTROL register
>>> 2. Wait for the Port to acknowledge the soft reset by monitoring the
>>> PortSoftResetAck field of the PORT_CONTROL register, i.e.
>> PortSoftResetAck=1
>>> 3. Deasserting the PortSoftReset field
>>> 4. Wait for the Port to acknowledge the soft reset de-assertion by 
>>> monitoring
>> the
>>> PortSoftResetAck field of the PORT_CONTROL register, i.e.
>> PortSoftResetAck=0
>>> This sequence ensures that outstanding transactions are suitably flushed and
>>> that the FIM minimum reset pulse width is respected. Failing to follow this
>>> sequence leaves the AFU in an undefined state.
>> The OFS specification has not been posted publicly, yet.
>>
>> Also, this is how it was explained to me:
>>
>>> In most scenario, port will be able to get out of reset soon enough
>>> when SW releases the port reset, especially on all the PAC products
>>> which have been verified before release.
>>>
>>> Polling for HW to clear the ACK is meant to handle the following scenarios:
>>>
>>>   * Different platform can take variable period of time to get out of reset
>>>   * Bug in the HW that hold the port in reset
>> So this change is not required for the currently released PAC cards,
>> but it is needed for OFS based products. I don't think there is any reason
>> to hold off on the patch, as it is still valid for current products.
> As you know, this driver is used for different cards, and we need to make
> sure new changes introduced in new version spec, don't break old products
> as we are sharing the same driver. and we are not sure if in the future some
> new products but still uses old specs, and then things may be broken if the
> driver which always perform new flow. Another method is that introduce 1
> bit in hardware register to tell the driver to perform the additional steps,
> then it can avoid impacts to the old products. If this can't be done, then
> we at least need to verify this change on all existing hardware and suggest
> users to follow new spec only.

According to the HW engineers, the RTL implementation has not changed; it is
the same as the RTL in the current PAC products. Polling for HW to clear the
ACK is something we could have (should have?) been doing all along. The timing
hasn't been an issue for the current PAC products, as proven by our testing.
However, with OFS we cannot anticipate what the timing will be for customer
designed products, so the specification is calling out this requirement as a
precaution.

I am using a development machine that has the older PAC devices installed. I
cleared port errors on these cards as a quick check, and the reset completes
without hanging - which indicates that the ACK bit is in fact getting cleared.
So there is not need for any device-specific conditional statements here.

- Russ

>
> Hao



[PATCH v3 1/1] fpga: dfl: afu: harden port enable logic

2021-02-02 Thread Russ Weight
Port enable is not complete until ACK = 0. Change
__afu_port_enable() to guarantee that the enable process
is complete by polling for ACK == 0.

Signed-off-by: Russ Weight 
---
v3:
  - afu_port_err_clear() changed to prioritize port_enable failure over
other a detected mismatch in port errors.
  - reorganized code in port_reset() to be more readable.
v2:
  - Fixed typo in commit message
---
 drivers/fpga/dfl-afu-error.c |  8 
 drivers/fpga/dfl-afu-main.c  | 31 ++-
 drivers/fpga/dfl-afu.h   |  2 +-
 3 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
index c4691187cca9..2ced610059cc 100644
--- a/drivers/fpga/dfl-afu-error.c
+++ b/drivers/fpga/dfl-afu-error.c
@@ -52,7 +52,7 @@ static int afu_port_err_clear(struct device *dev, u64 err)
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
struct platform_device *pdev = to_platform_device(dev);
void __iomem *base_err, *base_hdr;
-   int ret = -EBUSY;
+   int enable_ret = 0, ret = -EBUSY;
u64 v;
 
base_err = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_ERROR);
@@ -102,12 +102,12 @@ static int afu_port_err_clear(struct device *dev, u64 err)
/* Clear mask */
__afu_port_err_mask(dev, false);
 
-   /* Enable the Port by clear the reset */
-   __afu_port_enable(pdev);
+   /* Enable the Port by clearing the reset */
+   enable_ret = __afu_port_enable(pdev);
 
 done:
mutex_unlock(>lock);
-   return ret;
+   return enable_ret ? enable_ret : ret;
 }
 
 static ssize_t errors_show(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 753cda4b2568..729eb306062e 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -21,6 +21,9 @@
 
 #include "dfl-afu.h"
 
+#define RST_POLL_INVL 10 /* us */
+#define RST_POLL_TIMEOUT 1000 /* us */
+
 /**
  * __afu_port_enable - enable a port by clear reset
  * @pdev: port platform device.
@@ -32,7 +35,7 @@
  *
  * The caller needs to hold lock for protection.
  */
-void __afu_port_enable(struct platform_device *pdev)
+int __afu_port_enable(struct platform_device *pdev)
 {
struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
void __iomem *base;
@@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
WARN_ON(!pdata->disable_count);
 
if (--pdata->disable_count != 0)
-   return;
+   return 0;
 
base = dfl_get_feature_ioaddr_by_id(>dev, PORT_FEATURE_ID_HEADER);
 
@@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
v = readq(base + PORT_HDR_CTRL);
v &= ~PORT_CTRL_SFTRST;
writeq(v, base + PORT_HDR_CTRL);
-}
 
-#define RST_POLL_INVL 10 /* us */
-#define RST_POLL_TIMEOUT 1000 /* us */
+   /*
+* HW clears the ack bit to indicate that the port is fully out
+* of reset.
+*/
+   if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
+  !(v & PORT_CTRL_SFTRST_ACK),
+  RST_POLL_INVL, RST_POLL_TIMEOUT)) {
+   dev_err(>dev, "timeout, failure to enable device\n");
+   return -ETIMEDOUT;
+   }
+
+   return 0;
+}
 
 /**
  * __afu_port_disable - disable a port by hold reset
@@ -111,9 +124,9 @@ static int __port_reset(struct platform_device *pdev)
 
ret = __afu_port_disable(pdev);
if (!ret)
-   __afu_port_enable(pdev);
+   return ret;
 
-   return ret;
+   return __afu_port_enable(pdev);
 }
 
 static int port_reset(struct platform_device *pdev)
@@ -872,11 +885,11 @@ static int afu_dev_destroy(struct platform_device *pdev)
 static int port_enable_set(struct platform_device *pdev, bool enable)
 {
struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
-   int ret = 0;
+   int ret;
 
mutex_lock(>lock);
if (enable)
-   __afu_port_enable(pdev);
+   ret = __afu_port_enable(pdev);
else
ret = __afu_port_disable(pdev);
mutex_unlock(>lock);
diff --git a/drivers/fpga/dfl-afu.h b/drivers/fpga/dfl-afu.h
index 576e94960086..e5020e2b1f3d 100644
--- a/drivers/fpga/dfl-afu.h
+++ b/drivers/fpga/dfl-afu.h
@@ -80,7 +80,7 @@ struct dfl_afu {
 };
 
 /* hold pdata->lock when call __afu_port_enable/disable */
-void __afu_port_enable(struct platform_device *pdev);
+int __afu_port_enable(struct platform_device *pdev);
 int __afu_port_disable(struct platform_device *pdev);
 
 void afu_mmio_region_init(struct dfl_feature_platform_data *pdata);
-- 
2.25.1



Re: [PATCH v2 1/1] fpga: dfl: afu: harden port enable logic

2021-02-02 Thread Russ Weight



On 9/17/20 2:38 PM, Moritz Fischer wrote:
> On Thu, Sep 17, 2020 at 01:28:22PM -0700, Tom Rix wrote:
>> On 9/17/20 11:32 AM, Russ Weight wrote:
>>> Port enable is not complete until ACK = 0. Change
>>> __afu_port_enable() to guarantee that the enable process
>>> is complete by polling for ACK == 0.
>>>
>>> Signed-off-by: Russ Weight 
> General note: Please keep a changelog if you send updated versions of a
> patch. This can be added here with an extra '---' + Text between Signed-off 
> and
> diffstat:
>
> --- 
> Changes from v1:
> - FOo
> - Bar
Yes - I'll do that on future patch updates. In this case v2 just fixed a typo
in the commit message, so the patch was essentially the same as v1.
>>> ---
>>>  drivers/fpga/dfl-afu-error.c |  2 +-
>>>  drivers/fpga/dfl-afu-main.c  | 29 +
>>>  drivers/fpga/dfl-afu.h   |  2 +-
>>>  3 files changed, 23 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
>>> index c4691187cca9..0806532a3e9f 100644
>>> --- a/drivers/fpga/dfl-afu-error.c
>>> +++ b/drivers/fpga/dfl-afu-error.c
>>> @@ -103,7 +103,7 @@ static int afu_port_err_clear(struct device *dev, u64 
>>> err)
>>> __afu_port_err_mask(dev, false);
>>>  
>> There is an earlier bit that sets ret = -EINVAL.
>>
>> This error will be lost or not handled well.
>>
>> Right now it doesn't seem to be handled.
> Ultimately you'd want to report *at least* one of them, the current code
> seems to continue and enable the port either case. Is that what it
> should be doing? 
>
> Is the timeout more severe than the invalid value? Do you want to print
> a warning?
>
> Either way a comment explaining why this is ok would be appreciated :)
Yes - I'll add a comment explaining how the errors arebeing prioritized.
I'll give priority to the timeout, asit is likely a HW failure.

>>> /* Enable the Port by clear the reset */
>>> -   __afu_port_enable(pdev);
>>> +   ret = __afu_port_enable(pdev);
>>>  
>>>  done:
>>> mutex_unlock(>lock);
>>> diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
>>> index 753cda4b2568..f73b06cdf13c 100644
>>> --- a/drivers/fpga/dfl-afu-main.c
>>> +++ b/drivers/fpga/dfl-afu-main.c
>>> @@ -21,6 +21,9 @@
>>>  
>>>  #include "dfl-afu.h"
>>>  
>>> +#define RST_POLL_INVL 10 /* us */
>>> +#define RST_POLL_TIMEOUT 1000 /* us */
>>> +
>>>  /**
>>>   * __afu_port_enable - enable a port by clear reset
>>>   * @pdev: port platform device.
>>> @@ -32,7 +35,7 @@
>>>   *
>>>   * The caller needs to hold lock for protection.
>>>   */
>>> -void __afu_port_enable(struct platform_device *pdev)
>>> +int __afu_port_enable(struct platform_device *pdev)
>>>  {
>>> struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
>>> void __iomem *base;
>>> @@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
>>> WARN_ON(!pdata->disable_count);
>>>  
>>> if (--pdata->disable_count != 0)
>>> -   return;
>>> +   return 0;
>> Is this really a success ? Maybe -EBUSY ?
> Seems like if it's severe enough for a warning you'd probably want to
> return an error.
As mentioned by Hao and Yilun, the disable_count is a reference count.The
WARN_ON() is checking for a different condition - an invalid reference count.
We should never call port_enable if the port is not disabled. Do you think a
comment is needed here?

Thanks,
- Russ

>>>  
>>> base = dfl_get_feature_ioaddr_by_id(>dev, PORT_FEATURE_ID_HEADER);
>>>  
>>> @@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
>>> v = readq(base + PORT_HDR_CTRL);
>>> v &= ~PORT_CTRL_SFTRST;
>>> writeq(v, base + PORT_HDR_CTRL);
>>> -}
>>>  
>>> -#define RST_POLL_INVL 10 /* us */
>>> -#define RST_POLL_TIMEOUT 1000 /* us */
>>> +   /*
>>> +* HW clears the ack bit to indicate that the port is fully out
>>> +* of reset.
>>> +*/
>>> +   if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
>>> +  !(v & PORT_CTRL_SFTRST_ACK),
>>> +  RST_POLL_INVL, RST_POLL_TIMEOUT)) {
>>> +   dev_err(>dev, "timeout, failure to enable device\n");
>>> +   re

Re: [PATCH v2 1/1] fpga: dfl: afu: harden port enable logic

2021-02-02 Thread Russ Weight



On 2/2/21 12:32 PM, Russ Weight wrote:
>
> On 9/17/20 1:28 PM, Tom Rix wrote:
>> On 9/17/20 11:32 AM, Russ Weight wrote:
>>> Port enable is not complete until ACK = 0. Change
>>> __afu_port_enable() to guarantee that the enable process
>>> is complete by polling for ACK == 0.
>>>
>>> Signed-off-by: Russ Weight 
>>> ---
>>>  drivers/fpga/dfl-afu-error.c |  2 +-
>>>  drivers/fpga/dfl-afu-main.c  | 29 +
>>>  drivers/fpga/dfl-afu.h   |  2 +-
>>>  3 files changed, 23 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
>>> index c4691187cca9..0806532a3e9f 100644
>>> --- a/drivers/fpga/dfl-afu-error.c
>>> +++ b/drivers/fpga/dfl-afu-error.c
>>> @@ -103,7 +103,7 @@ static int afu_port_err_clear(struct device *dev, u64 
>>> err)
>>> __afu_port_err_mask(dev, false);
>>>  
>> There is an earlier bit that sets ret = -EINVAL.
>>
>> This error will be lost or not handled well.
>>
>> Right now it doesn't seem to be handled.
> Good catch. I'll give priority to -EINVAL in the next version of the
> patch, as it is more informative in the context of this function.
Actually - Hao pointed out in his response that the falure to re-enable the port
is a more serious error, so the code flow OK, but needs a comment.

- Russ
>>> /* Enable the Port by clear the reset */
>>> -   __afu_port_enable(pdev);
>>> +   ret = __afu_port_enable(pdev);
>>>  
>>>  done:
>>> mutex_unlock(>lock);
>>> diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
>>> index 753cda4b2568..f73b06cdf13c 100644
>>> --- a/drivers/fpga/dfl-afu-main.c
>>> +++ b/drivers/fpga/dfl-afu-main.c
>>> @@ -21,6 +21,9 @@
>>>  
>>>  #include "dfl-afu.h"
>>>  
>>> +#define RST_POLL_INVL 10 /* us */
>>> +#define RST_POLL_TIMEOUT 1000 /* us */
>>> +
>>>  /**
>>>   * __afu_port_enable - enable a port by clear reset
>>>   * @pdev: port platform device.
>>> @@ -32,7 +35,7 @@
>>>   *
>>>   * The caller needs to hold lock for protection.
>>>   */
>>> -void __afu_port_enable(struct platform_device *pdev)
>>> +int __afu_port_enable(struct platform_device *pdev)
>>>  {
>>> struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
>>> void __iomem *base;
>>> @@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
>>> WARN_ON(!pdata->disable_count);
>>>  
>>> if (--pdata->disable_count != 0)
>>> -   return;
>>> +   return 0;
>> Is this really a success ? Maybe -EBUSY ?
> Yilun addressed this question in his previous response. This isessentially a
> reference count for nested disable calls. Weonly do the enable if the
> disable count has gone to zero, so this isn't an error condition.
>>>  
>>> base = dfl_get_feature_ioaddr_by_id(>dev, PORT_FEATURE_ID_HEADER);
>>>  
>>> @@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
>>> v = readq(base + PORT_HDR_CTRL);
>>> v &= ~PORT_CTRL_SFTRST;
>>> writeq(v, base + PORT_HDR_CTRL);
>>> -}
>>>  
>>> -#define RST_POLL_INVL 10 /* us */
>>> -#define RST_POLL_TIMEOUT 1000 /* us */
>>> +   /*
>>> +* HW clears the ack bit to indicate that the port is fully out
>>> +* of reset.
>>> +*/
>>> +   if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
>>> +  !(v & PORT_CTRL_SFTRST_ACK),
>>> +  RST_POLL_INVL, RST_POLL_TIMEOUT)) {
>>> +   dev_err(>dev, "timeout, failure to enable device\n");
>>> +   return -ETIMEDOUT;
>>> +   }
>>> +
>>> +   return 0;
>>> +}
>>>  
>>>  /**
>>>   * __afu_port_disable - disable a port by hold reset
>>> @@ -111,7 +124,7 @@ static int __port_reset(struct platform_device *pdev)
>>>  
>>> ret = __afu_port_disable(pdev);
>>> if (!ret)
>>> -   __afu_port_enable(pdev);
>>> +   ret = __afu_port_enable(pdev);
>>>  
>>> return ret;
>>>  }
>>> @@ -872,11 +885,11 @@ static int afu_dev_destroy(struct platform_device 
>>> *pdev)
>>>  static int port_enable_set(struct platform_device *pdev, bool enable)
>>

Re: [PATCH v2 1/1] fpga: dfl: afu: harden port enable logic

2021-02-02 Thread Russ Weight



On 9/17/20 1:28 PM, Tom Rix wrote:
> On 9/17/20 11:32 AM, Russ Weight wrote:
>> Port enable is not complete until ACK = 0. Change
>> __afu_port_enable() to guarantee that the enable process
>> is complete by polling for ACK == 0.
>>
>> Signed-off-by: Russ Weight 
>> ---
>>  drivers/fpga/dfl-afu-error.c |  2 +-
>>  drivers/fpga/dfl-afu-main.c  | 29 +
>>  drivers/fpga/dfl-afu.h   |  2 +-
>>  3 files changed, 23 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
>> index c4691187cca9..0806532a3e9f 100644
>> --- a/drivers/fpga/dfl-afu-error.c
>> +++ b/drivers/fpga/dfl-afu-error.c
>> @@ -103,7 +103,7 @@ static int afu_port_err_clear(struct device *dev, u64 
>> err)
>>  __afu_port_err_mask(dev, false);
>>  
> There is an earlier bit that sets ret = -EINVAL.
>
> This error will be lost or not handled well.
>
> Right now it doesn't seem to be handled.
Good catch. I'll give priority to -EINVAL in the next version of the
patch, as it is more informative in the context of this function.
>
>>  /* Enable the Port by clear the reset */
>> -__afu_port_enable(pdev);
>> +ret = __afu_port_enable(pdev);
>>  
>>  done:
>>  mutex_unlock(>lock);
>> diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
>> index 753cda4b2568..f73b06cdf13c 100644
>> --- a/drivers/fpga/dfl-afu-main.c
>> +++ b/drivers/fpga/dfl-afu-main.c
>> @@ -21,6 +21,9 @@
>>  
>>  #include "dfl-afu.h"
>>  
>> +#define RST_POLL_INVL 10 /* us */
>> +#define RST_POLL_TIMEOUT 1000 /* us */
>> +
>>  /**
>>   * __afu_port_enable - enable a port by clear reset
>>   * @pdev: port platform device.
>> @@ -32,7 +35,7 @@
>>   *
>>   * The caller needs to hold lock for protection.
>>   */
>> -void __afu_port_enable(struct platform_device *pdev)
>> +int __afu_port_enable(struct platform_device *pdev)
>>  {
>>  struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
>>  void __iomem *base;
>> @@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
>>  WARN_ON(!pdata->disable_count);
>>  
>>  if (--pdata->disable_count != 0)
>> -return;
>> +return 0;
> Is this really a success ? Maybe -EBUSY ?
Yilun addressed this question in his previous response. This isessentially a
reference count for nested disable calls. Weonly do the enable if the
disable count has gone to zero, so this isn't an error condition.
>>  
>>  base = dfl_get_feature_ioaddr_by_id(>dev, PORT_FEATURE_ID_HEADER);
>>  
>> @@ -49,10 +52,20 @@ void __afu_port_enable(struct platform_device *pdev)
>>  v = readq(base + PORT_HDR_CTRL);
>>  v &= ~PORT_CTRL_SFTRST;
>>  writeq(v, base + PORT_HDR_CTRL);
>> -}
>>  
>> -#define RST_POLL_INVL 10 /* us */
>> -#define RST_POLL_TIMEOUT 1000 /* us */
>> +/*
>> + * HW clears the ack bit to indicate that the port is fully out
>> + * of reset.
>> + */
>> +if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
>> +   !(v & PORT_CTRL_SFTRST_ACK),
>> +   RST_POLL_INVL, RST_POLL_TIMEOUT)) {
>> +dev_err(>dev, "timeout, failure to enable device\n");
>> +return -ETIMEDOUT;
>> +}
>> +
>> +return 0;
>> +}
>>  
>>  /**
>>   * __afu_port_disable - disable a port by hold reset
>> @@ -111,7 +124,7 @@ static int __port_reset(struct platform_device *pdev)
>>  
>>  ret = __afu_port_disable(pdev);
>>  if (!ret)
>> -__afu_port_enable(pdev);
>> +ret = __afu_port_enable(pdev);
>>  
>>  return ret;
>>  }
>> @@ -872,11 +885,11 @@ static int afu_dev_destroy(struct platform_device 
>> *pdev)
>>  static int port_enable_set(struct platform_device *pdev, bool enable)
>>  {
>>  struct dfl_feature_platform_data *pdata = dev_get_platdata(>dev);
>> -int ret = 0;
>> +int ret;
>>  
>>  mutex_lock(>lock);
>>  if (enable)
>> -__afu_port_enable(pdev);
>> +ret = __afu_port_enable(pdev);
>>  else
>>  ret = __afu_port_disable(pdev);
>>  mutex_unlock(>lock);
>> diff --git a/drivers/fpga/dfl-afu.h b/drivers/fpga/dfl-afu.h
>> index 576e94960086..e5020e2b1f3d 100644
>> --- a/drivers/fpga/dfl-afu.h
>> +++ b/dr

Re: [PATCH v2 1/1] fpga: dfl: afu: harden port enable logic

2021-02-02 Thread Russ Weight
Sorry for the delay on this patch. It seemed like a lower priority patch than
others, since we haven't seen any issues with current products. Please my
responses inline.

On 9/17/20 7:08 PM, Wu, Hao wrote:
>> -Original Message-
>> From: Russ Weight 
>> Sent: Friday, September 18, 2020 2:32 AM
>> To: m...@kernel.org; linux-f...@vger.kernel.org; linux-
>> ker...@vger.kernel.org
>> Cc: t...@redhat.com; lgonc...@redhat.com; Xu, Yilun ;
>> Wu, Hao ; Gerlach, Matthew
>> ; Weight, Russell H
>> 
>> Subject: [PATCH v2 1/1] fpga: dfl: afu: harden port enable logic
>>
>> Port enable is not complete until ACK = 0. Change
>> __afu_port_enable() to guarantee that the enable process
>> is complete by polling for ACK == 0.
> The description of this port reset ack bit is
>
> " After initiating a Port soft reset, SW should monitor this bit. HW
> will set this bit when all outstanding requests initiated by this port
> have been drained, and the minimum soft reset pulse width has
> elapsed. "
>
> But no description about what to do when clearing a Port soft reset
> to enable the port.
>
> So we need to understand clearly on why we need this change
> (e.g. what may happen without this change), and will it apply for all
> existing DFL devices and future ones, or just for one specific card.
> Could you please help? : )
I touched bases with the hardware engineers. The recommendation to wait
for ACK to be cleared is new with OFS and is documented in the latest
OFS specification as follows (see step #4):

> 3.7.1 AFU Soft Resets
> Software may cause a soft reset to be issued to the AFU as follows:
> 1. Assert the PortSoftReset field of the PORT_CONTROL register
> 2. Wait for the Port to acknowledge the soft reset by monitoring the
> PortSoftResetAck field of the PORT_CONTROL register, i.e. PortSoftResetAck=1
> 3. Deasserting the PortSoftReset field
> 4. Wait for the Port to acknowledge the soft reset de-assertion by monitoring 
> the
> PortSoftResetAck field of the PORT_CONTROL register, i.e. PortSoftResetAck=0
>
> This sequence ensures that outstanding transactions are suitably flushed and
> that the FIM minimum reset pulse width is respected. Failing to follow this 
> sequence leaves the AFU in an undefined state.

The OFS specification has not been posted publicly, yet.

Also, this is how it was explained to me:

> In most scenario, port will be able to get out of reset soon enough
> when SW releases the port reset, especially on all the PAC products
> which have been verified before release.
>
> Polling for HW to clear the ACK is meant to handle the following scenarios:
>
>   * Different platform can take variable period of time to get out of reset
>   * Bug in the HW that hold the port in reset

So this change is not required for the currently released PAC cards,
but it is needed for OFS based products. I don't think there is any reason
to hold off on the patch, as it is still valid for current products.

>> Signed-off-by: Russ Weight 
>> ---
>>  drivers/fpga/dfl-afu-error.c |  2 +-
>>  drivers/fpga/dfl-afu-main.c  | 29 +
>>  drivers/fpga/dfl-afu.h   |  2 +-
>>  3 files changed, 23 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/fpga/dfl-afu-error.c b/drivers/fpga/dfl-afu-error.c
>> index c4691187cca9..0806532a3e9f 100644
>> --- a/drivers/fpga/dfl-afu-error.c
>> +++ b/drivers/fpga/dfl-afu-error.c
>> @@ -103,7 +103,7 @@ static int afu_port_err_clear(struct device *dev, u64
>> err)
>>  __afu_port_err_mask(dev, false);
>>
>>  /* Enable the Port by clear the reset */
>> -__afu_port_enable(pdev);
>> +ret = __afu_port_enable(pdev);
>>
>>  done:
>>  mutex_unlock(>lock);
>> diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
>> index 753cda4b2568..f73b06cdf13c 100644
>> --- a/drivers/fpga/dfl-afu-main.c
>> +++ b/drivers/fpga/dfl-afu-main.c
>> @@ -21,6 +21,9 @@
>>
>>  #include "dfl-afu.h"
>>
>> +#define RST_POLL_INVL 10 /* us */
>> +#define RST_POLL_TIMEOUT 1000 /* us */
>> +
>>  /**
>>   * __afu_port_enable - enable a port by clear reset
>>   * @pdev: port platform device.
>> @@ -32,7 +35,7 @@
>>   *
>>   * The caller needs to hold lock for protection.
>>   */
>> -void __afu_port_enable(struct platform_device *pdev)
>> +int __afu_port_enable(struct platform_device *pdev)
>>  {
>>  struct dfl_feature_platform_data *pdata = dev_get_platdata(
>>> dev);
>>  void __iomem *base;
>> @@ -41,7 +44,7 @@ void __afu_port_enable(struct platform_device *pdev)
>>  WARN_ON(!pdata->disable

Re: [PATCH v8 0/5] Intel MAX10 BMC Secure Update Driver

2021-01-21 Thread Russ Weight



On 1/21/21 3:29 PM, Russ Weight wrote:
> The Intel MAX10 BMC Secure Update driver instantiates the FPGA
> Security Manager class driver and provides the callback functions
> required to support secure updates on Intel n3000 PAC devices.
> This driver is implemented as a sub-driver of the Intel MAX10 BMC
> mfd driver. Future instances of the MAX10 BMC will support other
> devices as well (e.g. d5005) and this same MAX10 BMC Secure
> Update driver will receive modifications to support that device.
>
> This driver interacts with the HW secure update engine of the
> BMC in order to transfer new FPGA and BMC images to FLASH so
> that they will be automatically loaded when the FPGA card reboots.
> Security is enforced by hardware and firmware. The MAX10 BMC
> Secure Update driver interacts with the firmware to initiate
> an update, pass in the necessary data, and collect status on
> the update.
>
> This driver provides sysfs files for displaying the flash count,
> the root entry hashes (REH), and the code-signing-key (CSK)
> cancellation vectors.
>
> These patches are dependent on other patches that are under
> review. If you want to apply and compile these patches on
> linux-next, please apply these patches first:
One more prerequisite patch. Apply this one first:

https://marc.info/?l=linux-kernel=161066634118704=2

> (1 patch)   https://marc.info/?l=linux-kernel=161126987101096=2
> (7 patches) https://marc.info/?l=linux-fpga=160988774201859=2
>
> Changelog v7 -> v8:
>   - Spit out patch "mfd: intel-m10-bmc: support for MAX10 BMC Secure
> Updates" and submitted it separately:
> https://marc.info/?l=linux-kernel=161126987101096=2
>
> Changelog v6 -> v7:
>   - Rebased patches for 5.11-rc2
>   - Updated Date and KernelVersion in ABI documentation
>
> Changelog v5 -> v6:
>   - Added WARN_ON() prior to several calls to regmap_bulk_read()
> to assert that the (SIZE / stride) calculations did not result
> in remainders.
>   - Changed the (size / stride) calculation in regmap_bulk_write()
> call to ensure that we don't write one less than intended.
>   - Changed flash_count_show() parameter list to achieve
> reverse-christmas tree format.
>   - Removed unnecessary call to rsu_check_complete() in
> m10bmc_sec_poll_complete() and changed while loop to
> do/while loop.
>   - Initialized auth_result and doorbell to HW_ERRINFO_POISON
> in m10bmc_sec_hw_errinfo() and removed unnecessary if statements.
>
> Changelog v4 -> v5:
>   - Renamed sysfs node user_flash_count to flash_count and updated
> the sysfs documentation accordingly to more accurately descirbe
> the purpose of the count.
>
> Changelog v3 -> v4:
>   - Moved sysfs files for displaying the flash count, the root
> entry hashes (REH), and the code-signing-key (CSK) cancellation
> vectors from the FPGA Security Manager class driver to this
> driver (as they are not generic enough for the class driver).
>   - Added a new ABI documentation file with informtaion about the
> new sysfs entries: sysfs-driver-intel-m10-bmc-secure
>   - Updated the MAINTAINERS file to add the new ABI documentation
> file: sysfs-driver-intel-m10-bmc-secure
>   - Removed unnecessary ret variable from m10bmc_secure_probe()
>   - Incorporated new devm_fpga_sec_mgr_register() function into
> m10bmc_secure_probe() and removed the m10bmc_secure_remove()
> function.
>
> Changelog v2 -> v3:
>   - Changed "MAX10 BMC Security Engine driver" to "MAX10 BMC Secure
> Update driver"
>   - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
>   - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
>   - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
> underlying functions are now called directly.
>   - Changed "_root_entry_hash" to "_reh", with a comment explaining
> what reh is.
>   - Renamed get_csk_vector() to m10bmc_csk_vector()
>   - Changed calling functions of functions that return "enum fpga_sec_err"
> to check for (ret != FPGA_SEC_ERR_NONE) instead of (ret)
>
> Changelog v1 -> v2:
>   - These patches were previously submitted as part of a larger V1
> patch set under the title "Intel FPGA Security Manager Class Driver".
>   - Grouped all changes to include/linux/mfd/intel-m10-bmc.h into a
> single patch: "mfd: intel-m10-bmc: support for MAX10 BMC Security
> Engine".
>   - Removed ifpga_sec_mgr_init() and ifpga_sec_mgr_uinit() functions.
>   - Adapted to changes in the Intel FPGA Security Manager by splitting
> the single call to ifpga_sec_mgr_reg

Re: [PATCH v8 0/1] Intel MAX10 BMC Macros for Secure Update

2021-01-21 Thread Russ Weight



On 1/21/21 2:55 PM, Russ Weight wrote:
> This patch was previously patch 1 of 6 in the patch-series entitled
> "Intel MAX10 BMC Secure Update Driver". This is the only patch in
> the series that is subject to conflicts with other ongoing changes
> and is separated here to simplify maintenance of the patchset.
>
> This patch creates a number of macro definitions that are required
> for the Intel MAX10 BMC Secure Update Driver.

Please apply this patch first. It was previously accepted but has not
landed in linux-next yet.
https://marc.info/?l=linux-kernel=161066634118704=2
>
> Changelog v7 -> v8:
>   - Rebased on next-20210121
>   - Separated out from patchset: "Intel MAX10 BMC Secure Update Driver"
> Changelog v6 -> v7:
>   - No change
> Changelog v5 -> v6:
>   - No change
> Changelog v4 -> v5:
>   - Renamed USER_FLASH_COUNT to STAGING_FLASH_COUNT
> Changelog v3 -> v4:
>   - No change
> Changelog v2 -> v3:
>   - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure
> Update driver"
>   - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
> underlying functions will be called directly.
> Changelog v1 -> v2:
>   - These functions and macros were previously distributed among
> the patches that needed them. They are now grouped together
> in a single patch containing changes to the Intel MAX10 BMC
> driver.
>   - Added DRBL_ prefix to some definitions
>   - Some address definitions were moved here from the .c files that
> use them.
>
> Russ Weight (1):
>   mfd: intel-m10-bmc: support for MAX10 BMC Secure Updates
>
>  include/linux/mfd/intel-m10-bmc.h | 85 +++
>  1 file changed, 85 insertions(+)
>



[PATCH v8 4/5] fpga: m10bmc-sec: add max10 secure update functions

2021-01-21 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to include
the functions that enable secure updates of BMC images,
FPGA images, etc.

Signed-off-by: Russ Weight 
---
v8:
  - Previously patch 5/6, otherwise no change
v7:
  - No change
v6:
  - Changed (size / stride) calculation to ((size + stride - 1) / stride)
to ensure that the proper count is passed to regmap_bulk_write().
  - Removed unnecessary call to rsu_check_complete() in
m10bmc_sec_poll_complete() and changed while loop to
do/while loop.
v5:
  - No change
v4:
  - No change
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed calling functions of functions that return "enum fpga_sec_err"
to check for (ret != FPGA_SEC_ERR_NONE) instead of (ret)
v2:
  - Reworked the rsu_start_done() function to make it more readable
  - Reworked while-loop condition/content in rsu_prog_ready()
  - Minor code cleanup per review comments
  - Added a comment to the m10bmc_sec_poll_complete() function to
explain the context (could take 30+ minutes to complete).
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
  - Moved MAX10 BMC address and function definitions to a separate
patch.
---
 drivers/fpga/intel-m10-bmc-secure.c | 303 +++-
 1 file changed, 302 insertions(+), 1 deletion(-)

diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index 87e16c146569..a290fcc4df4a 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -180,7 +180,308 @@ static const struct attribute_group 
*m10bmc_sec_attr_groups[] = {
NULL,
 };
 
-static const struct fpga_sec_mgr_ops m10bmc_sops = { };
+static void log_error_regs(struct m10bmc_sec *sec, u32 doorbell)
+{
+   u32 auth_result;
+
+   dev_err(sec->dev, "RSU error status: 0x%08x\n", doorbell);
+
+   if (!m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, _result))
+   dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result);
+}
+
+static enum fpga_sec_err rsu_check_idle(struct m10bmc_sec *sec)
+{
+   u32 doorbell;
+   int ret;
+
+   ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, );
+   if (ret)
+   return FPGA_SEC_ERR_RW_ERROR;
+
+   if (rsu_prog(doorbell) != RSU_PROG_IDLE &&
+   rsu_prog(doorbell) != RSU_PROG_RSU_DONE) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_BUSY;
+   }
+
+   return FPGA_SEC_ERR_NONE;
+}
+
+static inline bool rsu_start_done(u32 doorbell)
+{
+   u32 status, progress;
+
+   if (doorbell & DRBL_RSU_REQUEST)
+   return false;
+
+   status = rsu_stat(doorbell);
+   if (status == RSU_STAT_ERASE_FAIL || status == RSU_STAT_WEAROUT)
+   return true;
+
+   progress = rsu_prog(doorbell);
+   if (progress != RSU_PROG_IDLE && progress != RSU_PROG_RSU_DONE)
+   return true;
+
+   return false;
+}
+
+static enum fpga_sec_err rsu_update_init(struct m10bmc_sec *sec)
+{
+   u32 doorbell, status;
+   int ret;
+
+   ret = regmap_update_bits(sec->m10bmc->regmap,
+M10BMC_SYS_BASE + M10BMC_DOORBELL,
+DRBL_RSU_REQUEST | DRBL_HOST_STATUS,
+DRBL_RSU_REQUEST |
+FIELD_PREP(DRBL_HOST_STATUS,
+   HOST_STATUS_IDLE));
+   if (ret)
+   return FPGA_SEC_ERR_RW_ERROR;
+
+   ret = regmap_read_poll_timeout(sec->m10bmc->regmap,
+  M10BMC_SYS_BASE + M10BMC_DOORBELL,
+  doorbell,
+  rsu_start_done(doorbell),
+  NIOS_HANDSHAKE_INTERVAL_US,
+  NIOS_HANDSHAKE_TIMEOUT_US);
+
+   if (ret == -ETIMEDOUT) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_TIMEOUT;
+   } else if (ret) {
+   return FPGA_SEC_ERR_RW_ERROR;
+   }
+
+   status = rsu_stat(doorbell);
+   if (status == RSU_STAT_WEAROUT) {
+   dev_warn(sec->dev, "Excessive flash update count detected\n");
+   return FPGA_SEC_ERR_WEAROUT;
+   } else if (status == RSU_STAT_ERASE_FAIL) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_HW_ERROR;
+   }
+
+   return FPGA_SEC_ERR_NONE;
+}
+
+static enum fpga_sec_err rsu_prog_ready(struct m10bmc_sec *sec)
+{
+   unsigned long poll_timeout;
+   u32 doorbell, progress;
+

[PATCH v8 5/5] fpga: m10bmc-sec: add max10 get_hw_errinfo callback func

2021-01-21 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to include
a function that returns 64 bits of additional HW specific
data for errors that require additional information.
This callback function enables the hw_errinfo sysfs
node in the Intel Security Manager class driver.

Signed-off-by: Russ Weight 
---
v8:
  - Previously patch 6/6, otherwise no change
v7:
  - No change
v6:
  - Initialized auth_result and doorbell to HW_ERRINFO_POISON
in m10bmc_sec_hw_errinfo() and removed unnecessary if statements.
v5:
  - No change
v4:
  - No change
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
v2:
  - Implemented HW_ERRINFO_POISON for m10bmc_sec_hw_errinfo() to
ensure that corresponding bits are set to 1 if we are unable
to read the doorbell or auth_result registers.
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 drivers/fpga/intel-m10-bmc-secure.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index a290fcc4df4a..3a049c98cf43 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -476,11 +476,33 @@ static enum fpga_sec_err m10bmc_sec_cancel(struct 
fpga_sec_mgr *smgr)
return ret ? FPGA_SEC_ERR_RW_ERROR : FPGA_SEC_ERR_NONE;
 }
 
+#define HW_ERRINFO_POISON  GENMASK(31, 0)
+static u64 m10bmc_sec_hw_errinfo(struct fpga_sec_mgr *smgr)
+{
+   struct m10bmc_sec *sec = smgr->priv;
+   u32 auth_result = HW_ERRINFO_POISON;
+   u32 doorbell = HW_ERRINFO_POISON;
+
+   switch (smgr->err_code) {
+   case FPGA_SEC_ERR_HW_ERROR:
+   case FPGA_SEC_ERR_TIMEOUT:
+   case FPGA_SEC_ERR_BUSY:
+   case FPGA_SEC_ERR_WEAROUT:
+   m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, );
+   m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, _result);
+
+   return (u64)doorbell << 32 | (u64)auth_result;
+   default:
+   return 0;
+   }
+}
+
 static const struct fpga_sec_mgr_ops m10bmc_sops = {
.prepare = m10bmc_sec_prepare,
.write_blk = m10bmc_sec_write_blk,
.poll_complete = m10bmc_sec_poll_complete,
.cancel = m10bmc_sec_cancel,
+   .get_hw_errinfo = m10bmc_sec_hw_errinfo,
 };
 
 static int m10bmc_secure_probe(struct platform_device *pdev)
-- 
2.25.1



[PATCH v8 3/5] fpga: m10bmc-sec: expose max10 canceled keys in sysfs

2021-01-21 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to provide sysfs
files to expose the canceled code signing key (CSK) bit
vectors. These use the standard bitmap list format
(e.g. 1,2-6,9).

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v8:
  - Previously patch 4/6, otherwise no change
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Added WARN_ON() call for (size / stride) to ensure
that the proper count is passed to regmap_bulk_read().
v5:
  - No change
v4:
  - Moved sysfs files for displaying the code-signing-key (CSK)
cancellation vectors from the FPGA Security Manger class driver
to here. The m10bmc_csk_vector() and m10bmc_csk_cancel_nbits()
functions are removed and the functionality from these functions
is moved into a show_canceled_csk() function for for displaying
the CSK vectors.
  - Added ABI documentation for new sysfs entries
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Renamed get_csk_vector() to m10bmc_csk_vector()
v2:
  - Replaced small function-creation macros for explicit function
declarations.
  - Fixed get_csk_vector() function to properly apply the stride
variable in calls to m10bmc_raw_bulk_read()
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 .../testing/sysfs-driver-intel-m10-bmc-secure | 24 ++
 drivers/fpga/intel-m10-bmc-secure.c   | 48 +++
 2 files changed, 72 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
index 7300038d07c3..27890a9ba355 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -28,6 +28,30 @@ Description: Read only. Returns the root entry hash for the 
BMC image
underlying device supports it.
Format: "0x%x".
 
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/sr_canceled_csks
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the static region. The standard bitmap
+   list format is used (e.g. "1,2-6,9").
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/pr_canceled_csks
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the partial reconfiguration region. The
+   standard bitmap list format is used (e.g. "1,2-6,9").
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/bmc_canceled_csks
+Date:      January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the BMC.  The standard bitmap list format
+   is used (e.g. "1,2-6,9").
+
 What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/flash_count
 Date:  January 2021
 KernelVersion:  5.12
diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index ecd63c13cb2d..87e16c146569 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -79,6 +79,51 @@ DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, 
BMC_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
 
+#define CSK_BIT_LEN128U
+#define CSK_32ARRAY_SIZE   DIV_ROUND_UP(CSK_BIT_LEN, 32)
+
+static ssize_t
+show_canceled_csk(struct device *dev, u32 addr, char *buf)
+{
+   unsigned int i, stride, size = CSK_32ARRAY_SIZE * sizeof(u32);
+   struct m10bmc_sec *sec = dev_get_drvdata(dev);
+   DECLARE_BITMAP(csk_map, CSK_BIT_LEN);
+   __le32 csk_le32[CSK_32ARRAY_SIZE];
+   u32 csk32[CSK_32ARRAY_SIZE];
+   int ret;
+
+   stride = regmap_get_reg_stride(sec->m10bmc->regmap);
+
+   WARN_ON(size % stride);
+   ret = regmap_bulk_read(sec->m10bmc->regmap, addr, csk_le32,
+  size / stride);
+   if (ret) {
+   dev_err(sec->dev, "failed to read CSK vector: %x cnt %x: %d\n",
+   addr, size / stride, ret);
+   return ret;
+   }
+
+   for (i = 0; i < CSK_32ARRAY_SIZE; i++)
+   csk32[i] = le32_to_cpu(((csk_le32[i])));
+
+   bitmap_from_arr32(csk_map, csk32, CSK_BIT_LEN);
+   bitmap_complement(cs

[PATCH v8 2/5] fpga: m10bmc-sec: expose max10 flash update count

2021-01-21 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to provide a
sysfs file to expose the flash update count for the FPGA
user image.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v8:
  - Previously patch 3/6, otherwise no change
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Changed flash_count_show() parameter list to achieve
reverse-christmas tree format.
  - Added WARN_ON() call for (FLASH_COUNT_SIZE / stride) to ensure
that the proper count is passed to regmap_bulk_read().
v5:
  - Renamed sysfs node user_flash_count to flash_count and updated the
sysfs documentation accordingly.
v4:
  - Moved the sysfs file for displaying the flash count from the
FPGA Security Manager class driver to here. The
m10bmc_user_flash_count() function is removed and the
functionality is moved into a user_flash_count_show()
function.
  - Added ABI documentation for the new sysfs entry
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
v2:
  - Renamed get_qspi_flash_count() to m10bmc_user_flash_count()
  - Minor code cleanup per review comments
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 .../testing/sysfs-driver-intel-m10-bmc-secure |  8 
 drivers/fpga/intel-m10-bmc-secure.c   | 37 +++
 2 files changed, 45 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
index 296f809c447e..7300038d07c3 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -27,3 +27,11 @@ Description: Read only. Returns the root entry hash for the 
BMC image
"hash not programmed".  This file is only visible if the
underlying device supports it.
Format: "0x%x".
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/flash_count
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns number of times the secure update
+   staging area has been flashed.
+   Format: "%u".
diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index 5ac5f59b5731..ecd63c13cb2d 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct m10bmc_sec {
struct device *dev;
@@ -78,7 +79,43 @@ DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, 
BMC_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
 
+#define FLASH_COUNT_SIZE 4096  /* count stored as inverted bit vector */
+
+static ssize_t flash_count_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct m10bmc_sec *sec = dev_get_drvdata(dev);
+   unsigned int stride, num_bits;
+   u8 *flash_buf;
+   int cnt, ret;
+
+   stride = regmap_get_reg_stride(sec->m10bmc->regmap);
+   num_bits = FLASH_COUNT_SIZE * 8;
+
+   flash_buf = kmalloc(FLASH_COUNT_SIZE, GFP_KERNEL);
+   if (!flash_buf)
+   return -ENOMEM;
+
+   WARN_ON(FLASH_COUNT_SIZE % stride);
+   ret = regmap_bulk_read(sec->m10bmc->regmap, STAGING_FLASH_COUNT,
+  flash_buf, FLASH_COUNT_SIZE / stride);
+   if (ret) {
+   dev_err(sec->dev,
+   "failed to read flash count: %x cnt %x: %d\n",
+   STAGING_FLASH_COUNT, FLASH_COUNT_SIZE / stride, ret);
+   goto exit_free;
+   }
+   cnt = num_bits - bitmap_weight((unsigned long *)flash_buf, num_bits);
+
+exit_free:
+   kfree(flash_buf);
+
+   return ret ? : sysfs_emit(buf, "%u\n", cnt);
+}
+static DEVICE_ATTR_RO(flash_count);
+
 static struct attribute *m10bmc_security_attrs[] = {
+   _attr_flash_count.attr,
_attr_bmc_root_entry_hash.attr,
_attr_sr_root_entry_hash.attr,
_attr_pr_root_entry_hash.attr,
-- 
2.25.1



[PATCH v8 1/5] fpga: m10bmc-sec: create max10 bmc secure update driver

2021-01-21 Thread Russ Weight
Create a platform driver that can be invoked as a sub
driver for the Intel MAX10 BMC in order to support
secure updates. This sub-driver will invoke an
instance of the FPGA Security Manager class driver
in order to expose sysfs interfaces for managing and
monitoring secure updates to FPGA and BMC images.

This patch creates the MAX10 BMC Secure Update driver and
provides sysfs files for displaying the current root entry hashes
for the FPGA static region, the FPGA PR region, and the MAX10
BMC.

Signed-off-by: Russ Weight 
---
v8:
  - Previously patch 2/6, otherwise no change
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Added WARN_ON() call for (sha_num_bytes / stride) to assert
that the proper count is passed to regmap_bulk_read().
v5:
  - No change
v4:
  - Moved sysfs files for displaying the root entry hashes (REH)
from the FPGA Security Manager class driver to here. The
m10bmc_reh() and m10bmc_reh_size() functions are removed and
the functionality from these functions is moved into a
show_root_entry_hash() function for displaying the REHs.
  - Added ABI documentation for the new sysfs entries:
sysfs-driver-intel-m10-bmc-secure
  - Updated the MAINTAINERS file to add the new ABI documentation
file: sysfs-driver-intel-m10-bmc-secure
  - Removed unnecessary ret variable from m10bmc_secure_probe()
  - Incorporated new devm_fpga_sec_mgr_register() function into
m10bmc_secure_probe() and removed the m10bmc_secure_remove()
function.
v3:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure
Update driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed "_root_entry_hash" to "_reh", with a comment explaining
what reh is.
v2:
  - Added drivers/fpga/intel-m10-bmc-secure.c file to MAINTAINERS.
  - Switched to GENMASK(31, 16) for a couple of mask definitions.
  - Moved MAX10 BMC address and function definitions to a separate
patch.
  - Replaced small function-creation macros with explicit function
declarations.
  - Removed ifpga_sec_mgr_init() and ifpga_sec_mgr_uinit() functions.
  - Adapted to changes in the Intel FPGA Security Manager by splitting
the single call to ifpga_sec_mgr_register() into two function
calls: devm_ifpga_sec_mgr_create() and ifpga_sec_mgr_register().
---
 .../testing/sysfs-driver-intel-m10-bmc-secure |  29 
 MAINTAINERS   |   2 +
 drivers/fpga/Kconfig  |  11 ++
 drivers/fpga/Makefile |   3 +
 drivers/fpga/intel-m10-bmc-secure.c   | 135 ++
 5 files changed, 180 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
 create mode 100644 drivers/fpga/intel-m10-bmc-secure.c

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
new file mode 100644
index ..296f809c447e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -0,0 +1,29 @@
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/sr_root_entry_hash
+Date:      January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the static
+   region if one is programmed, else it returns the
+   string: "hash not programmed".  This file is only
+   visible if the underlying device supports it.
+   Format: "0x%x".
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/pr_root_entry_hash
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the partial
+   reconfiguration region if one is programmed, else it
+   returns the string: "hash not programmed".  This file
+   is only visible if the underlying device supports it.
+   Format: "0x%x".
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/bmc_root_entry_hash
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the BMC image
+   if one is programmed, else it returns the string:
+   "hash not programmed".  This file is only visible if the
+   underlying device supports it.
+   Format: "0x%x".
diff --git a/MAINTAINERS b/MAINTAINERS
index 0ccfb8378349..db30d5d7dd8a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7020,8 +7020,10 @@ M:   Russ

[PATCH v8 0/5] Intel MAX10 BMC Secure Update Driver

2021-01-21 Thread Russ Weight
The Intel MAX10 BMC Secure Update driver instantiates the FPGA
Security Manager class driver and provides the callback functions
required to support secure updates on Intel n3000 PAC devices.
This driver is implemented as a sub-driver of the Intel MAX10 BMC
mfd driver. Future instances of the MAX10 BMC will support other
devices as well (e.g. d5005) and this same MAX10 BMC Secure
Update driver will receive modifications to support that device.

This driver interacts with the HW secure update engine of the
BMC in order to transfer new FPGA and BMC images to FLASH so
that they will be automatically loaded when the FPGA card reboots.
Security is enforced by hardware and firmware. The MAX10 BMC
Secure Update driver interacts with the firmware to initiate
an update, pass in the necessary data, and collect status on
the update.

This driver provides sysfs files for displaying the flash count,
the root entry hashes (REH), and the code-signing-key (CSK)
cancellation vectors.

These patches are dependent on other patches that are under
review. If you want to apply and compile these patches on
linux-next, please apply these patches first:

(1 patch)   https://marc.info/?l=linux-kernel=161126987101096=2
(7 patches) https://marc.info/?l=linux-fpga=160988774201859=2

Changelog v7 -> v8:
  - Spit out patch "mfd: intel-m10-bmc: support for MAX10 BMC Secure
Updates" and submitted it separately:
https://marc.info/?l=linux-kernel=161126987101096=2

Changelog v6 -> v7:
  - Rebased patches for 5.11-rc2
  - Updated Date and KernelVersion in ABI documentation

Changelog v5 -> v6:
  - Added WARN_ON() prior to several calls to regmap_bulk_read()
to assert that the (SIZE / stride) calculations did not result
in remainders.
  - Changed the (size / stride) calculation in regmap_bulk_write()
call to ensure that we don't write one less than intended.
  - Changed flash_count_show() parameter list to achieve
reverse-christmas tree format.
  - Removed unnecessary call to rsu_check_complete() in
m10bmc_sec_poll_complete() and changed while loop to
do/while loop.
  - Initialized auth_result and doorbell to HW_ERRINFO_POISON
in m10bmc_sec_hw_errinfo() and removed unnecessary if statements.

Changelog v4 -> v5:
  - Renamed sysfs node user_flash_count to flash_count and updated
the sysfs documentation accordingly to more accurately descirbe
the purpose of the count.

Changelog v3 -> v4:
  - Moved sysfs files for displaying the flash count, the root
entry hashes (REH), and the code-signing-key (CSK) cancellation
vectors from the FPGA Security Manager class driver to this
driver (as they are not generic enough for the class driver).
  - Added a new ABI documentation file with informtaion about the
new sysfs entries: sysfs-driver-intel-m10-bmc-secure
  - Updated the MAINTAINERS file to add the new ABI documentation
file: sysfs-driver-intel-m10-bmc-secure
  - Removed unnecessary ret variable from m10bmc_secure_probe()
  - Incorporated new devm_fpga_sec_mgr_register() function into
m10bmc_secure_probe() and removed the m10bmc_secure_remove()
function.

Changelog v2 -> v3:
  - Changed "MAX10 BMC Security Engine driver" to "MAX10 BMC Secure
Update driver"
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed "_root_entry_hash" to "_reh", with a comment explaining
what reh is.
  - Renamed get_csk_vector() to m10bmc_csk_vector()
  - Changed calling functions of functions that return "enum fpga_sec_err"
to check for (ret != FPGA_SEC_ERR_NONE) instead of (ret)

Changelog v1 -> v2:
  - These patches were previously submitted as part of a larger V1
patch set under the title "Intel FPGA Security Manager Class Driver".
  - Grouped all changes to include/linux/mfd/intel-m10-bmc.h into a
single patch: "mfd: intel-m10-bmc: support for MAX10 BMC Security
Engine".
  - Removed ifpga_sec_mgr_init() and ifpga_sec_mgr_uinit() functions.
  - Adapted to changes in the Intel FPGA Security Manager by splitting
the single call to ifpga_sec_mgr_register() into two function
calls: devm_ifpga_sec_mgr_create() and ifpga_sec_mgr_register().
  - Replaced small function-creation macros for explicit function
declarations.
  - Bug fix for the get_csk_vector() function to properly apply the
stride variable in calls to m10bmc_raw_bulk_read().
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
  - Implemented HW_ERRINFO_POISON for m10bmc_sec_hw_errinfo() to
ensure that corresponding bits are set to 1 if we are unable
    to read the doorbell or auth_result registers.
  - Added comments and additional code cleanup per V

[PATCH v8 0/1] Intel MAX10 BMC Macros for Secure Update

2021-01-21 Thread Russ Weight
This patch was previously patch 1 of 6 in the patch-series entitled
"Intel MAX10 BMC Secure Update Driver". This is the only patch in
the series that is subject to conflicts with other ongoing changes
and is separated here to simplify maintenance of the patchset.

This patch creates a number of macro definitions that are required
for the Intel MAX10 BMC Secure Update Driver.

Changelog v7 -> v8:
  - Rebased on next-20210121
  - Separated out from patchset: "Intel MAX10 BMC Secure Update Driver"
Changelog v6 -> v7:
  - No change
Changelog v5 -> v6:
  - No change
Changelog v4 -> v5:
  - Renamed USER_FLASH_COUNT to STAGING_FLASH_COUNT
Changelog v3 -> v4:
  - No change
Changelog v2 -> v3:
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure
Update driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions will be called directly.
Changelog v1 -> v2:
  - These functions and macros were previously distributed among
the patches that needed them. They are now grouped together
in a single patch containing changes to the Intel MAX10 BMC
driver.
  - Added DRBL_ prefix to some definitions
  - Some address definitions were moved here from the .c files that
use them.

Russ Weight (1):
  mfd: intel-m10-bmc: support for MAX10 BMC Secure Updates

 include/linux/mfd/intel-m10-bmc.h | 85 +++
 1 file changed, 85 insertions(+)

-- 
2.25.1



[PATCH v8 1/1] mfd: intel-m10-bmc: support for MAX10 BMC Secure Updates

2021-01-21 Thread Russ Weight
Add macros and definitions required by the MAX10 BMC
Secure Update driver.

Signed-off-by: Russ Weight 
Acked-by: Lee Jones 
---
v8:
  - Previously patch 1/6 in "Intel MAX10 BMC Secure Update Driver"
  - Rebased on next-20210121
v7:
  - No change
v6:
  - No change
v5:
  - Renamed USER_FLASH_COUNT to STAGING_FLASH_COUNT
v4:
  - No change
v3:
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure
Update driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions will be called directly.
v2:
  - These functions and macros were previously distributed among
the patches that needed them. They are now grouped together
in a single patch containing changes to the Intel MAX10 BMC
driver.
  - Added DRBL_ prefix to some definitions
  - Some address definitions were moved here from the .c files that
use them.
---
 include/linux/mfd/intel-m10-bmc.h | 85 +++
 1 file changed, 85 insertions(+)

diff --git a/include/linux/mfd/intel-m10-bmc.h 
b/include/linux/mfd/intel-m10-bmc.h
index 74d4e193966a..d80bf55cf2e2 100644
--- a/include/linux/mfd/intel-m10-bmc.h
+++ b/include/linux/mfd/intel-m10-bmc.h
@@ -13,6 +13,9 @@
 #define M10BMC_SYS_BASE0x300800
 #define M10BMC_MEM_END 0x20fc
 
+#define M10BMC_STAGING_BASE0x1800
+#define M10BMC_STAGING_SIZE0x380
+
 /* Register offset of system registers */
 #define NIOS2_FW_VERSION   0x0
 #define M10BMC_MAC_LOW 0x10
@@ -30,6 +33,88 @@
 #define M10BMC_VER_PCB_INFO_MSKGENMASK(31, 24)
 #define M10BMC_VER_LEGACY_INVALID  0x
 
+/* Secure update doorbell register, in system register region */
+#define M10BMC_DOORBELL0x400
+
+/* Authorization Result register, in system register region */
+#define M10BMC_AUTH_RESULT 0x404
+
+/* Doorbell register fields */
+#define DRBL_RSU_REQUEST   BIT(0)
+#define DRBL_RSU_PROGRESS  GENMASK(7, 4)
+#define DRBL_HOST_STATUS   GENMASK(11, 8)
+#define DRBL_RSU_STATUSGENMASK(23, 16)
+#define DRBL_PKVL_EEPROM_LOAD_SEC  BIT(24)
+#define DRBL_PKVL1_POLL_EN BIT(25)
+#define DRBL_PKVL2_POLL_EN BIT(26)
+#define DRBL_CONFIG_SELBIT(28)
+#define DRBL_REBOOT_REQBIT(29)
+#define DRBL_REBOOT_DISABLED   BIT(30)
+
+/* Progress states */
+#define RSU_PROG_IDLE  0x0
+#define RSU_PROG_PREPARE   0x1
+#define RSU_PROG_READY 0x3
+#define RSU_PROG_AUTHENTICATING0x4
+#define RSU_PROG_COPYING   0x5
+#define RSU_PROG_UPDATE_CANCEL 0x6
+#define RSU_PROG_PROGRAM_KEY_HASH  0x7
+#define RSU_PROG_RSU_DONE  0x8
+#define RSU_PROG_PKVL_PROM_DONE0x9
+
+/* Device and error states */
+#define RSU_STAT_NORMAL0x0
+#define RSU_STAT_TIMEOUT   0x1
+#define RSU_STAT_AUTH_FAIL 0x2
+#define RSU_STAT_COPY_FAIL 0x3
+#define RSU_STAT_FATAL 0x4
+#define RSU_STAT_PKVL_REJECT   0x5
+#define RSU_STAT_NON_INC   0x6
+#define RSU_STAT_ERASE_FAIL0x7
+#define RSU_STAT_WEAROUT   0x8
+#define RSU_STAT_NIOS_OK   0x80
+#define RSU_STAT_USER_OK   0x81
+#define RSU_STAT_FACTORY_OK0x82
+#define RSU_STAT_USER_FAIL 0x83
+#define RSU_STAT_FACTORY_FAIL  0x84
+#define RSU_STAT_NIOS_FLASH_ERR0x85
+#define RSU_STAT_FPGA_FLASH_ERR0x86
+
+#define HOST_STATUS_IDLE   0x0
+#define HOST_STATUS_WRITE_DONE 0x1
+#define HOST_STATUS_ABORT_RSU  0x2
+
+#define rsu_prog(doorbell) FIELD_GET(DRBL_RSU_PROGRESS, doorbell)
+#define rsu_stat(doorbell) FIELD_GET(DRBL_RSU_STATUS, doorbell)
+
+/* interval 100ms and timeout 5s */
+#define NIOS_HANDSHAKE_INTERVAL_US (100 * 1000)
+#define NIOS_HANDSHAKE_TIMEOUT_US  (5 * 1000 * 1000)
+
+/* RSU PREP Timeout (2 minutes) to erase flash staging area */
+#define RSU_PREP_INTERVAL_MS   100
+#define RSU_PREP_TIMEOUT_MS(2 * 60 * 1000)
+
+/* RSU Complete Timeout (40 minutes) for full flash update */
+#define RSU_COMPLETE_INTERVAL_MS   1000
+#define RSU_COMPLETE_TIMEOUT_MS(40 * 60 * 1000)
+
+/* Addresses for security related data in FLASH */
+#define BMC_REH_ADDR   0x17ffc004
+#define BMC_PROG_ADDR  0x17ffc000
+#define BMC_PROG_MAGIC 0x5746
+
+#define SR_REH_ADDR0x17ffd004
+#define SR_PROG_ADDR   0x17ffd000
+#define SR_PROG_MAGIC  0x5253
+
+#define PR_REH_ADDR0x17ffe004
+#define PR_PROG_ADDR   0x17ffe000
+#define PR_PROG_MAGIC  0x5250
+
+/* Address of 4KB inverted bit vector containing staging area FLASH count */
+#define STAGING_FLASH_COUNT0x17ffb000
+
 /**
  * struct intel_m1

[PATCH v8 0/1] Intel MAX10 BMC Macros for Secure Update

2021-01-21 Thread Russ Weight
This patch was previously patch 1 of 6 in the patch-series entitled
"Intel MAX10 BMC Secure Update Driver". This is the only patch in
the series that is subject to conflicts with other ongoing changes
and is separated here to simplify maintenance of the patchset.

This patch creates a number of macro definitions that are required
for the Intel MAX10 BMC Secure Update Driver.

Changelog v7 -> v8:
  - Rebased on next-20210121
  - Separated out from patchset: "Intel MAX10 BMC Secure Update Driver"
Changelog v6 -> v7:
  - No change
Changelog v5 -> v6:
  - No change
Changelog v4 -> v5:
  - Renamed USER_FLASH_COUNT to STAGING_FLASH_COUNT
Changelog v3 -> v4:
  - No change
Changelog v2 -> v3:
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure
Update driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions will be called directly.
Changelog v1 -> v2:
  - These functions and macros were previously distributed among
the patches that needed them. They are now grouped together
in a single patch containing changes to the Intel MAX10 BMC
driver.
  - Added DRBL_ prefix to some definitions
  - Some address definitions were moved here from the .c files that
use them.

Russ Weight (1):
  mfd: intel-m10-bmc: support for MAX10 BMC Secure Updates

 include/linux/mfd/intel-m10-bmc.h | 85 +++
 1 file changed, 85 insertions(+)

-- 
2.25.1



Re: [PATCH v7 0/6] Intel MAX10 BMC Secure Update Driver

2021-01-21 Thread Russ Weight



On 1/19/21 12:49 PM, Tom Rix wrote:
> On 1/5/21 3:08 PM, Russ Weight wrote:
>
> ...
>
>>  .../testing/sysfs-driver-intel-m10-bmc-secure |  61 ++
>>  MAINTAINERS   |   2 +
>>  drivers/fpga/Kconfig  |  11 +
>>  drivers/fpga/Makefile |   3 +
>>  drivers/fpga/intel-m10-bmc-secure.c   | 543 ++
>>  include/linux/mfd/intel-m10-bmc.h |  85 +++
> I am having trouble pulling this into my testing branch where i am tracking 
> some other changes to intel-m10-bmc.h
>
> https://lore.kernel.org/lkml/20210114231648.199685-1-russell.h.wei...@intel.com/
>
> https://lore.kernel.org/lkml/160628-12748-3-git-send-email-yilun...@intel.com/
>
> so I am wondering if it makes sense to split the intel-m10-bmc.h change out 
> of this patchset and sent as a single patch to mfd subsystem ?  The change is 
> a bunch of #defines that don't do anything on their own, but will conflict 
> with other similar additions to the h file.
If I rebase my working branch onto the latest linux-next, I don't see any 
issues. But if I apply the patches to the latest linux-next (git am), then I 
do. Clearly I need to fix up this patch and resend. If there are no objections, 
I'll split this patch out as an individual patch for the next submission.

- Russ
>
> Tom
>
>>  6 files changed, 705 insertions(+)
>>  create mode 100644 
>> Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
>>  create mode 100644 drivers/fpga/intel-m10-bmc-secure.c
>>



[PATCH v4 1/1] mfd: intel-m10-bmc: expose mac address and count

2021-01-14 Thread Russ Weight
Create two sysfs entries for exposing the MAC address
and count from the MAX10 BMC register space. The MAC
address is the first in a sequential block of MAC addresses
reserved for the FPGA card. The MAC count is the number
of MAC addresses in the reserved block.

Signed-off-by: Russ Weight 
Signed-off-by: Xu Yilun 
---
v4:
  - Changed local variables macaddr1 and macaddr2 to macaddr_low
and macaddr_high
  - Change macros M10BMC_MACADDR1 and M10BMC_MACADDR2 to
M10BMC_MAC_LOW and M10BMC_MAC_HIGH
v3:
  - Updated Date and KernelVersion in ABI documentation
v2:
  - Updated the documentation for the mac_address and mac_count
sysfs nodes to clarify their usage.
  - Changed sysfs _show() functions to use sysfs_emit() instead
of sprintf.
---
 .../ABI/testing/sysfs-driver-intel-m10-bmc| 21 +
 drivers/mfd/intel-m10-bmc.c   | 43 +++
 include/linux/mfd/intel-m10-bmc.h |  9 
 3 files changed, 73 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
index 979a2d62513f..9773925138af 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
@@ -13,3 +13,24 @@ Contact: Xu Yilun 
 Description:   Read only. Returns the firmware version of Intel MAX10
BMC chip.
Format: "0x%x".
+
+What:  /sys/bus/spi/devices/.../mac_address
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns the first MAC address in a block
+   of sequential MAC addresses assigned to the board
+   that is managed by the Intel MAX10 BMC. It is stored in
+   FLASH storage and is mirrored in the MAX10 BMC register
+   space.
+   Format: "%02x:%02x:%02x:%02x:%02x:%02x".
+
+What:  /sys/bus/spi/devices/.../mac_count
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns the number of sequential MAC
+   addresses assigned to the board managed by the Intel
+   MAX10 BMC. This value is stored in FLASH and is mirrored
+   in the MAX10 BMC register space.
+   Format: "%u".
diff --git a/drivers/mfd/intel-m10-bmc.c b/drivers/mfd/intel-m10-bmc.c
index b84579b7b4f0..06c977519479 100644
--- a/drivers/mfd/intel-m10-bmc.c
+++ b/drivers/mfd/intel-m10-bmc.c
@@ -60,9 +60,52 @@ static ssize_t bmcfw_version_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(bmcfw_version);
 
+static ssize_t mac_address_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct intel_m10bmc *max10 = dev_get_drvdata(dev);
+   unsigned int macaddr_low, macaddr_high;
+   int ret;
+
+   ret = m10bmc_sys_read(max10, M10BMC_MAC_LOW, _low);
+   if (ret)
+   return ret;
+
+   ret = m10bmc_sys_read(max10, M10BMC_MAC_HIGH, _high);
+   if (ret)
+   return ret;
+
+   return sysfs_emit(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ (u8)FIELD_GET(M10BMC_MAC_BYTE1, macaddr_low),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE2, macaddr_low),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE3, macaddr_low),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE4, macaddr_low),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE5, macaddr_high),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE6, macaddr_high));
+}
+static DEVICE_ATTR_RO(mac_address);
+
+static ssize_t mac_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+   struct intel_m10bmc *max10 = dev_get_drvdata(dev);
+   unsigned int macaddr_high;
+   int ret;
+
+   ret = m10bmc_sys_read(max10, M10BMC_MAC_HIGH, _high);
+   if (ret)
+   return ret;
+
+   return sysfs_emit(buf, "%u\n",
+ (u8)FIELD_GET(M10BMC_MAC_COUNT, macaddr_high));
+}
+static DEVICE_ATTR_RO(mac_count);
+
 static struct attribute *m10bmc_attrs[] = {
_attr_bmc_version.attr,
_attr_bmcfw_version.attr,
+   _attr_mac_address.attr,
+   _attr_mac_count.attr,
NULL,
 };
 ATTRIBUTE_GROUPS(m10bmc);
diff --git a/include/linux/mfd/intel-m10-bmc.h 
b/include/linux/mfd/intel-m10-bmc.h
index c8ef2f1654a4..74d4e193966a 100644
--- a/include/linux/mfd/intel-m10-bmc.h
+++ b/include/linux/mfd/intel-m10-bmc.h
@@ -15,6 +15,15 @@
 
 /* Register offset of system registers */
 #define NIOS2_FW_VERSION   0x0
+#define M10BMC_MAC_LOW 0x10
+#define M10BMC_MAC_BYTE4   GENMASK(7, 0)
+#define M10BMC_MAC_BYTE3   GENMASK(15, 8)
+#define M10BMC_MAC_BYTE2   GENMASK(23, 16)
+#define M10BMC_MAC_BYTE1 

[PATCH v4 0/1] mfd: intel-m10-bmc: add sysfs files for mac_address

2021-01-14 Thread Russ Weight
Add two sysfs nodes to the Intel MAX10 BMC driver: mac_address
and mac_count. The mac_address provides the first of a series
of sequential MAC addresses assigned to the FPGA card. The
mac_count indicates how many MAC addresses are assigned to the
card.

Changelog v3 -> v4:
  - Changed local variables macaddr1 and macaddr2 to macaddr_low
and macaddr_high
  - Change macros M10BMC_MACADDR1 and M10BMC_MACADDR2 to
M10BMC_MAC_LOW and M10BMC_MAC_HIGH

Changelog v2 -> v3:
  - Updated Date and KernelVersion in ABI documentation

Changelog v1 -> v2:
  - Updated the documentation for the mac_address and mac_count
sysfs nodes to clearify their usage.
  - Changed sysfs _show() functions to use sysfs_emit() instead
of sprintf.

Russ Weight (1):
  mfd: intel-m10-bmc: expose mac address and count

 .../ABI/testing/sysfs-driver-intel-m10-bmc| 21 +
 drivers/mfd/intel-m10-bmc.c   | 43 +++
 include/linux/mfd/intel-m10-bmc.h |  9 
 3 files changed, 73 insertions(+)

-- 
2.25.1



Re: [PATCH v3 1/1] mfd: intel-m10-bmc: expose mac address and count

2021-01-14 Thread Russ Weight



On 1/14/21 5:23 AM, Lee Jones wrote:
> On Tue, 05 Jan 2021, Russ Weight wrote:
>
>> Create two sysfs entries for exposing the MAC address
>> and count from the MAX10 BMC register space. The MAC
>> address is the first in a sequential block of MAC addresses
>> reserved for the FPGA card. The MAC count is the number
>> of MAC addresses in the reserved block.
>>
>> Signed-off-by: Russ Weight 
>> Signed-off-by: Xu Yilun 
>> ---
>> v3:
>>   - Updated Date and KernelVersion in ABI documentation
>> v2:
>>   - Updated the documentation for the mac_address and mac_count
>> sysfs nodes to clarify their usage.
>>   - Changed sysfs _show() functions to use sysfs_emit() instead
>> of sprintf.
>> ---
>>  .../ABI/testing/sysfs-driver-intel-m10-bmc| 21 +
>>  drivers/mfd/intel-m10-bmc.c   | 43 +++
>>  include/linux/mfd/intel-m10-bmc.h |  9 
>>  3 files changed, 73 insertions(+)
>>
>> diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc 
>> b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
>> index 979a2d62513f..9773925138af 100644
>> --- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
>> +++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
>> @@ -13,3 +13,24 @@ Contact:  Xu Yilun 
>>  Description:Read only. Returns the firmware version of Intel MAX10
>>  BMC chip.
>>  Format: "0x%x".
>> +
>> +What:   /sys/bus/spi/devices/.../mac_address
>> +Date:   January 2021
>> +KernelVersion:  5.12
>> +Contact:Russ Weight 
>> +Description:Read only. Returns the first MAC address in a block
>> +of sequential MAC addresses assigned to the board
>> +that is managed by the Intel MAX10 BMC. It is stored in
>> +FLASH storage and is mirrored in the MAX10 BMC register
>> +space.
>> +Format: "%02x:%02x:%02x:%02x:%02x:%02x".
>> +
>> +What:   /sys/bus/spi/devices/.../mac_count
>> +Date:   January 2021
>> +KernelVersion:  5.12
>> +Contact:Russ Weight 
>> +Description:Read only. Returns the number of sequential MAC
>> +addresses assigned to the board managed by the Intel
>> +MAX10 BMC. This value is stored in FLASH and is mirrored
>> +in the MAX10 BMC register space.
>> +Format: "%u".
>> diff --git a/drivers/mfd/intel-m10-bmc.c b/drivers/mfd/intel-m10-bmc.c
>> index b84579b7b4f0..751c0ecf95d6 100644
>> --- a/drivers/mfd/intel-m10-bmc.c
>> +++ b/drivers/mfd/intel-m10-bmc.c
>> @@ -60,9 +60,52 @@ static ssize_t bmcfw_version_show(struct device *dev,
>>  }
>>  static DEVICE_ATTR_RO(bmcfw_version);
>>  
>> +static ssize_t mac_address_show(struct device *dev,
>> +struct device_attribute *attr, char *buf)
>> +{
>> +struct intel_m10bmc *max10 = dev_get_drvdata(dev);
>> +unsigned int macaddr1, macaddr2;
> This naming convention is confusing.
>
> It took me a minute to work it out.
>
> Does 'high' and 'low' make sense!

Yes - that is more descriptive. I'll make the change and resubmit.

Thanks!
- Russ
>
>> +int ret;
>> +
>> +ret = m10bmc_sys_read(max10, M10BMC_MACADDR1, );
>> +if (ret)
>> +return ret;
>> +
>> +ret = m10bmc_sys_read(max10, M10BMC_MACADDR2, );
>> +if (ret)
>> +return ret;
>> +
>> +return sysfs_emit(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
>> +  (u8)FIELD_GET(M10BMC_MAC_BYTE1, macaddr1),
>> +  (u8)FIELD_GET(M10BMC_MAC_BYTE2, macaddr1),
>> +  (u8)FIELD_GET(M10BMC_MAC_BYTE3, macaddr1),
>> +  (u8)FIELD_GET(M10BMC_MAC_BYTE4, macaddr1),
>> +  (u8)FIELD_GET(M10BMC_MAC_BYTE5, macaddr2),
>> +  (u8)FIELD_GET(M10BMC_MAC_BYTE6, macaddr2));
>> +}
>> +static DEVICE_ATTR_RO(mac_address);
>> +
>> +static ssize_t mac_count_show(struct device *dev,
>> +  struct device_attribute *attr, char *buf)
>> +{
>> +struct intel_m10bmc *max10 = dev_get_drvdata(dev);
>> +unsigned int macaddr2;
>> +int ret;
>> +
>> +ret = m10bmc_sys_read(max10, M10BMC_MACADDR2, );
>> +if (ret)
>> +return ret;
>> +
>> +return sysfs_emit(buf, "%u\n",
>> +   

[PATCH v7 3/6] fpga: m10bmc-sec: expose max10 flash update count

2021-01-05 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to provide a
sysfs file to expose the flash update count for the FPGA
user image.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Changed flash_count_show() parameter list to achieve
reverse-christmas tree format.
  - Added WARN_ON() call for (FLASH_COUNT_SIZE / stride) to ensure
that the proper count is passed to regmap_bulk_read().
v5:
  - Renamed sysfs node user_flash_count to flash_count and updated the
sysfs documentation accordingly.
v4:
  - Moved the sysfs file for displaying the flash count from the
FPGA Security Manager class driver to here. The
m10bmc_user_flash_count() function is removed and the
functionality is moved into a user_flash_count_show()
function.
  - Added ABI documentation for the new sysfs entry
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
v2:
  - Renamed get_qspi_flash_count() to m10bmc_user_flash_count()
  - Minor code cleanup per review comments
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 .../testing/sysfs-driver-intel-m10-bmc-secure |  8 
 drivers/fpga/intel-m10-bmc-secure.c   | 37 +++
 2 files changed, 45 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
index 296f809c447e..7300038d07c3 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -27,3 +27,11 @@ Description: Read only. Returns the root entry hash for the 
BMC image
"hash not programmed".  This file is only visible if the
underlying device supports it.
Format: "0x%x".
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/flash_count
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns number of times the secure update
+   staging area has been flashed.
+   Format: "%u".
diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index 5ac5f59b5731..ecd63c13cb2d 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct m10bmc_sec {
struct device *dev;
@@ -78,7 +79,43 @@ DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, 
BMC_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
 
+#define FLASH_COUNT_SIZE 4096  /* count stored as inverted bit vector */
+
+static ssize_t flash_count_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct m10bmc_sec *sec = dev_get_drvdata(dev);
+   unsigned int stride, num_bits;
+   u8 *flash_buf;
+   int cnt, ret;
+
+   stride = regmap_get_reg_stride(sec->m10bmc->regmap);
+   num_bits = FLASH_COUNT_SIZE * 8;
+
+   flash_buf = kmalloc(FLASH_COUNT_SIZE, GFP_KERNEL);
+   if (!flash_buf)
+   return -ENOMEM;
+
+   WARN_ON(FLASH_COUNT_SIZE % stride);
+   ret = regmap_bulk_read(sec->m10bmc->regmap, STAGING_FLASH_COUNT,
+  flash_buf, FLASH_COUNT_SIZE / stride);
+   if (ret) {
+   dev_err(sec->dev,
+   "failed to read flash count: %x cnt %x: %d\n",
+   STAGING_FLASH_COUNT, FLASH_COUNT_SIZE / stride, ret);
+   goto exit_free;
+   }
+   cnt = num_bits - bitmap_weight((unsigned long *)flash_buf, num_bits);
+
+exit_free:
+   kfree(flash_buf);
+
+   return ret ? : sysfs_emit(buf, "%u\n", cnt);
+}
+static DEVICE_ATTR_RO(flash_count);
+
 static struct attribute *m10bmc_security_attrs[] = {
+   _attr_flash_count.attr,
_attr_bmc_root_entry_hash.attr,
_attr_sr_root_entry_hash.attr,
_attr_pr_root_entry_hash.attr,
-- 
2.25.1



[PATCH v7 6/6] fpga: m10bmc-sec: add max10 get_hw_errinfo callback func

2021-01-05 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to include
a function that returns 64 bits of additional HW specific
data for errors that require additional information.
This callback function enables the hw_errinfo sysfs
node in the Intel Security Manager class driver.

Signed-off-by: Russ Weight 
---
v7:
  - No change
v6:
  - Initialized auth_result and doorbell to HW_ERRINFO_POISON
in m10bmc_sec_hw_errinfo() and removed unnecessary if statements.
v5:
  - No change
v4:
  - No change
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
v2:
  - Implemented HW_ERRINFO_POISON for m10bmc_sec_hw_errinfo() to
ensure that corresponding bits are set to 1 if we are unable
to read the doorbell or auth_result registers.
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
 drivers/fpga/intel-m10-bmc-secure.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index a290fcc4df4a..3a049c98cf43 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -476,11 +476,33 @@ static enum fpga_sec_err m10bmc_sec_cancel(struct 
fpga_sec_mgr *smgr)
return ret ? FPGA_SEC_ERR_RW_ERROR : FPGA_SEC_ERR_NONE;
 }
 
+#define HW_ERRINFO_POISON  GENMASK(31, 0)
+static u64 m10bmc_sec_hw_errinfo(struct fpga_sec_mgr *smgr)
+{
+   struct m10bmc_sec *sec = smgr->priv;
+   u32 auth_result = HW_ERRINFO_POISON;
+   u32 doorbell = HW_ERRINFO_POISON;
+
+   switch (smgr->err_code) {
+   case FPGA_SEC_ERR_HW_ERROR:
+   case FPGA_SEC_ERR_TIMEOUT:
+   case FPGA_SEC_ERR_BUSY:
+   case FPGA_SEC_ERR_WEAROUT:
+   m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, );
+   m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, _result);
+
+   return (u64)doorbell << 32 | (u64)auth_result;
+   default:
+   return 0;
+   }
+}
+
 static const struct fpga_sec_mgr_ops m10bmc_sops = {
.prepare = m10bmc_sec_prepare,
.write_blk = m10bmc_sec_write_blk,
.poll_complete = m10bmc_sec_poll_complete,
.cancel = m10bmc_sec_cancel,
+   .get_hw_errinfo = m10bmc_sec_hw_errinfo,
 };
 
 static int m10bmc_secure_probe(struct platform_device *pdev)
-- 
2.25.1



[PATCH v7 4/6] fpga: m10bmc-sec: expose max10 canceled keys in sysfs

2021-01-05 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to provide sysfs
files to expose the canceled code signing key (CSK) bit
vectors. These use the standard bitmap list format
(e.g. 1,2-6,9).

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Added WARN_ON() call for (size / stride) to ensure
that the proper count is passed to regmap_bulk_read().
v5:
  - No change
v4:
  - Moved sysfs files for displaying the code-signing-key (CSK)
cancellation vectors from the FPGA Security Manger class driver
to here. The m10bmc_csk_vector() and m10bmc_csk_cancel_nbits()
functions are removed and the functionality from these functions
is moved into a show_canceled_csk() function for for displaying
the CSK vectors.
  - Added ABI documentation for new sysfs entries
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Renamed get_csk_vector() to m10bmc_csk_vector()
v2:
  - Replaced small function-creation macros for explicit function
declarations.
  - Fixed get_csk_vector() function to properly apply the stride
variable in calls to m10bmc_raw_bulk_read()
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
---
 .../testing/sysfs-driver-intel-m10-bmc-secure | 24 ++
 drivers/fpga/intel-m10-bmc-secure.c   | 48 +++
 2 files changed, 72 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
index 7300038d07c3..27890a9ba355 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -28,6 +28,30 @@ Description: Read only. Returns the root entry hash for the 
BMC image
underlying device supports it.
Format: "0x%x".
 
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/sr_canceled_csks
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the static region. The standard bitmap
+   list format is used (e.g. "1,2-6,9").
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/pr_canceled_csks
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the partial reconfiguration region. The
+   standard bitmap list format is used (e.g. "1,2-6,9").
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/bmc_canceled_csks
+Date:      January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns a list of indices for canceled code
+   signing keys for the BMC.  The standard bitmap list format
+   is used (e.g. "1,2-6,9").
+
 What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/flash_count
 Date:  January 2021
 KernelVersion:  5.12
diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index ecd63c13cb2d..87e16c146569 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -79,6 +79,51 @@ DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, 
BMC_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);
 DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
 
+#define CSK_BIT_LEN128U
+#define CSK_32ARRAY_SIZE   DIV_ROUND_UP(CSK_BIT_LEN, 32)
+
+static ssize_t
+show_canceled_csk(struct device *dev, u32 addr, char *buf)
+{
+   unsigned int i, stride, size = CSK_32ARRAY_SIZE * sizeof(u32);
+   struct m10bmc_sec *sec = dev_get_drvdata(dev);
+   DECLARE_BITMAP(csk_map, CSK_BIT_LEN);
+   __le32 csk_le32[CSK_32ARRAY_SIZE];
+   u32 csk32[CSK_32ARRAY_SIZE];
+   int ret;
+
+   stride = regmap_get_reg_stride(sec->m10bmc->regmap);
+
+   WARN_ON(size % stride);
+   ret = regmap_bulk_read(sec->m10bmc->regmap, addr, csk_le32,
+  size / stride);
+   if (ret) {
+   dev_err(sec->dev, "failed to read CSK vector: %x cnt %x: %d\n",
+   addr, size / stride, ret);
+   return ret;
+   }
+
+   for (i = 0; i < CSK_32ARRAY_SIZE; i++)
+   csk32[i] = le32_to_cpu(((csk_le32[i])));
+
+   bitmap_from_arr32(csk_map, csk32, CSK_BIT_LEN);
+   bitmap_complement(csk_map, csk_map, CSK_BIT_LEN);
+   return bitmap_

[PATCH v7 5/6] fpga: m10bmc-sec: add max10 secure update functions

2021-01-05 Thread Russ Weight
Extend the MAX10 BMC Secure Update driver to include
the functions that enable secure updates of BMC images,
FPGA images, etc.

Signed-off-by: Russ Weight 
---
v7:
  - No change
v6:
  - Changed (size / stride) calculation to ((size + stride - 1) / stride)
to ensure that the proper count is passed to regmap_bulk_write().
  - Removed unnecessary call to rsu_check_complete() in
m10bmc_sec_poll_complete() and changed while loop to
do/while loop.
v5:
  - No change
v4:
  - No change
v3:
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure Update
driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed calling functions of functions that return "enum fpga_sec_err"
to check for (ret != FPGA_SEC_ERR_NONE) instead of (ret)
v2:
  - Reworked the rsu_start_done() function to make it more readable
  - Reworked while-loop condition/content in rsu_prog_ready()
  - Minor code cleanup per review comments
  - Added a comment to the m10bmc_sec_poll_complete() function to
explain the context (could take 30+ minutes to complete).
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
  - Moved MAX10 BMC address and function definitions to a separate
patch.
---
 drivers/fpga/intel-m10-bmc-secure.c | 303 +++-
 1 file changed, 302 insertions(+), 1 deletion(-)

diff --git a/drivers/fpga/intel-m10-bmc-secure.c 
b/drivers/fpga/intel-m10-bmc-secure.c
index 87e16c146569..a290fcc4df4a 100644
--- a/drivers/fpga/intel-m10-bmc-secure.c
+++ b/drivers/fpga/intel-m10-bmc-secure.c
@@ -180,7 +180,308 @@ static const struct attribute_group 
*m10bmc_sec_attr_groups[] = {
NULL,
 };
 
-static const struct fpga_sec_mgr_ops m10bmc_sops = { };
+static void log_error_regs(struct m10bmc_sec *sec, u32 doorbell)
+{
+   u32 auth_result;
+
+   dev_err(sec->dev, "RSU error status: 0x%08x\n", doorbell);
+
+   if (!m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, _result))
+   dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result);
+}
+
+static enum fpga_sec_err rsu_check_idle(struct m10bmc_sec *sec)
+{
+   u32 doorbell;
+   int ret;
+
+   ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, );
+   if (ret)
+   return FPGA_SEC_ERR_RW_ERROR;
+
+   if (rsu_prog(doorbell) != RSU_PROG_IDLE &&
+   rsu_prog(doorbell) != RSU_PROG_RSU_DONE) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_BUSY;
+   }
+
+   return FPGA_SEC_ERR_NONE;
+}
+
+static inline bool rsu_start_done(u32 doorbell)
+{
+   u32 status, progress;
+
+   if (doorbell & DRBL_RSU_REQUEST)
+   return false;
+
+   status = rsu_stat(doorbell);
+   if (status == RSU_STAT_ERASE_FAIL || status == RSU_STAT_WEAROUT)
+   return true;
+
+   progress = rsu_prog(doorbell);
+   if (progress != RSU_PROG_IDLE && progress != RSU_PROG_RSU_DONE)
+   return true;
+
+   return false;
+}
+
+static enum fpga_sec_err rsu_update_init(struct m10bmc_sec *sec)
+{
+   u32 doorbell, status;
+   int ret;
+
+   ret = regmap_update_bits(sec->m10bmc->regmap,
+M10BMC_SYS_BASE + M10BMC_DOORBELL,
+DRBL_RSU_REQUEST | DRBL_HOST_STATUS,
+DRBL_RSU_REQUEST |
+FIELD_PREP(DRBL_HOST_STATUS,
+   HOST_STATUS_IDLE));
+   if (ret)
+   return FPGA_SEC_ERR_RW_ERROR;
+
+   ret = regmap_read_poll_timeout(sec->m10bmc->regmap,
+  M10BMC_SYS_BASE + M10BMC_DOORBELL,
+  doorbell,
+  rsu_start_done(doorbell),
+  NIOS_HANDSHAKE_INTERVAL_US,
+  NIOS_HANDSHAKE_TIMEOUT_US);
+
+   if (ret == -ETIMEDOUT) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_TIMEOUT;
+   } else if (ret) {
+   return FPGA_SEC_ERR_RW_ERROR;
+   }
+
+   status = rsu_stat(doorbell);
+   if (status == RSU_STAT_WEAROUT) {
+   dev_warn(sec->dev, "Excessive flash update count detected\n");
+   return FPGA_SEC_ERR_WEAROUT;
+   } else if (status == RSU_STAT_ERASE_FAIL) {
+   log_error_regs(sec, doorbell);
+   return FPGA_SEC_ERR_HW_ERROR;
+   }
+
+   return FPGA_SEC_ERR_NONE;
+}
+
+static enum fpga_sec_err rsu_prog_ready(struct m10bmc_sec *sec)
+{
+   unsigned long poll_timeout;
+   u32 doorbell, progress;
+   int ret;
+
+   ret = m10bmc_sys_read(sec->m10b

[PATCH v7 0/6] Intel MAX10 BMC Secure Update Driver

2021-01-05 Thread Russ Weight
The Intel MAX10 BMC Secure Update driver instantiates the FPGA
Security Manager class driver and provides the callback functions
required to support secure updates on Intel n3000 PAC devices.
This driver is implemented as a sub-driver of the Intel MAX10 BMC
mfd driver. Future instances of the MAX10 BMC will support other
devices as well (e.g. d5005) and this same MAX10 BMC Secure
Update driver will receive modifications to support that device.

This driver interacts with the HW secure update engine of the
BMC in order to transfer new FPGA and BMC images to FLASH so
that they will be automatically loaded when the FPGA card reboots.
Security is enforced by hardware and firmware. The MAX10 BMC
Secure Update driver interacts with the firmware to initiate
an update, pass in the necessary data, and collect status on
the update.

This driver provides sysfs files for displaying the flash count,
the root entry hashes (REH), and the code-signing-key (CSK)
cancellation vectors.

These patches are dependent on other patches that are under
review. If you want to apply and compile these patches on
linux-next, please apply these patches first:

(7 patches) https://marc.info/?l=linux-fpga=160988774201859=2

If you have an n3000 PAC card and want to test this driver, you
will also need these patches:

(6 patches) https://marc.info/?l=linux-fpga=160920855708582=2

Changelog v6 -> v7:
  - Rebased patches for 5.11-rc2
  - Updated Date and KernelVersion in ABI documentation

Changelog v5 -> v6:
  - Added WARN_ON() prior to several calls to regmap_bulk_read()
to assert that the (SIZE / stride) calculations did not result
in remainders.
  - Changed the (size / stride) calculation in regmap_bulk_write()
call to ensure that we don't write one less than intended.
  - Changed flash_count_show() parameter list to achieve
reverse-christmas tree format.
  - Removed unnecessary call to rsu_check_complete() in
m10bmc_sec_poll_complete() and changed while loop to
do/while loop.
  - Initialized auth_result and doorbell to HW_ERRINFO_POISON
in m10bmc_sec_hw_errinfo() and removed unnecessary if statements.

Changelog v4 -> v5:
  - Renamed sysfs node user_flash_count to flash_count and updated
the sysfs documentation accordingly to more accurately descirbe
the purpose of the count.

Changelog v3 -> v4:
  - Moved sysfs files for displaying the flash count, the root
entry hashes (REH), and the code-signing-key (CSK) cancellation
vectors from the FPGA Security Manager class driver to this
driver (as they are not generic enough for the class driver).
  - Added a new ABI documentation file with informtaion about the
new sysfs entries: sysfs-driver-intel-m10-bmc-secure
  - Updated the MAINTAINERS file to add the new ABI documentation
file: sysfs-driver-intel-m10-bmc-secure
  - Removed unnecessary ret variable from m10bmc_secure_probe()
  - Incorporated new devm_fpga_sec_mgr_register() function into
m10bmc_secure_probe() and removed the m10bmc_secure_remove()
function.

Changelog v2 -> v3:
  - Changed "MAX10 BMC Security Engine driver" to "MAX10 BMC Secure
Update driver"
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed "_root_entry_hash" to "_reh", with a comment explaining
what reh is.
  - Renamed get_csk_vector() to m10bmc_csk_vector()
  - Changed calling functions of functions that return "enum fpga_sec_err"
to check for (ret != FPGA_SEC_ERR_NONE) instead of (ret)

Changelog v1 -> v2:
  - These patches were previously submitted as part of a larger V1
patch set under the title "Intel FPGA Security Manager Class Driver".
  - Grouped all changes to include/linux/mfd/intel-m10-bmc.h into a
single patch: "mfd: intel-m10-bmc: support for MAX10 BMC Security
Engine".
  - Removed ifpga_sec_mgr_init() and ifpga_sec_mgr_uinit() functions.
  - Adapted to changes in the Intel FPGA Security Manager by splitting
the single call to ifpga_sec_mgr_register() into two function
calls: devm_ifpga_sec_mgr_create() and ifpga_sec_mgr_register().
  - Replaced small function-creation macros for explicit function
declarations.
  - Bug fix for the get_csk_vector() function to properly apply the
stride variable in calls to m10bmc_raw_bulk_read().
  - Added m10bmc_ prefix to functions in m10bmc_iops structure
  - Implemented HW_ERRINFO_POISON for m10bmc_sec_hw_errinfo() to
ensure that corresponding bits are set to 1 if we are unable
    to read the doorbell or auth_result registers.
  - Added comments and additional code cleanup per V1 review.

Russ Weight (6):
  mfd: intel-m10-bmc: support for MAX10 BMC Secure Updates
  fpga: m10bmc-s

[PATCH v7 2/6] fpga: m10bmc-sec: create max10 bmc secure update driver

2021-01-05 Thread Russ Weight
Create a platform driver that can be invoked as a sub
driver for the Intel MAX10 BMC in order to support
secure updates. This sub-driver will invoke an
instance of the FPGA Security Manager class driver
in order to expose sysfs interfaces for managing and
monitoring secure updates to FPGA and BMC images.

This patch creates the MAX10 BMC Secure Update driver and
provides sysfs files for displaying the current root entry hashes
for the FPGA static region, the FPGA PR region, and the MAX10
BMC.

Signed-off-by: Russ Weight 
---
v7:
  - Updated Date and KernelVersion in ABI documentation
v6:
  - Added WARN_ON() call for (sha_num_bytes / stride) to assert
that the proper count is passed to regmap_bulk_read().
v5:
  - No change
v4:
  - Moved sysfs files for displaying the root entry hashes (REH)
from the FPGA Security Manager class driver to here. The
m10bmc_reh() and m10bmc_reh_size() functions are removed and
the functionality from these functions is moved into a
show_root_entry_hash() function for displaying the REHs.
  - Added ABI documentation for the new sysfs entries:
sysfs-driver-intel-m10-bmc-secure
  - Updated the MAINTAINERS file to add the new ABI documentation
file: sysfs-driver-intel-m10-bmc-secure
  - Removed unnecessary ret variable from m10bmc_secure_probe()
  - Incorporated new devm_fpga_sec_mgr_register() function into
m10bmc_secure_probe() and removed the m10bmc_secure_remove()
function.
v3:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure
Update driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions are now called directly.
  - Changed "_root_entry_hash" to "_reh", with a comment explaining
what reh is.
v2:
  - Added drivers/fpga/intel-m10-bmc-secure.c file to MAINTAINERS.
  - Switched to GENMASK(31, 16) for a couple of mask definitions.
  - Moved MAX10 BMC address and function definitions to a separate
patch.
  - Replaced small function-creation macros with explicit function
declarations.
  - Removed ifpga_sec_mgr_init() and ifpga_sec_mgr_uinit() functions.
  - Adapted to changes in the Intel FPGA Security Manager by splitting
the single call to ifpga_sec_mgr_register() into two function
calls: devm_ifpga_sec_mgr_create() and ifpga_sec_mgr_register().
---
 .../testing/sysfs-driver-intel-m10-bmc-secure |  29 
 MAINTAINERS   |   2 +
 drivers/fpga/Kconfig  |  11 ++
 drivers/fpga/Makefile |   3 +
 drivers/fpga/intel-m10-bmc-secure.c   | 135 ++
 5 files changed, 180 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
 create mode 100644 drivers/fpga/intel-m10-bmc-secure.c

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
new file mode 100644
index ..296f809c447e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure
@@ -0,0 +1,29 @@
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/sr_root_entry_hash
+Date:      January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the static
+   region if one is programmed, else it returns the
+   string: "hash not programmed".  This file is only
+   visible if the underlying device supports it.
+   Format: "0x%x".
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/pr_root_entry_hash
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the partial
+   reconfiguration region if one is programmed, else it
+   returns the string: "hash not programmed".  This file
+   is only visible if the underlying device supports it.
+   Format: "0x%x".
+
+What:  
/sys/bus/platform/devices/n3000bmc-secure.*.auto/security/bmc_root_entry_hash
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns the root entry hash for the BMC image
+   if one is programmed, else it returns the string:
+   "hash not programmed".  This file is only visible if the
+   underlying device supports it.
+   Format: "0x%x".
diff --git a/MAINTAINERS b/MAINTAINERS
index affc1881ebb9..ecbf02daa42e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6989,8 +6989,10 @@ M:   Russ Weight 
 L: linux-f...@vger.kernel.org
 S: Maintained
 F

[PATCH v7 1/6] mfd: intel-m10-bmc: support for MAX10 BMC Secure Updates

2021-01-05 Thread Russ Weight
Add macros and definitions required by the MAX10 BMC
Secure Update driver.

Signed-off-by: Russ Weight 
Acked-by: Lee Jones 
---
v7:
  - No change
v6:
  - No change
v5:
  - Renamed USER_FLASH_COUNT to STAGING_FLASH_COUNT
v4:
  - No change
v3:
  - Changed "MAX10 BMC Secure Engine driver" to "MAX10 BMC Secure
Update driver"
  - Removed wrapper functions (m10bmc_raw_*, m10bmc_sys_*). The
underlying functions will be called directly.
v2:
  - These functions and macros were previously distributed among
the patches that needed them. They are now grouped together
in a single patch containing changes to the Intel MAX10 BMC
driver.
  - Added DRBL_ prefix to some definitions
  - Some address definitions were moved here from the .c files that
use them.
---
 include/linux/mfd/intel-m10-bmc.h | 85 +++
 1 file changed, 85 insertions(+)

diff --git a/include/linux/mfd/intel-m10-bmc.h 
b/include/linux/mfd/intel-m10-bmc.h
index 2279e34f0814..64aa7c537917 100644
--- a/include/linux/mfd/intel-m10-bmc.h
+++ b/include/linux/mfd/intel-m10-bmc.h
@@ -13,6 +13,9 @@
 #define M10BMC_SYS_BASE0x300800
 #define M10BMC_MEM_END 0x20fc
 
+#define M10BMC_STAGING_BASE0x1800
+#define M10BMC_STAGING_SIZE0x380
+
 /* Register offset of system registers */
 #define NIOS2_FW_VERSION   0x0
 #define M10BMC_MACADDR10x10
@@ -30,6 +33,88 @@
 #define M10BMC_VER_PCB_INFO_MSKGENMASK(31, 24)
 #define M10BMC_VER_LEGACY_INVALID  0x
 
+/* Secure update doorbell register, in system register region */
+#define M10BMC_DOORBELL0x400
+
+/* Authorization Result register, in system register region */
+#define M10BMC_AUTH_RESULT 0x404
+
+/* Doorbell register fields */
+#define DRBL_RSU_REQUEST   BIT(0)
+#define DRBL_RSU_PROGRESS  GENMASK(7, 4)
+#define DRBL_HOST_STATUS   GENMASK(11, 8)
+#define DRBL_RSU_STATUSGENMASK(23, 16)
+#define DRBL_PKVL_EEPROM_LOAD_SEC  BIT(24)
+#define DRBL_PKVL1_POLL_EN BIT(25)
+#define DRBL_PKVL2_POLL_EN BIT(26)
+#define DRBL_CONFIG_SELBIT(28)
+#define DRBL_REBOOT_REQBIT(29)
+#define DRBL_REBOOT_DISABLED   BIT(30)
+
+/* Progress states */
+#define RSU_PROG_IDLE  0x0
+#define RSU_PROG_PREPARE   0x1
+#define RSU_PROG_READY 0x3
+#define RSU_PROG_AUTHENTICATING0x4
+#define RSU_PROG_COPYING   0x5
+#define RSU_PROG_UPDATE_CANCEL 0x6
+#define RSU_PROG_PROGRAM_KEY_HASH  0x7
+#define RSU_PROG_RSU_DONE  0x8
+#define RSU_PROG_PKVL_PROM_DONE0x9
+
+/* Device and error states */
+#define RSU_STAT_NORMAL0x0
+#define RSU_STAT_TIMEOUT   0x1
+#define RSU_STAT_AUTH_FAIL 0x2
+#define RSU_STAT_COPY_FAIL 0x3
+#define RSU_STAT_FATAL 0x4
+#define RSU_STAT_PKVL_REJECT   0x5
+#define RSU_STAT_NON_INC   0x6
+#define RSU_STAT_ERASE_FAIL0x7
+#define RSU_STAT_WEAROUT   0x8
+#define RSU_STAT_NIOS_OK   0x80
+#define RSU_STAT_USER_OK   0x81
+#define RSU_STAT_FACTORY_OK0x82
+#define RSU_STAT_USER_FAIL 0x83
+#define RSU_STAT_FACTORY_FAIL  0x84
+#define RSU_STAT_NIOS_FLASH_ERR0x85
+#define RSU_STAT_FPGA_FLASH_ERR0x86
+
+#define HOST_STATUS_IDLE   0x0
+#define HOST_STATUS_WRITE_DONE 0x1
+#define HOST_STATUS_ABORT_RSU  0x2
+
+#define rsu_prog(doorbell) FIELD_GET(DRBL_RSU_PROGRESS, doorbell)
+#define rsu_stat(doorbell) FIELD_GET(DRBL_RSU_STATUS, doorbell)
+
+/* interval 100ms and timeout 5s */
+#define NIOS_HANDSHAKE_INTERVAL_US (100 * 1000)
+#define NIOS_HANDSHAKE_TIMEOUT_US  (5 * 1000 * 1000)
+
+/* RSU PREP Timeout (2 minutes) to erase flash staging area */
+#define RSU_PREP_INTERVAL_MS   100
+#define RSU_PREP_TIMEOUT_MS(2 * 60 * 1000)
+
+/* RSU Complete Timeout (40 minutes) for full flash update */
+#define RSU_COMPLETE_INTERVAL_MS   1000
+#define RSU_COMPLETE_TIMEOUT_MS(40 * 60 * 1000)
+
+/* Addresses for security related data in FLASH */
+#define BMC_REH_ADDR   0x17ffc004
+#define BMC_PROG_ADDR  0x17ffc000
+#define BMC_PROG_MAGIC 0x5746
+
+#define SR_REH_ADDR0x17ffd004
+#define SR_PROG_ADDR   0x17ffd000
+#define SR_PROG_MAGIC  0x5253
+
+#define PR_REH_ADDR0x17ffe004
+#define PR_PROG_ADDR   0x17ffe000
+#define PR_PROG_MAGIC  0x5250
+
+/* Address of 4KB inverted bit vector containing staging area FLASH count */
+#define STAGING_FLASH_COUNT0x17ffb000
+
 /**
  * struct intel_m10bmc - Intel MAX 10 BMC parent driver data structure
  * @dev: this device
-- 
2.25.1



[PATCH v9 4/7] fpga: sec-mgr: expose sec-mgr update errors

2021-01-05 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an update/error sysfs node that can be read for error
information when a secure update fails.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the error_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Use dev_err() for invalid error code in sec_error()
v2:
  - Bumped documentation date and version
  - Added warning to sec_progress() for invalid progress status
  - Added sec_error() function (similar to sec_progress())
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 17 
 drivers/fpga/fpga-sec-mgr.c   | 83 ---
 include/linux/fpga/fpga-sec-mgr.h |  1 +
 3 files changed, 89 insertions(+), 12 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 703e123a1d42..ee8552518f56 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -27,3 +27,20 @@ Description: Read-only. Returns a string describing the 
current
programming. Userspace code can poll on this file,
as it will be signaled by sysfs_notify() on each
state change.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/error
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read-only. Returns a string describing the failure
+   of a secure update. This string will be in the form
+   of :, where  will be one of
+   the status strings described for the status sysfs
+   file and  will be one of the following:
+   hw-error, timeout, user-abort, device-busy,
+   invalid-file-size, read-write-error, flash-wearout,
+   file-read-error.  The error sysfs file is only
+   meaningful when the secure update engine is in the
+   idle state. If this file is read while a secure
+   update is in progress, then the read will fail with
+   EBUSY.
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index dd60014b7511..3bd89598cccd 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -32,10 +32,16 @@ static void update_progress(struct fpga_sec_mgr *smgr,
sysfs_notify(>dev.kobj, "update", "status");
 }
 
+static void set_error(struct fpga_sec_mgr *smgr, enum fpga_sec_err err_code)
+{
+   smgr->err_state = smgr->progress;
+   smgr->err_code = err_code;
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
-   smgr->err_code = err_code;
+   set_error(smgr, err_code);
smgr->sops->cancel(smgr);
 }
 
@@ -58,7 +64,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
 
get_device(>dev);
if (request_firmware(, smgr->filename, >dev)) {
-   smgr->err_code = FPGA_SEC_ERR_FILE_READ;
+   set_error(smgr, FPGA_SEC_ERR_FILE_READ);
goto idle_exit;
}
 
@@ -66,7 +72,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
smgr->remaining_size = fw->size;
 
if (!try_module_get(smgr->dev.parent->driver->owner)) {
-   smgr->err_code = FPGA_SEC_ERR_BUSY;
+   set_error(smgr, FPGA_SEC_ERR_BUSY);
goto release_fw_exit;
}
 
@@ -128,24 +134,76 @@ static const char * const sec_mgr_prog_str[] = {
"programming"   /* FPGA_SEC_PROG_PROGRAMMING */
 };
 
-static ssize_t
-status_show(struct device *dev, struct device_attribute *attr, char *buf)
+static const char * const sec_mgr_err_str[] = {
+   "none", /* FPGA_SEC_ERR_NONE */
+   "hw-error", /* FPGA_SEC_ERR_HW_ERROR */
+   "timeout",  /* FPGA_SEC_ERR_TIMEOUT */
+   "user-abort",   /* FPGA_SEC_ERR_CANCELED */
+   "device-busy",  /* FPGA_SEC_ERR_BUSY */
+   "invalid-file-size",/* FPGA_SEC_ERR_INVALID_SIZE */
+   "read-write-error", /* FPGA_SEC_ERR_RW_ERROR */
+   "flash-wearout",/* FPGA_SEC_ERR_WEAROUT */
+   "file-read-error"   /* FPGA_SEC_ERR_FILE_READ */
+};
+
+static const char *sec_progress(struct device *dev, enum fpga_sec_prog prog)
 {
-   struct fpga_sec_mgr *smgr = to_sec_mgr(dev);

[PATCH v9 5/7] fpga: sec-mgr: expose sec-mgr update size

2021-01-05 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an update/remaining_size sysfs node that can be read to
determine how much data remains to be transferred to the
secure update engine. This file can be used to monitor
progress during the "writing" phase of an update.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the remaining_size_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: imgr -> smgr, ifpga_ to fpga_
v3:
  - No change
v2:
  - Bumped documentation date and version
---
 Documentation/ABI/testing/sysfs-class-fpga-sec-mgr | 11 +++
 drivers/fpga/fpga-sec-mgr.c| 10 ++
 2 files changed, 21 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index ee8552518f56..150b137a6246 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -28,6 +28,17 @@ Description: Read-only. Returns a string describing the 
current
as it will be signaled by sysfs_notify() on each
state change.
 
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/remaining_size
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read-only. Returns the size of data that remains to
+   be written to the secure update engine. The size
+   value is initialized to the full size of the file
+   image and the value is updated periodically during
+   the "writing" phase of the update.
+   Format: "%u".
+
 What:  /sys/class/fpga_sec_mgr/fpga_secX/update/error
 Date:  January 2021
 KernelVersion:  5.12
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 3bd89598cccd..951020942991 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -204,6 +204,15 @@ error_show(struct device *dev, struct device_attribute 
*attr, char *buf)
 }
 static DEVICE_ATTR_RO(error);
 
+static ssize_t remaining_size_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
+
+   return sysfs_emit(buf, "%u\n", smgr->remaining_size);
+}
+static DEVICE_ATTR_RO(remaining_size);
+
 static ssize_t filename_store(struct device *dev, struct device_attribute 
*attr,
  const char *buf, size_t count)
 {
@@ -240,6 +249,7 @@ static struct attribute *sec_mgr_update_attrs[] = {
_attr_filename.attr,
_attr_status.attr,
_attr_error.attr,
+   _attr_remaining_size.attr,
NULL,
 };
 
-- 
2.25.1



[PATCH v9 7/7] fpga: sec-mgr: expose hardware error info

2021-01-05 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an optional update/hw_errinfo sysfs node that can be used
to retrieve 64 bits of device specific error information
following a secure update failure.

The underlying driver must provide a get_hw_errinfo() callback
function to enable this feature. This data is treated as
opaque by the class driver. It is left to user-space software
or support personnel to interpret this data.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - No change
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - No change
v2:
  - Bumped documentation date and version
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 14 +++
 drivers/fpga/fpga-sec-mgr.c   | 38 +++
 include/linux/fpga/fpga-sec-mgr.h |  5 +++
 3 files changed, 57 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index af323a58bdda..c7ff2c1f4400 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -65,3 +65,17 @@ Description: Read-only. Returns a string describing the 
failure
idle state. If this file is read while a secure
update is in progress, then the read will fail with
EBUSY.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/hw_errinfo
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read-only. Returns a 64 bit error value providing
+   hardware specific information that may be useful in
+   debugging errors that occur during FPGA image updates.
+   This file is only visible if the underlying device
+   supports it. The hw_errinfo value is only accessible
+   when the secure update engine is in the idle state.
+   If this file is read while a secure update is in
+   progress, then the read will fail with EBUSY.
+   Format: "0x%llx".
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index d354fe2ab582..aebe06d9a54a 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -38,10 +38,17 @@ static void set_error(struct fpga_sec_mgr *smgr, enum 
fpga_sec_err err_code)
smgr->err_code = err_code;
 }
 
+static void set_hw_errinfo(struct fpga_sec_mgr *smgr)
+{
+   if (smgr->sops->get_hw_errinfo)
+   smgr->hw_errinfo = smgr->sops->get_hw_errinfo(smgr);
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
set_error(smgr, err_code);
+   set_hw_errinfo(smgr);
smgr->sops->cancel(smgr);
 }
 
@@ -227,6 +234,23 @@ error_show(struct device *dev, struct device_attribute 
*attr, char *buf)
 }
 static DEVICE_ATTR_RO(error);
 
+static ssize_t
+hw_errinfo_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
+   int ret;
+
+   mutex_lock(>lock);
+   if (smgr->progress != FPGA_SEC_PROG_IDLE)
+   ret = -EBUSY;
+   else
+   ret = sysfs_emit(buf, "0x%llx\n", smgr->hw_errinfo);
+   mutex_unlock(>lock);
+
+   return ret;
+}
+static DEVICE_ATTR_RO(hw_errinfo);
+
 static ssize_t remaining_size_show(struct device *dev,
   struct device_attribute *attr, char *buf)
 {
@@ -258,6 +282,7 @@ static ssize_t filename_store(struct device *dev, struct 
device_attribute *attr,
}
 
smgr->err_code = FPGA_SEC_ERR_NONE;
+   smgr->hw_errinfo = 0;
smgr->request_cancel = false;
smgr->progress = FPGA_SEC_PROG_READING;
reinit_completion(>update_done);
@@ -292,18 +317,31 @@ static ssize_t cancel_store(struct device *dev, struct 
device_attribute *attr,
 }
 static DEVICE_ATTR_WO(cancel);
 
+static umode_t
+sec_mgr_update_visible(struct kobject *kobj, struct attribute *attr, int n)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(kobj_to_dev(kobj));
+
+   if (attr == _attr_hw_errinfo.attr && !smgr->sops->get_hw_errinfo)
+   return 0;
+
+   return attr->mode;
+}
+
 static struct attribute *sec_mgr_update_attrs[] = {
_attr_filename.attr,
_attr_cancel.attr,
_attr_status.attr,
_attr_error.attr,
_attr_remaining_size.attr,
+   _attr_hw_errinfo.attr,
NULL,
 };
 
 static struct attribute_group sec_mgr_update_at

[PATCH v9 3/7] fpga: sec-mgr: expose sec-mgr update status

2021-01-05 Thread Russ Weight
Extend the FPGA Security Manager class driver to
include an update/status sysfs node that can be polled
and read to monitor the progress of an ongoing secure
update. Sysfs_notify() is used to signal transitions
between different phases of the update process.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the status_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Use a local variable to read progress once in status_show()
  - Use dev_err to report invalid progress status
v2:
  - Bumped documentation date and version
  - Changed progress state "read_file" to "reading"
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 11 +
 drivers/fpga/fpga-sec-mgr.c   | 42 +--
 2 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index d5839fbcd71b..703e123a1d42 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -16,3 +16,14 @@ Description: Write only. Write the filename of an image
BMC images, BMC firmware, Static Region images,
and Root Entry Hashes, and to cancel Code Signing
Keys (CSK).
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/status
+Date:      January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read-only. Returns a string describing the current
+   status of an update. The string will be one of the
+   following: idle, reading, preparing, writing,
+   programming. Userspace code can poll on this file,
+   as it will be signaled by sysfs_notify() on each
+   state change.
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 7347ba1ba73e..dd60014b7511 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -25,6 +25,13 @@ struct fpga_sec_mgr_devres {
 
 #define to_sec_mgr(d) container_of(d, struct fpga_sec_mgr, dev)
 
+static void update_progress(struct fpga_sec_mgr *smgr,
+   enum fpga_sec_prog new_progress)
+{
+   smgr->progress = new_progress;
+   sysfs_notify(>dev.kobj, "update", "status");
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
@@ -35,7 +42,7 @@ static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
 static void progress_complete(struct fpga_sec_mgr *smgr)
 {
mutex_lock(>lock);
-   smgr->progress = FPGA_SEC_PROG_IDLE;
+   update_progress(smgr, FPGA_SEC_PROG_IDLE);
complete_all(>update_done);
mutex_unlock(>lock);
 }
@@ -63,14 +70,14 @@ static void fpga_sec_mgr_update(struct work_struct *work)
goto release_fw_exit;
}
 
-   smgr->progress = FPGA_SEC_PROG_PREPARING;
+   update_progress(smgr, FPGA_SEC_PROG_PREPARING);
ret = smgr->sops->prepare(smgr);
if (ret != FPGA_SEC_ERR_NONE) {
fpga_sec_dev_error(smgr, ret);
goto modput_exit;
}
 
-   smgr->progress = FPGA_SEC_PROG_WRITING;
+   update_progress(smgr, FPGA_SEC_PROG_WRITING);
size = smgr->remaining_size;
while (size) {
blk_size = min_t(u32, size, WRITE_BLOCK_SIZE);
@@ -85,7 +92,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
offset += blk_size;
}
 
-   smgr->progress = FPGA_SEC_PROG_PROGRAMMING;
+   update_progress(smgr, FPGA_SEC_PROG_PROGRAMMING);
ret = smgr->sops->poll_complete(smgr);
if (ret != FPGA_SEC_ERR_NONE)
fpga_sec_dev_error(smgr, ret);
@@ -113,6 +120,32 @@ static void fpga_sec_mgr_update(struct work_struct *work)
progress_complete(smgr);
 }
 
+static const char * const sec_mgr_prog_str[] = {
+   "idle", /* FPGA_SEC_PROG_IDLE */
+   "reading",  /* FPGA_SEC_PROG_READING */
+   "preparing",/* FPGA_SEC_PROG_PREPARING */
+   "writing",  /* FPGA_SEC_PROG_WRITING */
+   "programming"   /* FPGA_SEC_PROG_PROGRAMMING */
+};
+
+static ssize_t
+status_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
+   const char *status = "unknown-status";
+   enum fpga_sec_prog progre

[PATCH v9 1/7] fpga: sec-mgr: fpga security manager class driver

2021-01-05 Thread Russ Weight
Create the FPGA Security Manager class driver. The security
manager provides interfaces to manage secure updates for the
FPGA and BMC images that are stored in FLASH. The driver can
also be used to update root entry hashes and to cancel code
signing keys. The image type is encoded in the image file
and is decoded by the HW/FW secure update engine.

Signed-off-by: Russ Weight 
Signed-off-by: Xu Yilun 
Reviewed-by: Tom Rix 
---
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - Fixed grammatical error in Documentation/fpga/fpga-sec-mgr.rst
v7:
  - Changed Date in documentation file to December 2020
v6:
  - Removed sysfs support and documentation for the display of the
flash count, root entry hashes, and code-signing-key cancelation
vectors.
v5:
  - Added the devm_fpga_sec_mgr_unregister() function, following recent
changes to the fpga_manager() implementation.
  - Changed some *_show() functions to use sysfs_emit() instead of sprintf(
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Modified sysfs handler check in check_sysfs_handler() to make
it more readable.
v2:
  - Bumped documentation dates and versions
  - Added Documentation/fpga/ifpga-sec-mgr.rst 
  - Removed references to bmc_flash_count & smbus_flash_count (not supported)
  - Split ifpga_sec_mgr_register() into create() and register() functions
  - Added devm_ifpga_sec_mgr_create()
  - Removed typedefs for imgr ops
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  |   5 +
 Documentation/fpga/fpga-sec-mgr.rst   |  44 +++
 Documentation/fpga/index.rst  |   1 +
 MAINTAINERS   |   9 +
 drivers/fpga/Kconfig  |   9 +
 drivers/fpga/Makefile |   3 +
 drivers/fpga/fpga-sec-mgr.c   | 296 ++
 include/linux/fpga/fpga-sec-mgr.h |  44 +++
 8 files changed, 411 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
 create mode 100644 Documentation/fpga/fpga-sec-mgr.rst
 create mode 100644 drivers/fpga/fpga-sec-mgr.c
 create mode 100644 include/linux/fpga/fpga-sec-mgr.h

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
new file mode 100644
index ..9457612ebdbd
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -0,0 +1,5 @@
+What:  /sys/class/fpga_sec_mgr/fpga_secX/name
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Name of low level fpga security manager driver.
diff --git a/Documentation/fpga/fpga-sec-mgr.rst 
b/Documentation/fpga/fpga-sec-mgr.rst
new file mode 100644
index ..9f74c29fe63d
--- /dev/null
+++ b/Documentation/fpga/fpga-sec-mgr.rst
@@ -0,0 +1,44 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+
+FPGA Security Manager Class Driver
+
+
+The FPGA Security Manager class driver provides a common
+API for user-space tools to manage updates for secure FPGA
+devices. Device drivers that instantiate the Security
+Manager class driver will interact with a HW secure update
+engine in order to transfer new FPGA and BMC images to FLASH so
+that they will be automatically loaded when the FPGA card reboots.
+
+A significant difference between the FPGA Manager and the FPGA
+Security Manager is that the FPGA Manager does a live update (Partial
+Reconfiguration) to a device, whereas the FPGA Security Manager
+updates the FLASH images for the Static Region and the BMC so that
+they will be loaded the next time the FPGA card boots. Security is
+enforced by hardware and firmware. The security manager interacts
+with the firmware to initiate an update, pass in the necessary data,
+and collect status on the update.
+
+In addition to managing secure updates of the FPGA and BMC images,
+the FPGA Security Manager update process may also be used to
+program root entry hashes and cancellation keys for the FPGA static
+region, the FPGA partial reconfiguration region, and the BMC.
+
+Secure updates make use of the request_firmware framework, which
+requires that image files are accessible under /lib/firmware. A request
+for a secure update returns immediately, while the update itself
+proceeds in the context of a kernel worker thread. Sysfs files provide
+a means for monitoring the progress of a secure update and for
+retrieving error information in the event of a failure.
+
+Sysfs Attributes
+
+
+The API includes a sysfs entry *name* to export the name of the parent
+driver. It also includes an *update* sub-directory that can be used to
+instantiate and monitor a secure update.
+
+See `<../ABI/testing/sysfs-class

[PATCH v9 2/7] fpga: sec-mgr: enable secure updates

2021-01-05 Thread Russ Weight
Extend the FPGA Security Manager class driver to
include an update/filename sysfs node that can be used
to initiate a secure update.  The filename of a secure
update file (BMC image, FPGA image, Root Entry Hash image,
or Code Signing Key cancellation image) can be written to
this sysfs entry to cause a secure update to occur.

The write of the filename will return immediately, and the
update will begin in the context of a kernel worker thread.
This tool utilizes the request_firmware framework, which
requires that the image file reside under /lib/firmware.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
  - Changed filename_store() to use kmemdup_nul() instead of
kstrndup() and changed the count to not assume a line-return.
v6:
  - Changed "security update" to "secure update" in commit message
v5:
  - When checking the return values for functions of type enum
fpga_sec_err err_code, test for FPGA_SEC_ERR_NONE instead of 0
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Removed unnecessary "goto done"
  - Added a comment to explain imgr->driver_unload in
ifpga_sec_mgr_unregister()
v2:
  - Bumped documentation date and version
  - Removed explicit value assignments in enums
  - Other minor code cleanup per review comments 
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  |  13 ++
 drivers/fpga/fpga-sec-mgr.c   | 164 ++
 include/linux/fpga/fpga-sec-mgr.h |  49 ++
 3 files changed, 226 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 9457612ebdbd..d5839fbcd71b 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -3,3 +3,16 @@ Date:  January 2021
 KernelVersion:  5.12
 Contact:   Russ Weight 
 Description:   Name of low level fpga security manager driver.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/filename
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Write only. Write the filename of an image
+   file to this sysfs file to initiate a secure
+   update. The file must have an appropriate header
+   which, among other things, identifies the target
+   for the update. This mechanism is used to update
+   BMC images, BMC firmware, Static Region images,
+   and Root Entry Hashes, and to cancel Code Signing
+   Keys (CSK).
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 468379e0c825..7347ba1ba73e 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -5,8 +5,11 @@
  * Copyright (C) 2019-2020 Intel Corporation, Inc.
  */
 
+#include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -18,8 +21,140 @@ struct fpga_sec_mgr_devres {
struct fpga_sec_mgr *smgr;
 };
 
+#define WRITE_BLOCK_SIZE 0x4000/* Update remaining_size every 0x4000 
bytes */
+
 #define to_sec_mgr(d) container_of(d, struct fpga_sec_mgr, dev)
 
+static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
+  enum fpga_sec_err err_code)
+{
+   smgr->err_code = err_code;
+   smgr->sops->cancel(smgr);
+}
+
+static void progress_complete(struct fpga_sec_mgr *smgr)
+{
+   mutex_lock(>lock);
+   smgr->progress = FPGA_SEC_PROG_IDLE;
+   complete_all(>update_done);
+   mutex_unlock(>lock);
+}
+
+static void fpga_sec_mgr_update(struct work_struct *work)
+{
+   u32 size, blk_size, offset = 0;
+   struct fpga_sec_mgr *smgr;
+   const struct firmware *fw;
+   enum fpga_sec_err ret;
+
+   smgr = container_of(work, struct fpga_sec_mgr, work);
+
+   get_device(>dev);
+   if (request_firmware(, smgr->filename, >dev)) {
+   smgr->err_code = FPGA_SEC_ERR_FILE_READ;
+   goto idle_exit;
+   }
+
+   smgr->data = fw->data;
+   smgr->remaining_size = fw->size;
+
+   if (!try_module_get(smgr->dev.parent->driver->owner)) {
+   smgr->err_code = FPGA_SEC_ERR_BUSY;
+   goto release_fw_exit;
+   }
+
+   smgr->progress = FPGA_SEC_PROG_PREPARING;
+   ret = smgr->sops->prepare(smgr);
+   if (ret != FPGA_SEC_ERR_NONE) {
+   fpga_sec_dev_error(smgr, ret);
+   goto modput_exit;
+   }
+
+   smgr->progress = FPGA_SEC_PROG_WRITING;
+   size = smgr->remaining_size;
+   while (size) {
+ 

[PATCH v9 6/7] fpga: sec-mgr: enable cancel of secure update

2021-01-05 Thread Russ Weight
Extend the FPGA Security Manager class driver to include
an update/cancel sysfs file that can be written to request
that an update be canceled. The write may return EBUSY if
the update has progressed to the point that it cannot be
canceled by software or ENODEV if there is no update in
progress.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v9:
  - Updated Date and KernelVersion in ABI documentation
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - No change
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - No change
v2:
  - Bumped documentation date and version
  - Minor code cleanup per review comments 
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 10 
 drivers/fpga/fpga-sec-mgr.c   | 59 +--
 include/linux/fpga/fpga-sec-mgr.h |  1 +
 3 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index 150b137a6246..af323a58bdda 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -17,6 +17,16 @@ Description: Write only. Write the filename of an image
and Root Entry Hashes, and to cancel Code Signing
Keys (CSK).
 
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/cancel
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Write-only. Write a "1" to this file to request
+   that a current update be canceled. This request
+   will be rejected (EBUSY) if the programming phase
+   has already started or (ENODEV) if there is no
+   update in progress.
+
 What:  /sys/class/fpga_sec_mgr/fpga_secX/update/status
 Date:  January 2021
 KernelVersion:  5.12
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 951020942991..d354fe2ab582 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -45,6 +45,23 @@ static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
smgr->sops->cancel(smgr);
 }
 
+static int progress_transition(struct fpga_sec_mgr *smgr,
+  enum fpga_sec_prog new_progress)
+{
+   int ret = 0;
+
+   mutex_lock(>lock);
+   if (smgr->request_cancel) {
+   set_error(smgr, FPGA_SEC_ERR_CANCELED);
+   smgr->sops->cancel(smgr);
+   ret = -ECANCELED;
+   } else {
+   update_progress(smgr, new_progress);
+   }
+   mutex_unlock(>lock);
+   return ret;
+}
+
 static void progress_complete(struct fpga_sec_mgr *smgr)
 {
mutex_lock(>lock);
@@ -76,16 +93,20 @@ static void fpga_sec_mgr_update(struct work_struct *work)
goto release_fw_exit;
}
 
-   update_progress(smgr, FPGA_SEC_PROG_PREPARING);
+   if (progress_transition(smgr, FPGA_SEC_PROG_PREPARING))
+   goto modput_exit;
+
ret = smgr->sops->prepare(smgr);
if (ret != FPGA_SEC_ERR_NONE) {
fpga_sec_dev_error(smgr, ret);
goto modput_exit;
}
 
-   update_progress(smgr, FPGA_SEC_PROG_WRITING);
+   if (progress_transition(smgr, FPGA_SEC_PROG_WRITING))
+   goto done;
+
size = smgr->remaining_size;
-   while (size) {
+   while (size && !smgr->request_cancel) {
blk_size = min_t(u32, size, WRITE_BLOCK_SIZE);
size -= blk_size;
ret = smgr->sops->write_blk(smgr, offset, blk_size);
@@ -98,7 +119,9 @@ static void fpga_sec_mgr_update(struct work_struct *work)
offset += blk_size;
}
 
-   update_progress(smgr, FPGA_SEC_PROG_PROGRAMMING);
+   if (progress_transition(smgr, FPGA_SEC_PROG_PROGRAMMING))
+   goto done;
+
ret = smgr->sops->poll_complete(smgr);
if (ret != FPGA_SEC_ERR_NONE)
fpga_sec_dev_error(smgr, ret);
@@ -235,6 +258,7 @@ static ssize_t filename_store(struct device *dev, struct 
device_attribute *attr,
}
 
smgr->err_code = FPGA_SEC_ERR_NONE;
+   smgr->request_cancel = false;
smgr->progress = FPGA_SEC_PROG_READING;
reinit_completion(>update_done);
schedule_work(>work);
@@ -245,8 +269,32 @@ static ssize_t filename_store(struct device *dev, struct 
device_attribute *attr,
 }
 static DEVICE_ATTR_WO(filename);
 
+static ssize_t cancel_store(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
+

[PATCH v9 0/7] FPGA Security Manager Class Driver

2021-01-05 Thread Russ Weight
The FPGA Security Manager class driver provides a common
API for user-space tools to manage updates for secure FPGA
devices. Device drivers that instantiate the FPGA Security
Manager class driver will interact with a HW secure update
engine in order to transfer new FPGA and BMC images to FLASH so
that they will be automatically loaded when the FPGA card reboots.

A significant difference between the FPGA Manager and the FPGA 
Security Manager is that the FPGA Manager does a live update (Partial
Reconfiguration) to a device whereas the FPGA Security Manager
updates the FLASH images for the Static Region and the BMC so that
they will be loaded the next time the FPGA card boots. Security is
enforced by hardware and firmware. The security manager interacts
with the firmware to initiate an update, pass in the necessary data,
and collect status on the update.

The n3000bmc-secure driver is the first driver to use the FPGA
Security Manager. This driver was previously submitted in the same
patch set, but has been split out into a separate patch set starting
with V2. Future devices will also make use of this common API for
secure updates.

In addition to managing secure updates of the FPGA and BMC images,
the FPGA Security Manager update process may also be used to
program root entry hashes and cancellation keys for the FPGA static
region, the FPGA partial reconfiguration region, and the BMC.
The image files are self-describing, and contain a header describing
the image type.

Secure updates make use of the request_firmware framework, which
requires that image files are accessible under /lib/firmware. A request
for a secure update returns immediately, while the update itself
proceeds in the context of a kernel worker thread. Sysfs files provide
a means for monitoring the progress of a secure update and for
retrieving error information in the event of a failure.

The API includes a "name" sysfs file to export the name of the parent
driver. It also includes an "update" sub-directory containing files that
that can be used to instantiate and monitor a secure update.

Changelog v8 -> v9:
  - Rebased patches for 5.11-rc2
  - Updated Date and KernelVersion in ABI documentation

Changelog v7 -> v8:
  - Fixed grammatical error in Documentation/fpga/fpga-sec-mgr.rst

Changelog v6 -> v7:
  - Changed dates in documentation file to December 2020
  - Changed filename_store() to use kmemdup_nul() instead of
kstrndup() and changed the count to not assume a line-return.

Changelog v5 -> v6:
  - Removed sysfs support and documentation for the display of the
flash count, root entry hashes, and code-signing-key cancelation
vectors from the class driver. This information can vary by device
and will instead be displayed by the device-specific parent driver.

Changelog v4 -> v5:
  - Added the devm_fpga_sec_mgr_unregister() function, following recent
changes to the fpga_manager() implementation.
  - Changed most of the *_show() functions to use sysfs_emit()
instead of sprintf(
  - When checking the return values for functions of type enum
fpga_sec_err err_code, test for FPGA_SEC_ERR_NONE instead of 0

Changelog v3 -> v4:
  - This driver is generic enough that it could be used for non Intel
FPGA devices. Changed from "Intel FPGA Security Manager" to FPGA
Security Manager" and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
Note that this also affects some filenames.

Changelog v2 -> v3:
  - Use dev_err() to report invalid progress in sec_progress()
  - Use dev_err() to report invalid error code in sec_error()
  - Modified sysfs handler check in check_sysfs_handler() to make
it more readable.
  - Removed unnecessary "goto done"
  - Added a comment to explain imgr->driver_unload in
ifpga_sec_mgr_unregister()

Changelog v1 -> v2:
  - Separated out the MAX10 BMC Security Engine to be submitted in
a separate patch-set.
  - Bumped documentation dates and versions
  - Split ifpga_sec_mgr_register() into create() and register() functions
  - Added devm_ifpga_sec_mgr_create()
  - Added Documentation/fpga/ifpga-sec-mgr.rst 
  - Changed progress state "read_file" to "reading"
  - Added sec_error() function (similar to sec_progress())
  - Removed references to bmc_flash_count & smbus_flash_count (not supported)
  - Removed typedefs for imgr ops
  - Removed explicit value assignments in enums
  - Other minor code cleanup per review comments 

Russ Weight (7):
  fpga: sec-mgr: fpga security manager class driver
  fpga: sec-mgr: enable secure updates
  fpga: sec-mgr: expose sec-mgr update status
  fpga: sec-mgr: expose sec-mgr update errors
  fpga: sec-mgr: expose sec-mgr update size
  fpga: sec-mgr: enable cancel of secure update
  fpga: sec-mgr: expose hardware error info

 .../ABI/testing/sysfs-clas

[PATCH v3 1/1] mfd: intel-m10-bmc: expose mac address and count

2021-01-05 Thread Russ Weight
Create two sysfs entries for exposing the MAC address
and count from the MAX10 BMC register space. The MAC
address is the first in a sequential block of MAC addresses
reserved for the FPGA card. The MAC count is the number
of MAC addresses in the reserved block.

Signed-off-by: Russ Weight 
Signed-off-by: Xu Yilun 
---
v3:
  - Updated Date and KernelVersion in ABI documentation
v2:
  - Updated the documentation for the mac_address and mac_count
sysfs nodes to clarify their usage.
  - Changed sysfs _show() functions to use sysfs_emit() instead
of sprintf.
---
 .../ABI/testing/sysfs-driver-intel-m10-bmc| 21 +
 drivers/mfd/intel-m10-bmc.c   | 43 +++
 include/linux/mfd/intel-m10-bmc.h |  9 
 3 files changed, 73 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc 
b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
index 979a2d62513f..9773925138af 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
@@ -13,3 +13,24 @@ Contact: Xu Yilun 
 Description:   Read only. Returns the firmware version of Intel MAX10
BMC chip.
Format: "0x%x".
+
+What:  /sys/bus/spi/devices/.../mac_address
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns the first MAC address in a block
+   of sequential MAC addresses assigned to the board
+   that is managed by the Intel MAX10 BMC. It is stored in
+   FLASH storage and is mirrored in the MAX10 BMC register
+   space.
+   Format: "%02x:%02x:%02x:%02x:%02x:%02x".
+
+What:  /sys/bus/spi/devices/.../mac_count
+Date:  January 2021
+KernelVersion:  5.12
+Contact:   Russ Weight 
+Description:   Read only. Returns the number of sequential MAC
+   addresses assigned to the board managed by the Intel
+   MAX10 BMC. This value is stored in FLASH and is mirrored
+   in the MAX10 BMC register space.
+   Format: "%u".
diff --git a/drivers/mfd/intel-m10-bmc.c b/drivers/mfd/intel-m10-bmc.c
index b84579b7b4f0..751c0ecf95d6 100644
--- a/drivers/mfd/intel-m10-bmc.c
+++ b/drivers/mfd/intel-m10-bmc.c
@@ -60,9 +60,52 @@ static ssize_t bmcfw_version_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(bmcfw_version);
 
+static ssize_t mac_address_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct intel_m10bmc *max10 = dev_get_drvdata(dev);
+   unsigned int macaddr1, macaddr2;
+   int ret;
+
+   ret = m10bmc_sys_read(max10, M10BMC_MACADDR1, );
+   if (ret)
+   return ret;
+
+   ret = m10bmc_sys_read(max10, M10BMC_MACADDR2, );
+   if (ret)
+   return ret;
+
+   return sysfs_emit(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ (u8)FIELD_GET(M10BMC_MAC_BYTE1, macaddr1),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE2, macaddr1),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE3, macaddr1),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE4, macaddr1),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE5, macaddr2),
+ (u8)FIELD_GET(M10BMC_MAC_BYTE6, macaddr2));
+}
+static DEVICE_ATTR_RO(mac_address);
+
+static ssize_t mac_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+   struct intel_m10bmc *max10 = dev_get_drvdata(dev);
+   unsigned int macaddr2;
+   int ret;
+
+   ret = m10bmc_sys_read(max10, M10BMC_MACADDR2, );
+   if (ret)
+   return ret;
+
+   return sysfs_emit(buf, "%u\n",
+ (u8)FIELD_GET(M10BMC_MAC_COUNT, macaddr2));
+}
+static DEVICE_ATTR_RO(mac_count);
+
 static struct attribute *m10bmc_attrs[] = {
_attr_bmc_version.attr,
_attr_bmcfw_version.attr,
+   _attr_mac_address.attr,
+   _attr_mac_count.attr,
NULL,
 };
 ATTRIBUTE_GROUPS(m10bmc);
diff --git a/include/linux/mfd/intel-m10-bmc.h 
b/include/linux/mfd/intel-m10-bmc.h
index c8ef2f1654a4..2279e34f0814 100644
--- a/include/linux/mfd/intel-m10-bmc.h
+++ b/include/linux/mfd/intel-m10-bmc.h
@@ -15,6 +15,15 @@
 
 /* Register offset of system registers */
 #define NIOS2_FW_VERSION   0x0
+#define M10BMC_MACADDR10x10
+#define M10BMC_MAC_BYTE4   GENMASK(7, 0)
+#define M10BMC_MAC_BYTE3   GENMASK(15, 8)
+#define M10BMC_MAC_BYTE2   GENMASK(23, 16)
+#define M10BMC_MAC_BYTE1   GENMASK(31, 24)
+#define M10BMC_MACADDR20x14
+#define M10BMC_MAC_BYTE6   GENMASK(7, 0)
+#define M10BMC_MAC_BYTE5   GENMASK(15, 8)
+#define M10BMC_MAC_COUNT 

[PATCH v3 0/1] mfd: intel-m10-bmc: add sysfs files for mac_address

2021-01-05 Thread Russ Weight
Add two sysfs nodes to the Intel MAX10 BMC driver: mac_address
and mac_count. The mac_address provides the first of a series
of sequential MAC addresses assigned to the FPGA card. The
mac_count indicates how many MAC addresses are assigned to the
card.

Changelog v2 -> v3:
  - Updated Date and KernelVersion in ABI documentation

Changelog v1 -> v2:
  - Updated the documentation for the mac_address and mac_count
sysfs nodes to clearify their usage.
  - Changed sysfs _show() functions to use sysfs_emit() instead
of sprintf.

Russ Weight (1):
  mfd: intel-m10-bmc: expose mac address and count

 .../ABI/testing/sysfs-driver-intel-m10-bmc| 21 +
 drivers/mfd/intel-m10-bmc.c   | 43 +++
 include/linux/mfd/intel-m10-bmc.h |  9 
 3 files changed, 73 insertions(+)

-- 
2.25.1



Re: [PATCH v5 2/2] Documentation: fpga: dfl: Add description for DFL UIO support

2021-01-04 Thread Russ Weight



On 1/1/21 7:13 PM, Xu Yilun wrote:
> This patch adds description for UIO support for dfl devices on DFL
> bus.
>
> Signed-off-by: Xu Yilun 
> ---
> v2: no doc in v1, add it for v2.
> v3: some documentation fixes.
> v4: documentation change since the driver matching is changed.
> v5: no change.
> ---
>  Documentation/fpga/dfl.rst | 24 
>  1 file changed, 24 insertions(+)
>
> diff --git a/Documentation/fpga/dfl.rst b/Documentation/fpga/dfl.rst
> index 0404fe6..b8497f3 100644
> --- a/Documentation/fpga/dfl.rst
> +++ b/Documentation/fpga/dfl.rst
> @@ -7,6 +7,7 @@ Authors:
>  - Enno Luebbers 
>  - Xiao Guangrong 
>  - Wu Hao 
> +- Xu Yilun 
>  
>  The Device Feature List (DFL) FPGA framework (and drivers according to
>  this framework) hides the very details of low layer hardwares and provides
> @@ -502,6 +503,29 @@ FME Partial Reconfiguration Sub Feature driver (see 
> drivers/fpga/dfl-fme-pr.c)
>  could be a reference.
>  
>  
> +UIO support for DFL devices
> +===
> +The purpose of an FPGA is to be reprogrammed with newly developed hardware
> +components. New hardware can instantiate a new private feature in the DFL, 
> and
> +then get a DFL device in their system. In some cases users may need a 
> userspace
> +driver for the DFL device:
> +
> +* Users may need to run some diagnostic test for their hardwares.
> +* Users may prototype the kernel driver in user space.
> +* Some hardware is designed for specific purposes and does not fit into one 
> of
> +  the standard kernel subsystems.
> +
> +This requires the direct access to the MMIO space and interrupt handling in
This may be better stated as:

"This requires direct access to MMIO space and interrupt handling from 
userspace."

- Russ

> +userspace. The dfl-uio-pdev module exposes the UIO device interfaces for this
> +purpose. It adds the uio_pdrv_genirq platform device with the resources of
> +the DFL feature, and lets the generic UIO platform device driver provide UIO
> +support to userspace.
> +
> +FPGA_DFL_UIO_PDEV should be selected to enable the dfl-uio-pdev module 
> driver.
> +To support a new DFL feature been directly accessed via UIO, its feature id
> +should be added to the driver's id_table.
> +
> +
>  Open discussion
>  ===
>  FME driver exports one ioctl (DFL_FPGA_FME_PORT_PR) for partial 
> reconfiguration



[PATCH v8 3/7] fpga: sec-mgr: expose sec-mgr update status

2020-12-09 Thread Russ Weight
Extend the FPGA Security Manager class driver to
include an update/status sysfs node that can be polled
and read to monitor the progress of an ongoing secure
update. Sysfs_notify() is used to signal transitions
between different phases of the update process.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
v6:
  - No change
v5:
  - Use new function sysfs_emit() in the status_show() function
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Use a local variable to read progress once in status_show()
  - Use dev_err to report invalid progress status
v2:
  - Bumped documentation date and version
  - Changed progress state "read_file" to "reading"
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  | 11 +
 drivers/fpga/fpga-sec-mgr.c   | 42 +--
 2 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index e9334f986380..d3be25d63a08 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -16,3 +16,14 @@ Description: Write only. Write the filename of an image
BMC images, BMC firmware, Static Region images,
and Root Entry Hashes, and to cancel Code Signing
Keys (CSK).
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/status
+Date:  December 2020
+KernelVersion:  5.11
+Contact:   Russ Weight 
+Description:   Read-only. Returns a string describing the current
+   status of an update. The string will be one of the
+   following: idle, reading, preparing, writing,
+   programming. Userspace code can poll on this file,
+   as it will be signaled by sysfs_notify() on each
+   state change.
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 7347ba1ba73e..dd60014b7511 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -25,6 +25,13 @@ struct fpga_sec_mgr_devres {
 
 #define to_sec_mgr(d) container_of(d, struct fpga_sec_mgr, dev)
 
+static void update_progress(struct fpga_sec_mgr *smgr,
+   enum fpga_sec_prog new_progress)
+{
+   smgr->progress = new_progress;
+   sysfs_notify(>dev.kobj, "update", "status");
+}
+
 static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
   enum fpga_sec_err err_code)
 {
@@ -35,7 +42,7 @@ static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
 static void progress_complete(struct fpga_sec_mgr *smgr)
 {
mutex_lock(>lock);
-   smgr->progress = FPGA_SEC_PROG_IDLE;
+   update_progress(smgr, FPGA_SEC_PROG_IDLE);
complete_all(>update_done);
mutex_unlock(>lock);
 }
@@ -63,14 +70,14 @@ static void fpga_sec_mgr_update(struct work_struct *work)
goto release_fw_exit;
}
 
-   smgr->progress = FPGA_SEC_PROG_PREPARING;
+   update_progress(smgr, FPGA_SEC_PROG_PREPARING);
ret = smgr->sops->prepare(smgr);
if (ret != FPGA_SEC_ERR_NONE) {
fpga_sec_dev_error(smgr, ret);
goto modput_exit;
}
 
-   smgr->progress = FPGA_SEC_PROG_WRITING;
+   update_progress(smgr, FPGA_SEC_PROG_WRITING);
size = smgr->remaining_size;
while (size) {
blk_size = min_t(u32, size, WRITE_BLOCK_SIZE);
@@ -85,7 +92,7 @@ static void fpga_sec_mgr_update(struct work_struct *work)
offset += blk_size;
}
 
-   smgr->progress = FPGA_SEC_PROG_PROGRAMMING;
+   update_progress(smgr, FPGA_SEC_PROG_PROGRAMMING);
ret = smgr->sops->poll_complete(smgr);
if (ret != FPGA_SEC_ERR_NONE)
fpga_sec_dev_error(smgr, ret);
@@ -113,6 +120,32 @@ static void fpga_sec_mgr_update(struct work_struct *work)
progress_complete(smgr);
 }
 
+static const char * const sec_mgr_prog_str[] = {
+   "idle", /* FPGA_SEC_PROG_IDLE */
+   "reading",  /* FPGA_SEC_PROG_READING */
+   "preparing",/* FPGA_SEC_PROG_PREPARING */
+   "writing",  /* FPGA_SEC_PROG_WRITING */
+   "programming"   /* FPGA_SEC_PROG_PROGRAMMING */
+};
+
+static ssize_t
+status_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+   struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
+   const char *status = "unknown-status";
+   enum fpga_sec_prog progress;
+
+   progress = smgr->progress;

[PATCH v8 0/7] FPGA Security Manager Class Driver

2020-12-09 Thread Russ Weight
The FPGA Security Manager class driver provides a common
API for user-space tools to manage updates for secure FPGA
devices. Device drivers that instantiate the FPGA Security
Manager class driver will interact with a HW secure update
engine in order to transfer new FPGA and BMC images to FLASH so
that they will be automatically loaded when the FPGA card reboots.

A significant difference between the FPGA Manager and the FPGA 
Security Manager is that the FPGA Manager does a live update (Partial
Reconfiguration) to a device whereas the FPGA Security Manager
updates the FLASH images for the Static Region and the BMC so that
they will be loaded the next time the FPGA card boots. Security is
enforced by hardware and firmware. The security manager interacts
with the firmware to initiate an update, pass in the necessary data,
and collect status on the update.

The n3000bmc-secure driver is the first driver to use the FPGA
Security Manager. This driver was previously submitted in the same
patch set, but has been split out into a separate patch set starting
with V2. Future devices will also make use of this common API for
secure updates.

In addition to managing secure updates of the FPGA and BMC images,
the FPGA Security Manager update process may also be used to
program root entry hashes and cancellation keys for the FPGA static
region, the FPGA partial reconfiguration region, and the BMC.
The image files are self-describing, and contain a header describing
the image type.

Secure updates make use of the request_firmware framework, which
requires that image files are accessible under /lib/firmware. A request
for a secure update returns immediately, while the update itself
proceeds in the context of a kernel worker thread. Sysfs files provide
a means for monitoring the progress of a secure update and for
retrieving error information in the event of a failure.

The API includes a "name" sysfs file to export the name of the parent
driver. It also includes an "update" sub-directory containing files that
that can be used to instantiate and monitor a secure update.

Changelog v7 -> v8:
  - Fixed grammatical error in Documentation/fpga/fpga-sec-mgr.rst

Changelog v6 -> v7:
  - Changed dates in documentation file to December 2020
  - Changed filename_store() to use kmemdup_nul() instead of
kstrndup() and changed the count to not assume a line-return.

Changelog v5 -> v6:
  - Removed sysfs support and documentation for the display of the
flash count, root entry hashes, and code-signing-key cancelation
vectors from the class driver. This information can vary by device
and will instead be displayed by the device-specific parent driver.

Changelog v4 -> v5:
  - Added the devm_fpga_sec_mgr_unregister() function, following recent
changes to the fpga_manager() implementation.
  - Changed most of the *_show() functions to use sysfs_emit()
instead of sprintf(
  - When checking the return values for functions of type enum
fpga_sec_err err_code, test for FPGA_SEC_ERR_NONE instead of 0

Changelog v3 -> v4:
  - This driver is generic enough that it could be used for non Intel
FPGA devices. Changed from "Intel FPGA Security Manager" to FPGA
Security Manager" and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
Note that this also affects some filenames.

Changelog v2 -> v3:
  - Use dev_err() to report invalid progress in sec_progress()
  - Use dev_err() to report invalid error code in sec_error()
  - Modified sysfs handler check in check_sysfs_handler() to make
it more readable.
  - Removed unnecessary "goto done"
  - Added a comment to explain imgr->driver_unload in
ifpga_sec_mgr_unregister()

Changelog v1 -> v2:
  - Separated out the MAX10 BMC Security Engine to be submitted in
a separate patch-set.
  - Bumped documentation dates and versions
  - Split ifpga_sec_mgr_register() into create() and register() functions
  - Added devm_ifpga_sec_mgr_create()
  - Added Documentation/fpga/ifpga-sec-mgr.rst 
  - Changed progress state "read_file" to "reading"
  - Added sec_error() function (similar to sec_progress())
  - Removed references to bmc_flash_count & smbus_flash_count (not supported)
  - Removed typedefs for imgr ops
  - Removed explicit value assignments in enums
  - Other minor code cleanup per review comments 

Russ Weight (7):
  fpga: sec-mgr: fpga security manager class driver
  fpga: sec-mgr: enable secure updates
  fpga: sec-mgr: expose sec-mgr update status
  fpga: sec-mgr: expose sec-mgr update errors
  fpga: sec-mgr: expose sec-mgr update size
  fpga: sec-mgr: enable cancel of secure update
  fpga: sec-mgr: expose hardware error info

 .../ABI/testing/sysfs-class-fpga-sec-mgr  |  81 +++
 Documentation/fpga/fpga-sec-mgr.rst   |  44 ++
 Documentation/fpga

[PATCH v8 2/7] fpga: sec-mgr: enable secure updates

2020-12-09 Thread Russ Weight
Extend the FPGA Security Manager class driver to
include an update/filename sysfs node that can be used
to initiate a secure update.  The filename of a secure
update file (BMC image, FPGA image, Root Entry Hash image,
or Code Signing Key cancellation image) can be written to
this sysfs entry to cause a secure update to occur.

The write of the filename will return immediately, and the
update will begin in the context of a kernel worker thread.
This tool utilizes the request_firmware framework, which
requires that the image file reside under /lib/firmware.

Signed-off-by: Russ Weight 
Reviewed-by: Tom Rix 
---
v8:
  - No change
v7:
  - Changed Date in documentation file to December 2020
  - Changed filename_store() to use kmemdup_nul() instead of
kstrndup() and changed the count to not assume a line-return.
v6:
  - Changed "security update" to "secure update" in commit message
v5:
  - When checking the return values for functions of type enum
fpga_sec_err err_code, test for FPGA_SEC_ERR_NONE instead of 0
v4:
  - Changed from "Intel FPGA Security Manager" to FPGA Security Manager"
and removed unnecessary references to "Intel".
  - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_
v3:
  - Removed unnecessary "goto done"
  - Added a comment to explain imgr->driver_unload in
ifpga_sec_mgr_unregister()
v2:
  - Bumped documentation date and version
  - Removed explicit value assignments in enums
  - Other minor code cleanup per review comments 
---
 .../ABI/testing/sysfs-class-fpga-sec-mgr  |  13 ++
 drivers/fpga/fpga-sec-mgr.c   | 164 ++
 include/linux/fpga/fpga-sec-mgr.h |  49 ++
 3 files changed, 226 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr 
b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
index f4211981441e..e9334f986380 100644
--- a/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
+++ b/Documentation/ABI/testing/sysfs-class-fpga-sec-mgr
@@ -3,3 +3,16 @@ Date:  December 2020
 KernelVersion:  5.11
 Contact:   Russ Weight 
 Description:   Name of low level fpga security manager driver.
+
+What:  /sys/class/fpga_sec_mgr/fpga_secX/update/filename
+Date:  December 2020
+KernelVersion:  5.11
+Contact:   Russ Weight 
+Description:   Write only. Write the filename of an image
+   file to this sysfs file to initiate a secure
+   update. The file must have an appropriate header
+   which, among other things, identifies the target
+   for the update. This mechanism is used to update
+   BMC images, BMC firmware, Static Region images,
+   and Root Entry Hashes, and to cancel Code Signing
+   Keys (CSK).
diff --git a/drivers/fpga/fpga-sec-mgr.c b/drivers/fpga/fpga-sec-mgr.c
index 468379e0c825..7347ba1ba73e 100644
--- a/drivers/fpga/fpga-sec-mgr.c
+++ b/drivers/fpga/fpga-sec-mgr.c
@@ -5,8 +5,11 @@
  * Copyright (C) 2019-2020 Intel Corporation, Inc.
  */
 
+#include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -18,8 +21,140 @@ struct fpga_sec_mgr_devres {
struct fpga_sec_mgr *smgr;
 };
 
+#define WRITE_BLOCK_SIZE 0x4000/* Update remaining_size every 0x4000 
bytes */
+
 #define to_sec_mgr(d) container_of(d, struct fpga_sec_mgr, dev)
 
+static void fpga_sec_dev_error(struct fpga_sec_mgr *smgr,
+  enum fpga_sec_err err_code)
+{
+   smgr->err_code = err_code;
+   smgr->sops->cancel(smgr);
+}
+
+static void progress_complete(struct fpga_sec_mgr *smgr)
+{
+   mutex_lock(>lock);
+   smgr->progress = FPGA_SEC_PROG_IDLE;
+   complete_all(>update_done);
+   mutex_unlock(>lock);
+}
+
+static void fpga_sec_mgr_update(struct work_struct *work)
+{
+   u32 size, blk_size, offset = 0;
+   struct fpga_sec_mgr *smgr;
+   const struct firmware *fw;
+   enum fpga_sec_err ret;
+
+   smgr = container_of(work, struct fpga_sec_mgr, work);
+
+   get_device(>dev);
+   if (request_firmware(, smgr->filename, >dev)) {
+   smgr->err_code = FPGA_SEC_ERR_FILE_READ;
+   goto idle_exit;
+   }
+
+   smgr->data = fw->data;
+   smgr->remaining_size = fw->size;
+
+   if (!try_module_get(smgr->dev.parent->driver->owner)) {
+   smgr->err_code = FPGA_SEC_ERR_BUSY;
+   goto release_fw_exit;
+   }
+
+   smgr->progress = FPGA_SEC_PROG_PREPARING;
+   ret = smgr->sops->prepare(smgr);
+   if (ret != FPGA_SEC_ERR_NONE) {
+   fpga_sec_dev_error(smgr, ret);
+   goto modput_exit;
+   }
+
+   smgr->progress = FPGA_SEC_PROG_WRITING;
+   size = smgr->remaining_size;
+   while (size) {
+   blk_size = min_t(u32, size, WRITE_

  1   2   3   >