efi_loader: efi_device_path: Pass net udevice as argument

In preparation to support multiple EFI net objects, support
constructing device paths using an ethernet device different
than the default. Add a udevice argument to the device path
generation, and keep the callsites with eth_get_dev() to
preserve existing functionality.

Signed-off-by: Adriano Cordova <adriano.cordova@canonical.com>
This commit is contained in:
Adriano Cordova
2025-03-03 11:13:14 -03:00
committed by Heinrich Schuchardt
parent 6a832d4b2e
commit 267b0a7ddf
3 changed files with 23 additions and 61 deletions

View File

@@ -925,8 +925,8 @@ struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part);
struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part); struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part);
struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp, struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp,
const char *path); const char *path);
struct efi_device_path *efi_dp_from_eth(void); struct efi_device_path *efi_dp_from_eth(struct udevice *dev);
struct efi_device_path *efi_dp_from_http(const char *server); struct efi_device_path *efi_dp_from_http(const char *server, struct udevice *dev);
struct efi_device_path *efi_dp_from_mem(uint32_t mem_type, struct efi_device_path *efi_dp_from_mem(uint32_t mem_type,
uint64_t start_address, uint64_t start_address,
size_t size); size_t size);

View File

@@ -954,20 +954,20 @@ struct efi_device_path *efi_dp_from_uart(void)
return buf; return buf;
} }
struct efi_device_path __maybe_unused *efi_dp_from_eth(void) struct efi_device_path __maybe_unused *efi_dp_from_eth(struct udevice *dev)
{ {
void *buf, *start; void *buf, *start;
unsigned dpsize = 0; unsigned dpsize = 0;
assert(eth_get_dev()); assert(dev);
dpsize += dp_size(eth_get_dev()); dpsize += dp_size(dev);
start = buf = efi_alloc(dpsize + sizeof(END)); start = buf = efi_alloc(dpsize + sizeof(END));
if (!buf) if (!buf)
return NULL; return NULL;
buf = dp_fill(buf, eth_get_dev()); buf = dp_fill(buf, dev);
*((struct efi_device_path *)buf) = END; *((struct efi_device_path *)buf) = END;
@@ -984,11 +984,13 @@ struct efi_device_path __maybe_unused *efi_dp_from_eth(void)
* @ip: IPv4 local address * @ip: IPv4 local address
* @mask: network mask * @mask: network mask
* @srv: IPv4 remote/server address * @srv: IPv4 remote/server address
* @dev: net udevice
* Return: pointer to device path, NULL on error * Return: pointer to device path, NULL on error
*/ */
static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip, static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip,
struct efi_ipv4_address *mask, struct efi_ipv4_address *mask,
struct efi_ipv4_address *srv) struct efi_ipv4_address *srv,
struct udevice *dev)
{ {
struct efi_device_path *dp1, *dp2, *pos; struct efi_device_path *dp1, *dp2, *pos;
struct { struct {
@@ -1010,7 +1012,7 @@ static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip,
pos = &dp.end; pos = &dp.end;
memcpy(pos, &END, sizeof(END)); memcpy(pos, &END, sizeof(END));
dp1 = efi_dp_from_eth(); dp1 = efi_dp_from_eth(dev);
if (!dp1) if (!dp1)
return NULL; return NULL;
@@ -1029,9 +1031,10 @@ static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip,
* and an END node. * and an END node.
* *
* @server: URI of remote server * @server: URI of remote server
* @dev: net udevice
* Return: pointer to HTTP device path, NULL on error * Return: pointer to HTTP device path, NULL on error
*/ */
struct efi_device_path *efi_dp_from_http(const char *server) struct efi_device_path *efi_dp_from_http(const char *server, struct udevice *dev)
{ {
struct efi_device_path *dp1, *dp2; struct efi_device_path *dp1, *dp2;
struct efi_device_path_uri *uridp; struct efi_device_path_uri *uridp;
@@ -1047,10 +1050,11 @@ struct efi_device_path *efi_dp_from_http(const char *server)
efi_net_get_addr(&ip, &mask, NULL); efi_net_get_addr(&ip, &mask, NULL);
dp1 = efi_dp_from_ipv4(&ip, &mask, NULL); dp1 = efi_dp_from_ipv4(&ip, &mask, NULL, dev);
if (!dp1) if (!dp1)
return NULL; return NULL;
strcpy(tmp, "http://"); strcpy(tmp, "http://");
if (server) { if (server) {

View File

@@ -952,14 +952,12 @@ efi_status_t efi_net_register(void)
if (r != EFI_SUCCESS) if (r != EFI_SUCCESS)
goto failure_to_add_protocol; goto failure_to_add_protocol;
if (net_dp) if (!net_dp)
r = efi_add_protocol(&netobj->header, &efi_guid_device_path, efi_net_set_dp("Net", NULL);
net_dp); r = efi_add_protocol(&netobj->header, &efi_guid_device_path,
else net_dp);
r = efi_net_set_dp("Net", NULL);
if (r != EFI_SUCCESS) if (r != EFI_SUCCESS)
goto failure_to_add_protocol; goto failure_to_add_protocol;
r = efi_add_protocol(&netobj->header, &efi_pxe_base_code_protocol_guid, r = efi_add_protocol(&netobj->header, &efi_pxe_base_code_protocol_guid,
&netobj->pxe); &netobj->pxe);
if (r != EFI_SUCCESS) if (r != EFI_SUCCESS)
@@ -1077,58 +1075,18 @@ out_of_resources:
*/ */
efi_status_t efi_net_set_dp(const char *dev, const char *server) efi_status_t efi_net_set_dp(const char *dev, const char *server)
{ {
efi_status_t ret = EFI_SUCCESS; efi_free_pool(net_dp);
struct efi_handler *phandler;
struct efi_device_path *old_net_dp, *new_net_dp;
old_net_dp = net_dp; net_dp = NULL;
new_net_dp = NULL;
if (!strcmp(dev, "Net")) if (!strcmp(dev, "Net"))
new_net_dp = efi_dp_from_eth(); net_dp = efi_dp_from_eth(eth_get_dev());
else if (!strcmp(dev, "Http")) else if (!strcmp(dev, "Http"))
new_net_dp = efi_dp_from_http(server); net_dp = efi_dp_from_http(server, eth_get_dev());
if (!new_net_dp) { if (!net_dp)
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;
}
// If netobj is not started yet, end here.
if (!netobj) {
goto exit;
}
phandler = NULL;
efi_search_protocol(&netobj->header, &efi_guid_device_path, &phandler);
// If the device path protocol is not yet installed, install it
if (!phandler)
goto add;
// If it is already installed, try to update it
ret = efi_reinstall_protocol_interface(&netobj->header, &efi_guid_device_path,
old_net_dp, new_net_dp);
if (ret != EFI_SUCCESS)
goto error;
net_dp = new_net_dp;
efi_free_pool(old_net_dp);
return EFI_SUCCESS; return EFI_SUCCESS;
add:
ret = efi_add_protocol(&netobj->header, &efi_guid_device_path,
new_net_dp);
if (ret != EFI_SUCCESS)
goto error;
exit:
net_dp = new_net_dp;
efi_free_pool(old_net_dp);
return ret;
error:
// Failed, restore
efi_free_pool(new_net_dp);
return ret;
} }
/** /**