efi_loader: EFI_SIMPLE_NETWORK.Transmit() fill header
authorHeinrich Schuchardt <xypron.glpk@gmx.de>
Sat, 31 Aug 2019 08:55:29 +0000 (10:55 +0200)
committerHeinrich Schuchardt <xypron.glpk@gmx.de>
Thu, 5 Sep 2019 21:18:51 +0000 (23:18 +0200)
Fill the media header in EFI_SIMPLE_NETWORK.Transmit().
Check that the buffer size is large enough for the header.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
lib/efi_loader/efi_net.c

index bf6d5ab0b3850b344e88c132ce74687bc3415c9f..950b6ed4b2bbd2fbf520e28787a33cf3f38d88ba 100644 (file)
@@ -409,15 +409,33 @@ static efi_status_t EFIAPI efi_net_transmit
                goto out;
        }
 
-       if (header_size) {
-               /*
-                * TODO: We would need to create the header
-                * if header_size != 0
-                */
-               ret = EFI_UNSUPPORTED;
+       /* At least the IP header has to fit into the buffer */
+       if (buffer_size < this->mode->media_header_size) {
+               ret = EFI_BUFFER_TOO_SMALL;
                goto out;
        }
 
+       /*
+        * TODO:
+        * Support VLANs. Use net_set_ether() for copying the header. Use a
+        * U_BOOT_ENV_CALLBACK to update the media header size.
+        */
+       if (header_size) {
+               struct ethernet_hdr *header = buffer;
+
+               if (!dest_addr || !protocol ||
+                   header_size != this->mode->media_header_size) {
+                       ret = EFI_INVALID_PARAMETER;
+                       goto out;
+               }
+               if (!src_addr)
+                       src_addr = &this->mode->current_address;
+
+               memcpy(header->et_dest, dest_addr, ARP_HLEN);
+               memcpy(header->et_src, src_addr, ARP_HLEN);
+               header->et_protlen = htons(*protocol);
+       }
+
        switch (this->mode->state) {
        case EFI_NETWORK_STOPPED:
                ret = EFI_NOT_STARTED;
@@ -764,6 +782,7 @@ efi_status_t efi_net_register(void)
        netobj->net_mode.state = EFI_NETWORK_STARTED;
        memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6);
        netobj->net_mode.hwaddr_size = ARP_HLEN;
+       netobj->net_mode.media_header_size = ETHER_HDR_SIZE;
        netobj->net_mode.max_packet_size = PKTSIZE;
        netobj->net_mode.if_type = ARP_ETHER;