|
@@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
27
|
27
|
#include <assert.h>
|
28
|
28
|
#include <byteswap.h>
|
29
|
29
|
#include <ipxe/usb.h>
|
|
30
|
+#include <ipxe/cdc.h>
|
30
|
31
|
|
31
|
32
|
/** @file
|
32
|
33
|
*
|
|
@@ -678,6 +679,7 @@ static int usb_function ( struct usb_function *func,
|
678
|
679
|
struct usb_device *usb = func->usb;
|
679
|
680
|
struct usb_interface_association_descriptor *association;
|
680
|
681
|
struct usb_interface_descriptor *interface;
|
|
682
|
+ struct cdc_union_descriptor *cdc_union;
|
681
|
683
|
unsigned int i;
|
682
|
684
|
|
683
|
685
|
/* First, look for an interface association descriptor */
|
|
@@ -685,8 +687,7 @@ static int usb_function ( struct usb_function *func,
|
685
|
687
|
if ( association ) {
|
686
|
688
|
|
687
|
689
|
/* Sanity check */
|
688
|
|
- if ( ( association->first + association->count ) >
|
689
|
|
- config->interfaces ) {
|
|
690
|
+ if ( association->count > config->interfaces ) {
|
690
|
691
|
DBGC ( usb, "USB %s has invalid association [%d-%d)\n",
|
691
|
692
|
func->name, association->first,
|
692
|
693
|
( association->first + association->count ) );
|
|
@@ -714,6 +715,30 @@ static int usb_function ( struct usb_function *func,
|
714
|
715
|
memcpy ( &func->class, &interface->class, sizeof ( func->class ) );
|
715
|
716
|
func->count = 1;
|
716
|
717
|
func->interface[0] = first;
|
|
718
|
+
|
|
719
|
+ /* Look for a CDC union descriptor, if applicable */
|
|
720
|
+ if ( ( func->class.class == USB_CLASS_CDC ) &&
|
|
721
|
+ ( cdc_union = cdc_union_descriptor ( config, interface ) ) ) {
|
|
722
|
+
|
|
723
|
+ /* Determine interface count */
|
|
724
|
+ func->count = ( ( cdc_union->header.len -
|
|
725
|
+ offsetof ( typeof ( *cdc_union ),
|
|
726
|
+ interface[0] ) ) /
|
|
727
|
+ sizeof ( cdc_union->interface[0] ) );
|
|
728
|
+ if ( func->count > config->interfaces ) {
|
|
729
|
+ DBGC ( usb, "USB %s has invalid union functional "
|
|
730
|
+ "descriptor with %d interfaces\n",
|
|
731
|
+ func->name, func->count );
|
|
732
|
+ return -ERANGE;
|
|
733
|
+ }
|
|
734
|
+
|
|
735
|
+ /* Describe function */
|
|
736
|
+ for ( i = 0 ; i < func->count ; i++ )
|
|
737
|
+ func->interface[i] = cdc_union->interface[i];
|
|
738
|
+
|
|
739
|
+ return 0;
|
|
740
|
+ }
|
|
741
|
+
|
717
|
742
|
return 0;
|
718
|
743
|
}
|
719
|
744
|
|
|
@@ -842,7 +867,11 @@ usb_probe_all ( struct usb_device *usb,
|
842
|
867
|
|
843
|
868
|
/* Mark interfaces as used */
|
844
|
869
|
for ( i = 0 ; i < func->count ; i++ ) {
|
845
|
|
- assert ( func->interface[i] < config->interfaces );
|
|
870
|
+ if ( func->interface[i] >= config->interfaces ) {
|
|
871
|
+ DBGC ( usb, "USB %s has invalid interface %d\n",
|
|
872
|
+ func->name, func->interface[i] );
|
|
873
|
+ goto err_interface;
|
|
874
|
+ }
|
846
|
875
|
used[ func->interface[i] ] = 1;
|
847
|
876
|
}
|
848
|
877
|
|
|
@@ -872,6 +901,7 @@ usb_probe_all ( struct usb_device *usb,
|
872
|
901
|
err_probe:
|
873
|
902
|
free ( func );
|
874
|
903
|
err_alloc:
|
|
904
|
+ err_interface:
|
875
|
905
|
err_function:
|
876
|
906
|
/* Continue registering other functions */
|
877
|
907
|
continue;
|