:: commit 2362f1a7859760e38f3137761f07bcc480349f5b

Bryce Lanham <blanham@gmail.com> — 2023-04-24 11:44

parents: 2a26d90394

Implement Multiboot2 network tag

Added caching of the dhcp response in the pxe code, and then adding the
tag containing it.
diff --git a/common/protos/multiboot2.c b/common/protos/multiboot2.c
index d6791613..816aa887 100644
--- a/common/protos/multiboot2.c
+++ b/common/protos/multiboot2.c
@@ -24,6 +24,7 @@
 #include <mm/pmm.h>
 #include <lib/misc.h>
 #include <drivers/vga_textmode.h>
+#include <pxe/pxe.h>
 
 #define LIMINE_BRAND "Limine " LIMINE_VERSION
 
@@ -56,6 +57,7 @@ static size_t get_multiboot2_info_size(
                 ALIGN_UP(sizeof(struct multiboot_tag_efi64_ih), MULTIBOOT_TAG_ALIGN) +                                  // EFI image handle 64
             #endif
         #endif
+        ALIGN_UP(sizeof(struct multiboot_tag_network) + cached_dhcp_packet_len, MULTIBOOT_TAG_ALIGN) +                  // network info
         ALIGN_UP(sizeof(struct multiboot_tag), MULTIBOOT_TAG_ALIGN);                                                    // end
 }
 
@@ -782,6 +784,22 @@ skip_modeset:;
     }
 #endif
 
+    //////////////////////////////////////////////
+    // Create network info tag
+    //////////////////////////////////////////////
+    {
+        if (cached_dhcp_packet_len) {
+            struct multiboot_tag_network *tag = (struct multiboot_tag_network *)(mb2_info + info_idx);
+
+            tag->type = MULTIBOOT_TAG_TYPE_NETWORK;
+            tag->size = sizeof(struct multiboot_tag_network) + cached_dhcp_packet_len;
+
+            // Copy over the DHCP packet.
+            memcpy(tag->dhcpack, cached_dhcp_packet, cached_dhcp_packet_len);
+            append_tag(info_idx, tag);
+        }
+    }
+
     //////////////////////////////////////////////
     // Create end tag
     //////////////////////////////////////////////
diff --git a/common/pxe/pxe.h b/common/pxe/pxe.h
index e80c7150..20c51119 100644
--- a/common/pxe/pxe.h
+++ b/common/pxe/pxe.h
@@ -4,6 +4,9 @@
 #include <stdint.h>
 #include <lib/part.h>
 
+extern uint8_t cached_dhcp_packet[1472];
+extern int cached_dhcp_packet_len;
+
 #if defined (BIOS)
 
 struct volume *pxe_bind_volume(void);
diff --git a/common/pxe/tftp.s2.c b/common/pxe/tftp.s2.c
index db32b5d6..ff7c8078 100644
--- a/common/pxe/tftp.s2.c
+++ b/common/pxe/tftp.s2.c
@@ -10,6 +10,10 @@
 #include <mm/pmm.h>
 #include <lib/misc.h>
 
+// cache the dhcp packet
+uint8_t cached_dhcp_packet[1472] = { 0 };
+int cached_dhcp_packet_len = 0;
+
 #if defined (BIOS)
 
 static uint32_t get_boot_server_info(void) {
@@ -17,6 +21,8 @@ static uint32_t get_boot_server_info(void) {
     cachedinfo.packet_type = PXENV_PACKET_TYPE_CACHED_REPLY;
     pxe_call(PXENV_GET_CACHED_INFO, ((uint16_t)rm_seg(&cachedinfo)), (uint16_t)rm_off(&cachedinfo));
     struct bootph *ph = (struct bootph*)(void *) (((((uint32_t)cachedinfo.buffer) >> 16) << 4) + (((uint32_t)cachedinfo.buffer) & 0xFFFF));
+    memcpy(&cached_dhcp_packet, ph, sizeof(struct bootph));
+    cached_dhcp_packet_len = sizeof(struct bootph);
     return ph->sip;
 }
 
@@ -141,6 +147,8 @@ static EFI_IP_ADDRESS *parse_ip_addr(struct volume *part, const char *server_add
         else if (part->pxe_base_code->Mode->ProxyOfferReceived) packet = &part->pxe_base_code->Mode->ProxyOffer;
         else packet = &part->pxe_base_code->Mode->DhcpAck;
         memcpy(out.Addr, packet->Dhcpv4.BootpSiAddr, 4);
+        memcpy(cached_dhcp_packet, packet, sizeof(EFI_PXE_BASE_CODE_PACKET));
+        cached_dhcp_packet_len = sizeof(EFI_PXE_BASE_CODE_PACKET);
     } else {
         if (inet_pton(server_addr, &out.Addr)) {
             panic(true, "tftp: Invalid IPv4 address: \"%s\"", server_addr);
diff --git a/test/multiboot2.c b/test/multiboot2.c
index ef522285..34428541 100644
--- a/test/multiboot2.c
+++ b/test/multiboot2.c
@@ -132,6 +132,12 @@ void multiboot2_main(uint32_t magic, struct multiboot_info* mb_info_addr) {
 
                 break;
             }
+
+            case MULTIBOOT_TAG_TYPE_NETWORK: {
+                struct multiboot_tag_network *network = (struct multiboot_tag_network *)tag;
+                e9_printf("\t network tag exists");
+                break;
+            }
         }
 
         add_size = tag->size;
tab: 248 wrap: offon