diff options
Diffstat (limited to 'drivers/scsi/isci')
-rw-r--r-- | drivers/scsi/isci/init.c | 7 | ||||
-rw-r--r-- | drivers/scsi/isci/probe_roms.c | 64 | ||||
-rw-r--r-- | drivers/scsi/isci/probe_roms.h | 2 |
3 files changed, 68 insertions, 5 deletions
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 65519321e1cc..13105294fbea 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -474,10 +474,9 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic 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 0b90e7c546c0..927feaddc04d 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 @@ struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmw 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 76651c01895a..96d8b9212457 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -69,7 +69,7 @@ enum sci_status isci_parse_oem_parameters( 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 |