diff options
Diffstat (limited to 'drivers/scsi/isci/probe_roms.c')
-rw-r--r-- | drivers/scsi/isci/probe_roms.c | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 64e9a808c814..0d968d3b334b 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c | |||
@@ -61,6 +61,11 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) | |||
61 | 61 | ||
62 | len = pci_biosrom_size(pdev); | 62 | len = pci_biosrom_size(pdev); |
63 | rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL); | 63 | rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL); |
64 | if (!rom) { | ||
65 | dev_warn(&pdev->dev, | ||
66 | "Unable to allocate memory for orom\n"); | ||
67 | return NULL; | ||
68 | } | ||
64 | 69 | ||
65 | for (i = 0; i < len && rom; i += ISCI_OEM_SIG_SIZE) { | 70 | for (i = 0; i < len && rom; i += ISCI_OEM_SIG_SIZE) { |
66 | memcpy_fromio(oem_sig, oprom + i, ISCI_OEM_SIG_SIZE); | 71 | memcpy_fromio(oem_sig, oprom + i, ISCI_OEM_SIG_SIZE); |
@@ -181,7 +186,11 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev) | |||
181 | { | 186 | { |
182 | struct efi_variable *evar; | 187 | struct efi_variable *evar; |
183 | efi_status_t status; | 188 | efi_status_t status; |
184 | struct isci_orom *orom = NULL; | 189 | struct isci_orom *rom = NULL; |
190 | struct isci_oem_hdr *oem_hdr; | ||
191 | u8 *tmp, sum; | ||
192 | int j; | ||
193 | size_t copy_len; | ||
185 | 194 | ||
186 | evar = devm_kzalloc(&pdev->dev, | 195 | evar = devm_kzalloc(&pdev->dev, |
187 | sizeof(struct efi_variable), | 196 | sizeof(struct efi_variable), |
@@ -192,6 +201,16 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev) | |||
192 | return NULL; | 201 | return NULL; |
193 | } | 202 | } |
194 | 203 | ||
204 | rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL); | ||
205 | if (!rom) { | ||
206 | dev_warn(&pdev->dev, | ||
207 | "Unable to allocate memory for orom\n"); | ||
208 | return NULL; | ||
209 | } | ||
210 | |||
211 | for (j = 0; j < strlen(ISCI_EFI_VAR_NAME) + 1; j++) | ||
212 | evar->VariableName[j] = ISCI_EFI_VAR_NAME[j]; | ||
213 | |||
195 | evar->DataSize = 1024; | 214 | evar->DataSize = 1024; |
196 | evar->VendorGuid = ISCI_EFI_VENDOR_GUID; | 215 | evar->VendorGuid = ISCI_EFI_VENDOR_GUID; |
197 | evar->Attributes = ISCI_EFI_ATTRIBUTES; | 216 | evar->Attributes = ISCI_EFI_ATTRIBUTES; |
@@ -205,19 +224,48 @@ struct isci_orom *isci_get_efi_var(struct pci_dev *pdev) | |||
205 | else | 224 | else |
206 | status = EFI_NOT_FOUND; | 225 | status = EFI_NOT_FOUND; |
207 | 226 | ||
208 | if (status == EFI_SUCCESS) | 227 | if (status != EFI_SUCCESS) { |
209 | orom = (struct isci_orom *)evar->Data; | ||
210 | else | ||
211 | dev_warn(&pdev->dev, | 228 | dev_warn(&pdev->dev, |
212 | "Unable to obtain EFI variable for OEM parms\n"); | 229 | "Unable to obtain EFI variable for OEM parms\n"); |
230 | return NULL; | ||
231 | } | ||
232 | |||
233 | oem_hdr = (struct isci_oem_hdr *)evar->Data; | ||
213 | 234 | ||
214 | if (orom && memcmp(orom->hdr.signature, ISCI_ROM_SIG, | 235 | if (memcmp(oem_hdr->sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) != 0) { |
215 | strlen(ISCI_ROM_SIG)) != 0) | ||
216 | dev_warn(&pdev->dev, | 236 | dev_warn(&pdev->dev, |
217 | "Verifying OROM signature failed\n"); | 237 | "Invalid OEM header signature\n"); |
238 | return NULL; | ||
239 | } | ||
218 | 240 | ||
219 | if (!orom) | 241 | /* calculate checksum */ |
220 | devm_kfree(&pdev->dev, evar); | 242 | tmp = (u8 *)oem_hdr; |
243 | for (j = 0, sum = 0; j < sizeof(oem_hdr); j++, tmp++) | ||
244 | sum += *tmp; | ||
221 | 245 | ||
222 | return orom; | 246 | tmp = (u8 *)rom; |
247 | for (j = 0; j < sizeof(*rom); j++, tmp++) | ||
248 | sum += *tmp; | ||
249 | |||
250 | if (sum != 0) { | ||
251 | dev_warn(&pdev->dev, | ||
252 | "OEM table checksum failed\n"); | ||
253 | return NULL; | ||
254 | } | ||
255 | |||
256 | copy_len = min(evar->DataSize, | ||
257 | min(oem_hdr->len - sizeof(*oem_hdr), | ||
258 | sizeof(*rom))); | ||
259 | |||
260 | memcpy(rom, (char *)evar->Data + sizeof(*oem_hdr), copy_len); | ||
261 | |||
262 | if (memcmp(rom->hdr.signature, | ||
263 | ISCI_ROM_SIG, | ||
264 | ISCI_ROM_SIG_SIZE) != 0) { | ||
265 | dev_warn(&pdev->dev, | ||
266 | "Invalid OEM table signature\n"); | ||
267 | return NULL; | ||
268 | } | ||
269 | |||
270 | return rom; | ||
223 | } | 271 | } |