aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0039-crypto-ccp-Add-DOWNLOAD_FIRMWARE-SEV-command.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0039-crypto-ccp-Add-DOWNLOAD_FIRMWARE-SEV-command.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0039-crypto-ccp-Add-DOWNLOAD_FIRMWARE-SEV-command.patch223
1 files changed, 223 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0039-crypto-ccp-Add-DOWNLOAD_FIRMWARE-SEV-command.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0039-crypto-ccp-Add-DOWNLOAD_FIRMWARE-SEV-command.patch
new file mode 100644
index 00000000..73e46ca2
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0039-crypto-ccp-Add-DOWNLOAD_FIRMWARE-SEV-command.patch
@@ -0,0 +1,223 @@
+From 1856c4c431831ab97dce791f992bb70765521965 Mon Sep 17 00:00:00 2001
+From: Janakarajan Natarajan <Janakarajan.Natarajan@amd.com>
+Date: Fri, 25 May 2018 15:23:29 -0500
+Subject: [PATCH 39/95] crypto: ccp - Add DOWNLOAD_FIRMWARE SEV command
+
+The DOWNLOAD_FIRMWARE command, added as of SEV API v0.15, allows the OS
+to install SEV firmware newer than the currently active SEV firmware.
+
+For the new SEV firmware to be applied it must:
+* Pass the validation test performed by the existing firmware.
+* Be of the same build or a newer build compared to the existing firmware.
+
+For more information please refer to "Section 5.11 DOWNLOAD_FIRMWARE" of
+https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf
+
+Signed-off-by: Janakarajan Natarajan <Janakarajan.Natarajan@amd.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
+---
+ drivers/crypto/ccp/psp-dev.c | 99 +++++++++++++++++++++++++++++++++++++++-----
+ drivers/crypto/ccp/psp-dev.h | 4 ++
+ include/linux/psp-sev.h | 12 ++++++
+ 3 files changed, 105 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c
+index d95ec52..12838b4 100644
+--- a/drivers/crypto/ccp/psp-dev.c
++++ b/drivers/crypto/ccp/psp-dev.c
+@@ -22,11 +22,17 @@
+ #include <linux/delay.h>
+ #include <linux/hw_random.h>
+ #include <linux/ccp.h>
++#include <linux/firmware.h>
+
+ #include "sp-dev.h"
+ #include "psp-dev.h"
+
++#define SEV_VERSION_GREATER_OR_EQUAL(_maj, _min) \
++ ((psp_master->api_major) >= _maj && \
++ (psp_master->api_minor) >= _min)
++
+ #define DEVICE_NAME "sev"
++#define SEV_FW_FILE "amd/sev.fw"
+
+ static DEFINE_MUTEX(sev_cmd_mutex);
+ static struct sev_misc_dev *misc_dev;
+@@ -112,6 +118,7 @@ static int sev_cmd_buffer_len(int cmd)
+ case SEV_CMD_RECEIVE_UPDATE_DATA: return sizeof(struct sev_data_receive_update_data);
+ case SEV_CMD_RECEIVE_UPDATE_VMSA: return sizeof(struct sev_data_receive_update_vmsa);
+ case SEV_CMD_LAUNCH_UPDATE_SECRET: return sizeof(struct sev_data_launch_secret);
++ case SEV_CMD_DOWNLOAD_FIRMWARE: return sizeof(struct sev_data_download_firmware);
+ default: return 0;
+ }
+
+@@ -378,6 +385,79 @@ void *psp_copy_user_blob(u64 __user uaddr, u32 len)
+ }
+ EXPORT_SYMBOL_GPL(psp_copy_user_blob);
+
++static int sev_get_api_version(void)
++{
++ struct sev_user_data_status *status;
++ int error, ret;
++
++ status = &psp_master->status_cmd_buf;
++ ret = sev_platform_status(status, &error);
++ if (ret) {
++ dev_err(psp_master->dev,
++ "SEV: failed to get status. Error: %#x\n", error);
++ return 1;
++ }
++
++ psp_master->api_major = status->api_major;
++ psp_master->api_minor = status->api_minor;
++ psp_master->build = status->build;
++
++ return 0;
++}
++
++/* Don't fail if SEV FW couldn't be updated. Continue with existing SEV FW */
++static int sev_update_firmware(struct device *dev)
++{
++ struct sev_data_download_firmware *data;
++ const struct firmware *firmware;
++ int ret, error, order;
++ struct page *p;
++ u64 data_size;
++
++ ret = request_firmware(&firmware, SEV_FW_FILE, dev);
++ if (ret < 0)
++ return -1;
++
++ /*
++ * SEV FW expects the physical address given to it to be 32
++ * byte aligned. Memory allocated has structure placed at the
++ * beginning followed by the firmware being passed to the SEV
++ * FW. Allocate enough memory for data structure + alignment
++ * padding + SEV FW.
++ */
++ data_size = ALIGN(sizeof(struct sev_data_download_firmware), 32);
++
++ order = get_order(firmware->size + data_size);
++ p = alloc_pages(GFP_KERNEL, order);
++ if (!p) {
++ ret = -1;
++ goto fw_err;
++ }
++
++ /*
++ * Copy firmware data to a kernel allocated contiguous
++ * memory region.
++ */
++ data = page_address(p);
++ memcpy(page_address(p) + data_size, firmware->data, firmware->size);
++
++ data->address = __psp_pa(page_address(p) + data_size);
++ data->len = firmware->size;
++
++ ret = sev_do_cmd(SEV_CMD_DOWNLOAD_FIRMWARE, data, &error);
++ if (ret)
++ dev_dbg(dev, "Failed to update SEV firmware: %#x\n", error);
++ else
++ dev_info(dev, "SEV firmware update successful\n");
++
++ __free_pages(p, order);
++
++fw_err:
++ release_firmware(firmware);
++
++ return ret;
++}
++
+ static int sev_ioctl_do_pek_import(struct sev_issue_cmd *argp)
+ {
+ struct sev_user_data_pek_cert_import input;
+@@ -750,7 +830,6 @@ EXPORT_SYMBOL_GPL(sev_issue_cmd_external_user);
+
+ void psp_pci_init(void)
+ {
+- struct sev_user_data_status *status;
+ struct sp_device *sp;
+ int error, rc;
+
+@@ -760,6 +839,13 @@ void psp_pci_init(void)
+
+ psp_master = sp->psp_data;
+
++ if (sev_get_api_version())
++ goto err;
++
++ if (SEV_VERSION_GREATER_OR_EQUAL(0, 15) &&
++ sev_update_firmware(psp_master->dev) == 0)
++ sev_get_api_version();
++
+ /* Initialize the platform */
+ rc = sev_platform_init(&error);
+ if (rc) {
+@@ -767,16 +853,9 @@ void psp_pci_init(void)
+ goto err;
+ }
+
+- /* Display SEV firmware version */
+- status = &psp_master->status_cmd_buf;
+- rc = sev_platform_status(status, &error);
+- if (rc) {
+- dev_err(sp->dev, "SEV: failed to get status error %#x\n", error);
+- goto err;
+- }
++ dev_info(sp->dev, "SEV API:%d.%d build:%d\n", psp_master->api_major,
++ psp_master->api_minor, psp_master->build);
+
+- dev_info(sp->dev, "SEV API:%d.%d build:%d\n", status->api_major,
+- status->api_minor, status->build);
+ return;
+
+ err:
+diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h
+index c81f0b1..c7e9098a 100644
+--- a/drivers/crypto/ccp/psp-dev.h
++++ b/drivers/crypto/ccp/psp-dev.h
+@@ -78,6 +78,10 @@ struct psp_device {
+ struct sev_misc_dev *sev_misc;
+ struct sev_user_data_status status_cmd_buf;
+ struct sev_data_init init_cmd_buf;
++
++ u8 api_major;
++ u8 api_minor;
++ u8 build;
+ };
+
+ #endif /* __PSP_DEV_H */
+diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h
+index 93addfa..1d24962 100644
+--- a/include/linux/psp-sev.h
++++ b/include/linux/psp-sev.h
+@@ -54,6 +54,7 @@ enum sev_cmd {
+ SEV_CMD_PDH_CERT_EXPORT = 0x008,
+ SEV_CMD_PDH_GEN = 0x009,
+ SEV_CMD_DF_FLUSH = 0x00A,
++ SEV_CMD_DOWNLOAD_FIRMWARE = 0x00B,
+
+ /* Guest commands */
+ SEV_CMD_DECOMMISSION = 0x020,
+@@ -130,6 +131,17 @@ struct sev_data_pek_cert_import {
+ } __packed;
+
+ /**
++ * struct sev_data_download_firmware - DOWNLOAD_FIRMWARE command parameters
++ *
++ * @address: physical address of firmware image
++ * @len: len of the firmware image
++ */
++struct sev_data_download_firmware {
++ u64 address; /* In */
++ u32 len; /* In */
++} __packed;
++
++/**
+ * struct sev_data_pdh_cert_export - PDH_CERT_EXPORT command parameters
+ *
+ * @pdh_address: PDH certificate address
+--
+2.7.4
+