Commit 28cbe2f4 authored by Kashyap Desai's avatar Kashyap Desai Committed by Martin K. Petersen

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: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Reviewed-by: default avatarHimanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: default avatarKashyap Desai <kashyap.desai@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 2f9c4d52
...@@ -154,6 +154,15 @@ extern struct list_head mrioc_list; ...@@ -154,6 +154,15 @@ extern struct list_head mrioc_list;
#define MPI3MR_IRQ_POLL_SLEEP 2 #define MPI3MR_IRQ_POLL_SLEEP 2
#define MPI3MR_IRQ_POLL_TRIGGER_IOCOUNT 8 #define MPI3MR_IRQ_POLL_TRIGGER_IOCOUNT 8
/* Definitions for the controller security status*/
#define MPI3MR_CTLR_SECURITY_STATUS_MASK 0x0C
#define MPI3MR_CTLR_SECURE_DBG_STATUS_MASK 0x02
#define MPI3MR_INVALID_DEVICE 0x00
#define MPI3MR_CONFIG_SECURE_DEVICE 0x04
#define MPI3MR_HARD_SECURE_DEVICE 0x08
#define MPI3MR_TAMPERED_DEVICE 0x0C
/* SGE Flag definition */ /* SGE Flag definition */
#define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \ #define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \
(MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \ (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \
......
...@@ -3188,6 +3188,75 @@ static inline void mpi3mr_init_drv_cmd(struct mpi3mr_drv_cmd *cmdptr, ...@@ -3188,6 +3188,75 @@ static inline void mpi3mr_init_drv_cmd(struct mpi3mr_drv_cmd *cmdptr,
cmdptr->host_tag = host_tag; cmdptr->host_tag = host_tag;
} }
/**
* 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 * mpi3mr_probe - PCI probe callback
* @pdev: PCI device instance * @pdev: PCI device instance
...@@ -3210,6 +3279,11 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -3210,6 +3279,11 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct Scsi_Host *shost = NULL; struct Scsi_Host *shost = NULL;
int retval = 0, i; 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, shost = scsi_host_alloc(&mpi3mr_driver_template,
sizeof(struct mpi3mr_ioc)); sizeof(struct mpi3mr_ioc));
if (!shost) { if (!shost) {
...@@ -3326,6 +3400,9 @@ static void mpi3mr_remove(struct pci_dev *pdev) ...@@ -3326,6 +3400,9 @@ static void mpi3mr_remove(struct pci_dev *pdev)
unsigned long flags; unsigned long flags;
struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next; struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next;
if (!shost)
return;
mrioc = shost_priv(shost); mrioc = shost_priv(shost);
while (mrioc->reset_in_progress || mrioc->is_driver_loading) while (mrioc->reset_in_progress || mrioc->is_driver_loading)
ssleep(1); ssleep(1);
...@@ -3444,6 +3521,9 @@ static int mpi3mr_resume(struct pci_dev *pdev) ...@@ -3444,6 +3521,9 @@ static int mpi3mr_resume(struct pci_dev *pdev)
pci_power_t device_state = pdev->current_state; pci_power_t device_state = pdev->current_state;
int r; int r;
if (!shost)
return 0;
mrioc = shost_priv(shost); mrioc = shost_priv(shost);
ioc_info(mrioc, "pdev=0x%p, slot=%s, previous operating state [D%d]\n", ioc_info(mrioc, "pdev=0x%p, slot=%s, previous operating state [D%d]\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment