diff options
author | Kashyap Desai <kashyap.desai@broadcom.com> | 2021-05-20 20:55:43 +0530 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2021-06-02 00:56:17 -0400 |
commit | 28cbe2f420d338cc4cb8f0cc367b22ea3c41b3b5 (patch) | |
tree | 29c84321c04c4366da0b3652293db769554b9903 /drivers/scsi/mpi3mr/mpi3mr_os.c | |
parent | 2f9c4d520aa60f1bc65b791ac2a5fa3ed622d095 (diff) | |
download | linux-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.c | 80 |
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", |