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

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
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -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 | \
+80 −0
Original line number Original line Diff line number Diff line
@@ -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)
	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)
	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)
	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",