[PATCH 05/16] efi_net: efi_loader: Add efi_netobj_alloc to allocate an efi_net_obj

Heinrich Schuchardt xypron.glpk at gmx.de
Tue Apr 15 10:18:54 CEST 2025


On 11.03.25 17:47, Adriano Cordova wrote:
> Rework the logic to allocate an efi_net_obj and its members. An
> efi_net_obj now gets allocated only in efi_netobj_alloc.
>
> Signed-off-by: Adriano Cordova <adriano.cordova at canonical.com>
> ---
>   lib/efi_loader/efi_net.c | 131 ++++++++++++++++++++++++---------------
>   1 file changed, 80 insertions(+), 51 deletions(-)
>
> diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
> index a40d319a27f..a14ecf3d182 100644
> --- a/lib/efi_loader/efi_net.c
> +++ b/lib/efi_loader/efi_net.c
> @@ -1152,19 +1152,10 @@ static int efi_netobj_init(struct efi_net_obj *netobj)
>   	size_t *receive_lengths = NULL;
>   	int i, j;
>
> -	if (!netobj || efi_netobj_is_active(netobj))
> +	if (!netobj || !netobj->net || efi_netobj_is_active(netobj))
>   		return 0;
>
>   	dev = netobj->dev;
> -	if (!dev) {
> -		/* No network device active, don't expose any */
> -		return 0;
> -	}
> -
> -	if (!netobj->net)
> -		netobj->net = calloc(1, sizeof(*netobj->net));
> -	if (!netobj->net)
> -		goto out_of_resources;
>
>   	if (!netobj->net_mode)
>   		netobj->net_mode = calloc(1, sizeof(*netobj->net_mode));
> @@ -1344,6 +1335,84 @@ efi_status_t efi_net_init(void)
>   	return EFI_SUCCESS;
>   }
>
> +/**
> + * efi_netobj_alloc() - allocate an efi_net_obj from either a simple
> + *			network protocol interface or a net udevice
> + *
> + * @handle:	EFI handle
> + * @net:	pointer to simple network protocol
> + * @dev:	pointer to net udevice
> + * Return:	pointer to EFI net object, NULL on error
> + */
> +struct efi_net_obj *efi_netobj_alloc(efi_handle_t handle,
> +					struct efi_simple_network *net,
> +					struct udevice *dev)
> +{
> +	int i;
> +	struct efi_net_obj *netobj;
> +
> +	// Find a slot for this efi_net_obj
> +
> +	// Try to recycle
> +	for (i = 0; i < MAX_EFI_NET_OBJS; i++) {

We should avoid artificial limitations like MAX_EFI_NET_OBJS.

Objects that exist once per handle should be linked to the handle by
installing a protocol interface.

> +		if (net_objs[i] && !net_objs[i]->net && !net_objs[i]->dev && !net_objs[i]->handle)
> +			break;
> +	}
> +	if (i == MAX_EFI_NET_OBJS) {
> +		for (i = 0; i < MAX_EFI_NET_OBJS; i++) {
> +			if (!net_objs[i])
> +				break;
> +		}
> +	}
> +	if (i == MAX_EFI_NET_OBJS)
> +		return NULL;
> +
> +	if (!net_objs[i]) {
> +		netobj = calloc(1, sizeof(*netobj));
> +		net_objs[i] = netobj;
> +	} else {
> +		netobj = net_objs[i];
> +	}
> +	if (!netobj)
> +		return NULL;
> +
> +	if (netobj->net) {
> +		if (netobj->net->mode)
> +			free(netobj->net->mode);
> +		free(netobj->net);
> +	}
> +
> +	if (handle) {
> +		netobj->handle = handle;
> +	}
> +	else {
> +		netobj->handle = calloc(1, sizeof(*netobj->handle));

All handles in U-Boot have to be in a linked list, see
LIST_HEAD(efi_obj_list) in lib/efi_loader/efi_boottime.c.

The only way to create an EFI handle is by installing a protocol
interface calling InstallMultipleProtocolInterfaces(*handle) or
InstallProtocolInterface(*handle) with handle = NULL.


> +		if (!netobj->handle) {
> +			free(netobj);
> +			return NULL;
> +		}
> +	}
> +
> +	if (net) {
> +		netobj->net = net;
> +		netobj->net_mode = net->mode;
> +	} else {
> +		netobj->net = calloc(1, sizeof(*netobj->net));
> +		if (!netobj->net) {
> +			free(netobj->handle);

EFI handles can only be deleted by uninstalling all protocol interfaces.

> +			free(netobj);
> +			return NULL;
> +		}
> +	}
> +
> +	netobj->dev = dev;
> +	netobj->efi_seq_num = i;
> +
> +	printf("\nefi_net: allocated EFI net device %d\n", netobj->efi_seq_num);

This printf could be useful for debugging but it is disrupting the
output of network devices and nothing that an end user would be
interested in.

efi_net: allocated EFI net device 0
eth0: eth at 10002000
efi_net: allocated EFI net device 1
, eth5: eth at 10003000
efi_net: allocated EFI net device 2
, eth3: sbe5
efi_net: allocated EFI net device 3
, eth6: eth at 10004000
efi_net: allocated EFI net device 4
, eth8: phy-test-eth
efi_net: allocated EFI net device 5
, eth4: dsa-test-eth
efi_net: allocated EFI net device 6
, eth2: lan0
efi_net: allocated EFI net device 7
, eth7: lan1

How about:

log_debug("efinet %d\n", netobj->efi_seq_num);

Best regards

Heinrich

> +
> +	return netobj;
> +}
> +
>   /**
>    * efi_net_register() - register a net device
>    *
> @@ -1356,9 +1425,7 @@ efi_status_t efi_net_init(void)
>   int efi_net_register(void *ctx, struct event *event)
>   {
>   	struct udevice *dev;
> -	int seq_num;
>   	enum uclass_id id;
> -	struct efi_net_obj *netobj;
>   	int i;
>
>   	dev = event->data.dm.dev;
> @@ -1378,48 +1445,10 @@ int efi_net_register(void *ctx, struct event *event)
>   		}
>   	}
>
> -	// Find a slot for this efi_net_obj
> -	seq_num = -1;
> -	// Try to recycle
> -	for (i = 0; i < MAX_EFI_NET_OBJS; i++) {
> -		if (net_objs[i] && !net_objs[i]->dev) {
> -			seq_num = i;
> -			break;
> -		}
> -	}
> -	if (seq_num < 0) {
> -		for (i = 0; i < MAX_EFI_NET_OBJS; i++) {
> -			if (!net_objs[i]) {
> -				seq_num = i;
> -				break;
> -			}
> -		}
> -	}
> -	if (seq_num < 0)
> +	if (!efi_netobj_alloc(NULL, NULL, dev))
>   		return -1;
>
> -	if (!net_objs[seq_num]) {
> -		netobj = calloc(1, sizeof(*netobj));
> -		net_objs[seq_num] = netobj;
> -	} else {
> -		netobj = net_objs[seq_num];
> -	}
> -	if (!netobj)
> -		goto out_of_resources;
> -
> -	netobj->handle = calloc(1, sizeof(*netobj->handle));
> -	if (!netobj->handle) {
> -		free(netobj);
> -		goto out_of_resources;
> -	}
> -
> -	netobj->dev = dev;
> -	netobj->efi_seq_num = seq_num;
> -	printf("efi_net registered device number %d\n", netobj->efi_seq_num);
>   	return 0;
> -out_of_resources:
> -	printf("ERROR: Out of memory\n");
> -	return -1;
>   }
>
>   /**



More information about the U-Boot mailing list