isci: Adding EFI variable skeletal support

Adding EFI variable retrieving for OEM parameters. Still need GUID and
variable name.

Also updated the data struct for oem parameters and hex file for firmware

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
[fix CONFIG_EFI=n compile error]
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 6551932..1310529 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -474,10 +474,9 @@
 		return -ENOMEM;
 	pci_set_drvdata(pdev, pci_info);
 
-	if (efi_enabled) {
-		/* do EFI parsing here */
-		orom = NULL;
-	} else
+	if (efi_enabled)
+		orom = isci_get_efi_var(pdev);
+	else
 		orom = isci_request_oprom(pdev);
 
 	if (!orom) {
diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c
index 0b90e7c..927fead 100644
--- a/drivers/scsi/isci/probe_roms.c
+++ b/drivers/scsi/isci/probe_roms.c
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/firmware.h>
 #include <linux/uaccess.h>
+#include <linux/efi.h>
 #include <asm/probe_roms.h>
 
 #include "isci.h"
@@ -36,6 +37,15 @@
 #include "sci_environment.h"
 #include "probe_roms.h"
 
+struct efi_variable {
+	efi_char16_t  VariableName[1024/sizeof(efi_char16_t)];
+	efi_guid_t    VendorGuid;
+	unsigned long DataSize;
+	__u8          Data[1024];
+	efi_status_t  Status;
+	__u32         Attributes;
+} __attribute__((packed));
+
 struct isci_orom *isci_request_oprom(struct pci_dev *pdev)
 {
 	void __iomem *oprom = pci_map_biosrom(pdev);
@@ -131,3 +141,57 @@
 
 	return orom;
 }
+
+static struct efi *get_efi(void)
+{
+	#ifdef CONFIG_EFI
+	return &efi;
+	#else
+	return NULL;
+	#endif
+}
+
+struct isci_orom *isci_get_efi_var(struct pci_dev *pdev)
+{
+	struct efi_variable *evar;
+	efi_status_t status;
+	struct isci_orom *orom = NULL;
+
+	evar = devm_kzalloc(&pdev->dev,
+			    sizeof(struct efi_variable),
+			    GFP_KERNEL);
+	if (!evar) {
+		dev_warn(&pdev->dev,
+			 "Unable to allocate memory for EFI var\n");
+		return NULL;
+	}
+
+	evar->DataSize = 1024;
+	evar->VendorGuid = ISCI_EFI_VENDOR_GUID;
+	evar->Attributes = ISCI_EFI_ATTRIBUTES;
+
+	if (get_efi())
+		status = get_efi()->get_variable(evar->VariableName,
+						 &evar->VendorGuid,
+						 &evar->Attributes,
+						 &evar->DataSize,
+						 evar->Data);
+	else
+		status = EFI_NOT_FOUND;
+
+	if (status == EFI_SUCCESS)
+		orom = (struct isci_orom *)evar->Data;
+	else
+		dev_warn(&pdev->dev,
+			 "Unable to obtain EFI variable for OEM parms\n");
+
+	if (orom && memcmp(orom->hdr.signature, ISCI_ROM_SIG,
+			   strlen(ISCI_ROM_SIG)) != 0)
+		dev_warn(&pdev->dev,
+			 "Verifying OROM signature failed\n");
+
+	if (!orom)
+		devm_kfree(&pdev->dev, evar);
+
+	return orom;
+}
diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h
index 76651c0..96d8b92 100644
--- a/drivers/scsi/isci/probe_roms.h
+++ b/drivers/scsi/isci/probe_roms.h
@@ -69,7 +69,7 @@
 	struct isci_orom *orom,
 	int scu_index);
 struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw);
-int isci_get_efi_var(struct pci_dev *pdev);
+struct isci_orom *isci_get_efi_var(struct pci_dev *pdev);
 #else
 #define SCI_MAX_PORTS 4
 #define SCI_MAX_PHYS 4