diff --git a/src/core/interface.c b/src/core/interface.c index f0c0ae64..c69875ea 100644 --- a/src/core/interface.c +++ b/src/core/interface.c @@ -150,6 +150,31 @@ static struct interface * intf_get_passthru ( struct interface *intf ) { } } +/** + * Get object interface destination and operation method (without pass-through) + * + * @v intf Object interface + * @v type Operation type + * @ret dest Destination interface + * @ret func Implementing method, or NULL + */ +void * intf_get_dest_op_no_passthru_untyped ( struct interface *intf, + void *type, + struct interface **dest ) { + struct interface_descriptor *desc; + struct interface_operation *op; + unsigned int i; + + *dest = intf_get ( intf->dest ); + desc = (*dest)->desc; + for ( i = desc->num_op, op = desc->op ; i ; i--, op++ ) { + if ( op->type == type ) + return op->func; + } + + return NULL; +} + /** * Get object interface destination and operation method * @@ -160,20 +185,16 @@ static struct interface * intf_get_passthru ( struct interface *intf ) { */ void * intf_get_dest_op_untyped ( struct interface *intf, void *type, struct interface **dest ) { - struct interface_descriptor *desc; - struct interface_operation *op; - unsigned int i; + void *func; while ( 1 ) { + /* Search for an implementing method provided by the * current destination interface. */ - *dest = intf_get ( intf->dest ); - desc = (*dest)->desc; - for ( i = desc->num_op, op = desc->op ; i ; i--, op++ ) { - if ( op->type == type ) - return op->func; - } + func = intf_get_dest_op_no_passthru_untyped( intf, type, dest ); + if ( func ) + return func; /* Pass through to the underlying interface, if applicable */ if ( ! ( intf = intf_get_passthru ( *dest ) ) ) diff --git a/src/core/xfer.c b/src/core/xfer.c index 057ab8b3..dce245f9 100644 --- a/src/core/xfer.c +++ b/src/core/xfer.c @@ -56,7 +56,7 @@ static struct xfer_metadata dummy_metadata; int xfer_vredirect ( struct interface *intf, int type, va_list args ) { struct interface *dest; xfer_vredirect_TYPE ( void * ) *op = - intf_get_dest_op ( intf, xfer_vredirect, &dest ); + intf_get_dest_op_no_passthru ( intf, xfer_vredirect, &dest ); void *object = intf_object ( dest ); int rc; diff --git a/src/include/ipxe/interface.h b/src/include/ipxe/interface.h index 49add330..a474aaad 100644 --- a/src/include/ipxe/interface.h +++ b/src/include/ipxe/interface.h @@ -132,6 +132,9 @@ extern void intf_nullify ( struct interface *intf ); extern struct interface * intf_get ( struct interface *intf ); extern void intf_put ( struct interface *intf ); extern void * __attribute__ (( pure )) intf_object ( struct interface *intf ); +extern void * intf_get_dest_op_no_passthru_untyped ( struct interface *intf, + void *type, + struct interface **dest ); extern void * intf_get_dest_op_untyped ( struct interface *intf, void *type, struct interface **dest ); @@ -171,6 +174,18 @@ static inline void intf_init ( struct interface *intf, .desc = &(descriptor), \ } +/** + * Get object interface destination and operation method (without pass-through) + * + * @v intf Object interface + * @v type Operation type + * @ret dest Destination interface + * @ret func Implementing method, or NULL + */ +#define intf_get_dest_op_no_passthru( intf, type, dest ) \ + ( ( type ## _TYPE ( void * ) * ) \ + intf_get_dest_op_no_passthru_untyped ( intf, type, dest ) ) + /** * Get object interface destination and operation method *