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.cord...@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@10002000
efi_net: allocated EFI net device 1
, eth5: eth@10003000
efi_net: allocated EFI net device 2
, eth3: sbe5
efi_net: allocated EFI net device 3
, eth6: eth@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;
  }

  /**

Reply via email to