Unify sparc init with other ieee1275.
* grub-core/Makefile.core.def (kernel): Use kern/ieee1275/init.c instead of kern/sparc64/ieee1275/init.c. * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options) [__sparc__]: Set GRUB_IEEE1275_FLAG_NO_PARTITION_0. * grub-core/kern/ieee1275/init.c [__sparc__]: Include grub/machine/kernel.h. (grub_ieee1275_original_stack) [__sparc__]: New variable. (grub_claim_heap) [__sparc__]: Use sparc version. (grub_machine_init): Moved args parsing to (grub_parse_cmdline): ...this. * grub-core/kern/sparc64/ieee1275/init.c: Removed. * include/grub/offsets.h (GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP): New definition. (GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN): Likewise. Move BOOTP to separate file. * grub-core/Makefile.core.def (net): Add net/bootp.c. * grub-core/net/net.c: Move all BOOTP functions to * grub-core/net/bootp.c: ... here. Use frame interface on PXE. * grub-core/Makefile.core.def (pxecmd): Removed. (pxe): Use net/drivers/i386/pc/pxe.c rather than net/i386/pc/pxe.c. * grub-core/commands/i386/pc/pxecmd.c: Removed. * grub-core/i386/pc/pxe.c: Moved from here ... * grub-core/net/i386/pc/pxe.c: ... here. Rewritten. * grub-core/net/net.c (grub_net_open_real): Handle old pxe syntax. * include/grub/i386/pc/pxe.h (grub_pxe_unload): Removed. EFI network support. * grub-core/Makefile.core.def (efinet): New module. * grub-core/disk/efi/efidisk.c (compare_device_paths): Moved from here... * grub-core/kern/efi/efi.c (grub_efi_compare_device_paths): ... here. All users updated. * grub-core/kern/efi/init.c (grub_efi_net_config): New variable. (grub_machine_get_bootlocation): Call grub_efi_net_config if needed. * grub-core/kern/x86_64/efi/callwrap.S (efi_wrap_7): New function. * grub-core/net/drivers/efi/efinet.c: New file. * include/grub/efi/efi.h (grub_efi_compare_device_paths): New proto. (grub_efi_net_config): New extern var. Various cleanups and bugfixes. * grub-core/disk/efi/efidisk.c (grub_efidisk_open): Fix off-by-one error. (grub_efidisk_get_device_name): Unify similar codepaths. Accept whole disk declared as partition. * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_open): Fix memory leak on failure. * grub-core/kern/dl.c (grub_dl_load_file): Fix memory leak. * grub-core/kern/mm.c (grub_debug_malloc): Don't use unsupported %zx. (grub_debug_zalloc): Likewise. (grub_debug_realloc): Likewise. (grub_debug_memalign): Likewise. * grub-core/net/arp.c (grub_net_arp_receive): IPv4 is 4-byte wide. Check that target is IPv4. * grub-core/net/drivers/ieee1275/ofnet.c (grub_ofnet_findcards): Use local-mac-address as fallback. * grub-core/net/ethernet.c (grub_net_recv_ethernet_packet): Prevent memory leak. * grub-core/net/ip.c (ipchksum): Rename to ... (grub_net_ip_chksum): ... this. All users updated. (grub_net_recv_ip_packets): Special handling for DHCP. * util/grub-mkimage.c (generate_image): Zero-out aout header. Unify prefix handling * grub-core/kern/efi/init.c (grub_efi_set_prefix): Revamped into ... (grub_machine_get_bootlocation): ... this. * grub-core/kern/emu/main.c (grub_machine_set_prefix): Revamped into ... (grub_machine_get_bootlocation): ... this. (grub_prefix): New variable. (prefix): Removed. (root_dev): New variable. (dir): Likewise. (main): Use new variables. * grub-core/kern/i386/coreboot/init.c (grub_machine_set_prefix): Revamped into ... (grub_machine_get_bootlocation): ... this. * grub-core/kern/i386/efi/init.c (grub_machine_set_prefix): Removed. * grub-core/kern/i386/pc/init.c (make_install_device): Revamped into ... (grub_machine_get_bootlocation): ... this. (grub_machine_set_prefix): Removed. * grub-core/kern/ia64/efi/init.c (grub_machine_set_prefix): Removed. * grub-core/kern/ieee1275/init.c (grub_machine_set_prefix): Revamped into ... (grub_machine_get_bootlocation): ... this. * grub-core/kern/main.c (grub_set_root_dev): Revamped into ... (grub_set_prefix_and_root): ... this. All users updated. * grub-core/kern/mips/init.c (grub_machine_set_prefix): Revamped into ... (grub_machine_get_bootlocation): ... this. * include/grub/kernel.h (grub_machine_set_prefix): Removed. (grub_machine_get_bootlocation): New proto. * include/grub/i386/pc/kernel.h (grub_pc_net_config): New var. Less intrusive and more reliable seek on network implementation. * grub-core/kern/file.c (grub_file_net_seek): Removed. (grub_file_seek): Don't call grub_file_net_seek. * grub-core/net/net.c (grub_net_fs_read): Renamed to ... (grub_net_fs_read_real): .. this. (grub_net_seek_real): Use net->offset. (grub_net_fs_read): Seek if necessary. Unify IEEE1275 netwotk config with the other platforms. * grub-core/kern/ieee1275/init.c (grub_ieee1275_net_config): New variable. (grub_machine_get_bootlocation): Support network. * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args): Support type and device parsing. (grub_ieee1275_get_device_type): New function. * grub-core/net/drivers/ieee1275/ofnet.c (grub_getbootp_real): Revamped into ... (grub_ieee1275_net_config_real): ... this. (grub_ofnet_probecards): Removed. * grub-core/Makefile.am (KERNEL_HEADER_FILES): Remove ofnet.h. * include/grub/ieee1275/ofnet.h: Removed. * include/grub/ieee1275/ieee1275.h (grub_ieee1275_net_config): NEw extern var. (grub_ieee1275_get_device_type): New function. Unify network device closing across platforms and make more robust. * grub-core/kern/ieee1275/init.c (grub_machine_fini): Don't call grub_grubnet_fini. * grub-core/net/ethernet.c (send_ethernet_packet): Open card if it isn't already. * grub-core/net/net.c (grub_net_network_level_interface_register): Update num_ifaces. (grub_net_card_unregister): Close all interfaces. (receive_packets): Don't poll if no iterfaces are registered. Open if necessary. (grub_net_fini_hw): New function. (grub_net_restore_hw): Likewise. (fini_hnd): New variable. (GRUB_MOD_INIT): Register preboot hook. (GRUB_MOD_FINI): Run and unregister preboot hook. Poll network cards when idle. * grub-core/kern/term.c (grub_net_poll_cards_idle): New variable. (grub_checkkey): Call grub_net_poll_cards_idle if it's not NULL. * grub-core/net/net.c (receive_packets): Save last poll time. (grub_net_poll_cards_idle_real): New function. (GRUB_MOD_INIT): Register grub_net_poll_cards_idle. (GRUB_MOD_FINI): Unregister grub_net_poll_cards_idle. * include/grub/kernel.h (grub_poll_cards_idle): New extern variable. Rename ofnet interfaces. * grub-core/net/drivers/ieee1275/ofnet.c (find_alias): New function. (grub_ofnet_findcards): Use ofnet_%s names. * util/grub-mknetdir.in: Support for EFI and IEEE1275. Cleanup socket opening. * grub-core/net/net.c (grub_net_fs_open): Rewritten. (grub_net_fs_close): Likewise. (grub_net_fs_read_real): Use eof member. * include/grub/net/udp.h (+grub_net_udp_open): New proto. (+grub_net_udp_close): New inline function. * include/grub/net/tftp.h: Moved to the top of ... * grub-core/net/tftp.c: ... here. * include/grub/net/ip.h: Moved mostly to the top of ... * grub-core/net/ip.c: ... here. * include/grub/net/ethernet.h: Moved mostly to the top of ... * grub-core/net/ethernet.c: ... here. * grub-core/kern/device.c (grub_device_close): Free device->net->server. * grub-core/commands/probe.c (grub_cmd_probe): Use protocol name for FS name. * include/grub/net/ip.h (ipv4_ini): Removed. (ipv4_fini): Likewise. * include/grub/net/ip.h (grub_net_recv_ip_packets): New proto. (grub_net_send_ip_packets): Likewise.
This commit is contained in:
commit
abee94edf9
53 changed files with 2820 additions and 2174 deletions
191
ChangeLog
191
ChangeLog
|
@ -1,3 +1,194 @@
|
|||
2011-07-06 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Unify sparc init with other ieee1275.
|
||||
|
||||
* grub-core/Makefile.core.def (kernel): Use kern/ieee1275/init.c
|
||||
instead of kern/sparc64/ieee1275/init.c.
|
||||
* grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options)
|
||||
[__sparc__]: Set GRUB_IEEE1275_FLAG_NO_PARTITION_0.
|
||||
* grub-core/kern/ieee1275/init.c [__sparc__]: Include
|
||||
grub/machine/kernel.h.
|
||||
(grub_ieee1275_original_stack) [__sparc__]: New variable.
|
||||
(grub_claim_heap) [__sparc__]: Use sparc version.
|
||||
(grub_machine_init): Moved args parsing to
|
||||
(grub_parse_cmdline): ...this.
|
||||
* grub-core/kern/sparc64/ieee1275/init.c: Removed.
|
||||
* include/grub/offsets.h (GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP):
|
||||
New definition.
|
||||
(GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN): Likewise.
|
||||
|
||||
Move BOOTP to separate file.
|
||||
|
||||
* grub-core/Makefile.core.def (net): Add net/bootp.c.
|
||||
* grub-core/net/net.c: Move all BOOTP functions to
|
||||
* grub-core/net/bootp.c: ... here.
|
||||
|
||||
Use frame interface on PXE.
|
||||
|
||||
* grub-core/Makefile.core.def (pxecmd): Removed.
|
||||
(pxe): Use net/drivers/i386/pc/pxe.c rather than net/i386/pc/pxe.c.
|
||||
* grub-core/commands/i386/pc/pxecmd.c: Removed.
|
||||
* grub-core/i386/pc/pxe.c: Moved from here ...
|
||||
* grub-core/net/i386/pc/pxe.c: ... here. Rewritten.
|
||||
* grub-core/net/net.c (grub_net_open_real): Handle old pxe syntax.
|
||||
* include/grub/i386/pc/pxe.h (grub_pxe_unload): Removed.
|
||||
|
||||
EFI network support.
|
||||
|
||||
* grub-core/Makefile.core.def (efinet): New module.
|
||||
* grub-core/disk/efi/efidisk.c (compare_device_paths): Moved from
|
||||
here...
|
||||
* grub-core/kern/efi/efi.c (grub_efi_compare_device_paths): ... here.
|
||||
All users updated.
|
||||
* grub-core/kern/efi/init.c (grub_efi_net_config): New variable.
|
||||
(grub_machine_get_bootlocation): Call grub_efi_net_config if needed.
|
||||
* grub-core/kern/x86_64/efi/callwrap.S (efi_wrap_7): New function.
|
||||
* grub-core/net/drivers/efi/efinet.c: New file.
|
||||
* include/grub/efi/efi.h (grub_efi_compare_device_paths): New proto.
|
||||
(grub_efi_net_config): New extern var.
|
||||
|
||||
Various cleanups and bugfixes.
|
||||
|
||||
* grub-core/disk/efi/efidisk.c (grub_efidisk_open): Fix off-by-one
|
||||
error.
|
||||
(grub_efidisk_get_device_name): Unify similar codepaths. Accept whole
|
||||
disk declared as partition.
|
||||
* grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_open): Fix memory
|
||||
leak on failure.
|
||||
* grub-core/kern/dl.c (grub_dl_load_file): Fix memory leak.
|
||||
* grub-core/kern/mm.c (grub_debug_malloc): Don't use unsupported %zx.
|
||||
(grub_debug_zalloc): Likewise.
|
||||
(grub_debug_realloc): Likewise.
|
||||
(grub_debug_memalign): Likewise.
|
||||
* grub-core/net/arp.c (grub_net_arp_receive): IPv4 is 4-byte wide.
|
||||
Check that target is IPv4.
|
||||
* grub-core/net/drivers/ieee1275/ofnet.c (grub_ofnet_findcards): Use
|
||||
local-mac-address as fallback.
|
||||
* grub-core/net/ethernet.c (grub_net_recv_ethernet_packet): Prevent
|
||||
memory leak.
|
||||
* grub-core/net/ip.c (ipchksum): Rename to ...
|
||||
(grub_net_ip_chksum): ... this. All users updated.
|
||||
(grub_net_recv_ip_packets): Special handling for DHCP.
|
||||
* util/grub-mkimage.c (generate_image): Zero-out aout header.
|
||||
|
||||
Unify prefix handling
|
||||
|
||||
* grub-core/kern/efi/init.c (grub_efi_set_prefix): Revamped into ...
|
||||
(grub_machine_get_bootlocation): ... this.
|
||||
* grub-core/kern/emu/main.c (grub_machine_set_prefix): Revamped into ...
|
||||
(grub_machine_get_bootlocation): ... this.
|
||||
(grub_prefix): New variable.
|
||||
(prefix): Removed.
|
||||
(root_dev): New variable.
|
||||
(dir): Likewise.
|
||||
(main): Use new variables.
|
||||
* grub-core/kern/i386/coreboot/init.c (grub_machine_set_prefix):
|
||||
Revamped into ...
|
||||
(grub_machine_get_bootlocation): ... this.
|
||||
* grub-core/kern/i386/efi/init.c (grub_machine_set_prefix): Removed.
|
||||
* grub-core/kern/i386/pc/init.c (make_install_device): Revamped into ...
|
||||
(grub_machine_get_bootlocation): ... this.
|
||||
(grub_machine_set_prefix): Removed.
|
||||
* grub-core/kern/ia64/efi/init.c (grub_machine_set_prefix): Removed.
|
||||
* grub-core/kern/ieee1275/init.c (grub_machine_set_prefix):
|
||||
Revamped into ...
|
||||
(grub_machine_get_bootlocation): ... this.
|
||||
* grub-core/kern/main.c (grub_set_root_dev): Revamped into ...
|
||||
(grub_set_prefix_and_root): ... this. All users updated.
|
||||
* grub-core/kern/mips/init.c (grub_machine_set_prefix):
|
||||
Revamped into ...
|
||||
(grub_machine_get_bootlocation): ... this.
|
||||
* include/grub/kernel.h (grub_machine_set_prefix): Removed.
|
||||
(grub_machine_get_bootlocation): New proto.
|
||||
* include/grub/i386/pc/kernel.h (grub_pc_net_config): New var.
|
||||
|
||||
Less intrusive and more reliable seek on network implementation.
|
||||
|
||||
* grub-core/kern/file.c (grub_file_net_seek): Removed.
|
||||
(grub_file_seek): Don't call grub_file_net_seek.
|
||||
* grub-core/net/net.c (grub_net_fs_read): Renamed to ...
|
||||
(grub_net_fs_read_real): .. this.
|
||||
(grub_net_seek_real): Use net->offset.
|
||||
(grub_net_fs_read): Seek if necessary.
|
||||
|
||||
Unify IEEE1275 netwotk config with the other platforms.
|
||||
|
||||
* grub-core/kern/ieee1275/init.c (grub_ieee1275_net_config):
|
||||
New variable.
|
||||
(grub_machine_get_bootlocation): Support network.
|
||||
* grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args):
|
||||
Support type and device parsing.
|
||||
(grub_ieee1275_get_device_type): New function.
|
||||
* grub-core/net/drivers/ieee1275/ofnet.c (grub_getbootp_real): Revamped
|
||||
into ...
|
||||
(grub_ieee1275_net_config_real): ... this.
|
||||
(grub_ofnet_probecards): Removed.
|
||||
* grub-core/Makefile.am (KERNEL_HEADER_FILES): Remove ofnet.h.
|
||||
* include/grub/ieee1275/ofnet.h: Removed.
|
||||
* include/grub/ieee1275/ieee1275.h (grub_ieee1275_net_config): NEw
|
||||
extern var.
|
||||
(grub_ieee1275_get_device_type): New function.
|
||||
|
||||
Unify network device closing across platforms and make more robust.
|
||||
|
||||
* grub-core/kern/ieee1275/init.c (grub_machine_fini): Don't call
|
||||
grub_grubnet_fini.
|
||||
* grub-core/net/ethernet.c (send_ethernet_packet): Open card if it isn't
|
||||
already.
|
||||
* grub-core/net/net.c (grub_net_network_level_interface_register):
|
||||
Update num_ifaces.
|
||||
(grub_net_card_unregister): Close all interfaces.
|
||||
(receive_packets): Don't poll if no iterfaces are registered.
|
||||
Open if necessary.
|
||||
(grub_net_fini_hw): New function.
|
||||
(grub_net_restore_hw): Likewise.
|
||||
(fini_hnd): New variable.
|
||||
(GRUB_MOD_INIT): Register preboot hook.
|
||||
(GRUB_MOD_FINI): Run and unregister preboot hook.
|
||||
|
||||
Poll network cards when idle.
|
||||
|
||||
* grub-core/kern/term.c (grub_net_poll_cards_idle): New variable.
|
||||
(grub_checkkey): Call grub_net_poll_cards_idle if it's not NULL.
|
||||
* grub-core/net/net.c (receive_packets): Save last poll time.
|
||||
(grub_net_poll_cards_idle_real): New function.
|
||||
(GRUB_MOD_INIT): Register grub_net_poll_cards_idle.
|
||||
(GRUB_MOD_FINI): Unregister grub_net_poll_cards_idle.
|
||||
* include/grub/kernel.h (grub_poll_cards_idle): New extern variable.
|
||||
|
||||
Rename ofnet interfaces.
|
||||
|
||||
* grub-core/net/drivers/ieee1275/ofnet.c (find_alias): New function.
|
||||
(grub_ofnet_findcards): Use ofnet_%s names.
|
||||
|
||||
* util/grub-mknetdir.in: Support for EFI and IEEE1275.
|
||||
|
||||
Cleanup socket opening.
|
||||
|
||||
* grub-core/net/net.c (grub_net_fs_open): Rewritten.
|
||||
(grub_net_fs_close): Likewise.
|
||||
(grub_net_fs_read_real): Use eof member.
|
||||
* include/grub/net/udp.h (+grub_net_udp_open): New proto.
|
||||
(+grub_net_udp_close): New inline function.
|
||||
|
||||
* include/grub/net/tftp.h: Moved to the top of ...
|
||||
* grub-core/net/tftp.c: ... here.
|
||||
* include/grub/net/ip.h: Moved mostly to the top of ...
|
||||
* grub-core/net/ip.c: ... here.
|
||||
* include/grub/net/ethernet.h: Moved mostly to the top of ...
|
||||
* grub-core/net/ethernet.c: ... here.
|
||||
|
||||
* grub-core/kern/device.c (grub_device_close): Free device->net->server.
|
||||
|
||||
* grub-core/commands/probe.c (grub_cmd_probe): Use protocol name for
|
||||
FS name.
|
||||
|
||||
* include/grub/net/ip.h (ipv4_ini): Removed.
|
||||
(ipv4_fini): Likewise.
|
||||
|
||||
* include/grub/net/ip.h (grub_net_recv_ip_packets): New proto.
|
||||
(grub_net_send_ip_packets): Likewise.
|
||||
|
||||
2011-07-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_init): Use new
|
||||
|
|
|
@ -115,7 +115,6 @@ endif
|
|||
|
||||
if COND_i386_ieee1275
|
||||
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/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
|
@ -188,7 +187,6 @@ endif
|
|||
|
||||
if COND_powerpc_ieee1275
|
||||
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/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
|
@ -196,7 +194,6 @@ endif
|
|||
|
||||
if COND_sparc64_ieee1275
|
||||
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/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
|
|
|
@ -102,6 +102,7 @@ kernel = {
|
|||
ieee1275 = kern/ieee1275/mmap.c;
|
||||
ieee1275 = kern/ieee1275/openfw.c;
|
||||
ieee1275 = term/ieee1275/ofconsole.c;
|
||||
ieee1275 = kern/ieee1275/init.c;
|
||||
|
||||
terminfoinkernel = term/terminfo.c;
|
||||
terminfoinkernel = term/tparm.c;
|
||||
|
@ -153,8 +154,6 @@ kernel = {
|
|||
i386_multiboot = kern/i386/multiboot_mmap.c;
|
||||
i386_multiboot = kern/i386/tsc.c;
|
||||
|
||||
i386_ieee1275 = kern/ieee1275/init.c;
|
||||
|
||||
mips = kern/mips/cache.S;
|
||||
mips = kern/mips/dl.c;
|
||||
mips = kern/mips/init.c;
|
||||
|
@ -184,14 +183,12 @@ kernel = {
|
|||
extra_dist = video/sm712_init.c;
|
||||
mips_loongson = commands/keylayouts.c;
|
||||
|
||||
powerpc_ieee1275 = kern/ieee1275/init.c;
|
||||
powerpc_ieee1275 = kern/powerpc/cache.S;
|
||||
powerpc_ieee1275 = kern/powerpc/dl.c;
|
||||
|
||||
sparc64_ieee1275 = kern/sparc64/cache.S;
|
||||
sparc64_ieee1275 = kern/sparc64/dl.c;
|
||||
sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c;
|
||||
sparc64_ieee1275 = kern/sparc64/ieee1275/init.c;
|
||||
|
||||
emu = disk/host.c;
|
||||
emu = gnulib/progname.c;
|
||||
|
@ -722,12 +719,6 @@ module = {
|
|||
common = commands/probe.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = pxecmd;
|
||||
i386_pc = commands/i386/pc/pxecmd.c;
|
||||
enable = i386_pc;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = read;
|
||||
common = commands/read.c;
|
||||
|
@ -1105,7 +1096,7 @@ module = {
|
|||
|
||||
module = {
|
||||
name = pxe;
|
||||
i386_pc = net/i386/pc/pxe.c;
|
||||
i386_pc = net/drivers/i386/pc/pxe.c;
|
||||
enable = i386_pc;
|
||||
};
|
||||
|
||||
|
@ -1588,6 +1579,7 @@ module = {
|
|||
module = {
|
||||
name = net;
|
||||
common = net/net.c;
|
||||
common = net/bootp.c;
|
||||
common = net/ip.c;
|
||||
common = net/udp.c;
|
||||
common = net/ethernet.c;
|
||||
|
@ -1602,10 +1594,16 @@ module = {
|
|||
|
||||
module = {
|
||||
name = ofnet;
|
||||
ieee1275 = net/drivers/ieee1275/ofnet.c;
|
||||
common = net/drivers/ieee1275/ofnet.c;
|
||||
enable = ieee1275;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = efinet;
|
||||
common = net/drivers/efi/efinet.c;
|
||||
enable = efi;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = emunet;
|
||||
emu = net/drivers/emu/emunet.c;
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/* pxe.c - command to control the pxe driver */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009 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/dl.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/machine/pxe.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_pxe_unload (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
if (! grub_pxe_pxenv)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment");
|
||||
|
||||
grub_pxe_unload ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(pxecmd)
|
||||
{
|
||||
cmd = grub_register_command ("pxe_unload", grub_cmd_pxe_unload,
|
||||
0,
|
||||
N_("Unload PXE environment."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(pxecmd)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
|
@ -74,7 +74,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
{
|
||||
const char *val = "none";
|
||||
if (dev->net)
|
||||
val = dev->net->name;
|
||||
val = dev->net->protocol->name;
|
||||
if (dev->disk)
|
||||
val = dev->disk->dev->name;
|
||||
if (state[0].set)
|
||||
|
|
|
@ -84,54 +84,6 @@ find_last_device_path (const grub_efi_device_path_t *dp)
|
|||
return p;
|
||||
}
|
||||
|
||||
/* Compare device paths. */
|
||||
static int
|
||||
compare_device_paths (const grub_efi_device_path_t *dp1,
|
||||
const grub_efi_device_path_t *dp2)
|
||||
{
|
||||
if (! dp1 || ! dp2)
|
||||
/* Return non-zero. */
|
||||
return 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
grub_efi_uint8_t type1, type2;
|
||||
grub_efi_uint8_t subtype1, subtype2;
|
||||
grub_efi_uint16_t len1, len2;
|
||||
int ret;
|
||||
|
||||
type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
|
||||
type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
|
||||
|
||||
if (type1 != type2)
|
||||
return (int) type2 - (int) type1;
|
||||
|
||||
subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
|
||||
subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
|
||||
|
||||
if (subtype1 != subtype2)
|
||||
return (int) subtype1 - (int) subtype2;
|
||||
|
||||
len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
|
||||
len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
|
||||
|
||||
if (len1 != len2)
|
||||
return (int) len1 - (int) len2;
|
||||
|
||||
ret = grub_memcmp (dp1, dp2, len1);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
|
||||
break;
|
||||
|
||||
dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
|
||||
dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct grub_efidisk_data *
|
||||
make_devices (void)
|
||||
{
|
||||
|
@ -214,7 +166,7 @@ find_parent_device (struct grub_efidisk_data *devices,
|
|||
if (parent == d)
|
||||
continue;
|
||||
|
||||
if (compare_device_paths (parent->device_path, dp) == 0)
|
||||
if (grub_efi_compare_device_paths (parent->device_path, dp) == 0)
|
||||
{
|
||||
/* Found. */
|
||||
if (! parent->last_device_path)
|
||||
|
@ -249,7 +201,7 @@ iterate_child_devices (struct grub_efidisk_data *devices,
|
|||
ldp->length[0] = sizeof (*ldp);
|
||||
ldp->length[1] = 0;
|
||||
|
||||
if (compare_device_paths (dp, d->device_path) == 0)
|
||||
if (grub_efi_compare_device_paths (dp, d->device_path) == 0)
|
||||
if (hook (p))
|
||||
{
|
||||
grub_free (dp);
|
||||
|
@ -273,11 +225,11 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = compare_device_paths (find_last_device_path ((*p)->device_path),
|
||||
find_last_device_path (d->device_path));
|
||||
ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path),
|
||||
find_last_device_path (d->device_path));
|
||||
if (ret == 0)
|
||||
ret = compare_device_paths ((*p)->device_path,
|
||||
d->device_path);
|
||||
ret = grub_efi_compare_device_paths ((*p)->device_path,
|
||||
d->device_path);
|
||||
if (ret == 0)
|
||||
return;
|
||||
else if (ret > 0)
|
||||
|
@ -530,7 +482,7 @@ grub_efidisk_open (const char *name, struct grub_disk *disk)
|
|||
and total sectors should be replaced with total blocks. */
|
||||
grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
|
||||
m, (unsigned long long) m->last_block, m->block_size);
|
||||
disk->total_sectors = m->last_block;
|
||||
disk->total_sectors = m->last_block + 1;
|
||||
if (m->block_size & (m->block_size - 1) || !m->block_size)
|
||||
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
|
||||
m->block_size);
|
||||
|
@ -706,7 +658,35 @@ grub_efidisk_get_device_handle (grub_disk_t disk)
|
|||
char *
|
||||
grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||
{
|
||||
grub_efi_device_path_t *dp, *ldp;
|
||||
grub_efi_device_path_t *dp, *ldp, *sdp;
|
||||
/* This is a hard disk partition. */
|
||||
grub_disk_t parent = 0;
|
||||
auto int find_parent_disk (const char *name);
|
||||
|
||||
/* Find the disk which is the parent of a given hard disk partition. */
|
||||
int find_parent_disk (const char *name)
|
||||
{
|
||||
grub_disk_t disk;
|
||||
|
||||
disk = grub_disk_open (name);
|
||||
if (! disk)
|
||||
return 1;
|
||||
|
||||
if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
|
||||
{
|
||||
struct grub_efidisk_data *d;
|
||||
|
||||
d = disk->data;
|
||||
if (grub_efi_compare_device_paths (d->device_path, sdp) == 0)
|
||||
{
|
||||
parent = disk;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
grub_disk_close (disk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dp = grub_efi_get_device_path (handle);
|
||||
if (! dp)
|
||||
|
@ -720,40 +700,12 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
|||
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
|
||||
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
|
||||
{
|
||||
/* This is a hard disk partition. */
|
||||
grub_disk_t parent = 0;
|
||||
grub_partition_t tpart = NULL;
|
||||
char *device_name;
|
||||
grub_efi_device_path_t *dup_dp, *dup_ldp;
|
||||
grub_efi_hard_drive_device_path_t hd;
|
||||
auto int find_parent_disk (const char *name);
|
||||
auto int find_partition (grub_disk_t disk, const grub_partition_t part);
|
||||
|
||||
/* Find the disk which is the parent of a given hard disk partition. */
|
||||
int find_parent_disk (const char *name)
|
||||
{
|
||||
grub_disk_t disk;
|
||||
|
||||
disk = grub_disk_open (name);
|
||||
if (! disk)
|
||||
return 1;
|
||||
|
||||
if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
|
||||
{
|
||||
struct grub_efidisk_data *d;
|
||||
|
||||
d = disk->data;
|
||||
if (compare_device_paths (d->device_path, dup_dp) == 0)
|
||||
{
|
||||
parent = disk;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
grub_disk_close (disk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find the identical partition. */
|
||||
int find_partition (grub_disk_t disk __attribute__ ((unused)),
|
||||
const grub_partition_t part)
|
||||
|
@ -780,6 +732,8 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
|||
dup_ldp->length[0] = sizeof (*dup_ldp);
|
||||
dup_ldp->length[1] = 0;
|
||||
|
||||
sdp = dup_dp;
|
||||
|
||||
grub_efidisk_iterate (find_parent_disk);
|
||||
grub_free (dup_dp);
|
||||
|
||||
|
@ -788,19 +742,27 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
|||
|
||||
/* Find a partition which matches the hard drive device path. */
|
||||
grub_memcpy (&hd, ldp, sizeof (hd));
|
||||
grub_partition_iterate (parent, find_partition);
|
||||
|
||||
if (! tpart)
|
||||
if (hd.partition_start == 0
|
||||
&& hd.partition_size == grub_disk_get_size (parent))
|
||||
{
|
||||
grub_disk_close (parent);
|
||||
return 0;
|
||||
device_name = grub_strdup (parent->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *partition_name;
|
||||
|
||||
{
|
||||
char *partition_name = grub_partition_get_name (tpart);
|
||||
device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
|
||||
grub_free (partition_name);
|
||||
}
|
||||
grub_partition_iterate (parent, find_partition);
|
||||
|
||||
if (! tpart)
|
||||
{
|
||||
grub_disk_close (parent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
partition_name = grub_partition_get_name (tpart);
|
||||
device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
|
||||
grub_free (partition_name);
|
||||
}
|
||||
grub_disk_close (parent);
|
||||
|
||||
return device_name;
|
||||
|
@ -808,36 +770,15 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
|||
else
|
||||
{
|
||||
/* This should be an entire disk. */
|
||||
auto int find_disk (const char *name);
|
||||
char *device_name = 0;
|
||||
|
||||
int find_disk (const char *name)
|
||||
{
|
||||
grub_disk_t disk;
|
||||
sdp = dp;
|
||||
|
||||
disk = grub_disk_open (name);
|
||||
if (! disk)
|
||||
return 1;
|
||||
|
||||
if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
|
||||
{
|
||||
struct grub_efidisk_data *d;
|
||||
|
||||
d = disk->data;
|
||||
if (compare_device_paths (d->device_path, dp) == 0)
|
||||
{
|
||||
device_name = grub_strdup (disk->name);
|
||||
grub_disk_close (disk);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
grub_disk_close (disk);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
grub_efidisk_iterate (find_disk);
|
||||
grub_efidisk_iterate (find_parent_disk);
|
||||
if (!parent)
|
||||
return NULL;
|
||||
device_name = grub_strdup (parent->name);
|
||||
grub_disk_close (parent);
|
||||
return device_name;
|
||||
}
|
||||
|
||||
|
|
|
@ -243,14 +243,24 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
|
|||
grub_dprintf ("disk", "Opening `%s'.\n", devpath);
|
||||
|
||||
if (grub_ieee1275_finddevice (devpath, &dev))
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties");
|
||||
{
|
||||
grub_free (devpath);
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
"can't read device properties");
|
||||
}
|
||||
|
||||
if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop),
|
||||
&actual))
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
|
||||
{
|
||||
grub_free (devpath);
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
|
||||
}
|
||||
|
||||
if (grub_strcmp (prop, "block"))
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device");
|
||||
{
|
||||
grub_free (devpath);
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device");
|
||||
}
|
||||
|
||||
/* XXX: There is no property to read the number of blocks. There
|
||||
should be a property `#blocks', but it is not there. Perhaps it
|
||||
|
|
|
@ -79,7 +79,7 @@ grub_device_close (grub_device_t device)
|
|||
|
||||
if (device->net)
|
||||
{
|
||||
grub_free (device->net->name);
|
||||
grub_free (device->net->server);
|
||||
grub_free (device->net);
|
||||
}
|
||||
|
||||
|
|
|
@ -688,11 +688,9 @@ grub_dl_load_file (const char *filename)
|
|||
grub_file_close (file);
|
||||
|
||||
mod = grub_dl_load_core (core, size);
|
||||
grub_free (core);
|
||||
if (! mod)
|
||||
{
|
||||
grub_free (core);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
mod->ref_count--;
|
||||
return mod;
|
||||
|
|
|
@ -746,3 +746,51 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
|||
dp = (grub_efi_device_path_t *) ((char *) dp + len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Compare device paths. */
|
||||
int
|
||||
grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
|
||||
const grub_efi_device_path_t *dp2)
|
||||
{
|
||||
if (! dp1 || ! dp2)
|
||||
/* Return non-zero. */
|
||||
return 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
grub_efi_uint8_t type1, type2;
|
||||
grub_efi_uint8_t subtype1, subtype2;
|
||||
grub_efi_uint16_t len1, len2;
|
||||
int ret;
|
||||
|
||||
type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
|
||||
type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
|
||||
|
||||
if (type1 != type2)
|
||||
return (int) type2 - (int) type1;
|
||||
|
||||
subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
|
||||
subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
|
||||
|
||||
if (subtype1 != subtype2)
|
||||
return (int) subtype1 - (int) subtype2;
|
||||
|
||||
len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
|
||||
len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
|
||||
|
||||
if (len1 != len2)
|
||||
return (int) len1 - (int) len2;
|
||||
|
||||
ret = grub_memcmp (dp1, dp2, len1);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
|
||||
break;
|
||||
|
||||
dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
|
||||
dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -42,84 +42,28 @@ grub_efi_init (void)
|
|||
grub_efidisk_init ();
|
||||
}
|
||||
|
||||
void (*grub_efi_net_config) (grub_efi_handle_t hnd,
|
||||
char **device,
|
||||
char **path);
|
||||
|
||||
void
|
||||
grub_efi_set_prefix (void)
|
||||
grub_machine_get_bootlocation (char **device, char **path)
|
||||
{
|
||||
grub_efi_loaded_image_t *image = NULL;
|
||||
char *device = NULL;
|
||||
char *path = NULL;
|
||||
char *p;
|
||||
|
||||
{
|
||||
char *pptr = NULL;
|
||||
if (grub_prefix[0] == '(')
|
||||
{
|
||||
pptr = grub_strrchr (grub_prefix, ')');
|
||||
if (pptr)
|
||||
{
|
||||
device = grub_strndup (grub_prefix + 1, pptr - grub_prefix - 1);
|
||||
pptr++;
|
||||
}
|
||||
}
|
||||
if (!pptr)
|
||||
pptr = grub_prefix;
|
||||
if (pptr[0])
|
||||
path = grub_strdup (pptr);
|
||||
}
|
||||
image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||
if (!image)
|
||||
return;
|
||||
*device = grub_efidisk_get_device_name (image->device_handle);
|
||||
*path = grub_efi_get_filename (image->file_path);
|
||||
if (!*device && grub_efi_net_config)
|
||||
grub_efi_net_config (image->device_handle, device, path);
|
||||
|
||||
if ((!device || device[0] == ',' || !device[0]) || !path)
|
||||
image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||
if (image)
|
||||
{
|
||||
if (!device)
|
||||
device = grub_efidisk_get_device_name (image->device_handle);
|
||||
else if (device[0] == ',' || !device[0])
|
||||
{
|
||||
/* We have a partition, but still need to fill in the drive. */
|
||||
char *image_device, *comma, *new_device;
|
||||
|
||||
image_device = grub_efidisk_get_device_name (image->device_handle);
|
||||
comma = grub_strchr (image_device, ',');
|
||||
if (comma)
|
||||
{
|
||||
char *drive = grub_strndup (image_device, comma - image_device);
|
||||
new_device = grub_xasprintf ("%s%s", drive, device);
|
||||
grub_free (drive);
|
||||
}
|
||||
else
|
||||
new_device = grub_xasprintf ("%s%s", image_device, device);
|
||||
|
||||
grub_free (image_device);
|
||||
grub_free (device);
|
||||
device = new_device;
|
||||
}
|
||||
}
|
||||
|
||||
if (image && !path)
|
||||
{
|
||||
char *p;
|
||||
|
||||
path = grub_efi_get_filename (image->file_path);
|
||||
|
||||
/* Get the directory. */
|
||||
p = grub_strrchr (path, '/');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
if (device && path)
|
||||
{
|
||||
char *prefix;
|
||||
|
||||
prefix = grub_xasprintf ("(%s)%s", device, path);
|
||||
if (prefix)
|
||||
{
|
||||
grub_env_set ("prefix", prefix);
|
||||
grub_free (prefix);
|
||||
}
|
||||
}
|
||||
|
||||
grub_free (device);
|
||||
grub_free (path);
|
||||
/* Get the directory. */
|
||||
p = grub_strrchr (*path, '/');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
static jmp_buf main_env;
|
||||
|
||||
/* Store the prefix specified by an argument. */
|
||||
static char *prefix = NULL;
|
||||
static char *root_dev = NULL, *dir = NULL;
|
||||
|
||||
int grub_no_autoload;
|
||||
|
||||
|
@ -71,11 +71,10 @@ grub_machine_init (void)
|
|||
}
|
||||
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
grub_machine_get_bootlocation (char **device, char **path)
|
||||
{
|
||||
grub_env_set ("prefix", prefix);
|
||||
free (prefix);
|
||||
prefix = 0;
|
||||
*device = root_dev;
|
||||
*path = dir;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -84,6 +83,8 @@ grub_machine_fini (void)
|
|||
grub_console_fini ();
|
||||
}
|
||||
|
||||
char grub_prefix[64] = "";
|
||||
|
||||
|
||||
|
||||
static struct option options[] =
|
||||
|
@ -132,22 +133,24 @@ void grub_emu_init (void);
|
|||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
char *root_dev = 0;
|
||||
char *dir = DEFAULT_DIRECTORY;
|
||||
char *dev_map = DEFAULT_DEVICE_MAP;
|
||||
volatile int hold = 0;
|
||||
int opt;
|
||||
|
||||
set_program_name (argv[0]);
|
||||
|
||||
dir = xstrdup (DEFAULT_DIRECTORY);
|
||||
|
||||
while ((opt = getopt_long (argc, argv, "r:d:m:vH:hV", options, 0)) != -1)
|
||||
switch (opt)
|
||||
{
|
||||
case 'r':
|
||||
root_dev = optarg;
|
||||
free (root_dev);
|
||||
root_dev = xstrdup (optarg);
|
||||
break;
|
||||
case 'd':
|
||||
dir = optarg;
|
||||
free (dir);
|
||||
dir = xstrdup (optarg);
|
||||
break;
|
||||
case 'm':
|
||||
dev_map = optarg;
|
||||
|
@ -219,9 +222,6 @@ main (int argc, char *argv[])
|
|||
dir = xstrdup (dir);
|
||||
else
|
||||
dir = grub_make_system_path_relative_to_its_root (dir);
|
||||
prefix = xmalloc (strlen (root_dev) + 2 + strlen (dir) + 1);
|
||||
sprintf (prefix, "(%s)%s", root_dev, dir);
|
||||
free (dir);
|
||||
|
||||
/* Start GRUB! */
|
||||
if (setjmp (main_env) == 0)
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <grub/fs.h>
|
||||
#include <grub/device.h>
|
||||
|
||||
grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL;
|
||||
void (*EXPORT_VAR (grub_grubnet_fini)) (void);
|
||||
|
||||
grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX];
|
||||
|
@ -183,9 +182,6 @@ grub_file_seek (grub_file_t file, grub_off_t offset)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (file->device->net && grub_file_net_seek)
|
||||
grub_file_net_seek (file, offset);
|
||||
|
||||
old = file->offset;
|
||||
file->offset = offset;
|
||||
|
||||
|
|
|
@ -107,10 +107,9 @@ grub_machine_init (void)
|
|||
}
|
||||
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
grub_machine_get_bootlocation (char **device __attribute__ ((unused)),
|
||||
char **path __attribute__ ((unused)))
|
||||
{
|
||||
/* Initialize the prefix. */
|
||||
grub_env_set ("prefix", grub_prefix);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -39,9 +39,3 @@ grub_machine_fini (void)
|
|||
{
|
||||
grub_efi_fini ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
{
|
||||
grub_efi_set_prefix ();
|
||||
}
|
||||
|
|
|
@ -45,52 +45,41 @@ struct mem_region
|
|||
static struct mem_region mem_regions[MAX_REGIONS];
|
||||
static int num_regions;
|
||||
|
||||
static char *
|
||||
make_install_device (void)
|
||||
void (*grub_pc_net_config) (char **device, char **path);
|
||||
|
||||
void
|
||||
grub_machine_get_bootlocation (char **device, char **path)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
/* No hardcoded root partition - make it from the boot drive and the
|
||||
partition number encoded at the install time. */
|
||||
if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL)
|
||||
{
|
||||
if (grub_pc_net_config)
|
||||
grub_pc_net_config (device, path);
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX: This should be enough. */
|
||||
char dev[100], *ptr = dev;
|
||||
#define DEV_SIZE 100
|
||||
*device = grub_malloc (DEV_SIZE);
|
||||
ptr = *device;
|
||||
grub_snprintf (*device, DEV_SIZE,
|
||||
"%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f',
|
||||
grub_boot_drive & 0x7f);
|
||||
ptr += grub_strlen (ptr);
|
||||
|
||||
if (grub_prefix[0] != '(')
|
||||
{
|
||||
/* No hardcoded root partition - make it from the boot drive and the
|
||||
partition number encoded at the install time. */
|
||||
if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL)
|
||||
{
|
||||
grub_strcpy (dev, "(pxe");
|
||||
ptr += sizeof ("(pxe") - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_snprintf (dev, sizeof (dev),
|
||||
"(%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f',
|
||||
grub_boot_drive & 0x7f);
|
||||
ptr += grub_strlen (ptr);
|
||||
if (grub_install_dos_part >= 0)
|
||||
grub_snprintf (ptr, DEV_SIZE - (ptr - *device),
|
||||
",%u", grub_install_dos_part + 1);
|
||||
ptr += grub_strlen (ptr);
|
||||
|
||||
if (grub_install_dos_part >= 0)
|
||||
grub_snprintf (ptr, sizeof (dev) - (ptr - dev),
|
||||
",%u", grub_install_dos_part + 1);
|
||||
ptr += grub_strlen (ptr);
|
||||
|
||||
if (grub_install_bsd_part >= 0)
|
||||
grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%u",
|
||||
grub_install_bsd_part + 1);
|
||||
ptr += grub_strlen (ptr);
|
||||
}
|
||||
|
||||
grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ")%s", grub_prefix);
|
||||
grub_strcpy (grub_prefix, dev);
|
||||
}
|
||||
else if (grub_prefix[1] == ',' || grub_prefix[1] == ')')
|
||||
{
|
||||
/* We have a prefix, but still need to fill in the boot drive. */
|
||||
grub_snprintf (dev, sizeof (dev),
|
||||
"(%cd%u%s", (grub_boot_drive & 0x80) ? 'h' : 'f',
|
||||
grub_boot_drive & 0x7f, grub_prefix + 1);
|
||||
grub_strcpy (grub_prefix, dev);
|
||||
}
|
||||
|
||||
return grub_prefix;
|
||||
if (grub_install_bsd_part >= 0)
|
||||
grub_snprintf (ptr, DEV_SIZE - (ptr - *device), ",%u",
|
||||
grub_install_bsd_part + 1);
|
||||
ptr += grub_strlen (ptr);
|
||||
*ptr = 0;
|
||||
}
|
||||
|
||||
/* Add a memory region. */
|
||||
|
@ -211,13 +200,6 @@ grub_machine_init (void)
|
|||
grub_tsc_init ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
{
|
||||
/* Initialize the prefix. */
|
||||
grub_env_set ("prefix", make_install_device ());
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_fini (void)
|
||||
{
|
||||
|
|
|
@ -40,12 +40,6 @@ grub_machine_fini (void)
|
|||
grub_efi_fini ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
{
|
||||
grub_efi_set_prefix ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_arch_sync_caches (void *address, grub_size_t len)
|
||||
{
|
||||
|
|
|
@ -60,6 +60,10 @@ grub_ieee1275_find_options (void)
|
|||
int is_olpc = 0;
|
||||
int is_qemu = 0;
|
||||
|
||||
#ifdef __sparc__
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0);
|
||||
#endif
|
||||
|
||||
grub_ieee1275_finddevice ("/", &root);
|
||||
grub_ieee1275_finddevice ("/options", &options);
|
||||
grub_ieee1275_finddevice ("/openprom", &openprom);
|
||||
|
|
|
@ -31,10 +31,12 @@
|
|||
#include <grub/ieee1275/console.h>
|
||||
#include <grub/ieee1275/ofdisk.h>
|
||||
#include <grub/ieee1275/ieee1275.h>
|
||||
#include <grub/ieee1275/ofnet.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/offsets.h>
|
||||
#include <grub/memory.h>
|
||||
#ifdef __sparc__
|
||||
#include <grub/machine/kernel.h>
|
||||
#endif
|
||||
|
||||
/* The minimal heap size we can live with. */
|
||||
#define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024)
|
||||
|
@ -49,6 +51,10 @@
|
|||
extern char _start[];
|
||||
extern char _end[];
|
||||
|
||||
#ifdef __sparc__
|
||||
grub_addr_t grub_ieee1275_original_stack;
|
||||
#endif
|
||||
|
||||
void
|
||||
grub_exit (void)
|
||||
{
|
||||
|
@ -70,52 +76,51 @@ grub_translate_ieee1275_path (char *filepath)
|
|||
}
|
||||
}
|
||||
|
||||
void (*grub_ieee1275_net_config) (const char *dev,
|
||||
char **device,
|
||||
char **path);
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
grub_machine_get_bootlocation (char **device, char **path)
|
||||
{
|
||||
char bootpath[64]; /* XXX check length */
|
||||
char *filename;
|
||||
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])
|
||||
{
|
||||
grub_env_set ("prefix", grub_prefix);
|
||||
/* Prefix is hardcoded in the core image. */
|
||||
return;
|
||||
}
|
||||
|
||||
char *type;
|
||||
|
||||
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath,
|
||||
sizeof (bootpath), 0))
|
||||
{
|
||||
/* Should never happen. */
|
||||
grub_printf ("/chosen/bootpath property missing!\n");
|
||||
grub_env_set ("prefix", "");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Transform an OF device path to a GRUB path. */
|
||||
|
||||
prefix = grub_ieee1275_encode_devname (bootpath);
|
||||
type = grub_ieee1275_get_device_type (bootpath);
|
||||
if (type && grub_strcmp (type, "network") == 0)
|
||||
{
|
||||
char *dev, *canon;
|
||||
char *ptr;
|
||||
dev = grub_ieee1275_get_aliasdevname (bootpath);
|
||||
canon = grub_ieee1275_canonicalise_devname (dev);
|
||||
ptr = canon + grub_strlen (canon) - 1;
|
||||
while (ptr > canon && (*ptr == ',' || *ptr == ':'))
|
||||
ptr--;
|
||||
ptr++;
|
||||
*ptr = 0;
|
||||
|
||||
if (grub_ieee1275_net_config)
|
||||
grub_ieee1275_net_config (canon, device, path);
|
||||
grub_free (dev);
|
||||
grub_free (canon);
|
||||
}
|
||||
else
|
||||
*device = grub_ieee1275_encode_devname (bootpath);
|
||||
grub_free (type);
|
||||
|
||||
filename = grub_ieee1275_get_filename (bootpath);
|
||||
if (filename)
|
||||
{
|
||||
char *newprefix;
|
||||
char *lastslash = grub_strrchr (filename, '\\');
|
||||
|
||||
/* Truncate at last directory. */
|
||||
|
@ -124,23 +129,22 @@ grub_machine_set_prefix (void)
|
|||
*lastslash = '\0';
|
||||
grub_translate_ieee1275_path (filename);
|
||||
|
||||
newprefix = grub_xasprintf ("%s%s", prefix, filename);
|
||||
if (newprefix)
|
||||
{
|
||||
grub_free (prefix);
|
||||
prefix = newprefix;
|
||||
}
|
||||
*path = filename;
|
||||
}
|
||||
}
|
||||
|
||||
grub_env_set ("prefix", prefix);
|
||||
|
||||
grub_free (filename);
|
||||
grub_free (prefix);
|
||||
}
|
||||
|
||||
/* Claim some available memory in the first /memory node. */
|
||||
static void grub_claim_heap (void)
|
||||
#ifdef __sparc__
|
||||
static void
|
||||
grub_claim_heap (void)
|
||||
{
|
||||
grub_mm_init_region ((void *) (grub_modules_get_end ()
|
||||
+ GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
grub_claim_heap (void)
|
||||
{
|
||||
unsigned long total = 0;
|
||||
|
||||
|
@ -208,23 +212,14 @@ static void grub_claim_heap (void)
|
|||
else
|
||||
grub_machine_mmap_iterate (heap_init);
|
||||
}
|
||||
#endif
|
||||
|
||||
static grub_uint64_t ieee1275_get_time_ms (void);
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
static void
|
||||
grub_parse_cmdline (void)
|
||||
{
|
||||
char args[256];
|
||||
grub_ssize_t actual;
|
||||
char args[256];
|
||||
|
||||
grub_ieee1275_init ();
|
||||
|
||||
grub_console_init_early ();
|
||||
grub_claim_heap ();
|
||||
grub_console_init_lately ();
|
||||
grub_ofdisk_init ();
|
||||
|
||||
/* Process commandline. */
|
||||
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
|
||||
sizeof args, &actual) == 0
|
||||
&& actual > 1)
|
||||
|
@ -257,6 +252,21 @@ grub_machine_init (void)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static grub_uint64_t ieee1275_get_time_ms (void);
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
grub_ieee1275_init ();
|
||||
|
||||
grub_console_init_early ();
|
||||
grub_claim_heap ();
|
||||
grub_console_init_lately ();
|
||||
grub_ofdisk_init ();
|
||||
|
||||
grub_parse_cmdline ();
|
||||
|
||||
grub_install_get_time_ms (ieee1275_get_time_ms);
|
||||
}
|
||||
|
@ -264,8 +274,6 @@ grub_machine_init (void)
|
|||
void
|
||||
grub_machine_fini (void)
|
||||
{
|
||||
if (grub_grubnet_fini)
|
||||
grub_grubnet_fini ();
|
||||
grub_ofdisk_fini ();
|
||||
grub_console_fini ();
|
||||
}
|
||||
|
|
|
@ -22,16 +22,14 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/mm.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
|
||||
{
|
||||
GRUB_PARSE_FILENAME,
|
||||
GRUB_PARSE_PARTITION,
|
||||
GRUB_PARSE_DEVICE
|
||||
GRUB_PARSE_DEVICE,
|
||||
GRUB_PARSE_DEVICE_TYPE
|
||||
};
|
||||
|
||||
/* Walk children of 'devpath', calling hook for each. */
|
||||
|
@ -322,14 +320,9 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
|
|||
{
|
||||
char type[64]; /* XXX check size. */
|
||||
char *device = grub_ieee1275_get_devname (path);
|
||||
char *args = grub_ieee1275_get_devargs (path);
|
||||
char *ret = 0;
|
||||
grub_ieee1275_phandle_t dev;
|
||||
|
||||
if (!args)
|
||||
/* Shouldn't happen. */
|
||||
return 0;
|
||||
|
||||
/* We need to know what type of device it is in order to parse the full
|
||||
file path properly. */
|
||||
if (grub_ieee1275_finddevice (device, &dev))
|
||||
|
@ -344,50 +337,86 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!grub_strcmp ("block", type))
|
||||
switch (ptype)
|
||||
{
|
||||
/* The syntax of the device arguments is defined in the CHRP and PReP
|
||||
IEEE1275 bindings: "[partition][,[filename]]". */
|
||||
char *comma = grub_strchr (args, ',');
|
||||
case GRUB_PARSE_DEVICE:
|
||||
ret = grub_strdup (device);
|
||||
break;
|
||||
case GRUB_PARSE_DEVICE_TYPE:
|
||||
ret = grub_strdup (type);
|
||||
break;
|
||||
case GRUB_PARSE_FILENAME:
|
||||
{
|
||||
char *comma;
|
||||
char *args;
|
||||
|
||||
if (ptype == GRUB_PARSE_FILENAME)
|
||||
{
|
||||
if (comma)
|
||||
{
|
||||
char *filepath = comma + 1;
|
||||
if (grub_strcmp ("block", type) != 0)
|
||||
goto unknown;
|
||||
|
||||
/* Make sure filepath has leading backslash. */
|
||||
if (filepath[0] != '\\')
|
||||
ret = grub_xasprintf ("\\%s", filepath);
|
||||
else
|
||||
ret = grub_strdup (filepath);
|
||||
args = grub_ieee1275_get_devargs (path);
|
||||
if (!args)
|
||||
/* Shouldn't happen. */
|
||||
return 0;
|
||||
|
||||
/* The syntax of the device arguments is defined in the CHRP and PReP
|
||||
IEEE1275 bindings: "[partition][,[filename]]". */
|
||||
comma = grub_strchr (args, ',');
|
||||
|
||||
if (comma)
|
||||
{
|
||||
char *filepath = comma + 1;
|
||||
|
||||
/* Make sure filepath has leading backslash. */
|
||||
if (filepath[0] != '\\')
|
||||
ret = grub_xasprintf ("\\%s", filepath);
|
||||
else
|
||||
ret = grub_strdup (filepath);
|
||||
}
|
||||
grub_free (args);
|
||||
}
|
||||
else if (ptype == GRUB_PARSE_PARTITION)
|
||||
{
|
||||
if (!comma)
|
||||
ret = grub_strdup (args);
|
||||
else
|
||||
ret = grub_strndup (args, (grub_size_t)(comma - args));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_PARSE_PARTITION:
|
||||
{
|
||||
char *comma;
|
||||
char *args;
|
||||
|
||||
else if (!grub_strcmp ("network", type))
|
||||
{
|
||||
if (ptype == GRUB_PARSE_DEVICE)
|
||||
ret = grub_strdup(device);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (grub_strcmp ("block", type) != 0)
|
||||
goto unknown;
|
||||
|
||||
args = grub_ieee1275_get_devargs (path);
|
||||
if (!args)
|
||||
/* Shouldn't happen. */
|
||||
return 0;
|
||||
|
||||
comma = grub_strchr (args, ',');
|
||||
if (!comma)
|
||||
ret = grub_strdup (args);
|
||||
else
|
||||
ret = grub_strndup (args, (grub_size_t)(comma - args));
|
||||
/* Consistently provide numbered partitions to GRUB.
|
||||
OpenBOOT traditionally uses alphabetical partition
|
||||
specifiers. */
|
||||
if (ret[0] >= 'a' && ret[0] <= 'z')
|
||||
ret[0] = '1' + (ret[0] - 'a');
|
||||
grub_free (args);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
unknown:
|
||||
grub_printf ("Unsupported type %s for device %s\n", type, device);
|
||||
}
|
||||
|
||||
fail:
|
||||
grub_free (device);
|
||||
grub_free (args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
grub_ieee1275_get_device_type (const char *path)
|
||||
{
|
||||
return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE_TYPE);
|
||||
}
|
||||
|
||||
char *
|
||||
grub_ieee1275_get_aliasdevname (const char *path)
|
||||
{
|
||||
|
|
|
@ -129,27 +129,74 @@ grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
|
|||
return grub_strdup (val);
|
||||
}
|
||||
|
||||
/* Set the root device according to the dl prefix. */
|
||||
static void
|
||||
grub_set_root_dev (void)
|
||||
grub_set_prefix_and_root (void)
|
||||
{
|
||||
const char *prefix;
|
||||
char *device = NULL;
|
||||
char *path = NULL;
|
||||
char *fwdevice = NULL;
|
||||
char *fwpath = NULL;
|
||||
|
||||
grub_register_variable_hook ("root", 0, grub_env_write_root);
|
||||
|
||||
prefix = grub_env_get ("prefix");
|
||||
{
|
||||
char *pptr = NULL;
|
||||
if (grub_prefix[0] == '(')
|
||||
{
|
||||
pptr = grub_strrchr (grub_prefix, ')');
|
||||
if (pptr)
|
||||
{
|
||||
device = grub_strndup (grub_prefix + 1, pptr - grub_prefix - 1);
|
||||
pptr++;
|
||||
}
|
||||
}
|
||||
if (!pptr)
|
||||
pptr = grub_prefix;
|
||||
if (pptr[0])
|
||||
path = grub_strdup (pptr);
|
||||
}
|
||||
if ((!device || device[0] == ',' || !device[0]) || !path)
|
||||
grub_machine_get_bootlocation (&fwdevice, &fwpath);
|
||||
|
||||
if (prefix)
|
||||
if (!device && fwdevice)
|
||||
device = fwdevice;
|
||||
else if (fwdevice && (device[0] == ',' || !device[0]))
|
||||
{
|
||||
char *dev;
|
||||
/* We have a partition, but still need to fill in the drive. */
|
||||
char *comma, *new_device;
|
||||
|
||||
dev = grub_file_get_device_name (prefix);
|
||||
if (dev)
|
||||
comma = grub_strchr (fwdevice, ',');
|
||||
if (comma)
|
||||
{
|
||||
grub_env_set ("root", dev);
|
||||
grub_free (dev);
|
||||
char *drive = grub_strndup (fwdevice, comma - fwdevice);
|
||||
new_device = grub_xasprintf ("%s%s", drive, device);
|
||||
grub_free (drive);
|
||||
}
|
||||
else
|
||||
new_device = grub_xasprintf ("%s%s", fwdevice, device);
|
||||
|
||||
grub_free (fwdevice);
|
||||
grub_free (device);
|
||||
device = new_device;
|
||||
}
|
||||
if (fwpath && !path)
|
||||
path = fwpath;
|
||||
if (device)
|
||||
{
|
||||
char *prefix;
|
||||
|
||||
prefix = grub_xasprintf ("(%s)%s", device, path ? : "");
|
||||
if (prefix)
|
||||
{
|
||||
grub_env_set ("prefix", prefix);
|
||||
grub_free (prefix);
|
||||
}
|
||||
grub_env_set ("root", device);
|
||||
}
|
||||
|
||||
grub_free (device);
|
||||
grub_free (path);
|
||||
grub_print_error ();
|
||||
}
|
||||
|
||||
/* Load the normal mode module and execute the normal mode if possible. */
|
||||
|
@ -187,8 +234,7 @@ grub_main (void)
|
|||
|
||||
/* It is better to set the root device as soon as possible,
|
||||
for convenience. */
|
||||
grub_machine_set_prefix ();
|
||||
grub_set_root_dev ();
|
||||
grub_set_prefix_and_root ();
|
||||
grub_env_export ("root");
|
||||
grub_env_export ("prefix");
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ grub_get_rtc (void)
|
|||
}
|
||||
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
grub_machine_get_bootlocation (char **device __attribute__ ((unused)),
|
||||
char **path __attribute__ ((unused)))
|
||||
{
|
||||
grub_env_set ("prefix", grub_prefix);
|
||||
}
|
||||
|
|
|
@ -515,7 +515,7 @@ grub_debug_malloc (const char *file, int line, grub_size_t size)
|
|||
void *ptr;
|
||||
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%s:%d: malloc (0x%zx) = ", file, line, size);
|
||||
grub_printf ("%s:%d: malloc (0x%" PRIxGRUB_SIZE ") = ", file, line, size);
|
||||
ptr = grub_malloc (size);
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%p\n", ptr);
|
||||
|
@ -528,7 +528,7 @@ grub_debug_zalloc (const char *file, int line, grub_size_t size)
|
|||
void *ptr;
|
||||
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%s:%d: zalloc (0x%zx) = ", file, line, size);
|
||||
grub_printf ("%s:%d: zalloc (0x%" PRIxGRUB_SIZE ") = ", file, line, size);
|
||||
ptr = grub_zalloc (size);
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%p\n", ptr);
|
||||
|
@ -547,7 +547,7 @@ void *
|
|||
grub_debug_realloc (const char *file, int line, void *ptr, grub_size_t size)
|
||||
{
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%s:%d: realloc (%p, 0x%zx) = ", file, line, ptr, size);
|
||||
grub_printf ("%s:%d: realloc (%p, 0x%" PRIxGRUB_SIZE ") = ", file, line, ptr, size);
|
||||
ptr = grub_realloc (ptr, size);
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%p\n", ptr);
|
||||
|
@ -561,8 +561,8 @@ grub_debug_memalign (const char *file, int line, grub_size_t align,
|
|||
void *ptr;
|
||||
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%s:%d: memalign (0x%zx, 0x%zx) = ",
|
||||
file, line, align, size);
|
||||
grub_printf ("%s:%d: memalign (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE
|
||||
") = ", file, line, align, size);
|
||||
ptr = grub_memalign (align, size);
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%p\n", ptr);
|
||||
|
|
|
@ -1,174 +0,0 @@
|
|||
/* init.c -- Initialize GRUB on SPARC64. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/kernel.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/machine/boot.h>
|
||||
#include <grub/ieee1275/console.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/machine/time.h>
|
||||
#include <grub/ieee1275/ofdisk.h>
|
||||
#include <grub/ieee1275/ieee1275.h>
|
||||
|
||||
grub_addr_t grub_ieee1275_original_stack;
|
||||
|
||||
void
|
||||
grub_exit (void)
|
||||
{
|
||||
grub_ieee1275_exit ();
|
||||
}
|
||||
|
||||
static grub_uint64_t
|
||||
ieee1275_get_time_ms (void)
|
||||
{
|
||||
grub_uint32_t msecs = 0;
|
||||
|
||||
grub_ieee1275_milliseconds (&msecs);
|
||||
|
||||
return msecs;
|
||||
}
|
||||
|
||||
grub_uint32_t
|
||||
grub_get_rtc (void)
|
||||
{
|
||||
return ieee1275_get_time_ms ();
|
||||
}
|
||||
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
extern char _end[];
|
||||
return (grub_addr_t) _end;
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
{
|
||||
if (grub_prefix[0] != '(')
|
||||
{
|
||||
char bootpath[IEEE1275_MAX_PATH_LEN];
|
||||
char *prefix, *path, *colon;
|
||||
grub_ssize_t actual;
|
||||
|
||||
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath",
|
||||
&bootpath, sizeof (bootpath), &actual))
|
||||
{
|
||||
/* Should never happen. */
|
||||
grub_printf ("/chosen/bootpath property missing!\n");
|
||||
grub_env_set ("prefix", "");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Transform an OF device path to a GRUB path. */
|
||||
colon = grub_strchr (bootpath, ':');
|
||||
if (colon)
|
||||
{
|
||||
char *part = colon + 1;
|
||||
|
||||
/* Consistently provide numbered partitions to GRUB.
|
||||
OpenBOOT traditionally uses alphabetical partition
|
||||
specifiers. */
|
||||
if (part[0] >= 'a' && part[0] <= 'z')
|
||||
part[0] = '1' + (part[0] - 'a');
|
||||
}
|
||||
prefix = grub_ieee1275_encode_devname (bootpath);
|
||||
|
||||
path = grub_xasprintf("%s%s", prefix, grub_prefix);
|
||||
|
||||
grub_strcpy (grub_prefix, path);
|
||||
|
||||
grub_free (path);
|
||||
grub_free (prefix);
|
||||
}
|
||||
|
||||
grub_env_set ("prefix", grub_prefix);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_heap_init (void)
|
||||
{
|
||||
grub_mm_init_region ((void *) (grub_modules_get_end ()
|
||||
+ GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_parse_cmdline (void)
|
||||
{
|
||||
grub_ssize_t actual;
|
||||
char args[256];
|
||||
|
||||
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
|
||||
sizeof args, &actual) == 0
|
||||
&& actual > 1)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (i < actual)
|
||||
{
|
||||
char *command = &args[i];
|
||||
char *end;
|
||||
char *val;
|
||||
|
||||
end = grub_strchr (command, ';');
|
||||
if (end == 0)
|
||||
i = actual; /* No more commands after this one. */
|
||||
else
|
||||
{
|
||||
*end = '\0';
|
||||
i += end - command + 1;
|
||||
while (grub_isspace(args[i]))
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Process command. */
|
||||
val = grub_strchr (command, '=');
|
||||
if (val)
|
||||
{
|
||||
*val = '\0';
|
||||
grub_env_set (command, val + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
grub_ieee1275_init ();
|
||||
grub_console_init_early ();
|
||||
grub_heap_init ();
|
||||
grub_console_init_lately ();
|
||||
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0);
|
||||
grub_ofdisk_init ();
|
||||
|
||||
grub_parse_cmdline ();
|
||||
grub_install_get_time_ms (ieee1275_get_time_ms);
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_fini (void)
|
||||
{
|
||||
grub_ofdisk_fini ();
|
||||
grub_console_fini ();
|
||||
}
|
|
@ -29,6 +29,7 @@ struct grub_term_output *grub_term_outputs;
|
|||
struct grub_term_input *grub_term_inputs;
|
||||
|
||||
void (*grub_term_poll_usb) (void) = NULL;
|
||||
void (*grub_net_poll_cards_idle) (void) = NULL;
|
||||
|
||||
/* Put a Unicode character. */
|
||||
static void
|
||||
|
@ -91,6 +92,9 @@ grub_checkkey (void)
|
|||
if (grub_term_poll_usb)
|
||||
grub_term_poll_usb ();
|
||||
|
||||
if (grub_net_poll_cards_idle)
|
||||
grub_net_poll_cards_idle ();
|
||||
|
||||
FOR_ACTIVE_TERM_INPUTS(term)
|
||||
{
|
||||
pending_key = term->getkey (term);
|
||||
|
|
|
@ -95,6 +95,20 @@ FUNCTION(efi_wrap_6)
|
|||
addq $64, %rsp
|
||||
ret
|
||||
|
||||
FUNCTION(efi_wrap_7)
|
||||
subq $96, %rsp
|
||||
mov 96+16(%rsp), %rax
|
||||
mov %rax, 48(%rsp)
|
||||
mov 96+8(%rsp), %rax
|
||||
mov %rax, 40(%rsp)
|
||||
mov %r9, 32(%rsp)
|
||||
mov %r8, %r9
|
||||
mov %rcx, %r8
|
||||
mov %rsi, %rcx
|
||||
call *%rdi
|
||||
addq $96, %rsp
|
||||
ret
|
||||
|
||||
FUNCTION(efi_wrap_10)
|
||||
subq $96, %rsp
|
||||
mov 96+40(%rsp), %rax
|
||||
|
|
|
@ -144,7 +144,8 @@ grub_net_arp_receive (struct grub_net_buff *nb)
|
|||
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||
{
|
||||
/* Am I the protocol address target? */
|
||||
if (grub_memcmp (target_protocol_address, &inf->address.ipv4, 6) == 0
|
||||
if (inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
|
||||
&& grub_memcmp (target_protocol_address, &inf->address.ipv4, 4) == 0
|
||||
&& grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST)
|
||||
{
|
||||
grub_net_link_level_address_t aux;
|
||||
|
|
539
grub-core/net/bootp.c
Normal file
539
grub-core/net/bootp.c
Normal file
|
@ -0,0 +1,539 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010,2011 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/net.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/net/ip.h>
|
||||
#include <grub/net/netbuff.h>
|
||||
#include <grub/net/udp.h>
|
||||
#include <grub/datetime.h>
|
||||
|
||||
static char *
|
||||
grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
|
||||
const char *val __attribute__ ((unused)))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
set_env_limn_ro (const char *intername, const char *suffix,
|
||||
char *value, grub_size_t len)
|
||||
{
|
||||
char c;
|
||||
char varname[sizeof ("net_") + grub_strlen (intername) + sizeof ("_")
|
||||
+ grub_strlen (suffix)];
|
||||
grub_snprintf (varname, sizeof (varname), "net_%s_%s", intername, suffix);
|
||||
c = value[len];
|
||||
value[len] = 0;
|
||||
grub_env_set (varname, value);
|
||||
value[len] = c;
|
||||
grub_register_variable_hook (varname, 0, grub_env_write_readonly);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_dhcp_vendor (const char *name, void *vend, int limit)
|
||||
{
|
||||
grub_uint8_t *ptr, *ptr0;
|
||||
|
||||
ptr = ptr0 = vend;
|
||||
|
||||
if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0
|
||||
|| ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1
|
||||
|| ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2
|
||||
|| ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3)
|
||||
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 (name, "hostname", (char *) ptr, taglength);
|
||||
break;
|
||||
|
||||
case 15:
|
||||
set_env_limn_ro (name, "domain", (char *) ptr, taglength);
|
||||
break;
|
||||
|
||||
case 17:
|
||||
set_env_limn_ro (name, "rootpath", (char *) ptr, taglength);
|
||||
break;
|
||||
|
||||
case 18:
|
||||
set_env_limn_ro (name, "extensionspath", (char *) ptr, taglength);
|
||||
break;
|
||||
|
||||
/* If you need any other options please contact GRUB
|
||||
developpement team. */
|
||||
}
|
||||
|
||||
ptr += taglength;
|
||||
}
|
||||
}
|
||||
|
||||
#define OFFSET_OF(x, y) ((grub_uint8_t *)((y)->x) - (grub_uint8_t *)(y))
|
||||
|
||||
struct grub_net_network_level_interface *
|
||||
grub_net_configure_by_dhcp_ack (const char *name,
|
||||
struct grub_net_card *card,
|
||||
grub_net_interface_flags_t flags,
|
||||
const struct grub_net_bootp_packet *bp,
|
||||
grub_size_t size,
|
||||
int is_def, char **device, char **path)
|
||||
{
|
||||
grub_net_network_level_address_t addr;
|
||||
grub_net_link_level_address_t hwaddr;
|
||||
struct grub_net_network_level_interface *inter;
|
||||
|
||||
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||
addr.ipv4 = bp->your_ip;
|
||||
|
||||
if (device)
|
||||
*device = 0;
|
||||
if (path)
|
||||
*path = 0;
|
||||
|
||||
grub_memcpy (hwaddr.mac, bp->mac_addr,
|
||||
bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len
|
||||
: sizeof (hwaddr.mac));
|
||||
hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||
|
||||
inter = grub_net_add_addr (name, card, addr, hwaddr, flags);
|
||||
{
|
||||
grub_net_network_level_netaddress_t target;
|
||||
grub_net_network_level_address_t gw;
|
||||
char rname[grub_strlen (name) + sizeof ("_gw")];
|
||||
|
||||
target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||
target.ipv4.base = bp->server_ip;
|
||||
target.ipv4.masksize = 32;
|
||||
gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||
gw.ipv4 = bp->gateway_ip;
|
||||
grub_snprintf (rname, sizeof (rname), "%s_gw", name);
|
||||
grub_net_add_route_gw (rname, target, gw);
|
||||
}
|
||||
{
|
||||
grub_net_network_level_netaddress_t target;
|
||||
target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||
target.ipv4.base = bp->gateway_ip;
|
||||
target.ipv4.masksize = 32;
|
||||
grub_net_add_route (name, target, inter);
|
||||
}
|
||||
|
||||
if (size > OFFSET_OF (boot_file, bp))
|
||||
set_env_limn_ro (name, "boot_file", (char *) bp->boot_file,
|
||||
sizeof (bp->boot_file));
|
||||
if (is_def)
|
||||
grub_net_default_server = 0;
|
||||
if (size > OFFSET_OF (server_name, bp)
|
||||
&& bp->server_name[0])
|
||||
{
|
||||
set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name,
|
||||
sizeof (bp->server_name));
|
||||
if (is_def && !grub_net_default_server)
|
||||
{
|
||||
grub_net_default_server = grub_strdup (bp->server_name);
|
||||
grub_print_error ();
|
||||
}
|
||||
if (device && !*device)
|
||||
{
|
||||
*device = grub_xasprintf ("tftp,%s", bp->server_name);
|
||||
grub_print_error ();
|
||||
}
|
||||
}
|
||||
if (is_def && !grub_net_default_server)
|
||||
{
|
||||
grub_net_default_server = grub_xasprintf ("%d.%d.%d.%d",
|
||||
((grub_uint8_t *) &bp->server_ip)[0],
|
||||
((grub_uint8_t *) &bp->server_ip)[1],
|
||||
((grub_uint8_t *) &bp->server_ip)[2],
|
||||
((grub_uint8_t *) &bp->server_ip)[3]);
|
||||
grub_print_error ();
|
||||
}
|
||||
|
||||
if (device && !*device)
|
||||
{
|
||||
*device = grub_xasprintf ("tftp,%d.%d.%d.%d",
|
||||
((grub_uint8_t *) &bp->server_ip)[0],
|
||||
((grub_uint8_t *) &bp->server_ip)[1],
|
||||
((grub_uint8_t *) &bp->server_ip)[2],
|
||||
((grub_uint8_t *) &bp->server_ip)[3]);
|
||||
grub_print_error ();
|
||||
}
|
||||
if (size > OFFSET_OF (boot_file, bp) && path)
|
||||
{
|
||||
*path = grub_strndup (bp->boot_file, sizeof (bp->boot_file));
|
||||
grub_print_error ();
|
||||
if (*path)
|
||||
{
|
||||
char *slash;
|
||||
slash = grub_strrchr (*path, '/');
|
||||
if (slash)
|
||||
*slash = 0;
|
||||
else
|
||||
**path = 0;
|
||||
}
|
||||
}
|
||||
if (size > OFFSET_OF (vendor, bp))
|
||||
parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp));
|
||||
|
||||
inter->dhcp_ack = grub_malloc (size);
|
||||
if (inter->dhcp_ack)
|
||||
{
|
||||
grub_memcpy (inter->dhcp_ack, bp, size);
|
||||
inter->dhcp_acklen = size;
|
||||
}
|
||||
else
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
return inter;
|
||||
}
|
||||
|
||||
void
|
||||
grub_net_process_dhcp (struct grub_net_buff *nb,
|
||||
struct grub_net_card *card)
|
||||
{
|
||||
char *name;
|
||||
struct grub_net_network_level_interface *inf;
|
||||
|
||||
name = grub_xasprintf ("%s:dhcp", card->name);
|
||||
if (!name)
|
||||
{
|
||||
grub_print_error ();
|
||||
return;
|
||||
}
|
||||
grub_net_configure_by_dhcp_ack (name, card,
|
||||
0, (const struct grub_net_bootp_packet *) nb->data,
|
||||
(nb->tail - nb->data), 0, 0, 0);
|
||||
grub_free (name);
|
||||
if (grub_errno)
|
||||
grub_print_error ();
|
||||
else
|
||||
{
|
||||
FOR_NET_NETWORK_LEVEL_INTERFACES(inf)
|
||||
if (grub_memcmp (inf->name, card->name, grub_strlen (card->name)) == 0
|
||||
&& grub_memcmp (inf->name + grub_strlen (card->name),
|
||||
":dhcp_tmp", sizeof (":dhcp_tmp") - 1) == 0)
|
||||
{
|
||||
grub_net_network_level_interface_unregister (inf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char
|
||||
hexdigit (grub_uint8_t val)
|
||||
{
|
||||
if (val < 10)
|
||||
return val + '0';
|
||||
return val + 'a' - 10;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_net_network_level_interface *inter;
|
||||
int num;
|
||||
grub_uint8_t *ptr;
|
||||
grub_uint8_t taglength;
|
||||
|
||||
if (argc < 4)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "4 arguments expected");
|
||||
|
||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
|
||||
if (grub_strcmp (inter->name, args[1]) == 0)
|
||||
break;
|
||||
|
||||
if (!inter)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("unrecognised interface %s"), args[1]);
|
||||
|
||||
if (!inter->dhcp_ack)
|
||||
return grub_error (GRUB_ERR_IO, N_("no DHCP info found"));
|
||||
|
||||
if (inter->dhcp_acklen <= OFFSET_OF (vendor, inter->dhcp_ack))
|
||||
return grub_error (GRUB_ERR_IO, N_("no DHCP options found"));
|
||||
|
||||
num = grub_strtoul (args[2], 0, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
|
||||
ptr = inter->dhcp_ack->vendor;
|
||||
|
||||
if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0
|
||||
|| ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1
|
||||
|| ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2
|
||||
|| ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3)
|
||||
return grub_error (GRUB_ERR_IO, N_("no DHCP options found"));
|
||||
ptr = ptr + sizeof (grub_uint32_t);
|
||||
while (1)
|
||||
{
|
||||
grub_uint8_t tagtype;
|
||||
|
||||
if (ptr >= ((grub_uint8_t *) inter->dhcp_ack) + inter->dhcp_acklen)
|
||||
return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num);
|
||||
|
||||
tagtype = *ptr++;
|
||||
|
||||
/* Pad tag. */
|
||||
if (tagtype == 0)
|
||||
continue;
|
||||
|
||||
/* End tag. */
|
||||
if (tagtype == 0xff)
|
||||
return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num);
|
||||
|
||||
taglength = *ptr++;
|
||||
|
||||
if (tagtype == num)
|
||||
break;
|
||||
ptr += taglength;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[3], "string") == 0)
|
||||
{
|
||||
char *val = grub_malloc (taglength + 1);
|
||||
if (!val)
|
||||
return grub_errno;
|
||||
grub_memcpy (val, ptr, taglength);
|
||||
val[taglength] = 0;
|
||||
if (args[0][0] == '-' && args[0][1] == 0)
|
||||
grub_printf ("%s\n", val);
|
||||
else
|
||||
return grub_env_set (args[0], val);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[3], "number") == 0)
|
||||
{
|
||||
grub_uint64_t val = 0;
|
||||
int i;
|
||||
for (i = 0; i < taglength; i++)
|
||||
val = (val << 8) | ptr[i];
|
||||
if (args[0][0] == '-' && args[0][1] == 0)
|
||||
grub_printf ("%llu\n", (unsigned long long) val);
|
||||
else
|
||||
{
|
||||
char valn[64];
|
||||
grub_printf (valn, sizeof (valn), "%lld\n", (unsigned long long) val);
|
||||
return grub_env_set (args[0], valn);
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[3], "hex") == 0)
|
||||
{
|
||||
char *val = grub_malloc (2 * taglength + 1);
|
||||
int i;
|
||||
if (!val)
|
||||
return grub_errno;
|
||||
for (i = 0; i < taglength; i++)
|
||||
{
|
||||
val[2 * i] = hexdigit (ptr[i] >> 4);
|
||||
val[2 * i + 1] = hexdigit (ptr[i] & 0xf);
|
||||
}
|
||||
val[2 * taglength] = 0;
|
||||
if (args[0][0] == '-' && args[0][1] == 0)
|
||||
grub_printf ("%s\n", val);
|
||||
else
|
||||
return grub_env_set (args[0], val);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"unrecognised format specification %s", args[3]);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_net_card *card;
|
||||
struct grub_net_network_level_interface *ifaces;
|
||||
grub_size_t ncards = 0;
|
||||
unsigned j = 0;
|
||||
int interval;
|
||||
grub_err_t err;
|
||||
|
||||
FOR_NET_CARDS (card)
|
||||
{
|
||||
if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
|
||||
continue;
|
||||
ncards++;
|
||||
}
|
||||
|
||||
ifaces = grub_zalloc (ncards * sizeof (ifaces[0]));
|
||||
if (!ifaces)
|
||||
return grub_errno;
|
||||
|
||||
j = 0;
|
||||
FOR_NET_CARDS (card)
|
||||
{
|
||||
if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
|
||||
continue;
|
||||
ifaces[j].card = card;
|
||||
ifaces[j].next = &ifaces[j+1];
|
||||
if (j)
|
||||
ifaces[j].prev = &ifaces[j-1].next;
|
||||
ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name);
|
||||
card->num_ifaces++;
|
||||
if (!ifaces[j].name)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < j; i++)
|
||||
grub_free (ifaces[i].name);
|
||||
grub_free (ifaces);
|
||||
return grub_errno;
|
||||
}
|
||||
ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV;
|
||||
grub_memcpy (&ifaces[j].hwaddress, &card->default_address,
|
||||
sizeof (ifaces[j].hwaddress));
|
||||
j++;
|
||||
}
|
||||
ifaces[ncards - 1].next = grub_net_network_level_interfaces;
|
||||
if (grub_net_network_level_interfaces)
|
||||
grub_net_network_level_interfaces->prev = & ifaces[ncards - 1].next;
|
||||
grub_net_network_level_interfaces = &ifaces[0];
|
||||
ifaces[0].prev = &grub_net_network_level_interfaces;
|
||||
for (interval = 200; interval < 10000; interval *= 2)
|
||||
{
|
||||
int done = 0;
|
||||
for (j = 0; j < ncards; j++)
|
||||
{
|
||||
struct grub_net_bootp_packet *pack;
|
||||
struct grub_datetime date;
|
||||
grub_int32_t t;
|
||||
struct grub_net_buff *nb;
|
||||
struct udphdr *udph;
|
||||
grub_net_network_level_address_t target;
|
||||
|
||||
if (!ifaces[j].prev)
|
||||
continue;
|
||||
nb = grub_netbuff_alloc (sizeof (*pack));
|
||||
if (!nb)
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
return grub_errno;
|
||||
}
|
||||
err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128);
|
||||
if (err)
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
return err;
|
||||
}
|
||||
err = grub_netbuff_push (nb, sizeof (*pack) + 64);
|
||||
if (err)
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
return err;
|
||||
}
|
||||
pack = (void *) nb->data;
|
||||
done = 1;
|
||||
grub_memset (pack, 0, sizeof (*pack) + 64);
|
||||
pack->opcode = 1;
|
||||
pack->hw_type = 1;
|
||||
pack->hw_len = 6;
|
||||
err = grub_get_datetime (&date);
|
||||
if (err || !grub_datetime2unixtime (&date, &t))
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
t = 0;
|
||||
}
|
||||
pack->ident = grub_cpu_to_be32 (t);
|
||||
pack->seconds = 0;//grub_cpu_to_be16 (t);
|
||||
|
||||
grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6);
|
||||
|
||||
grub_netbuff_push (nb, sizeof (*udph));
|
||||
|
||||
udph = (struct udphdr *) nb->data;
|
||||
udph->src = grub_cpu_to_be16 (68);
|
||||
udph->dst = grub_cpu_to_be16 (67);
|
||||
udph->chksum = 0;
|
||||
udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
|
||||
|
||||
target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||
target.ipv4 = 0xffffffff;
|
||||
|
||||
err = grub_net_send_ip_packet (&ifaces[j], &target, nb);
|
||||
grub_netbuff_free (nb);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (!done)
|
||||
break;
|
||||
grub_net_poll_cards (interval);
|
||||
}
|
||||
|
||||
err = GRUB_ERR_NONE;
|
||||
for (j = 0; j < ncards; j++)
|
||||
{
|
||||
grub_free (ifaces[j].name);
|
||||
if (!ifaces[j].prev)
|
||||
continue;
|
||||
grub_error_push ();
|
||||
grub_net_network_level_interface_unregister (&ifaces[j]);
|
||||
err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s",
|
||||
ifaces[j].card->name);
|
||||
}
|
||||
|
||||
grub_free (ifaces);
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_dhcp, cmd_getdhcp, cmd_bootp;
|
||||
|
||||
void
|
||||
grub_bootp_init (void)
|
||||
{
|
||||
cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp,
|
||||
"[CARD]",
|
||||
N_("perform a bootp autoconfiguration"));
|
||||
cmd_dhcp = grub_register_command ("net_dhcp", grub_cmd_bootp,
|
||||
"[CARD]",
|
||||
N_("perform a bootp autoconfiguration"));
|
||||
cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt,
|
||||
N_("VAR INTERFACE NUMBER DESCRIPTION"),
|
||||
N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value."));
|
||||
}
|
||||
|
||||
void
|
||||
grub_bootp_fini (void)
|
||||
{
|
||||
grub_unregister_command (cmd_getdhcp);
|
||||
grub_unregister_command (cmd_dhcp);
|
||||
grub_unregister_command (cmd_bootp);
|
||||
}
|
201
grub-core/net/drivers/efi/efinet.c
Normal file
201
grub-core/net/drivers/efi/efinet.c
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010,2011 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/net/netbuff.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/efi/api.h>
|
||||
#include <grub/efi/efi.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/* GUID. */
|
||||
static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID;
|
||||
static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID;
|
||||
|
||||
static grub_err_t
|
||||
send_card_buffer (const struct grub_net_card *dev,
|
||||
struct grub_net_buff *pack)
|
||||
{
|
||||
grub_efi_status_t st;
|
||||
grub_efi_simple_network_t *net = dev->efi_net;
|
||||
st = efi_call_7 (net->transmit, net, 0, (pack->tail - pack->data),
|
||||
pack->data, NULL, NULL, NULL);
|
||||
if (st != GRUB_EFI_SUCCESS)
|
||||
return grub_error (GRUB_ERR_IO, "Couldn't send network packet.");
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_ssize_t
|
||||
get_card_packet (const struct grub_net_card *dev,
|
||||
struct grub_net_buff *nb)
|
||||
{
|
||||
grub_efi_simple_network_t *net = dev->efi_net;
|
||||
grub_err_t err;
|
||||
grub_efi_status_t st;
|
||||
grub_efi_uintn_t bufsize = 1500;
|
||||
|
||||
err = grub_netbuff_clear (nb);
|
||||
if (err)
|
||||
return -1;
|
||||
|
||||
err = grub_netbuff_put (nb, 1500);
|
||||
if (err)
|
||||
return -1;
|
||||
|
||||
st = efi_call_7 (net->receive, net, NULL, &bufsize,
|
||||
nb->data, NULL, NULL, NULL);
|
||||
if (st == GRUB_EFI_BUFFER_TOO_SMALL)
|
||||
{
|
||||
err = grub_netbuff_put (nb, bufsize - 1500);
|
||||
if (err)
|
||||
return -1;
|
||||
st = efi_call_7 (net->receive, net, NULL, &bufsize,
|
||||
nb->data, NULL, NULL, NULL);
|
||||
}
|
||||
if (st != GRUB_EFI_SUCCESS)
|
||||
{
|
||||
grub_netbuff_clear (nb);
|
||||
return -1;
|
||||
}
|
||||
err = grub_netbuff_unput (nb, (nb->tail - nb->data) - bufsize);
|
||||
if (err)
|
||||
return -1;
|
||||
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
static struct grub_net_card_driver efidriver =
|
||||
{
|
||||
.name = "efinet",
|
||||
.send = send_card_buffer,
|
||||
.recv = get_card_packet
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
grub_efinet_findcards (void)
|
||||
{
|
||||
grub_efi_uintn_t num_handles;
|
||||
grub_efi_handle_t *handles;
|
||||
grub_efi_handle_t *handle;
|
||||
int i = 0;
|
||||
|
||||
/* Find handles which support the disk io interface. */
|
||||
handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &net_io_guid,
|
||||
0, &num_handles);
|
||||
if (! handles)
|
||||
return;
|
||||
for (handle = handles; num_handles--; handle++)
|
||||
{
|
||||
grub_efi_simple_network_t *net;
|
||||
struct grub_net_card *card;
|
||||
|
||||
net = grub_efi_open_protocol (*handle, &net_io_guid,
|
||||
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (! net)
|
||||
/* This should not happen... Why? */
|
||||
continue;
|
||||
|
||||
if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
|
||||
&& efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (net->mode->state == GRUB_EFI_NETWORK_STOPPED)
|
||||
continue;
|
||||
|
||||
if (net->mode->state == GRUB_EFI_NETWORK_STARTED
|
||||
&& efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
card = grub_zalloc (sizeof (struct grub_net_card));
|
||||
if (!card)
|
||||
{
|
||||
grub_print_error ();
|
||||
grub_free (handles);
|
||||
return;
|
||||
}
|
||||
|
||||
card->name = grub_xasprintf ("efinet%d", i++);
|
||||
card->driver = &efidriver;
|
||||
card->flags = 0;
|
||||
card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||
grub_memcpy (card->default_address.mac,
|
||||
net->mode->current_address,
|
||||
sizeof (card->default_address.mac));
|
||||
card->efi_net = net;
|
||||
card->efi_handle = *handle;
|
||||
|
||||
grub_net_card_register (card);
|
||||
}
|
||||
grub_free (handles);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
|
||||
char **path)
|
||||
{
|
||||
struct grub_net_card *card;
|
||||
grub_efi_device_path_t *dp;
|
||||
|
||||
dp = grub_efi_get_device_path (hnd);
|
||||
if (! dp)
|
||||
return;
|
||||
|
||||
FOR_NET_CARDS (card)
|
||||
{
|
||||
grub_efi_device_path_t *cdp;
|
||||
struct grub_efi_pxe *pxe;
|
||||
struct grub_efi_pxe_mode *pxe_mode;
|
||||
if (card->driver != &efidriver)
|
||||
continue;
|
||||
cdp = grub_efi_get_device_path (card->efi_handle);
|
||||
if (! cdp)
|
||||
continue;
|
||||
if (grub_efi_compare_device_paths (dp, cdp) != 0)
|
||||
continue;
|
||||
pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
|
||||
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (! pxe)
|
||||
continue;
|
||||
pxe_mode = pxe->mode;
|
||||
grub_net_configure_by_dhcp_ack (card->name, card, 0,
|
||||
(struct grub_net_bootp_packet *)
|
||||
&pxe_mode->dhcp_ack,
|
||||
sizeof (pxe_mode->dhcp_ack),
|
||||
1, device, path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GRUB_MOD_INIT(efinet)
|
||||
{
|
||||
grub_efinet_findcards ();
|
||||
grub_efi_net_config = grub_efi_net_config_real;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(efinet)
|
||||
{
|
||||
struct grub_net_card *card, *next;
|
||||
|
||||
FOR_NET_CARDS_SAFE (card, next)
|
||||
if (card->driver == &efidriver)
|
||||
grub_net_card_unregister (card);
|
||||
}
|
||||
|
359
grub-core/net/drivers/i386/pc/pxe.c
Normal file
359
grub-core/net/drivers/i386/pc/pxe.c
Normal file
|
@ -0,0 +1,359 @@
|
|||
/* pxe.c - Driver to provide access to the pxe filesystem */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009,2011 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/dl.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
|
||||
#include <grub/machine/pxe.h>
|
||||
#include <grub/machine/int.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define SEGMENT(x) ((x) >> 4)
|
||||
#define OFFSET(x) ((x) & 0xF)
|
||||
#define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x))
|
||||
#define LINEAR(x) (void *) ((((x) >> 16) << 4) + ((x) & 0xFFFF))
|
||||
|
||||
struct grub_pxe_undi_open
|
||||
{
|
||||
grub_uint16_t status;
|
||||
grub_uint16_t open_flag;
|
||||
grub_uint16_t pkt_filter;
|
||||
grub_uint16_t mcast_count;
|
||||
grub_uint8_t mcast[8][6];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_pxe_undi_info
|
||||
{
|
||||
grub_uint16_t status;
|
||||
grub_uint16_t base_io;
|
||||
grub_uint16_t int_number;
|
||||
grub_uint16_t mtu;
|
||||
grub_uint16_t hwtype;
|
||||
grub_uint16_t hwaddrlen;
|
||||
grub_uint8_t current_addr[16];
|
||||
grub_uint8_t permanent_addr[16];
|
||||
grub_uint32_t romaddr;
|
||||
grub_uint16_t rxbufct;
|
||||
grub_uint16_t txbufct;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct grub_pxe_undi_isr
|
||||
{
|
||||
grub_uint16_t status;
|
||||
grub_uint16_t func_flag;
|
||||
grub_uint16_t buffer_len;
|
||||
grub_uint16_t frame_len;
|
||||
grub_uint16_t frame_hdr_len;
|
||||
grub_uint32_t buffer;
|
||||
grub_uint8_t prot_type;
|
||||
grub_uint8_t pkt_type;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_PXE_ISR_IN_START = 1,
|
||||
GRUB_PXE_ISR_IN_PROCESS,
|
||||
GRUB_PXE_ISR_IN_GET_NEXT
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_PXE_ISR_OUT_OURS = 0,
|
||||
GRUB_PXE_ISR_OUT_NOT_OURS = 1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_PXE_ISR_OUT_DONE = 0,
|
||||
GRUB_PXE_ISR_OUT_TRANSMIT = 2,
|
||||
GRUB_PXE_ISR_OUT_RECEIVE = 3,
|
||||
GRUB_PXE_ISR_OUT_BUSY = 4,
|
||||
};
|
||||
|
||||
struct grub_pxe_undi_transmit
|
||||
{
|
||||
grub_uint16_t status;
|
||||
grub_uint8_t protocol;
|
||||
grub_uint8_t xmitflag;
|
||||
grub_uint32_t dest;
|
||||
grub_uint32_t tbd;
|
||||
grub_uint32_t reserved[2];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_pxe_undi_tbd
|
||||
{
|
||||
grub_uint16_t len;
|
||||
grub_uint32_t buf;
|
||||
grub_uint16_t blk_count;
|
||||
struct
|
||||
{
|
||||
grub_uint8_t ptr_type;
|
||||
grub_uint8_t reserved;
|
||||
grub_uint16_t len;
|
||||
grub_uint32_t ptr;
|
||||
} blocks[8];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_pxe_bangpxe *grub_pxe_pxenv;
|
||||
static grub_uint32_t pxe_rm_entry = 0;
|
||||
|
||||
static struct grub_pxe_bangpxe *
|
||||
grub_pxe_scan (void)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
struct grub_pxenv *pxenv;
|
||||
struct grub_pxe_bangpxe *bangpxe;
|
||||
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
|
||||
regs.ebx = 0;
|
||||
regs.ecx = 0;
|
||||
regs.eax = 0x5650;
|
||||
regs.es = 0;
|
||||
|
||||
grub_bios_interrupt (0x1a, ®s);
|
||||
|
||||
if ((regs.eax & 0xffff) != 0x564e)
|
||||
return NULL;
|
||||
|
||||
pxenv = (struct grub_pxenv *) ((regs.es << 4) + (regs.ebx & 0xffff));
|
||||
if (grub_memcmp (pxenv->signature, GRUB_PXE_SIGNATURE,
|
||||
sizeof (pxenv->signature))
|
||||
!= 0)
|
||||
return NULL;
|
||||
|
||||
if (pxenv->version < 0x201)
|
||||
return NULL;
|
||||
|
||||
bangpxe = (void *) ((((pxenv->pxe_ptr & 0xffff0000) >> 16) << 4)
|
||||
+ (pxenv->pxe_ptr & 0xffff));
|
||||
|
||||
if (!bangpxe)
|
||||
return NULL;
|
||||
|
||||
if (grub_memcmp (bangpxe->signature, GRUB_PXE_BANGPXE_SIGNATURE,
|
||||
sizeof (bangpxe->signature)) != 0)
|
||||
return NULL;
|
||||
|
||||
pxe_rm_entry = bangpxe->rm_entry;
|
||||
|
||||
return bangpxe;
|
||||
}
|
||||
|
||||
static grub_ssize_t
|
||||
grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)),
|
||||
struct grub_net_buff *buf)
|
||||
{
|
||||
struct grub_pxe_undi_isr *isr;
|
||||
static int in_progress = 0;
|
||||
char *ptr, *end;
|
||||
int len;
|
||||
|
||||
isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||
|
||||
if (!in_progress)
|
||||
{
|
||||
grub_memset (isr, 0, sizeof (*isr));
|
||||
isr->func_flag = GRUB_PXE_ISR_IN_START;
|
||||
grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry);
|
||||
if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_OURS)
|
||||
{
|
||||
in_progress = 0;
|
||||
return -1;
|
||||
}
|
||||
grub_memset (isr, 0, sizeof (*isr));
|
||||
isr->func_flag = GRUB_PXE_ISR_IN_PROCESS;
|
||||
grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_memset (isr, 0, sizeof (*isr));
|
||||
isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT;
|
||||
grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry);
|
||||
}
|
||||
|
||||
while (isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE)
|
||||
{
|
||||
if (isr->status || isr->func_flag == GRUB_PXE_ISR_OUT_DONE)
|
||||
{
|
||||
in_progress = 0;
|
||||
return -1;
|
||||
}
|
||||
grub_memset (isr, 0, sizeof (*isr));
|
||||
isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT;
|
||||
grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry);
|
||||
}
|
||||
|
||||
grub_netbuff_put (buf, isr->frame_len);
|
||||
ptr = buf->data;
|
||||
end = ptr + isr->frame_len;
|
||||
len = isr->frame_len;
|
||||
grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len);
|
||||
ptr += isr->buffer_len;
|
||||
while (ptr < end)
|
||||
{
|
||||
grub_memset (isr, 0, sizeof (*isr));
|
||||
isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT;
|
||||
grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry);
|
||||
if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE)
|
||||
{
|
||||
in_progress = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len);
|
||||
ptr += isr->buffer_len;
|
||||
}
|
||||
in_progress = 1;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_pxe_send (const struct grub_net_card *dev __attribute__ ((unused)),
|
||||
struct grub_net_buff *pack)
|
||||
{
|
||||
struct grub_pxe_undi_transmit *trans;
|
||||
struct grub_pxe_undi_tbd *tbd;
|
||||
char *buf;
|
||||
|
||||
trans = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||
grub_memset (trans, 0, sizeof (*trans));
|
||||
tbd = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 128);
|
||||
grub_memset (tbd, 0, sizeof (*tbd));
|
||||
buf = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 256);
|
||||
grub_memcpy (buf, pack->data, pack->tail - pack->data);
|
||||
|
||||
trans->tbd = SEGOFS ((grub_addr_t) tbd);
|
||||
trans->protocol = 0;
|
||||
tbd->len = pack->tail - pack->data;
|
||||
tbd->buf = SEGOFS ((grub_addr_t) buf);
|
||||
|
||||
grub_pxe_call (GRUB_PXENV_UNDI_TRANSMIT, trans, pxe_rm_entry);
|
||||
if (trans->status)
|
||||
return grub_error (GRUB_ERR_IO, "PXE send failed (status 0x%x)",
|
||||
trans->status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_pxe_close (const struct grub_net_card *dev __attribute__ ((unused)))
|
||||
{
|
||||
if (pxe_rm_entry)
|
||||
grub_pxe_call (GRUB_PXENV_UNDI_CLOSE,
|
||||
(void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
|
||||
pxe_rm_entry);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_pxe_open (const struct grub_net_card *dev __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_pxe_undi_open *ou;
|
||||
ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||
grub_memset (ou, 0, sizeof (*ou));
|
||||
ou->pkt_filter = 4;
|
||||
grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry);
|
||||
|
||||
if (ou->status)
|
||||
return grub_error (GRUB_ERR_IO, "can't open UNDI");
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
struct grub_net_card_driver grub_pxe_card_driver =
|
||||
{
|
||||
.open = grub_pxe_open,
|
||||
.close = grub_pxe_close,
|
||||
.send = grub_pxe_send,
|
||||
.recv = grub_pxe_recv
|
||||
};
|
||||
|
||||
struct grub_net_card grub_pxe_card =
|
||||
{
|
||||
.driver = &grub_pxe_card_driver,
|
||||
.name = "pxe"
|
||||
};
|
||||
|
||||
static void
|
||||
grub_pc_net_config_real (char **device, char **path)
|
||||
{
|
||||
struct grub_net_bootp_packet *bp;
|
||||
struct grub_pxenv_get_cached_info ci;
|
||||
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_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0,
|
||||
bp, GRUB_PXE_BOOTP_SIZE,
|
||||
1, device, path);
|
||||
|
||||
}
|
||||
|
||||
GRUB_MOD_INIT(pxe)
|
||||
{
|
||||
struct grub_pxe_bangpxe *pxenv;
|
||||
struct grub_pxe_undi_info *ui;
|
||||
unsigned i;
|
||||
|
||||
pxenv = grub_pxe_scan ();
|
||||
if (! pxenv)
|
||||
return;
|
||||
|
||||
ui = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||
grub_memset (ui, 0, sizeof (*ui));
|
||||
grub_pxe_call (GRUB_PXENV_UNDI_GET_INFORMATION, ui, pxe_rm_entry);
|
||||
|
||||
grub_memcpy (grub_pxe_card.default_address.mac, ui->current_addr,
|
||||
sizeof (grub_pxe_card.default_address.mac));
|
||||
for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++)
|
||||
if (grub_pxe_card.default_address.mac[i] != 0)
|
||||
break;
|
||||
if (i != sizeof (grub_pxe_card.default_address.mac))
|
||||
{
|
||||
for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++)
|
||||
if (grub_pxe_card.default_address.mac[i] != 0xff)
|
||||
break;
|
||||
}
|
||||
if (i == sizeof (grub_pxe_card.default_address.mac))
|
||||
grub_memcpy (grub_pxe_card.default_address.mac, ui->permanent_addr,
|
||||
sizeof (grub_pxe_card.default_address.mac));
|
||||
|
||||
grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||
|
||||
grub_net_card_register (&grub_pxe_card);
|
||||
grub_pc_net_config = grub_pc_net_config_real;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(pxe)
|
||||
{
|
||||
grub_pc_net_config = 0;
|
||||
grub_net_card_unregister (&grub_pxe_card);
|
||||
}
|
|
@ -1,5 +1,22 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010,2011 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/net/netbuff.h>
|
||||
#include <grub/ieee1275/ofnet.h>
|
||||
#include <grub/ieee1275/ieee1275.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/net.h>
|
||||
|
@ -7,8 +24,15 @@
|
|||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
struct grub_ofnetcard_data
|
||||
{
|
||||
char *path;
|
||||
grub_ieee1275_ihandle_t handle;
|
||||
grub_uint32_t mtu;
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
card_open (struct grub_net_card *dev)
|
||||
card_open (const struct grub_net_card *dev)
|
||||
{
|
||||
int status;
|
||||
struct grub_ofnetcard_data *data = dev->data;
|
||||
|
@ -26,14 +50,13 @@ card_open (struct grub_net_card *dev)
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
card_close (struct grub_net_card *dev)
|
||||
static void
|
||||
card_close (const 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
|
||||
|
@ -75,8 +98,8 @@ get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb)
|
|||
static struct grub_net_card_driver ofdriver =
|
||||
{
|
||||
.name = "ofnet",
|
||||
.init = card_open,
|
||||
.fini = card_close,
|
||||
.open = card_open,
|
||||
.close = card_close,
|
||||
.send = send_card_buffer,
|
||||
.recv = get_card_packet
|
||||
};
|
||||
|
@ -94,51 +117,113 @@ bootp_response_properties[] =
|
|||
{ .name = "bootpreply-packet", .offset = 0x2a},
|
||||
};
|
||||
|
||||
static grub_bootp_t
|
||||
grub_getbootp_real (void)
|
||||
static void
|
||||
grub_ieee1275_net_config_real (const char *devpath, char **device, char **path)
|
||||
{
|
||||
grub_bootp_t packet = grub_malloc (sizeof *packet);
|
||||
char *bootp_response;
|
||||
grub_ssize_t size;
|
||||
unsigned int i;
|
||||
struct grub_net_card *card;
|
||||
|
||||
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;
|
||||
/* FIXME: Check that it's the right card. */
|
||||
FOR_NET_CARDS (card)
|
||||
{
|
||||
char *bootp_response;
|
||||
char *cardpath;
|
||||
char *canon;
|
||||
|
||||
if (size < 0)
|
||||
return NULL;
|
||||
grub_ssize_t size = -1;
|
||||
unsigned int i;
|
||||
|
||||
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;
|
||||
if (card->driver != &ofdriver)
|
||||
continue;
|
||||
|
||||
grub_memcpy (packet, bootp_response + bootp_response_properties[i].offset, sizeof (*packet));
|
||||
grub_free (bootp_response);
|
||||
return packet;
|
||||
cardpath = ((struct grub_ofnetcard_data *) card->data)->path;
|
||||
canon = grub_ieee1275_canonicalise_devname (cardpath);
|
||||
if (grub_strcmp (devpath, canon) != 0)
|
||||
{
|
||||
grub_free (canon);
|
||||
continue;
|
||||
}
|
||||
grub_free (canon);
|
||||
|
||||
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;
|
||||
|
||||
bootp_response = grub_malloc (size);
|
||||
if (!bootp_response)
|
||||
{
|
||||
grub_print_error ();
|
||||
return;
|
||||
}
|
||||
if (grub_ieee1275_get_property (grub_ieee1275_chosen,
|
||||
bootp_response_properties[i].name,
|
||||
bootp_response, size, 0) < 0)
|
||||
return;
|
||||
|
||||
grub_net_configure_by_dhcp_ack (card->name, card, 0,
|
||||
(struct grub_net_bootp_packet *)
|
||||
&bootp_response
|
||||
+ bootp_response_properties[i].offset,
|
||||
size - bootp_response_properties[i].offset,
|
||||
1, device, path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
find_alias (const char *fullname)
|
||||
{
|
||||
char *ret = NULL;
|
||||
auto int find_alias_hook (struct grub_ieee1275_devalias *alias);
|
||||
|
||||
int find_alias_hook (struct grub_ieee1275_devalias *alias)
|
||||
{
|
||||
if (grub_strcmp (alias->path, fullname) == 0)
|
||||
{
|
||||
ret = grub_strdup (alias->name);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_devalias_iterate (find_alias_hook);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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"))
|
||||
{
|
||||
struct grub_ofnetcard_data *ofdata;
|
||||
struct grub_net_card *card;
|
||||
grub_ieee1275_phandle_t devhandle;
|
||||
grub_net_link_level_address_t lla;
|
||||
char *shortname;
|
||||
|
||||
ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data));
|
||||
if (!ofdata)
|
||||
{
|
||||
grub_print_error ();
|
||||
return 1;
|
||||
}
|
||||
card = grub_zalloc (sizeof (struct grub_net_card));
|
||||
if (!card)
|
||||
{
|
||||
grub_free (ofdata);
|
||||
grub_print_error ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -146,11 +231,19 @@ grub_ofnet_findcards (void)
|
|||
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.");
|
||||
{
|
||||
ofdata->mtu = 1500;
|
||||
}
|
||||
|
||||
if (grub_ieee1275_get_property
|
||||
(devhandle, "mac-address", &(lla.mac), 6, 0))
|
||||
return grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address.");
|
||||
if (grub_ieee1275_get_property (devhandle, "mac-address",
|
||||
&(lla.mac), 6, 0)
|
||||
&& grub_ieee1275_get_property (devhandle, "local-mac-address",
|
||||
&(lla.mac), 6, 0))
|
||||
{
|
||||
grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address.");
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||
card->default_address = lla;
|
||||
|
@ -158,7 +251,12 @@ grub_ofnet_findcards (void)
|
|||
card->driver = NULL;
|
||||
card->data = ofdata;
|
||||
card->flags = 0;
|
||||
card->name = grub_xasprintf ("eth%d", i++);
|
||||
shortname = find_alias (alias->path);
|
||||
card->name = grub_xasprintf ("ofnet_%s", shortname ? : alias->path);
|
||||
card->idle_poll_delay_ms = 1;
|
||||
grub_free (shortname);
|
||||
|
||||
card->driver = &ofdriver;
|
||||
grub_net_card_register (card);
|
||||
return 0;
|
||||
}
|
||||
|
@ -169,69 +267,18 @@ grub_ofnet_findcards (void)
|
|||
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_ieee1275_net_config = grub_ieee1275_net_config_real;
|
||||
}
|
||||
|
||||
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;
|
||||
struct grub_net_card *card, *next;
|
||||
|
||||
FOR_NET_CARDS_SAFE (card, next)
|
||||
if (card->driver && grub_strcmp (card->driver->name, "ofnet") == 0)
|
||||
grub_net_card_unregister (card);
|
||||
grub_ieee1275_net_config = 0;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010,2011 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/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/net/ethernet.h>
|
||||
|
@ -8,6 +26,28 @@
|
|||
#include <grub/time.h>
|
||||
#include <grub/net/arp.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));
|
||||
|
||||
grub_err_t
|
||||
send_ethernet_packet (struct grub_net_network_level_interface *inf,
|
||||
struct grub_net_buff *nb,
|
||||
|
@ -25,7 +65,15 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
|
|||
grub_memcpy (eth->src, inf->hwaddress.mac, 6);
|
||||
|
||||
eth->type = grub_cpu_to_be16 (ethertype);
|
||||
|
||||
if (!inf->card->opened)
|
||||
{
|
||||
err = GRUB_ERR_NONE;
|
||||
if (inf->card->driver->open)
|
||||
err = inf->card->driver->open (inf->card);
|
||||
if (err)
|
||||
return err;
|
||||
inf->card->opened = 1;
|
||||
}
|
||||
return inf->card->driver->send (inf->card, nb);
|
||||
}
|
||||
|
||||
|
@ -69,10 +117,14 @@ grub_net_recv_ethernet_packet (struct grub_net_buff * nb,
|
|||
{
|
||||
grub_net_arp_receive (nb);
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
/* IP packet. */
|
||||
if (type == GRUB_NET_ETHERTYPE_IP)
|
||||
grub_net_recv_ip_packets (nb, card, &hwaddress);
|
||||
|
||||
{
|
||||
grub_net_recv_ip_packets (nb, card, &hwaddress);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
|
|
@ -1,482 +0,0 @@
|
|||
/* pxe.c - Driver to provide access to the pxe filesystem */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009 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/dl.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/bufio.h>
|
||||
#include <grub/env.h>
|
||||
|
||||
#include <grub/machine/pxe.h>
|
||||
#include <grub/machine/int.h>
|
||||
#include <grub/machine/memory.h>
|
||||
|
||||
#define SEGMENT(x) ((x) >> 4)
|
||||
#define OFFSET(x) ((x) & 0xF)
|
||||
#define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x))
|
||||
#define LINEAR(x) (void *) (((x >> 16) << 4) + (x & 0xFFFF))
|
||||
|
||||
struct grub_pxe_bangpxe *grub_pxe_pxenv;
|
||||
static grub_uint32_t grub_pxe_default_server_ip;
|
||||
#if 0
|
||||
static grub_uint32_t grub_pxe_default_gateway_ip;
|
||||
#endif
|
||||
static unsigned grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE;
|
||||
static grub_uint32_t pxe_rm_entry = 0;
|
||||
static grub_file_t curr_file = 0;
|
||||
|
||||
struct grub_pxe_data
|
||||
{
|
||||
grub_uint32_t packet_number;
|
||||
grub_uint32_t block_size;
|
||||
grub_uint32_t server_ip;
|
||||
grub_uint32_t gateway_ip;
|
||||
char filename[0];
|
||||
};
|
||||
|
||||
|
||||
static struct grub_pxe_bangpxe *
|
||||
grub_pxe_scan (void)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
struct grub_pxenv *pxenv;
|
||||
struct grub_pxe_bangpxe *bangpxe;
|
||||
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
|
||||
regs.ebx = 0;
|
||||
regs.ecx = 0;
|
||||
regs.eax = 0x5650;
|
||||
regs.es = 0;
|
||||
|
||||
grub_bios_interrupt (0x1a, ®s);
|
||||
|
||||
if ((regs.eax & 0xffff) != 0x564e)
|
||||
return NULL;
|
||||
|
||||
pxenv = (struct grub_pxenv *) ((regs.es << 4) + (regs.ebx & 0xffff));
|
||||
if (grub_memcmp (pxenv->signature, GRUB_PXE_SIGNATURE,
|
||||
sizeof (pxenv->signature))
|
||||
!= 0)
|
||||
return NULL;
|
||||
|
||||
if (pxenv->version < 0x201)
|
||||
return NULL;
|
||||
|
||||
bangpxe = (void *) ((((pxenv->pxe_ptr & 0xffff0000) >> 16) << 4)
|
||||
+ (pxenv->pxe_ptr & 0xffff));
|
||||
|
||||
if (!bangpxe)
|
||||
return NULL;
|
||||
|
||||
if (grub_memcmp (bangpxe->signature, GRUB_PXE_BANGPXE_SIGNATURE,
|
||||
sizeof (bangpxe->signature)) != 0)
|
||||
return NULL;
|
||||
|
||||
pxe_rm_entry = bangpxe->rm_entry;
|
||||
|
||||
return bangpxe;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_pxefs_dir (grub_device_t device __attribute__ ((unused)),
|
||||
const char *path __attribute__ ((unused)),
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info)
|
||||
__attribute__ ((unused)))
|
||||
{
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_pxefs_open (struct grub_file *file, const char *name)
|
||||
{
|
||||
union
|
||||
{
|
||||
struct grub_pxenv_tftp_get_fsize c1;
|
||||
struct grub_pxenv_tftp_open c2;
|
||||
} c;
|
||||
struct grub_pxe_data *data;
|
||||
grub_file_t file_int, bufio;
|
||||
|
||||
data = grub_zalloc (sizeof (*data) + grub_strlen (name) + 1);
|
||||
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)
|
||||
{
|
||||
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2, pxe_rm_entry);
|
||||
curr_file = 0;
|
||||
}
|
||||
|
||||
c.c1.server_ip = data->server_ip;
|
||||
c.c1.gateway_ip = data->gateway_ip;
|
||||
grub_strcpy ((char *)&c.c1.filename[0], name);
|
||||
grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry);
|
||||
if (c.c1.status)
|
||||
{
|
||||
grub_free (data);
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
|
||||
}
|
||||
|
||||
file->size = c.c1.file_size;
|
||||
|
||||
c.c2.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT);
|
||||
c.c2.packet_size = grub_pxe_blksize;
|
||||
grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2, pxe_rm_entry);
|
||||
if (c.c2.status)
|
||||
{
|
||||
grub_free (data);
|
||||
return grub_error (GRUB_ERR_BAD_FS, "open fails");
|
||||
}
|
||||
|
||||
data->block_size = c.c2.packet_size;
|
||||
grub_strcpy (data->filename, name);
|
||||
|
||||
file_int = grub_malloc (sizeof (*file_int));
|
||||
if (! file_int)
|
||||
{
|
||||
grub_free (data);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
file->data = data;
|
||||
file->not_easily_seekable = 1;
|
||||
grub_memcpy (file_int, file, sizeof (struct grub_file));
|
||||
curr_file = file_int;
|
||||
|
||||
bufio = grub_bufio_open (file_int, data->block_size);
|
||||
if (! bufio)
|
||||
{
|
||||
grub_free (file_int);
|
||||
grub_free (data);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_memcpy (file, bufio, sizeof (struct grub_file));
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_ssize_t
|
||||
grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
{
|
||||
struct grub_pxenv_tftp_read c;
|
||||
struct grub_pxe_data *data;
|
||||
grub_uint32_t pn;
|
||||
grub_uint64_t r;
|
||||
|
||||
data = file->data;
|
||||
|
||||
pn = grub_divmod64 (file->offset, data->block_size, &r);
|
||||
if (r)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS,
|
||||
"read access must be aligned to packet size");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((curr_file != file) || (data->packet_number > pn))
|
||||
{
|
||||
struct grub_pxenv_tftp_open o;
|
||||
|
||||
if (curr_file != 0)
|
||||
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o, pxe_rm_entry);
|
||||
|
||||
o.server_ip = data->server_ip;
|
||||
o.gateway_ip = data->gateway_ip;
|
||||
grub_strcpy ((char *)&o.filename[0], data->filename);
|
||||
o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT);
|
||||
o.packet_size = data->block_size;
|
||||
grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &o, pxe_rm_entry);
|
||||
if (o.status)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "open fails");
|
||||
return -1;
|
||||
}
|
||||
data->block_size = o.packet_size;
|
||||
data->packet_number = 0;
|
||||
curr_file = file;
|
||||
}
|
||||
|
||||
c.buffer = SEGOFS (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
|
||||
while (pn >= data->packet_number)
|
||||
{
|
||||
c.buffer_size = data->block_size;
|
||||
grub_pxe_call (GRUB_PXENV_TFTP_READ, &c, pxe_rm_entry);
|
||||
if (c.status)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "read fails");
|
||||
return -1;
|
||||
}
|
||||
data->packet_number++;
|
||||
}
|
||||
|
||||
grub_memcpy (buf, (char *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_pxefs_close (grub_file_t file)
|
||||
{
|
||||
struct grub_pxenv_tftp_close c;
|
||||
|
||||
if (curr_file == file)
|
||||
{
|
||||
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c, pxe_rm_entry);
|
||||
curr_file = 0;
|
||||
}
|
||||
|
||||
grub_free (file->data);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_pxefs_label (grub_device_t device __attribute ((unused)),
|
||||
char **label __attribute ((unused)))
|
||||
{
|
||||
*label = 0;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static struct grub_fs grub_pxefs_fs =
|
||||
{
|
||||
.name = "pxe",
|
||||
.dir = grub_pxefs_dir,
|
||||
.open = grub_pxefs_open,
|
||||
.read = grub_pxefs_read,
|
||||
.close = grub_pxefs_close,
|
||||
.label = grub_pxefs_label,
|
||||
.next = 0
|
||||
};
|
||||
|
||||
static grub_ssize_t
|
||||
grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)),
|
||||
struct grub_net_buff *buf __attribute__ ((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_pxe_send (const struct grub_net_card *dev __attribute__ ((unused)),
|
||||
struct grub_net_buff *buf __attribute__ ((unused)))
|
||||
{
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "not implemented");
|
||||
}
|
||||
|
||||
struct grub_net_card_driver grub_pxe_card_driver =
|
||||
{
|
||||
.send = grub_pxe_send,
|
||||
.recv = grub_pxe_recv
|
||||
};
|
||||
|
||||
struct grub_net_card grub_pxe_card =
|
||||
{
|
||||
.driver = &grub_pxe_card_driver,
|
||||
.name = "pxe"
|
||||
};
|
||||
|
||||
void
|
||||
grub_pxe_unload (void)
|
||||
{
|
||||
if (grub_pxe_pxenv)
|
||||
{
|
||||
grub_fs_unregister (&grub_pxefs_fs);
|
||||
grub_net_card_unregister (&grub_pxe_card);
|
||||
grub_pxe_pxenv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_ip_env (char *varname, grub_uint32_t ip)
|
||||
{
|
||||
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_net_addr_to_str (&addr, buf);
|
||||
grub_env_set (varname, buf);
|
||||
}
|
||||
|
||||
static char *
|
||||
write_ip_env (grub_uint32_t *ip, const char *val)
|
||||
{
|
||||
char *buf;
|
||||
grub_err_t err;
|
||||
grub_net_network_level_address_t addr;
|
||||
|
||||
err = grub_net_resolve_address (val, &addr);
|
||||
if (err)
|
||||
return 0;
|
||||
if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
|
||||
return NULL;
|
||||
|
||||
/* Normalize the IP. */
|
||||
buf = grub_malloc (GRUB_NET_MAX_STR_ADDR_LEN);
|
||||
if (!buf)
|
||||
return 0;
|
||||
grub_net_addr_to_str (&addr, buf);
|
||||
|
||||
*ip = addr.ipv4;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *
|
||||
grub_env_write_pxe_default_server (struct grub_env_var *var
|
||||
__attribute__ ((unused)),
|
||||
const char *val)
|
||||
{
|
||||
return write_ip_env (&grub_pxe_default_server_ip, val);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char *
|
||||
grub_env_write_pxe_default_gateway (struct grub_env_var *var
|
||||
__attribute__ ((unused)),
|
||||
const char *val)
|
||||
{
|
||||
return write_ip_env (&grub_pxe_default_gateway_ip, val);
|
||||
}
|
||||
#endif
|
||||
|
||||
static char *
|
||||
grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)),
|
||||
const char *val)
|
||||
{
|
||||
unsigned size;
|
||||
char *buf;
|
||||
|
||||
size = grub_strtoul (val, 0, 0);
|
||||
if (grub_errno)
|
||||
return 0;
|
||||
|
||||
if (size < GRUB_PXE_MIN_BLKSIZE)
|
||||
size = GRUB_PXE_MIN_BLKSIZE;
|
||||
else if (size > GRUB_PXE_MAX_BLKSIZE)
|
||||
size = GRUB_PXE_MAX_BLKSIZE;
|
||||
|
||||
buf = grub_xasprintf ("%d", size);
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
grub_pxe_blksize = size;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
GRUB_MOD_INIT(pxe)
|
||||
{
|
||||
struct grub_pxe_bangpxe *pxenv;
|
||||
struct grub_pxenv_get_cached_info ci;
|
||||
struct grub_net_bootp_packet *bp;
|
||||
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);
|
||||
if (buf)
|
||||
grub_env_set ("pxe_blksize", buf);
|
||||
grub_free (buf);
|
||||
|
||||
grub_register_variable_hook ("pxe_blksize", 0,
|
||||
grub_env_write_pxe_blocksize);
|
||||
|
||||
grub_memcpy (grub_pxe_card.default_address.mac, bp->mac_addr,
|
||||
bp->hw_len < sizeof (grub_pxe_card.default_address.mac)
|
||||
? bp->hw_len : sizeof (grub_pxe_card.default_address.mac));
|
||||
grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||
|
||||
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_pxe_unload ();
|
||||
}
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010,2011 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/net/ip.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/net/arp.h>
|
||||
|
@ -7,8 +25,32 @@
|
|||
#include <grub/net/netbuff.h>
|
||||
#include <grub/mm.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));
|
||||
|
||||
grub_uint16_t
|
||||
ipchksum (void *ipv, int len)
|
||||
grub_net_ip_chksum (void *ipv, int len)
|
||||
{
|
||||
grub_uint16_t *ip = (grub_uint16_t *) ipv;
|
||||
grub_uint32_t sum = 0;
|
||||
|
@ -48,7 +90,7 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface * inf,
|
|||
iph->dest = target->ipv4;
|
||||
|
||||
iph->chksum = 0;
|
||||
iph->chksum = ipchksum ((void *) nb->data, sizeof (*iph));
|
||||
iph->chksum = grub_net_ip_chksum ((void *) nb->data, sizeof (*iph));
|
||||
|
||||
/* Determine link layer target address via ARP. */
|
||||
err = grub_net_arp_resolve (inf, target, &ll_target_addr);
|
||||
|
@ -65,50 +107,49 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb,
|
|||
{
|
||||
struct iphdr *iph = (struct iphdr *) nb->data;
|
||||
grub_err_t err;
|
||||
struct grub_net_network_level_interface *inf;
|
||||
struct grub_net_network_level_interface *inf = NULL;
|
||||
|
||||
err = grub_netbuff_pull (nb, sizeof (*iph));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||
/* DHCP needs special treatment since we don't know IP yet. */
|
||||
{
|
||||
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;
|
||||
struct udphdr *udph;
|
||||
udph = (struct udphdr *) nb->data;
|
||||
if (iph->protocol == IP_UDP && grub_be_to_cpu16 (udph->dst) == 68)
|
||||
{
|
||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||
if (inf->card == card
|
||||
&& inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV
|
||||
&& grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
|
||||
{
|
||||
err = grub_netbuff_pull (nb, sizeof (*udph));
|
||||
if (err)
|
||||
return err;
|
||||
grub_net_process_dhcp (nb, inf->card);
|
||||
grub_netbuff_free (nb);
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!inf)
|
||||
{
|
||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||
{
|
||||
if (inf->card == card
|
||||
&& inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC
|
||||
&& 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)
|
||||
{
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (iph->protocol)
|
||||
{
|
||||
case IP_UDP:
|
||||
return grub_net_recv_udp_packet (nb, inf);
|
||||
break;
|
||||
default:
|
||||
grub_netbuff_free (nb);
|
||||
break;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2010,2011 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
|
||||
|
@ -16,7 +16,6 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/net/udp.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/net/netbuff.h>
|
||||
#include <grub/time.h>
|
||||
|
@ -28,10 +27,14 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/net/ethernet.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/bufio.h>
|
||||
#include <grub/kernel.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
char *grub_net_default_server;
|
||||
|
||||
struct grub_net_route
|
||||
{
|
||||
struct grub_net_route *next;
|
||||
|
@ -49,20 +52,27 @@ struct grub_net_route
|
|||
struct grub_net_route *grub_net_routes = NULL;
|
||||
struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL;
|
||||
struct grub_net_card *grub_net_cards = NULL;
|
||||
struct grub_net_card_driver *grub_net_card_drivers = NULL;
|
||||
struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL;
|
||||
static struct grub_fs grub_net_fs;
|
||||
|
||||
static inline void
|
||||
grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter)
|
||||
void
|
||||
grub_net_card_unregister (struct grub_net_card *card)
|
||||
{
|
||||
*inter->prev = inter->next;
|
||||
if (inter->next)
|
||||
inter->next->prev = inter->prev;
|
||||
inter->next = 0;
|
||||
inter->prev = 0;
|
||||
struct grub_net_network_level_interface *inf, *next;
|
||||
FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(inf, next)
|
||||
if (inf->card == card)
|
||||
grub_net_network_level_interface_unregister (inf);
|
||||
if (card->opened)
|
||||
{
|
||||
if (card->driver->close)
|
||||
card->driver->close (card);
|
||||
card->opened = 0;
|
||||
}
|
||||
grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards),
|
||||
GRUB_AS_LIST (card));
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
grub_net_route_register (struct grub_net_route *route)
|
||||
{
|
||||
|
@ -117,7 +127,7 @@ match_net (const grub_net_network_level_netaddress_t *net,
|
|||
return 0;
|
||||
switch (net->type)
|
||||
{
|
||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC:
|
||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
|
||||
return 0;
|
||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
|
||||
{
|
||||
|
@ -236,8 +246,8 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf)
|
|||
{
|
||||
switch (target->type)
|
||||
{
|
||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC:
|
||||
grub_strcpy (buf, "promisc");
|
||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
|
||||
grub_strcpy (buf, "temporary");
|
||||
return;
|
||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
|
||||
{
|
||||
|
@ -334,6 +344,7 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa
|
|||
grub_register_variable_hook (name, 0, addr_set_env);
|
||||
}
|
||||
|
||||
inter->card->num_ifaces++;
|
||||
inter->prev = &grub_net_network_level_interfaces;
|
||||
inter->next = grub_net_network_level_interfaces;
|
||||
if (inter->next)
|
||||
|
@ -343,7 +354,7 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa
|
|||
|
||||
struct grub_net_network_level_interface *
|
||||
grub_net_add_addr (const char *name,
|
||||
const struct grub_net_card *card,
|
||||
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)
|
||||
|
@ -519,8 +530,8 @@ print_net_address (const grub_net_network_level_netaddress_t *target)
|
|||
{
|
||||
switch (target->type)
|
||||
{
|
||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC:
|
||||
grub_printf ("promisc\n");
|
||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
|
||||
grub_printf ("temporary\n");
|
||||
break;
|
||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
|
||||
{
|
||||
|
@ -574,9 +585,10 @@ grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)),
|
|||
struct grub_net_card *card;
|
||||
FOR_NET_CARDS(card)
|
||||
{
|
||||
grub_printf ("%s ", card->name);
|
||||
char buf[MAX_STR_HWADDR_LEN];
|
||||
hwaddr_to_str (&card->default_address, buf);
|
||||
grub_printf ("%s %s\n", card->name, buf);
|
||||
}
|
||||
grub_printf ("\n");
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -603,27 +615,68 @@ struct grub_net_socket *grub_net_sockets;
|
|||
static grub_net_t
|
||||
grub_net_open_real (const char *name)
|
||||
{
|
||||
const char *comma = grub_strchr (name, ',');
|
||||
grub_net_app_level_t proto;
|
||||
const char *protname, *server;
|
||||
grub_size_t protnamelen;
|
||||
|
||||
if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
|
||||
{
|
||||
protname = "tftp";
|
||||
protnamelen = sizeof ("tftp") - 1;
|
||||
server = name + sizeof ("pxe:") - 1;
|
||||
}
|
||||
else if (grub_strcmp (name, "pxe") == 0)
|
||||
{
|
||||
protname = "tftp";
|
||||
protnamelen = sizeof ("tftp") - 1;
|
||||
server = grub_net_default_server;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *comma;
|
||||
comma = grub_strchr (name, ',');
|
||||
if (comma)
|
||||
{
|
||||
protnamelen = comma - name;
|
||||
server = comma + 1;
|
||||
protname = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
protnamelen = grub_strlen (name);
|
||||
server = grub_net_default_server;
|
||||
protname = name;
|
||||
}
|
||||
}
|
||||
if (!server)
|
||||
{
|
||||
grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no server");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!comma)
|
||||
comma = name + grub_strlen (name);
|
||||
FOR_NET_APP_LEVEL (proto)
|
||||
{
|
||||
if (comma - name == (grub_ssize_t) grub_strlen (proto->name)
|
||||
&& grub_memcmp (proto->name, name, comma - name) == 0)
|
||||
if (grub_memcmp (proto->name, protname, protnamelen) == 0
|
||||
&& proto->name[protnamelen] == 0)
|
||||
{
|
||||
grub_net_t ret = grub_malloc (sizeof (*ret));
|
||||
grub_net_t ret = grub_zalloc (sizeof (*ret));
|
||||
if (!ret)
|
||||
return NULL;
|
||||
ret->protocol = proto;
|
||||
ret->name = grub_strdup (name);
|
||||
if (!ret->name)
|
||||
if (server)
|
||||
{
|
||||
grub_free (ret);
|
||||
return NULL;
|
||||
ret->server = grub_strdup (server);
|
||||
if (!ret->server)
|
||||
{
|
||||
grub_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
ret->server = NULL;
|
||||
ret->fs = &grub_net_fs;
|
||||
ret->offset = 0;
|
||||
ret->eof = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -643,73 +696,69 @@ grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused))
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_net_fs_open (struct grub_file *file, const char *name)
|
||||
grub_net_fs_open (struct grub_file *file_out, const char *name)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_net_network_level_address_t addr;
|
||||
struct grub_net_network_level_interface *inf;
|
||||
grub_net_network_level_address_t gateway;
|
||||
grub_net_socket_t socket;
|
||||
static int port = 25300;
|
||||
const char *comma;
|
||||
struct grub_file *file, *bufio;
|
||||
|
||||
comma = grub_strchr (file->device->net->name, ',');
|
||||
if (!comma)
|
||||
return grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no separator");
|
||||
file = grub_malloc (sizeof (*file));
|
||||
if (!file)
|
||||
return grub_errno;
|
||||
|
||||
err = grub_net_resolve_address (comma + 1, &addr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = grub_net_route_address (addr, &gateway, &inf);
|
||||
grub_memcpy (file, file_out, sizeof (struct grub_file));
|
||||
file->device->net->packs.first = NULL;
|
||||
file->device->net->packs.last = NULL;
|
||||
file->device->net->name = grub_strdup (name);
|
||||
if (!file->device->net->name)
|
||||
return grub_errno;
|
||||
|
||||
err = file->device->net->protocol->open (file, name);
|
||||
if (err)
|
||||
return err;
|
||||
bufio = grub_bufio_open (file, 32768);
|
||||
if (! bufio)
|
||||
{
|
||||
file->device->net->protocol->close (file);
|
||||
grub_free (file->device->net->name);
|
||||
grub_free (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
socket = (grub_net_socket_t) grub_malloc (sizeof (*socket));
|
||||
if (socket == NULL)
|
||||
return grub_errno;
|
||||
|
||||
socket->inf = inf;
|
||||
socket->out_nla = addr;
|
||||
socket->in_port = port++;
|
||||
socket->status = 0;
|
||||
socket->app = file->device->net->protocol;
|
||||
socket->packs.first = NULL;
|
||||
socket->packs.last = NULL;
|
||||
file->device->net->socket = socket;
|
||||
grub_net_socket_register (socket);
|
||||
|
||||
err = file->device->net->protocol->open (file,name);
|
||||
if (err)
|
||||
goto fail;
|
||||
file->not_easily_seekable = 1;
|
||||
|
||||
grub_memcpy (file_out, bufio, sizeof (struct grub_file));
|
||||
grub_free (bufio);
|
||||
return GRUB_ERR_NONE;
|
||||
fail:
|
||||
grub_net_socket_unregister (socket);
|
||||
grub_free (socket);
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_net_fs_close (grub_file_t file)
|
||||
{
|
||||
grub_net_socket_t sock = file->device->net->socket;
|
||||
while (sock->packs.first)
|
||||
while (file->device->net->packs.first)
|
||||
{
|
||||
grub_netbuff_free (sock->packs.first->nb);
|
||||
grub_net_remove_packet (sock->packs.first);
|
||||
grub_netbuff_free (file->device->net->packs.first->nb);
|
||||
grub_net_remove_packet (file->device->net->packs.first);
|
||||
}
|
||||
grub_net_socket_unregister (sock);
|
||||
grub_free (sock);
|
||||
file->device->net->protocol->close (file);
|
||||
grub_free (file->device->net->name);
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
receive_packets (struct grub_net_card *card)
|
||||
{
|
||||
if (card->num_ifaces == 0)
|
||||
return;
|
||||
if (!card->opened)
|
||||
{
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
if (card->driver->open)
|
||||
err = card->driver->open (card);
|
||||
if (err)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
card->opened = 1;
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
/* Maybe should be better have a fixed number of packets for each card
|
||||
|
@ -720,6 +769,7 @@ receive_packets (struct grub_net_card *card)
|
|||
if (!nb)
|
||||
{
|
||||
grub_print_error ();
|
||||
card->last_poll = grub_get_time_ms ();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -727,6 +777,7 @@ receive_packets (struct grub_net_card *card)
|
|||
if (actual < 0)
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
card->last_poll = grub_get_time_ms ();
|
||||
break;
|
||||
}
|
||||
grub_net_recv_ethernet_packet (nb, card);
|
||||
|
@ -747,13 +798,27 @@ grub_net_poll_cards (unsigned time)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
grub_net_poll_cards_idle_real (void)
|
||||
{
|
||||
struct grub_net_card *card;
|
||||
FOR_NET_CARDS (card)
|
||||
{
|
||||
grub_uint64_t ctime = grub_get_time_ms ();
|
||||
|
||||
if (ctime < card->last_poll
|
||||
|| ctime >= card->last_poll + card->idle_poll_delay_ms)
|
||||
receive_packets (card);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read from the packets list*/
|
||||
static grub_ssize_t
|
||||
grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
|
||||
{
|
||||
grub_net_socket_t sock = file->device->net->socket;
|
||||
grub_net_t sock = file->device->net;
|
||||
struct grub_net_buff *nb;
|
||||
char *ptr = buf;
|
||||
char *ptr = buf;
|
||||
grub_size_t amount, total = 0;
|
||||
int try = 0;
|
||||
while (try <= 3)
|
||||
|
@ -767,6 +832,7 @@ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
amount = len;
|
||||
len -= amount;
|
||||
total += amount;
|
||||
file->device->net->offset += amount;
|
||||
if (buf)
|
||||
{
|
||||
grub_memcpy (ptr, nb->data, amount);
|
||||
|
@ -783,7 +849,7 @@ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
if (!len)
|
||||
return total;
|
||||
}
|
||||
if (sock->status == 1)
|
||||
if (!sock->eof)
|
||||
{
|
||||
try++;
|
||||
grub_net_poll_cards (200);
|
||||
|
@ -794,454 +860,49 @@ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
return total;
|
||||
}
|
||||
|
||||
/* Read from the packets list*/
|
||||
static grub_err_t
|
||||
grub_net_seek_real (struct grub_file *file, grub_off_t offset)
|
||||
{
|
||||
grub_net_socket_t sock = file->device->net->socket;
|
||||
struct grub_net_buff *nb;
|
||||
grub_size_t len = offset - file->offset;
|
||||
grub_size_t len = offset - file->device->net->offset;
|
||||
|
||||
if (!len)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
/* We cant seek backwards past the current packet. */
|
||||
if (file->offset > offset)
|
||||
{
|
||||
nb = sock->packs.first->nb;
|
||||
return grub_netbuff_push (nb, file->offset - offset);
|
||||
if (file->device->net->offset > offset)
|
||||
{
|
||||
grub_err_t err;
|
||||
while (file->device->net->packs.first)
|
||||
{
|
||||
grub_netbuff_free (file->device->net->packs.first->nb);
|
||||
grub_net_remove_packet (file->device->net->packs.first);
|
||||
}
|
||||
file->device->net->protocol->close (file);
|
||||
|
||||
file->device->net->packs.first = NULL;
|
||||
file->device->net->packs.last = NULL;
|
||||
file->device->net->offset = 0;
|
||||
file->device->net->eof = 0;
|
||||
err = file->device->net->protocol->open (file, file->device->net->name);
|
||||
if (err)
|
||||
return err;
|
||||
len = offset;
|
||||
}
|
||||
|
||||
grub_net_fs_read (file, NULL, len);
|
||||
grub_net_fs_read_real (file, NULL, len);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static char *
|
||||
grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
|
||||
const char *val __attribute__ ((unused)))
|
||||
static grub_ssize_t
|
||||
grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
set_env_limn_ro (const char *intername, const char *suffix,
|
||||
char *value, grub_size_t len)
|
||||
{
|
||||
char c;
|
||||
char varname[sizeof ("net_") + grub_strlen (intername) + sizeof ("_")
|
||||
+ grub_strlen (suffix)];
|
||||
grub_snprintf (varname, sizeof (varname), "net_%s_%s", intername, suffix);
|
||||
c = value[len];
|
||||
value[len] = 0;
|
||||
grub_env_set (varname, value);
|
||||
value[len] = c;
|
||||
grub_register_variable_hook (varname, 0, grub_env_write_readonly);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_dhcp_vendor (const char *name, void *vend, int limit)
|
||||
{
|
||||
grub_uint8_t *ptr, *ptr0;
|
||||
|
||||
ptr = ptr0 = vend;
|
||||
|
||||
if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) != GRUB_NET_BOOTP_RFC1048_MAGIC)
|
||||
return;
|
||||
ptr = ptr + sizeof (grub_uint32_t);
|
||||
while (ptr - ptr0 < limit)
|
||||
if (file->offset != file->device->net->offset)
|
||||
{
|
||||
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 (name, "hostname", (char *) ptr, taglength);
|
||||
break;
|
||||
|
||||
case 15:
|
||||
set_env_limn_ro (name, "domain", (char *) ptr, taglength);
|
||||
break;
|
||||
|
||||
case 17:
|
||||
set_env_limn_ro (name, "rootpath", (char *) ptr, taglength);
|
||||
break;
|
||||
|
||||
case 18:
|
||||
set_env_limn_ro (name, "extensionspath", (char *) ptr, taglength);
|
||||
break;
|
||||
|
||||
/* If you need any other options please contact GRUB
|
||||
developpement team. */
|
||||
}
|
||||
|
||||
ptr += taglength;
|
||||
grub_err_t err;
|
||||
err = grub_net_seek_real (file, file->offset);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
#define OFFSET_OF(x, y) ((grub_uint8_t *)((y)->x) - (grub_uint8_t *)(y))
|
||||
|
||||
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)
|
||||
{
|
||||
grub_net_network_level_address_t addr;
|
||||
grub_net_link_level_address_t hwaddr;
|
||||
struct grub_net_network_level_interface *inter;
|
||||
|
||||
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||
addr.ipv4 = bp->your_ip;
|
||||
|
||||
grub_memcpy (hwaddr.mac, bp->mac_addr,
|
||||
bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len
|
||||
: sizeof (hwaddr.mac));
|
||||
hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||
|
||||
inter = grub_net_add_addr (name, card, addr, hwaddr, flags);
|
||||
if (bp->gateway_ip != bp->server_ip)
|
||||
{
|
||||
grub_net_network_level_netaddress_t target;
|
||||
grub_net_network_level_address_t gw;
|
||||
char rname[grub_strlen (name) + sizeof ("_gw")];
|
||||
|
||||
target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||
target.ipv4.base = bp->server_ip;
|
||||
target.ipv4.masksize = 32;
|
||||
gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||
gw.ipv4 = bp->gateway_ip;
|
||||
grub_snprintf (rname, sizeof (rname), "%s_gw", name);
|
||||
grub_net_add_route_gw (rname, target, gw);
|
||||
}
|
||||
{
|
||||
grub_net_network_level_netaddress_t target;
|
||||
target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||
target.ipv4.base = bp->gateway_ip;
|
||||
target.ipv4.masksize = 32;
|
||||
grub_net_add_route (name, target, inter);
|
||||
}
|
||||
|
||||
if (size > OFFSET_OF (boot_file, bp))
|
||||
set_env_limn_ro (name, "boot_file", (char *) bp->boot_file,
|
||||
sizeof (bp->boot_file));
|
||||
if (size > OFFSET_OF (server_name, bp))
|
||||
set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name,
|
||||
sizeof (bp->server_name));
|
||||
if (size > OFFSET_OF (vendor, bp))
|
||||
parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp));
|
||||
|
||||
inter->dhcp_ack = grub_malloc (size);
|
||||
if (inter->dhcp_ack)
|
||||
{
|
||||
grub_memcpy (inter->dhcp_ack, bp, size);
|
||||
inter->dhcp_acklen = size;
|
||||
}
|
||||
else
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
return inter;
|
||||
}
|
||||
|
||||
void
|
||||
grub_net_process_dhcp (struct grub_net_buff *nb,
|
||||
const struct grub_net_card *card)
|
||||
{
|
||||
char *name;
|
||||
struct grub_net_network_level_interface *inf;
|
||||
|
||||
name = grub_xasprintf ("%s:dhcp", card->name);
|
||||
if (!name)
|
||||
{
|
||||
grub_print_error ();
|
||||
return;
|
||||
}
|
||||
grub_net_configure_by_dhcp_ack (name, card,
|
||||
0, (const struct grub_net_bootp_packet *) nb->data,
|
||||
(nb->tail - nb->data));
|
||||
grub_free (name);
|
||||
if (grub_errno)
|
||||
grub_print_error ();
|
||||
else
|
||||
{
|
||||
FOR_NET_NETWORK_LEVEL_INTERFACES(inf)
|
||||
if (grub_memcmp (inf->name, card->name, grub_strlen (card->name)) == 0
|
||||
&& grub_memcmp (inf->name + grub_strlen (card->name),
|
||||
":dhcp_tmp", sizeof (":dhcp_tmp") - 1) == 0)
|
||||
{
|
||||
grub_net_network_level_interface_unregister (inf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char
|
||||
hexdigit (grub_uint8_t val)
|
||||
{
|
||||
if (val < 10)
|
||||
return val + '0';
|
||||
return val + 'a' - 10;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_net_network_level_interface *inter;
|
||||
int num;
|
||||
grub_uint8_t *ptr;
|
||||
grub_uint8_t taglength;
|
||||
|
||||
if (argc < 4)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "4 arguments expected");
|
||||
|
||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
|
||||
if (grub_strcmp (inter->name, args[1]) == 0)
|
||||
break;
|
||||
|
||||
if (!inter)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("unrecognised interface %s"), args[1]);
|
||||
|
||||
if (!inter->dhcp_ack)
|
||||
return grub_error (GRUB_ERR_IO, N_("no DHCP info found"));
|
||||
|
||||
if (inter->dhcp_acklen <= OFFSET_OF (vendor, inter->dhcp_ack))
|
||||
return grub_error (GRUB_ERR_IO, N_("no DHCP options found"));
|
||||
|
||||
num = grub_strtoul (args[2], 0, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
|
||||
ptr = inter->dhcp_ack->vendor;
|
||||
|
||||
if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr)
|
||||
!= GRUB_NET_BOOTP_RFC1048_MAGIC)
|
||||
return grub_error (GRUB_ERR_IO, N_("no DHCP options found"));
|
||||
ptr = ptr + sizeof (grub_uint32_t);
|
||||
while (1)
|
||||
{
|
||||
grub_uint8_t tagtype;
|
||||
|
||||
if (ptr >= ((grub_uint8_t *) inter->dhcp_ack) + inter->dhcp_acklen)
|
||||
return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num);
|
||||
|
||||
tagtype = *ptr++;
|
||||
|
||||
/* Pad tag. */
|
||||
if (tagtype == 0)
|
||||
continue;
|
||||
|
||||
/* End tag. */
|
||||
if (tagtype == 0xff)
|
||||
return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num);
|
||||
|
||||
taglength = *ptr++;
|
||||
|
||||
if (tagtype == num)
|
||||
break;
|
||||
ptr += taglength;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[3], "string") == 0)
|
||||
{
|
||||
char *val = grub_malloc (taglength + 1);
|
||||
if (!val)
|
||||
return grub_errno;
|
||||
grub_memcpy (val, ptr, taglength);
|
||||
val[taglength] = 0;
|
||||
if (args[0][0] == '-' && args[0][1] == 0)
|
||||
grub_printf ("%s\n", val);
|
||||
else
|
||||
return grub_env_set (args[0], val);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[3], "number") == 0)
|
||||
{
|
||||
grub_uint64_t val = 0;
|
||||
int i;
|
||||
for (i = 0; i < taglength; i++)
|
||||
val = (val << 8) | ptr[i];
|
||||
if (args[0][0] == '-' && args[0][1] == 0)
|
||||
grub_printf ("%llu\n", (unsigned long long) val);
|
||||
else
|
||||
{
|
||||
char valn[64];
|
||||
grub_printf (valn, sizeof (valn), "%lld\n", (unsigned long long) val);
|
||||
return grub_env_set (args[0], valn);
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[3], "hex") == 0)
|
||||
{
|
||||
char *val = grub_malloc (2 * taglength + 1);
|
||||
int i;
|
||||
if (!val)
|
||||
return grub_errno;
|
||||
for (i = 0; i < taglength; i++)
|
||||
{
|
||||
val[2 * i] = hexdigit (ptr[i] >> 4);
|
||||
val[2 * i + 1] = hexdigit (ptr[i] & 0xf);
|
||||
}
|
||||
val[2 * taglength] = 0;
|
||||
if (args[0][0] == '-' && args[0][1] == 0)
|
||||
grub_printf ("%s\n", val);
|
||||
else
|
||||
return grub_env_set (args[0], val);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"unrecognised format specification %s", args[3]);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_net_card *card;
|
||||
struct grub_net_network_level_interface *ifaces;
|
||||
grub_size_t ncards = 0;
|
||||
unsigned j = 0;
|
||||
int interval;
|
||||
grub_err_t err;
|
||||
|
||||
FOR_NET_CARDS (card)
|
||||
{
|
||||
if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
|
||||
continue;
|
||||
ncards++;
|
||||
}
|
||||
|
||||
ifaces = grub_zalloc (ncards * sizeof (ifaces[0]));
|
||||
if (!ifaces)
|
||||
return grub_errno;
|
||||
|
||||
j = 0;
|
||||
FOR_NET_CARDS (card)
|
||||
{
|
||||
if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
|
||||
continue;
|
||||
ifaces[j].card = card;
|
||||
ifaces[j].next = &ifaces[j+1];
|
||||
if (j)
|
||||
ifaces[j].prev = &ifaces[j-1].next;
|
||||
ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name);
|
||||
if (!ifaces[j].name)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < j; i++)
|
||||
grub_free (ifaces[i].name);
|
||||
grub_free (ifaces);
|
||||
return grub_errno;
|
||||
}
|
||||
ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC;
|
||||
grub_memcpy (&ifaces[j].hwaddress, &card->default_address,
|
||||
sizeof (ifaces[j].hwaddress));
|
||||
j++;
|
||||
}
|
||||
ifaces[ncards - 1].next = grub_net_network_level_interfaces;
|
||||
if (grub_net_network_level_interfaces)
|
||||
grub_net_network_level_interfaces->prev = & ifaces[ncards - 1].next;
|
||||
grub_net_network_level_interfaces = &ifaces[0];
|
||||
ifaces[0].prev = &grub_net_network_level_interfaces;
|
||||
for (interval = 200; interval < 10000; interval *= 2)
|
||||
{
|
||||
int done = 0;
|
||||
for (j = 0; j < ncards; j++)
|
||||
{
|
||||
struct grub_net_bootp_packet *pack;
|
||||
struct grub_datetime date;
|
||||
grub_int32_t t;
|
||||
struct grub_net_buff *nb;
|
||||
struct udphdr *udph;
|
||||
grub_net_network_level_address_t target;
|
||||
|
||||
if (!ifaces[j].prev)
|
||||
continue;
|
||||
nb = grub_netbuff_alloc (sizeof (*pack));
|
||||
if (!nb)
|
||||
return grub_errno;
|
||||
err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128);
|
||||
if (err)
|
||||
return err;
|
||||
err = grub_netbuff_push (nb, sizeof (*pack) + 64);
|
||||
if (err)
|
||||
return err;
|
||||
pack = (void *) nb->data;
|
||||
done = 1;
|
||||
grub_memset (pack, 0, sizeof (*pack) + 64);
|
||||
pack->opcode = 1;
|
||||
pack->hw_type = 1;
|
||||
pack->hw_len = 6;
|
||||
err = grub_get_datetime (&date);
|
||||
if (err || !grub_datetime2unixtime (&date, &t))
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
t = 0;
|
||||
}
|
||||
pack->ident = grub_cpu_to_be32 (t);
|
||||
pack->seconds = 0;//grub_cpu_to_be16 (t);
|
||||
|
||||
grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6);
|
||||
|
||||
grub_netbuff_push (nb, sizeof (*udph));
|
||||
|
||||
udph = (struct udphdr *) nb->data;
|
||||
udph->src = grub_cpu_to_be16 (68);
|
||||
udph->dst = grub_cpu_to_be16 (67);
|
||||
udph->chksum = 0;
|
||||
udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
|
||||
|
||||
target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||
target.ipv4 = 0xffffffff;
|
||||
|
||||
err = grub_net_send_ip_packet (&ifaces[j], &target, nb);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (!done)
|
||||
break;
|
||||
grub_net_poll_cards (interval);
|
||||
}
|
||||
|
||||
err = GRUB_ERR_NONE;
|
||||
for (j = 0; j < ncards; j++)
|
||||
{
|
||||
if (!ifaces[j].prev)
|
||||
continue;
|
||||
grub_error_push ();
|
||||
grub_net_network_level_interface_unregister (&ifaces[j]);
|
||||
err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s",
|
||||
ifaces[j].card->name);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_grubnet_fini_real (void)
|
||||
{
|
||||
struct grub_net_card *card;
|
||||
|
||||
FOR_NET_CARDS (card)
|
||||
if (card->driver)
|
||||
card->driver->fini (card);
|
||||
return grub_net_fs_read_real (file, buf, len);
|
||||
}
|
||||
|
||||
static struct grub_fs grub_net_fs =
|
||||
|
@ -1255,9 +916,32 @@ static struct grub_fs grub_net_fs =
|
|||
.uuid = NULL,
|
||||
.mtime = NULL,
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_net_fini_hw (int noreturn __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_net_card *card;
|
||||
FOR_NET_CARDS (card)
|
||||
if (card->opened)
|
||||
{
|
||||
if (card->driver->close)
|
||||
card->driver->close (card);
|
||||
card->opened = 0;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_net_restore_hw (void)
|
||||
{
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static void *fini_hnd;
|
||||
|
||||
static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute;
|
||||
static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp, cmd_bootp;
|
||||
static grub_command_t cmd_dhcp, cmd_lsaddr;
|
||||
static grub_command_t cmd_lsroutes, cmd_lscards;
|
||||
static grub_command_t cmd_lsaddr;
|
||||
|
||||
GRUB_MOD_INIT(net)
|
||||
{
|
||||
|
@ -1279,24 +963,19 @@ GRUB_MOD_INIT(net)
|
|||
"", N_("list network cards"));
|
||||
cmd_lsaddr = grub_register_command ("net_ls_addr", grub_cmd_listaddrs,
|
||||
"", N_("list network addresses"));
|
||||
cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp,
|
||||
"[CARD]",
|
||||
N_("perform a bootp autoconfiguration"));
|
||||
cmd_dhcp = grub_register_command ("net_dhcp", grub_cmd_bootp,
|
||||
"[CARD]",
|
||||
N_("perform a bootp autoconfiguration"));
|
||||
cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt,
|
||||
N_("VAR INTERFACE NUMBER DESCRIPTION"),
|
||||
N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value."));
|
||||
grub_bootp_init ();
|
||||
|
||||
grub_fs_register (&grub_net_fs);
|
||||
grub_net_open = grub_net_open_real;
|
||||
grub_file_net_seek = grub_net_seek_real;
|
||||
grub_grubnet_fini = grub_grubnet_fini_real;
|
||||
fini_hnd = grub_loader_register_preboot_hook (grub_net_fini_hw,
|
||||
grub_net_restore_hw,
|
||||
GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
|
||||
grub_net_poll_cards_idle = grub_net_poll_cards_idle_real;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(net)
|
||||
{
|
||||
grub_bootp_fini ();
|
||||
grub_unregister_command (cmd_addaddr);
|
||||
grub_unregister_command (cmd_deladdr);
|
||||
grub_unregister_command (cmd_addroute);
|
||||
|
@ -1304,9 +983,9 @@ GRUB_MOD_FINI(net)
|
|||
grub_unregister_command (cmd_lsroutes);
|
||||
grub_unregister_command (cmd_lscards);
|
||||
grub_unregister_command (cmd_lsaddr);
|
||||
grub_unregister_command (cmd_getdhcp);
|
||||
grub_fs_unregister (&grub_net_fs);
|
||||
grub_net_open = NULL;
|
||||
grub_file_net_seek = NULL;
|
||||
grub_grubnet_fini = NULL;
|
||||
grub_net_fini_hw (0);
|
||||
grub_loader_unregister_preboot_hook (fini_hnd);
|
||||
grub_net_poll_cards_idle = grub_net_poll_cards_idle_real;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,22 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010,2011 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/misc.h>
|
||||
#include <grub/net/tftp.h>
|
||||
#include <grub/net/udp.h>
|
||||
#include <grub/net/ip.h>
|
||||
#include <grub/net/ethernet.h>
|
||||
|
@ -11,6 +28,180 @@
|
|||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/* IP port for the MTFTP server used for Intel's PXE */
|
||||
enum
|
||||
{
|
||||
MTFTP_SERVER_PORT = 75,
|
||||
MTFTP_CLIENT_PORT = 76,
|
||||
/* IP port for the TFTP server */
|
||||
TFTP_SERVER_PORT = 69
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
TFTP_DEFAULTSIZE_PACKET = 512,
|
||||
TFTP_MAX_PACKET = 1432
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
TFTP_CODE_EOF = 1,
|
||||
TFTP_CODE_MORE = 2,
|
||||
TFTP_CODE_ERROR = 3,
|
||||
TFTP_CODE_BOOT = 4,
|
||||
TFTP_CODE_CFG = 5
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
TFTP_RRQ = 1,
|
||||
TFTP_WRQ = 2,
|
||||
TFTP_DATA = 3,
|
||||
TFTP_ACK = 4,
|
||||
TFTP_ERROR = 5,
|
||||
TFTP_OACK = 6
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
TFTP_EUNDEF = 0, /* not defined */
|
||||
TFTP_ENOTFOUND = 1, /* file not found */
|
||||
TFTP_EACCESS = 2, /* access violation */
|
||||
TFTP_ENOSPACE = 3, /* disk full or allocation exceeded */
|
||||
TFTP_EBADOP = 4, /* illegal TFTP operation */
|
||||
TFTP_EBADID = 5, /* unknown transfer ID */
|
||||
TFTP_EEXISTS = 6, /* file already exists */
|
||||
TFTP_ENOUSER = 7 /* no such user */
|
||||
};
|
||||
|
||||
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)) ;
|
||||
|
||||
|
||||
typedef struct tftp_data
|
||||
{
|
||||
grub_uint64_t file_size;
|
||||
grub_uint64_t block;
|
||||
grub_uint32_t block_size;
|
||||
int have_oack;
|
||||
grub_net_socket_t sock;
|
||||
} *tftp_data_t;
|
||||
|
||||
static grub_err_t
|
||||
tftp_receive (grub_net_socket_t sock __attribute__ ((unused)),
|
||||
struct grub_net_buff *nb,
|
||||
void *f)
|
||||
{
|
||||
grub_file_t file = f;
|
||||
struct tftphdr *tftph = (void *) nb->data;
|
||||
char nbdata[512];
|
||||
tftp_data_t data = file->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:
|
||||
data->block_size = TFTP_DEFAULTSIZE_PACKET;
|
||||
data->have_oack = 1;
|
||||
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);
|
||||
}
|
||||
if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0)
|
||||
{
|
||||
data->block_size = grub_strtoul (ptr + sizeof ("blksize\0") - 1,
|
||||
0, 0);
|
||||
}
|
||||
while (ptr < nb->tail && *ptr)
|
||||
ptr++;
|
||||
ptr++;
|
||||
}
|
||||
data->block = 0;
|
||||
grub_netbuff_free (nb);
|
||||
break;
|
||||
case TFTP_DATA:
|
||||
err = grub_netbuff_pull (nb, sizeof (tftph->opcode) +
|
||||
sizeof (tftph->u.data.block));
|
||||
if (err)
|
||||
return err;
|
||||
if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1)
|
||||
{
|
||||
unsigned size = nb->tail - nb->data;
|
||||
data->block++;
|
||||
if (size < data->block_size)
|
||||
{
|
||||
file->device->net->eof = 1;
|
||||
}
|
||||
/* Prevent garbage in broken cards. */
|
||||
if (size > data->block_size)
|
||||
{
|
||||
err = grub_netbuff_unput (nb, size - data->block_size);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
/* If there is data, puts packet in socket list. */
|
||||
if ((nb->tail - nb->data) > 0)
|
||||
grub_net_put_packet (&file->device->net->packs, nb);
|
||||
else
|
||||
grub_netbuff_free (nb);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
break;
|
||||
case TFTP_ERROR:
|
||||
grub_netbuff_free (nb);
|
||||
return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg);
|
||||
}
|
||||
grub_netbuff_clear (&nb_ack);
|
||||
grub_netbuff_reserve (&nb_ack, 512);
|
||||
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 (data->sock, &nb_ack);
|
||||
if (file->device->net->eof)
|
||||
{
|
||||
grub_net_udp_close (data->sock);
|
||||
data->sock = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
tftp_open (struct grub_file *file, const char *filename)
|
||||
{
|
||||
|
@ -24,17 +215,17 @@ tftp_open (struct grub_file *file, const char *filename)
|
|||
tftp_data_t data;
|
||||
grub_err_t err;
|
||||
|
||||
data = grub_malloc (sizeof (*data));
|
||||
data = grub_zalloc (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)
|
||||
err = grub_netbuff_push (&nb, sizeof (*tftph));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
tftph = (struct tftphdr *) nb.data;
|
||||
|
@ -68,111 +259,86 @@ tftp_open (struct grub_file *file, const char *filename)
|
|||
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);
|
||||
err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
file->not_easily_seekable = 1;
|
||||
file->data = data;
|
||||
data->sock = grub_net_udp_open (file->device->net->server,
|
||||
TFTP_SERVER_PORT, tftp_receive,
|
||||
file);
|
||||
if (!data->sock)
|
||||
return grub_errno;
|
||||
|
||||
err = grub_net_send_udp_packet (data->sock, &nb);
|
||||
if (err)
|
||||
{
|
||||
grub_net_udp_close (data->sock);
|
||||
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)
|
||||
if (data->have_oack)
|
||||
break;
|
||||
/* Retry. */
|
||||
/*err = grub_net_send_udp_packet (file->device->net->socket, &nb);
|
||||
if (err)
|
||||
return err; */
|
||||
err = grub_net_send_udp_packet (data->sock, &nb);
|
||||
if (err)
|
||||
{
|
||||
grub_net_udp_close (data->sock);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (file->device->net->socket->status == 0)
|
||||
return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp.");
|
||||
if (!data->have_oack)
|
||||
{
|
||||
grub_net_udp_close (data->sock);
|
||||
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)
|
||||
tftp_close (struct grub_file *file)
|
||||
{
|
||||
struct tftphdr *tftph;
|
||||
char nbdata[128];
|
||||
tftp_data_t data = sock->data;
|
||||
grub_err_t err;
|
||||
char *ptr;
|
||||
struct grub_net_buff nb_ack;
|
||||
tftp_data_t data = file->data;
|
||||
|
||||
nb_ack.head = nbdata;
|
||||
nb_ack.end = nbdata + sizeof (nbdata);
|
||||
|
||||
|
||||
tftph = (struct tftphdr *) nb->data;
|
||||
switch (grub_be_to_cpu16 (tftph->opcode))
|
||||
if (data->sock)
|
||||
{
|
||||
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);
|
||||
char nbdata[512];
|
||||
grub_err_t err;
|
||||
struct grub_net_buff nb_err;
|
||||
struct tftphdr *tftph;
|
||||
|
||||
break;
|
||||
case TFTP_ERROR:
|
||||
grub_netbuff_clear (nb);
|
||||
return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg);
|
||||
break;
|
||||
nb_err.head = nbdata;
|
||||
nb_err.end = nbdata + sizeof (nbdata);
|
||||
|
||||
grub_netbuff_clear (&nb_err);
|
||||
grub_netbuff_reserve (&nb_err, 512);
|
||||
err = grub_netbuff_push (&nb_err, sizeof (tftph->opcode)
|
||||
+ sizeof (tftph->u.err.errcode)
|
||||
+ sizeof ("closed"));
|
||||
if (!err)
|
||||
{
|
||||
tftph = (struct tftphdr *) nb_err.data;
|
||||
tftph->opcode = grub_cpu_to_be16 (TFTP_ERROR);
|
||||
tftph->u.err.errcode = grub_cpu_to_be16 (TFTP_EUNDEF);
|
||||
grub_memcpy (tftph->u.err.errmsg, "closed", sizeof ("closed"));
|
||||
|
||||
err = grub_net_send_udp_packet (data->sock, &nb_err);
|
||||
}
|
||||
if (err)
|
||||
grub_print_error ();
|
||||
grub_net_udp_close (data->sock);
|
||||
}
|
||||
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);
|
||||
grub_free (data);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -180,7 +346,6 @@ static struct grub_net_app_protocol grub_tftp_protocol =
|
|||
{
|
||||
.name = "tftp",
|
||||
.open = tftp_open,
|
||||
.read = tftp_receive,
|
||||
.close = tftp_close
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,46 @@
|
|||
#include <grub/net/netbuff.h>
|
||||
#include <grub/time.h>
|
||||
|
||||
grub_net_socket_t
|
||||
grub_net_udp_open (char *server,
|
||||
grub_uint16_t out_port,
|
||||
grub_err_t (*recv_hook) (grub_net_socket_t sock,
|
||||
struct grub_net_buff *nb,
|
||||
void *data),
|
||||
void *recv_hook_data)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_net_network_level_address_t addr;
|
||||
struct grub_net_network_level_interface *inf;
|
||||
grub_net_network_level_address_t gateway;
|
||||
grub_net_socket_t socket;
|
||||
static int in_port = 25300;
|
||||
|
||||
err = grub_net_resolve_address (server, &addr);
|
||||
if (err)
|
||||
return NULL;
|
||||
|
||||
err = grub_net_route_address (addr, &gateway, &inf);
|
||||
if (err)
|
||||
return NULL;
|
||||
|
||||
socket = grub_zalloc (sizeof (*socket));
|
||||
if (socket == NULL)
|
||||
return NULL;
|
||||
|
||||
socket->x_out_port = out_port;
|
||||
socket->x_inf = inf;
|
||||
socket->x_out_nla = addr;
|
||||
socket->x_in_port = in_port++;
|
||||
socket->x_status = GRUB_NET_SOCKET_START;
|
||||
socket->recv_hook = recv_hook;
|
||||
socket->recv_hook_data = recv_hook_data;
|
||||
|
||||
grub_net_socket_register (socket);
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_net_send_udp_packet (const grub_net_socket_t socket,
|
||||
struct grub_net_buff *nb)
|
||||
|
@ -16,14 +56,14 @@ grub_net_send_udp_packet (const grub_net_socket_t socket,
|
|||
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);
|
||||
udph->src = grub_cpu_to_be16 (socket->x_in_port);
|
||||
udph->dst = grub_cpu_to_be16 (socket->x_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);
|
||||
return grub_net_send_ip_packet (socket->x_inf, &(socket->x_out_nla), nb);
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
|
@ -32,30 +72,28 @@ grub_net_recv_udp_packet (struct grub_net_buff * nb,
|
|||
{
|
||||
struct udphdr *udph;
|
||||
grub_net_socket_t sock;
|
||||
grub_err_t err;
|
||||
udph = (struct udphdr *) nb->data;
|
||||
grub_netbuff_pull (nb, sizeof (*udph));
|
||||
err = grub_netbuff_pull (nb, sizeof (*udph));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
FOR_NET_SOCKETS (sock)
|
||||
{
|
||||
if (grub_be_to_cpu16 (udph->dst) == sock->in_port
|
||||
&& inf == sock->inf && sock->app)
|
||||
if (grub_be_to_cpu16 (udph->dst) == sock->x_in_port
|
||||
&& inf == sock->x_inf && sock->recv_hook)
|
||||
{
|
||||
if (sock->status == 0)
|
||||
sock->out_port = grub_be_to_cpu16 (udph->src);
|
||||
if (sock->x_status == GRUB_NET_SOCKET_START)
|
||||
{
|
||||
sock->x_out_port = grub_be_to_cpu16 (udph->src);
|
||||
sock->x_status = GRUB_NET_SOCKET_ESTABLISHED;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
sock->recv_hook (sock, nb, sock->recv_hook_data);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -84,6 +84,16 @@
|
|||
{ 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
|
||||
}
|
||||
|
||||
#define GRUB_EFI_SIMPLE_NETWORK_GUID \
|
||||
{ 0xa19832b9, 0xac25, 0x11d3, \
|
||||
{ 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
|
||||
}
|
||||
|
||||
#define GRUB_EFI_PXE_GUID \
|
||||
{ 0x03c4e603, 0xac28, 0x11d3, \
|
||||
{ 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
|
||||
}
|
||||
|
||||
#define GRUB_EFI_DEVICE_PATH_GUID \
|
||||
{ 0x09576e91, 0x6d3f, 0x11d2, \
|
||||
{ 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
|
||||
|
@ -1113,6 +1123,36 @@ struct grub_efi_simple_text_output_interface
|
|||
};
|
||||
typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t;
|
||||
|
||||
typedef grub_uint8_t grub_efi_pxe_packet_t[1472];
|
||||
|
||||
typedef struct grub_efi_pxe_mode
|
||||
{
|
||||
grub_uint8_t unused[52];
|
||||
grub_efi_pxe_packet_t dhcp_discover;
|
||||
grub_efi_pxe_packet_t dhcp_ack;
|
||||
grub_efi_pxe_packet_t proxy_offer;
|
||||
grub_efi_pxe_packet_t pxe_discover;
|
||||
grub_efi_pxe_packet_t pxe_reply;
|
||||
} grub_efi_pxe_mode_t;
|
||||
|
||||
typedef struct grub_efi_pxe
|
||||
{
|
||||
grub_uint64_t rev;
|
||||
void (*start) (void);
|
||||
void (*stop) (void);
|
||||
void (*dhcp) (void);
|
||||
void (*discover) (void);
|
||||
void (*mftp) (void);
|
||||
void (*udpwrite) (void);
|
||||
void (*udpread) (void);
|
||||
void (*setipfilter) (void);
|
||||
void (*arp) (void);
|
||||
void (*setparams) (void);
|
||||
void (*setstationip) (void);
|
||||
void (*setpackets) (void);
|
||||
struct grub_efi_pxe_mode *mode;
|
||||
} grub_efi_pxe_t;
|
||||
|
||||
#define GRUB_EFI_BLACK 0x00
|
||||
#define GRUB_EFI_BLUE 0x01
|
||||
#define GRUB_EFI_GREEN 0x02
|
||||
|
@ -1214,6 +1254,74 @@ struct grub_efi_block_io_media
|
|||
};
|
||||
typedef struct grub_efi_block_io_media grub_efi_block_io_media_t;
|
||||
|
||||
typedef grub_uint8_t grub_efi_mac_t[32];
|
||||
|
||||
struct grub_efi_simple_network_mode
|
||||
{
|
||||
grub_uint32_t state;
|
||||
grub_uint32_t hwaddr_size;
|
||||
grub_uint32_t media_header_size;
|
||||
grub_uint32_t max_packet_size;
|
||||
grub_uint32_t nvram_size;
|
||||
grub_uint32_t nvram_access_size;
|
||||
grub_uint32_t receive_filter_mask;
|
||||
grub_uint32_t receive_filter_setting;
|
||||
grub_uint32_t max_mcast_filter_count;
|
||||
grub_uint32_t mcast_filter_count;
|
||||
grub_efi_mac_t mcast_filter[16];
|
||||
grub_efi_mac_t current_address;
|
||||
grub_efi_mac_t broadcast_address;
|
||||
grub_efi_mac_t permanent_address;
|
||||
grub_uint8_t if_type;
|
||||
grub_uint8_t mac_changeable;
|
||||
grub_uint8_t multitx_supported;
|
||||
grub_uint8_t media_present_supported;
|
||||
grub_uint8_t media_present;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_EFI_NETWORK_STOPPED,
|
||||
GRUB_EFI_NETWORK_STARTED,
|
||||
GRUB_EFI_NETWORK_INITIALIZED,
|
||||
};
|
||||
|
||||
struct grub_efi_simple_network
|
||||
{
|
||||
grub_uint64_t revision;
|
||||
grub_efi_status_t (*start) (struct grub_efi_simple_network *this);
|
||||
void (*stop) (void);
|
||||
grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this,
|
||||
grub_efi_uintn_t extra_rx,
|
||||
grub_efi_uintn_t extra_tx);
|
||||
void (*reset) (void);
|
||||
void (*shutdown) (void);
|
||||
void (*receive_filters) (void);
|
||||
void (*station_address) (void);
|
||||
void (*statistics) (void);
|
||||
void (*mcastiptomac) (void);
|
||||
void (*nvdata) (void);
|
||||
void (*getstatus) (void);
|
||||
grub_efi_status_t (*transmit) (struct grub_efi_simple_network *this,
|
||||
grub_efi_uintn_t header_size,
|
||||
grub_efi_uintn_t buffer_size,
|
||||
void *buffer,
|
||||
grub_efi_mac_t *src_addr,
|
||||
grub_efi_mac_t *dest_addr,
|
||||
grub_efi_uint16_t *protocol);
|
||||
grub_efi_status_t (*receive) (struct grub_efi_simple_network *this,
|
||||
grub_efi_uintn_t *header_size,
|
||||
grub_efi_uintn_t *buffer_size,
|
||||
void *buffer,
|
||||
grub_efi_mac_t *src_addr,
|
||||
grub_efi_mac_t *dest_addr,
|
||||
grub_uint16_t *protocol);
|
||||
void (*waitforpacket) (void);
|
||||
struct grub_efi_simple_network_mode *mode;
|
||||
};
|
||||
typedef struct grub_efi_simple_network grub_efi_simple_network_t;
|
||||
|
||||
|
||||
struct grub_efi_block_io
|
||||
{
|
||||
grub_efi_uint64_t revision;
|
||||
|
@ -1243,6 +1351,7 @@ typedef struct grub_efi_block_io grub_efi_block_io_t;
|
|||
#define efi_call_4(func, a, b, c, d) func(a, b, c, d)
|
||||
#define efi_call_5(func, a, b, c, d, e) func(a, b, c, d, e)
|
||||
#define efi_call_6(func, a, b, c, d, e, f) func(a, b, c, d, e, f)
|
||||
#define efi_call_7(func, a, b, c, d, e, f, g) func(a, b, c, d, e, f, g)
|
||||
#define efi_call_10(func, a, b, c, d, e, f, g, h, i, j) func(a, b, c, d, e, f, g, h, i, j)
|
||||
|
||||
#else
|
||||
|
@ -1250,24 +1359,31 @@ typedef struct grub_efi_block_io grub_efi_block_io_t;
|
|||
#define efi_call_0(func) \
|
||||
efi_wrap_0(func)
|
||||
#define efi_call_1(func, a) \
|
||||
efi_wrap_1(func, (grub_uint64_t) a)
|
||||
efi_wrap_1(func, (grub_uint64_t) (a))
|
||||
#define efi_call_2(func, a, b) \
|
||||
efi_wrap_2(func, (grub_uint64_t) a, (grub_uint64_t) b)
|
||||
efi_wrap_2(func, (grub_uint64_t) (a), (grub_uint64_t) (b))
|
||||
#define efi_call_3(func, a, b, c) \
|
||||
efi_wrap_3(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c)
|
||||
efi_wrap_3(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
|
||||
(grub_uint64_t) (c))
|
||||
#define efi_call_4(func, a, b, c, d) \
|
||||
efi_wrap_4(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \
|
||||
(grub_uint64_t) d)
|
||||
efi_wrap_4(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
|
||||
(grub_uint64_t) (c), (grub_uint64_t) (d))
|
||||
#define efi_call_5(func, a, b, c, d, e) \
|
||||
efi_wrap_5(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \
|
||||
(grub_uint64_t) d, (grub_uint64_t) e)
|
||||
efi_wrap_5(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
|
||||
(grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e))
|
||||
#define efi_call_6(func, a, b, c, d, e, f) \
|
||||
efi_wrap_6(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \
|
||||
(grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f)
|
||||
efi_wrap_6(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
|
||||
(grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \
|
||||
(grub_uint64_t) (f))
|
||||
#define efi_call_7(func, a, b, c, d, e, f, g) \
|
||||
efi_wrap_7(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
|
||||
(grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \
|
||||
(grub_uint64_t) (f), (grub_uint64_t) (g))
|
||||
#define efi_call_10(func, a, b, c, d, e, f, g, h, i, j) \
|
||||
efi_wrap_10(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \
|
||||
(grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f, (grub_uint64_t) g, \
|
||||
(grub_uint64_t) h, (grub_uint64_t) i, (grub_uint64_t) j)
|
||||
efi_wrap_10(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
|
||||
(grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \
|
||||
(grub_uint64_t) (f), (grub_uint64_t) (g), (grub_uint64_t) (h), \
|
||||
(grub_uint64_t) (i), (grub_uint64_t) (j))
|
||||
|
||||
grub_uint64_t EXPORT_FUNC(efi_wrap_0) (void *func);
|
||||
grub_uint64_t EXPORT_FUNC(efi_wrap_1) (void *func, grub_uint64_t arg1);
|
||||
|
@ -1285,6 +1401,10 @@ grub_uint64_t EXPORT_FUNC(efi_wrap_6) (void *func, grub_uint64_t arg1,
|
|||
grub_uint64_t arg2, grub_uint64_t arg3,
|
||||
grub_uint64_t arg4, grub_uint64_t arg5,
|
||||
grub_uint64_t arg6);
|
||||
grub_uint64_t EXPORT_FUNC(efi_wrap_7) (void *func, grub_uint64_t arg1,
|
||||
grub_uint64_t arg2, grub_uint64_t arg3,
|
||||
grub_uint64_t arg4, grub_uint64_t arg5,
|
||||
grub_uint64_t arg6, grub_uint64_t arg7);
|
||||
grub_uint64_t EXPORT_FUNC(efi_wrap_10) (void *func, grub_uint64_t arg1,
|
||||
grub_uint64_t arg2, grub_uint64_t arg3,
|
||||
grub_uint64_t arg4, grub_uint64_t arg5,
|
||||
|
|
|
@ -62,6 +62,14 @@ grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memo
|
|||
grub_efi_uint32_t descriptor_version,
|
||||
grub_efi_memory_descriptor_t *virtual_map);
|
||||
|
||||
int
|
||||
EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
|
||||
const grub_efi_device_path_t *dp2);
|
||||
|
||||
extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd,
|
||||
char **device,
|
||||
char **path);
|
||||
|
||||
void grub_efi_mm_init (void);
|
||||
void grub_efi_mm_fini (void);
|
||||
void grub_efi_init (void);
|
||||
|
|
|
@ -44,6 +44,8 @@ extern grub_int32_t grub_install_bsd_part;
|
|||
/* The boot BIOS drive number. */
|
||||
extern grub_uint8_t EXPORT_VAR(grub_boot_drive);
|
||||
|
||||
extern void (*EXPORT_VAR(grub_pc_net_config)) (char **device, char **path);
|
||||
|
||||
#endif /* ! ASM_FILE */
|
||||
|
||||
#endif /* ! KERNEL_MACHINE_HEADER */
|
||||
|
|
|
@ -287,8 +287,6 @@ int EXPORT_FUNC(grub_pxe_call) (int func, void * data, grub_uint32_t pxe_rm_entr
|
|||
|
||||
extern struct grub_pxe_bangpxe *grub_pxe_pxenv;
|
||||
|
||||
void grub_pxe_unload (void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* GRUB_CPU_PXE_H */
|
||||
|
|
|
@ -64,12 +64,9 @@ struct grub_ieee1275_common_hdr
|
|||
typedef grub_uint32_t grub_ieee1275_ihandle_t;
|
||||
typedef grub_uint32_t grub_ieee1275_phandle_t;
|
||||
|
||||
struct grub_ofnetcard_data
|
||||
{
|
||||
char *path;
|
||||
grub_ieee1275_ihandle_t handle;
|
||||
grub_uint32_t mtu;
|
||||
};
|
||||
extern void (*EXPORT_VAR(grub_ieee1275_net_config)) (const char *dev,
|
||||
char **device,
|
||||
char **path);
|
||||
|
||||
/* Maps a device alias to a pathname. */
|
||||
extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen);
|
||||
|
@ -203,5 +200,6 @@ int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook)
|
|||
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_get_device_type) (const char *path);
|
||||
|
||||
#endif /* ! GRUB_IEEE1275_HEADER */
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* 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 */
|
|
@ -84,12 +84,16 @@ void grub_machine_init (void);
|
|||
void EXPORT_FUNC(grub_machine_fini) (void);
|
||||
|
||||
/* The machine-specific prefix initialization. */
|
||||
void grub_machine_set_prefix (void);
|
||||
void
|
||||
grub_machine_get_bootlocation (char **device, char **path);
|
||||
|
||||
/* Register all the exported symbols. This is automatically generated. */
|
||||
void grub_register_exported_symbols (void);
|
||||
|
||||
#if ! defined (ASM_FILE) && !defined (GRUB_MACHINE_EMU)
|
||||
extern void (*EXPORT_VAR(grub_net_poll_cards_idle)) (void);
|
||||
|
||||
|
||||
#if ! defined (ASM_FILE)
|
||||
extern char grub_prefix[];
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2010,2011 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
|
||||
|
@ -60,32 +60,14 @@ 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 (*open) (const struct grub_net_card *dev);
|
||||
void (*close) (const struct grub_net_card *dev);
|
||||
grub_err_t (*send) (const struct grub_net_card *dev,
|
||||
struct grub_net_buff *buf);
|
||||
grub_ssize_t (*recv) (const struct grub_net_card *dev,
|
||||
struct grub_net_buff *buf);
|
||||
};
|
||||
|
||||
extern struct grub_net_card_driver *grub_net_card_drivers;
|
||||
|
||||
static inline void
|
||||
grub_net_card_driver_register (struct grub_net_card_driver *driver)
|
||||
{
|
||||
grub_list_push (GRUB_AS_LIST_P (&grub_net_card_drivers),
|
||||
GRUB_AS_LIST (driver));
|
||||
}
|
||||
|
||||
static inline void
|
||||
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));
|
||||
}
|
||||
|
||||
#define FOR_NET_CARD_DRIVERS(var) for (var = grub_net_card_drivers; var; var = var->next)
|
||||
|
||||
typedef struct grub_net_packet
|
||||
{
|
||||
struct grub_net_packet *next;
|
||||
|
@ -100,6 +82,10 @@ typedef struct grub_net_packets
|
|||
grub_net_packet_t *last;
|
||||
} grub_net_packets_t;
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
#include <grub/efi/api.h>
|
||||
#endif
|
||||
|
||||
struct grub_net_card
|
||||
{
|
||||
struct grub_net_card *next;
|
||||
|
@ -107,8 +93,19 @@ struct grub_net_card
|
|||
struct grub_net_card_driver *driver;
|
||||
grub_net_link_level_address_t default_address;
|
||||
grub_net_card_flags_t flags;
|
||||
int num_ifaces;
|
||||
int opened;
|
||||
unsigned idle_poll_delay_ms;
|
||||
grub_uint64_t last_poll;
|
||||
union
|
||||
{
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
struct
|
||||
{
|
||||
struct grub_efi_simple_network *efi_net;
|
||||
grub_efi_handle_t efi_handle;
|
||||
};
|
||||
#endif
|
||||
void *data;
|
||||
int data_num;
|
||||
};
|
||||
|
@ -118,7 +115,7 @@ struct grub_net_network_level_interface;
|
|||
|
||||
typedef enum grub_network_level_protocol_id
|
||||
{
|
||||
GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC,
|
||||
GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV,
|
||||
GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
|
||||
} grub_network_level_protocol_id_t;
|
||||
|
||||
|
@ -196,22 +193,23 @@ struct grub_net_app_protocol
|
|||
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;
|
||||
|
||||
enum { GRUB_NET_SOCKET_START,
|
||||
GRUB_NET_SOCKET_ESTABLISHED,
|
||||
GRUB_NET_SOCKET_CLOSED } x_status;
|
||||
int x_in_port;
|
||||
int x_out_port;
|
||||
grub_err_t (*recv_hook) (grub_net_socket_t sock, struct grub_net_buff *nb,
|
||||
void *recv);
|
||||
void *recv_hook_data;
|
||||
grub_net_network_level_address_t x_out_nla;
|
||||
struct grub_net_network_level_interface *x_inf;
|
||||
};
|
||||
|
||||
extern struct grub_net_socket *grub_net_sockets;
|
||||
|
@ -234,22 +232,23 @@ grub_net_socket_unregister (grub_net_socket_t sock)
|
|||
|
||||
typedef struct grub_net
|
||||
{
|
||||
char *server;
|
||||
char *name;
|
||||
grub_net_app_level_t protocol;
|
||||
grub_net_socket_t socket;
|
||||
grub_net_packets_t packs;
|
||||
grub_off_t offset;
|
||||
grub_fs_t fs;
|
||||
int eof;
|
||||
} *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;
|
||||
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;
|
||||
|
@ -297,7 +296,7 @@ grub_net_session_recv (struct grub_net_session *session, void *buf,
|
|||
|
||||
struct grub_net_network_level_interface *
|
||||
grub_net_add_addr (const char *name,
|
||||
const struct grub_net_card *card,
|
||||
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);
|
||||
|
@ -334,14 +333,12 @@ grub_net_card_register (struct grub_net_card *card)
|
|||
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));
|
||||
}
|
||||
void
|
||||
grub_net_card_unregister (struct grub_net_card *card);
|
||||
|
||||
#define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next)
|
||||
#define FOR_NET_CARDS_SAFE(var, next) for (var = grub_net_cards, next = var->next; var; var = next, next = var->next)
|
||||
|
||||
|
||||
struct grub_net_session *
|
||||
grub_net_open_tcp (char *address, grub_uint16_t port);
|
||||
|
@ -389,23 +386,27 @@ struct grub_net_bootp_packet
|
|||
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];
|
||||
char server_name[64];
|
||||
char boot_file[128];
|
||||
grub_uint8_t vendor[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define GRUB_NET_BOOTP_RFC1048_MAGIC 0x63825363L
|
||||
#define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63
|
||||
#define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82
|
||||
#define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53
|
||||
#define GRUB_NET_BOOTP_RFC1048_MAGIC_3 0x63
|
||||
|
||||
struct grub_net_network_level_interface *
|
||||
grub_net_configure_by_dhcp_ack (const char *name,
|
||||
const struct grub_net_card *card,
|
||||
struct grub_net_card *card,
|
||||
grub_net_interface_flags_t flags,
|
||||
const struct grub_net_bootp_packet *bp,
|
||||
grub_size_t size);
|
||||
grub_size_t size,
|
||||
int is_def, char **device, char **path);
|
||||
|
||||
void
|
||||
grub_net_process_dhcp (struct grub_net_buff *nb,
|
||||
const struct grub_net_card *card);
|
||||
struct grub_net_card *card);
|
||||
|
||||
int
|
||||
grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a,
|
||||
|
@ -425,31 +426,25 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target,
|
|||
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)
|
||||
#define FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(var,next) for (var = grub_net_network_level_interfaces, next = var->next; var; var = next, next = var->next)
|
||||
|
||||
void
|
||||
grub_net_poll_cards (unsigned time);
|
||||
|
||||
void grub_bootp_init (void);
|
||||
void grub_bootp_fini (void);
|
||||
|
||||
static inline void
|
||||
grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter)
|
||||
{
|
||||
inter->card->num_ifaces--;
|
||||
*inter->prev = inter->next;
|
||||
if (inter->next)
|
||||
inter->next->prev = inter->prev;
|
||||
inter->next = 0;
|
||||
inter->prev = 0;
|
||||
}
|
||||
|
||||
extern char *grub_net_default_server;
|
||||
|
||||
#endif /* ! GRUB_NET_HEADER */
|
||||
|
|
|
@ -1,30 +1,26 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010,2011 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_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
|
||||
{
|
||||
|
@ -32,7 +28,6 @@ enum
|
|||
GRUB_NET_ETHERTYPE_ARP = 0x0806
|
||||
};
|
||||
|
||||
|
||||
grub_err_t
|
||||
send_ethernet_packet (struct grub_net_network_level_interface *inf,
|
||||
struct grub_net_buff *nb,
|
||||
|
|
|
@ -1,35 +1,42 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010,2011 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_NET_IP_HEADER
|
||||
#define GRUB_NET_IP_HEADER 1
|
||||
#include <grub/misc.h>
|
||||
#include <grub/net.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 */
|
||||
enum
|
||||
{
|
||||
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);
|
||||
grub_uint16_t grub_net_ip_chksum(void *ipv, int len);
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
#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
|
|
@ -11,14 +11,28 @@ struct udphdr
|
|||
grub_uint16_t chksum;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
grub_net_socket_t
|
||||
grub_net_udp_open (char *server,
|
||||
grub_uint16_t out_port,
|
||||
grub_err_t (*recv_hook) (grub_net_socket_t sock,
|
||||
struct grub_net_buff *nb,
|
||||
void *data),
|
||||
void *recv_hook_data);
|
||||
|
||||
static inline void
|
||||
grub_net_udp_close (grub_net_socket_t sock)
|
||||
{
|
||||
grub_net_socket_unregister (sock);
|
||||
grub_free (sock);
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb);
|
||||
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
|
||||
|
|
|
@ -169,8 +169,10 @@
|
|||
/* Non-zero value is only needed for PowerMacs. */
|
||||
#define GRUB_KERNEL_I386_IEEE1275_MOD_GAP 0x0
|
||||
#define GRUB_KERNEL_I386_COREBOOT_MOD_GAP 0x0
|
||||
#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP 0x0
|
||||
|
||||
#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000
|
||||
#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN 0x1
|
||||
|
||||
#define GRUB_KERNEL_MIPS_LOONGSON_MOD_ALIGN 0x1
|
||||
#define GRUB_KERNEL_MIPS_ARC_MOD_ALIGN 0x1
|
||||
|
|
|
@ -1323,6 +1323,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
|
|||
aout_size = core_size + sizeof (*aout_head);
|
||||
aout_img = xmalloc (aout_size);
|
||||
aout_head = aout_img;
|
||||
grub_memset (aout_head, 0, sizeof (*aout_head));
|
||||
aout_head->a_midmag = grub_host_to_target32 ((AOUT_MID_SUN << 16)
|
||||
| AOUT32_OMAGIC);
|
||||
aout_head->a_text = grub_host_to_target32 (core_size);
|
||||
|
|
|
@ -45,6 +45,12 @@ debug=no
|
|||
debug_image=
|
||||
subdir=`echo /boot/grub | sed ${transform}`
|
||||
pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc
|
||||
ppc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/powerpc-ieee1275
|
||||
sparc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/sparc64-ieee1275
|
||||
i386_ieee1275_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-ieee1275
|
||||
efi32_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-efi
|
||||
efi64_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/x86_64-efi
|
||||
itanium_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/ia64-efi
|
||||
|
||||
# Usage: usage
|
||||
# Print the usage.
|
||||
|
@ -196,11 +202,20 @@ process_input_dir ()
|
|||
config_opt="-c ${grubdir}/load.cfg "
|
||||
fi
|
||||
|
||||
prefix="/${subdir}/${platform}";
|
||||
case "${platform}" in
|
||||
i386-pc) mkimage_target=i386-pc-pxe;
|
||||
netmodules="pxe";
|
||||
prefix="(pxe)/${subdir}/${platform}";
|
||||
ext=0 ;;
|
||||
sparc64-ieee1275) mkimage_target=sparc64-ieee1275-aout;
|
||||
netmodules="ofnet";
|
||||
ext=img ;;
|
||||
*-ieee1275) mkimage_target="${platform}";
|
||||
netmodules="ofnet";
|
||||
ext=elf ;;
|
||||
*-efi) mkimage_target="${platform}";
|
||||
netmodules="efinet";
|
||||
ext=efi ;;
|
||||
*) echo Unsupported platform ${platform};
|
||||
exit 1;;
|
||||
esac
|
||||
|
@ -209,13 +224,31 @@ process_input_dir ()
|
|||
source ${subdir}/grub.cfg
|
||||
EOF
|
||||
|
||||
$grub_mkimage ${config_opt} -d "${input_dir}" -O ${mkimage_target} --output=${grubdir}/core.$ext --prefix=$prefix $modules $netmodules || exit 1
|
||||
$grub_mkimage ${config_opt} -d "${input_dir}" -O ${mkimage_target} --output=${grubdir}/core.$ext --prefix=$prefix $modules $netmodules tftp || exit 1
|
||||
echo "Netboot directory for ${platform} created. Configure your DHCP server to point to ${subdir}/${platform}/core.$ext"
|
||||
}
|
||||
|
||||
if [ "${override_dir}" = "" ] ; then
|
||||
if test -e "${pc_dir}" ; then
|
||||
process_input_dir ${pc_dir} i386-pc
|
||||
process_input_dir "${pc_dir}" i386-pc
|
||||
fi
|
||||
if test -e "${ppc_dir}" ; then
|
||||
process_input_dir "${ppc_dir}" powerpc-ieee1275
|
||||
fi
|
||||
if test -e "${sparc_dir}" ; then
|
||||
process_input_dir ${sparc_dir} sparc64-ieee1275
|
||||
fi
|
||||
if test -e "${i386_ieee1275_dir}" ; then
|
||||
process_input_dir "${i386_ieee1275_dir}" i386-ieee1275
|
||||
fi
|
||||
if test -e "${efi32_dir}" ; then
|
||||
process_input_dir "${efi32_dir}" i386-efi
|
||||
fi
|
||||
if test -e "${efi64_dir}" ; then
|
||||
process_input_dir "${efi64_dir}" x86_64-efi
|
||||
fi
|
||||
if test -e "${itanium_dir}" ; then
|
||||
process_input_dir "${itanium_dir}" ia64-efi
|
||||
fi
|
||||
else
|
||||
source "${override_dir}"/modinfo.sh
|
||||
|
|
Loading…
Reference in a new issue