diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-03-08 18:53:51 +0100 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 12:55:31 +0200 |
commit | 3b67c1f376acb24b7c6679f75275ac5a96792986 (patch) | |
tree | 1d9db0ca797010ee7998dde4eb62c3bc3b878526 /drivers/scsi/isci/probe_roms.c | |
parent | isci: copy the oem parameters instead of assign (diff) | |
download | linux-3b67c1f376acb24b7c6679f75275ac5a96792986.tar.xz linux-3b67c1f376acb24b7c6679f75275ac5a96792986.zip |
isci: fixup with testing from isci OROM in BIOS
Added fixups for the OROM parsing code after testing with BIOS OROM
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/probe_roms.c')
-rw-r--r-- | drivers/scsi/isci/probe_roms.c | 48 |
1 files changed, 42 insertions, 6 deletions
diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 822240578115..64e9a808c814 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -51,6 +51,10 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) void __iomem *oprom = pci_map_biosrom(pdev); struct isci_orom *rom = NULL; size_t len, i; + int j; + char oem_sig[4]; + struct isci_oem_hdr oem_hdr; + u8 *tmp, sum; if (!oprom) return NULL; @@ -58,13 +62,45 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) len = pci_biosrom_size(pdev); rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL); - for (i = 0; i < len && rom; i += ISCI_ROM_SIG_SIZE) { - memcpy_fromio(rom->hdr.signature, oprom + i, ISCI_ROM_SIG_SIZE); - if (memcmp(rom->hdr.signature, ISCI_ROM_SIG, - ISCI_ROM_SIG_SIZE) == 0) { - size_t copy_len = min(len - i, sizeof(*rom)); + for (i = 0; i < len && rom; i += ISCI_OEM_SIG_SIZE) { + memcpy_fromio(oem_sig, oprom + i, ISCI_OEM_SIG_SIZE); - memcpy_fromio(rom, oprom + i, copy_len); + /* we think we found the OEM table */ + if (memcmp(oem_sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) == 0) { + size_t copy_len; + + memcpy_fromio(&oem_hdr, oprom + i, sizeof(oem_hdr)); + + copy_len = min(oem_hdr.len - sizeof(oem_hdr), + sizeof(*rom)); + + memcpy_fromio(rom, + oprom + i + sizeof(oem_hdr), + copy_len); + + /* calculate checksum */ + tmp = (u8 *)&oem_hdr; + for (j = 0, sum = 0; j < sizeof(oem_hdr); j++, tmp++) + sum += *tmp; + + tmp = (u8 *)rom; + for (j = 0; j < sizeof(*rom); j++, tmp++) + sum += *tmp; + + if (sum != 0) { + dev_warn(&pdev->dev, + "OEM table checksum failed\n"); + continue; + } + + /* keep going if that's not the oem param table */ + if (memcmp(rom->hdr.signature, + ISCI_ROM_SIG, + ISCI_ROM_SIG_SIZE) != 0) + continue; + + dev_info(&pdev->dev, + "OEM parameter table found in OROM\n"); break; } } |