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;
}
/**