summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpi3mr/mpi3mr_os.c
diff options
context:
space:
mode:
authorKashyap Desai <kashyap.desai@broadcom.com>2021-05-20 20:55:43 +0530
committerMartin K. Petersen <martin.petersen@oracle.com>2021-06-02 00:56:17 -0400
commit28cbe2f420d338cc4cb8f0cc367b22ea3c41b3b5 (patch)
tree29c84321c04c4366da0b3652293db769554b9903 /drivers/scsi/mpi3mr/mpi3mr_os.c
parent2f9c4d520aa60f1bc65b791ac2a5fa3ed622d095 (diff)
downloadlinux-28cbe2f420d338cc4cb8f0cc367b22ea3c41b3b5.tar.gz
linux-28cbe2f420d338cc4cb8f0cc367b22ea3c41b3b5.tar.bz2
linux-28cbe2f420d338cc4cb8f0cc367b22ea3c41b3b5.zip
scsi: mpi3mr: Add support for DSN secure firmware check
Read PCI_EXT_CAP_ID_DSN to query security status. The driver will throw a warning message when a non-secure type controller is detected. The purpose of this interface is to avoid interacting with any firmware which is not secured/signed by Broadcom. Any tampering on firmware component will be detected by hardware and it will be communicated to the driver to avoid any further interaction with that component. Link: https://lore.kernel.org/r/20210520152545.2710479-23-kashyap.desai@broadcom.com Cc: sathya.prakash@broadcom.com Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/mpi3mr/mpi3mr_os.c')
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_os.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c
index dd71cdc5945c..6400ca57fb1e 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_os.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_os.c
@@ -3189,6 +3189,75 @@ static inline void mpi3mr_init_drv_cmd(struct mpi3mr_drv_cmd *cmdptr,
}
/**
+ * osintfc_mrioc_security_status -Check controller secure status
+ * @pdev: PCI device instance
+ *
+ * Read the Device Serial Number capability from PCI config
+ * space and decide whether the controller is secure or not.
+ *
+ * Return: 0 on success, non-zero on failure.
+ */
+static int
+osintfc_mrioc_security_status(struct pci_dev *pdev)
+{
+ u32 cap_data;
+ int base;
+ u32 ctlr_status;
+ u32 debug_status;
+ int retval = 0;
+
+ base = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DSN);
+ if (!base) {
+ dev_err(&pdev->dev,
+ "%s: PCI_EXT_CAP_ID_DSN is not supported\n", __func__);
+ return -1;
+ }
+
+ pci_read_config_dword(pdev, base + 4, &cap_data);
+
+ debug_status = cap_data & MPI3MR_CTLR_SECURE_DBG_STATUS_MASK;
+ ctlr_status = cap_data & MPI3MR_CTLR_SECURITY_STATUS_MASK;
+
+ switch (ctlr_status) {
+ case MPI3MR_INVALID_DEVICE:
+ dev_err(&pdev->dev,
+ "%s: Non secure ctlr (Invalid) is detected: DID: 0x%x: SVID: 0x%x: SDID: 0x%x\n",
+ __func__, pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
+ retval = -1;
+ break;
+ case MPI3MR_CONFIG_SECURE_DEVICE:
+ if (!debug_status)
+ dev_info(&pdev->dev,
+ "%s: Config secure ctlr is detected\n",
+ __func__);
+ break;
+ case MPI3MR_HARD_SECURE_DEVICE:
+ break;
+ case MPI3MR_TAMPERED_DEVICE:
+ dev_err(&pdev->dev,
+ "%s: Non secure ctlr (Tampered) is detected: DID: 0x%x: SVID: 0x%x: SDID: 0x%x\n",
+ __func__, pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
+ retval = -1;
+ break;
+ default:
+ retval = -1;
+ break;
+ }
+
+ if (!retval && debug_status) {
+ dev_err(&pdev->dev,
+ "%s: Non secure ctlr (Secure Dbg) is detected: DID: 0x%x: SVID: 0x%x: SDID: 0x%x\n",
+ __func__, pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
+ retval = -1;
+ }
+
+ return retval;
+}
+
+/**
* mpi3mr_probe - PCI probe callback
* @pdev: PCI device instance
* @id: PCI device ID details
@@ -3210,6 +3279,11 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct Scsi_Host *shost = NULL;
int retval = 0, i;
+ if (osintfc_mrioc_security_status(pdev)) {
+ warn_non_secure_ctlr = 1;
+ return 1; /* For Invalid and Tampered device */
+ }
+
shost = scsi_host_alloc(&mpi3mr_driver_template,
sizeof(struct mpi3mr_ioc));
if (!shost) {
@@ -3326,6 +3400,9 @@ static void mpi3mr_remove(struct pci_dev *pdev)
unsigned long flags;
struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next;
+ if (!shost)
+ return;
+
mrioc = shost_priv(shost);
while (mrioc->reset_in_progress || mrioc->is_driver_loading)
ssleep(1);
@@ -3444,6 +3521,9 @@ static int mpi3mr_resume(struct pci_dev *pdev)
pci_power_t device_state = pdev->current_state;
int r;
+ if (!shost)
+ return 0;
+
mrioc = shost_priv(shost);
ioc_info(mrioc, "pdev=0x%p, slot=%s, previous operating state [D%d]\n",