efi_loader: EFI_SIMPLE_NETWORK.Transmit() fill header

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>
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
index bf6d5ab..950b6ed 100644
--- a/lib/efi_loader/efi_net.c
+++ b/lib/efi_loader/efi_net.c
@@ -409,15 +409,33 @@
 		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 @@
 	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;