Fix broken blksize negotiation, fix broken seek and change a way net device is filled n i386-pc
This commit is contained in:
parent
cae730b452
commit
6708faafde
8 changed files with 105 additions and 44 deletions
|
@ -25,7 +25,6 @@
|
|||
#include <grub/fs.h>
|
||||
#include <grub/device.h>
|
||||
|
||||
grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL;
|
||||
void (*EXPORT_VAR (grub_grubnet_fini)) (void);
|
||||
|
||||
grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX];
|
||||
|
@ -183,9 +182,6 @@ grub_file_seek (grub_file_t file, grub_off_t offset)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (file->device->net && grub_file_net_seek)
|
||||
grub_file_net_seek (file, offset);
|
||||
|
||||
old = file->offset;
|
||||
file->offset = offset;
|
||||
|
||||
|
|
|
@ -45,9 +45,10 @@ struct mem_region
|
|||
static struct mem_region mem_regions[MAX_REGIONS];
|
||||
static int num_regions;
|
||||
|
||||
void (*grub_pc_net_config) (char **device, char **path);
|
||||
|
||||
void
|
||||
grub_machine_get_bootlocation (char **device,
|
||||
char **path __attribute__ ((unused)))
|
||||
grub_machine_get_bootlocation (char **device, char **path)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
|
@ -55,7 +56,8 @@ grub_machine_get_bootlocation (char **device,
|
|||
partition number encoded at the install time. */
|
||||
if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL)
|
||||
{
|
||||
*device = grub_strdup ("pxe");
|
||||
if (grub_pc_net_config)
|
||||
grub_pc_net_config (device, path);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <grub/machine/pxe.h>
|
||||
#include <grub/machine/int.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -45,6 +46,22 @@ struct grub_pxe_undi_open
|
|||
grub_uint8_t mcast[8][6];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_pxe_undi_info
|
||||
{
|
||||
grub_uint16_t status;
|
||||
grub_uint16_t base_io;
|
||||
grub_uint16_t int_number;
|
||||
grub_uint16_t mtu;
|
||||
grub_uint16_t hwtype;
|
||||
grub_uint16_t hwaddrlen;
|
||||
grub_uint8_t current_addr[16];
|
||||
grub_uint8_t permanent_addr[16];
|
||||
grub_uint32_t romaddr;
|
||||
grub_uint16_t rxbufct;
|
||||
grub_uint16_t txbufct;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct grub_pxe_undi_isr
|
||||
{
|
||||
grub_uint16_t status;
|
||||
|
@ -259,7 +276,7 @@ struct grub_net_card grub_pxe_card =
|
|||
void
|
||||
grub_pxe_unload (void)
|
||||
{
|
||||
if (grub_pxe_pxenv)
|
||||
if (pxe_rm_entry)
|
||||
{
|
||||
grub_pxe_call (GRUB_PXENV_UNDI_CLOSE,
|
||||
(void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
|
||||
|
@ -269,17 +286,11 @@ grub_pxe_unload (void)
|
|||
}
|
||||
}
|
||||
|
||||
GRUB_MOD_INIT(pxe)
|
||||
static void
|
||||
grub_pc_net_config_real (char **device, char **path)
|
||||
{
|
||||
struct grub_pxe_bangpxe *pxenv;
|
||||
struct grub_pxenv_get_cached_info ci;
|
||||
struct grub_net_bootp_packet *bp;
|
||||
struct grub_pxe_undi_open *ou;
|
||||
|
||||
pxenv = grub_pxe_scan ();
|
||||
if (! pxenv)
|
||||
return;
|
||||
|
||||
struct grub_pxenv_get_cached_info ci;
|
||||
ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK;
|
||||
ci.buffer = 0;
|
||||
ci.buffer_size = 0;
|
||||
|
@ -289,9 +300,41 @@ GRUB_MOD_INIT(pxe)
|
|||
|
||||
bp = LINEAR (ci.buffer);
|
||||
|
||||
grub_memcpy (grub_pxe_card.default_address.mac, bp->mac_addr,
|
||||
bp->hw_len < sizeof (grub_pxe_card.default_address.mac)
|
||||
? bp->hw_len : sizeof (grub_pxe_card.default_address.mac));
|
||||
grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0,
|
||||
bp, GRUB_PXE_BOOTP_SIZE,
|
||||
1, device, path);
|
||||
}
|
||||
|
||||
GRUB_MOD_INIT(pxe)
|
||||
{
|
||||
struct grub_pxe_bangpxe *pxenv;
|
||||
struct grub_pxe_undi_open *ou;
|
||||
struct grub_pxe_undi_info *ui;
|
||||
unsigned i;
|
||||
|
||||
pxenv = grub_pxe_scan ();
|
||||
if (! pxenv)
|
||||
return;
|
||||
|
||||
ui = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||
grub_memset (ui, 0, sizeof (*ui));
|
||||
grub_pxe_call (GRUB_PXENV_UNDI_GET_INFORMATION, ui, pxe_rm_entry);
|
||||
|
||||
grub_memcpy (grub_pxe_card.default_address.mac, ui->current_addr,
|
||||
sizeof (grub_pxe_card.default_address.mac));
|
||||
for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++)
|
||||
if (grub_pxe_card.default_address.mac[i] != 0)
|
||||
break;
|
||||
if (i != sizeof (grub_pxe_card.default_address.mac))
|
||||
{
|
||||
for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++)
|
||||
if (grub_pxe_card.default_address.mac[i] != 0xff)
|
||||
break;
|
||||
}
|
||||
if (i == sizeof (grub_pxe_card.default_address.mac))
|
||||
grub_memcpy (grub_pxe_card.default_address.mac, ui->permanent_addr,
|
||||
sizeof (grub_pxe_card.default_address.mac));
|
||||
|
||||
grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||
|
||||
ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||
|
@ -303,11 +346,11 @@ GRUB_MOD_INIT(pxe)
|
|||
return;
|
||||
|
||||
grub_net_card_register (&grub_pxe_card);
|
||||
grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0,
|
||||
bp, GRUB_PXE_BOOTP_SIZE);
|
||||
grub_pc_net_config = grub_pc_net_config_real;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(pxe)
|
||||
{
|
||||
grub_pc_net_config = 0;
|
||||
grub_pxe_unload ();
|
||||
}
|
||||
|
|
|
@ -664,6 +664,7 @@ grub_net_open_real (const char *name)
|
|||
else
|
||||
ret->server = NULL;
|
||||
ret->fs = &grub_net_fs;
|
||||
ret->offset = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -784,7 +785,7 @@ grub_net_poll_cards (unsigned time)
|
|||
|
||||
/* Read from the packets list*/
|
||||
static grub_ssize_t
|
||||
grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
|
||||
{
|
||||
grub_net_socket_t sock = file->device->net->socket;
|
||||
struct grub_net_buff *nb;
|
||||
|
@ -802,6 +803,7 @@ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
amount = len;
|
||||
len -= amount;
|
||||
total += amount;
|
||||
file->device->net->offset += amount;
|
||||
if (buf)
|
||||
{
|
||||
grub_memcpy (ptr, nb->data, amount);
|
||||
|
@ -829,28 +831,40 @@ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
return total;
|
||||
}
|
||||
|
||||
/* Read from the packets list*/
|
||||
static grub_err_t
|
||||
grub_net_seek_real (struct grub_file *file, grub_off_t offset)
|
||||
{
|
||||
grub_net_socket_t sock = file->device->net->socket;
|
||||
struct grub_net_buff *nb;
|
||||
grub_size_t len = offset - file->offset;
|
||||
grub_size_t len = offset - file->device->net->offset;
|
||||
|
||||
if (!len)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
/* We cant seek backwards past the current packet. */
|
||||
if (file->offset > offset)
|
||||
if (file->device->net->offset > offset)
|
||||
{
|
||||
nb = sock->packs.first->nb;
|
||||
return grub_netbuff_push (nb, file->offset - offset);
|
||||
return grub_netbuff_push (nb, file->device->net->offset - offset);
|
||||
}
|
||||
|
||||
grub_net_fs_read (file, NULL, len);
|
||||
grub_net_fs_read_real (file, NULL, len);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_ssize_t
|
||||
grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
{
|
||||
if (file->offset != file->device->net->offset)
|
||||
{
|
||||
grub_err_t err;
|
||||
err = grub_net_seek_real (file, file->offset);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
return grub_net_fs_read_real (file, buf, len);
|
||||
}
|
||||
|
||||
static char *
|
||||
grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
|
||||
const char *val __attribute__ ((unused)))
|
||||
|
@ -1384,7 +1398,6 @@ GRUB_MOD_INIT(net)
|
|||
|
||||
grub_fs_register (&grub_net_fs);
|
||||
grub_net_open = grub_net_open_real;
|
||||
grub_file_net_seek = grub_net_seek_real;
|
||||
grub_grubnet_fini = grub_grubnet_fini_real;
|
||||
}
|
||||
|
||||
|
@ -1400,6 +1413,5 @@ GRUB_MOD_FINI(net)
|
|||
grub_unregister_command (cmd_getdhcp);
|
||||
grub_fs_unregister (&grub_net_fs);
|
||||
grub_net_open = NULL;
|
||||
grub_file_net_seek = NULL;
|
||||
grub_grubnet_fini = NULL;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,13 @@
|
|||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
typedef struct tftp_data
|
||||
{
|
||||
grub_uint64_t file_size;
|
||||
grub_uint64_t block;
|
||||
grub_uint32_t block_size;
|
||||
} *tftp_data_t;
|
||||
|
||||
static grub_err_t
|
||||
tftp_open (struct grub_file *file, const char *filename)
|
||||
{
|
||||
|
@ -85,9 +92,9 @@ tftp_open (struct grub_file *file, const char *filename)
|
|||
if (file->device->net->socket->status != 0)
|
||||
break;
|
||||
/* Retry. */
|
||||
/*err = grub_net_send_udp_packet (file->device->net->socket, &nb);
|
||||
if (err)
|
||||
return err; */
|
||||
err = grub_net_send_udp_packet (file->device->net->socket, &nb);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (file->device->net->socket->status == 0)
|
||||
|
@ -110,11 +117,11 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb)
|
|||
nb_ack.head = nbdata;
|
||||
nb_ack.end = nbdata + sizeof (nbdata);
|
||||
|
||||
|
||||
tftph = (struct tftphdr *) nb->data;
|
||||
switch (grub_be_to_cpu16 (tftph->opcode))
|
||||
{
|
||||
case TFTP_OACK:
|
||||
data->block_size = 512;
|
||||
for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;)
|
||||
{
|
||||
if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0)
|
||||
|
@ -122,6 +129,11 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb)
|
|||
data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1,
|
||||
0, 0);
|
||||
}
|
||||
if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0)
|
||||
{
|
||||
data->block_size = grub_strtoul (ptr + sizeof ("blksize\0") - 1,
|
||||
0, 0);
|
||||
}
|
||||
while (ptr < nb->tail && *ptr)
|
||||
ptr++;
|
||||
ptr++;
|
||||
|
@ -139,12 +151,12 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb)
|
|||
{
|
||||
data->block++;
|
||||
unsigned size = nb->tail - nb->data;
|
||||
if (size < 1024)
|
||||
if (size < data->block_size)
|
||||
sock->status = 2;
|
||||
/* Prevent garbage in broken cards. */
|
||||
if (size > 1024)
|
||||
if (size > data->block_size)
|
||||
{
|
||||
err = grub_netbuff_unput (nb, size - 1024);
|
||||
err = grub_netbuff_unput (nb, size - data->block_size);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ extern grub_int32_t grub_install_bsd_part;
|
|||
/* The boot BIOS drive number. */
|
||||
extern grub_uint8_t EXPORT_VAR(grub_boot_drive);
|
||||
|
||||
extern void (*EXPORT_VAR(grub_pc_net_config)) (char **device, char **path);
|
||||
|
||||
#endif /* ! ASM_FILE */
|
||||
|
||||
#endif /* ! KERNEL_MACHINE_HEADER */
|
||||
|
|
|
@ -242,11 +242,11 @@ typedef struct grub_net
|
|||
char *server;
|
||||
grub_net_app_level_t protocol;
|
||||
grub_net_socket_t socket;
|
||||
grub_off_t offset;
|
||||
grub_fs_t fs;
|
||||
} *grub_net_t;
|
||||
|
||||
extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name);
|
||||
extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, grub_off_t offset);
|
||||
extern void (*EXPORT_VAR (grub_grubnet_fini)) (void);
|
||||
|
||||
struct grub_net_network_level_interface
|
||||
|
|
|
@ -43,12 +43,6 @@
|
|||
/* * own here because this is cleaner, and maps to the same data layout.
|
||||
* */
|
||||
|
||||
typedef struct tftp_data
|
||||
{
|
||||
int file_size;
|
||||
int block;
|
||||
} *tftp_data_t;
|
||||
|
||||
|
||||
struct tftphdr {
|
||||
grub_uint16_t opcode;
|
||||
|
|
Loading…
Reference in a new issue