@@ -83,6 +83,15 @@ static inline int fpga_mgr_parse_header(struct fpga_manager *mgr,
return 0;
}
+static inline int fpga_mgr_parse_aes_key(struct fpga_manager *mgr,
+ struct fpga_image_info *info,
+ const char *buf, size_t count)
+{
+ if (mgr->mops->parse_aes_key)
+ return mgr->mops->parse_aes_key(mgr, info, buf, count);
+ return 0;
+}
+
static inline int fpga_mgr_write_init(struct fpga_manager *mgr,
struct fpga_image_info *info,
const char *buf, size_t count)
@@ -559,6 +568,43 @@ static int fpga_mgr_firmware_load(struct fpga_manager *mgr,
return ret;
}
+/**
+ * fpga_mgr_get_aes_key - request aes key form the firmware class
+ * @mgr: fpga manager
+ * @info: fpga image specific information
+ * @image_name: name of image file on the aes key firmware search path
+ *
+ *
+ * Request an aes key image using the firmware class, then Step the low level
+ * fpga manager through the device-specific steps. Update the state before each
+ * step to provide info on what step failed if there is a failure.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+static int fpga_mgr_get_aes_key(struct fpga_manager *mgr,
+ struct fpga_image_info *info,
+ const char *image_name,
+ const struct firmware *fw)
+{
+ struct device *dev = &mgr->dev;
+ int ret;
+
+ dev_info(dev, "Get Aes-key: %s to %s\n", image_name, mgr->name);
+
+ mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ;
+
+ ret = request_firmware(&fw, image_name, dev);
+ if (ret) {
+ mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR;
+ dev_err(dev, "Error requesting firmware %s\n", image_name);
+ return ret;
+ }
+
+ ret = fpga_mgr_parse_aes_key(mgr, info, fw->data, fw->size);
+
+ return ret;
+}
+
/**
* fpga_mgr_load - load FPGA from scatter/gather table, buffer, or firmware
* @mgr: fpga manager
@@ -571,15 +617,41 @@ static int fpga_mgr_firmware_load(struct fpga_manager *mgr,
*/
int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info)
{
+ const struct firmware *fw;
+ int ret;
+
info->header_size = mgr->mops->initial_header_size;
- if (info->sgt)
- return fpga_mgr_buf_load_sg(mgr, info, info->sgt);
- if (info->buf && info->count)
- return fpga_mgr_buf_load(mgr, info, info->buf, info->count);
- if (info->firmware_name)
- return fpga_mgr_firmware_load(mgr, info, info->firmware_name);
- return -EINVAL;
+ if (info->encrypted_key_name) {
+ ret = fpga_mgr_get_aes_key(mgr, info,
+ info->encrypted_key_name, fw);
+ if (ret)
+ return ret;
+
+ info->flags |= FPGA_MGR_USRKEY_ENCRYPTED_BITSTREAM;
+ }
+
+ if (info->sgt) {
+ ret = fpga_mgr_buf_load_sg(mgr, info, info->sgt);
+ if (ret)
+ goto free_fw;
+ } else if (info->buf && info->count) {
+ ret = fpga_mgr_buf_load(mgr, info, info->buf, info->count);
+ if (ret)
+ goto free_fw;
+ } else if (info->firmware_name) {
+ ret = fpga_mgr_firmware_load(mgr, info, info->firmware_name);
+ if (ret)
+ goto free_fw;
+ } else {
+ ret = -EINVAL;
+ }
+
+free_fw:
+ if (info->encrypted_key_name)
+ release_firmware(fw);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(fpga_mgr_load);
@@ -196,6 +196,7 @@ of_fpga_region_parse_ov(struct fpga_region *region,
struct device_node *overlay)
{
struct device *dev = ®ion->dev;
+ const char *encrypted_key_name;
struct fpga_image_info *info;
const char *firmware_name;
int ret;
@@ -238,6 +239,15 @@ of_fpga_region_parse_ov(struct fpga_region *region,
return ERR_PTR(-ENOMEM);
}
+ if (!of_property_read_string(overlay, "encrypted-key-name",
+ &encrypted_key_name)) {
+ info->encrypted_key_name = devm_kstrdup(dev,
+ encrypted_key_name,
+ GFP_KERNEL);
+ if (!info->encrypted_key_name)
+ return ERR_PTR(-ENOMEM);
+ }
+
of_property_read_u32(overlay, "region-unfreeze-timeout-us",
&info->enable_timeout_us);
@@ -71,12 +71,15 @@ enum fpga_mgr_states {
* %FPGA_MGR_BITSTREAM_LSB_FIRST: SPI bitstream bit order is LSB first
*
* %FPGA_MGR_COMPRESSED_BITSTREAM: FPGA bitstream is compressed
+ *
+ * %FPGA_MGR_USRKEY_ENCRYPTED_BITSTREAM: indicates bitstream is encrypted with user-key
*/
#define FPGA_MGR_PARTIAL_RECONFIG BIT(0)
#define FPGA_MGR_EXTERNAL_CONFIG BIT(1)
#define FPGA_MGR_ENCRYPTED_BITSTREAM BIT(2)
#define FPGA_MGR_BITSTREAM_LSB_FIRST BIT(3)
#define FPGA_MGR_COMPRESSED_BITSTREAM BIT(4)
+#define FPGA_MGR_USRKEY_ENCRYPTED_BITSTREAM BIT(5)
/**
* struct fpga_image_info - information specific to an FPGA image
@@ -86,6 +89,7 @@ enum fpga_mgr_states {
* @config_complete_timeout_us: maximum time for FPGA to switch to operating
* status in the write_complete op.
* @firmware_name: name of FPGA image firmware file
+ * @encrypted_key_name: name of the FPGA image encrypted user-key file
* @sgt: scatter/gather table containing FPGA image
* @buf: contiguous buffer containing FPGA image
* @count: size of buf
@@ -102,6 +106,7 @@ struct fpga_image_info {
u32 disable_timeout_us;
u32 config_complete_timeout_us;
char *firmware_name;
+ char *encrypted_key_name;
struct sg_table *sgt;
const char *buf;
size_t count;
@@ -172,6 +177,9 @@ struct fpga_manager_ops {
bool skip_header;
enum fpga_mgr_states (*state)(struct fpga_manager *mgr);
u64 (*status)(struct fpga_manager *mgr);
+ int (*parse_aes_key)(struct fpga_manager *mgr,
+ struct fpga_image_info *info,
+ const char *buf, size_t count);
int (*parse_header)(struct fpga_manager *mgr,
struct fpga_image_info *info,
const char *buf, size_t count);
Adds parse_aes_key() callback to fpga_manager_ops, It will read the AES key from firmware to support user-key encrypted bitstream loading. Signed-off-by: Nava kishore Manne <nava.kishore.manne@amd.com> --- drivers/fpga/fpga-mgr.c | 86 ++++++++++++++++++++++++++++++++--- drivers/fpga/of-fpga-region.c | 10 ++++ include/linux/fpga/fpga-mgr.h | 8 ++++ 3 files changed, 97 insertions(+), 7 deletions(-)