Add a dhcp cache to store the DHCP ACKs received by the U-Boot network
stack.

Signed-off-by: Adriano Cordova <adriano.cord...@canonical.com>
---
 lib/efi_loader/efi_net.c | 55 +++++++++++++++++++++++++++++++---------
 1 file changed, 43 insertions(+), 12 deletions(-)

diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
index f65287ad6ab..2fac39ae513 100644
--- a/lib/efi_loader/efi_net.c
+++ b/lib/efi_loader/efi_net.c
@@ -24,12 +24,12 @@
 #include <vsprintf.h>
 #include <net.h>
 
+#define MAX_NUM_DHCP_ENTRIES 10
 #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;
-static struct efi_pxe_packet *dhcp_ack;
 static void *new_tx_packet;
 static void *transmit_buffer;
 static uchar **receive_buffer;
@@ -61,6 +61,15 @@ static struct wget_http_info efi_wget_info = {
 };
 #endif
 
+struct dhcp_entry {
+       struct efi_pxe_packet *dhcp_ack;
+       struct udevice *dev;
+       bool is_valid;
+};
+
+static struct dhcp_entry dhcp_cache[MAX_NUM_DHCP_ENTRIES];
+static int next_dhcp_entry;
+
 /*
  * The notification function of this event is called in every timer cycle
  * to check if a new network packet has been received.
@@ -317,6 +326,7 @@ static efi_status_t EFIAPI efi_net_shutdown(struct 
efi_simple_network *this)
        eth_set_dev(netobj->dev);
        env_set("ethact", eth_get_name());
        eth_halt();
+
        this->int_status = 0;
        wait_for_packet->is_signaled = false;
        this->mode->state = EFI_NETWORK_STARTED;
@@ -718,18 +728,28 @@ out:
  */
 void efi_net_set_dhcp_ack(void *pkt, int len)
 {
-       int maxsize = sizeof(*dhcp_ack);
+       struct efi_pxe_packet **dhcp_ack;
+       struct udevice *dev;
+
+       dhcp_ack = &dhcp_cache[next_dhcp_entry].dhcp_ack;
+
+       /* For now this function gets called only by the current device */
+       dev = eth_get_dev();
 
-       if (!dhcp_ack) {
-               dhcp_ack = malloc(maxsize);
-               if (!dhcp_ack)
+       int maxsize = sizeof(**dhcp_ack);
+
+       if (!*dhcp_ack) {
+               *dhcp_ack = malloc(maxsize);
+               if (!*dhcp_ack)
                        return;
        }
-       memset(dhcp_ack, 0, maxsize);
-       memcpy(dhcp_ack, pkt, min(len, maxsize));
+       memset(*dhcp_ack, 0, maxsize);
+       memcpy(*dhcp_ack, pkt, min(len, maxsize));
 
-       if (netobj)
-               netobj->pxe_mode.dhcp_ack = *dhcp_ack;
+       dhcp_cache[next_dhcp_entry].is_valid = true;
+       dhcp_cache[next_dhcp_entry].dev = dev;
+       next_dhcp_entry++;
+       next_dhcp_entry %= MAX_NUM_DHCP_ENTRIES;
 }
 
 /**
@@ -1036,7 +1056,7 @@ set_addr:
 efi_status_t efi_net_register(struct udevice *dev)
 {
        efi_status_t r;
-       int i;
+       int i, j;
 
        if (!dev) {
                /* No network device active, don't expose any */
@@ -1123,8 +1143,19 @@ efi_status_t efi_net_register(struct udevice *dev)
        netobj->pxe.set_station_ip = efi_pxe_base_code_set_station_ip;
        netobj->pxe.set_packets = efi_pxe_base_code_set_packets;
        netobj->pxe.mode = &netobj->pxe_mode;
-       if (dhcp_ack)
-               netobj->pxe_mode.dhcp_ack = *dhcp_ack;
+
+       /*
+        * Scan dhcp entries for one corresponding
+        * to this udevice, from newest to oldest
+        */
+       i = (next_dhcp_entry + MAX_NUM_DHCP_ENTRIES - 1) % MAX_NUM_DHCP_ENTRIES;
+       for (j = 0; dhcp_cache[i].is_valid && j < MAX_NUM_DHCP_ENTRIES;
+            i = (i + MAX_NUM_DHCP_ENTRIES - 1) % MAX_NUM_DHCP_ENTRIES, j++) {
+               if (dev == dhcp_cache[i].dev) {
+                       netobj->pxe_mode.dhcp_ack = *dhcp_cache[i].dhcp_ack;
+                       break;
+               }
+       }
 
        /*
         * Create WaitForPacket event.
-- 
2.45.2

Reply via email to