return GRUB_ERR_NONE;
}
-static grub_ssize_t
-get_card_packet (const struct grub_net_card *dev,
- struct grub_net_buff *nb)
+static struct grub_net_buff *
+get_card_packet (const struct grub_net_card *dev)
{
grub_efi_simple_network_t *net = dev->efi_net;
grub_err_t err;
grub_efi_status_t st;
- grub_efi_uintn_t bufsize = 1500;
+ grub_efi_uintn_t bufsize = 1536;
+ struct grub_net_buff *nb;
- err = grub_netbuff_clear (nb);
- if (err)
- return -1;
+ nb = grub_netbuff_alloc (bufsize);
+ if (!nb)
+ return NULL;
- err = grub_netbuff_put (nb, 1500);
- if (err)
- return -1;
+ /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
+ by 4. So that IP header is aligned on 4 bytes. */
+ grub_netbuff_reserve (nb, 2);
+ if (!nb)
+ {
+ grub_netbuff_free (nb);
+ return NULL;
+ }
st = efi_call_7 (net->receive, net, NULL, &bufsize,
nb->data, NULL, NULL, NULL);
if (st == GRUB_EFI_BUFFER_TOO_SMALL)
{
- err = grub_netbuff_put (nb, bufsize - 1500);
- if (err)
- return -1;
+ grub_netbuff_free (nb);
+
+ bufsize = ALIGN_UP (bufsize, 32);
+
+ nb = grub_netbuff_alloc (bufsize);
+ if (!nb)
+ return NULL;
+
+ /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
+ by 4. So that IP header is aligned on 4 bytes. */
+ grub_netbuff_reserve (nb, 2);
+ if (!nb)
+ {
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+
st = efi_call_7 (net->receive, net, NULL, &bufsize,
nb->data, NULL, NULL, NULL);
}
if (st != GRUB_EFI_SUCCESS)
{
- grub_netbuff_clear (nb);
- return -1;
+ grub_netbuff_free (nb);
+ return NULL;
}
- err = grub_netbuff_unput (nb, (nb->tail - nb->data) - bufsize);
+ err = grub_netbuff_put (nb, bufsize);
if (err)
- return -1;
+ {
+ grub_netbuff_free (nb);
+ return NULL;
+ }
- return bufsize;
+ return nb;
}
static struct grub_net_card_driver efidriver =
return GRUB_ERR_NONE;
}
-static grub_ssize_t
-get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)),
- struct grub_net_buff *pack)
+static struct grub_net_buff *
+get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)))
{
ssize_t actual;
+ struct grub_net_buff *nb;
- grub_netbuff_clear (pack);
- actual = read (fd, pack->data, 1500);
+ nb = grub_netbuff_alloc (1536);
+ if (!nb)
+ return NULL;
+
+ /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
+ by 4. So that IP header is aligned on 4 bytes. */
+ grub_netbuff_reserve (nb, 2);
+ if (!nb)
+ {
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+
+ actual = read (fd, nb->data, 1536);
if (actual < 0)
- return -1;
- grub_netbuff_put (pack, actual);
+ {
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ grub_netbuff_put (nb, actual);
- return actual;
+ return nb;
}
static struct grub_net_card_driver emudriver =
return bangpxe;
}
-static grub_ssize_t
-grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)),
- struct grub_net_buff *buf)
+static struct grub_net_buff *
+grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)))
{
struct grub_pxe_undi_isr *isr;
static int in_progress = 0;
char *ptr, *end;
- int len;
+ struct grub_net_buff *buf;
isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_OURS)
{
in_progress = 0;
- return -1;
+ return NULL;
}
grub_memset (isr, 0, sizeof (*isr));
isr->func_flag = GRUB_PXE_ISR_IN_PROCESS;
if (isr->status || isr->func_flag == GRUB_PXE_ISR_OUT_DONE)
{
in_progress = 0;
- return -1;
+ return NULL;
}
grub_memset (isr, 0, sizeof (*isr));
isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT;
grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry);
}
- grub_netbuff_put (buf, isr->frame_len);
+ buf = grub_netbuff_alloc (isr->frame_len);
+ if (!buf)
+ return NULL;
+ /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
+ by 4. So that IP header is aligned on 4 bytes. */
+ grub_netbuff_reserve (buf, 2);
+ if (!buf)
+ {
+ grub_netbuff_free (buf);
+ return NULL;
+ }
ptr = buf->data;
end = ptr + isr->frame_len;
- len = isr->frame_len;
+ grub_netbuff_put (buf, isr->frame_len);
grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len);
ptr += isr->buffer_len;
while (ptr < end)
if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE)
{
in_progress = 1;
- return -1;
+ grub_netbuff_free (buf);
+ return NULL;
}
grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len);
}
in_progress = 1;
- return len;
+ return buf;
}
static grub_err_t
return GRUB_ERR_NONE;
}
-static grub_ssize_t
-get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb)
+static struct grub_net_buff *
+get_card_packet (const struct grub_net_card *dev)
{
grub_ssize_t actual;
int rc;
struct grub_ofnetcard_data *data = dev->data;
grub_uint64_t start_time;
+ struct grub_net_buff *nb;
- grub_netbuff_clear (nb);
+ nb = grub_netbuff_alloc (dev->mtu + 64);
+ /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
+ by 4. So that IP header is aligned on 4 bytes. */
+ grub_netbuff_reserve (nb, 2);
+ if (!nb)
+ {
+ grub_netbuff_free (nb);
+ return NULL;
+ }
start_time = grub_get_time_ms ();
do
- rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu, &actual);
+ rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu + 64, &actual);
while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
if (actual)
{
grub_netbuff_put (nb, actual);
- return actual;
+ return nb;
}
- return -1;
+ grub_netbuff_free (nb);
+ return NULL;
}
static struct grub_net_card_driver ofdriver =
struct grub_net_network_level_interface *inf = NULL;
grub_net_network_level_address_t source;
+ if (((grub_addr_t) nb->data) & 3)
+ grub_fatal ("unaligned %p\n", nb->data);
+
if ((iph->verhdrlen >> 4) != 4)
{
grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4));
/* Maybe should be better have a fixed number of packets for each card
and just mark them as used and not used. */
struct grub_net_buff *nb;
- grub_ssize_t actual;
- nb = grub_netbuff_alloc (1500);
- if (!nb)
- {
- grub_print_error ();
- card->last_poll = grub_get_time_ms ();
- return;
- }
- actual = card->driver->recv (card, nb);
- if (actual < 0)
+ nb = card->driver->recv (card);
+ if (!nb)
{
- grub_netbuff_free (nb);
card->last_poll = grub_get_time_ms ();
break;
}
void (*close) (const struct grub_net_card *dev);
grub_err_t (*send) (const struct grub_net_card *dev,
struct grub_net_buff *buf);
- grub_ssize_t (*recv) (const struct grub_net_card *dev,
- struct grub_net_buff *buf);
+ struct grub_net_buff * (*recv) (const struct grub_net_card *dev);
};
typedef struct grub_net_packet