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>
|
2011-07-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_init): Use new
|
* grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_init): Use new
|
||||||
|
|
|
@ -115,7 +115,6 @@ endif
|
||||||
|
|
||||||
if COND_i386_ieee1275
|
if COND_i386_ieee1275
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h
|
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||||
|
@ -188,7 +187,6 @@ endif
|
||||||
|
|
||||||
if COND_powerpc_ieee1275
|
if COND_powerpc_ieee1275
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h
|
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||||
|
@ -196,7 +194,6 @@ endif
|
||||||
|
|
||||||
if COND_sparc64_ieee1275
|
if COND_sparc64_ieee1275
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h
|
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||||
|
|
|
@ -102,6 +102,7 @@ kernel = {
|
||||||
ieee1275 = kern/ieee1275/mmap.c;
|
ieee1275 = kern/ieee1275/mmap.c;
|
||||||
ieee1275 = kern/ieee1275/openfw.c;
|
ieee1275 = kern/ieee1275/openfw.c;
|
||||||
ieee1275 = term/ieee1275/ofconsole.c;
|
ieee1275 = term/ieee1275/ofconsole.c;
|
||||||
|
ieee1275 = kern/ieee1275/init.c;
|
||||||
|
|
||||||
terminfoinkernel = term/terminfo.c;
|
terminfoinkernel = term/terminfo.c;
|
||||||
terminfoinkernel = term/tparm.c;
|
terminfoinkernel = term/tparm.c;
|
||||||
|
@ -153,8 +154,6 @@ kernel = {
|
||||||
i386_multiboot = kern/i386/multiboot_mmap.c;
|
i386_multiboot = kern/i386/multiboot_mmap.c;
|
||||||
i386_multiboot = kern/i386/tsc.c;
|
i386_multiboot = kern/i386/tsc.c;
|
||||||
|
|
||||||
i386_ieee1275 = kern/ieee1275/init.c;
|
|
||||||
|
|
||||||
mips = kern/mips/cache.S;
|
mips = kern/mips/cache.S;
|
||||||
mips = kern/mips/dl.c;
|
mips = kern/mips/dl.c;
|
||||||
mips = kern/mips/init.c;
|
mips = kern/mips/init.c;
|
||||||
|
@ -184,14 +183,12 @@ kernel = {
|
||||||
extra_dist = video/sm712_init.c;
|
extra_dist = video/sm712_init.c;
|
||||||
mips_loongson = commands/keylayouts.c;
|
mips_loongson = commands/keylayouts.c;
|
||||||
|
|
||||||
powerpc_ieee1275 = kern/ieee1275/init.c;
|
|
||||||
powerpc_ieee1275 = kern/powerpc/cache.S;
|
powerpc_ieee1275 = kern/powerpc/cache.S;
|
||||||
powerpc_ieee1275 = kern/powerpc/dl.c;
|
powerpc_ieee1275 = kern/powerpc/dl.c;
|
||||||
|
|
||||||
sparc64_ieee1275 = kern/sparc64/cache.S;
|
sparc64_ieee1275 = kern/sparc64/cache.S;
|
||||||
sparc64_ieee1275 = kern/sparc64/dl.c;
|
sparc64_ieee1275 = kern/sparc64/dl.c;
|
||||||
sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c;
|
sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c;
|
||||||
sparc64_ieee1275 = kern/sparc64/ieee1275/init.c;
|
|
||||||
|
|
||||||
emu = disk/host.c;
|
emu = disk/host.c;
|
||||||
emu = gnulib/progname.c;
|
emu = gnulib/progname.c;
|
||||||
|
@ -722,12 +719,6 @@ module = {
|
||||||
common = commands/probe.c;
|
common = commands/probe.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
|
||||||
name = pxecmd;
|
|
||||||
i386_pc = commands/i386/pc/pxecmd.c;
|
|
||||||
enable = i386_pc;
|
|
||||||
};
|
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = read;
|
name = read;
|
||||||
common = commands/read.c;
|
common = commands/read.c;
|
||||||
|
@ -1105,7 +1096,7 @@ module = {
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = pxe;
|
name = pxe;
|
||||||
i386_pc = net/i386/pc/pxe.c;
|
i386_pc = net/drivers/i386/pc/pxe.c;
|
||||||
enable = i386_pc;
|
enable = i386_pc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1588,6 +1579,7 @@ module = {
|
||||||
module = {
|
module = {
|
||||||
name = net;
|
name = net;
|
||||||
common = net/net.c;
|
common = net/net.c;
|
||||||
|
common = net/bootp.c;
|
||||||
common = net/ip.c;
|
common = net/ip.c;
|
||||||
common = net/udp.c;
|
common = net/udp.c;
|
||||||
common = net/ethernet.c;
|
common = net/ethernet.c;
|
||||||
|
@ -1602,10 +1594,16 @@ module = {
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = ofnet;
|
name = ofnet;
|
||||||
ieee1275 = net/drivers/ieee1275/ofnet.c;
|
common = net/drivers/ieee1275/ofnet.c;
|
||||||
enable = ieee1275;
|
enable = ieee1275;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = efinet;
|
||||||
|
common = net/drivers/efi/efinet.c;
|
||||||
|
enable = efi;
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = emunet;
|
name = emunet;
|
||||||
emu = net/drivers/emu/emunet.c;
|
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";
|
const char *val = "none";
|
||||||
if (dev->net)
|
if (dev->net)
|
||||||
val = dev->net->name;
|
val = dev->net->protocol->name;
|
||||||
if (dev->disk)
|
if (dev->disk)
|
||||||
val = dev->disk->dev->name;
|
val = dev->disk->dev->name;
|
||||||
if (state[0].set)
|
if (state[0].set)
|
||||||
|
|
|
@ -84,54 +84,6 @@ find_last_device_path (const grub_efi_device_path_t *dp)
|
||||||
return p;
|
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 *
|
static struct grub_efidisk_data *
|
||||||
make_devices (void)
|
make_devices (void)
|
||||||
{
|
{
|
||||||
|
@ -214,7 +166,7 @@ find_parent_device (struct grub_efidisk_data *devices,
|
||||||
if (parent == d)
|
if (parent == d)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (compare_device_paths (parent->device_path, dp) == 0)
|
if (grub_efi_compare_device_paths (parent->device_path, dp) == 0)
|
||||||
{
|
{
|
||||||
/* Found. */
|
/* Found. */
|
||||||
if (! parent->last_device_path)
|
if (! parent->last_device_path)
|
||||||
|
@ -249,7 +201,7 @@ iterate_child_devices (struct grub_efidisk_data *devices,
|
||||||
ldp->length[0] = sizeof (*ldp);
|
ldp->length[0] = sizeof (*ldp);
|
||||||
ldp->length[1] = 0;
|
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))
|
if (hook (p))
|
||||||
{
|
{
|
||||||
grub_free (dp);
|
grub_free (dp);
|
||||||
|
@ -273,11 +225,11 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = compare_device_paths (find_last_device_path ((*p)->device_path),
|
ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path),
|
||||||
find_last_device_path (d->device_path));
|
find_last_device_path (d->device_path));
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = compare_device_paths ((*p)->device_path,
|
ret = grub_efi_compare_device_paths ((*p)->device_path,
|
||||||
d->device_path);
|
d->device_path);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
return;
|
return;
|
||||||
else if (ret > 0)
|
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. */
|
and total sectors should be replaced with total blocks. */
|
||||||
grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
|
grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
|
||||||
m, (unsigned long long) m->last_block, m->block_size);
|
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)
|
if (m->block_size & (m->block_size - 1) || !m->block_size)
|
||||||
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
|
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
|
||||||
m->block_size);
|
m->block_size);
|
||||||
|
@ -706,7 +658,35 @@ grub_efidisk_get_device_handle (grub_disk_t disk)
|
||||||
char *
|
char *
|
||||||
grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
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);
|
dp = grub_efi_get_device_path (handle);
|
||||||
if (! dp)
|
if (! dp)
|
||||||
|
@ -720,40 +700,12 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||||
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
|
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
|
||||||
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
|
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
|
||||||
{
|
{
|
||||||
/* This is a hard disk partition. */
|
|
||||||
grub_disk_t parent = 0;
|
|
||||||
grub_partition_t tpart = NULL;
|
grub_partition_t tpart = NULL;
|
||||||
char *device_name;
|
char *device_name;
|
||||||
grub_efi_device_path_t *dup_dp, *dup_ldp;
|
grub_efi_device_path_t *dup_dp, *dup_ldp;
|
||||||
grub_efi_hard_drive_device_path_t hd;
|
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);
|
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. */
|
/* Find the identical partition. */
|
||||||
int find_partition (grub_disk_t disk __attribute__ ((unused)),
|
int find_partition (grub_disk_t disk __attribute__ ((unused)),
|
||||||
const grub_partition_t part)
|
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[0] = sizeof (*dup_ldp);
|
||||||
dup_ldp->length[1] = 0;
|
dup_ldp->length[1] = 0;
|
||||||
|
|
||||||
|
sdp = dup_dp;
|
||||||
|
|
||||||
grub_efidisk_iterate (find_parent_disk);
|
grub_efidisk_iterate (find_parent_disk);
|
||||||
grub_free (dup_dp);
|
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. */
|
/* Find a partition which matches the hard drive device path. */
|
||||||
grub_memcpy (&hd, ldp, sizeof (hd));
|
grub_memcpy (&hd, ldp, sizeof (hd));
|
||||||
grub_partition_iterate (parent, find_partition);
|
if (hd.partition_start == 0
|
||||||
|
&& hd.partition_size == grub_disk_get_size (parent))
|
||||||
if (! tpart)
|
|
||||||
{
|
{
|
||||||
grub_disk_close (parent);
|
device_name = grub_strdup (parent->name);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *partition_name;
|
||||||
|
|
||||||
{
|
grub_partition_iterate (parent, find_partition);
|
||||||
char *partition_name = grub_partition_get_name (tpart);
|
|
||||||
device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
|
if (! tpart)
|
||||||
grub_free (partition_name);
|
{
|
||||||
}
|
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);
|
grub_disk_close (parent);
|
||||||
|
|
||||||
return device_name;
|
return device_name;
|
||||||
|
@ -808,36 +770,15 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This should be an entire disk. */
|
/* This should be an entire disk. */
|
||||||
auto int find_disk (const char *name);
|
|
||||||
char *device_name = 0;
|
char *device_name = 0;
|
||||||
|
|
||||||
int find_disk (const char *name)
|
sdp = dp;
|
||||||
{
|
|
||||||
grub_disk_t disk;
|
|
||||||
|
|
||||||
disk = grub_disk_open (name);
|
grub_efidisk_iterate (find_parent_disk);
|
||||||
if (! disk)
|
if (!parent)
|
||||||
return 1;
|
return NULL;
|
||||||
|
device_name = grub_strdup (parent->name);
|
||||||
if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
|
grub_disk_close (parent);
|
||||||
{
|
|
||||||
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);
|
|
||||||
return device_name;
|
return device_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -243,14 +243,24 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
|
||||||
grub_dprintf ("disk", "Opening `%s'.\n", devpath);
|
grub_dprintf ("disk", "Opening `%s'.\n", devpath);
|
||||||
|
|
||||||
if (grub_ieee1275_finddevice (devpath, &dev))
|
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),
|
if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop),
|
||||||
&actual))
|
&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"))
|
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
|
/* XXX: There is no property to read the number of blocks. There
|
||||||
should be a property `#blocks', but it is not there. Perhaps it
|
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)
|
if (device->net)
|
||||||
{
|
{
|
||||||
grub_free (device->net->name);
|
grub_free (device->net->server);
|
||||||
grub_free (device->net);
|
grub_free (device->net);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -688,11 +688,9 @@ grub_dl_load_file (const char *filename)
|
||||||
grub_file_close (file);
|
grub_file_close (file);
|
||||||
|
|
||||||
mod = grub_dl_load_core (core, size);
|
mod = grub_dl_load_core (core, size);
|
||||||
|
grub_free (core);
|
||||||
if (! mod)
|
if (! mod)
|
||||||
{
|
return 0;
|
||||||
grub_free (core);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mod->ref_count--;
|
mod->ref_count--;
|
||||||
return mod;
|
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);
|
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 ();
|
grub_efidisk_init ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void (*grub_efi_net_config) (grub_efi_handle_t hnd,
|
||||||
|
char **device,
|
||||||
|
char **path);
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_efi_set_prefix (void)
|
grub_machine_get_bootlocation (char **device, char **path)
|
||||||
{
|
{
|
||||||
grub_efi_loaded_image_t *image = NULL;
|
grub_efi_loaded_image_t *image = NULL;
|
||||||
char *device = NULL;
|
char *p;
|
||||||
char *path = NULL;
|
|
||||||
|
|
||||||
{
|
image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||||
char *pptr = NULL;
|
if (!image)
|
||||||
if (grub_prefix[0] == '(')
|
return;
|
||||||
{
|
*device = grub_efidisk_get_device_name (image->device_handle);
|
||||||
pptr = grub_strrchr (grub_prefix, ')');
|
*path = grub_efi_get_filename (image->file_path);
|
||||||
if (pptr)
|
if (!*device && grub_efi_net_config)
|
||||||
{
|
grub_efi_net_config (image->device_handle, device, path);
|
||||||
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)
|
/* Get the directory. */
|
||||||
image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
p = grub_strrchr (*path, '/');
|
||||||
if (image)
|
if (p)
|
||||||
{
|
*p = '\0';
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
static jmp_buf main_env;
|
static jmp_buf main_env;
|
||||||
|
|
||||||
/* Store the prefix specified by an argument. */
|
/* Store the prefix specified by an argument. */
|
||||||
static char *prefix = NULL;
|
static char *root_dev = NULL, *dir = NULL;
|
||||||
|
|
||||||
int grub_no_autoload;
|
int grub_no_autoload;
|
||||||
|
|
||||||
|
@ -71,11 +71,10 @@ grub_machine_init (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_machine_set_prefix (void)
|
grub_machine_get_bootlocation (char **device, char **path)
|
||||||
{
|
{
|
||||||
grub_env_set ("prefix", prefix);
|
*device = root_dev;
|
||||||
free (prefix);
|
*path = dir;
|
||||||
prefix = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -84,6 +83,8 @@ grub_machine_fini (void)
|
||||||
grub_console_fini ();
|
grub_console_fini ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char grub_prefix[64] = "";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static struct option options[] =
|
static struct option options[] =
|
||||||
|
@ -132,22 +133,24 @@ void grub_emu_init (void);
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *root_dev = 0;
|
|
||||||
char *dir = DEFAULT_DIRECTORY;
|
|
||||||
char *dev_map = DEFAULT_DEVICE_MAP;
|
char *dev_map = DEFAULT_DEVICE_MAP;
|
||||||
volatile int hold = 0;
|
volatile int hold = 0;
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
set_program_name (argv[0]);
|
set_program_name (argv[0]);
|
||||||
|
|
||||||
|
dir = xstrdup (DEFAULT_DIRECTORY);
|
||||||
|
|
||||||
while ((opt = getopt_long (argc, argv, "r:d:m:vH:hV", options, 0)) != -1)
|
while ((opt = getopt_long (argc, argv, "r:d:m:vH:hV", options, 0)) != -1)
|
||||||
switch (opt)
|
switch (opt)
|
||||||
{
|
{
|
||||||
case 'r':
|
case 'r':
|
||||||
root_dev = optarg;
|
free (root_dev);
|
||||||
|
root_dev = xstrdup (optarg);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
dir = optarg;
|
free (dir);
|
||||||
|
dir = xstrdup (optarg);
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
dev_map = optarg;
|
dev_map = optarg;
|
||||||
|
@ -219,9 +222,6 @@ main (int argc, char *argv[])
|
||||||
dir = xstrdup (dir);
|
dir = xstrdup (dir);
|
||||||
else
|
else
|
||||||
dir = grub_make_system_path_relative_to_its_root (dir);
|
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! */
|
/* Start GRUB! */
|
||||||
if (setjmp (main_env) == 0)
|
if (setjmp (main_env) == 0)
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include <grub/fs.h>
|
#include <grub/fs.h>
|
||||||
#include <grub/device.h>
|
#include <grub/device.h>
|
||||||
|
|
||||||
grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL;
|
|
||||||
void (*EXPORT_VAR (grub_grubnet_fini)) (void);
|
void (*EXPORT_VAR (grub_grubnet_fini)) (void);
|
||||||
|
|
||||||
grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX];
|
grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX];
|
||||||
|
@ -183,9 +182,6 @@ grub_file_seek (grub_file_t file, grub_off_t offset)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->device->net && grub_file_net_seek)
|
|
||||||
grub_file_net_seek (file, offset);
|
|
||||||
|
|
||||||
old = file->offset;
|
old = file->offset;
|
||||||
file->offset = offset;
|
file->offset = offset;
|
||||||
|
|
||||||
|
|
|
@ -107,10 +107,9 @@ grub_machine_init (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
void
|
||||||
|
|
|
@ -39,9 +39,3 @@ grub_machine_fini (void)
|
||||||
{
|
{
|
||||||
grub_efi_fini ();
|
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 struct mem_region mem_regions[MAX_REGIONS];
|
||||||
static int num_regions;
|
static int num_regions;
|
||||||
|
|
||||||
static char *
|
void (*grub_pc_net_config) (char **device, char **path);
|
||||||
make_install_device (void)
|
|
||||||
|
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. */
|
/* 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] != '(')
|
if (grub_install_dos_part >= 0)
|
||||||
{
|
grub_snprintf (ptr, DEV_SIZE - (ptr - *device),
|
||||||
/* No hardcoded root partition - make it from the boot drive and the
|
",%u", grub_install_dos_part + 1);
|
||||||
partition number encoded at the install time. */
|
ptr += grub_strlen (ptr);
|
||||||
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)
|
if (grub_install_bsd_part >= 0)
|
||||||
grub_snprintf (ptr, sizeof (dev) - (ptr - dev),
|
grub_snprintf (ptr, DEV_SIZE - (ptr - *device), ",%u",
|
||||||
",%u", grub_install_dos_part + 1);
|
grub_install_bsd_part + 1);
|
||||||
ptr += grub_strlen (ptr);
|
ptr += grub_strlen (ptr);
|
||||||
|
*ptr = 0;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a memory region. */
|
/* Add a memory region. */
|
||||||
|
@ -211,13 +200,6 @@ grub_machine_init (void)
|
||||||
grub_tsc_init ();
|
grub_tsc_init ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
grub_machine_set_prefix (void)
|
|
||||||
{
|
|
||||||
/* Initialize the prefix. */
|
|
||||||
grub_env_set ("prefix", make_install_device ());
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_machine_fini (void)
|
grub_machine_fini (void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,12 +40,6 @@ grub_machine_fini (void)
|
||||||
grub_efi_fini ();
|
grub_efi_fini ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
grub_machine_set_prefix (void)
|
|
||||||
{
|
|
||||||
grub_efi_set_prefix ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_arch_sync_caches (void *address, grub_size_t len)
|
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_olpc = 0;
|
||||||
int is_qemu = 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 ("/", &root);
|
||||||
grub_ieee1275_finddevice ("/options", &options);
|
grub_ieee1275_finddevice ("/options", &options);
|
||||||
grub_ieee1275_finddevice ("/openprom", &openprom);
|
grub_ieee1275_finddevice ("/openprom", &openprom);
|
||||||
|
|
|
@ -31,10 +31,12 @@
|
||||||
#include <grub/ieee1275/console.h>
|
#include <grub/ieee1275/console.h>
|
||||||
#include <grub/ieee1275/ofdisk.h>
|
#include <grub/ieee1275/ofdisk.h>
|
||||||
#include <grub/ieee1275/ieee1275.h>
|
#include <grub/ieee1275/ieee1275.h>
|
||||||
#include <grub/ieee1275/ofnet.h>
|
|
||||||
#include <grub/net.h>
|
#include <grub/net.h>
|
||||||
#include <grub/offsets.h>
|
#include <grub/offsets.h>
|
||||||
#include <grub/memory.h>
|
#include <grub/memory.h>
|
||||||
|
#ifdef __sparc__
|
||||||
|
#include <grub/machine/kernel.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The minimal heap size we can live with. */
|
/* The minimal heap size we can live with. */
|
||||||
#define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024)
|
#define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024)
|
||||||
|
@ -49,6 +51,10 @@
|
||||||
extern char _start[];
|
extern char _start[];
|
||||||
extern char _end[];
|
extern char _end[];
|
||||||
|
|
||||||
|
#ifdef __sparc__
|
||||||
|
grub_addr_t grub_ieee1275_original_stack;
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_exit (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
|
void
|
||||||
grub_machine_set_prefix (void)
|
grub_machine_get_bootlocation (char **device, char **path)
|
||||||
{
|
{
|
||||||
char bootpath[64]; /* XXX check length */
|
char bootpath[64]; /* XXX check length */
|
||||||
char *filename;
|
char *filename;
|
||||||
char *prefix;
|
char *type;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath,
|
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath,
|
||||||
sizeof (bootpath), 0))
|
sizeof (bootpath), 0))
|
||||||
{
|
{
|
||||||
/* Should never happen. */
|
/* Should never happen. */
|
||||||
grub_printf ("/chosen/bootpath property missing!\n");
|
grub_printf ("/chosen/bootpath property missing!\n");
|
||||||
grub_env_set ("prefix", "");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Transform an OF device path to a GRUB path. */
|
/* 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);
|
filename = grub_ieee1275_get_filename (bootpath);
|
||||||
if (filename)
|
if (filename)
|
||||||
{
|
{
|
||||||
char *newprefix;
|
|
||||||
char *lastslash = grub_strrchr (filename, '\\');
|
char *lastslash = grub_strrchr (filename, '\\');
|
||||||
|
|
||||||
/* Truncate at last directory. */
|
/* Truncate at last directory. */
|
||||||
|
@ -124,23 +129,22 @@ grub_machine_set_prefix (void)
|
||||||
*lastslash = '\0';
|
*lastslash = '\0';
|
||||||
grub_translate_ieee1275_path (filename);
|
grub_translate_ieee1275_path (filename);
|
||||||
|
|
||||||
newprefix = grub_xasprintf ("%s%s", prefix, filename);
|
*path = filename;
|
||||||
if (newprefix)
|
|
||||||
{
|
|
||||||
grub_free (prefix);
|
|
||||||
prefix = newprefix;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_env_set ("prefix", prefix);
|
|
||||||
|
|
||||||
grub_free (filename);
|
|
||||||
grub_free (prefix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Claim some available memory in the first /memory node. */
|
/* 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;
|
unsigned long total = 0;
|
||||||
|
|
||||||
|
@ -208,23 +212,14 @@ static void grub_claim_heap (void)
|
||||||
else
|
else
|
||||||
grub_machine_mmap_iterate (heap_init);
|
grub_machine_mmap_iterate (heap_init);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static grub_uint64_t ieee1275_get_time_ms (void);
|
static void
|
||||||
|
grub_parse_cmdline (void)
|
||||||
void
|
|
||||||
grub_machine_init (void)
|
|
||||||
{
|
{
|
||||||
char args[256];
|
|
||||||
grub_ssize_t actual;
|
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,
|
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
|
||||||
sizeof args, &actual) == 0
|
sizeof args, &actual) == 0
|
||||||
&& actual > 1)
|
&& 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);
|
grub_install_get_time_ms (ieee1275_get_time_ms);
|
||||||
}
|
}
|
||||||
|
@ -264,8 +274,6 @@ grub_machine_init (void)
|
||||||
void
|
void
|
||||||
grub_machine_fini (void)
|
grub_machine_fini (void)
|
||||||
{
|
{
|
||||||
if (grub_grubnet_fini)
|
|
||||||
grub_grubnet_fini ();
|
|
||||||
grub_ofdisk_fini ();
|
grub_ofdisk_fini ();
|
||||||
grub_console_fini ();
|
grub_console_fini ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,16 +22,14 @@
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/ieee1275/ieee1275.h>
|
#include <grub/ieee1275/ieee1275.h>
|
||||||
#include <grub/ieee1275/ofnet.h>
|
|
||||||
#include <grub/net.h>
|
#include <grub/net.h>
|
||||||
#include <grub/net/tftp.h>
|
|
||||||
|
|
||||||
grub_bootp_t (*grub_getbootp) (void);
|
|
||||||
enum grub_ieee1275_parse_type
|
enum grub_ieee1275_parse_type
|
||||||
{
|
{
|
||||||
GRUB_PARSE_FILENAME,
|
GRUB_PARSE_FILENAME,
|
||||||
GRUB_PARSE_PARTITION,
|
GRUB_PARSE_PARTITION,
|
||||||
GRUB_PARSE_DEVICE
|
GRUB_PARSE_DEVICE,
|
||||||
|
GRUB_PARSE_DEVICE_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Walk children of 'devpath', calling hook for each. */
|
/* 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 type[64]; /* XXX check size. */
|
||||||
char *device = grub_ieee1275_get_devname (path);
|
char *device = grub_ieee1275_get_devname (path);
|
||||||
char *args = grub_ieee1275_get_devargs (path);
|
|
||||||
char *ret = 0;
|
char *ret = 0;
|
||||||
grub_ieee1275_phandle_t dev;
|
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
|
/* We need to know what type of device it is in order to parse the full
|
||||||
file path properly. */
|
file path properly. */
|
||||||
if (grub_ieee1275_finddevice (device, &dev))
|
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;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!grub_strcmp ("block", type))
|
switch (ptype)
|
||||||
{
|
{
|
||||||
/* The syntax of the device arguments is defined in the CHRP and PReP
|
case GRUB_PARSE_DEVICE:
|
||||||
IEEE1275 bindings: "[partition][,[filename]]". */
|
ret = grub_strdup (device);
|
||||||
char *comma = grub_strchr (args, ',');
|
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 (grub_strcmp ("block", type) != 0)
|
||||||
{
|
goto unknown;
|
||||||
if (comma)
|
|
||||||
{
|
|
||||||
char *filepath = comma + 1;
|
|
||||||
|
|
||||||
/* Make sure filepath has leading backslash. */
|
args = grub_ieee1275_get_devargs (path);
|
||||||
if (filepath[0] != '\\')
|
if (!args)
|
||||||
ret = grub_xasprintf ("\\%s", filepath);
|
/* Shouldn't happen. */
|
||||||
else
|
return 0;
|
||||||
ret = grub_strdup (filepath);
|
|
||||||
|
/* 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)
|
break;
|
||||||
{
|
case GRUB_PARSE_PARTITION:
|
||||||
if (!comma)
|
{
|
||||||
ret = grub_strdup (args);
|
char *comma;
|
||||||
else
|
char *args;
|
||||||
ret = grub_strndup (args, (grub_size_t)(comma - args));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (!grub_strcmp ("network", type))
|
if (grub_strcmp ("block", type) != 0)
|
||||||
{
|
goto unknown;
|
||||||
if (ptype == GRUB_PARSE_DEVICE)
|
|
||||||
ret = grub_strdup(device);
|
args = grub_ieee1275_get_devargs (path);
|
||||||
}
|
if (!args)
|
||||||
else
|
/* 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);
|
grub_printf ("Unsupported type %s for device %s\n", type, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
grub_free (device);
|
grub_free (device);
|
||||||
grub_free (args);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
grub_ieee1275_get_device_type (const char *path)
|
||||||
|
{
|
||||||
|
return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
grub_ieee1275_get_aliasdevname (const char *path)
|
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);
|
return grub_strdup (val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the root device according to the dl prefix. */
|
|
||||||
static void
|
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);
|
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);
|
comma = grub_strchr (fwdevice, ',');
|
||||||
if (dev)
|
if (comma)
|
||||||
{
|
{
|
||||||
grub_env_set ("root", dev);
|
char *drive = grub_strndup (fwdevice, comma - fwdevice);
|
||||||
grub_free (dev);
|
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. */
|
/* 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,
|
/* It is better to set the root device as soon as possible,
|
||||||
for convenience. */
|
for convenience. */
|
||||||
grub_machine_set_prefix ();
|
grub_set_prefix_and_root ();
|
||||||
grub_set_root_dev ();
|
|
||||||
grub_env_export ("root");
|
grub_env_export ("root");
|
||||||
grub_env_export ("prefix");
|
grub_env_export ("prefix");
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ grub_get_rtc (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
void *ptr;
|
||||||
|
|
||||||
if (grub_mm_debug)
|
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);
|
ptr = grub_malloc (size);
|
||||||
if (grub_mm_debug)
|
if (grub_mm_debug)
|
||||||
grub_printf ("%p\n", ptr);
|
grub_printf ("%p\n", ptr);
|
||||||
|
@ -528,7 +528,7 @@ grub_debug_zalloc (const char *file, int line, grub_size_t size)
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
|
||||||
if (grub_mm_debug)
|
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);
|
ptr = grub_zalloc (size);
|
||||||
if (grub_mm_debug)
|
if (grub_mm_debug)
|
||||||
grub_printf ("%p\n", ptr);
|
grub_printf ("%p\n", ptr);
|
||||||
|
@ -547,7 +547,7 @@ void *
|
||||||
grub_debug_realloc (const char *file, int line, void *ptr, grub_size_t size)
|
grub_debug_realloc (const char *file, int line, void *ptr, grub_size_t size)
|
||||||
{
|
{
|
||||||
if (grub_mm_debug)
|
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);
|
ptr = grub_realloc (ptr, size);
|
||||||
if (grub_mm_debug)
|
if (grub_mm_debug)
|
||||||
grub_printf ("%p\n", ptr);
|
grub_printf ("%p\n", ptr);
|
||||||
|
@ -561,8 +561,8 @@ grub_debug_memalign (const char *file, int line, grub_size_t align,
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
|
||||||
if (grub_mm_debug)
|
if (grub_mm_debug)
|
||||||
grub_printf ("%s:%d: memalign (0x%zx, 0x%zx) = ",
|
grub_printf ("%s:%d: memalign (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE
|
||||||
file, line, align, size);
|
") = ", file, line, align, size);
|
||||||
ptr = grub_memalign (align, size);
|
ptr = grub_memalign (align, size);
|
||||||
if (grub_mm_debug)
|
if (grub_mm_debug)
|
||||||
grub_printf ("%p\n", ptr);
|
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;
|
struct grub_term_input *grub_term_inputs;
|
||||||
|
|
||||||
void (*grub_term_poll_usb) (void) = NULL;
|
void (*grub_term_poll_usb) (void) = NULL;
|
||||||
|
void (*grub_net_poll_cards_idle) (void) = NULL;
|
||||||
|
|
||||||
/* Put a Unicode character. */
|
/* Put a Unicode character. */
|
||||||
static void
|
static void
|
||||||
|
@ -91,6 +92,9 @@ grub_checkkey (void)
|
||||||
if (grub_term_poll_usb)
|
if (grub_term_poll_usb)
|
||||||
grub_term_poll_usb ();
|
grub_term_poll_usb ();
|
||||||
|
|
||||||
|
if (grub_net_poll_cards_idle)
|
||||||
|
grub_net_poll_cards_idle ();
|
||||||
|
|
||||||
FOR_ACTIVE_TERM_INPUTS(term)
|
FOR_ACTIVE_TERM_INPUTS(term)
|
||||||
{
|
{
|
||||||
pending_key = term->getkey (term);
|
pending_key = term->getkey (term);
|
||||||
|
|
|
@ -95,6 +95,20 @@ FUNCTION(efi_wrap_6)
|
||||||
addq $64, %rsp
|
addq $64, %rsp
|
||||||
ret
|
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)
|
FUNCTION(efi_wrap_10)
|
||||||
subq $96, %rsp
|
subq $96, %rsp
|
||||||
mov 96+40(%rsp), %rax
|
mov 96+40(%rsp), %rax
|
||||||
|
|
|
@ -144,7 +144,8 @@ grub_net_arp_receive (struct grub_net_buff *nb)
|
||||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||||
{
|
{
|
||||||
/* Am I the protocol address target? */
|
/* 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_be_to_cpu16 (arp_header->op) == ARP_REQUEST)
|
||||||
{
|
{
|
||||||
grub_net_link_level_address_t aux;
|
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/net/netbuff.h>
|
||||||
#include <grub/ieee1275/ofnet.h>
|
|
||||||
#include <grub/ieee1275/ieee1275.h>
|
#include <grub/ieee1275/ieee1275.h>
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/net.h>
|
#include <grub/net.h>
|
||||||
|
@ -7,8 +24,15 @@
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
struct grub_ofnetcard_data
|
||||||
|
{
|
||||||
|
char *path;
|
||||||
|
grub_ieee1275_ihandle_t handle;
|
||||||
|
grub_uint32_t mtu;
|
||||||
|
};
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
card_open (struct grub_net_card *dev)
|
card_open (const struct grub_net_card *dev)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
struct grub_ofnetcard_data *data = dev->data;
|
struct grub_ofnetcard_data *data = dev->data;
|
||||||
|
@ -26,14 +50,13 @@ card_open (struct grub_net_card *dev)
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static void
|
||||||
card_close (struct grub_net_card *dev)
|
card_close (const struct grub_net_card *dev)
|
||||||
{
|
{
|
||||||
struct grub_ofnetcard_data *data = dev->data;
|
struct grub_ofnetcard_data *data = dev->data;
|
||||||
|
|
||||||
if (data->handle)
|
if (data->handle)
|
||||||
grub_ieee1275_close (data->handle);
|
grub_ieee1275_close (data->handle);
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
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 =
|
static struct grub_net_card_driver ofdriver =
|
||||||
{
|
{
|
||||||
.name = "ofnet",
|
.name = "ofnet",
|
||||||
.init = card_open,
|
.open = card_open,
|
||||||
.fini = card_close,
|
.close = card_close,
|
||||||
.send = send_card_buffer,
|
.send = send_card_buffer,
|
||||||
.recv = get_card_packet
|
.recv = get_card_packet
|
||||||
};
|
};
|
||||||
|
@ -94,51 +117,113 @@ bootp_response_properties[] =
|
||||||
{ .name = "bootpreply-packet", .offset = 0x2a},
|
{ .name = "bootpreply-packet", .offset = 0x2a},
|
||||||
};
|
};
|
||||||
|
|
||||||
static grub_bootp_t
|
static void
|
||||||
grub_getbootp_real (void)
|
grub_ieee1275_net_config_real (const char *devpath, char **device, char **path)
|
||||||
{
|
{
|
||||||
grub_bootp_t packet = grub_malloc (sizeof *packet);
|
struct grub_net_card *card;
|
||||||
char *bootp_response;
|
|
||||||
grub_ssize_t size;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++)
|
/* FIXME: Check that it's the right card. */
|
||||||
if (grub_ieee1275_get_property_length (grub_ieee1275_chosen,
|
FOR_NET_CARDS (card)
|
||||||
bootp_response_properties[i].name,
|
{
|
||||||
&size) >= 0)
|
char *bootp_response;
|
||||||
break;
|
char *cardpath;
|
||||||
|
char *canon;
|
||||||
|
|
||||||
if (size < 0)
|
grub_ssize_t size = -1;
|
||||||
return NULL;
|
unsigned int i;
|
||||||
|
|
||||||
bootp_response = grub_malloc (size);
|
if (card->driver != &ofdriver)
|
||||||
if (grub_ieee1275_get_property (grub_ieee1275_chosen,
|
continue;
|
||||||
bootp_response_properties[i].name,
|
|
||||||
bootp_response, size, 0) < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
grub_memcpy (packet, bootp_response + bootp_response_properties[i].offset, sizeof (*packet));
|
cardpath = ((struct grub_ofnetcard_data *) card->data)->path;
|
||||||
grub_free (bootp_response);
|
canon = grub_ieee1275_canonicalise_devname (cardpath);
|
||||||
return packet;
|
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
|
static void
|
||||||
grub_ofnet_findcards (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);
|
auto int search_net_devices (struct grub_ieee1275_devalias *alias);
|
||||||
|
|
||||||
int search_net_devices (struct grub_ieee1275_devalias *alias)
|
int search_net_devices (struct grub_ieee1275_devalias *alias)
|
||||||
{
|
{
|
||||||
if (!grub_strcmp (alias->type, "network"))
|
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);
|
ofdata->path = grub_strdup (alias->path);
|
||||||
|
|
||||||
grub_ieee1275_finddevice (ofdata->path, &devhandle);
|
grub_ieee1275_finddevice (ofdata->path, &devhandle);
|
||||||
|
@ -146,11 +231,19 @@ grub_ofnet_findcards (void)
|
||||||
if (grub_ieee1275_get_integer_property
|
if (grub_ieee1275_get_integer_property
|
||||||
(devhandle, "max-frame-size", &(ofdata->mtu),
|
(devhandle, "max-frame-size", &(ofdata->mtu),
|
||||||
sizeof (ofdata->mtu), 0))
|
sizeof (ofdata->mtu), 0))
|
||||||
return grub_error (GRUB_ERR_IO, "Couldn't retrieve mtu size.");
|
{
|
||||||
|
ofdata->mtu = 1500;
|
||||||
|
}
|
||||||
|
|
||||||
if (grub_ieee1275_get_property
|
if (grub_ieee1275_get_property (devhandle, "mac-address",
|
||||||
(devhandle, "mac-address", &(lla.mac), 6, 0))
|
&(lla.mac), 6, 0)
|
||||||
return grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address.");
|
&& 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;
|
lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||||
card->default_address = lla;
|
card->default_address = lla;
|
||||||
|
@ -158,7 +251,12 @@ grub_ofnet_findcards (void)
|
||||||
card->driver = NULL;
|
card->driver = NULL;
|
||||||
card->data = ofdata;
|
card->data = ofdata;
|
||||||
card->flags = 0;
|
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);
|
grub_net_card_register (card);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -169,69 +267,18 @@ grub_ofnet_findcards (void)
|
||||||
grub_ieee1275_devices_iterate (search_net_devices);
|
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)
|
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_findcards ();
|
||||||
grub_ofnet_probecards ();
|
grub_ieee1275_net_config = grub_ieee1275_net_config_real;
|
||||||
FOR_NET_CARDS (card)
|
|
||||||
if (card->driver == NULL)
|
|
||||||
grub_net_card_unregister (card);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(ofnet)
|
GRUB_MOD_FINI(ofnet)
|
||||||
{
|
{
|
||||||
struct grub_net_card *card;
|
struct grub_net_card *card, *next;
|
||||||
FOR_NET_CARDS (card)
|
|
||||||
if (card->driver && !grub_strcmp (card->driver->name, "ofnet"))
|
FOR_NET_CARDS_SAFE (card, next)
|
||||||
{
|
if (card->driver && grub_strcmp (card->driver->name, "ofnet") == 0)
|
||||||
card->driver->fini (card);
|
grub_net_card_unregister (card);
|
||||||
card->driver = NULL;
|
grub_ieee1275_net_config = 0;
|
||||||
}
|
|
||||||
grub_net_card_driver_unregister (&ofdriver);
|
|
||||||
grub_getbootp = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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/misc.h>
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/net/ethernet.h>
|
#include <grub/net/ethernet.h>
|
||||||
|
@ -8,6 +26,28 @@
|
||||||
#include <grub/time.h>
|
#include <grub/time.h>
|
||||||
#include <grub/net/arp.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
|
grub_err_t
|
||||||
send_ethernet_packet (struct grub_net_network_level_interface *inf,
|
send_ethernet_packet (struct grub_net_network_level_interface *inf,
|
||||||
struct grub_net_buff *nb,
|
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);
|
grub_memcpy (eth->src, inf->hwaddress.mac, 6);
|
||||||
|
|
||||||
eth->type = grub_cpu_to_be16 (ethertype);
|
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);
|
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_net_arp_receive (nb);
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
/* IP packet. */
|
/* IP packet. */
|
||||||
if (type == GRUB_NET_ETHERTYPE_IP)
|
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;
|
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/net/ip.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/net/arp.h>
|
#include <grub/net/arp.h>
|
||||||
|
@ -7,8 +25,32 @@
|
||||||
#include <grub/net/netbuff.h>
|
#include <grub/net/netbuff.h>
|
||||||
#include <grub/mm.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
|
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_uint16_t *ip = (grub_uint16_t *) ipv;
|
||||||
grub_uint32_t sum = 0;
|
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->dest = target->ipv4;
|
||||||
|
|
||||||
iph->chksum = 0;
|
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. */
|
/* Determine link layer target address via ARP. */
|
||||||
err = grub_net_arp_resolve (inf, target, &ll_target_addr);
|
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;
|
struct iphdr *iph = (struct iphdr *) nb->data;
|
||||||
grub_err_t err;
|
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));
|
err = grub_netbuff_pull (nb, sizeof (*iph));
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
/* DHCP needs special treatment since we don't know IP yet. */
|
||||||
{
|
{
|
||||||
if (inf->card == card
|
struct udphdr *udph;
|
||||||
&& inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
|
udph = (struct udphdr *) nb->data;
|
||||||
&& inf->address.ipv4 == iph->dest
|
if (iph->protocol == IP_UDP && grub_be_to_cpu16 (udph->dst) == 68)
|
||||||
&& grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
|
{
|
||||||
break;
|
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)
|
if (!inf)
|
||||||
{
|
{
|
||||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||||
|
{
|
||||||
if (inf->card == card
|
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)
|
&& grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!inf)
|
|
||||||
{
|
|
||||||
if (iph->protocol == IP_UDP
|
|
||||||
&& grub_net_hwaddr_cmp (&card->default_address, hwaddress) == 0)
|
|
||||||
{
|
|
||||||
struct udphdr *udph;
|
|
||||||
udph = (struct udphdr *) nb->data;
|
|
||||||
err = grub_netbuff_pull (nb, sizeof (*udph));
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
if (grub_be_to_cpu16 (udph->dst) == 68)
|
|
||||||
grub_net_process_dhcp (nb, card);
|
|
||||||
}
|
|
||||||
grub_netbuff_free (nb);
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (iph->protocol)
|
switch (iph->protocol)
|
||||||
{
|
{
|
||||||
case IP_UDP:
|
case IP_UDP:
|
||||||
return grub_net_recv_udp_packet (nb, inf);
|
return grub_net_recv_udp_packet (nb, inf);
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* GRUB -- GRand Unified Bootloader
|
* 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
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -16,7 +16,6 @@
|
||||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grub/net/udp.h>
|
|
||||||
#include <grub/net.h>
|
#include <grub/net.h>
|
||||||
#include <grub/net/netbuff.h>
|
#include <grub/net/netbuff.h>
|
||||||
#include <grub/time.h>
|
#include <grub/time.h>
|
||||||
|
@ -28,10 +27,14 @@
|
||||||
#include <grub/command.h>
|
#include <grub/command.h>
|
||||||
#include <grub/env.h>
|
#include <grub/env.h>
|
||||||
#include <grub/net/ethernet.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+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
char *grub_net_default_server;
|
||||||
|
|
||||||
struct grub_net_route
|
struct grub_net_route
|
||||||
{
|
{
|
||||||
struct grub_net_route *next;
|
struct grub_net_route *next;
|
||||||
|
@ -49,20 +52,27 @@ struct grub_net_route
|
||||||
struct grub_net_route *grub_net_routes = NULL;
|
struct grub_net_route *grub_net_routes = NULL;
|
||||||
struct grub_net_network_level_interface *grub_net_network_level_interfaces = 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 *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;
|
struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL;
|
||||||
static struct grub_fs grub_net_fs;
|
static struct grub_fs grub_net_fs;
|
||||||
|
|
||||||
static inline void
|
void
|
||||||
grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter)
|
grub_net_card_unregister (struct grub_net_card *card)
|
||||||
{
|
{
|
||||||
*inter->prev = inter->next;
|
struct grub_net_network_level_interface *inf, *next;
|
||||||
if (inter->next)
|
FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(inf, next)
|
||||||
inter->next->prev = inter->prev;
|
if (inf->card == card)
|
||||||
inter->next = 0;
|
grub_net_network_level_interface_unregister (inf);
|
||||||
inter->prev = 0;
|
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
|
static inline void
|
||||||
grub_net_route_register (struct grub_net_route *route)
|
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;
|
return 0;
|
||||||
switch (net->type)
|
switch (net->type)
|
||||||
{
|
{
|
||||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC:
|
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
|
||||||
return 0;
|
return 0;
|
||||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
|
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)
|
switch (target->type)
|
||||||
{
|
{
|
||||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC:
|
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
|
||||||
grub_strcpy (buf, "promisc");
|
grub_strcpy (buf, "temporary");
|
||||||
return;
|
return;
|
||||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
|
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);
|
grub_register_variable_hook (name, 0, addr_set_env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inter->card->num_ifaces++;
|
||||||
inter->prev = &grub_net_network_level_interfaces;
|
inter->prev = &grub_net_network_level_interfaces;
|
||||||
inter->next = grub_net_network_level_interfaces;
|
inter->next = grub_net_network_level_interfaces;
|
||||||
if (inter->next)
|
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 *
|
struct grub_net_network_level_interface *
|
||||||
grub_net_add_addr (const char *name,
|
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_network_level_address_t addr,
|
||||||
grub_net_link_level_address_t hwaddress,
|
grub_net_link_level_address_t hwaddress,
|
||||||
grub_net_interface_flags_t flags)
|
grub_net_interface_flags_t flags)
|
||||||
|
@ -519,8 +530,8 @@ print_net_address (const grub_net_network_level_netaddress_t *target)
|
||||||
{
|
{
|
||||||
switch (target->type)
|
switch (target->type)
|
||||||
{
|
{
|
||||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC:
|
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
|
||||||
grub_printf ("promisc\n");
|
grub_printf ("temporary\n");
|
||||||
break;
|
break;
|
||||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
|
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;
|
struct grub_net_card *card;
|
||||||
FOR_NET_CARDS(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;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,27 +615,68 @@ struct grub_net_socket *grub_net_sockets;
|
||||||
static grub_net_t
|
static grub_net_t
|
||||||
grub_net_open_real (const char *name)
|
grub_net_open_real (const char *name)
|
||||||
{
|
{
|
||||||
const char *comma = grub_strchr (name, ',');
|
|
||||||
grub_net_app_level_t proto;
|
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)
|
FOR_NET_APP_LEVEL (proto)
|
||||||
{
|
{
|
||||||
if (comma - name == (grub_ssize_t) grub_strlen (proto->name)
|
if (grub_memcmp (proto->name, protname, protnamelen) == 0
|
||||||
&& grub_memcmp (proto->name, name, comma - name) == 0)
|
&& proto->name[protnamelen] == 0)
|
||||||
{
|
{
|
||||||
grub_net_t ret = grub_malloc (sizeof (*ret));
|
grub_net_t ret = grub_zalloc (sizeof (*ret));
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return NULL;
|
return NULL;
|
||||||
ret->protocol = proto;
|
ret->protocol = proto;
|
||||||
ret->name = grub_strdup (name);
|
if (server)
|
||||||
if (!ret->name)
|
|
||||||
{
|
{
|
||||||
grub_free (ret);
|
ret->server = grub_strdup (server);
|
||||||
return NULL;
|
if (!ret->server)
|
||||||
|
{
|
||||||
|
grub_free (ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ret->server = NULL;
|
||||||
ret->fs = &grub_net_fs;
|
ret->fs = &grub_net_fs;
|
||||||
|
ret->offset = 0;
|
||||||
|
ret->eof = 0;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -643,73 +696,69 @@ grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused))
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
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_err_t err;
|
||||||
grub_net_network_level_address_t addr;
|
struct grub_file *file, *bufio;
|
||||||
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;
|
|
||||||
|
|
||||||
comma = grub_strchr (file->device->net->name, ',');
|
file = grub_malloc (sizeof (*file));
|
||||||
if (!comma)
|
if (!file)
|
||||||
return grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no separator");
|
return grub_errno;
|
||||||
|
|
||||||
err = grub_net_resolve_address (comma + 1, &addr);
|
grub_memcpy (file, file_out, sizeof (struct grub_file));
|
||||||
if (err)
|
file->device->net->packs.first = NULL;
|
||||||
return err;
|
file->device->net->packs.last = NULL;
|
||||||
|
file->device->net->name = grub_strdup (name);
|
||||||
err = grub_net_route_address (addr, &gateway, &inf);
|
if (!file->device->net->name)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
err = file->device->net->protocol->open (file, name);
|
||||||
if (err)
|
if (err)
|
||||||
return 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));
|
grub_memcpy (file_out, bufio, sizeof (struct grub_file));
|
||||||
if (socket == NULL)
|
grub_free (bufio);
|
||||||
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;
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
fail:
|
|
||||||
grub_net_socket_unregister (socket);
|
|
||||||
grub_free (socket);
|
|
||||||
return err;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_net_fs_close (grub_file_t file)
|
grub_net_fs_close (grub_file_t file)
|
||||||
{
|
{
|
||||||
grub_net_socket_t sock = file->device->net->socket;
|
while (file->device->net->packs.first)
|
||||||
while (sock->packs.first)
|
|
||||||
{
|
{
|
||||||
grub_netbuff_free (sock->packs.first->nb);
|
grub_netbuff_free (file->device->net->packs.first->nb);
|
||||||
grub_net_remove_packet (sock->packs.first);
|
grub_net_remove_packet (file->device->net->packs.first);
|
||||||
}
|
}
|
||||||
grub_net_socket_unregister (sock);
|
file->device->net->protocol->close (file);
|
||||||
grub_free (sock);
|
grub_free (file->device->net->name);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
receive_packets (struct grub_net_card *card)
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
/* Maybe should be better have a fixed number of packets for each card
|
/* 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)
|
if (!nb)
|
||||||
{
|
{
|
||||||
grub_print_error ();
|
grub_print_error ();
|
||||||
|
card->last_poll = grub_get_time_ms ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,6 +777,7 @@ receive_packets (struct grub_net_card *card)
|
||||||
if (actual < 0)
|
if (actual < 0)
|
||||||
{
|
{
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
|
card->last_poll = grub_get_time_ms ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
grub_net_recv_ethernet_packet (nb, card);
|
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*/
|
/* Read from the packets list*/
|
||||||
static grub_ssize_t
|
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;
|
struct grub_net_buff *nb;
|
||||||
char *ptr = buf;
|
char *ptr = buf;
|
||||||
grub_size_t amount, total = 0;
|
grub_size_t amount, total = 0;
|
||||||
int try = 0;
|
int try = 0;
|
||||||
while (try <= 3)
|
while (try <= 3)
|
||||||
|
@ -767,6 +832,7 @@ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
amount = len;
|
amount = len;
|
||||||
len -= amount;
|
len -= amount;
|
||||||
total += amount;
|
total += amount;
|
||||||
|
file->device->net->offset += amount;
|
||||||
if (buf)
|
if (buf)
|
||||||
{
|
{
|
||||||
grub_memcpy (ptr, nb->data, amount);
|
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)
|
if (!len)
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
if (sock->status == 1)
|
if (!sock->eof)
|
||||||
{
|
{
|
||||||
try++;
|
try++;
|
||||||
grub_net_poll_cards (200);
|
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;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read from the packets list*/
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_net_seek_real (struct grub_file *file, grub_off_t offset)
|
grub_net_seek_real (struct grub_file *file, grub_off_t offset)
|
||||||
{
|
{
|
||||||
grub_net_socket_t sock = file->device->net->socket;
|
grub_size_t len = offset - file->device->net->offset;
|
||||||
struct grub_net_buff *nb;
|
|
||||||
grub_size_t len = offset - file->offset;
|
|
||||||
|
|
||||||
if (!len)
|
if (!len)
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
|
||||||
/* We cant seek backwards past the current packet. */
|
if (file->device->net->offset > offset)
|
||||||
if (file->offset > offset)
|
{
|
||||||
{
|
grub_err_t err;
|
||||||
nb = sock->packs.first->nb;
|
while (file->device->net->packs.first)
|
||||||
return grub_netbuff_push (nb, file->offset - offset);
|
{
|
||||||
|
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;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static grub_ssize_t
|
||||||
grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
|
grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
const char *val __attribute__ ((unused)))
|
|
||||||
{
|
{
|
||||||
return NULL;
|
if (file->offset != file->device->net->offset)
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
grub_uint8_t tagtype;
|
grub_err_t err;
|
||||||
grub_uint8_t taglength;
|
err = grub_net_seek_real (file, file->offset);
|
||||||
|
if (err)
|
||||||
tagtype = *ptr++;
|
return err;
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
}
|
return grub_net_fs_read_real (file, buf, len);
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct grub_fs grub_net_fs =
|
static struct grub_fs grub_net_fs =
|
||||||
|
@ -1255,9 +916,32 @@ static struct grub_fs grub_net_fs =
|
||||||
.uuid = NULL,
|
.uuid = NULL,
|
||||||
.mtime = 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_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute;
|
||||||
static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp, cmd_bootp;
|
static grub_command_t cmd_lsroutes, cmd_lscards;
|
||||||
static grub_command_t cmd_dhcp, cmd_lsaddr;
|
static grub_command_t cmd_lsaddr;
|
||||||
|
|
||||||
GRUB_MOD_INIT(net)
|
GRUB_MOD_INIT(net)
|
||||||
{
|
{
|
||||||
|
@ -1279,24 +963,19 @@ GRUB_MOD_INIT(net)
|
||||||
"", N_("list network cards"));
|
"", N_("list network cards"));
|
||||||
cmd_lsaddr = grub_register_command ("net_ls_addr", grub_cmd_listaddrs,
|
cmd_lsaddr = grub_register_command ("net_ls_addr", grub_cmd_listaddrs,
|
||||||
"", N_("list network addresses"));
|
"", N_("list network addresses"));
|
||||||
cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp,
|
grub_bootp_init ();
|
||||||
"[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_fs_register (&grub_net_fs);
|
grub_fs_register (&grub_net_fs);
|
||||||
grub_net_open = grub_net_open_real;
|
grub_net_open = grub_net_open_real;
|
||||||
grub_file_net_seek = grub_net_seek_real;
|
fini_hnd = grub_loader_register_preboot_hook (grub_net_fini_hw,
|
||||||
grub_grubnet_fini = grub_grubnet_fini_real;
|
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_MOD_FINI(net)
|
||||||
{
|
{
|
||||||
|
grub_bootp_fini ();
|
||||||
grub_unregister_command (cmd_addaddr);
|
grub_unregister_command (cmd_addaddr);
|
||||||
grub_unregister_command (cmd_deladdr);
|
grub_unregister_command (cmd_deladdr);
|
||||||
grub_unregister_command (cmd_addroute);
|
grub_unregister_command (cmd_addroute);
|
||||||
|
@ -1304,9 +983,9 @@ GRUB_MOD_FINI(net)
|
||||||
grub_unregister_command (cmd_lsroutes);
|
grub_unregister_command (cmd_lsroutes);
|
||||||
grub_unregister_command (cmd_lscards);
|
grub_unregister_command (cmd_lscards);
|
||||||
grub_unregister_command (cmd_lsaddr);
|
grub_unregister_command (cmd_lsaddr);
|
||||||
grub_unregister_command (cmd_getdhcp);
|
|
||||||
grub_fs_unregister (&grub_net_fs);
|
grub_fs_unregister (&grub_net_fs);
|
||||||
grub_net_open = NULL;
|
grub_net_open = NULL;
|
||||||
grub_file_net_seek = NULL;
|
grub_net_fini_hw (0);
|
||||||
grub_grubnet_fini = NULL;
|
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/misc.h>
|
||||||
#include <grub/net/tftp.h>
|
|
||||||
#include <grub/net/udp.h>
|
#include <grub/net/udp.h>
|
||||||
#include <grub/net/ip.h>
|
#include <grub/net/ip.h>
|
||||||
#include <grub/net/ethernet.h>
|
#include <grub/net/ethernet.h>
|
||||||
|
@ -11,6 +28,180 @@
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
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
|
static grub_err_t
|
||||||
tftp_open (struct grub_file *file, const char *filename)
|
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;
|
tftp_data_t data;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
|
||||||
data = grub_malloc (sizeof (*data));
|
data = grub_zalloc (sizeof (*data));
|
||||||
if (!data)
|
if (!data)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
file->device->net->socket->data = (void *) data;
|
|
||||||
nb.head = open_data;
|
nb.head = open_data;
|
||||||
nb.end = open_data + sizeof (open_data);
|
nb.end = open_data + sizeof (open_data);
|
||||||
grub_netbuff_clear (&nb);
|
grub_netbuff_clear (&nb);
|
||||||
|
|
||||||
grub_netbuff_reserve (&nb, 1500);
|
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;
|
return err;
|
||||||
|
|
||||||
tftph = (struct tftphdr *) nb.data;
|
tftph = (struct tftphdr *) nb.data;
|
||||||
|
@ -68,111 +259,86 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||||
rrq += grub_strlen ("0") + 1;
|
rrq += grub_strlen ("0") + 1;
|
||||||
hdrlen = sizeof (tftph->opcode) + rrqlen;
|
hdrlen = sizeof (tftph->opcode) + rrqlen;
|
||||||
|
|
||||||
if ((err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen))) != GRUB_ERR_NONE)
|
err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen));
|
||||||
return err;
|
|
||||||
file->device->net->socket->out_port = TFTP_SERVER_PORT;
|
|
||||||
|
|
||||||
err = grub_net_send_udp_packet (file->device->net->socket, &nb);
|
|
||||||
if (err)
|
if (err)
|
||||||
return 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. */
|
/* Receive OACK packet. */
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
grub_net_poll_cards (100);
|
grub_net_poll_cards (100);
|
||||||
if (grub_errno)
|
if (grub_errno)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
if (file->device->net->socket->status != 0)
|
if (data->have_oack)
|
||||||
break;
|
break;
|
||||||
/* Retry. */
|
/* Retry. */
|
||||||
/*err = grub_net_send_udp_packet (file->device->net->socket, &nb);
|
err = grub_net_send_udp_packet (data->sock, &nb);
|
||||||
if (err)
|
if (err)
|
||||||
return err; */
|
{
|
||||||
|
grub_net_udp_close (data->sock);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->device->net->socket->status == 0)
|
if (!data->have_oack)
|
||||||
return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp.");
|
{
|
||||||
|
grub_net_udp_close (data->sock);
|
||||||
|
return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp.");
|
||||||
|
}
|
||||||
file->size = data->file_size;
|
file->size = data->file_size;
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
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;
|
tftp_data_t data = file->data;
|
||||||
char nbdata[128];
|
|
||||||
tftp_data_t data = sock->data;
|
|
||||||
grub_err_t err;
|
|
||||||
char *ptr;
|
|
||||||
struct grub_net_buff nb_ack;
|
|
||||||
|
|
||||||
nb_ack.head = nbdata;
|
if (data->sock)
|
||||||
nb_ack.end = nbdata + sizeof (nbdata);
|
|
||||||
|
|
||||||
|
|
||||||
tftph = (struct tftphdr *) nb->data;
|
|
||||||
switch (grub_be_to_cpu16 (tftph->opcode))
|
|
||||||
{
|
{
|
||||||
case TFTP_OACK:
|
char nbdata[512];
|
||||||
for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;)
|
grub_err_t err;
|
||||||
{
|
struct grub_net_buff nb_err;
|
||||||
if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0)
|
struct tftphdr *tftph;
|
||||||
{
|
|
||||||
data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1,
|
|
||||||
0, 0);
|
|
||||||
}
|
|
||||||
while (ptr < nb->tail && *ptr)
|
|
||||||
ptr++;
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
sock->status = 1;
|
|
||||||
data->block = 0;
|
|
||||||
grub_netbuff_clear (nb);
|
|
||||||
break;
|
|
||||||
case TFTP_DATA:
|
|
||||||
if ((err = grub_netbuff_pull (nb, sizeof (tftph->opcode) +
|
|
||||||
sizeof (tftph->u.data.block))) != GRUB_ERR_NONE)
|
|
||||||
return err;
|
|
||||||
if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1)
|
|
||||||
{
|
|
||||||
data->block++;
|
|
||||||
unsigned size = nb->tail - nb->data;
|
|
||||||
if (size < 1024)
|
|
||||||
sock->status = 2;
|
|
||||||
/* Prevent garbage in broken cards. */
|
|
||||||
if (size > 1024)
|
|
||||||
if ((err = grub_netbuff_unput (nb, size - 1024)) != GRUB_ERR_NONE)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
grub_netbuff_clear (nb);
|
|
||||||
|
|
||||||
break;
|
nb_err.head = nbdata;
|
||||||
case TFTP_ERROR:
|
nb_err.end = nbdata + sizeof (nbdata);
|
||||||
grub_netbuff_clear (nb);
|
|
||||||
return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg);
|
grub_netbuff_clear (&nb_err);
|
||||||
break;
|
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_free (data);
|
||||||
grub_netbuff_reserve (&nb_ack, 128);
|
|
||||||
err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode)
|
|
||||||
+ sizeof (tftph->u.ack.block));
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
tftph = (struct tftphdr *) nb_ack.data;
|
|
||||||
tftph->opcode = grub_cpu_to_be16 (TFTP_ACK);
|
|
||||||
tftph->u.ack.block = grub_cpu_to_be16 (data->block);
|
|
||||||
|
|
||||||
err = grub_net_send_udp_packet (sock, &nb_ack);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
tftp_close (struct grub_file *file __attribute__ ((unused)))
|
|
||||||
{
|
|
||||||
grub_free (file->device->net->socket->data);
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +346,6 @@ static struct grub_net_app_protocol grub_tftp_protocol =
|
||||||
{
|
{
|
||||||
.name = "tftp",
|
.name = "tftp",
|
||||||
.open = tftp_open,
|
.open = tftp_open,
|
||||||
.read = tftp_receive,
|
|
||||||
.close = tftp_close
|
.close = tftp_close
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,46 @@
|
||||||
#include <grub/net/netbuff.h>
|
#include <grub/net/netbuff.h>
|
||||||
#include <grub/time.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_err_t
|
||||||
grub_net_send_udp_packet (const grub_net_socket_t socket,
|
grub_net_send_udp_packet (const grub_net_socket_t socket,
|
||||||
struct grub_net_buff *nb)
|
struct grub_net_buff *nb)
|
||||||
|
@ -16,14 +56,14 @@ grub_net_send_udp_packet (const grub_net_socket_t socket,
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
udph = (struct udphdr *) nb->data;
|
udph = (struct udphdr *) nb->data;
|
||||||
udph->src = grub_cpu_to_be16 (socket->in_port);
|
udph->src = grub_cpu_to_be16 (socket->x_in_port);
|
||||||
udph->dst = grub_cpu_to_be16 (socket->out_port);
|
udph->dst = grub_cpu_to_be16 (socket->x_out_port);
|
||||||
|
|
||||||
/* No chechksum. */
|
/* No chechksum. */
|
||||||
udph->chksum = 0;
|
udph->chksum = 0;
|
||||||
udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
|
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
|
grub_err_t
|
||||||
|
@ -32,30 +72,28 @@ grub_net_recv_udp_packet (struct grub_net_buff * nb,
|
||||||
{
|
{
|
||||||
struct udphdr *udph;
|
struct udphdr *udph;
|
||||||
grub_net_socket_t sock;
|
grub_net_socket_t sock;
|
||||||
|
grub_err_t err;
|
||||||
udph = (struct udphdr *) nb->data;
|
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)
|
FOR_NET_SOCKETS (sock)
|
||||||
{
|
{
|
||||||
if (grub_be_to_cpu16 (udph->dst) == sock->in_port
|
if (grub_be_to_cpu16 (udph->dst) == sock->x_in_port
|
||||||
&& inf == sock->inf && sock->app)
|
&& inf == sock->x_inf && sock->recv_hook)
|
||||||
{
|
{
|
||||||
if (sock->status == 0)
|
if (sock->x_status == GRUB_NET_SOCKET_START)
|
||||||
sock->out_port = grub_be_to_cpu16 (udph->src);
|
{
|
||||||
|
sock->x_out_port = grub_be_to_cpu16 (udph->src);
|
||||||
|
sock->x_status = GRUB_NET_SOCKET_ESTABLISHED;
|
||||||
|
}
|
||||||
|
|
||||||
/* App protocol remove its own reader. */
|
/* App protocol remove its own reader. */
|
||||||
sock->app->read (sock, nb);
|
sock->recv_hook (sock, nb, sock->recv_hook_data);
|
||||||
|
|
||||||
/* If there is data, puts packet in socket list. */
|
|
||||||
if ((nb->tail - nb->data) > 0)
|
|
||||||
grub_net_put_packet (&sock->packs, nb);
|
|
||||||
else
|
|
||||||
grub_netbuff_free (nb);
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (grub_be_to_cpu16 (udph->dst) == 68)
|
|
||||||
grub_net_process_dhcp (nb, inf->card);
|
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,16 @@
|
||||||
{ 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
|
{ 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 \
|
#define GRUB_EFI_DEVICE_PATH_GUID \
|
||||||
{ 0x09576e91, 0x6d3f, 0x11d2, \
|
{ 0x09576e91, 0x6d3f, 0x11d2, \
|
||||||
{ 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
|
{ 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 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_BLACK 0x00
|
||||||
#define GRUB_EFI_BLUE 0x01
|
#define GRUB_EFI_BLUE 0x01
|
||||||
#define GRUB_EFI_GREEN 0x02
|
#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 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
|
struct grub_efi_block_io
|
||||||
{
|
{
|
||||||
grub_efi_uint64_t revision;
|
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_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_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_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)
|
#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
|
#else
|
||||||
|
@ -1250,24 +1359,31 @@ typedef struct grub_efi_block_io grub_efi_block_io_t;
|
||||||
#define efi_call_0(func) \
|
#define efi_call_0(func) \
|
||||||
efi_wrap_0(func)
|
efi_wrap_0(func)
|
||||||
#define efi_call_1(func, a) \
|
#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) \
|
#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) \
|
#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) \
|
#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, \
|
efi_wrap_4(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
|
||||||
(grub_uint64_t) d)
|
(grub_uint64_t) (c), (grub_uint64_t) (d))
|
||||||
#define efi_call_5(func, a, b, c, d, e) \
|
#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, \
|
efi_wrap_5(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
|
||||||
(grub_uint64_t) d, (grub_uint64_t) e)
|
(grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e))
|
||||||
#define efi_call_6(func, a, b, c, d, e, f) \
|
#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, \
|
efi_wrap_6(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
|
||||||
(grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f)
|
(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) \
|
#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, \
|
efi_wrap_10(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \
|
||||||
(grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f, (grub_uint64_t) g, \
|
(grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \
|
||||||
(grub_uint64_t) h, (grub_uint64_t) i, (grub_uint64_t) j)
|
(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_0) (void *func);
|
||||||
grub_uint64_t EXPORT_FUNC(efi_wrap_1) (void *func, grub_uint64_t arg1);
|
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 arg2, grub_uint64_t arg3,
|
||||||
grub_uint64_t arg4, grub_uint64_t arg5,
|
grub_uint64_t arg4, grub_uint64_t arg5,
|
||||||
grub_uint64_t arg6);
|
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 EXPORT_FUNC(efi_wrap_10) (void *func, grub_uint64_t arg1,
|
||||||
grub_uint64_t arg2, grub_uint64_t arg3,
|
grub_uint64_t arg2, grub_uint64_t arg3,
|
||||||
grub_uint64_t arg4, grub_uint64_t arg5,
|
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_uint32_t descriptor_version,
|
||||||
grub_efi_memory_descriptor_t *virtual_map);
|
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_init (void);
|
||||||
void grub_efi_mm_fini (void);
|
void grub_efi_mm_fini (void);
|
||||||
void grub_efi_init (void);
|
void grub_efi_init (void);
|
||||||
|
|
|
@ -44,6 +44,8 @@ extern grub_int32_t grub_install_bsd_part;
|
||||||
/* The boot BIOS drive number. */
|
/* The boot BIOS drive number. */
|
||||||
extern grub_uint8_t EXPORT_VAR(grub_boot_drive);
|
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 /* ! ASM_FILE */
|
||||||
|
|
||||||
#endif /* ! KERNEL_MACHINE_HEADER */
|
#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;
|
extern struct grub_pxe_bangpxe *grub_pxe_pxenv;
|
||||||
|
|
||||||
void grub_pxe_unload (void);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* GRUB_CPU_PXE_H */
|
#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_ihandle_t;
|
||||||
typedef grub_uint32_t grub_ieee1275_phandle_t;
|
typedef grub_uint32_t grub_ieee1275_phandle_t;
|
||||||
|
|
||||||
struct grub_ofnetcard_data
|
extern void (*EXPORT_VAR(grub_ieee1275_net_config)) (const char *dev,
|
||||||
{
|
char **device,
|
||||||
char *path;
|
char **path);
|
||||||
grub_ieee1275_ihandle_t handle;
|
|
||||||
grub_uint32_t mtu;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Maps a device alias to a pathname. */
|
/* Maps a device alias to a pathname. */
|
||||||
extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen);
|
extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen);
|
||||||
|
@ -203,5 +200,6 @@ int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook)
|
||||||
alias));
|
alias));
|
||||||
char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path);
|
char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path);
|
||||||
char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path);
|
char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path);
|
||||||
|
char *EXPORT_FUNC(grub_ieee1275_get_device_type) (const char *path);
|
||||||
|
|
||||||
#endif /* ! GRUB_IEEE1275_HEADER */
|
#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);
|
void EXPORT_FUNC(grub_machine_fini) (void);
|
||||||
|
|
||||||
/* The machine-specific prefix initialization. */
|
/* 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. */
|
/* Register all the exported symbols. This is automatically generated. */
|
||||||
void grub_register_exported_symbols (void);
|
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[];
|
extern char grub_prefix[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* GRUB -- GRand Unified Bootloader
|
* 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
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -60,32 +60,14 @@ struct grub_net_card_driver
|
||||||
{
|
{
|
||||||
struct grub_net_card_driver *next;
|
struct grub_net_card_driver *next;
|
||||||
char *name;
|
char *name;
|
||||||
grub_err_t (*init) (struct grub_net_card *dev);
|
grub_err_t (*open) (const struct grub_net_card *dev);
|
||||||
grub_err_t (*fini) (struct grub_net_card *dev);
|
void (*close) (const struct grub_net_card *dev);
|
||||||
grub_err_t (*send) (const struct grub_net_card *dev,
|
grub_err_t (*send) (const struct grub_net_card *dev,
|
||||||
struct grub_net_buff *buf);
|
struct grub_net_buff *buf);
|
||||||
grub_ssize_t (*recv) (const struct grub_net_card *dev,
|
grub_ssize_t (*recv) (const struct grub_net_card *dev,
|
||||||
struct grub_net_buff *buf);
|
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
|
typedef struct grub_net_packet
|
||||||
{
|
{
|
||||||
struct grub_net_packet *next;
|
struct grub_net_packet *next;
|
||||||
|
@ -100,6 +82,10 @@ typedef struct grub_net_packets
|
||||||
grub_net_packet_t *last;
|
grub_net_packet_t *last;
|
||||||
} grub_net_packets_t;
|
} grub_net_packets_t;
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_EFI
|
||||||
|
#include <grub/efi/api.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
struct grub_net_card
|
struct grub_net_card
|
||||||
{
|
{
|
||||||
struct grub_net_card *next;
|
struct grub_net_card *next;
|
||||||
|
@ -107,8 +93,19 @@ struct grub_net_card
|
||||||
struct grub_net_card_driver *driver;
|
struct grub_net_card_driver *driver;
|
||||||
grub_net_link_level_address_t default_address;
|
grub_net_link_level_address_t default_address;
|
||||||
grub_net_card_flags_t flags;
|
grub_net_card_flags_t flags;
|
||||||
|
int num_ifaces;
|
||||||
|
int opened;
|
||||||
|
unsigned idle_poll_delay_ms;
|
||||||
|
grub_uint64_t last_poll;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
#ifdef GRUB_MACHINE_EFI
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
struct grub_efi_simple_network *efi_net;
|
||||||
|
grub_efi_handle_t efi_handle;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
void *data;
|
void *data;
|
||||||
int data_num;
|
int data_num;
|
||||||
};
|
};
|
||||||
|
@ -118,7 +115,7 @@ struct grub_net_network_level_interface;
|
||||||
|
|
||||||
typedef enum grub_network_level_protocol_id
|
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_NET_NETWORK_LEVEL_PROTOCOL_IPV4
|
||||||
} grub_network_level_protocol_id_t;
|
} grub_network_level_protocol_id_t;
|
||||||
|
|
||||||
|
@ -196,22 +193,23 @@ struct grub_net_app_protocol
|
||||||
int (*hook) (const char *filename,
|
int (*hook) (const char *filename,
|
||||||
const struct grub_dirhook_info *info));
|
const struct grub_dirhook_info *info));
|
||||||
grub_err_t (*open) (struct grub_file *file, const char *filename);
|
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 (*close) (struct grub_file *file);
|
||||||
grub_err_t (*label) (grub_device_t device, char **label);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct grub_net_socket
|
struct grub_net_socket
|
||||||
{
|
{
|
||||||
struct grub_net_socket *next;
|
struct grub_net_socket *next;
|
||||||
int status;
|
|
||||||
int in_port;
|
enum { GRUB_NET_SOCKET_START,
|
||||||
int out_port;
|
GRUB_NET_SOCKET_ESTABLISHED,
|
||||||
grub_net_app_level_t app;
|
GRUB_NET_SOCKET_CLOSED } x_status;
|
||||||
grub_net_network_level_address_t out_nla;
|
int x_in_port;
|
||||||
struct grub_net_network_level_interface *inf;
|
int x_out_port;
|
||||||
grub_net_packets_t packs;
|
grub_err_t (*recv_hook) (grub_net_socket_t sock, struct grub_net_buff *nb,
|
||||||
void *data;
|
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;
|
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
|
typedef struct grub_net
|
||||||
{
|
{
|
||||||
|
char *server;
|
||||||
char *name;
|
char *name;
|
||||||
grub_net_app_level_t protocol;
|
grub_net_app_level_t protocol;
|
||||||
grub_net_socket_t socket;
|
grub_net_packets_t packs;
|
||||||
|
grub_off_t offset;
|
||||||
grub_fs_t fs;
|
grub_fs_t fs;
|
||||||
|
int eof;
|
||||||
} *grub_net_t;
|
} *grub_net_t;
|
||||||
|
|
||||||
extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name);
|
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
|
||||||
{
|
{
|
||||||
struct grub_net_network_level_interface *next;
|
struct grub_net_network_level_interface *next;
|
||||||
struct grub_net_network_level_interface **prev;
|
struct grub_net_network_level_interface **prev;
|
||||||
char *name;
|
char *name;
|
||||||
const struct grub_net_card *card;
|
struct grub_net_card *card;
|
||||||
grub_net_network_level_address_t address;
|
grub_net_network_level_address_t address;
|
||||||
grub_net_link_level_address_t hwaddress;
|
grub_net_link_level_address_t hwaddress;
|
||||||
grub_net_interface_flags_t flags;
|
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 *
|
struct grub_net_network_level_interface *
|
||||||
grub_net_add_addr (const char *name,
|
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_network_level_address_t addr,
|
||||||
grub_net_link_level_address_t hwaddress,
|
grub_net_link_level_address_t hwaddress,
|
||||||
grub_net_interface_flags_t flags);
|
grub_net_interface_flags_t flags);
|
||||||
|
@ -334,14 +333,12 @@ grub_net_card_register (struct grub_net_card *card)
|
||||||
GRUB_AS_LIST (card));
|
GRUB_AS_LIST (card));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
void
|
||||||
grub_net_card_unregister (struct grub_net_card *card)
|
grub_net_card_unregister (struct grub_net_card *card);
|
||||||
{
|
|
||||||
grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards),
|
|
||||||
GRUB_AS_LIST (card));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next)
|
#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 *
|
struct grub_net_session *
|
||||||
grub_net_open_tcp (char *address, grub_uint16_t port);
|
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 server_ip;
|
||||||
grub_uint32_t gateway_ip;
|
grub_uint32_t gateway_ip;
|
||||||
grub_net_bootp_mac_addr_t mac_addr;
|
grub_net_bootp_mac_addr_t mac_addr;
|
||||||
grub_uint8_t server_name[64];
|
char server_name[64];
|
||||||
grub_uint8_t boot_file[128];
|
char boot_file[128];
|
||||||
grub_uint8_t vendor[0];
|
grub_uint8_t vendor[0];
|
||||||
} __attribute__ ((packed));
|
} __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 *
|
struct grub_net_network_level_interface *
|
||||||
grub_net_configure_by_dhcp_ack (const char *name,
|
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,
|
grub_net_interface_flags_t flags,
|
||||||
const struct grub_net_bootp_packet *bp,
|
const struct grub_net_bootp_packet *bp,
|
||||||
grub_size_t size);
|
grub_size_t size,
|
||||||
|
int is_def, char **device, char **path);
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_net_process_dhcp (struct grub_net_buff *nb,
|
grub_net_process_dhcp (struct grub_net_buff *nb,
|
||||||
const struct grub_net_card *card);
|
struct grub_net_card *card);
|
||||||
|
|
||||||
int
|
int
|
||||||
grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a,
|
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;
|
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)
|
#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,
|
#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)
|
||||||
struct grub_net_buff *nb,
|
|
||||||
grub_net_link_level_address_t *target);
|
|
||||||
|
|
||||||
typedef int
|
|
||||||
(*grub_net_packet_handler_t) (struct grub_net_buff *nb,
|
|
||||||
struct grub_net_network_level_interface *inf);
|
|
||||||
|
|
||||||
grub_err_t grub_net_recv_link_layer (struct grub_net_network_level_interface *inf,
|
|
||||||
grub_net_packet_handler_t handler);
|
|
||||||
|
|
||||||
|
|
||||||
grub_err_t
|
|
||||||
grub_net_recv_ip_packets (struct grub_net_buff *nb,
|
|
||||||
const struct grub_net_card *card,
|
|
||||||
const grub_net_link_level_address_t *hwaddress);
|
|
||||||
|
|
||||||
grub_err_t
|
|
||||||
grub_net_send_ip_packet (struct grub_net_network_level_interface *inf,
|
|
||||||
const grub_net_network_level_address_t *target,
|
|
||||||
struct grub_net_buff *nb);
|
|
||||||
|
|
||||||
#define FOR_NET_NL_PACKETS(inf, var) FOR_PACKETS(inf->nl_pending, var)
|
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_net_poll_cards (unsigned time);
|
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 */
|
#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
|
#ifndef GRUB_NET_ETHERNET_HEADER
|
||||||
#define GRUB_NET_ETHERNET_HEADER 1
|
#define GRUB_NET_ETHERNET_HEADER 1
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/net.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 */
|
/* IANA Ethertype */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -32,7 +28,6 @@ enum
|
||||||
GRUB_NET_ETHERTYPE_ARP = 0x0806
|
GRUB_NET_ETHERTYPE_ARP = 0x0806
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
send_ethernet_packet (struct grub_net_network_level_interface *inf,
|
send_ethernet_packet (struct grub_net_network_level_interface *inf,
|
||||||
struct grub_net_buff *nb,
|
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
|
#ifndef GRUB_NET_IP_HEADER
|
||||||
#define GRUB_NET_IP_HEADER 1
|
#define GRUB_NET_IP_HEADER 1
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
|
||||||
struct iphdr {
|
enum
|
||||||
grub_uint8_t verhdrlen;
|
{
|
||||||
grub_uint8_t service;
|
IP_UDP = 0x11 /* UDP protocol */
|
||||||
grub_uint16_t len;
|
};
|
||||||
grub_uint16_t ident;
|
|
||||||
grub_uint16_t frags;
|
|
||||||
grub_uint8_t ttl;
|
|
||||||
grub_uint8_t protocol;
|
|
||||||
grub_uint16_t chksum;
|
|
||||||
grub_uint32_t src;
|
|
||||||
grub_uint32_t dest;
|
|
||||||
} __attribute__ ((packed)) ;
|
|
||||||
|
|
||||||
struct ip6hdr
|
|
||||||
{
|
|
||||||
grub_uint8_t version:4, priority:4;
|
|
||||||
grub_uint8_t flow_lbl[3];
|
|
||||||
grub_uint16_t payload_len;
|
|
||||||
grub_uint8_t nexthdr;
|
|
||||||
grub_uint8_t hop_limit;
|
|
||||||
grub_uint8_t saddr[16];
|
|
||||||
grub_uint8_t daddr[16];
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
|
|
||||||
#define IP_UDP 0x11 /* UDP protocol */
|
|
||||||
#define IP_BROADCAST 0xFFFFFFFF
|
#define IP_BROADCAST 0xFFFFFFFF
|
||||||
|
|
||||||
grub_uint16_t ipchksum(void *ipv, int len);
|
grub_uint16_t grub_net_ip_chksum(void *ipv, int len);
|
||||||
void ipv4_ini(void);
|
|
||||||
void ipv4_fini(void);
|
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
|
#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;
|
grub_uint16_t chksum;
|
||||||
} __attribute__ ((packed));
|
} __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_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_err_t
|
||||||
grub_net_recv_udp_packet (struct grub_net_buff *nb,
|
grub_net_recv_udp_packet (struct grub_net_buff *nb,
|
||||||
struct grub_net_network_level_interface *inf);
|
struct grub_net_network_level_interface *inf);
|
||||||
|
|
||||||
|
|
||||||
#define FOR_NET_UDP_PACKETS(inf, var) FOR_PACKETS(inf->udp_pending, var)
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -169,8 +169,10 @@
|
||||||
/* Non-zero value is only needed for PowerMacs. */
|
/* Non-zero value is only needed for PowerMacs. */
|
||||||
#define GRUB_KERNEL_I386_IEEE1275_MOD_GAP 0x0
|
#define GRUB_KERNEL_I386_IEEE1275_MOD_GAP 0x0
|
||||||
#define GRUB_KERNEL_I386_COREBOOT_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_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_LOONGSON_MOD_ALIGN 0x1
|
||||||
#define GRUB_KERNEL_MIPS_ARC_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_size = core_size + sizeof (*aout_head);
|
||||||
aout_img = xmalloc (aout_size);
|
aout_img = xmalloc (aout_size);
|
||||||
aout_head = aout_img;
|
aout_head = aout_img;
|
||||||
|
grub_memset (aout_head, 0, sizeof (*aout_head));
|
||||||
aout_head->a_midmag = grub_host_to_target32 ((AOUT_MID_SUN << 16)
|
aout_head->a_midmag = grub_host_to_target32 ((AOUT_MID_SUN << 16)
|
||||||
| AOUT32_OMAGIC);
|
| AOUT32_OMAGIC);
|
||||||
aout_head->a_text = grub_host_to_target32 (core_size);
|
aout_head->a_text = grub_host_to_target32 (core_size);
|
||||||
|
|
|
@ -45,6 +45,12 @@ debug=no
|
||||||
debug_image=
|
debug_image=
|
||||||
subdir=`echo /boot/grub | sed ${transform}`
|
subdir=`echo /boot/grub | sed ${transform}`
|
||||||
pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc
|
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
|
# Usage: usage
|
||||||
# Print the usage.
|
# Print the usage.
|
||||||
|
@ -196,11 +202,20 @@ process_input_dir ()
|
||||||
config_opt="-c ${grubdir}/load.cfg "
|
config_opt="-c ${grubdir}/load.cfg "
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
prefix="/${subdir}/${platform}";
|
||||||
case "${platform}" in
|
case "${platform}" in
|
||||||
i386-pc) mkimage_target=i386-pc-pxe;
|
i386-pc) mkimage_target=i386-pc-pxe;
|
||||||
netmodules="pxe";
|
netmodules="pxe";
|
||||||
prefix="(pxe)/${subdir}/${platform}";
|
|
||||||
ext=0 ;;
|
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};
|
*) echo Unsupported platform ${platform};
|
||||||
exit 1;;
|
exit 1;;
|
||||||
esac
|
esac
|
||||||
|
@ -209,13 +224,31 @@ process_input_dir ()
|
||||||
source ${subdir}/grub.cfg
|
source ${subdir}/grub.cfg
|
||||||
EOF
|
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"
|
echo "Netboot directory for ${platform} created. Configure your DHCP server to point to ${subdir}/${platform}/core.$ext"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "${override_dir}" = "" ] ; then
|
if [ "${override_dir}" = "" ] ; then
|
||||||
if test -e "${pc_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
|
fi
|
||||||
else
|
else
|
||||||
source "${override_dir}"/modinfo.sh
|
source "${override_dir}"/modinfo.sh
|
||||||
|
|
Loading…
Add table
Reference in a new issue