[PATCH 12/16] efi_loader: efi_net: add snp_owner field to efi_net_obj struct

Heinrich Schuchardt xypron.glpk at gmx.de
Mon Apr 14 18:03:42 CEST 2025


On 11.03.25 17:47, Adriano Cordova wrote:
> Two efi_net_obj's could share the same efi_simple_network_protocol interface.
> For example, say a working U-Boot net device is registered in the EFI
> subsystem, this will create an instance of an efi simple network protocol.
> Then another handle, say handle A, could be created using this same efi simple
> network protocol interface, and connect controller could be called. A U-Boot
> udevice would be created for handle A and it would be registered in the EFI
> subsystem as an efi_net_obj with the same simple network protocol interface as
> the efi_net_obj we started with.

Why do you think it would be problematic if some new udevice is created
which via efi_net_driver could call into the driver of the physical udevice?

What we should avoid is having multiple handles pointing to the same
udevice.

>
> Signed-off-by: Adriano Cordova <adriano.cordova at canonical.com>
> ---
>   lib/efi_loader/efi_net.c | 51 +++++++++++++++++++++++++---------------
>   1 file changed, 32 insertions(+), 19 deletions(-)
>
> diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
> index 5a00e7a570c..3ad51d343da 100644
> --- a/lib/efi_loader/efi_net.c
> +++ b/lib/efi_loader/efi_net.c
> @@ -110,6 +110,7 @@ struct efi_net_obj {
>   	struct efi_event *wait_for_packet;
>   	struct efi_event *network_timer_event;
>   	int efi_seq_num;
> +	bool snp_owner;

Building the documentation fails because a description for the new
element snp_owner is missing.

Best regards

Heinrich

>   };
>
>   static int curr_efi_net_obj;
> @@ -134,15 +135,17 @@ static bool efi_netobj_is_active(struct efi_net_obj *netobj)
>    *
>    *
>    * @snp:	pointer to the simple network protocol
> + * @bool:	snp owner
>    * Return:	pointer to efi_net_obj, NULL on error
>    */
> -static struct efi_net_obj *efi_netobj_from_snp(struct efi_simple_network *snp)
> +static struct efi_net_obj *efi_netobj_from_snp(struct efi_simple_network *snp,
> +					       bool snp_owner)
>   {
>   	int i;
>
>   	for (i = 0; i < MAX_EFI_NET_OBJS; i++) {
> -		if (net_objs[i] && net_objs[i]->net == snp) {
> -			// Do not register duplicate devices
> +		if (net_objs[i] && net_objs[i]->net == snp &&
> +		    (!snp_owner || net_objs[i]->snp_owner)) {
>   			return net_objs[i];
>   		}
>   	}
> @@ -171,7 +174,7 @@ static efi_status_t EFIAPI efi_net_start(struct efi_simple_network *this)
>   		goto out;
>   	}
>
> -	nt = efi_netobj_from_snp(this);
> +	nt = efi_netobj_from_snp(this, true);
>
>   	if (this->mode->state != EFI_NETWORK_STOPPED) {
>   		ret = EFI_ALREADY_STARTED;
> @@ -207,7 +210,7 @@ static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this)
>   		goto out;
>   	}
>
> -	nt = efi_netobj_from_snp(this);
> +	nt = efi_netobj_from_snp(this, true);
>
>   	if (this->mode->state == EFI_NETWORK_STOPPED) {
>   		ret = EFI_NOT_STARTED;
> @@ -250,7 +253,7 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this,
>   		r = EFI_INVALID_PARAMETER;
>   		goto out;
>   	}
> -	nt = efi_netobj_from_snp(this);
> +	nt = efi_netobj_from_snp(this, true);
>
>   	switch (this->mode->state) {
>   	case EFI_NETWORK_INITIALIZED:
> @@ -347,7 +350,7 @@ static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this)
>   		ret = EFI_INVALID_PARAMETER;
>   		goto out;
>   	}
> -	nt = efi_netobj_from_snp(this);
> +	nt = efi_netobj_from_snp(this, true);
>
>   	switch (this->mode->state) {
>   	case EFI_NETWORK_INITIALIZED:
> @@ -553,7 +556,7 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this,
>   		goto out;
>   	}
>
> -	nt = efi_netobj_from_snp(this);
> +	nt = efi_netobj_from_snp(this, true);
>
>   	switch (this->mode->state) {
>   	case EFI_NETWORK_STOPPED:
> @@ -614,7 +617,7 @@ static efi_status_t EFIAPI efi_net_transmit
>   		goto out;
>   	}
>
> -	nt = efi_netobj_from_snp(this);
> +	nt = efi_netobj_from_snp(this, true);
>
>   	/* We do not support jumbo packets */
>   	if (buffer_size > PKTSIZE_ALIGN) {
> @@ -712,7 +715,7 @@ static efi_status_t EFIAPI efi_net_receive
>   		goto out;
>   	}
>
> -	nt = efi_netobj_from_snp(this);
> +	nt = efi_netobj_from_snp(this, true);
>
>   	switch (this->mode->state) {
>   	case EFI_NETWORK_STOPPED:
> @@ -870,7 +873,7 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event,
>   	if (!this || this->mode->state != EFI_NETWORK_INITIALIZED)
>   		goto out;
>
> -	nt = efi_netobj_from_snp(this);
> +	nt = efi_netobj_from_snp(this, true);
>   	curr_efi_net_obj = nt->efi_seq_num;
>
>   	// The following only happens if the net obj was removed but the event
> @@ -1205,7 +1208,7 @@ static int efi_netobj_init(struct efi_net_obj *netobj)
>
>   	dev = netobj->dev;
>
> -	if (efi_netobj_is_active(netobj))
> +	if (efi_netobj_is_active(netobj) || !netobj->snp_owner)
>   		goto set_timers;
>
>   	if (!netobj->net_mode)
> @@ -1417,6 +1420,7 @@ struct efi_net_obj *efi_netobj_alloc(efi_handle_t handle,
>   			free(netobj->net->mode);
>   		free(netobj->net);
>   	}
> +	netobj->net = NULL;
>
>   	if (handle) {
>   		netobj->handle = handle;
> @@ -1429,6 +1433,8 @@ struct efi_net_obj *efi_netobj_alloc(efi_handle_t handle,
>   		}
>   	}
>
> +	netobj->snp_owner = efi_netobj_from_snp(net, true) ? false : true;
> +
>   	if (net) {
>   		netobj->net = net;
>   		netobj->net_mode = net->mode;
> @@ -1556,14 +1562,9 @@ int efi_net_unregister(void *ctx, struct event *event)
>   		return -1;
>   	}
>
> +	interface = NULL;
>   	if (drv != dev->driver) {
>   		ret = EFI_CALL(efi_disconnect_controller(netobj->handle, NULL, NULL));
> -		if (ret != EFI_SUCCESS)
> -			return -1;
> -		ret = EFI_CALL(efi_close_event(netobj->wait_for_packet));
> -		if (ret != EFI_SUCCESS)
> -			return -1;
> -		ret = EFI_CALL(efi_close_event(netobj->network_timer_event));
>   		if (ret != EFI_SUCCESS)
>   			return -1;
>
> @@ -1581,6 +1582,15 @@ int efi_net_unregister(void *ctx, struct event *event)
>   		}
>   	}
>
> +	if (netobj->snp_owner) {
> +		ret = EFI_CALL(efi_close_event(netobj->wait_for_packet));
> +		if (ret != EFI_SUCCESS)
> +			return -1;
> +		ret = EFI_CALL(efi_close_event(netobj->network_timer_event));
> +		if (ret != EFI_SUCCESS)
> +			return -1;
> +	}
> +
>   #if IS_ENABLED(CONFIG_EFI_IP4_CONFIG2_PROTOCOL)
>   	if (netobj->ip4_config2) {
>   		r = efi_ipconfig_unregister(netobj->handle, netobj->ip4_config2);
> @@ -1603,8 +1613,11 @@ int efi_net_unregister(void *ctx, struct event *event)
>   		ret = efi_delete_handle(netobj->handle);
>   		if (ret != EFI_SUCCESS)
>   			return -1;
> +	}
> +
> +	efi_free_pool(interface);
>
> -		efi_free_pool(interface);
> +	if (netobj->snp_owner) {
>   		if (netobj->net)
>   			free(netobj->net);
>   		if (netobj->net_mode)



More information about the U-Boot mailing list