Network infrastructure.
The ARP protocol was made by Paulo Pinatti <ppinatti@br.ibm.com> * include/grub/net/arp.h: New file. * include/grub/net/device.h: Likewise. * include/grub/net/ethernet.h: Likewise. * include/grub/net/ip.h: Likewise. * include/grub/net/netbuff.h: Likewise. * include/grub/net/tftp.h: Likewise. * include/grub/net/udp.h: Likewise. * include/grub/ieee1275/ofnet.h: Likewise. * include/grub/emu/export.h: Likewise. * include/grub/net.h: Likewise. * grub-core/net/arp.c: Likewise. * grub-core/net/ethernet.c: Likewise. * grub-core/net/ip.c: Likewise. * grub-core/net/udp.c: Likewise. * grub-core/net/tftp.c: Likewise. * grub-core/net/netbuff.c: Likewise. * grub-core/net/net.c: Likewise. * grub-core/net/drivers/emu/emunet.c: Likewise. * grub-core/net/drivers/ieee1275/ofnet.c: Likewise. * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add net.h, ofnet.h and export.h. * grub-core/Makefile.core.def (net): New module. (tftp): Likewise. (ofnet): Likewise. (emunet): Likewise. * grub-core/commands/ls.c (grub_ls_list_devices) [!GRUB_UTIL]: List network protocols. * grub-core/kern/device.c (grub_net_open) : New variable. (grub_device_open): Handle network device. (grub_device_close): Likewise. * grub-core/kern/file.c (grub_file_net_seek) : New variable. (grub_grubnet_fini): Likewise. (grub_file_seek): Seek in network device. * grub-core/kern/fs.c (grub_fs_probe): Handle network devices. * grub-core/kern/ieee1275/init.c (grub_machine_set_prefix): Handle network root. (grub_machine_fini): Call grub_grubnet_fini. * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args): Handle network. (grub_ieee1275_get_aliasdevname): New function. * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_get_mbi_size): Add unofficial Solaris network info. (grub_multiboot_make_mbi): Likewise. * grub-core/fs/i386/pc/pxe.c: Moved from here ... * grub-core/net/i386/pc/pxe.c: ...here. Adapted for new design. * include/grub/device.h (grub_fs): Removed. * include/grub/err.h (grub_err_t): Add network-related values. * include/grub/i386/pc/pxe.h: Removed bootp parts. * include/grub/ieee1275/ieee1275.h (grub_ofnetcard_data): New struct. (grub_ieee1275_get_aliasdevname): New proto. * include/grub/net.h: Rewritten. Also-By: Paulo Pinatti <ppinatti@br.ibm.com> Also-By: Vladimir Serbinenko <phcoder@gmail.com>
This commit is contained in:
commit
90162423e9
35 changed files with 3447 additions and 399 deletions
58
ChangeLog
58
ChangeLog
|
@ -1,3 +1,61 @@
|
||||||
|
2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
2011-06-24 Manoel Rebelo Abranches <mrabran@gmail.com>
|
||||||
|
|
||||||
|
Network infrastructure.
|
||||||
|
The ARP protocol was made by Paulo Pinatti <ppinatti@br.ibm.com>
|
||||||
|
|
||||||
|
* include/grub/net/arp.h: New file.
|
||||||
|
* include/grub/net/device.h: Likewise.
|
||||||
|
* include/grub/net/ethernet.h: Likewise.
|
||||||
|
* include/grub/net/ip.h: Likewise.
|
||||||
|
* include/grub/net/netbuff.h: Likewise.
|
||||||
|
* include/grub/net/tftp.h: Likewise.
|
||||||
|
* include/grub/net/udp.h: Likewise.
|
||||||
|
* include/grub/ieee1275/ofnet.h: Likewise.
|
||||||
|
* include/grub/emu/export.h: Likewise.
|
||||||
|
* include/grub/net.h: Likewise.
|
||||||
|
* grub-core/net/arp.c: Likewise.
|
||||||
|
* grub-core/net/ethernet.c: Likewise.
|
||||||
|
* grub-core/net/ip.c: Likewise.
|
||||||
|
* grub-core/net/udp.c: Likewise.
|
||||||
|
* grub-core/net/tftp.c: Likewise.
|
||||||
|
* grub-core/net/netbuff.c: Likewise.
|
||||||
|
* grub-core/net/net.c: Likewise.
|
||||||
|
* grub-core/net/drivers/emu/emunet.c: Likewise.
|
||||||
|
* grub-core/net/drivers/ieee1275/ofnet.c: Likewise.
|
||||||
|
* grub-core/Makefile.am (KERNEL_HEADER_FILES): Add net.h, ofnet.h and
|
||||||
|
export.h.
|
||||||
|
* grub-core/Makefile.core.def (net): New module.
|
||||||
|
(tftp): Likewise.
|
||||||
|
(ofnet): Likewise.
|
||||||
|
(emunet): Likewise.
|
||||||
|
* grub-core/commands/ls.c (grub_ls_list_devices) [!GRUB_UTIL]: List
|
||||||
|
network protocols.
|
||||||
|
* grub-core/kern/device.c (grub_net_open) : New variable.
|
||||||
|
(grub_device_open): Handle network device.
|
||||||
|
(grub_device_close): Likewise.
|
||||||
|
* grub-core/kern/file.c (grub_file_net_seek) : New variable.
|
||||||
|
(grub_grubnet_fini): Likewise.
|
||||||
|
(grub_file_seek): Seek in network device.
|
||||||
|
* grub-core/kern/fs.c (grub_fs_probe): Handle network devices.
|
||||||
|
* grub-core/kern/ieee1275/init.c (grub_machine_set_prefix): Handle
|
||||||
|
network root.
|
||||||
|
(grub_machine_fini): Call grub_grubnet_fini.
|
||||||
|
* grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args): Handle
|
||||||
|
network.
|
||||||
|
(grub_ieee1275_get_aliasdevname): New function.
|
||||||
|
* grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_get_mbi_size):
|
||||||
|
Add unofficial Solaris network info.
|
||||||
|
(grub_multiboot_make_mbi): Likewise.
|
||||||
|
* grub-core/fs/i386/pc/pxe.c: Moved from here ...
|
||||||
|
* grub-core/net/i386/pc/pxe.c: ...here. Adapted for new design.
|
||||||
|
* include/grub/device.h (grub_fs): Removed.
|
||||||
|
* include/grub/err.h (grub_err_t): Add network-related values.
|
||||||
|
* include/grub/i386/pc/pxe.h: Removed bootp parts.
|
||||||
|
* include/grub/ieee1275/ieee1275.h (grub_ofnetcard_data): New struct.
|
||||||
|
(grub_ieee1275_get_aliasdevname): New proto.
|
||||||
|
* include/grub/net.h: Rewritten.
|
||||||
|
|
||||||
2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
|
2011-06-24 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/disk/raid.c (insert_array): Ensure uniqueness of readable
|
* grub-core/disk/raid.c (insert_array): Ensure uniqueness of readable
|
||||||
|
|
|
@ -79,6 +79,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
|
||||||
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
|
||||||
|
|
||||||
|
@ -112,6 +113,7 @@ endif
|
||||||
|
|
||||||
if COND_i386_ieee1275
|
if COND_i386_ieee1275
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||||
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||||
|
@ -171,6 +173,7 @@ endif
|
||||||
|
|
||||||
if COND_powerpc_ieee1275
|
if COND_powerpc_ieee1275
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||||
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||||
|
@ -178,6 +181,7 @@ endif
|
||||||
|
|
||||||
if COND_sparc64_ieee1275
|
if COND_sparc64_ieee1275
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||||
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||||
|
@ -187,6 +191,7 @@ endif
|
||||||
if COND_emu
|
if COND_emu
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h
|
||||||
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/export.h
|
||||||
if COND_GRUB_EMU_SDL
|
if COND_GRUB_EMU_SDL
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -1100,7 +1100,7 @@ module = {
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = pxe;
|
name = pxe;
|
||||||
i386_pc = fs/i386/pc/pxe.c;
|
i386_pc = net/i386/pc/pxe.c;
|
||||||
enable = i386_pc;
|
enable = i386_pc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1571,6 +1571,33 @@ module = {
|
||||||
common = hook/datehook.c;
|
common = hook/datehook.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = net;
|
||||||
|
common = net/net.c;
|
||||||
|
common = net/ip.c;
|
||||||
|
common = net/udp.c;
|
||||||
|
common = net/ethernet.c;
|
||||||
|
common = net/arp.c;
|
||||||
|
common = net/netbuff.c;
|
||||||
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = tftp;
|
||||||
|
common = net/tftp.c;
|
||||||
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = ofnet;
|
||||||
|
ieee1275 = net/drivers/ieee1275/ofnet.c;
|
||||||
|
enable = ieee1275;
|
||||||
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = emunet;
|
||||||
|
emu = net/drivers/emu/emunet.c;
|
||||||
|
enable = emu;
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = legacycfg;
|
name = legacycfg;
|
||||||
common = commands/legacycfg.c;
|
common = commands/legacycfg.c;
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <grub/extcmd.h>
|
#include <grub/extcmd.h>
|
||||||
#include <grub/datetime.h>
|
#include <grub/datetime.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -60,6 +61,22 @@ grub_ls_list_devices (int longlist)
|
||||||
|
|
||||||
grub_device_iterate (grub_ls_print_devices);
|
grub_device_iterate (grub_ls_print_devices);
|
||||||
grub_xputs ("\n");
|
grub_xputs ("\n");
|
||||||
|
|
||||||
|
#ifndef GRUB_UTIL
|
||||||
|
{
|
||||||
|
grub_net_app_level_t proto;
|
||||||
|
int first = 1;
|
||||||
|
FOR_NET_APP_LEVEL (proto)
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
grub_puts_ (N_ ("Network protocols:"));
|
||||||
|
first = 0;
|
||||||
|
grub_printf ("%s ", proto->name);
|
||||||
|
}
|
||||||
|
grub_xputs ("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
grub_refresh ();
|
grub_refresh ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -74,7 +74,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
{
|
{
|
||||||
const char *val = "none";
|
const char *val = "none";
|
||||||
if (dev->net)
|
if (dev->net)
|
||||||
val = dev->net->dev->name;
|
val = dev->net->name;
|
||||||
if (dev->disk)
|
if (dev->disk)
|
||||||
val = dev->disk->dev->name;
|
val = dev->disk->dev->name;
|
||||||
if (state[0].set)
|
if (state[0].set)
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include <grub/env.h>
|
#include <grub/env.h>
|
||||||
#include <grub/partition.h>
|
#include <grub/partition.h>
|
||||||
|
|
||||||
|
grub_net_t (*grub_net_open) (const char *name) = NULL;
|
||||||
|
|
||||||
grub_device_t
|
grub_device_t
|
||||||
grub_device_open (const char *name)
|
grub_device_open (const char *name)
|
||||||
{
|
{
|
||||||
|
@ -46,14 +48,18 @@ grub_device_open (const char *name)
|
||||||
if (! dev)
|
if (! dev)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
dev->net = NULL;
|
||||||
/* Try to open a disk. */
|
/* Try to open a disk. */
|
||||||
disk = grub_disk_open (name);
|
dev->disk = grub_disk_open (name);
|
||||||
if (! disk)
|
if (dev->disk)
|
||||||
goto fail;
|
return dev;
|
||||||
|
if (grub_net_open && grub_errno == GRUB_ERR_UNKNOWN_DEVICE)
|
||||||
dev->disk = disk;
|
{
|
||||||
dev->net = 0; /* FIXME */
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
dev->net = grub_net_open (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->net)
|
||||||
return dev;
|
return dev;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -71,6 +77,12 @@ grub_device_close (grub_device_t device)
|
||||||
if (device->disk)
|
if (device->disk)
|
||||||
grub_disk_close (device->disk);
|
grub_disk_close (device->disk);
|
||||||
|
|
||||||
|
if (device->net)
|
||||||
|
{
|
||||||
|
grub_free (device->net->name);
|
||||||
|
grub_free (device->net);
|
||||||
|
}
|
||||||
|
|
||||||
grub_free (device);
|
grub_free (device);
|
||||||
|
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
|
@ -20,10 +20,14 @@
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/file.h>
|
#include <grub/file.h>
|
||||||
|
#include <grub/net.h>
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/fs.h>
|
#include <grub/fs.h>
|
||||||
#include <grub/device.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];
|
grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX];
|
||||||
grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX];
|
grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX];
|
||||||
|
|
||||||
|
@ -148,7 +152,6 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len)
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
res = (file->fs->read) (file, buf, len);
|
res = (file->fs->read) (file, buf, len);
|
||||||
if (res > 0)
|
if (res > 0)
|
||||||
file->offset += res;
|
file->offset += res;
|
||||||
|
@ -180,7 +183,11 @@ grub_file_seek (grub_file_t file, grub_off_t offset)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file->device->net && grub_file_net_seek)
|
||||||
|
grub_file_net_seek (file, offset);
|
||||||
|
|
||||||
old = file->offset;
|
old = file->offset;
|
||||||
file->offset = offset;
|
file->offset = offset;
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ grub_fs_probe (grub_device_t device)
|
||||||
count--;
|
count--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (device->net->fs)
|
else if (device->net && device->net->fs)
|
||||||
return device->net->fs;
|
return device->net->fs;
|
||||||
|
|
||||||
grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem");
|
grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem");
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
#include <grub/ieee1275/console.h>
|
#include <grub/ieee1275/console.h>
|
||||||
#include <grub/ieee1275/ofdisk.h>
|
#include <grub/ieee1275/ofdisk.h>
|
||||||
#include <grub/ieee1275/ieee1275.h>
|
#include <grub/ieee1275/ieee1275.h>
|
||||||
|
#include <grub/ieee1275/ofnet.h>
|
||||||
|
#include <grub/net.h>
|
||||||
#include <grub/offsets.h>
|
#include <grub/offsets.h>
|
||||||
#include <grub/memory.h>
|
#include <grub/memory.h>
|
||||||
|
|
||||||
|
@ -74,6 +76,21 @@ grub_machine_set_prefix (void)
|
||||||
char bootpath[64]; /* XXX check length */
|
char bootpath[64]; /* XXX check length */
|
||||||
char *filename;
|
char *filename;
|
||||||
char *prefix;
|
char *prefix;
|
||||||
|
grub_bootp_t bootp_pckt;
|
||||||
|
char addr[GRUB_NET_MAX_STR_ADDR_LEN];
|
||||||
|
|
||||||
|
/* Set the net prefix when possible. */
|
||||||
|
if (grub_getbootp && (bootp_pckt = grub_getbootp()))
|
||||||
|
{
|
||||||
|
grub_uint32_t n = bootp_pckt->siaddr;
|
||||||
|
grub_snprintf (addr, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d",
|
||||||
|
((n >> 24) & 0xff), ((n >> 16) & 0xff),
|
||||||
|
((n >> 8) & 0xff), ((n >> 0) & 0xff));
|
||||||
|
prefix = grub_xasprintf ("(tftp,%s)%s", addr,grub_prefix);
|
||||||
|
grub_env_set ("prefix", prefix);
|
||||||
|
grub_free (prefix);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (grub_prefix[0])
|
if (grub_prefix[0])
|
||||||
{
|
{
|
||||||
|
@ -247,6 +264,8 @@ grub_machine_init (void)
|
||||||
void
|
void
|
||||||
grub_machine_fini (void)
|
grub_machine_fini (void)
|
||||||
{
|
{
|
||||||
|
if (grub_grubnet_fini)
|
||||||
|
grub_grubnet_fini ();
|
||||||
grub_ofdisk_fini ();
|
grub_ofdisk_fini ();
|
||||||
grub_console_fini ();
|
grub_console_fini ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,16 @@
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/ieee1275/ieee1275.h>
|
#include <grub/ieee1275/ieee1275.h>
|
||||||
|
#include <grub/ieee1275/ofnet.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
#include <grub/net/tftp.h>
|
||||||
|
|
||||||
|
grub_bootp_t (*grub_getbootp) (void);
|
||||||
enum grub_ieee1275_parse_type
|
enum grub_ieee1275_parse_type
|
||||||
{
|
{
|
||||||
GRUB_PARSE_FILENAME,
|
GRUB_PARSE_FILENAME,
|
||||||
GRUB_PARSE_PARTITION,
|
GRUB_PARSE_PARTITION,
|
||||||
|
GRUB_PARSE_DEVICE
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Walk children of 'devpath', calling hook for each. */
|
/* Walk children of 'devpath', calling hook for each. */
|
||||||
|
@ -366,12 +371,14 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
|
||||||
ret = grub_strndup (args, (grub_size_t)(comma - args));
|
ret = grub_strndup (args, (grub_size_t)(comma - args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (!grub_strcmp ("network", type))
|
||||||
|
{
|
||||||
|
if (ptype == GRUB_PARSE_DEVICE)
|
||||||
|
ret = grub_strdup(device);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* XXX Handle net devices by configuring & registering a grub_net_dev
|
|
||||||
here, then return its name?
|
|
||||||
Example path: "net:<server ip>,<file name>,<client ip>,<gateway
|
|
||||||
ip>,<bootp retries>,<tftp retries>". */
|
|
||||||
grub_printf ("Unsupported type %s for device %s\n", type, device);
|
grub_printf ("Unsupported type %s for device %s\n", type, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,6 +388,12 @@ fail:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
grub_ieee1275_get_aliasdevname (const char *path)
|
||||||
|
{
|
||||||
|
return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
grub_ieee1275_get_filename (const char *path)
|
grub_ieee1275_get_filename (const char *path)
|
||||||
{
|
{
|
||||||
|
@ -467,3 +480,4 @@ grub_ieee1275_canonicalise_devname (const char *path)
|
||||||
grub_free (buf);
|
grub_free (buf);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <grub/relocator.h>
|
#include <grub/relocator.h>
|
||||||
#include <grub/video.h>
|
#include <grub/video.h>
|
||||||
#include <grub/file.h>
|
#include <grub/file.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
|
||||||
/* The bits in the required part of flags field we don't support. */
|
/* The bits in the required part of flags field we don't support. */
|
||||||
#define UNSUPPORTED_FLAGS 0x0000fff8
|
#define UNSUPPORTED_FLAGS 0x0000fff8
|
||||||
|
@ -194,7 +195,10 @@ grub_multiboot_load (grub_file_t file)
|
||||||
static grub_size_t
|
static grub_size_t
|
||||||
grub_multiboot_get_mbi_size (void)
|
grub_multiboot_get_mbi_size (void)
|
||||||
{
|
{
|
||||||
return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
|
grub_size_t ret;
|
||||||
|
struct grub_net_network_level_interface *net;
|
||||||
|
|
||||||
|
ret = sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
|
||||||
+ modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
|
+ modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
|
||||||
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4)
|
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4)
|
||||||
+ grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)
|
+ grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)
|
||||||
|
@ -205,6 +209,15 @@ grub_multiboot_get_mbi_size (void)
|
||||||
+ sizeof (struct grub_vbe_mode_info_block)
|
+ sizeof (struct grub_vbe_mode_info_block)
|
||||||
#endif
|
#endif
|
||||||
+ ALIGN_UP (sizeof (struct multiboot_apm_info), 4);
|
+ ALIGN_UP (sizeof (struct multiboot_apm_info), 4);
|
||||||
|
|
||||||
|
FOR_NET_NETWORK_LEVEL_INTERFACES(net)
|
||||||
|
if (net->dhcp_ack)
|
||||||
|
{
|
||||||
|
ret += net->dhcp_acklen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill previously allocated Multiboot mmap. */
|
/* Fill previously allocated Multiboot mmap. */
|
||||||
|
@ -530,6 +543,20 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
|
||||||
mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
|
mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
struct grub_net_network_level_interface *net;
|
||||||
|
FOR_NET_NETWORK_LEVEL_INTERFACES(net)
|
||||||
|
if (net->dhcp_ack)
|
||||||
|
{
|
||||||
|
grub_memcpy (ptrorig, net->dhcp_ack, net->dhcp_acklen);
|
||||||
|
mbi->drives_addr = ptrdest;
|
||||||
|
mbi->drives_length = net->dhcp_acklen;
|
||||||
|
ptrorig += net->dhcp_acklen;
|
||||||
|
ptrdest += net->dhcp_acklen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (elf_sec_num)
|
if (elf_sec_num)
|
||||||
{
|
{
|
||||||
mbi->u.elf_sec.addr = ptrdest;
|
mbi->u.elf_sec.addr = ptrdest;
|
||||||
|
|
166
grub-core/net/arp.c
Normal file
166
grub-core/net/arp.c
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
#include <grub/net/arp.h>
|
||||||
|
#include <grub/net/netbuff.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
#include <grub/net/ethernet.h>
|
||||||
|
#include <grub/net/ip.h>
|
||||||
|
#include <grub/time.h>
|
||||||
|
|
||||||
|
static struct arp_entry arp_table[10];
|
||||||
|
static grub_int8_t new_table_entry = -1;
|
||||||
|
|
||||||
|
static void
|
||||||
|
arp_init_table (void)
|
||||||
|
{
|
||||||
|
grub_memset (arp_table, 0, sizeof (arp_table));
|
||||||
|
new_table_entry = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct arp_entry *
|
||||||
|
arp_find_entry (const grub_net_network_level_address_t *proto)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < ARRAY_SIZE (arp_table); i++)
|
||||||
|
{
|
||||||
|
if (arp_table[i].avail == 1 &&
|
||||||
|
arp_table[i].nl_address.ipv4 == proto->ipv4)
|
||||||
|
return &(arp_table[i]);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_arp_resolve (struct grub_net_network_level_interface *inf,
|
||||||
|
const grub_net_network_level_address_t *proto_addr,
|
||||||
|
grub_net_link_level_address_t *hw_addr)
|
||||||
|
{
|
||||||
|
struct arp_entry *entry;
|
||||||
|
struct grub_net_buff nb;
|
||||||
|
struct arphdr *arp_header;
|
||||||
|
grub_net_link_level_address_t target_hw_addr;
|
||||||
|
char *aux, arp_data[128];
|
||||||
|
grub_err_t err;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
|
||||||
|
&& proto_addr->ipv4 == 0xffffffff)
|
||||||
|
{
|
||||||
|
hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||||
|
grub_memset (hw_addr->mac, -1, 6);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check cache table. */
|
||||||
|
entry = arp_find_entry (proto_addr);
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
*hw_addr = entry->ll_address;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
/* Build a request packet. */
|
||||||
|
nb.head = arp_data;
|
||||||
|
nb.end = arp_data + sizeof (arp_data);
|
||||||
|
grub_netbuff_clear (&nb);
|
||||||
|
grub_netbuff_reserve (&nb, 128);
|
||||||
|
|
||||||
|
err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
arp_header = (struct arphdr *) nb.data;
|
||||||
|
arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET);
|
||||||
|
arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP);
|
||||||
|
/* FIXME Add support to ipv6 address. */
|
||||||
|
arp_header->hln = 6;
|
||||||
|
arp_header->pln = 4;
|
||||||
|
arp_header->op = grub_cpu_to_be16 (ARP_REQUEST);
|
||||||
|
aux = (char *) arp_header + sizeof (*arp_header);
|
||||||
|
/* Sender hardware address. */
|
||||||
|
grub_memcpy (aux, &inf->hwaddress.mac, 6);
|
||||||
|
|
||||||
|
aux += 6;
|
||||||
|
/* Sender protocol address */
|
||||||
|
grub_memcpy (aux, &inf->address.ipv4, 4);
|
||||||
|
aux += 4;
|
||||||
|
/* Target hardware address */
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
aux[i] = 0x00;
|
||||||
|
aux += 6;
|
||||||
|
/* Target protocol address */
|
||||||
|
grub_memcpy (aux, &proto_addr->ipv4, 4);
|
||||||
|
grub_memset (&target_hw_addr.mac, 0xff, 6);
|
||||||
|
|
||||||
|
send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP);
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
entry = arp_find_entry (proto_addr);
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
grub_memcpy (hw_addr, &entry->ll_address, sizeof (*hw_addr));
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
grub_net_poll_cards (200);
|
||||||
|
}
|
||||||
|
|
||||||
|
return grub_error (GRUB_ERR_TIMEOUT, "timeout: could not resolve hardware address");
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_arp_receive (struct grub_net_buff *nb)
|
||||||
|
{
|
||||||
|
struct arphdr *arp_header = (struct arphdr *) nb->data;
|
||||||
|
struct arp_entry *entry;
|
||||||
|
grub_uint8_t *sender_hardware_address, *sender_protocol_address;
|
||||||
|
grub_uint8_t *target_hardware_address, *target_protocol_address;
|
||||||
|
grub_net_network_level_address_t hwaddress;
|
||||||
|
struct grub_net_network_level_interface *inf;
|
||||||
|
|
||||||
|
sender_hardware_address =
|
||||||
|
(grub_uint8_t *) arp_header + sizeof (*arp_header);
|
||||||
|
sender_protocol_address = sender_hardware_address + arp_header->hln;
|
||||||
|
target_hardware_address = sender_protocol_address + arp_header->pln;
|
||||||
|
target_protocol_address = target_hardware_address + arp_header->hln;
|
||||||
|
grub_memcpy (&hwaddress.ipv4, sender_protocol_address, 4);
|
||||||
|
|
||||||
|
/* Check if the sender is in the cache table. */
|
||||||
|
entry = arp_find_entry (&hwaddress);
|
||||||
|
/* Update sender hardware address. */
|
||||||
|
if (entry)
|
||||||
|
grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Add sender to cache table. */
|
||||||
|
if (new_table_entry == -1)
|
||||||
|
arp_init_table ();
|
||||||
|
entry = &(arp_table[new_table_entry]);
|
||||||
|
entry->avail = 1;
|
||||||
|
grub_memcpy (&entry->nl_address.ipv4, sender_protocol_address, 4);
|
||||||
|
grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6);
|
||||||
|
new_table_entry++;
|
||||||
|
if (new_table_entry == ARRAY_SIZE (arp_table))
|
||||||
|
new_table_entry = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||||
|
{
|
||||||
|
/* Am I the protocol address target? */
|
||||||
|
if (grub_memcmp (target_protocol_address, &inf->address.ipv4, 6) == 0
|
||||||
|
&& grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST)
|
||||||
|
{
|
||||||
|
grub_net_link_level_address_t aux;
|
||||||
|
/* Swap hardware fields */
|
||||||
|
grub_memcpy (target_hardware_address, sender_hardware_address,
|
||||||
|
arp_header->hln);
|
||||||
|
grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6);
|
||||||
|
grub_memcpy (aux.mac, sender_protocol_address, 6);
|
||||||
|
grub_memcpy (sender_protocol_address, target_protocol_address,
|
||||||
|
arp_header->pln);
|
||||||
|
grub_memcpy (target_protocol_address, aux.mac, arp_header->pln);
|
||||||
|
/* Change operation to REPLY and send packet */
|
||||||
|
arp_header->op = grub_be_to_cpu16 (ARP_REPLY);
|
||||||
|
grub_memcpy (aux.mac, target_hardware_address, 6);
|
||||||
|
send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
86
grub-core/net/drivers/emu/emunet.c
Normal file
86
grub-core/net/drivers/emu/emunet.c
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/net/netbuff.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_tun.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <grub/term.h>
|
||||||
|
|
||||||
|
static int fd;
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
send_card_buffer (const struct grub_net_card *dev __attribute__ ((unused)),
|
||||||
|
struct grub_net_buff *pack)
|
||||||
|
{
|
||||||
|
ssize_t actual;
|
||||||
|
|
||||||
|
actual = write (fd, pack->data, pack->tail - pack->data);
|
||||||
|
if (actual < 0)
|
||||||
|
return grub_error (GRUB_ERR_IO, "couldn't send packets");
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_ssize_t
|
||||||
|
get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)),
|
||||||
|
struct grub_net_buff *pack)
|
||||||
|
{
|
||||||
|
ssize_t actual;
|
||||||
|
|
||||||
|
grub_netbuff_clear (pack);
|
||||||
|
actual = read (fd, pack->data, 1500);
|
||||||
|
if (actual < 0)
|
||||||
|
return -1;
|
||||||
|
grub_netbuff_put (pack, actual);
|
||||||
|
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct grub_net_card_driver emudriver =
|
||||||
|
{
|
||||||
|
.name = "emu",
|
||||||
|
.send = send_card_buffer,
|
||||||
|
.recv = get_card_packet
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct grub_net_card emucard =
|
||||||
|
{
|
||||||
|
.name = "emu0",
|
||||||
|
.driver = &emudriver,
|
||||||
|
.default_address = {
|
||||||
|
.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET,
|
||||||
|
{.mac = {0, 1, 2, 3, 4, 5}}
|
||||||
|
},
|
||||||
|
.flags = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
GRUB_MOD_INIT(emunet)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
fd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK);
|
||||||
|
if (fd < 0)
|
||||||
|
return;
|
||||||
|
grub_memset (&ifr, 0, sizeof (ifr));
|
||||||
|
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
||||||
|
if (ioctl (fd, TUNSETIFF, &ifr) < 0)
|
||||||
|
{
|
||||||
|
close (fd);
|
||||||
|
fd = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
grub_net_card_register (&emucard);
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_FINI(emunet)
|
||||||
|
{
|
||||||
|
if (fd >= 0)
|
||||||
|
{
|
||||||
|
close (fd);
|
||||||
|
grub_net_card_unregister (&emucard);
|
||||||
|
}
|
||||||
|
}
|
237
grub-core/net/drivers/ieee1275/ofnet.c
Normal file
237
grub-core/net/drivers/ieee1275/ofnet.c
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
#include <grub/net/netbuff.h>
|
||||||
|
#include <grub/ieee1275/ofnet.h>
|
||||||
|
#include <grub/ieee1275/ieee1275.h>
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
#include <grub/time.h>
|
||||||
|
|
||||||
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
card_open (struct grub_net_card *dev)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
struct grub_ofnetcard_data *data = dev->data;
|
||||||
|
char path[grub_strlen (data->path) +
|
||||||
|
grub_strlen (":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512") + 1];
|
||||||
|
|
||||||
|
/* The full string will prevent a bootp packet to be sent. Just put some valid ip in there. */
|
||||||
|
grub_snprintf (path, sizeof (path), "%s%s", data->path,
|
||||||
|
":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512");
|
||||||
|
status = grub_ieee1275_open (path, &(data->handle));
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
return grub_error (GRUB_ERR_IO, "Couldn't open network card.");
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
card_close (struct grub_net_card *dev)
|
||||||
|
{
|
||||||
|
struct grub_ofnetcard_data *data = dev->data;
|
||||||
|
|
||||||
|
if (data->handle)
|
||||||
|
grub_ieee1275_close (data->handle);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack)
|
||||||
|
{
|
||||||
|
int actual;
|
||||||
|
int status;
|
||||||
|
struct grub_ofnetcard_data *data = dev->data;
|
||||||
|
|
||||||
|
status = grub_ieee1275_write (data->handle, pack->data,
|
||||||
|
pack->tail - pack->data, &actual);
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
return grub_error (GRUB_ERR_IO, "Couldn't send network packet.");
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_ssize_t
|
||||||
|
get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb)
|
||||||
|
{
|
||||||
|
|
||||||
|
int actual, rc;
|
||||||
|
struct grub_ofnetcard_data *data = dev->data;
|
||||||
|
grub_uint64_t start_time;
|
||||||
|
|
||||||
|
grub_netbuff_clear (nb);
|
||||||
|
start_time = grub_get_time_ms ();
|
||||||
|
do
|
||||||
|
rc = grub_ieee1275_read (data->handle, nb->data, data->mtu, &actual);
|
||||||
|
while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
|
||||||
|
if (actual)
|
||||||
|
{
|
||||||
|
grub_netbuff_put (nb, actual);
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct grub_net_card_driver ofdriver =
|
||||||
|
{
|
||||||
|
.name = "ofnet",
|
||||||
|
.init = card_open,
|
||||||
|
.fini = card_close,
|
||||||
|
.send = send_card_buffer,
|
||||||
|
.recv = get_card_packet
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
int offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
bootp_response_properties[] =
|
||||||
|
{
|
||||||
|
{ .name = "bootp-response", .offset = 0},
|
||||||
|
{ .name = "dhcp-response", .offset = 0},
|
||||||
|
{ .name = "bootpreply-packet", .offset = 0x2a},
|
||||||
|
};
|
||||||
|
|
||||||
|
static grub_bootp_t
|
||||||
|
grub_getbootp_real (void)
|
||||||
|
{
|
||||||
|
grub_bootp_t packet = grub_malloc (sizeof *packet);
|
||||||
|
char *bootp_response;
|
||||||
|
grub_ssize_t size;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++)
|
||||||
|
if (grub_ieee1275_get_property_length (grub_ieee1275_chosen,
|
||||||
|
bootp_response_properties[i].name,
|
||||||
|
&size) >= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (size < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
bootp_response = grub_malloc (size);
|
||||||
|
if (grub_ieee1275_get_property (grub_ieee1275_chosen,
|
||||||
|
bootp_response_properties[i].name,
|
||||||
|
bootp_response, size, 0) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
grub_memcpy (packet, bootp_response + bootp_response_properties[i].offset, sizeof (*packet));
|
||||||
|
grub_free (bootp_response);
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_ofnet_findcards (void)
|
||||||
|
{
|
||||||
|
struct grub_net_card *card;
|
||||||
|
grub_ieee1275_phandle_t devhandle;
|
||||||
|
grub_net_link_level_address_t lla;
|
||||||
|
int i = 0;
|
||||||
|
auto int search_net_devices (struct grub_ieee1275_devalias *alias);
|
||||||
|
|
||||||
|
int search_net_devices (struct grub_ieee1275_devalias *alias)
|
||||||
|
{
|
||||||
|
if (!grub_strcmp (alias->type, "network"))
|
||||||
|
{
|
||||||
|
|
||||||
|
card = grub_malloc (sizeof (struct grub_net_card));
|
||||||
|
struct grub_ofnetcard_data *ofdata =
|
||||||
|
grub_malloc (sizeof (struct grub_ofnetcard_data));
|
||||||
|
ofdata->path = grub_strdup (alias->path);
|
||||||
|
|
||||||
|
grub_ieee1275_finddevice (ofdata->path, &devhandle);
|
||||||
|
|
||||||
|
if (grub_ieee1275_get_integer_property
|
||||||
|
(devhandle, "max-frame-size", &(ofdata->mtu),
|
||||||
|
sizeof (ofdata->mtu), 0))
|
||||||
|
return grub_error (GRUB_ERR_IO, "Couldn't retrieve mtu size.");
|
||||||
|
|
||||||
|
if (grub_ieee1275_get_property
|
||||||
|
(devhandle, "mac-address", &(lla.mac), 6, 0))
|
||||||
|
return grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address.");
|
||||||
|
|
||||||
|
lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||||
|
card->default_address = lla;
|
||||||
|
|
||||||
|
card->driver = NULL;
|
||||||
|
card->data = ofdata;
|
||||||
|
card->flags = 0;
|
||||||
|
card->name = grub_xasprintf ("eth%d", i++);
|
||||||
|
grub_net_card_register (card);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look at all nodes for devices of the type network. */
|
||||||
|
grub_ieee1275_devices_iterate (search_net_devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_ofnet_probecards (void)
|
||||||
|
{
|
||||||
|
struct grub_net_card *card;
|
||||||
|
struct grub_net_card_driver *driver;
|
||||||
|
struct grub_net_network_level_interface *inter;
|
||||||
|
grub_bootp_t bootp_pckt;
|
||||||
|
grub_net_network_level_address_t addr;
|
||||||
|
grub_net_network_level_netaddress_t net;
|
||||||
|
bootp_pckt = grub_getbootp ();
|
||||||
|
|
||||||
|
/* Assign correspondent driver for each device. */
|
||||||
|
FOR_NET_CARDS (card)
|
||||||
|
{
|
||||||
|
FOR_NET_CARD_DRIVERS (driver)
|
||||||
|
{
|
||||||
|
if (driver->init (card) == GRUB_ERR_NONE)
|
||||||
|
{
|
||||||
|
card->driver = driver;
|
||||||
|
if (bootp_pckt
|
||||||
|
&& grub_memcmp (bootp_pckt->chaddr, card->default_address.mac, 6) == 0)
|
||||||
|
{
|
||||||
|
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||||
|
addr.ipv4 = bootp_pckt->yiaddr;
|
||||||
|
grub_net_add_addr ("bootp_cli_addr", card, addr,
|
||||||
|
card->default_address, 0);
|
||||||
|
FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
|
||||||
|
if (grub_strcmp (inter->name, "bootp_cli_addr") == 0)
|
||||||
|
break;
|
||||||
|
net.type = addr.type;
|
||||||
|
net.ipv4.base = addr.ipv4;
|
||||||
|
net.ipv4.masksize = 24;
|
||||||
|
grub_net_add_route ("bootp-router", net, inter);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grub_free (bootp_pckt);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_INIT(ofnet)
|
||||||
|
{
|
||||||
|
struct grub_net_card *card;
|
||||||
|
grub_getbootp = grub_getbootp_real;
|
||||||
|
grub_net_card_driver_register (&ofdriver);
|
||||||
|
grub_ofnet_findcards ();
|
||||||
|
grub_ofnet_probecards ();
|
||||||
|
FOR_NET_CARDS (card)
|
||||||
|
if (card->driver == NULL)
|
||||||
|
grub_net_card_unregister (card);
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_FINI(ofnet)
|
||||||
|
{
|
||||||
|
struct grub_net_card *card;
|
||||||
|
FOR_NET_CARDS (card)
|
||||||
|
if (card->driver && !grub_strcmp (card->driver->name, "ofnet"))
|
||||||
|
{
|
||||||
|
card->driver->fini (card);
|
||||||
|
card->driver = NULL;
|
||||||
|
}
|
||||||
|
grub_net_card_driver_unregister (&ofdriver);
|
||||||
|
grub_getbootp = NULL;
|
||||||
|
}
|
78
grub-core/net/ethernet.c
Normal file
78
grub-core/net/ethernet.c
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/net/ethernet.h>
|
||||||
|
#include <grub/net/ip.h>
|
||||||
|
#include <grub/net/arp.h>
|
||||||
|
#include <grub/net/netbuff.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
#include <grub/time.h>
|
||||||
|
#include <grub/net/arp.h>
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
send_ethernet_packet (struct grub_net_network_level_interface *inf,
|
||||||
|
struct grub_net_buff *nb,
|
||||||
|
grub_net_link_level_address_t target_addr,
|
||||||
|
grub_uint16_t ethertype)
|
||||||
|
{
|
||||||
|
struct etherhdr *eth;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
err = grub_netbuff_push (nb, sizeof (*eth));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
eth = (struct etherhdr *) nb->data;
|
||||||
|
grub_memcpy (eth->dst, target_addr.mac, 6);
|
||||||
|
grub_memcpy (eth->src, inf->hwaddress.mac, 6);
|
||||||
|
|
||||||
|
eth->type = grub_cpu_to_be16 (ethertype);
|
||||||
|
|
||||||
|
return inf->card->driver->send (inf->card, nb);
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_recv_ethernet_packet (struct grub_net_buff * nb,
|
||||||
|
const struct grub_net_card * card)
|
||||||
|
{
|
||||||
|
struct etherhdr *eth;
|
||||||
|
struct llchdr *llch;
|
||||||
|
struct snaphdr *snaph;
|
||||||
|
grub_uint16_t type;
|
||||||
|
grub_net_link_level_address_t hwaddress;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
eth = (struct etherhdr *) nb->data;
|
||||||
|
type = grub_be_to_cpu16 (eth->type);
|
||||||
|
err = grub_netbuff_pull (nb, sizeof (*eth));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (type <= 1500)
|
||||||
|
{
|
||||||
|
llch = (struct llchdr *) nb->data;
|
||||||
|
type = llch->dsap & LLCADDRMASK;
|
||||||
|
|
||||||
|
if (llch->dsap == 0xaa && llch->ssap == 0xaa && llch->ctrl == 0x3)
|
||||||
|
{
|
||||||
|
err = grub_netbuff_pull (nb, sizeof (*llch));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
snaph = (struct snaphdr *) nb->data;
|
||||||
|
type = snaph->type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||||
|
grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac));
|
||||||
|
|
||||||
|
/* ARP packet. */
|
||||||
|
if (type == GRUB_NET_ETHERTYPE_ARP)
|
||||||
|
{
|
||||||
|
grub_net_arp_receive (nb);
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
}
|
||||||
|
/* IP packet. */
|
||||||
|
if (type == GRUB_NET_ETHERTYPE_IP)
|
||||||
|
grub_net_recv_ip_packets (nb, card, &hwaddress);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
|
@ -18,9 +18,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/fs.h>
|
#include <grub/net.h>
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/disk.h>
|
|
||||||
#include <grub/file.h>
|
#include <grub/file.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/bufio.h>
|
#include <grub/bufio.h>
|
||||||
|
@ -30,35 +29,29 @@
|
||||||
#include <grub/machine/int.h>
|
#include <grub/machine/int.h>
|
||||||
#include <grub/machine/memory.h>
|
#include <grub/machine/memory.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
|
||||||
|
|
||||||
#define SEGMENT(x) ((x) >> 4)
|
#define SEGMENT(x) ((x) >> 4)
|
||||||
#define OFFSET(x) ((x) & 0xF)
|
#define OFFSET(x) ((x) & 0xF)
|
||||||
#define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x))
|
#define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x))
|
||||||
#define LINEAR(x) (void *) (((x >> 16) <<4) + (x & 0xFFFF))
|
#define LINEAR(x) (void *) (((x >> 16) << 4) + (x & 0xFFFF))
|
||||||
|
|
||||||
struct grub_pxe_disk_data
|
|
||||||
{
|
|
||||||
grub_uint32_t server_ip;
|
|
||||||
grub_uint32_t gateway_ip;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct grub_pxe_bangpxe *grub_pxe_pxenv;
|
struct grub_pxe_bangpxe *grub_pxe_pxenv;
|
||||||
static grub_uint32_t grub_pxe_your_ip;
|
|
||||||
static grub_uint32_t grub_pxe_default_server_ip;
|
static grub_uint32_t grub_pxe_default_server_ip;
|
||||||
|
#if 0
|
||||||
static grub_uint32_t grub_pxe_default_gateway_ip;
|
static grub_uint32_t grub_pxe_default_gateway_ip;
|
||||||
|
#endif
|
||||||
static unsigned grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE;
|
static unsigned grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE;
|
||||||
|
static grub_uint32_t pxe_rm_entry = 0;
|
||||||
static grub_file_t curr_file = 0;
|
static grub_file_t curr_file = 0;
|
||||||
|
|
||||||
struct grub_pxe_data
|
struct grub_pxe_data
|
||||||
{
|
{
|
||||||
grub_uint32_t packet_number;
|
grub_uint32_t packet_number;
|
||||||
grub_uint32_t block_size;
|
grub_uint32_t block_size;
|
||||||
|
grub_uint32_t server_ip;
|
||||||
|
grub_uint32_t gateway_ip;
|
||||||
char filename[0];
|
char filename[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
static grub_uint32_t pxe_rm_entry = 0;
|
|
||||||
|
|
||||||
static struct grub_pxe_bangpxe *
|
static struct grub_pxe_bangpxe *
|
||||||
grub_pxe_scan (void)
|
grub_pxe_scan (void)
|
||||||
|
@ -103,132 +96,13 @@ grub_pxe_scan (void)
|
||||||
return bangpxe;
|
return bangpxe;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
grub_pxe_iterate (int (*hook) (const char *name))
|
|
||||||
{
|
|
||||||
if (hook ("pxe"))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
|
grub_pxefs_dir (grub_device_t device __attribute__ ((unused)),
|
||||||
{
|
|
||||||
grub_uint32_t newip = 0;
|
|
||||||
unsigned long t;
|
|
||||||
int i;
|
|
||||||
const char *ptr = val;
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
t = grub_strtoul (ptr, (char **) &ptr, 0);
|
|
||||||
if (grub_errno)
|
|
||||||
return grub_errno;
|
|
||||||
if (t & ~0xff)
|
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
|
|
||||||
newip >>= 8;
|
|
||||||
newip |= (t << 24);
|
|
||||||
if (i != 3 && *ptr != '.')
|
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
*ip = newip;
|
|
||||||
if (rest)
|
|
||||||
*rest = ptr - 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_pxe_open (const char *name, grub_disk_t disk)
|
|
||||||
{
|
|
||||||
struct grub_pxe_disk_data *data;
|
|
||||||
|
|
||||||
if (grub_strcmp (name, "pxe") != 0
|
|
||||||
&& grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) != 0)
|
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a pxe disk");
|
|
||||||
|
|
||||||
data = grub_malloc (sizeof (*data));
|
|
||||||
if (!data)
|
|
||||||
return grub_errno;
|
|
||||||
|
|
||||||
if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
|
|
||||||
{
|
|
||||||
const char *ptr;
|
|
||||||
grub_err_t err;
|
|
||||||
|
|
||||||
ptr = name + sizeof ("pxe:") - 1;
|
|
||||||
err = parse_ip (ptr, &(data->server_ip), &ptr);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
if (*ptr == ':')
|
|
||||||
{
|
|
||||||
err = parse_ip (ptr + 1, &(data->gateway_ip), 0);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
data->gateway_ip = grub_pxe_default_gateway_ip;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data->server_ip = grub_pxe_default_server_ip;
|
|
||||||
data->gateway_ip = grub_pxe_default_gateway_ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
disk->total_sectors = 0;
|
|
||||||
disk->id = (unsigned long) data;
|
|
||||||
|
|
||||||
disk->data = data;
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
grub_pxe_close (grub_disk_t disk)
|
|
||||||
{
|
|
||||||
grub_free (disk->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_pxe_read (grub_disk_t disk __attribute((unused)),
|
|
||||||
grub_disk_addr_t sector __attribute((unused)),
|
|
||||||
grub_size_t size __attribute((unused)),
|
|
||||||
char *buf __attribute((unused)))
|
|
||||||
{
|
|
||||||
return GRUB_ERR_OUT_OF_RANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_pxe_write (grub_disk_t disk __attribute((unused)),
|
|
||||||
grub_disk_addr_t sector __attribute((unused)),
|
|
||||||
grub_size_t size __attribute((unused)),
|
|
||||||
const char *buf __attribute((unused)))
|
|
||||||
{
|
|
||||||
return GRUB_ERR_OUT_OF_RANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct grub_disk_dev grub_pxe_dev =
|
|
||||||
{
|
|
||||||
.name = "pxe",
|
|
||||||
.id = GRUB_DISK_DEVICE_PXE_ID,
|
|
||||||
.iterate = grub_pxe_iterate,
|
|
||||||
.open = grub_pxe_open,
|
|
||||||
.close = grub_pxe_close,
|
|
||||||
.read = grub_pxe_read,
|
|
||||||
.write = grub_pxe_write,
|
|
||||||
.next = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_pxefs_dir (grub_device_t device,
|
|
||||||
const char *path __attribute__ ((unused)),
|
const char *path __attribute__ ((unused)),
|
||||||
int (*hook) (const char *filename,
|
int (*hook) (const char *filename,
|
||||||
const struct grub_dirhook_info *info)
|
const struct grub_dirhook_info *info)
|
||||||
__attribute__ ((unused)))
|
__attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
if (device->disk->dev->id != GRUB_DISK_DEVICE_PXE_ID)
|
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "not a pxe disk");
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,11 +115,45 @@ grub_pxefs_open (struct grub_file *file, const char *name)
|
||||||
struct grub_pxenv_tftp_open c2;
|
struct grub_pxenv_tftp_open c2;
|
||||||
} c;
|
} c;
|
||||||
struct grub_pxe_data *data;
|
struct grub_pxe_data *data;
|
||||||
struct grub_pxe_disk_data *disk_data = file->device->disk->data;
|
|
||||||
grub_file_t file_int, bufio;
|
grub_file_t file_int, bufio;
|
||||||
|
|
||||||
if (file->device->disk->dev->id != GRUB_DISK_DEVICE_PXE_ID)
|
data = grub_zalloc (sizeof (*data) + grub_strlen (name) + 1);
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "not a pxe disk");
|
if (!data)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
{
|
||||||
|
grub_net_network_level_address_t addr;
|
||||||
|
grub_net_network_level_address_t gateway;
|
||||||
|
struct grub_net_network_level_interface *interf;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
if (grub_strncmp (file->device->net->name,
|
||||||
|
"pxe,", sizeof ("pxe,") - 1) == 0
|
||||||
|
|| grub_strncmp (file->device->net->name,
|
||||||
|
"pxe:", sizeof ("pxe:") - 1) == 0)
|
||||||
|
{
|
||||||
|
err = grub_net_resolve_address (file->device->net->name
|
||||||
|
+ sizeof ("pxe,") - 1, &addr);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_free (data);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr.ipv4 = grub_pxe_default_server_ip;
|
||||||
|
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||||
|
}
|
||||||
|
err = grub_net_route_address (addr, &gateway, &interf);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_free (data);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
data->server_ip = addr.ipv4;
|
||||||
|
data->gateway_ip = gateway.ipv4;
|
||||||
|
}
|
||||||
|
|
||||||
if (curr_file != 0)
|
if (curr_file != 0)
|
||||||
{
|
{
|
||||||
|
@ -253,12 +161,15 @@ grub_pxefs_open (struct grub_file *file, const char *name)
|
||||||
curr_file = 0;
|
curr_file = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
c.c1.server_ip = disk_data->server_ip;
|
c.c1.server_ip = data->server_ip;
|
||||||
c.c1.gateway_ip = disk_data->gateway_ip;
|
c.c1.gateway_ip = data->gateway_ip;
|
||||||
grub_strcpy ((char *)&c.c1.filename[0], name);
|
grub_strcpy ((char *)&c.c1.filename[0], name);
|
||||||
grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry);
|
grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry);
|
||||||
if (c.c1.status)
|
if (c.c1.status)
|
||||||
|
{
|
||||||
|
grub_free (data);
|
||||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
|
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
|
||||||
|
}
|
||||||
|
|
||||||
file->size = c.c1.file_size;
|
file->size = c.c1.file_size;
|
||||||
|
|
||||||
|
@ -266,11 +177,10 @@ grub_pxefs_open (struct grub_file *file, const char *name)
|
||||||
c.c2.packet_size = grub_pxe_blksize;
|
c.c2.packet_size = grub_pxe_blksize;
|
||||||
grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2, pxe_rm_entry);
|
grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2, pxe_rm_entry);
|
||||||
if (c.c2.status)
|
if (c.c2.status)
|
||||||
|
{
|
||||||
|
grub_free (data);
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "open fails");
|
return grub_error (GRUB_ERR_BAD_FS, "open fails");
|
||||||
|
}
|
||||||
data = grub_zalloc (sizeof (struct grub_pxe_data) + grub_strlen (name) + 1);
|
|
||||||
if (! data)
|
|
||||||
return grub_errno;
|
|
||||||
|
|
||||||
data->block_size = c.c2.packet_size;
|
data->block_size = c.c2.packet_size;
|
||||||
grub_strcpy (data->filename, name);
|
grub_strcpy (data->filename, name);
|
||||||
|
@ -305,7 +215,6 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
{
|
{
|
||||||
struct grub_pxenv_tftp_read c;
|
struct grub_pxenv_tftp_read c;
|
||||||
struct grub_pxe_data *data;
|
struct grub_pxe_data *data;
|
||||||
struct grub_pxe_disk_data *disk_data = file->device->disk->data;
|
|
||||||
grub_uint32_t pn;
|
grub_uint32_t pn;
|
||||||
grub_uint64_t r;
|
grub_uint64_t r;
|
||||||
|
|
||||||
|
@ -326,8 +235,8 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
if (curr_file != 0)
|
if (curr_file != 0)
|
||||||
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o, pxe_rm_entry);
|
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o, pxe_rm_entry);
|
||||||
|
|
||||||
o.server_ip = disk_data->server_ip;
|
o.server_ip = data->server_ip;
|
||||||
o.gateway_ip = disk_data->gateway_ip;
|
o.gateway_ip = data->gateway_ip;
|
||||||
grub_strcpy ((char *)&o.filename[0], data->filename);
|
grub_strcpy ((char *)&o.filename[0], data->filename);
|
||||||
o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT);
|
o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT);
|
||||||
o.packet_size = data->block_size;
|
o.packet_size = data->block_size;
|
||||||
|
@ -386,7 +295,7 @@ grub_pxefs_label (grub_device_t device __attribute ((unused)),
|
||||||
|
|
||||||
static struct grub_fs grub_pxefs_fs =
|
static struct grub_fs grub_pxefs_fs =
|
||||||
{
|
{
|
||||||
.name = "pxefs",
|
.name = "pxe",
|
||||||
.dir = grub_pxefs_dir,
|
.dir = grub_pxefs_dir,
|
||||||
.open = grub_pxefs_open,
|
.open = grub_pxefs_open,
|
||||||
.read = grub_pxefs_read,
|
.read = grub_pxefs_read,
|
||||||
|
@ -395,134 +304,31 @@ static struct grub_fs grub_pxefs_fs =
|
||||||
.next = 0
|
.next = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *
|
static grub_ssize_t
|
||||||
grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
|
grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)),
|
||||||
const char *val __attribute__ ((unused)))
|
struct grub_net_buff *buf __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static grub_err_t
|
||||||
set_mac_env (grub_uint8_t *mac_addr, grub_size_t mac_len)
|
grub_pxe_send (struct grub_net_card *dev __attribute__ ((unused)),
|
||||||
|
struct grub_net_buff *buf __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
char buf[(sizeof ("XX:") - 1) * mac_len + 1];
|
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "not implemented");
|
||||||
char *ptr = buf;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
for (i = 0; i < mac_len; i++)
|
|
||||||
{
|
|
||||||
grub_snprintf (ptr, sizeof (buf) - (ptr - buf),
|
|
||||||
"%02x:", mac_addr[i] & 0xff);
|
|
||||||
ptr += (sizeof ("XX:") - 1);
|
|
||||||
}
|
|
||||||
if (mac_len)
|
|
||||||
*(ptr - 1) = 0;
|
|
||||||
else
|
|
||||||
buf[0] = 0;
|
|
||||||
|
|
||||||
grub_env_set ("net_pxe_mac", buf);
|
|
||||||
/* XXX: Is it possible to change MAC in PXE? */
|
|
||||||
grub_register_variable_hook ("net_pxe_mac", 0, grub_env_write_readonly);
|
|
||||||
grub_env_export ("net_pxe_mac");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
struct grub_net_card_driver grub_pxe_card_driver =
|
||||||
set_env_limn_ro (const char *varname, char *value, grub_size_t len)
|
|
||||||
{
|
{
|
||||||
char c;
|
.send = grub_pxe_send,
|
||||||
c = value[len];
|
.recv = grub_pxe_recv
|
||||||
value[len] = 0;
|
};
|
||||||
grub_env_set (varname, value);
|
|
||||||
value[len] = c;
|
|
||||||
grub_register_variable_hook (varname, 0, grub_env_write_readonly);
|
|
||||||
grub_env_export (varname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
struct grub_net_card grub_pxe_card =
|
||||||
parse_dhcp_vendor (void *vend, int limit)
|
|
||||||
{
|
{
|
||||||
grub_uint8_t *ptr, *ptr0;
|
.driver = &grub_pxe_card_driver,
|
||||||
|
.name = "pxe"
|
||||||
ptr = ptr0 = vend;
|
};
|
||||||
|
|
||||||
if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) != 0x63825363)
|
|
||||||
return;
|
|
||||||
ptr = ptr + sizeof (grub_uint32_t);
|
|
||||||
while (ptr - ptr0 < limit)
|
|
||||||
{
|
|
||||||
grub_uint8_t tagtype;
|
|
||||||
grub_uint8_t taglength;
|
|
||||||
|
|
||||||
tagtype = *ptr++;
|
|
||||||
|
|
||||||
/* Pad tag. */
|
|
||||||
if (tagtype == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* End tag. */
|
|
||||||
if (tagtype == 0xff)
|
|
||||||
return;
|
|
||||||
|
|
||||||
taglength = *ptr++;
|
|
||||||
|
|
||||||
switch (tagtype)
|
|
||||||
{
|
|
||||||
case 12:
|
|
||||||
set_env_limn_ro ("net_pxe_hostname", (char *) ptr, taglength);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 15:
|
|
||||||
set_env_limn_ro ("net_pxe_domain", (char *) ptr, taglength);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 17:
|
|
||||||
set_env_limn_ro ("net_pxe_rootpath", (char *) ptr, taglength);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 18:
|
|
||||||
set_env_limn_ro ("net_pxe_extensionspath", (char *) ptr, taglength);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* If you need any other options please contact GRUB
|
|
||||||
development team. */
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr += taglength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
grub_pxe_detect (void)
|
|
||||||
{
|
|
||||||
struct grub_pxe_bangpxe *pxenv;
|
|
||||||
struct grub_pxenv_get_cached_info ci;
|
|
||||||
struct grub_pxenv_boot_player *bp;
|
|
||||||
|
|
||||||
pxenv = grub_pxe_scan ();
|
|
||||||
if (! pxenv)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK;
|
|
||||||
ci.buffer = 0;
|
|
||||||
ci.buffer_size = 0;
|
|
||||||
grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry);
|
|
||||||
if (ci.status)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bp = LINEAR (ci.buffer);
|
|
||||||
|
|
||||||
grub_pxe_your_ip = bp->your_ip;
|
|
||||||
grub_pxe_default_server_ip = bp->server_ip;
|
|
||||||
grub_pxe_default_gateway_ip = bp->gateway_ip;
|
|
||||||
set_mac_env (bp->mac_addr, bp->hw_len < sizeof (bp->mac_addr) ? bp->hw_len
|
|
||||||
: sizeof (bp->mac_addr));
|
|
||||||
set_env_limn_ro ("net_pxe_boot_file", (char *) bp->boot_file,
|
|
||||||
sizeof (bp->boot_file));
|
|
||||||
set_env_limn_ro ("net_pxe_dhcp_server_name", (char *) bp->server_name,
|
|
||||||
sizeof (bp->server_name));
|
|
||||||
parse_dhcp_vendor (&bp->vendor, sizeof (bp->vendor));
|
|
||||||
grub_pxe_pxenv = pxenv;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_pxe_unload (void)
|
grub_pxe_unload (void)
|
||||||
|
@ -530,8 +336,7 @@ grub_pxe_unload (void)
|
||||||
if (grub_pxe_pxenv)
|
if (grub_pxe_pxenv)
|
||||||
{
|
{
|
||||||
grub_fs_unregister (&grub_pxefs_fs);
|
grub_fs_unregister (&grub_pxefs_fs);
|
||||||
grub_disk_dev_unregister (&grub_pxe_dev);
|
grub_net_card_unregister (&grub_pxe_card);
|
||||||
|
|
||||||
grub_pxe_pxenv = 0;
|
grub_pxe_pxenv = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -539,10 +344,12 @@ grub_pxe_unload (void)
|
||||||
static void
|
static void
|
||||||
set_ip_env (char *varname, grub_uint32_t ip)
|
set_ip_env (char *varname, grub_uint32_t ip)
|
||||||
{
|
{
|
||||||
char buf[sizeof ("XXX.XXX.XXX.XXX")];
|
char buf[GRUB_NET_MAX_STR_ADDR_LEN];
|
||||||
|
grub_net_network_level_address_t addr;
|
||||||
|
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||||
|
addr.ipv4 = ip;
|
||||||
|
|
||||||
grub_snprintf (buf, sizeof (buf), "%d.%d.%d.%d", (ip & 0xff),
|
grub_net_addr_to_str (&addr, buf);
|
||||||
(ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);
|
|
||||||
grub_env_set (varname, buf);
|
grub_env_set (varname, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,19 +358,21 @@ write_ip_env (grub_uint32_t *ip, const char *val)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
grub_uint32_t newip;
|
grub_net_network_level_address_t addr;
|
||||||
|
|
||||||
err = parse_ip (val, &newip, 0);
|
err = grub_net_resolve_address (val, &addr);
|
||||||
if (err)
|
if (err)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* Normalize the IP. */
|
/* Normalize the IP. */
|
||||||
buf = grub_xasprintf ("%d.%d.%d.%d", (newip & 0xff), (newip >> 8) & 0xff,
|
buf = grub_malloc (GRUB_NET_MAX_STR_ADDR_LEN);
|
||||||
(newip >> 16) & 0xff, (newip >> 24) & 0xff);
|
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return 0;
|
return 0;
|
||||||
|
grub_net_addr_to_str (&addr, buf);
|
||||||
|
|
||||||
*ip = newip;
|
*ip = addr.ipv4;
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
@ -576,6 +385,7 @@ grub_env_write_pxe_default_server (struct grub_env_var *var
|
||||||
return write_ip_env (&grub_pxe_default_server_ip, val);
|
return write_ip_env (&grub_pxe_default_server_ip, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static char *
|
static char *
|
||||||
grub_env_write_pxe_default_gateway (struct grub_env_var *var
|
grub_env_write_pxe_default_gateway (struct grub_env_var *var
|
||||||
__attribute__ ((unused)),
|
__attribute__ ((unused)),
|
||||||
|
@ -583,6 +393,7 @@ grub_env_write_pxe_default_gateway (struct grub_env_var *var
|
||||||
{
|
{
|
||||||
return write_ip_env (&grub_pxe_default_gateway_ip, val);
|
return write_ip_env (&grub_pxe_default_gateway_ip, val);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)),
|
grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)),
|
||||||
|
@ -609,42 +420,60 @@ grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)),
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GRUB_MOD_INIT(pxe)
|
GRUB_MOD_INIT(pxe)
|
||||||
{
|
{
|
||||||
grub_pxe_detect ();
|
struct grub_pxe_bangpxe *pxenv;
|
||||||
if (grub_pxe_pxenv)
|
struct grub_pxenv_get_cached_info ci;
|
||||||
{
|
struct grub_net_bootp_ack *bp;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
|
pxenv = grub_pxe_scan ();
|
||||||
|
if (! pxenv)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK;
|
||||||
|
ci.buffer = 0;
|
||||||
|
ci.buffer_size = 0;
|
||||||
|
grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry);
|
||||||
|
if (ci.status)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bp = LINEAR (ci.buffer);
|
||||||
|
|
||||||
|
grub_pxe_default_server_ip = bp->server_ip;
|
||||||
|
grub_pxe_pxenv = pxenv;
|
||||||
|
|
||||||
|
set_ip_env ("pxe_default_server", grub_pxe_default_server_ip);
|
||||||
|
grub_register_variable_hook ("pxe_default_server", 0,
|
||||||
|
grub_env_write_pxe_default_server);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
grub_pxe_default_gateway_ip = bp->gateway_ip;
|
||||||
|
|
||||||
|
grub_register_variable_hook ("pxe_default_gateway", 0,
|
||||||
|
grub_env_write_pxe_default_gateway);
|
||||||
|
#endif
|
||||||
|
|
||||||
buf = grub_xasprintf ("%d", grub_pxe_blksize);
|
buf = grub_xasprintf ("%d", grub_pxe_blksize);
|
||||||
if (buf)
|
if (buf)
|
||||||
grub_env_set ("pxe_blksize", buf);
|
grub_env_set ("pxe_blksize", buf);
|
||||||
grub_free (buf);
|
grub_free (buf);
|
||||||
|
|
||||||
set_ip_env ("pxe_default_server", grub_pxe_default_server_ip);
|
|
||||||
set_ip_env ("pxe_default_gateway", grub_pxe_default_gateway_ip);
|
|
||||||
set_ip_env ("net_pxe_ip", grub_pxe_your_ip);
|
|
||||||
grub_register_variable_hook ("pxe_default_server", 0,
|
|
||||||
grub_env_write_pxe_default_server);
|
|
||||||
grub_register_variable_hook ("pxe_default_gateway", 0,
|
|
||||||
grub_env_write_pxe_default_gateway);
|
|
||||||
|
|
||||||
|
|
||||||
/* XXX: Is it possible to change IP in PXE? */
|
|
||||||
grub_register_variable_hook ("net_pxe_ip", 0,
|
|
||||||
grub_env_write_readonly);
|
|
||||||
grub_register_variable_hook ("pxe_blksize", 0,
|
grub_register_variable_hook ("pxe_blksize", 0,
|
||||||
grub_env_write_pxe_blocksize);
|
grub_env_write_pxe_blocksize);
|
||||||
|
|
||||||
grub_env_export ("pxe_default_server");
|
grub_memcpy (grub_pxe_card.default_address.mac, bp->mac_addr,
|
||||||
grub_env_export ("pxe_default_gateway");
|
bp->hw_len < sizeof (grub_pxe_card.default_address.mac)
|
||||||
grub_env_export ("net_pxe_ip");
|
? bp->hw_len : sizeof (grub_pxe_card.default_address.mac));
|
||||||
grub_env_export ("pxe_blksize");
|
grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||||
|
|
||||||
grub_disk_dev_register (&grub_pxe_dev);
|
|
||||||
grub_fs_register (&grub_pxefs_fs);
|
grub_fs_register (&grub_pxefs_fs);
|
||||||
}
|
grub_net_card_register (&grub_pxe_card);
|
||||||
|
grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card,
|
||||||
|
GRUB_NET_INTERFACE_PERMANENT
|
||||||
|
| GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE
|
||||||
|
| GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE,
|
||||||
|
bp, GRUB_PXE_BOOTP_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(pxe)
|
GRUB_MOD_FINI(pxe)
|
118
grub-core/net/ip.c
Normal file
118
grub-core/net/ip.c
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
#include <grub/net/ip.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/net/arp.h>
|
||||||
|
#include <grub/net/udp.h>
|
||||||
|
#include <grub/net/ethernet.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
#include <grub/net/netbuff.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
|
||||||
|
grub_uint16_t
|
||||||
|
ipchksum (void *ipv, int len)
|
||||||
|
{
|
||||||
|
grub_uint16_t *ip = (grub_uint16_t *) ipv;
|
||||||
|
grub_uint32_t sum = 0;
|
||||||
|
|
||||||
|
len >>= 1;
|
||||||
|
while (len--)
|
||||||
|
{
|
||||||
|
sum += grub_be_to_cpu16 (*(ip++));
|
||||||
|
if (sum > 0xFFFF)
|
||||||
|
sum -= 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return grub_cpu_to_be16 ((~sum) & 0x0000FFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_send_ip_packet (struct grub_net_network_level_interface * inf,
|
||||||
|
const grub_net_network_level_address_t * target,
|
||||||
|
struct grub_net_buff * nb)
|
||||||
|
{
|
||||||
|
struct iphdr *iph;
|
||||||
|
static int id = 0x2400;
|
||||||
|
grub_net_link_level_address_t ll_target_addr;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
grub_netbuff_push (nb, sizeof (*iph));
|
||||||
|
iph = (struct iphdr *) nb->data;
|
||||||
|
|
||||||
|
iph->verhdrlen = ((4 << 4) | 5);
|
||||||
|
iph->service = 0;
|
||||||
|
iph->len = grub_cpu_to_be16 (nb->tail - nb->data);
|
||||||
|
iph->ident = grub_cpu_to_be16 (++id);
|
||||||
|
iph->frags = 0;
|
||||||
|
iph->ttl = 0xff;
|
||||||
|
iph->protocol = 0x11;
|
||||||
|
iph->src = inf->address.ipv4;
|
||||||
|
iph->dest = target->ipv4;
|
||||||
|
|
||||||
|
iph->chksum = 0;
|
||||||
|
iph->chksum = ipchksum ((void *) nb->data, sizeof (*iph));
|
||||||
|
|
||||||
|
/* Determine link layer target address via ARP. */
|
||||||
|
err = grub_net_arp_resolve (inf, target, &ll_target_addr);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
return send_ethernet_packet (inf, nb, ll_target_addr,
|
||||||
|
GRUB_NET_ETHERTYPE_IP);
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_recv_ip_packets (struct grub_net_buff * nb,
|
||||||
|
const struct grub_net_card * card,
|
||||||
|
const grub_net_link_level_address_t * hwaddress)
|
||||||
|
{
|
||||||
|
struct iphdr *iph = (struct iphdr *) nb->data;
|
||||||
|
grub_err_t err;
|
||||||
|
struct grub_net_network_level_interface *inf;
|
||||||
|
|
||||||
|
err = grub_netbuff_pull (nb, sizeof (*iph));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||||
|
{
|
||||||
|
if (inf->card == card
|
||||||
|
&& inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
|
||||||
|
&& inf->address.ipv4 == iph->dest
|
||||||
|
&& grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!inf)
|
||||||
|
{
|
||||||
|
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||||
|
if (inf->card == card
|
||||||
|
&& inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC
|
||||||
|
&& grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!inf)
|
||||||
|
{
|
||||||
|
if (iph->protocol == IP_UDP
|
||||||
|
&& grub_net_hwaddr_cmp (&card->default_address, hwaddress) == 0)
|
||||||
|
{
|
||||||
|
struct udphdr *udph;
|
||||||
|
udph = (struct udphdr *) nb->data;
|
||||||
|
err = grub_netbuff_pull (nb, sizeof (*udph));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
if (grub_be_to_cpu16 (udph->dst) == 68)
|
||||||
|
grub_net_process_dhcp (nb, card);
|
||||||
|
}
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (iph->protocol)
|
||||||
|
{
|
||||||
|
case IP_UDP:
|
||||||
|
return grub_net_recv_udp_packet (nb, inf);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
1312
grub-core/net/net.c
Normal file
1312
grub-core/net/net.c
Normal file
File diff suppressed because it is too large
Load diff
106
grub-core/net/netbuff.c
Normal file
106
grub-core/net/netbuff.c
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/err.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/net/netbuff.h>
|
||||||
|
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_netbuff_put (struct grub_net_buff *nb, grub_size_t len)
|
||||||
|
{
|
||||||
|
nb->tail += len;
|
||||||
|
if (nb->tail > nb->end)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, "put out of the packet range.");
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_netbuff_unput (struct grub_net_buff *nb, grub_size_t len)
|
||||||
|
{
|
||||||
|
nb->tail -= len;
|
||||||
|
if (nb->tail < nb->head)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
|
"unput out of the packet range.");
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_netbuff_push (struct grub_net_buff *nb, grub_size_t len)
|
||||||
|
{
|
||||||
|
nb->data -= len;
|
||||||
|
if (nb->data < nb->head)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
|
"push out of the packet range.");
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_netbuff_pull (struct grub_net_buff *nb, grub_size_t len)
|
||||||
|
{
|
||||||
|
nb->data += len;
|
||||||
|
if (nb->data > nb->end)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
|
"pull out of the packet range.");
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_netbuff_reserve (struct grub_net_buff *nb, grub_size_t len)
|
||||||
|
{
|
||||||
|
nb->data += len;
|
||||||
|
nb->tail += len;
|
||||||
|
if ((nb->tail > nb->end) || (nb->data > nb->end))
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
|
"reserve out of the packet range.");
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct grub_net_buff *
|
||||||
|
grub_netbuff_alloc (grub_size_t len)
|
||||||
|
{
|
||||||
|
struct grub_net_buff *nb;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
if (len < NETBUFFMINLEN)
|
||||||
|
len = NETBUFFMINLEN;
|
||||||
|
|
||||||
|
len = ALIGN_UP (len, NETBUFF_ALIGN);
|
||||||
|
data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb));
|
||||||
|
if (!data)
|
||||||
|
return NULL;
|
||||||
|
nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len);
|
||||||
|
nb->head = nb->data = nb->tail = data;
|
||||||
|
nb->end = (char *) nb;
|
||||||
|
return nb;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_netbuff_free (struct grub_net_buff *nb)
|
||||||
|
{
|
||||||
|
grub_free (nb->head);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_netbuff_clear (struct grub_net_buff *nb)
|
||||||
|
{
|
||||||
|
nb->data = nb->tail = nb->head;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
195
grub-core/net/tftp.c
Normal file
195
grub-core/net/tftp.c
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/net/tftp.h>
|
||||||
|
#include <grub/net/udp.h>
|
||||||
|
#include <grub/net/ip.h>
|
||||||
|
#include <grub/net/ethernet.h>
|
||||||
|
#include <grub/net/netbuff.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/file.h>
|
||||||
|
|
||||||
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
tftp_open (struct grub_file *file, const char *filename)
|
||||||
|
{
|
||||||
|
struct tftphdr *tftph;
|
||||||
|
char *rrq;
|
||||||
|
int i;
|
||||||
|
int rrqlen;
|
||||||
|
int hdrlen;
|
||||||
|
char open_data[1500];
|
||||||
|
struct grub_net_buff nb;
|
||||||
|
tftp_data_t data;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
data = grub_malloc (sizeof (*data));
|
||||||
|
if (!data)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
file->device->net->socket->data = (void *) data;
|
||||||
|
nb.head = open_data;
|
||||||
|
nb.end = open_data + sizeof (open_data);
|
||||||
|
grub_netbuff_clear (&nb);
|
||||||
|
|
||||||
|
grub_netbuff_reserve (&nb, 1500);
|
||||||
|
if ((err = grub_netbuff_push (&nb, sizeof (*tftph))) != GRUB_ERR_NONE)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
tftph = (struct tftphdr *) nb.data;
|
||||||
|
|
||||||
|
rrq = (char *) tftph->u.rrq;
|
||||||
|
rrqlen = 0;
|
||||||
|
|
||||||
|
tftph->opcode = grub_cpu_to_be16 (TFTP_RRQ);
|
||||||
|
grub_strcpy (rrq, filename);
|
||||||
|
rrqlen += grub_strlen (filename) + 1;
|
||||||
|
rrq += grub_strlen (filename) + 1;
|
||||||
|
|
||||||
|
grub_strcpy (rrq, "octet");
|
||||||
|
rrqlen += grub_strlen ("octet") + 1;
|
||||||
|
rrq += grub_strlen ("octet") + 1;
|
||||||
|
|
||||||
|
grub_strcpy (rrq, "blksize");
|
||||||
|
rrqlen += grub_strlen ("blksize") + 1;
|
||||||
|
rrq += grub_strlen ("blksize") + 1;
|
||||||
|
|
||||||
|
grub_strcpy (rrq, "1024");
|
||||||
|
rrqlen += grub_strlen ("1024") + 1;
|
||||||
|
rrq += grub_strlen ("1024") + 1;
|
||||||
|
|
||||||
|
grub_strcpy (rrq, "tsize");
|
||||||
|
rrqlen += grub_strlen ("tsize") + 1;
|
||||||
|
rrq += grub_strlen ("tsize") + 1;
|
||||||
|
|
||||||
|
grub_strcpy (rrq, "0");
|
||||||
|
rrqlen += grub_strlen ("0") + 1;
|
||||||
|
rrq += grub_strlen ("0") + 1;
|
||||||
|
hdrlen = sizeof (tftph->opcode) + rrqlen;
|
||||||
|
|
||||||
|
if ((err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen))) != GRUB_ERR_NONE)
|
||||||
|
return err;
|
||||||
|
file->device->net->socket->out_port = TFTP_SERVER_PORT;
|
||||||
|
|
||||||
|
err = grub_net_send_udp_packet (file->device->net->socket, &nb);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* Receive OACK packet. */
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
grub_net_poll_cards (100);
|
||||||
|
if (grub_errno)
|
||||||
|
return grub_errno;
|
||||||
|
if (file->device->net->socket->status != 0)
|
||||||
|
break;
|
||||||
|
/* Retry. */
|
||||||
|
/*err = grub_net_send_udp_packet (file->device->net->socket, &nb);
|
||||||
|
if (err)
|
||||||
|
return err; */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file->device->net->socket->status == 0)
|
||||||
|
return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp.");
|
||||||
|
file->size = data->file_size;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb)
|
||||||
|
{
|
||||||
|
struct tftphdr *tftph;
|
||||||
|
char nbdata[128];
|
||||||
|
tftp_data_t data = sock->data;
|
||||||
|
grub_err_t err;
|
||||||
|
char *ptr;
|
||||||
|
struct grub_net_buff nb_ack;
|
||||||
|
|
||||||
|
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:
|
||||||
|
for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;)
|
||||||
|
{
|
||||||
|
if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0)
|
||||||
|
{
|
||||||
|
data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1,
|
||||||
|
0, 0);
|
||||||
|
}
|
||||||
|
while (ptr < nb->tail && *ptr)
|
||||||
|
ptr++;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
sock->status = 1;
|
||||||
|
data->block = 0;
|
||||||
|
grub_netbuff_clear (nb);
|
||||||
|
break;
|
||||||
|
case TFTP_DATA:
|
||||||
|
if ((err = grub_netbuff_pull (nb, sizeof (tftph->opcode) +
|
||||||
|
sizeof (tftph->u.data.block))) != GRUB_ERR_NONE)
|
||||||
|
return err;
|
||||||
|
if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1)
|
||||||
|
{
|
||||||
|
data->block++;
|
||||||
|
unsigned size = nb->tail - nb->data;
|
||||||
|
if (size < 1024)
|
||||||
|
sock->status = 2;
|
||||||
|
/* Prevent garbage in broken cards. */
|
||||||
|
if (size > 1024)
|
||||||
|
if ((err = grub_netbuff_unput (nb, size - 1024)) != GRUB_ERR_NONE)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
grub_netbuff_clear (nb);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case TFTP_ERROR:
|
||||||
|
grub_netbuff_clear (nb);
|
||||||
|
return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
grub_netbuff_clear (&nb_ack);
|
||||||
|
grub_netbuff_reserve (&nb_ack, 128);
|
||||||
|
err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode)
|
||||||
|
+ sizeof (tftph->u.ack.block));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
tftph = (struct tftphdr *) nb_ack.data;
|
||||||
|
tftph->opcode = grub_cpu_to_be16 (TFTP_ACK);
|
||||||
|
tftph->u.ack.block = grub_cpu_to_be16 (data->block);
|
||||||
|
|
||||||
|
err = grub_net_send_udp_packet (sock, &nb_ack);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
tftp_close (struct grub_file *file __attribute__ ((unused)))
|
||||||
|
{
|
||||||
|
grub_free (file->device->net->socket->data);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct grub_net_app_protocol grub_tftp_protocol =
|
||||||
|
{
|
||||||
|
.name = "tftp",
|
||||||
|
.open = tftp_open,
|
||||||
|
.read = tftp_receive,
|
||||||
|
.close = tftp_close
|
||||||
|
};
|
||||||
|
|
||||||
|
GRUB_MOD_INIT (tftp)
|
||||||
|
{
|
||||||
|
grub_net_app_level_register (&grub_tftp_protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_FINI (tftp)
|
||||||
|
{
|
||||||
|
grub_net_app_level_unregister (&grub_tftp_protocol);
|
||||||
|
}
|
61
grub-core/net/udp.c
Normal file
61
grub-core/net/udp.c
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#include <grub/net.h>
|
||||||
|
#include <grub/net/udp.h>
|
||||||
|
#include <grub/net/ip.h>
|
||||||
|
#include <grub/net/netbuff.h>
|
||||||
|
#include <grub/time.h>
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_send_udp_packet (const grub_net_socket_t socket,
|
||||||
|
struct grub_net_buff *nb)
|
||||||
|
{
|
||||||
|
struct udphdr *udph;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
err = grub_netbuff_push (nb, sizeof (*udph));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
udph = (struct udphdr *) nb->data;
|
||||||
|
udph->src = grub_cpu_to_be16 (socket->in_port);
|
||||||
|
udph->dst = grub_cpu_to_be16 (socket->out_port);
|
||||||
|
|
||||||
|
/* No chechksum. */
|
||||||
|
udph->chksum = 0;
|
||||||
|
udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
|
||||||
|
|
||||||
|
return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb);
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_recv_udp_packet (struct grub_net_buff * nb,
|
||||||
|
struct grub_net_network_level_interface * inf)
|
||||||
|
{
|
||||||
|
struct udphdr *udph;
|
||||||
|
grub_net_socket_t sock;
|
||||||
|
udph = (struct udphdr *) nb->data;
|
||||||
|
grub_netbuff_pull (nb, sizeof (*udph));
|
||||||
|
|
||||||
|
FOR_NET_SOCKETS (sock)
|
||||||
|
{
|
||||||
|
if (grub_be_to_cpu16 (udph->dst) == sock->in_port
|
||||||
|
&& inf == sock->inf && sock->app)
|
||||||
|
{
|
||||||
|
if (sock->status == 0)
|
||||||
|
sock->out_port = grub_be_to_cpu16 (udph->src);
|
||||||
|
|
||||||
|
/* App protocol remove its own reader. */
|
||||||
|
sock->app->read (sock, nb);
|
||||||
|
|
||||||
|
/* If there is data, puts packet in socket list. */
|
||||||
|
if ((nb->tail - nb->data) > 0)
|
||||||
|
grub_net_put_packet (&sock->packs, nb);
|
||||||
|
else
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (grub_be_to_cpu16 (udph->dst) == 68)
|
||||||
|
grub_net_process_dhcp (nb, inf->card);
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
struct grub_disk;
|
struct grub_disk;
|
||||||
struct grub_net;
|
struct grub_net;
|
||||||
struct grub_fs;
|
|
||||||
|
|
||||||
struct grub_device
|
struct grub_device
|
||||||
{
|
{
|
||||||
|
|
6
include/grub/emu/export.h
Normal file
6
include/grub/emu/export.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
void EXPORT_FUNC (open64) (void);
|
||||||
|
void EXPORT_FUNC (close) (void);
|
||||||
|
void EXPORT_FUNC (read) (void);
|
||||||
|
void EXPORT_FUNC (write) (void);
|
||||||
|
void EXPORT_FUNC (ioctl) (void);
|
||||||
|
|
|
@ -56,6 +56,10 @@ typedef enum
|
||||||
GRUB_ERR_IO,
|
GRUB_ERR_IO,
|
||||||
GRUB_ERR_ACCESS_DENIED,
|
GRUB_ERR_ACCESS_DENIED,
|
||||||
GRUB_ERR_EXTRACTOR,
|
GRUB_ERR_EXTRACTOR,
|
||||||
|
GRUB_ERR_NET_BAD_ADDRESS,
|
||||||
|
GRUB_ERR_NET_ROUTE_LOOP,
|
||||||
|
GRUB_ERR_NET_NO_ROUTE,
|
||||||
|
GRUB_ERR_WAIT,
|
||||||
GRUB_ERR_BUG
|
GRUB_ERR_BUG
|
||||||
}
|
}
|
||||||
grub_err_t;
|
grub_err_t;
|
||||||
|
|
|
@ -152,9 +152,9 @@
|
||||||
#define GRUB_PXE_BOOTP_BCAST 0x8000
|
#define GRUB_PXE_BOOTP_BCAST 0x8000
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
#define GRUB_PXE_BOOTP_DHCPVEND 1024 /* DHCP extended vendor field size. */
|
#define GRUB_PXE_BOOTP_SIZE (1024 + 236) /* DHCP extended vendor field size. */
|
||||||
#else
|
#else
|
||||||
#define GRUB_PXE_BOOTP_DHCPVEND 312 /* DHCP standard vendor field size. */
|
#define GRUB_PXE_BOOTP_SIZE (312 + 236) /* DHCP standard vendor field size. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define GRUB_PXE_MIN_BLKSIZE 512
|
#define GRUB_PXE_MIN_BLKSIZE 512
|
||||||
|
@ -162,8 +162,6 @@
|
||||||
|
|
||||||
#define GRUB_PXE_TFTP_PORT 69
|
#define GRUB_PXE_TFTP_PORT 69
|
||||||
|
|
||||||
#define GRUB_PXE_VM_RFC1048 0x63825363L
|
|
||||||
|
|
||||||
#define GRUB_PXE_ERR_LEN 0xFFFFFFFF
|
#define GRUB_PXE_ERR_LEN 0xFFFFFFFF
|
||||||
|
|
||||||
#ifndef ASM_FILE
|
#ifndef ASM_FILE
|
||||||
|
@ -214,38 +212,6 @@ struct grub_pxenv_get_cached_info
|
||||||
grub_uint16_t buffer_limit;
|
grub_uint16_t buffer_limit;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
#define GRUB_PXE_MAC_ADDR_LEN 16
|
|
||||||
|
|
||||||
typedef grub_uint8_t grub_pxe_mac_addr_t[GRUB_PXE_MAC_ADDR_LEN];
|
|
||||||
|
|
||||||
struct grub_pxenv_boot_player
|
|
||||||
{
|
|
||||||
grub_uint8_t opcode;
|
|
||||||
grub_uint8_t hw_type; /* hardware type. */
|
|
||||||
grub_uint8_t hw_len; /* hardware addr len. */
|
|
||||||
grub_uint8_t gate_hops; /* zero it. */
|
|
||||||
grub_uint32_t ident; /* random number chosen by client. */
|
|
||||||
grub_uint16_t seconds; /* seconds since did initial bootstrap. */
|
|
||||||
grub_uint16_t flags;
|
|
||||||
grub_uint32_t client_ip;
|
|
||||||
grub_uint32_t your_ip;
|
|
||||||
grub_uint32_t server_ip;
|
|
||||||
grub_uint32_t gateway_ip;
|
|
||||||
grub_pxe_mac_addr_t mac_addr;
|
|
||||||
grub_uint8_t server_name[64];
|
|
||||||
grub_uint8_t boot_file[128];
|
|
||||||
union
|
|
||||||
{
|
|
||||||
grub_uint8_t d[GRUB_PXE_BOOTP_DHCPVEND]; /* raw array of vendor/dhcp options. */
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
grub_uint32_t magic; /* DHCP magic cookie. */
|
|
||||||
grub_uint32_t flags; /* bootp flags/opcodes. */
|
|
||||||
grub_uint8_t padding[56];
|
|
||||||
} v;
|
|
||||||
} vendor;
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
|
|
||||||
struct grub_pxenv_tftp_open
|
struct grub_pxenv_tftp_open
|
||||||
{
|
{
|
||||||
grub_uint16_t status;
|
grub_uint16_t status;
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/machine/ieee1275.h>
|
#include <grub/machine/ieee1275.h>
|
||||||
|
|
||||||
/* Maps a device alias to a pathname. */
|
|
||||||
struct grub_ieee1275_devalias
|
struct grub_ieee1275_devalias
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -65,6 +64,14 @@ struct grub_ieee1275_common_hdr
|
||||||
typedef grub_uint32_t grub_ieee1275_ihandle_t;
|
typedef grub_uint32_t grub_ieee1275_ihandle_t;
|
||||||
typedef grub_uint32_t grub_ieee1275_phandle_t;
|
typedef grub_uint32_t grub_ieee1275_phandle_t;
|
||||||
|
|
||||||
|
struct grub_ofnetcard_data
|
||||||
|
{
|
||||||
|
char *path;
|
||||||
|
grub_ieee1275_ihandle_t handle;
|
||||||
|
grub_uint32_t mtu;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Maps a device alias to a pathname. */
|
||||||
extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen);
|
extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen);
|
||||||
extern grub_ieee1275_ihandle_t EXPORT_VAR(grub_ieee1275_mmu);
|
extern grub_ieee1275_ihandle_t EXPORT_VAR(grub_ieee1275_mmu);
|
||||||
extern int (* EXPORT_VAR(grub_ieee1275_entry_fn)) (void *);
|
extern int (* EXPORT_VAR(grub_ieee1275_entry_fn)) (void *);
|
||||||
|
@ -191,11 +198,10 @@ EXPORT_FUNC(grub_ieee1275_map) (grub_addr_t phys, grub_addr_t virt,
|
||||||
|
|
||||||
char *EXPORT_FUNC(grub_ieee1275_encode_devname) (const char *path);
|
char *EXPORT_FUNC(grub_ieee1275_encode_devname) (const char *path);
|
||||||
char *EXPORT_FUNC(grub_ieee1275_get_filename) (const char *path);
|
char *EXPORT_FUNC(grub_ieee1275_get_filename) (const char *path);
|
||||||
|
|
||||||
int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook)
|
int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook)
|
||||||
(struct grub_ieee1275_devalias *
|
(struct grub_ieee1275_devalias *
|
||||||
alias));
|
alias));
|
||||||
|
char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path);
|
||||||
char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path);
|
char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path);
|
||||||
|
|
||||||
#endif /* ! GRUB_IEEE1275_HEADER */
|
#endif /* ! GRUB_IEEE1275_HEADER */
|
||||||
|
|
66
include/grub/ieee1275/ofnet.h
Normal file
66
include/grub/ieee1275/ofnet.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2002,2007 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRUB_OFNET_HEADER
|
||||||
|
#define GRUB_OFNET_HEADER 1
|
||||||
|
|
||||||
|
#include <grub/symbol.h>
|
||||||
|
#include <grub/err.h>
|
||||||
|
#include <grub/types.h>
|
||||||
|
|
||||||
|
struct grub_ofnet
|
||||||
|
{
|
||||||
|
/* The net name. */
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
/* The OF device string. */
|
||||||
|
char *dev;
|
||||||
|
/*server ip*/
|
||||||
|
char *sip;
|
||||||
|
/*client ip*/
|
||||||
|
char *cip;
|
||||||
|
/*gateway*/
|
||||||
|
char *gat;
|
||||||
|
/**/
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct grub_ofnet *grub_ofnet_t;
|
||||||
|
|
||||||
|
struct grub_bootp {
|
||||||
|
grub_uint8_t op; /* 1 = BOOTREQUEST, 2 = BOOTREPLY */
|
||||||
|
grub_uint8_t htype; /* Hardware address type. */
|
||||||
|
grub_uint8_t hlen; /* Hardware address length */
|
||||||
|
grub_uint8_t hops; /* Used by gateways in cross-gateway booting. */
|
||||||
|
grub_uint32_t xid; /* Transaction ID */
|
||||||
|
grub_uint16_t secs; /* Seconds elapsed. */
|
||||||
|
grub_uint16_t unused; /* Unused. */
|
||||||
|
grub_uint32_t ciaddr; /* Client IP address, */
|
||||||
|
grub_uint32_t yiaddr; /* Client IP address filled by server. */
|
||||||
|
grub_uint32_t siaddr; /* Server IP address. */
|
||||||
|
grub_uint32_t giaddr; /* Gateway IP address. */
|
||||||
|
unsigned char chaddr [16]; /* Client hardware address */
|
||||||
|
char sname [64]; /* Server name */
|
||||||
|
char file [128]; /* Boot filename */
|
||||||
|
unsigned char vend [64];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct grub_bootp* grub_bootp_t;
|
||||||
|
|
||||||
|
extern grub_bootp_t (*EXPORT_VAR (grub_getbootp)) (void);
|
||||||
|
#endif /* ! GRUB_NET_HEADER */
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* GRUB -- GRand Unified Bootloader
|
* GRUB -- GRand Unified Bootloader
|
||||||
* Copyright (C) 2002,2007 Free Software Foundation, Inc.
|
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* GRUB is free software: you can redistribute it and/or modify
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,54 +19,437 @@
|
||||||
#ifndef GRUB_NET_HEADER
|
#ifndef GRUB_NET_HEADER
|
||||||
#define GRUB_NET_HEADER 1
|
#define GRUB_NET_HEADER 1
|
||||||
|
|
||||||
#include <grub/symbol.h>
|
|
||||||
#include <grub/err.h>
|
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
|
#include <grub/err.h>
|
||||||
|
#include <grub/list.h>
|
||||||
|
#include <grub/fs.h>
|
||||||
|
#include <grub/file.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/net/netbuff.h>
|
||||||
|
|
||||||
struct grub_net;
|
typedef enum grub_link_level_protocol_id
|
||||||
|
|
||||||
struct grub_net_dev
|
|
||||||
{
|
{
|
||||||
/* The device name. */
|
GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET
|
||||||
const char *name;
|
} grub_link_level_protocol_id_t;
|
||||||
|
|
||||||
/* FIXME: Just a template. */
|
typedef struct grub_net_link_level_address
|
||||||
int (*probe) (struct grub_net *net, const void *addr);
|
{
|
||||||
void (*reset) (struct grub_net *net);
|
grub_link_level_protocol_id_t type;
|
||||||
int (*poll) (struct grub_net *net);
|
union
|
||||||
void (*transmit) (struct grub_net *net, const void *destip,
|
{
|
||||||
unsigned srcsock, unsigned destsock, const void *packet);
|
grub_uint8_t mac[6];
|
||||||
void (*disable) (struct grub_net *net);
|
};
|
||||||
|
} grub_net_link_level_address_t;
|
||||||
|
|
||||||
/* The next net device. */
|
typedef enum grub_net_interface_flags
|
||||||
struct grub_net_dev *next;
|
{
|
||||||
|
GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE = 1,
|
||||||
|
GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE = 2,
|
||||||
|
GRUB_NET_INTERFACE_PERMANENT = 4
|
||||||
|
} grub_net_interface_flags_t;
|
||||||
|
|
||||||
|
typedef enum grub_net_card_flags
|
||||||
|
{
|
||||||
|
GRUB_NET_CARD_HWADDRESS_IMMUTABLE = 1,
|
||||||
|
GRUB_NET_CARD_NO_MANUAL_INTERFACES = 2
|
||||||
|
} grub_net_card_flags_t;
|
||||||
|
|
||||||
|
struct grub_net_card;
|
||||||
|
|
||||||
|
struct grub_net_card_driver
|
||||||
|
{
|
||||||
|
struct grub_net_card_driver *next;
|
||||||
|
char *name;
|
||||||
|
grub_err_t (*init) (struct grub_net_card *dev);
|
||||||
|
grub_err_t (*fini) (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);
|
||||||
};
|
};
|
||||||
typedef struct grub_net_dev *grub_net_dev_t;
|
|
||||||
|
|
||||||
struct grub_fs;
|
extern struct grub_net_card_driver *grub_net_card_drivers;
|
||||||
|
|
||||||
struct grub_net
|
static inline void
|
||||||
|
grub_net_card_driver_register (struct grub_net_card_driver *driver)
|
||||||
{
|
{
|
||||||
/* The net name. */
|
grub_list_push (GRUB_AS_LIST_P (&grub_net_card_drivers),
|
||||||
const char *name;
|
GRUB_AS_LIST (driver));
|
||||||
|
}
|
||||||
|
|
||||||
/* The underlying disk device. */
|
static inline void
|
||||||
grub_net_dev_t dev;
|
grub_net_card_driver_unregister (struct grub_net_card_driver *driver)
|
||||||
|
{
|
||||||
|
grub_list_remove (GRUB_AS_LIST_P (&grub_net_card_drivers),
|
||||||
|
GRUB_AS_LIST (driver));
|
||||||
|
}
|
||||||
|
|
||||||
/* The binding filesystem. */
|
#define FOR_NET_CARD_DRIVERS(var) for (var = grub_net_card_drivers; var; var = var->next)
|
||||||
struct grub_fs *fs;
|
|
||||||
|
|
||||||
/* FIXME: More data would be required, such as an IP address, a mask,
|
typedef struct grub_net_packet
|
||||||
a gateway, etc. */
|
{
|
||||||
|
struct grub_net_packet *next;
|
||||||
|
struct grub_net_packet *prev;
|
||||||
|
struct grub_net_packets *up;
|
||||||
|
struct grub_net_buff *nb;
|
||||||
|
} grub_net_packet_t;
|
||||||
|
|
||||||
/* Device-specific data. */
|
typedef struct grub_net_packets
|
||||||
|
{
|
||||||
|
grub_net_packet_t *first;
|
||||||
|
grub_net_packet_t *last;
|
||||||
|
} grub_net_packets_t;
|
||||||
|
|
||||||
|
struct grub_net_card
|
||||||
|
{
|
||||||
|
struct grub_net_card *next;
|
||||||
|
char *name;
|
||||||
|
struct grub_net_card_driver *driver;
|
||||||
|
grub_net_link_level_address_t default_address;
|
||||||
|
grub_net_card_flags_t flags;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
int data_num;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct grub_net_network_level_interface;
|
||||||
|
|
||||||
|
typedef enum grub_network_level_protocol_id
|
||||||
|
{
|
||||||
|
GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC,
|
||||||
|
GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
|
||||||
|
} grub_network_level_protocol_id_t;
|
||||||
|
|
||||||
|
typedef struct grub_net_network_level_address
|
||||||
|
{
|
||||||
|
grub_network_level_protocol_id_t type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
grub_uint32_t ipv4;
|
||||||
|
};
|
||||||
|
} grub_net_network_level_address_t;
|
||||||
|
|
||||||
|
typedef struct grub_net_network_level_netaddress
|
||||||
|
{
|
||||||
|
grub_network_level_protocol_id_t type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
grub_uint32_t base;
|
||||||
|
int masksize;
|
||||||
|
} ipv4;
|
||||||
|
};
|
||||||
|
} grub_net_network_level_netaddress_t;
|
||||||
|
|
||||||
|
#define FOR_PACKETS(cont,var) for (var = (cont).first; var; var = var->next)
|
||||||
|
|
||||||
|
static inline grub_err_t
|
||||||
|
grub_net_put_packet (grub_net_packets_t *pkts, struct grub_net_buff *nb)
|
||||||
|
{
|
||||||
|
struct grub_net_packet *n;
|
||||||
|
|
||||||
|
n = grub_malloc (sizeof (*n));
|
||||||
|
if (!n)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
n->nb = nb;
|
||||||
|
n->next = NULL;
|
||||||
|
n->prev = NULL;
|
||||||
|
n->up = pkts;
|
||||||
|
if (pkts->first)
|
||||||
|
{
|
||||||
|
pkts->last->next = n;
|
||||||
|
pkts->last = n;
|
||||||
|
n->prev = pkts->last;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pkts->first = pkts->last = n;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
grub_net_remove_packet (grub_net_packet_t *pkt)
|
||||||
|
{
|
||||||
|
if (pkt->prev)
|
||||||
|
pkt->prev->next = pkt->next;
|
||||||
|
else
|
||||||
|
pkt->up->first = pkt->next;
|
||||||
|
if (pkt->next)
|
||||||
|
pkt->next->prev = pkt->prev;
|
||||||
|
else
|
||||||
|
pkt->up->last = pkt->prev;
|
||||||
|
grub_free (pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct grub_net_app_protocol *grub_net_app_level_t;
|
||||||
|
|
||||||
|
typedef struct grub_net_socket *grub_net_socket_t;
|
||||||
|
|
||||||
|
struct grub_net_app_protocol
|
||||||
|
{
|
||||||
|
struct grub_net_app_protocol *next;
|
||||||
|
char *name;
|
||||||
|
grub_err_t (*dir) (grub_device_t device, const char *path,
|
||||||
|
int (*hook) (const char *filename,
|
||||||
|
const struct grub_dirhook_info *info));
|
||||||
|
grub_err_t (*open) (struct grub_file *file, const char *filename);
|
||||||
|
grub_err_t (*read) (grub_net_socket_t sock, struct grub_net_buff *nb);
|
||||||
|
grub_err_t (*close) (struct grub_file *file);
|
||||||
|
grub_err_t (*label) (grub_device_t device, char **label);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct grub_net_socket
|
||||||
|
{
|
||||||
|
struct grub_net_socket *next;
|
||||||
|
int status;
|
||||||
|
int in_port;
|
||||||
|
int out_port;
|
||||||
|
grub_net_app_level_t app;
|
||||||
|
grub_net_network_level_address_t out_nla;
|
||||||
|
struct grub_net_network_level_interface *inf;
|
||||||
|
grub_net_packets_t packs;
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
typedef struct grub_net *grub_net_t;
|
|
||||||
|
|
||||||
/* FIXME: How to abstract networks? More consideration is necessary. */
|
extern struct grub_net_socket *grub_net_sockets;
|
||||||
|
|
||||||
/* Note: Networks are very different from disks, because networks must
|
static inline void
|
||||||
be initialized before used, and the status is persistent. */
|
grub_net_socket_register (grub_net_socket_t sock)
|
||||||
|
{
|
||||||
|
grub_list_push (GRUB_AS_LIST_P (&grub_net_sockets),
|
||||||
|
GRUB_AS_LIST (sock));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
grub_net_socket_unregister (grub_net_socket_t sock)
|
||||||
|
{
|
||||||
|
grub_list_remove (GRUB_AS_LIST_P (&grub_net_sockets),
|
||||||
|
GRUB_AS_LIST (sock));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FOR_NET_SOCKETS(var) for (var = grub_net_sockets; var; var = var->next)
|
||||||
|
|
||||||
|
typedef struct grub_net
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
grub_net_app_level_t protocol;
|
||||||
|
grub_net_socket_t socket;
|
||||||
|
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
|
||||||
|
{
|
||||||
|
struct grub_net_network_level_interface *next;
|
||||||
|
struct grub_net_network_level_interface **prev;
|
||||||
|
char *name;
|
||||||
|
const struct grub_net_card *card;
|
||||||
|
grub_net_network_level_address_t address;
|
||||||
|
grub_net_link_level_address_t hwaddress;
|
||||||
|
grub_net_interface_flags_t flags;
|
||||||
|
struct grub_net_bootp_packet *dhcp_ack;
|
||||||
|
grub_size_t dhcp_acklen;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct grub_net_session;
|
||||||
|
|
||||||
|
struct grub_net_session_level_protocol
|
||||||
|
{
|
||||||
|
void (*close) (struct grub_net_session *session);
|
||||||
|
grub_ssize_t (*recv) (struct grub_net_session *session, void *buf,
|
||||||
|
grub_size_t size);
|
||||||
|
grub_err_t (*send) (struct grub_net_session *session, void *buf,
|
||||||
|
grub_size_t size);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct grub_net_session
|
||||||
|
{
|
||||||
|
struct grub_net_session_level_protocol *protocol;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
grub_net_session_close (struct grub_net_session *session)
|
||||||
|
{
|
||||||
|
session->protocol->close (session);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline grub_err_t
|
||||||
|
grub_net_session_send (struct grub_net_session *session, void *buf,
|
||||||
|
grub_size_t size)
|
||||||
|
{
|
||||||
|
return session->protocol->send (session, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline grub_ssize_t
|
||||||
|
grub_net_session_recv (struct grub_net_session *session, void *buf,
|
||||||
|
grub_size_t size)
|
||||||
|
{
|
||||||
|
return session->protocol->recv (session, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct grub_net_network_level_interface *
|
||||||
|
grub_net_add_addr (const char *name,
|
||||||
|
const struct grub_net_card *card,
|
||||||
|
grub_net_network_level_address_t addr,
|
||||||
|
grub_net_link_level_address_t hwaddress,
|
||||||
|
grub_net_interface_flags_t flags);
|
||||||
|
|
||||||
|
extern struct grub_net_network_level_interface *grub_net_network_level_interfaces;
|
||||||
|
|
||||||
|
extern grub_net_app_level_t grub_net_app_level_list;
|
||||||
|
|
||||||
|
#ifndef GRUB_LST_GENERATOR
|
||||||
|
static inline void
|
||||||
|
grub_net_app_level_register (grub_net_app_level_t proto)
|
||||||
|
{
|
||||||
|
grub_list_push (GRUB_AS_LIST_P (&grub_net_app_level_list),
|
||||||
|
GRUB_AS_LIST (proto));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
grub_net_app_level_unregister (grub_net_app_level_t proto)
|
||||||
|
{
|
||||||
|
grub_list_remove (GRUB_AS_LIST_P (&grub_net_app_level_list),
|
||||||
|
GRUB_AS_LIST (proto));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FOR_NET_APP_LEVEL(var) FOR_LIST_ELEMENTS((var), \
|
||||||
|
(grub_net_app_level_list))
|
||||||
|
|
||||||
|
extern struct grub_net_card *grub_net_cards;
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
grub_net_card_register (struct grub_net_card *card)
|
||||||
|
{
|
||||||
|
grub_list_push (GRUB_AS_LIST_P (&grub_net_cards),
|
||||||
|
GRUB_AS_LIST (card));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
grub_net_card_unregister (struct grub_net_card *card)
|
||||||
|
{
|
||||||
|
grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards),
|
||||||
|
GRUB_AS_LIST (card));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next)
|
||||||
|
|
||||||
|
struct grub_net_session *
|
||||||
|
grub_net_open_tcp (char *address, grub_uint16_t port);
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_resolve_address (const char *name,
|
||||||
|
grub_net_network_level_address_t *addr);
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_resolve_net_address (const char *name,
|
||||||
|
grub_net_network_level_netaddress_t *addr);
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_route_address (grub_net_network_level_address_t addr,
|
||||||
|
grub_net_network_level_address_t *gateway,
|
||||||
|
struct grub_net_network_level_interface **interf);
|
||||||
|
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_add_route (const char *name,
|
||||||
|
grub_net_network_level_netaddress_t target,
|
||||||
|
struct grub_net_network_level_interface *inter);
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_add_route_gw (const char *name,
|
||||||
|
grub_net_network_level_netaddress_t target,
|
||||||
|
grub_net_network_level_address_t gw);
|
||||||
|
|
||||||
|
|
||||||
|
#define GRUB_NET_BOOTP_MAC_ADDR_LEN 16
|
||||||
|
|
||||||
|
typedef grub_uint8_t grub_net_bootp_mac_addr_t[GRUB_NET_BOOTP_MAC_ADDR_LEN];
|
||||||
|
|
||||||
|
struct grub_net_bootp_packet
|
||||||
|
{
|
||||||
|
grub_uint8_t opcode;
|
||||||
|
grub_uint8_t hw_type; /* hardware type. */
|
||||||
|
grub_uint8_t hw_len; /* hardware addr len. */
|
||||||
|
grub_uint8_t gate_hops; /* zero it. */
|
||||||
|
grub_uint32_t ident; /* random number chosen by client. */
|
||||||
|
grub_uint16_t seconds; /* seconds since did initial bootstrap. */
|
||||||
|
grub_uint16_t flags;
|
||||||
|
grub_uint32_t client_ip;
|
||||||
|
grub_uint32_t your_ip;
|
||||||
|
grub_uint32_t server_ip;
|
||||||
|
grub_uint32_t gateway_ip;
|
||||||
|
grub_net_bootp_mac_addr_t mac_addr;
|
||||||
|
grub_uint8_t server_name[64];
|
||||||
|
grub_uint8_t boot_file[128];
|
||||||
|
grub_uint8_t vendor[0];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#define GRUB_NET_BOOTP_RFC1048_MAGIC 0x63825363L
|
||||||
|
|
||||||
|
struct grub_net_network_level_interface *
|
||||||
|
grub_net_configure_by_dhcp_ack (const char *name,
|
||||||
|
const struct grub_net_card *card,
|
||||||
|
grub_net_interface_flags_t flags,
|
||||||
|
const struct grub_net_bootp_packet *bp,
|
||||||
|
grub_size_t size);
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_net_process_dhcp (struct grub_net_buff *nb,
|
||||||
|
const struct grub_net_card *card);
|
||||||
|
|
||||||
|
int
|
||||||
|
grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a,
|
||||||
|
const grub_net_link_level_address_t *b);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Currently suppoerted adresses:
|
||||||
|
IPv4: XXX.XXX.XXX.XXX
|
||||||
|
*/
|
||||||
|
#define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXX.XXX.XXX.XXX")
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_net_addr_to_str (const grub_net_network_level_address_t *target,
|
||||||
|
char *buf);
|
||||||
|
|
||||||
|
extern struct grub_net_network_level_interface *grub_net_network_level_interfaces;
|
||||||
|
#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next)
|
||||||
|
|
||||||
|
grub_err_t grub_net_send_link_layer (struct grub_net_network_level_interface *inf,
|
||||||
|
struct grub_net_buff *nb,
|
||||||
|
grub_net_link_level_address_t *target);
|
||||||
|
|
||||||
|
typedef int
|
||||||
|
(*grub_net_packet_handler_t) (struct grub_net_buff *nb,
|
||||||
|
struct grub_net_network_level_interface *inf);
|
||||||
|
|
||||||
|
grub_err_t grub_net_recv_link_layer (struct grub_net_network_level_interface *inf,
|
||||||
|
grub_net_packet_handler_t handler);
|
||||||
|
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_recv_ip_packets (struct grub_net_buff *nb,
|
||||||
|
const struct grub_net_card *card,
|
||||||
|
const grub_net_link_level_address_t *hwaddress);
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_send_ip_packet (struct grub_net_network_level_interface *inf,
|
||||||
|
const grub_net_network_level_address_t *target,
|
||||||
|
struct grub_net_buff *nb);
|
||||||
|
|
||||||
|
#define FOR_NET_NL_PACKETS(inf, var) FOR_PACKETS(inf->nl_pending, var)
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_net_poll_cards (unsigned time);
|
||||||
|
|
||||||
#endif /* ! GRUB_NET_HEADER */
|
#endif /* ! GRUB_NET_HEADER */
|
||||||
|
|
36
include/grub/net/arp.h
Normal file
36
include/grub/net/arp.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef GRUB_NET_ARP_HEADER
|
||||||
|
#define GRUB_NET_ARP_HEADER 1
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
/* IANA ARP constant to define hardware type as ethernet. */
|
||||||
|
GRUB_NET_ARPHRD_ETHERNET = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ARP header operation codes */
|
||||||
|
#define ARP_REQUEST 1
|
||||||
|
#define ARP_REPLY 2
|
||||||
|
|
||||||
|
struct arp_entry {
|
||||||
|
int avail;
|
||||||
|
grub_net_network_level_address_t nl_address;
|
||||||
|
grub_net_link_level_address_t ll_address;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct arphdr {
|
||||||
|
grub_uint16_t hrd;
|
||||||
|
grub_uint16_t pro;
|
||||||
|
grub_uint8_t hln;
|
||||||
|
grub_uint8_t pln;
|
||||||
|
grub_uint16_t op;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
extern grub_err_t grub_net_arp_receive(struct grub_net_buff *nb);
|
||||||
|
|
||||||
|
extern grub_err_t grub_net_arp_resolve(struct grub_net_network_level_interface *inf,
|
||||||
|
const grub_net_network_level_address_t *addr,
|
||||||
|
grub_net_link_level_address_t *hw_addr);
|
||||||
|
|
||||||
|
#endif
|
0
include/grub/net/device.h
Normal file
0
include/grub/net/device.h
Normal file
45
include/grub/net/ethernet.h
Normal file
45
include/grub/net/ethernet.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef GRUB_NET_ETHERNET_HEADER
|
||||||
|
#define GRUB_NET_ETHERNET_HEADER 1
|
||||||
|
#include <grub/types.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
|
||||||
|
#define LLCADDRMASK 0x7f
|
||||||
|
|
||||||
|
struct etherhdr
|
||||||
|
{
|
||||||
|
grub_uint8_t dst[6];
|
||||||
|
grub_uint8_t src[6];
|
||||||
|
grub_uint16_t type;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct llchdr
|
||||||
|
{
|
||||||
|
grub_uint8_t dsap;
|
||||||
|
grub_uint8_t ssap;
|
||||||
|
grub_uint8_t ctrl;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct snaphdr
|
||||||
|
{
|
||||||
|
grub_uint8_t oui[3];
|
||||||
|
grub_uint16_t type;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* IANA Ethertype */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
GRUB_NET_ETHERTYPE_IP = 0x0800,
|
||||||
|
GRUB_NET_ETHERTYPE_ARP = 0x0806
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
send_ethernet_packet (struct grub_net_network_level_interface *inf,
|
||||||
|
struct grub_net_buff *nb,
|
||||||
|
grub_net_link_level_address_t target_addr,
|
||||||
|
grub_uint16_t ethertype);
|
||||||
|
grub_err_t
|
||||||
|
grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
|
||||||
|
const struct grub_net_card *card);
|
||||||
|
|
||||||
|
#endif
|
35
include/grub/net/ip.h
Normal file
35
include/grub/net/ip.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef GRUB_NET_IP_HEADER
|
||||||
|
#define GRUB_NET_IP_HEADER 1
|
||||||
|
#include <grub/misc.h>
|
||||||
|
|
||||||
|
struct iphdr {
|
||||||
|
grub_uint8_t verhdrlen;
|
||||||
|
grub_uint8_t service;
|
||||||
|
grub_uint16_t len;
|
||||||
|
grub_uint16_t ident;
|
||||||
|
grub_uint16_t frags;
|
||||||
|
grub_uint8_t ttl;
|
||||||
|
grub_uint8_t protocol;
|
||||||
|
grub_uint16_t chksum;
|
||||||
|
grub_uint32_t src;
|
||||||
|
grub_uint32_t dest;
|
||||||
|
} __attribute__ ((packed)) ;
|
||||||
|
|
||||||
|
struct ip6hdr
|
||||||
|
{
|
||||||
|
grub_uint8_t version:4, priority:4;
|
||||||
|
grub_uint8_t flow_lbl[3];
|
||||||
|
grub_uint16_t payload_len;
|
||||||
|
grub_uint8_t nexthdr;
|
||||||
|
grub_uint8_t hop_limit;
|
||||||
|
grub_uint8_t saddr[16];
|
||||||
|
grub_uint8_t daddr[16];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#define IP_UDP 0x11 /* UDP protocol */
|
||||||
|
#define IP_BROADCAST 0xFFFFFFFF
|
||||||
|
|
||||||
|
grub_uint16_t ipchksum(void *ipv, int len);
|
||||||
|
void ipv4_ini(void);
|
||||||
|
void ipv4_fini(void);
|
||||||
|
#endif
|
30
include/grub/net/netbuff.h
Normal file
30
include/grub/net/netbuff.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef GRUB_NETBUFF_HEADER
|
||||||
|
#define GRUB_NETBUFF_HEADER
|
||||||
|
|
||||||
|
#include <grub/misc.h>
|
||||||
|
|
||||||
|
#define NETBUFF_ALIGN 2048
|
||||||
|
#define NETBUFFMINLEN 64
|
||||||
|
|
||||||
|
struct grub_net_buff
|
||||||
|
{
|
||||||
|
/*Pointer to the start of the buffer*/
|
||||||
|
char *head;
|
||||||
|
/*Pointer to the data */
|
||||||
|
char *data;
|
||||||
|
/*Pointer to the tail */
|
||||||
|
char *tail;
|
||||||
|
/*Pointer to the end of the buffer*/
|
||||||
|
char *end;
|
||||||
|
};
|
||||||
|
|
||||||
|
grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len);
|
||||||
|
grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len);
|
||||||
|
grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len);
|
||||||
|
grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len);
|
||||||
|
grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len);
|
||||||
|
grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff);
|
||||||
|
struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len );
|
||||||
|
grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff);
|
||||||
|
|
||||||
|
#endif
|
74
include/grub/net/tftp.h
Normal file
74
include/grub/net/tftp.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#ifndef GRUB_NET_TFTP_HEADER
|
||||||
|
#define GRUB_NET_TFTP_HEADER 1
|
||||||
|
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/net/ethernet.h>
|
||||||
|
#include <grub/net/udp.h>
|
||||||
|
|
||||||
|
/* IP port for the MTFTP server used for Intel's PXE */
|
||||||
|
#define MTFTP_SERVER_PORT 75
|
||||||
|
#define MTFTP_CLIENT_PORT 76
|
||||||
|
|
||||||
|
#define TFTP_DEFAULTSIZE_PACKET 512
|
||||||
|
#define TFTP_MAX_PACKET 1432
|
||||||
|
|
||||||
|
/* IP port for the TFTP server */
|
||||||
|
#define TFTP_SERVER_PORT 69
|
||||||
|
|
||||||
|
|
||||||
|
/* We define these based on what's in arpa/tftp.h. We just like our
|
||||||
|
* names better, cause they're clearer */
|
||||||
|
#define TFTP_RRQ 1
|
||||||
|
#define TFTP_WRQ 2
|
||||||
|
#define TFTP_DATA 3
|
||||||
|
#define TFTP_ACK 4
|
||||||
|
#define TFTP_ERROR 5
|
||||||
|
#define TFTP_OACK 6
|
||||||
|
|
||||||
|
#define TFTP_CODE_EOF 1
|
||||||
|
#define TFTP_CODE_MORE 2
|
||||||
|
#define TFTP_CODE_ERROR 3
|
||||||
|
#define TFTP_CODE_BOOT 4
|
||||||
|
#define TFTP_CODE_CFG 5
|
||||||
|
|
||||||
|
#define TFTP_EUNDEF 0 /* not defined */
|
||||||
|
#define TFTP_ENOTFOUND 1 /* file not found */
|
||||||
|
#define TFTP_EACCESS 2 /* access violation */
|
||||||
|
#define TFTP_ENOSPACE 3 /* disk full or allocation exceeded */
|
||||||
|
#define TFTP_EBADOP 4 /* illegal TFTP operation */
|
||||||
|
#define TFTP_EBADID 5 /* unknown transfer ID */
|
||||||
|
#define TFTP_EEXISTS 6 /* file already exists */
|
||||||
|
#define TFTP_ENOUSER 7 /* no such user */
|
||||||
|
|
||||||
|
/* * 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;
|
||||||
|
union {
|
||||||
|
grub_int8_t rrq[TFTP_DEFAULTSIZE_PACKET];
|
||||||
|
struct {
|
||||||
|
grub_uint16_t block;
|
||||||
|
grub_int8_t download[TFTP_MAX_PACKET];
|
||||||
|
} data;
|
||||||
|
struct {
|
||||||
|
grub_uint16_t block;
|
||||||
|
} ack;
|
||||||
|
struct {
|
||||||
|
grub_uint16_t errcode;
|
||||||
|
grub_int8_t errmsg[TFTP_DEFAULTSIZE_PACKET];
|
||||||
|
} err;
|
||||||
|
struct {
|
||||||
|
grub_int8_t data[TFTP_DEFAULTSIZE_PACKET+2];
|
||||||
|
} oack;
|
||||||
|
} u;
|
||||||
|
} __attribute__ ((packed)) ;
|
||||||
|
|
||||||
|
#endif
|
24
include/grub/net/udp.h
Normal file
24
include/grub/net/udp.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef GRUB_NET_UDP_HEADER
|
||||||
|
#define GRUB_NET_UDP_HEADER 1
|
||||||
|
#include <grub/types.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
|
||||||
|
struct udphdr
|
||||||
|
{
|
||||||
|
grub_uint16_t src;
|
||||||
|
grub_uint16_t dst;
|
||||||
|
grub_uint16_t len;
|
||||||
|
grub_uint16_t chksum;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb);
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_recv_udp_packet (struct grub_net_buff *nb,
|
||||||
|
struct grub_net_network_level_interface *inf);
|
||||||
|
|
||||||
|
|
||||||
|
#define FOR_NET_UDP_PACKETS(inf, var) FOR_PACKETS(inf->udp_pending, var)
|
||||||
|
|
||||||
|
#endif
|
Loading…
Add table
Add a link
Reference in a new issue