@@ -182,6 +182,7 @@ bool einj_initialized __ro_after_init;
182182
183183static void __iomem * einj_param ;
184184static u32 v5param_size ;
185+ static u32 v66param_size ;
185186static bool is_v2 ;
186187
187188static void einj_exec_ctx_init (struct apei_exec_context * ctx )
@@ -283,6 +284,24 @@ static void check_vendor_extension(u64 paddr,
283284 acpi_os_unmap_iomem (p , sizeof (v ));
284285}
285286
287+ static u32 einjv2_init (struct einjv2_extension_struct * e )
288+ {
289+ if (e -> revision != 1 ) {
290+ pr_info ("Unknown v2 extension revision %u\n" , e -> revision );
291+ return 0 ;
292+ }
293+ if (e -> length < sizeof (* e ) || e -> length > PAGE_SIZE ) {
294+ pr_info (FW_BUG "Bad1 v2 extension length %u\n" , e -> length );
295+ return 0 ;
296+ }
297+ if ((e -> length - sizeof (* e )) % sizeof (e -> component_arr [0 ])) {
298+ pr_info (FW_BUG "Bad2 v2 extension length %u\n" , e -> length );
299+ return 0 ;
300+ }
301+
302+ return (e -> length - sizeof (* e )) / sizeof (e -> component_arr [0 ]);
303+ }
304+
286305static void __iomem * einj_get_parameter_address (void )
287306{
288307 int i ;
@@ -310,28 +329,21 @@ static void __iomem *einj_get_parameter_address(void)
310329 v5param_size = sizeof (v5param );
311330 p = acpi_os_map_iomem (pa_v5 , sizeof (* p ));
312331 if (p ) {
313- int offset , len ;
314-
315332 memcpy_fromio (& v5param , p , v5param_size );
316333 acpi5 = 1 ;
317334 check_vendor_extension (pa_v5 , & v5param );
318- if (is_v2 && available_error_type & ACPI65_EINJV2_SUPP ) {
319- len = v5param .einjv2_struct .length ;
320- offset = offsetof(struct einjv2_extension_struct , component_arr );
321- max_nr_components = (len - offset ) /
322- sizeof (v5param .einjv2_struct .component_arr [0 ]);
323- /*
324- * The first call to acpi_os_map_iomem above does not include the
325- * component array, instead it is used to read and calculate maximum
326- * number of components supported by the system. Below, the mapping
327- * is expanded to include the component array.
328- */
335+ if (available_error_type & ACPI65_EINJV2_SUPP ) {
336+ struct einjv2_extension_struct * e ;
337+
338+ e = & v5param .einjv2_struct ;
339+ max_nr_components = einjv2_init (e );
340+
341+ /* remap including einjv2_extension_struct */
329342 acpi_os_unmap_iomem (p , v5param_size );
330- offset = offsetof(struct set_error_type_with_address , einjv2_struct );
331- v5param_size = offset + struct_size (& v5param .einjv2_struct ,
332- component_arr , max_nr_components );
333- p = acpi_os_map_iomem (pa_v5 , v5param_size );
343+ v66param_size = v5param_size - sizeof (* e ) + e -> length ;
344+ p = acpi_os_map_iomem (pa_v5 , v66param_size );
334345 }
346+
335347 return p ;
336348 }
337349 }
@@ -527,6 +539,7 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
527539 u64 param3 , u64 param4 )
528540{
529541 struct apei_exec_context ctx ;
542+ u32 param_size = is_v2 ? v66param_size : v5param_size ;
530543 u64 val , trigger_paddr , timeout = FIRMWARE_TIMEOUT ;
531544 int i , rc ;
532545
@@ -539,11 +552,11 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
539552 if (acpi5 ) {
540553 struct set_error_type_with_address * v5param ;
541554
542- v5param = kmalloc (v5param_size , GFP_KERNEL );
555+ v5param = kmalloc (param_size , GFP_KERNEL );
543556 if (!v5param )
544557 return - ENOMEM ;
545558
546- memcpy_fromio (v5param , einj_param , v5param_size );
559+ memcpy_fromio (v5param , einj_param , param_size );
547560 v5param -> type = type ;
548561 if (type & ACPI5_VENDOR_BIT ) {
549562 switch (vendor_flags ) {
@@ -601,7 +614,7 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
601614 break ;
602615 }
603616 }
604- memcpy_toio (einj_param , v5param , v5param_size );
617+ memcpy_toio (einj_param , v5param , param_size );
605618 kfree (v5param );
606619 } else {
607620 rc = apei_exec_run (& ctx , ACPI_EINJ_SET_ERROR_TYPE );
@@ -1132,9 +1145,14 @@ static void einj_remove(struct faux_device *fdev)
11321145 struct apei_exec_context ctx ;
11331146
11341147 if (einj_param ) {
1135- acpi_size size = (acpi5 ) ?
1136- v5param_size :
1137- sizeof (struct einj_parameter );
1148+ acpi_size size ;
1149+
1150+ if (v66param_size )
1151+ size = v66param_size ;
1152+ else if (acpi5 )
1153+ size = v5param_size ;
1154+ else
1155+ size = sizeof (struct einj_parameter );
11381156
11391157 acpi_os_unmap_iomem (einj_param , size );
11401158 if (vendor_errors .size )
0 commit comments