Some PXE stacks do not support P_UNKNOWN in UNDI TRANSMIT; nothing is sent at all. So strip Ethernet header for known frame types and let PXE stack add it.
PXE implementation that fail is e.g. 64bit_foxconn with PXE-2.0 (build 082) NIC: SIS900 PXE BootROM v1.09 Hook Int19 Reported-By: Beeblebrox <zap...@berentweb.com> Tested-By: Beeblebrox <zap...@berentweb.com> --- grub-core/net/drivers/i386/pc/pxe.c | 46 ++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index e8c0b22..3d78bdd 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -25,6 +25,7 @@ #include <grub/env.h> #include <grub/i18n.h> #include <grub/loader.h> +#include <grub/net/ethernet.h> #include <grub/machine/pxe.h> #include <grub/machine/int.h> @@ -38,6 +39,11 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x)) #define LINEAR(x) (void *) ((((x) >> 16) << 4) + ((x) & 0xFFFF)) +#define P_UNKNOWN 0 +#define P_IP 1 +#define P_ARP 2 +#define P_RARP 3 + struct grub_pxe_undi_open { grub_uint16_t status; @@ -256,22 +262,56 @@ grub_pxe_send (struct grub_net_card *dev __attribute__ ((unused)), struct grub_pxe_undi_transmit *trans; struct grub_pxe_undi_tbd *tbd; char *buf; + grub_uint8_t *dst; + grub_uint16_t type; trans = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; grub_memset (trans, 0, sizeof (*trans)); + dst = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 128 - 6); + /* First 6 bytes are destination address */ + grub_memcpy (dst, pack->data, 6); + + /* Some PXE stacks do not support P_UNKNOWN. So strip Ethernet + header for known protocols and let PXE implementation add it */ + grub_memcpy (&type, pack->data + 12, 2); + switch (type) + { + case grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP): + trans->protocol = P_IP; + break; + case grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_ARP): + trans->protocol = P_ARP; + break; + /* grub does not use RARP */ + default: + trans->protocol = P_UNKNOWN; + break; + } + if (trans->protocol) + { + grub_err_t err; + + err = grub_netbuff_pull (pack, 14); + if (err) + return err; + if (dst[0] == 0xff && dst[1] == 0xff && dst[2] == 0xff && + dst[3] == 0xff && dst[4] == 0xff && dst[5] == 0xff) + trans->xmitflag = 1; + else + trans->dest = SEGOFS ((grub_addr_t) dst); + } + tbd = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 128); grub_memset (tbd, 0, sizeof (*tbd)); buf = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 256); grub_memcpy (buf, pack->data, pack->tail - pack->data); - trans->tbd = SEGOFS ((grub_addr_t) tbd); - trans->protocol = 0; tbd->len = pack->tail - pack->data; tbd->buf = SEGOFS ((grub_addr_t) buf); grub_pxe_call (GRUB_PXENV_UNDI_TRANSMIT, trans, pxe_rm_entry); if (trans->status) - return grub_error (GRUB_ERR_IO, N_("couldn't send network packet")); + return grub_error (GRUB_ERR_IO, N_("couldn't send network packet, PXE status: 0x%04x"), trans->status); return 0; } -- tg: (0901e78..) e/pxe-send-fix (depends on: master) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel