mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-02 17:56:44 +03:00
efi_loader: efi_net: Add device path cache
In preparation to support mutiple efi net udevices. Add a device path cache to support device paths from multiple ethernet udevices. The device paths can be added to the cache before EFI gets initialized and the protocols get installed. Signed-off-by: Adriano Cordova <adriano.cordova@canonical.com>
This commit is contained in:
committed by
Heinrich Schuchardt
parent
267b0a7ddf
commit
dd5d82a599
@@ -129,15 +129,17 @@ static inline void efi_set_bootdev(const char *dev, const char *devnr,
|
||||
|
||||
#if CONFIG_IS_ENABLED(NETDEVICES) && CONFIG_IS_ENABLED(EFI_LOADER)
|
||||
/* Call this to update the current device path of the efi net device */
|
||||
efi_status_t efi_net_set_dp(const char *dev, const char *server);
|
||||
efi_status_t efi_net_new_dp(const char *dev, const char *server, struct udevice *udev);
|
||||
/* Call this to get the current device path of the efi net device */
|
||||
void efi_net_get_dp(struct efi_device_path **dp);
|
||||
void efi_net_dp_from_dev(struct efi_device_path **dp, struct udevice *udev, bool cache_only);
|
||||
void efi_net_get_addr(struct efi_ipv4_address *ip,
|
||||
struct efi_ipv4_address *mask,
|
||||
struct efi_ipv4_address *gw);
|
||||
struct efi_ipv4_address *gw,
|
||||
struct udevice *dev);
|
||||
void efi_net_set_addr(struct efi_ipv4_address *ip,
|
||||
struct efi_ipv4_address *mask,
|
||||
struct efi_ipv4_address *gw);
|
||||
struct efi_ipv4_address *gw,
|
||||
struct udevice *dev);
|
||||
efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buffer,
|
||||
u32 *status_code, ulong *file_size, char *headers_buffer);
|
||||
#define MAX_HTTP_HEADERS_SIZE SZ_64K
|
||||
@@ -151,13 +153,16 @@ struct http_header {
|
||||
|
||||
void efi_net_parse_headers(ulong *num_headers, struct http_header *headers);
|
||||
#else
|
||||
static inline void efi_net_get_dp(struct efi_device_path **dp) { }
|
||||
static inline void efi_net_dp_from_dev(struct efi_device_path **dp,
|
||||
struct udevice *udev, bool cache_only) { }
|
||||
static inline void efi_net_get_addr(struct efi_ipv4_address *ip,
|
||||
struct efi_ipv4_address *mask,
|
||||
struct efi_ipv4_address *gw) { }
|
||||
struct efi_ipv4_address *gw,
|
||||
struct udevice *dev) { }
|
||||
static inline void efi_net_set_addr(struct efi_ipv4_address *ip,
|
||||
struct efi_ipv4_address *mask,
|
||||
struct efi_ipv4_address *gw) { }
|
||||
struct efi_ipv4_address *gw,
|
||||
struct udevice *dev) { }
|
||||
#endif
|
||||
|
||||
/* Maximum number of configuration tables */
|
||||
@@ -649,8 +654,8 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
|
||||
/* Called by bootefi to make GOP (graphical) interface available */
|
||||
efi_status_t efi_gop_register(void);
|
||||
/* Called by bootefi to make the network interface available */
|
||||
efi_status_t efi_net_register(void);
|
||||
efi_status_t efi_net_do_start(void);
|
||||
efi_status_t efi_net_register(struct udevice *dev);
|
||||
efi_status_t efi_net_do_start(struct udevice *dev);
|
||||
/* Called by efi_net_register to make the ip4 config2 protocol available */
|
||||
efi_status_t efi_ipconfig_register(const efi_handle_t handle,
|
||||
struct efi_ip4_config2_protocol *ip4config);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <log.h>
|
||||
#include <malloc.h>
|
||||
#include <mapmem.h>
|
||||
#include <net.h>
|
||||
|
||||
static struct efi_device_path *bootefi_image_path;
|
||||
static struct efi_device_path *bootefi_device_path;
|
||||
@@ -67,7 +68,7 @@ static efi_status_t calculate_paths(const char *dev, const char *devnr,
|
||||
|
||||
#if IS_ENABLED(CONFIG_NETDEVICES)
|
||||
if (!strcmp(dev, "Net") || !strcmp(dev, "Http")) {
|
||||
ret = efi_net_set_dp(dev, devnr);
|
||||
ret = efi_net_new_dp(dev, devnr, eth_get_dev());
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1048,7 +1048,7 @@ struct efi_device_path *efi_dp_from_http(const char *server, struct udevice *dev
|
||||
(!server && IS_ENABLED(CONFIG_NET_LWIP)))
|
||||
return NULL;
|
||||
|
||||
efi_net_get_addr(&ip, &mask, NULL);
|
||||
efi_net_get_addr(&ip, &mask, NULL, dev);
|
||||
|
||||
dp1 = efi_dp_from_ipv4(&ip, &mask, NULL, dev);
|
||||
if (!dp1)
|
||||
@@ -1189,8 +1189,8 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
|
||||
dp = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
|
||||
(uintptr_t)image_addr, image_size);
|
||||
} else if (IS_ENABLED(CONFIG_NETDEVICES) &&
|
||||
(!strcmp(dev, "Net") || !strcmp(dev, "Http"))) {
|
||||
efi_net_get_dp(&dp);
|
||||
(!strcmp(dev, "Net") || !strcmp(dev, "Http"))) {
|
||||
efi_net_dp_from_dev(&dp, eth_get_dev(), false);
|
||||
} else if (!strcmp(dev, "Uart")) {
|
||||
dp = efi_dp_from_uart();
|
||||
} else {
|
||||
|
||||
@@ -188,7 +188,7 @@ static efi_status_t EFIAPI efi_http_configure(struct efi_http_protocol *this,
|
||||
|
||||
if (!ipv4_node->use_default_address) {
|
||||
efi_net_set_addr((struct efi_ipv4_address *)&ipv4_node->local_address,
|
||||
(struct efi_ipv4_address *)&ipv4_node->local_subnet, NULL);
|
||||
(struct efi_ipv4_address *)&ipv4_node->local_subnet, NULL, NULL);
|
||||
}
|
||||
|
||||
http_instance->current_offset = 0;
|
||||
|
||||
@@ -60,7 +60,7 @@ static efi_status_t EFIAPI efi_ip4_config2_set_data(struct efi_ip4_config2_proto
|
||||
memcpy((void *)¤t_http_ip, data,
|
||||
sizeof(struct efi_ip4_config2_manual_address));
|
||||
efi_net_set_addr(¤t_http_ip.address,
|
||||
¤t_http_ip.subnet_mask, NULL);
|
||||
¤t_http_ip.subnet_mask, NULL, NULL);
|
||||
return EFI_EXIT(EFI_SUCCESS);
|
||||
}
|
||||
return EFI_EXIT(EFI_BAD_BUFFER_SIZE);
|
||||
@@ -133,7 +133,7 @@ static efi_status_t EFIAPI efi_ip4_config2_get_data(struct efi_ip4_config2_proto
|
||||
return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
|
||||
}
|
||||
|
||||
efi_net_get_addr(¤t_http_ip.address, ¤t_http_ip.subnet_mask, NULL);
|
||||
efi_net_get_addr(¤t_http_ip.address, ¤t_http_ip.subnet_mask, NULL, NULL);
|
||||
memcpy(data, (void *)¤t_http_ip,
|
||||
sizeof(struct efi_ip4_config2_manual_address));
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <vsprintf.h>
|
||||
#include <net.h>
|
||||
|
||||
#define MAX_NUM_DP_ENTRIES 10
|
||||
|
||||
const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
|
||||
static const efi_guid_t efi_pxe_base_code_protocol_guid =
|
||||
EFI_PXE_BASE_CODE_PROTOCOL_GUID;
|
||||
@@ -36,18 +38,28 @@ static int rx_packet_idx;
|
||||
static int rx_packet_num;
|
||||
static struct efi_net_obj *netobj;
|
||||
|
||||
/*
|
||||
* The current network device path. This device path is updated when a new
|
||||
* bootfile is downloaded from the network. If then the bootfile is loaded
|
||||
* as an efi image, net_dp is passed as the device path of the loaded image.
|
||||
*/
|
||||
static struct efi_device_path *net_dp;
|
||||
struct dp_entry {
|
||||
struct efi_device_path *net_dp;
|
||||
struct udevice *dev;
|
||||
bool is_valid;
|
||||
};
|
||||
|
||||
/*
|
||||
* The network device path cache. An entry is added when a new bootfile
|
||||
* is downloaded from the network. If the bootfile is then loaded as an
|
||||
* efi image, the most recent entry corresponding to the device is passed
|
||||
* as the device path of the loaded image.
|
||||
*/
|
||||
static struct dp_entry dp_cache[MAX_NUM_DP_ENTRIES];
|
||||
static int next_dp_entry;
|
||||
|
||||
#if IS_ENABLED(CONFIG_EFI_HTTP_PROTOCOL)
|
||||
static struct wget_http_info efi_wget_info = {
|
||||
.set_bootdev = false,
|
||||
.check_buffer_size = true,
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The notification function of this event is called in every timer cycle
|
||||
@@ -63,6 +75,7 @@ static struct efi_event *wait_for_packet;
|
||||
* struct efi_net_obj - EFI object representing a network interface
|
||||
*
|
||||
* @header: EFI object header
|
||||
* @dev: net udevice
|
||||
* @net: simple network protocol interface
|
||||
* @net_mode: status of the network interface
|
||||
* @pxe: PXE base code protocol interface
|
||||
@@ -72,6 +85,7 @@ static struct efi_event *wait_for_packet;
|
||||
*/
|
||||
struct efi_net_obj {
|
||||
struct efi_object header;
|
||||
struct udevice *dev;
|
||||
struct efi_simple_network net;
|
||||
struct efi_simple_network_mode net_mode;
|
||||
struct efi_pxe_base_code_protocol pxe;
|
||||
@@ -84,6 +98,21 @@ struct efi_net_obj {
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* efi_netobj_is_active() - checks if a netobj is active in the efi subsystem
|
||||
*
|
||||
* @netobj: pointer to efi_net_obj
|
||||
* Return: true if active
|
||||
*/
|
||||
static bool efi_netobj_is_active(struct efi_net_obj *netobj)
|
||||
{
|
||||
if (!netobj || !efi_search_obj(&netobj->header))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* efi_net_start() - start the network interface
|
||||
*
|
||||
@@ -99,7 +128,6 @@ static efi_status_t EFIAPI efi_net_start(struct efi_simple_network *this)
|
||||
efi_status_t ret = EFI_SUCCESS;
|
||||
|
||||
EFI_ENTRY("%p", this);
|
||||
|
||||
/* Check parameters */
|
||||
if (!this) {
|
||||
ret = EFI_INVALID_PARAMETER;
|
||||
@@ -143,6 +171,8 @@ static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this)
|
||||
ret = EFI_NOT_STARTED;
|
||||
} else {
|
||||
/* Disable hardware and put it into the reset state */
|
||||
eth_set_dev(netobj->dev);
|
||||
env_set("ethact", eth_get_name());
|
||||
eth_halt();
|
||||
/* Clear cache of packets */
|
||||
rx_packet_num = 0;
|
||||
@@ -189,14 +219,13 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this,
|
||||
|
||||
/* Setup packet buffers */
|
||||
net_init();
|
||||
/* Disable hardware and put it into the reset state */
|
||||
eth_halt();
|
||||
/* Clear cache of packets */
|
||||
rx_packet_num = 0;
|
||||
/* Set current device according to environment variables */
|
||||
eth_set_current();
|
||||
/* Set the net device corresponding to the efi net object */
|
||||
eth_set_dev(netobj->dev);
|
||||
env_set("ethact", eth_get_name());
|
||||
/* Get hardware ready for send and receive operations */
|
||||
ret = eth_init();
|
||||
ret = eth_start_udev(netobj->dev);
|
||||
if (ret < 0) {
|
||||
eth_halt();
|
||||
this->mode->state = EFI_NETWORK_STOPPED;
|
||||
@@ -285,6 +314,8 @@ static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this)
|
||||
goto out;
|
||||
}
|
||||
|
||||
eth_set_dev(netobj->dev);
|
||||
env_set("ethact", eth_get_name());
|
||||
eth_halt();
|
||||
this->int_status = 0;
|
||||
wait_for_packet->is_signaled = false;
|
||||
@@ -576,6 +607,9 @@ static efi_status_t EFIAPI efi_net_transmit
|
||||
break;
|
||||
}
|
||||
|
||||
eth_set_dev(netobj->dev);
|
||||
env_set("ethact", eth_get_name());
|
||||
|
||||
/* Ethernet packets always fit, just bounce */
|
||||
memcpy(transmit_buffer, buffer, buffer_size);
|
||||
net_send_packet(transmit_buffer, buffer_size);
|
||||
@@ -753,6 +787,8 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event,
|
||||
goto out;
|
||||
|
||||
if (!rx_packet_num) {
|
||||
eth_set_dev(netobj->dev);
|
||||
env_set("ethact", eth_get_name());
|
||||
push_packet = efi_net_push;
|
||||
eth_rx();
|
||||
push_packet = NULL;
|
||||
@@ -878,17 +914,106 @@ static efi_status_t EFIAPI efi_pxe_base_code_set_packets(
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_netobj_set_dp() - set device path of a netobj
|
||||
*
|
||||
* @netobj: pointer to efi_net_obj
|
||||
* @dp: device path to set, allocated by caller
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_netobj_set_dp(struct efi_net_obj *netobj, struct efi_device_path *dp)
|
||||
{
|
||||
efi_status_t ret;
|
||||
struct efi_handler *phandler;
|
||||
struct efi_device_path *new_net_dp;
|
||||
|
||||
if (!efi_netobj_is_active(netobj))
|
||||
return EFI_SUCCESS;
|
||||
|
||||
// Create a device path for the netobj
|
||||
new_net_dp = dp;
|
||||
if (!new_net_dp)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
||||
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,
|
||||
phandler->protocol_interface, new_net_dp);
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
add:
|
||||
ret = efi_add_protocol(&netobj->header, &efi_guid_device_path,
|
||||
new_net_dp);
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_netobj_get_dp() - get device path of a netobj
|
||||
*
|
||||
* @netobj: pointer to efi_net_obj
|
||||
* Return: device path, NULL on error
|
||||
*/
|
||||
static struct efi_device_path *efi_netobj_get_dp(struct efi_net_obj *netobj)
|
||||
{
|
||||
struct efi_handler *phandler;
|
||||
|
||||
if (!efi_netobj_is_active(netobj))
|
||||
return NULL;
|
||||
|
||||
phandler = NULL;
|
||||
efi_search_protocol(&netobj->header, &efi_guid_device_path, &phandler);
|
||||
|
||||
if (phandler && phandler->protocol_interface)
|
||||
return efi_dp_dup(phandler->protocol_interface);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_net_do_start() - start the efi network stack
|
||||
*
|
||||
* This gets called from do_bootefi_exec() each time a payload gets executed.
|
||||
*
|
||||
* @dev: net udevice
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_net_do_start(void)
|
||||
efi_status_t efi_net_do_start(struct udevice *dev)
|
||||
{
|
||||
efi_status_t r = EFI_SUCCESS;
|
||||
struct efi_device_path *net_dp;
|
||||
|
||||
if (dev != netobj->dev )
|
||||
return r;
|
||||
|
||||
efi_net_dp_from_dev(&net_dp, netobj->dev, true);
|
||||
// If no dp cache entry applies and there already
|
||||
// is a device path installed, continue
|
||||
if (!net_dp) {
|
||||
if (efi_netobj_get_dp(netobj))
|
||||
goto set_addr;
|
||||
else
|
||||
net_dp = efi_dp_from_eth(netobj->dev);
|
||||
|
||||
}
|
||||
|
||||
if (!net_dp)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
||||
r = efi_netobj_set_dp(netobj, net_dp);
|
||||
if (r != EFI_SUCCESS)
|
||||
return r;
|
||||
set_addr:
|
||||
#ifdef CONFIG_EFI_HTTP_PROTOCOL
|
||||
/*
|
||||
* No harm on doing the following. If the PXE handle is present, the client could
|
||||
@@ -896,7 +1021,7 @@ efi_status_t efi_net_do_start(void)
|
||||
* but the PXE protocol is not yet implmenented, so we add this in the meantime.
|
||||
*/
|
||||
efi_net_get_addr((struct efi_ipv4_address *)&netobj->pxe_mode.station_ip,
|
||||
(struct efi_ipv4_address *)&netobj->pxe_mode.subnet_mask, NULL);
|
||||
(struct efi_ipv4_address *)&netobj->pxe_mode.subnet_mask, NULL, dev);
|
||||
#endif
|
||||
|
||||
return r;
|
||||
@@ -906,13 +1031,14 @@ efi_status_t efi_net_do_start(void)
|
||||
* efi_net_register() - register the simple network protocol
|
||||
*
|
||||
* This gets called from do_bootefi_exec().
|
||||
* @dev: net udevice
|
||||
*/
|
||||
efi_status_t efi_net_register(void)
|
||||
efi_status_t efi_net_register(struct udevice *dev)
|
||||
{
|
||||
efi_status_t r;
|
||||
int i;
|
||||
|
||||
if (!eth_get_dev()) {
|
||||
if (!dev) {
|
||||
/* No network device active, don't expose any */
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@@ -922,6 +1048,8 @@ efi_status_t efi_net_register(void)
|
||||
if (!netobj)
|
||||
goto out_of_resources;
|
||||
|
||||
netobj->dev = dev;
|
||||
|
||||
/* Allocate an aligned transmit buffer */
|
||||
transmit_buffer = calloc(1, PKTSIZE_ALIGN + PKTALIGN);
|
||||
if (!transmit_buffer)
|
||||
@@ -938,6 +1066,7 @@ efi_status_t efi_net_register(void)
|
||||
if (!receive_buffer[i])
|
||||
goto out_of_resources;
|
||||
}
|
||||
|
||||
receive_lengths = calloc(ETH_PACKETS_BATCH_RECV,
|
||||
sizeof(*receive_lengths));
|
||||
if (!receive_lengths)
|
||||
@@ -952,12 +1081,6 @@ efi_status_t efi_net_register(void)
|
||||
if (r != EFI_SUCCESS)
|
||||
goto failure_to_add_protocol;
|
||||
|
||||
if (!net_dp)
|
||||
efi_net_set_dp("Net", NULL);
|
||||
r = efi_add_protocol(&netobj->header, &efi_guid_device_path,
|
||||
net_dp);
|
||||
if (r != EFI_SUCCESS)
|
||||
goto failure_to_add_protocol;
|
||||
r = efi_add_protocol(&netobj->header, &efi_pxe_base_code_protocol_guid,
|
||||
&netobj->pxe);
|
||||
if (r != EFI_SUCCESS)
|
||||
@@ -978,7 +1101,9 @@ efi_status_t efi_net_register(void)
|
||||
netobj->net.receive = efi_net_receive;
|
||||
netobj->net.mode = &netobj->net_mode;
|
||||
netobj->net_mode.state = EFI_NETWORK_STOPPED;
|
||||
memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6);
|
||||
if (dev_get_plat(dev))
|
||||
memcpy(netobj->net_mode.current_address.mac_addr,
|
||||
((struct eth_pdata *)dev_get_plat(dev))->enetaddr, 6);
|
||||
netobj->net_mode.hwaddr_size = ARP_HLEN;
|
||||
netobj->net_mode.media_header_size = ETHER_HDR_SIZE;
|
||||
netobj->net_mode.max_packet_size = PKTSIZE;
|
||||
@@ -1012,6 +1137,7 @@ efi_status_t efi_net_register(void)
|
||||
return r;
|
||||
}
|
||||
netobj->net.wait_for_packet = wait_for_packet;
|
||||
|
||||
/*
|
||||
* Create a timer event.
|
||||
*
|
||||
@@ -1045,7 +1171,6 @@ efi_status_t efi_net_register(void)
|
||||
if (r != EFI_SUCCESS)
|
||||
goto failure_to_add_protocol;
|
||||
#endif
|
||||
|
||||
return EFI_SUCCESS;
|
||||
failure_to_add_protocol:
|
||||
printf("ERROR: Failure to add protocol\n");
|
||||
@@ -1064,46 +1189,91 @@ out_of_resources:
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_net_set_dp() - set device path of efi net device
|
||||
* efi_net_new_dp() - update device path associated to a net udevice
|
||||
*
|
||||
* This gets called to update the device path when a new boot
|
||||
* file is downloaded
|
||||
*
|
||||
* @dev: dev to set the device path from
|
||||
* @server: remote server address
|
||||
* @udev: net udevice
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_net_set_dp(const char *dev, const char *server)
|
||||
efi_status_t efi_net_new_dp(const char *dev, const char *server, struct udevice *udev)
|
||||
{
|
||||
efi_free_pool(net_dp);
|
||||
efi_status_t ret;
|
||||
struct efi_device_path *old_net_dp, *new_net_dp;
|
||||
struct efi_device_path **dp;
|
||||
|
||||
net_dp = NULL;
|
||||
dp = &dp_cache[next_dp_entry].net_dp;
|
||||
|
||||
dp_cache[next_dp_entry].dev = udev;
|
||||
dp_cache[next_dp_entry].is_valid = true;
|
||||
next_dp_entry++;
|
||||
next_dp_entry %= MAX_NUM_DP_ENTRIES;
|
||||
|
||||
old_net_dp = *dp;
|
||||
new_net_dp = NULL;
|
||||
if (!strcmp(dev, "Net"))
|
||||
net_dp = efi_dp_from_eth(eth_get_dev());
|
||||
new_net_dp = efi_dp_from_eth(udev);
|
||||
else if (!strcmp(dev, "Http"))
|
||||
net_dp = efi_dp_from_http(server, eth_get_dev());
|
||||
|
||||
if (!net_dp)
|
||||
new_net_dp = efi_dp_from_http(server, udev);
|
||||
if (!new_net_dp)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
*dp = new_net_dp;
|
||||
// Free the old cache entry
|
||||
efi_free_pool(old_net_dp);
|
||||
|
||||
if (!netobj || netobj->dev != udev)
|
||||
return EFI_SUCCESS;
|
||||
|
||||
new_net_dp = efi_dp_dup(*dp);
|
||||
if (!new_net_dp)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
ret = efi_netobj_set_dp(netobj, new_net_dp);
|
||||
if (ret != EFI_SUCCESS)
|
||||
efi_free_pool(new_net_dp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_net_get_dp() - get device path of efi net device
|
||||
* efi_net_dp_from_dev() - get device path associated to a net udevice
|
||||
*
|
||||
* Produce a copy of the current device path
|
||||
*
|
||||
* @dp: copy of the current device path, or NULL on error
|
||||
* @dp: copy of the current device path
|
||||
* @udev: net udevice
|
||||
* @cache_only: get device path from cache only
|
||||
*/
|
||||
void efi_net_get_dp(struct efi_device_path **dp)
|
||||
void efi_net_dp_from_dev(struct efi_device_path **dp, struct udevice *udev, bool cache_only)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!dp)
|
||||
return;
|
||||
if (!net_dp)
|
||||
efi_net_set_dp("Net", NULL);
|
||||
if (net_dp)
|
||||
*dp = efi_dp_dup(net_dp);
|
||||
|
||||
*dp = NULL;
|
||||
|
||||
if (cache_only)
|
||||
goto cache;
|
||||
|
||||
if (netobj && netobj->dev == udev) {
|
||||
*dp = efi_netobj_get_dp(netobj);
|
||||
if (*dp)
|
||||
return;
|
||||
}
|
||||
cache:
|
||||
// Search in the cache
|
||||
i = (next_dp_entry + MAX_NUM_DP_ENTRIES - 1) % MAX_NUM_DP_ENTRIES;
|
||||
for (j = 0; dp_cache[i].is_valid && j < MAX_NUM_DP_ENTRIES;
|
||||
i = (i + MAX_NUM_DP_ENTRIES - 1) % MAX_NUM_DP_ENTRIES, j++) {
|
||||
if (dp_cache[i].dev == udev) {
|
||||
*dp = efi_dp_dup(dp_cache[i].net_dp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1119,11 +1289,15 @@ void efi_net_get_dp(struct efi_device_path **dp)
|
||||
* be filled with the current network mask
|
||||
* @gw: pointer to an efi_ipv4_address struct to be
|
||||
* filled with the current network gateway
|
||||
* @dev: udevice
|
||||
*/
|
||||
void efi_net_get_addr(struct efi_ipv4_address *ip,
|
||||
struct efi_ipv4_address *mask,
|
||||
struct efi_ipv4_address *gw)
|
||||
struct efi_ipv4_address *gw,
|
||||
struct udevice *dev)
|
||||
{
|
||||
if (!dev)
|
||||
dev = eth_get_dev();
|
||||
#ifdef CONFIG_NET_LWIP
|
||||
char ipstr[] = "ipaddr\0\0";
|
||||
char maskstr[] = "netmask\0\0";
|
||||
@@ -1132,7 +1306,7 @@ void efi_net_get_addr(struct efi_ipv4_address *ip,
|
||||
struct in_addr tmp;
|
||||
char *env;
|
||||
|
||||
idx = dev_seq(eth_get_dev());
|
||||
idx = dev_seq(dev);
|
||||
|
||||
if (idx < 0 || idx > 99) {
|
||||
log_err("unexpected idx %d\n", idx);
|
||||
@@ -1179,11 +1353,15 @@ void efi_net_get_addr(struct efi_ipv4_address *ip,
|
||||
* @ip: pointer to new IP address
|
||||
* @mask: pointer to new network mask to set
|
||||
* @gw: pointer to new network gateway
|
||||
* @dev: udevice
|
||||
*/
|
||||
void efi_net_set_addr(struct efi_ipv4_address *ip,
|
||||
struct efi_ipv4_address *mask,
|
||||
struct efi_ipv4_address *gw)
|
||||
struct efi_ipv4_address *gw,
|
||||
struct udevice *dev)
|
||||
{
|
||||
if (!dev)
|
||||
dev = eth_get_dev();
|
||||
#ifdef CONFIG_NET_LWIP
|
||||
char ipstr[] = "ipaddr\0\0";
|
||||
char maskstr[] = "netmask\0\0";
|
||||
@@ -1192,7 +1370,7 @@ void efi_net_set_addr(struct efi_ipv4_address *ip,
|
||||
struct in_addr *addr;
|
||||
char tmp[46];
|
||||
|
||||
idx = dev_seq(eth_get_dev());
|
||||
idx = dev_seq(dev);
|
||||
|
||||
if (idx < 0 || idx > 99) {
|
||||
log_err("unexpected idx %d\n", idx);
|
||||
@@ -1230,6 +1408,7 @@ void efi_net_set_addr(struct efi_ipv4_address *ip,
|
||||
#endif
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_EFI_HTTP_PROTOCOL)
|
||||
/**
|
||||
* efi_net_set_buffer() - allocate a buffer of min 64K
|
||||
*
|
||||
@@ -1337,6 +1516,8 @@ efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buf
|
||||
ret = efi_net_set_buffer(buffer, last_head ? (size_t)efi_wget_info.hdr_cont_len : 0);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
eth_set_dev(netobj->dev);
|
||||
env_set("ethact", eth_get_name());
|
||||
wget_ret = wget_request((ulong)*buffer, url, &efi_wget_info);
|
||||
if ((ulong)efi_wget_info.hdr_cont_len > efi_wget_info.buffer_size) {
|
||||
// Try again with updated buffer size
|
||||
@@ -1344,6 +1525,8 @@ efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buf
|
||||
ret = efi_net_set_buffer(buffer, (size_t)efi_wget_info.hdr_cont_len);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
eth_set_dev(netobj->dev);
|
||||
env_set("ethact", eth_get_name());
|
||||
if (wget_request((ulong)*buffer, url, &efi_wget_info)) {
|
||||
efi_free_pool(*buffer);
|
||||
ret = EFI_DEVICE_ERROR;
|
||||
@@ -1363,6 +1546,8 @@ efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buf
|
||||
ret = efi_net_set_buffer(buffer, 0);
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
eth_set_dev(netobj->dev);
|
||||
env_set("ethact", eth_get_name());
|
||||
wget_request((ulong)*buffer, url, &efi_wget_info);
|
||||
*file_size = 0;
|
||||
*status_code = efi_wget_info.status_code;
|
||||
@@ -1376,3 +1561,4 @@ efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buf
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <efi_variable.h>
|
||||
#include <log.h>
|
||||
#include <asm-generic/unaligned.h>
|
||||
#include <net.h>
|
||||
|
||||
#define OBJ_LIST_INITIALIZED 0
|
||||
#define OBJ_LIST_NOT_INITIALIZED 1
|
||||
@@ -219,7 +220,7 @@ static efi_status_t efi_start_obj_list(void)
|
||||
efi_status_t ret = EFI_SUCCESS;
|
||||
|
||||
if (IS_ENABLED(CONFIG_NETDEVICES))
|
||||
ret = efi_net_do_start();
|
||||
ret = efi_net_do_start(eth_get_dev());
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -336,7 +337,7 @@ efi_status_t efi_init_obj_list(void)
|
||||
goto out;
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_NETDEVICES)) {
|
||||
ret = efi_net_register();
|
||||
ret = efi_net_register(eth_get_dev());
|
||||
if (ret != EFI_SUCCESS)
|
||||
goto out;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user