@@ -233,11 +233,12 @@ static bool add_spa(struct acpi_nfit_desc *acpi_desc,
233
233
struct nfit_table_prev * prev ,
234
234
struct acpi_nfit_system_address * spa )
235
235
{
236
+ size_t length = min_t (size_t , sizeof (* spa ), spa -> header .length );
236
237
struct device * dev = acpi_desc -> dev ;
237
238
struct nfit_spa * nfit_spa ;
238
239
239
240
list_for_each_entry (nfit_spa , & prev -> spas , list ) {
240
- if (memcmp (nfit_spa -> spa , spa , sizeof ( * spa ) ) == 0 ) {
241
+ if (memcmp (nfit_spa -> spa , spa , length ) == 0 ) {
241
242
list_move_tail (& nfit_spa -> list , & acpi_desc -> spas );
242
243
return true;
243
244
}
@@ -259,11 +260,12 @@ static bool add_memdev(struct acpi_nfit_desc *acpi_desc,
259
260
struct nfit_table_prev * prev ,
260
261
struct acpi_nfit_memory_map * memdev )
261
262
{
263
+ size_t length = min_t (size_t , sizeof (* memdev ), memdev -> header .length );
262
264
struct device * dev = acpi_desc -> dev ;
263
265
struct nfit_memdev * nfit_memdev ;
264
266
265
267
list_for_each_entry (nfit_memdev , & prev -> memdevs , list )
266
- if (memcmp (nfit_memdev -> memdev , memdev , sizeof ( * memdev ) ) == 0 ) {
268
+ if (memcmp (nfit_memdev -> memdev , memdev , length ) == 0 ) {
267
269
list_move_tail (& nfit_memdev -> list , & acpi_desc -> memdevs );
268
270
return true;
269
271
}
@@ -284,11 +286,12 @@ static bool add_dcr(struct acpi_nfit_desc *acpi_desc,
284
286
struct nfit_table_prev * prev ,
285
287
struct acpi_nfit_control_region * dcr )
286
288
{
289
+ size_t length = min_t (size_t , sizeof (* dcr ), dcr -> header .length );
287
290
struct device * dev = acpi_desc -> dev ;
288
291
struct nfit_dcr * nfit_dcr ;
289
292
290
293
list_for_each_entry (nfit_dcr , & prev -> dcrs , list )
291
- if (memcmp (nfit_dcr -> dcr , dcr , sizeof ( * dcr ) ) == 0 ) {
294
+ if (memcmp (nfit_dcr -> dcr , dcr , length ) == 0 ) {
292
295
list_move_tail (& nfit_dcr -> list , & acpi_desc -> dcrs );
293
296
return true;
294
297
}
@@ -308,11 +311,12 @@ static bool add_bdw(struct acpi_nfit_desc *acpi_desc,
308
311
struct nfit_table_prev * prev ,
309
312
struct acpi_nfit_data_region * bdw )
310
313
{
314
+ size_t length = min_t (size_t , sizeof (* bdw ), bdw -> header .length );
311
315
struct device * dev = acpi_desc -> dev ;
312
316
struct nfit_bdw * nfit_bdw ;
313
317
314
318
list_for_each_entry (nfit_bdw , & prev -> bdws , list )
315
- if (memcmp (nfit_bdw -> bdw , bdw , sizeof ( * bdw ) ) == 0 ) {
319
+ if (memcmp (nfit_bdw -> bdw , bdw , length ) == 0 ) {
316
320
list_move_tail (& nfit_bdw -> list , & acpi_desc -> bdws );
317
321
return true;
318
322
}
@@ -332,11 +336,12 @@ static bool add_idt(struct acpi_nfit_desc *acpi_desc,
332
336
struct nfit_table_prev * prev ,
333
337
struct acpi_nfit_interleave * idt )
334
338
{
339
+ size_t length = min_t (size_t , sizeof (* idt ), idt -> header .length );
335
340
struct device * dev = acpi_desc -> dev ;
336
341
struct nfit_idt * nfit_idt ;
337
342
338
343
list_for_each_entry (nfit_idt , & prev -> idts , list )
339
- if (memcmp (nfit_idt -> idt , idt , sizeof ( * idt ) ) == 0 ) {
344
+ if (memcmp (nfit_idt -> idt , idt , length ) == 0 ) {
340
345
list_move_tail (& nfit_idt -> list , & acpi_desc -> idts );
341
346
return true;
342
347
}
@@ -356,11 +361,12 @@ static bool add_flush(struct acpi_nfit_desc *acpi_desc,
356
361
struct nfit_table_prev * prev ,
357
362
struct acpi_nfit_flush_address * flush )
358
363
{
364
+ size_t length = min_t (size_t , sizeof (* flush ), flush -> header .length );
359
365
struct device * dev = acpi_desc -> dev ;
360
366
struct nfit_flush * nfit_flush ;
361
367
362
368
list_for_each_entry (nfit_flush , & prev -> flushes , list )
363
- if (memcmp (nfit_flush -> flush , flush , sizeof ( * flush ) ) == 0 ) {
369
+ if (memcmp (nfit_flush -> flush , flush , length ) == 0 ) {
364
370
list_move_tail (& nfit_flush -> list , & acpi_desc -> flushes );
365
371
return true;
366
372
}
@@ -655,7 +661,7 @@ static ssize_t revision_show(struct device *dev,
655
661
struct nvdimm_bus_descriptor * nd_desc = to_nd_desc (nvdimm_bus );
656
662
struct acpi_nfit_desc * acpi_desc = to_acpi_desc (nd_desc );
657
663
658
- return sprintf (buf , "%d\n" , acpi_desc -> nfit -> header .revision );
664
+ return sprintf (buf , "%d\n" , acpi_desc -> acpi_header .revision );
659
665
}
660
666
static DEVICE_ATTR_RO (revision );
661
667
@@ -1652,7 +1658,6 @@ int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, acpi_size sz)
1652
1658
1653
1659
data = (u8 * ) acpi_desc -> nfit ;
1654
1660
end = data + sz ;
1655
- data += sizeof (struct acpi_table_nfit );
1656
1661
while (!IS_ERR_OR_NULL (data ))
1657
1662
data = add_table (acpi_desc , & prev , data , end );
1658
1663
@@ -1748,13 +1753,29 @@ static int acpi_nfit_add(struct acpi_device *adev)
1748
1753
return PTR_ERR (acpi_desc );
1749
1754
}
1750
1755
1751
- acpi_desc -> nfit = (struct acpi_table_nfit * ) tbl ;
1756
+ /*
1757
+ * Save the acpi header for later and then skip it,
1758
+ * making nfit point to the first nfit table header.
1759
+ */
1760
+ acpi_desc -> acpi_header = * tbl ;
1761
+ acpi_desc -> nfit = (void * ) tbl + sizeof (struct acpi_table_nfit );
1762
+ sz -= sizeof (struct acpi_table_nfit );
1752
1763
1753
1764
/* Evaluate _FIT and override with that if present */
1754
1765
status = acpi_evaluate_object (adev -> handle , "_FIT" , NULL , & buf );
1755
1766
if (ACPI_SUCCESS (status ) && buf .length > 0 ) {
1756
- acpi_desc -> nfit = (struct acpi_table_nfit * )buf .pointer ;
1757
- sz = buf .length ;
1767
+ union acpi_object * obj ;
1768
+ /*
1769
+ * Adjust for the acpi_object header of the _FIT
1770
+ */
1771
+ obj = buf .pointer ;
1772
+ if (obj -> type == ACPI_TYPE_BUFFER ) {
1773
+ acpi_desc -> nfit =
1774
+ (struct acpi_nfit_header * )obj -> buffer .pointer ;
1775
+ sz = obj -> buffer .length ;
1776
+ } else
1777
+ dev_dbg (dev , "%s invalid type %d, ignoring _FIT\n" ,
1778
+ __func__ , (int ) obj -> type );
1758
1779
}
1759
1780
1760
1781
rc = acpi_nfit_init (acpi_desc , sz );
@@ -1777,7 +1798,8 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
1777
1798
{
1778
1799
struct acpi_nfit_desc * acpi_desc = dev_get_drvdata (& adev -> dev );
1779
1800
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER , NULL };
1780
- struct acpi_table_nfit * nfit_saved ;
1801
+ struct acpi_nfit_header * nfit_saved ;
1802
+ union acpi_object * obj ;
1781
1803
struct device * dev = & adev -> dev ;
1782
1804
acpi_status status ;
1783
1805
int ret ;
@@ -1808,12 +1830,19 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
1808
1830
}
1809
1831
1810
1832
nfit_saved = acpi_desc -> nfit ;
1811
- acpi_desc -> nfit = (struct acpi_table_nfit * )buf .pointer ;
1812
- ret = acpi_nfit_init (acpi_desc , buf .length );
1813
- if (!ret ) {
1814
- /* Merge failed, restore old nfit, and exit */
1815
- acpi_desc -> nfit = nfit_saved ;
1816
- dev_err (dev , "failed to merge updated NFIT\n" );
1833
+ obj = buf .pointer ;
1834
+ if (obj -> type == ACPI_TYPE_BUFFER ) {
1835
+ acpi_desc -> nfit =
1836
+ (struct acpi_nfit_header * )obj -> buffer .pointer ;
1837
+ ret = acpi_nfit_init (acpi_desc , obj -> buffer .length );
1838
+ if (ret ) {
1839
+ /* Merge failed, restore old nfit, and exit */
1840
+ acpi_desc -> nfit = nfit_saved ;
1841
+ dev_err (dev , "failed to merge updated NFIT\n" );
1842
+ }
1843
+ } else {
1844
+ /* Bad _FIT, restore old nfit */
1845
+ dev_err (dev , "Invalid _FIT\n" );
1817
1846
}
1818
1847
kfree (buf .pointer );
1819
1848
0 commit comments