From 9e7007b310fbdc663390af532ada0a4eed801156 Mon Sep 17 00:00:00 2001 From: bean Date: Tue, 5 Aug 2008 15:15:59 +0000 Subject: [PATCH] 2008-08-05 Bean * boot/i386/pc/pxeboot.S (_start): Use drive number 0x7F for pxe. * conf/i386-pc.rmk (kernel_img_HEADERS): Add machine/pxe.h. (pkglib_MODULES): Add pxe.mod and pxecmd.mod. (pxe_mod_SOURCES): New macro. (pxe_mod_CFLAGS): Likewise. (pxe_mod_LDFLAGS): Likewise. (pxecmd_mod_SOURCES): Likewise. (pxecmd_mod_CFLAGS): Likewise. (pxecmd_mod_LDFLAGS): Likewise. * kern/i386/pc/startup.S (grub_pxe_scan): New function. (grub_pxe_call): Likewise. * include/grub/disk.h (grub_disk_dev_id): Add GRUB_DISK_DEVICE_PXE_ID. * commands/i386/pc/pxecmd.c: New file. * disk/i386/pc/pxe.c: Likewise. * include/grub/i386/pc/pxe.h: Likewise. --- ChangeLog | 24 +++ boot/i386/pc/pxeboot.S | 3 +- commands/i386/pc/pxecmd.c | 96 +++++++++++ conf/i386-pc.mk | 119 ++++++++++++- conf/i386-pc.rmk | 15 +- conf/x86_64-efi.mk | 47 +++++- fs/i386/pc/pxe.c | 335 +++++++++++++++++++++++++++++++++++++ include/grub/disk.h | 1 + include/grub/i386/pc/pxe.h | 318 +++++++++++++++++++++++++++++++++++ kern/i386/pc/startup.S | 99 +++++++++++ 10 files changed, 1048 insertions(+), 9 deletions(-) create mode 100644 commands/i386/pc/pxecmd.c create mode 100644 fs/i386/pc/pxe.c create mode 100644 include/grub/i386/pc/pxe.h diff --git a/ChangeLog b/ChangeLog index f6ac4191b..d7d6a820c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2008-08-05 Bean + + * boot/i386/pc/pxeboot.S (_start): Use drive number 0x7F for pxe. + + * conf/i386-pc.rmk (kernel_img_HEADERS): Add machine/pxe.h. + (pkglib_MODULES): Add pxe.mod and pxecmd.mod. + (pxe_mod_SOURCES): New macro. + (pxe_mod_CFLAGS): Likewise. + (pxe_mod_LDFLAGS): Likewise. + (pxecmd_mod_SOURCES): Likewise. + (pxecmd_mod_CFLAGS): Likewise. + (pxecmd_mod_LDFLAGS): Likewise. + + * kern/i386/pc/startup.S (grub_pxe_scan): New function. + (grub_pxe_call): Likewise. + + * include/grub/disk.h (grub_disk_dev_id): Add GRUB_DISK_DEVICE_PXE_ID. + + * commands/i386/pc/pxecmd.c: New file. + + * disk/i386/pc/pxe.c: Likewise. + + * include/grub/i386/pc/pxe.h: Likewise. + 2008-08-05 Bean * util/console.c (grub_console_cur_color): New variable. diff --git a/boot/i386/pc/pxeboot.S b/boot/i386/pc/pxeboot.S index 7f2a14396..4fdff764f 100644 --- a/boot/i386/pc/pxeboot.S +++ b/boot/i386/pc/pxeboot.S @@ -26,7 +26,8 @@ .globl _start; _start: /* Root drive will default to boot drive */ - movb $0xFF, %dh + movb $0xFF, %dh + movb $0x7F, %dl /* Jump to the real world */ ljmp $0, $0x8200 diff --git a/commands/i386/pc/pxecmd.c b/commands/i386/pc/pxecmd.c new file mode 100644 index 000000000..bf4afa228 --- /dev/null +++ b/commands/i386/pc/pxecmd.c @@ -0,0 +1,96 @@ +/* pxe.c - command to control the pxe driver */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 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 . + */ + +#include +#include +#include +#include +#include +#include + +static const struct grub_arg_option options[] = +{ + {"info", 'i', 0, "show PXE information.", 0, 0}, + {"bsize", 'b', 0, "set PXE block size", 0, ARG_TYPE_INT}, + {"unload", 'u', 0, "unload PXE stack.", 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +static void +print_ip (grub_uint32_t ip) +{ + int i; + + for (i = 0; i < 3; i++) + { + grub_printf ("%d.", ip & 0xFF); + ip >>= 8; + } + grub_printf ("%d", ip); +} + +static grub_err_t +grub_cmd_pxe (struct grub_arg_list *state, int argc, char **args) +{ + if (! grub_pxe_pxenv) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment"); + + if (state[1].set) + { + int size; + + size = grub_strtoul (state[1].arg, 0, 0); + if (size < GRUB_PXE_MIN_BLKSIZE) + size = GRUB_PXE_MIN_BLKSIZE; + else if (size > GRUB_PXE_MAX_BLKSIZE) + size = GRUB_PXE_MAX_BLKSIZE; + + grub_pxe_blksize = size; + } + + if (state[0].set) + { + grub_printf ("blksize : %d\n", grub_pxe_blksize); + grub_printf ("client ip : "); + print_ip (grub_pxe_your_ip); + grub_printf ("\nserver ip : "); + print_ip (grub_pxe_server_ip); + grub_printf ("\ngateway ip : "); + print_ip (grub_pxe_gateway_ip); + grub_printf ("\n"); + } + + if (state[2].set) + grub_pxe_unload (); + + return 0; +} + +GRUB_MOD_INIT(pxecmd) +{ + (void) mod; /* To stop warning. */ + grub_register_command ("pxe", grub_cmd_pxe, GRUB_COMMAND_FLAG_BOTH, + "pxe [-i|-b|-u]", + "Command to control the PXE device.", options); +} + +GRUB_MOD_FINI(pxecmd) +{ + grub_unregister_command ("pxe"); +} diff --git a/conf/i386-pc.mk b/conf/i386-pc.mk index 71d975817..edbf0cf8f 100644 --- a/conf/i386-pc.mk +++ b/conf/i386-pc.mk @@ -225,7 +225,8 @@ kernel_img_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \ machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \ - machine/memory.h machine/loader.h machine/vga.h machine/vbe.h machine/kernel.h + machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \ + machine/kernel.h machine/pxe.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,$(GRUB_MEMORY_MACHINE_LINK_ADDR) $(COMMON_CFLAGS) @@ -899,7 +900,7 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \ vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \ videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod \ ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \ - aout.mod _bsd.mod bsd.mod + aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod # For biosdisk.mod. biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c @@ -3058,4 +3059,118 @@ partmap-bsd_mod-loader_i386_bsd_normal.lst: loader/i386/bsd_normal.c $(loader/i3 bsd_mod_CFLAGS = $(COMMON_CFLAGS) bsd_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For pxe.mod +pxe_mod_SOURCES = fs/i386/pc/pxe.c +CLEANFILES += pxe.mod mod-pxe.o mod-pxe.c pre-pxe.o pxe_mod-fs_i386_pc_pxe.o und-pxe.lst +ifneq ($(pxe_mod_EXPORTS),no) +CLEANFILES += def-pxe.lst +DEFSYMFILES += def-pxe.lst +endif +MOSTLYCLEANFILES += pxe_mod-fs_i386_pc_pxe.d +UNDSYMFILES += und-pxe.lst + +pxe.mod: pre-pxe.o mod-pxe.o $(TARGET_OBJ2ELF) + -rm -f $@ + $(TARGET_CC) $(pxe_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-pxe.o mod-pxe.o + if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@ + +pre-pxe.o: $(pxe_mod_DEPENDENCIES) pxe_mod-fs_i386_pc_pxe.o + -rm -f $@ + $(TARGET_CC) $(pxe_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pxe_mod-fs_i386_pc_pxe.o + +mod-pxe.o: mod-pxe.c + $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxe_mod_CFLAGS) -c -o $@ $< + +mod-pxe.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'pxe' $< > $@ || (rm -f $@; exit 1) + +ifneq ($(pxe_mod_EXPORTS),no) +def-pxe.lst: pre-pxe.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 pxe/' > $@ +endif + +und-pxe.lst: pre-pxe.o + echo 'pxe' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +pxe_mod-fs_i386_pc_pxe.o: fs/i386/pc/pxe.c $(fs/i386/pc/pxe.c_DEPENDENCIES) + $(TARGET_CC) -Ifs/i386/pc -I$(srcdir)/fs/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxe_mod_CFLAGS) -MD -c -o $@ $< +-include pxe_mod-fs_i386_pc_pxe.d + +CLEANFILES += cmd-pxe_mod-fs_i386_pc_pxe.lst fs-pxe_mod-fs_i386_pc_pxe.lst partmap-pxe_mod-fs_i386_pc_pxe.lst +COMMANDFILES += cmd-pxe_mod-fs_i386_pc_pxe.lst +FSFILES += fs-pxe_mod-fs_i386_pc_pxe.lst +PARTMAPFILES += partmap-pxe_mod-fs_i386_pc_pxe.lst + +cmd-pxe_mod-fs_i386_pc_pxe.lst: fs/i386/pc/pxe.c $(fs/i386/pc/pxe.c_DEPENDENCIES) gencmdlist.sh + set -e; $(TARGET_CC) -Ifs/i386/pc -I$(srcdir)/fs/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxe_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh pxe > $@ || (rm -f $@; exit 1) + +fs-pxe_mod-fs_i386_pc_pxe.lst: fs/i386/pc/pxe.c $(fs/i386/pc/pxe.c_DEPENDENCIES) genfslist.sh + set -e; $(TARGET_CC) -Ifs/i386/pc -I$(srcdir)/fs/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxe_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh pxe > $@ || (rm -f $@; exit 1) + +partmap-pxe_mod-fs_i386_pc_pxe.lst: fs/i386/pc/pxe.c $(fs/i386/pc/pxe.c_DEPENDENCIES) genpartmaplist.sh + set -e; $(TARGET_CC) -Ifs/i386/pc -I$(srcdir)/fs/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxe_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh pxe > $@ || (rm -f $@; exit 1) + + +pxe_mod_CFLAGS = $(COMMON_CFLAGS) +pxe_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For pxecmd.mod +pxecmd_mod_SOURCES = commands/i386/pc/pxecmd.c +CLEANFILES += pxecmd.mod mod-pxecmd.o mod-pxecmd.c pre-pxecmd.o pxecmd_mod-commands_i386_pc_pxecmd.o und-pxecmd.lst +ifneq ($(pxecmd_mod_EXPORTS),no) +CLEANFILES += def-pxecmd.lst +DEFSYMFILES += def-pxecmd.lst +endif +MOSTLYCLEANFILES += pxecmd_mod-commands_i386_pc_pxecmd.d +UNDSYMFILES += und-pxecmd.lst + +pxecmd.mod: pre-pxecmd.o mod-pxecmd.o $(TARGET_OBJ2ELF) + -rm -f $@ + $(TARGET_CC) $(pxecmd_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-pxecmd.o mod-pxecmd.o + if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@ + +pre-pxecmd.o: $(pxecmd_mod_DEPENDENCIES) pxecmd_mod-commands_i386_pc_pxecmd.o + -rm -f $@ + $(TARGET_CC) $(pxecmd_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pxecmd_mod-commands_i386_pc_pxecmd.o + +mod-pxecmd.o: mod-pxecmd.c + $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxecmd_mod_CFLAGS) -c -o $@ $< + +mod-pxecmd.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'pxecmd' $< > $@ || (rm -f $@; exit 1) + +ifneq ($(pxecmd_mod_EXPORTS),no) +def-pxecmd.lst: pre-pxecmd.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 pxecmd/' > $@ +endif + +und-pxecmd.lst: pre-pxecmd.o + echo 'pxecmd' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +pxecmd_mod-commands_i386_pc_pxecmd.o: commands/i386/pc/pxecmd.c $(commands/i386/pc/pxecmd.c_DEPENDENCIES) + $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxecmd_mod_CFLAGS) -MD -c -o $@ $< +-include pxecmd_mod-commands_i386_pc_pxecmd.d + +CLEANFILES += cmd-pxecmd_mod-commands_i386_pc_pxecmd.lst fs-pxecmd_mod-commands_i386_pc_pxecmd.lst partmap-pxecmd_mod-commands_i386_pc_pxecmd.lst +COMMANDFILES += cmd-pxecmd_mod-commands_i386_pc_pxecmd.lst +FSFILES += fs-pxecmd_mod-commands_i386_pc_pxecmd.lst +PARTMAPFILES += partmap-pxecmd_mod-commands_i386_pc_pxecmd.lst + +cmd-pxecmd_mod-commands_i386_pc_pxecmd.lst: commands/i386/pc/pxecmd.c $(commands/i386/pc/pxecmd.c_DEPENDENCIES) gencmdlist.sh + set -e; $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxecmd_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh pxecmd > $@ || (rm -f $@; exit 1) + +fs-pxecmd_mod-commands_i386_pc_pxecmd.lst: commands/i386/pc/pxecmd.c $(commands/i386/pc/pxecmd.c_DEPENDENCIES) genfslist.sh + set -e; $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxecmd_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh pxecmd > $@ || (rm -f $@; exit 1) + +partmap-pxecmd_mod-commands_i386_pc_pxecmd.lst: commands/i386/pc/pxecmd.c $(commands/i386/pc/pxecmd.c_DEPENDENCIES) genpartmaplist.sh + set -e; $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxecmd_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh pxecmd > $@ || (rm -f $@; exit 1) + + +pxecmd_mod_CFLAGS = $(COMMON_CFLAGS) +pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS) + include $(srcdir)/conf/common.mk diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index e400ffc63..3e8469e00 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -54,7 +54,8 @@ kernel_img_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \ machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \ - machine/memory.h machine/loader.h machine/vga.h machine/vbe.h machine/kernel.h + machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \ + machine/kernel.h machine/pxe.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,$(GRUB_MEMORY_MACHINE_LINK_ADDR) $(COMMON_CFLAGS) @@ -162,7 +163,7 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \ vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \ videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod \ ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \ - aout.mod _bsd.mod bsd.mod + aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod # For biosdisk.mod. biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c @@ -329,4 +330,14 @@ bsd_mod_SOURCES = loader/i386/bsd_normal.c bsd_mod_CFLAGS = $(COMMON_CFLAGS) bsd_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For pxe.mod +pxe_mod_SOURCES = fs/i386/pc/pxe.c +pxe_mod_CFLAGS = $(COMMON_CFLAGS) +pxe_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For pxecmd.mod +pxecmd_mod_SOURCES = commands/i386/pc/pxecmd.c +pxecmd_mod_CFLAGS = $(COMMON_CFLAGS) +pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS) + include $(srcdir)/conf/common.mk diff --git a/conf/x86_64-efi.mk b/conf/x86_64-efi.mk index 495af8308..8f25993fb 100644 --- a/conf/x86_64-efi.mk +++ b/conf/x86_64-efi.mk @@ -112,13 +112,14 @@ kernel_mod_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \ kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ kern/x86_64/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ + kern/generic/millisleep.c kern/generic/rtc_get_time_ms.c \ term/efi/console.c disk/efi/efidisk.c -CLEANFILES += kernel.mod mod-kernel.o mod-kernel.c pre-kernel.o kernel_mod-kern_x86_64_efi_startup.o kernel_mod-kern_x86_64_efi_callwrap.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_x86_64_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-term_efi_console.o kernel_mod-disk_efi_efidisk.o und-kernel.lst +CLEANFILES += kernel.mod mod-kernel.o mod-kernel.c pre-kernel.o kernel_mod-kern_x86_64_efi_startup.o kernel_mod-kern_x86_64_efi_callwrap.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_x86_64_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-kern_generic_millisleep.o kernel_mod-kern_generic_rtc_get_time_ms.o kernel_mod-term_efi_console.o kernel_mod-disk_efi_efidisk.o und-kernel.lst ifneq ($(kernel_mod_EXPORTS),no) CLEANFILES += def-kernel.lst DEFSYMFILES += def-kernel.lst endif -MOSTLYCLEANFILES += kernel_mod-kern_x86_64_efi_startup.d kernel_mod-kern_x86_64_efi_callwrap.d kernel_mod-kern_main.d kernel_mod-kern_device.d kernel_mod-kern_disk.d kernel_mod-kern_dl.d kernel_mod-kern_file.d kernel_mod-kern_fs.d kernel_mod-kern_err.d kernel_mod-kern_misc.d kernel_mod-kern_mm.d kernel_mod-kern_loader.d kernel_mod-kern_rescue.d kernel_mod-kern_term.d kernel_mod-kern_x86_64_dl.d kernel_mod-kern_i386_efi_init.d kernel_mod-kern_parser.d kernel_mod-kern_partition.d kernel_mod-kern_env.d kernel_mod-symlist.d kernel_mod-kern_efi_efi.d kernel_mod-kern_efi_init.d kernel_mod-kern_efi_mm.d kernel_mod-term_efi_console.d kernel_mod-disk_efi_efidisk.d +MOSTLYCLEANFILES += kernel_mod-kern_x86_64_efi_startup.d kernel_mod-kern_x86_64_efi_callwrap.d kernel_mod-kern_main.d kernel_mod-kern_device.d kernel_mod-kern_disk.d kernel_mod-kern_dl.d kernel_mod-kern_file.d kernel_mod-kern_fs.d kernel_mod-kern_err.d kernel_mod-kern_misc.d kernel_mod-kern_mm.d kernel_mod-kern_loader.d kernel_mod-kern_rescue.d kernel_mod-kern_term.d kernel_mod-kern_x86_64_dl.d kernel_mod-kern_i386_efi_init.d kernel_mod-kern_parser.d kernel_mod-kern_partition.d kernel_mod-kern_env.d kernel_mod-symlist.d kernel_mod-kern_efi_efi.d kernel_mod-kern_efi_init.d kernel_mod-kern_efi_mm.d kernel_mod-kern_generic_millisleep.d kernel_mod-kern_generic_rtc_get_time_ms.d kernel_mod-term_efi_console.d kernel_mod-disk_efi_efidisk.d UNDSYMFILES += und-kernel.lst kernel.mod: pre-kernel.o mod-kernel.o $(TARGET_OBJ2ELF) @@ -127,9 +128,9 @@ kernel.mod: pre-kernel.o mod-kernel.o $(TARGET_OBJ2ELF) if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@ -pre-kernel.o: $(kernel_mod_DEPENDENCIES) kernel_mod-kern_x86_64_efi_startup.o kernel_mod-kern_x86_64_efi_callwrap.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_x86_64_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-term_efi_console.o kernel_mod-disk_efi_efidisk.o +pre-kernel.o: $(kernel_mod_DEPENDENCIES) kernel_mod-kern_x86_64_efi_startup.o kernel_mod-kern_x86_64_efi_callwrap.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_x86_64_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-kern_generic_millisleep.o kernel_mod-kern_generic_rtc_get_time_ms.o kernel_mod-term_efi_console.o kernel_mod-disk_efi_efidisk.o -rm -f $@ - $(TARGET_CC) $(kernel_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ kernel_mod-kern_x86_64_efi_startup.o kernel_mod-kern_x86_64_efi_callwrap.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_x86_64_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-term_efi_console.o kernel_mod-disk_efi_efidisk.o + $(TARGET_CC) $(kernel_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ kernel_mod-kern_x86_64_efi_startup.o kernel_mod-kern_x86_64_efi_callwrap.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_x86_64_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-kern_generic_millisleep.o kernel_mod-kern_generic_rtc_get_time_ms.o kernel_mod-term_efi_console.o kernel_mod-disk_efi_efidisk.o mod-kernel.o: mod-kernel.c $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -c -o $@ $< @@ -583,6 +584,44 @@ partmap-kernel_mod-kern_efi_mm.lst: kern/efi/mm.c $(kern/efi/mm.c_DEPENDENCIES) set -e; $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1) +kernel_mod-kern_generic_millisleep.o: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES) + $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $< +-include kernel_mod-kern_generic_millisleep.d + +CLEANFILES += cmd-kernel_mod-kern_generic_millisleep.lst fs-kernel_mod-kern_generic_millisleep.lst partmap-kernel_mod-kern_generic_millisleep.lst +COMMANDFILES += cmd-kernel_mod-kern_generic_millisleep.lst +FSFILES += fs-kernel_mod-kern_generic_millisleep.lst +PARTMAPFILES += partmap-kernel_mod-kern_generic_millisleep.lst + +cmd-kernel_mod-kern_generic_millisleep.lst: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES) gencmdlist.sh + set -e; $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1) + +fs-kernel_mod-kern_generic_millisleep.lst: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES) genfslist.sh + set -e; $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1) + +partmap-kernel_mod-kern_generic_millisleep.lst: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES) genpartmaplist.sh + set -e; $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1) + + +kernel_mod-kern_generic_rtc_get_time_ms.o: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES) + $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $< +-include kernel_mod-kern_generic_rtc_get_time_ms.d + +CLEANFILES += cmd-kernel_mod-kern_generic_rtc_get_time_ms.lst fs-kernel_mod-kern_generic_rtc_get_time_ms.lst partmap-kernel_mod-kern_generic_rtc_get_time_ms.lst +COMMANDFILES += cmd-kernel_mod-kern_generic_rtc_get_time_ms.lst +FSFILES += fs-kernel_mod-kern_generic_rtc_get_time_ms.lst +PARTMAPFILES += partmap-kernel_mod-kern_generic_rtc_get_time_ms.lst + +cmd-kernel_mod-kern_generic_rtc_get_time_ms.lst: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES) gencmdlist.sh + set -e; $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1) + +fs-kernel_mod-kern_generic_rtc_get_time_ms.lst: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES) genfslist.sh + set -e; $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1) + +partmap-kernel_mod-kern_generic_rtc_get_time_ms.lst: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES) genpartmaplist.sh + set -e; $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1) + + kernel_mod-term_efi_console.o: term/efi/console.c $(term/efi/console.c_DEPENDENCIES) $(TARGET_CC) -Iterm/efi -I$(srcdir)/term/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $< -include kernel_mod-term_efi_console.d diff --git a/fs/i386/pc/pxe.c b/fs/i386/pc/pxe.c new file mode 100644 index 000000000..ced1088a5 --- /dev/null +++ b/fs/i386/pc/pxe.c @@ -0,0 +1,335 @@ +/* pxe.c - Driver to provide access to the pxe filesystem */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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_pxenv *grub_pxe_pxenv; +grub_uint32_t grub_pxe_your_ip; +grub_uint32_t grub_pxe_server_ip; +grub_uint32_t grub_pxe_gateway_ip; +int grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE; + +struct grub_pxe_data +{ + grub_uint32_t packet_number; + char filename[0]; +}; + +static int +grub_pxe_iterate (int (*hook) (const char *name)) +{ + if (hook ("pxe")) + return 1; + return 0; +} + +static grub_err_t +grub_pxe_open (const char *name, grub_disk_t disk) +{ + if (grub_strcmp (name, "pxe")) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a pxe disk"); + + disk->total_sectors = 0; + disk->id = (unsigned long) "pxe"; + + disk->has_partitions = 0; + disk->data = 0; + + return GRUB_ERR_NONE; +} + +static void +grub_pxe_close (grub_disk_t disk __attribute((unused))) +{ +} + +static grub_err_t +grub_pxe_read (grub_disk_t disk __attribute((unused)), + grub_disk_addr_t sector __attribute((unused)), + grub_size_t size __attribute((unused)), + char *buf __attribute((unused))) +{ + return GRUB_ERR_OUT_OF_RANGE; +} + +static grub_err_t +grub_pxe_write (grub_disk_t disk __attribute((unused)), + grub_disk_addr_t sector __attribute((unused)), + grub_size_t size __attribute((unused)), + const char *buf __attribute((unused))) +{ + return GRUB_ERR_OUT_OF_RANGE; +} + +static struct grub_disk_dev grub_pxe_dev = + { + .name = "pxe", + .id = GRUB_DISK_DEVICE_PXE_ID, + .iterate = grub_pxe_iterate, + .open = grub_pxe_open, + .close = grub_pxe_close, + .read = grub_pxe_read, + .write = grub_pxe_write, + .next = 0 + }; + +static grub_err_t +grub_pxefs_dir (grub_device_t device __attribute((unused)), + const char *path __attribute((unused)), + int (*hook) (const char *filename, int dir) __attribute((unused))) +{ + return GRUB_ERR_NONE; +} + +static struct grub_fs grub_pxefs_fs_int; + +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; + + c.c1.server_ip = grub_pxe_server_ip; + c.c1.gateway_ip = grub_pxe_gateway_ip; + grub_strcpy (c.c1.filename, name); + grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1); + if (c.c1.status) + 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); + if (c.c2.status) + return grub_error (GRUB_ERR_BAD_FS, "open fails"); + + data = grub_malloc (sizeof (struct grub_pxe_data) + grub_strlen (name) + 1); + if (! data) + return grub_errno; + + data->packet_number = 0; + grub_strcpy (data->filename, name); + + file_int = grub_malloc (sizeof (*file_int)); + if (! file_int) + { + grub_free (data); + return grub_errno; + } + + file_int->data = data; + file_int->offset = 0; + file_int->device = 0; + file_int->size = file->size; + file_int->read_hook = 0; + file_int->fs = &grub_pxefs_fs_int; + + bufio = grub_bufio_open (file_int, grub_pxe_blksize); + if (! bufio) + { + grub_free (file_int); + grub_free (data); + return grub_errno; + } + + file->data = bufio; + + return GRUB_ERR_NONE; +} + +static grub_ssize_t +grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len) +{ + grub_file_t bufio; + + bufio = file->data; + bufio->offset = file->offset; + + return bufio->fs->read (bufio, buf, len); +} + +static grub_ssize_t +grub_pxefs_close (grub_file_t file) +{ + grub_file_close ((grub_file_t) file->data); + + return grub_errno; +} + +static grub_ssize_t +grub_pxefs_read_int (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, r; + + data = file->data; + + pn = grub_divmod64 (file->offset, grub_pxe_blksize, &r); + if (r) + return grub_error (GRUB_ERR_BAD_FS, + "read access must be aligned to packet size"); + + if (data->packet_number > pn) + { + struct grub_pxenv_tftp_open o; + + grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o); + + o.server_ip = grub_pxe_server_ip; + o.gateway_ip = grub_pxe_gateway_ip; + grub_strcpy (o.filename, data->filename); + o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT); + o.packet_size = grub_pxe_blksize; + grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &o); + if (o.status) + return grub_error (GRUB_ERR_BAD_FS, "open fails"); + data->packet_number = 0; + } + + c.buffer = SEGOFS (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + while (pn >= data->packet_number) + { + c.buffer_size = grub_pxe_blksize; + grub_pxe_call (GRUB_PXENV_TFTP_READ, &c); + 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_int (grub_file_t file) +{ + struct grub_pxenv_tftp_close c; + + grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c); + 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 = "pxefs", + .dir = grub_pxefs_dir, + .open = grub_pxefs_open, + .read = grub_pxefs_read, + .close = grub_pxefs_close, + .label = grub_pxefs_label, + .next = 0 + }; + +static struct grub_fs grub_pxefs_fs_int = + { + .name = "pxefs", + .read = grub_pxefs_read_int, + .close = grub_pxefs_close_int, + }; + +static void +grub_pxe_detect (void) +{ + struct grub_pxenv *pxenv; + struct grub_pxenv_get_cached_info ci; + struct grub_pxenv_boot_player *bp; + + pxenv = grub_pxe_scan (); + if (! pxenv) + return; + + ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; + ci.buffer = 0; + ci.buffer_size = 0; + grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci); + if (ci.status) + return; + + bp = LINEAR (ci.buffer); + + grub_pxe_your_ip = bp->your_ip; + grub_pxe_server_ip = bp->server_ip; + grub_pxe_gateway_ip = bp->gateway_ip; + + grub_pxe_pxenv = pxenv; +} + +void +grub_pxe_unload (void) +{ + if (grub_pxe_pxenv) + { + grub_fs_unregister (&grub_pxefs_fs); + grub_disk_dev_unregister (&grub_pxe_dev); + + grub_pxe_pxenv = 0; + } +} + +GRUB_MOD_INIT(pxe) +{ + (void) mod; /* To stop warning. */ + + grub_pxe_detect (); + if (grub_pxe_pxenv) + { + grub_disk_dev_register (&grub_pxe_dev); + grub_fs_register (&grub_pxefs_fs); + } +} + +GRUB_MOD_FINI(pxe) +{ + grub_pxe_unload (); +} diff --git a/include/grub/disk.h b/include/grub/disk.h index 0e2789219..049cc91b9 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -39,6 +39,7 @@ enum grub_disk_dev_id GRUB_DISK_DEVICE_MEMDISK_ID, GRUB_DISK_DEVICE_NAND_ID, GRUB_DISK_DEVICE_UUID_ID, + GRUB_DISK_DEVICE_PXE_ID, }; struct grub_disk; diff --git a/include/grub/i386/pc/pxe.h b/include/grub/i386/pc/pxe.h new file mode 100644 index 000000000..482132896 --- /dev/null +++ b/include/grub/i386/pc/pxe.h @@ -0,0 +1,318 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 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 . + */ + +#ifndef GRUB_CPU_PXE_H +#define GRUB_CPU_PXE_H + +#include + +#define GRUB_PXENV_TFTP_OPEN 0x0020 +#define GRUB_PXENV_TFTP_CLOSE 0x0021 +#define GRUB_PXENV_TFTP_READ 0x0022 +#define GRUB_PXENV_TFTP_READ_FILE 0x0023 +#define GRUB_PXENV_TFTP_READ_FILE_PMODE 0x0024 +#define GRUB_PXENV_TFTP_GET_FSIZE 0x0025 + +#define GRUB_PXENV_UDP_OPEN 0x0030 +#define GRUB_PXENV_UDP_CLOSE 0x0031 +#define GRUB_PXENV_UDP_READ 0x0032 +#define GRUB_PXENV_UDP_WRITE 0x0033 + +#define GRUB_PXENV_START_UNDI 0x0000 +#define GRUB_PXENV_UNDI_STARTUP 0x0001 +#define GRUB_PXENV_UNDI_CLEANUP 0x0002 +#define GRUB_PXENV_UNDI_INITIALIZE 0x0003 +#define GRUB_PXENV_UNDI_RESET_NIC 0x0004 +#define GRUB_PXENV_UNDI_SHUTDOWN 0x0005 +#define GRUB_PXENV_UNDI_OPEN 0x0006 +#define GRUB_PXENV_UNDI_CLOSE 0x0007 +#define GRUB_PXENV_UNDI_TRANSMIT 0x0008 +#define GRUB_PXENV_UNDI_SET_MCAST_ADDR 0x0009 +#define GRUB_PXENV_UNDI_SET_STATION_ADDR 0x000A +#define GRUB_PXENV_UNDI_SET_PACKET_FILTER 0x000B +#define GRUB_PXENV_UNDI_GET_INFORMATION 0x000C +#define GRUB_PXENV_UNDI_GET_STATISTICS 0x000D +#define GRUB_PXENV_UNDI_CLEAR_STATISTICS 0x000E +#define GRUB_PXENV_UNDI_INITIATE_DIAGS 0x000F +#define GRUB_PXENV_UNDI_FORCE_INTERRUPT 0x0010 +#define GRUB_PXENV_UNDI_GET_MCAST_ADDR 0x0011 +#define GRUB_PXENV_UNDI_GET_NIC_TYPE 0x0012 +#define GRUB_PXENV_UNDI_GET_IFACE_INFO 0x0013 +#define GRUB_PXENV_UNDI_ISR 0x0014 +#define GRUB_PXENV_STOP_UNDI 0x0015 +#define GRUB_PXENV_UNDI_GET_STATE 0x0015 + +#define GRUB_PXENV_UNLOAD_STACK 0x0070 +#define GRUB_PXENV_GET_CACHED_INFO 0x0071 +#define GRUB_PXENV_RESTART_DHCP 0x0072 +#define GRUB_PXENV_RESTART_TFTP 0x0073 +#define GRUB_PXENV_MODE_SWITCH 0x0074 +#define GRUB_PXENV_START_BASE 0x0075 +#define GRUB_PXENV_STOP_BASE 0x0076 + +#define GRUB_PXENV_EXIT_SUCCESS 0x0000 +#define GRUB_PXENV_EXIT_FAILURE 0x0001 + +#define GRUB_PXENV_STATUS_SUCCESS 0x00 +#define GRUB_PXENV_STATUS_FAILURE 0x01 +#define GRUB_PXENV_STATUS_BAD_FUNC 0x02 +#define GRUB_PXENV_STATUS_UNSUPPORTED 0x03 +#define GRUB_PXENV_STATUS_KEEP_UNDI 0x04 +#define GRUB_PXENV_STATUS_KEEP_ALL 0x05 +#define GRUB_PXENV_STATUS_OUT_OF_RESOURCES 0x06 +#define GRUB_PXENV_STATUS_ARP_TIMEOUT 0x11 +#define GRUB_PXENV_STATUS_UDP_CLOSED 0x18 +#define GRUB_PXENV_STATUS_UDP_OPEN 0x19 +#define GRUB_PXENV_STATUS_TFTP_CLOSED 0x1A +#define GRUB_PXENV_STATUS_TFTP_OPEN 0x1B +#define GRUB_PXENV_STATUS_MCOPY_PROBLEM 0x20 +#define GRUB_PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21 +#define GRUB_PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22 +#define GRUB_PXENV_STATUS_BIS_INIT_FAILURE 0x23 +#define GRUB_PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24 +#define GRUB_PXENV_STATUS_BIS_GBOA_FAILURE 0x25 +#define GRUB_PXENV_STATUS_BIS_FREE_FAILURE 0x26 +#define GRUB_PXENV_STATUS_BIS_GSI_FAILURE 0x27 +#define GRUB_PXENV_STATUS_BIS_BAD_CKSUM 0x28 +#define GRUB_PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30 +#define GRUB_PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32 + +#define GRUB_PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33 +#define GRUB_PXENV_STATUS_TFTP_READ_TIMEOUT 0x35 +#define GRUB_PXENV_STATUS_TFTP_ERROR_OPCODE 0x36 +#define GRUB_PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38 +#define GRUB_PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39 +#define GRUB_PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3A +#define GRUB_PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3B +#define GRUB_PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3C +#define GRUB_PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3D +#define GRUB_PXENV_STATUS_TFTP_NO_FILESIZE 0x3E +#define GRUB_PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3F +#define GRUB_PXENV_STATUS_DHCP_TIMEOUT 0x51 +#define GRUB_PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52 +#define GRUB_PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53 +#define GRUB_PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54 +#define GRUB_PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60 +#define GRUB_PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61 +#define GRUB_PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62 +#define GRUB_PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63 +#define GRUB_PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64 +#define GRUB_PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65 +#define GRUB_PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66 +#define GRUB_PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67 +#define GRUB_PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68 +#define GRUB_PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69 +#define GRUB_PXENV_STATUS_UNDI_INVALID_STATE 0x6A +#define GRUB_PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6B +#define GRUB_PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6C +#define GRUB_PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74 +#define GRUB_PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76 +#define GRUB_PXENV_STATUS_BSTRAP_MISSING_LIST 0x77 +#define GRUB_PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78 +#define GRUB_PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79 +#define GRUB_PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xA0 +#define GRUB_PXENV_STATUS_BINL_NO_PXE_SERVER 0xA1 +#define GRUB_PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xA2 +#define GRUB_PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xA3 +#define GRUB_PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xB0 +#define GRUB_PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xC0 +#define GRUB_PXENV_STATUS_LOADER_NO_BC_ROMID 0xC1 +#define GRUB_PXENV_STATUS_LOADER_BAD_BC_ROMID 0xC2 +#define GRUB_PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xC3 +#define GRUB_PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xC4 +#define GRUB_PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xC5 +#define GRUB_PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xC6 +#define GRUB_PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xC8 +#define GRUB_PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xC9 +#define GRUB_PXENV_STATUS_LOADER_UNDI_START 0xCA +#define GRUB_PXENV_STATUS_LOADER_BC_START 0xCB + +#define GRUB_PXENV_PACKET_TYPE_DHCP_DISCOVER 1 +#define GRUB_PXENV_PACKET_TYPE_DHCP_ACK 2 +#define GRUB_PXENV_PACKET_TYPE_CACHED_REPLY 3 + +#define GRUB_PXE_BOOTP_REQ 1 +#define GRUB_PXE_BOOTP_REP 2 + +#define GRUB_PXE_BOOTP_BCAST 0x8000 + +#if 1 +#define GRUB_PXE_BOOTP_DHCPVEND 1024 /* DHCP extended vendor field size. */ +#else +#define GRUB_PXE_BOOTP_DHCPVEND 312 /* DHCP standard vendor field size. */ +#endif + +#define GRUB_PXE_MIN_BLKSIZE 512 +#define GRUB_PXE_MAX_BLKSIZE 1432 + +#define GRUB_PXE_TFTP_PORT 69 + +#define GRUB_PXE_VM_RFC1048 0x63825363L + +#define GRUB_PXE_ERR_LEN 0xFFFFFFFF + +#ifndef ASM_FILE + +struct grub_pxenv +{ + grub_uint8_t signature[6]; /* 'PXENV+'. */ + grub_uint16_t version; /* MSB = major, LSB = minor. */ + grub_uint8_t length; /* structure length. */ + grub_uint8_t checksum; /* checksum pad. */ + grub_uint32_t rm_entry; /* SEG:OFF to PXE entry point. */ + grub_uint32_t pm_offset; /* Protected mode entry. */ + grub_uint16_t pm_selector; /* Protected mode selector. */ + grub_uint16_t stack_seg; /* Stack segment address. */ + grub_uint16_t stack_size; /* Stack segment size (bytes). */ + grub_uint16_t bc_code_seg; /* BC Code segment address. */ + grub_uint16_t bc_code_size; /* BC Code segment size (bytes). */ + grub_uint16_t bc_data_seg; /* BC Data segment address. */ + grub_uint16_t bc_data_size; /* BC Data segment size (bytes). */ + grub_uint16_t undi_data_seg; /* UNDI Data segment address. */ + grub_uint16_t undi_data_size; /* UNDI Data segment size (bytes). */ + grub_uint16_t undi_code_seg; /* UNDI Code segment address. */ + grub_uint16_t undi_code_size; /* UNDI Code segment size (bytes). */ + grub_uint32_t pxe_ptr; /* SEG:OFF to !PXE struct. */ +} __attribute__ ((packed)); + +struct grub_pxenv_get_cached_info +{ + grub_uint16_t status; + grub_uint16_t packet_type; + grub_uint16_t buffer_size; + grub_uint32_t buffer; + grub_uint16_t buffer_limit; +} __attribute__ ((packed)); + +#define GRUB_PXE_MAC_ADDR_LEN 16 + +typedef grub_uint8_t grub_pxe_mac_addr[GRUB_PXE_MAC_ADDR_LEN]; + +struct grub_pxenv_boot_player +{ + grub_uint8_t opcode; + grub_uint8_t hw_type; /* hardware type. */ + grub_uint8_t hw_len; /* hardware addr len. */ + grub_uint8_t gate_hops; /* zero it. */ + grub_uint32_t ident; /* random number chosen by client. */ + grub_uint16_t seconds; /* seconds since did initial bootstrap. */ + grub_uint16_t flags; + grub_uint32_t client_ip; + grub_uint32_t your_ip; + grub_uint32_t server_ip; + grub_uint32_t gateway_ip; + grub_pxe_mac_addr mac_addr; + grub_uint8_t server_name[64]; + grub_uint8_t boot_file[128]; + union + { + grub_uint8_t d[GRUB_PXE_BOOTP_DHCPVEND]; /* raw array of vendor/dhcp options. */ + struct + { + grub_uint32_t magic; /* DHCP magic cookie. */ + grub_uint32_t flags; /* bootp flags/opcodes. */ + grub_uint8_t padding[56]; + } v; + } vendor; +} __attribute__ ((packed)); + +struct grub_pxenv_tftp_open +{ + grub_uint16_t status; + grub_uint32_t server_ip; + grub_uint32_t gateway_ip; + grub_uint8_t filename[128]; + grub_uint16_t tftp_port; + grub_uint16_t packet_size; +} __attribute__ ((packed)); + +struct grub_pxenv_tftp_close +{ + grub_uint16_t status; +} __attribute__ ((packed)); + +struct grub_pxenv_tftp_read +{ + grub_uint16_t status; + grub_uint16_t packet_number; + grub_uint16_t buffer_size; + grub_uint32_t buffer; +} __attribute__ ((packed)); + +struct grub_pxenv_tftp_get_fsize +{ + grub_uint16_t status; + grub_uint32_t server_ip; + grub_uint32_t gateway_ip; + grub_uint8_t filename[128]; + grub_uint32_t file_size; +} __attribute__ ((packed)); + +struct grub_pxenv_udp_open +{ + grub_uint16_t status; + grub_uint32_t src_ip; +} __attribute__ ((packed)); + +struct grub_pxenv_udp_close +{ + grub_uint16_t status; +} __attribute__ ((packed)); + +struct grub_pxenv_udp_write +{ + grub_uint16_t status; + grub_uint32_t ip; + grub_uint32_t gateway; + grub_uint16_t src_port; + grub_uint16_t dst_port; + grub_uint16_t buffer_size; + grub_uint32_t buffer; +} __attribute__ ((packed)); + +struct grub_pxenv_udp_read +{ + grub_uint16_t status; + grub_uint32_t src_ip; + grub_uint32_t dst_ip; + grub_uint16_t src_port; + grub_uint16_t dst_port; + grub_uint16_t buffer_size; + grub_uint32_t buffer; +} __attribute__ ((packed)); + +struct grub_pxenv_unload_stack +{ + grub_uint16_t status; + grub_uint8_t reserved[10]; +} __attribute__ ((packed)); + +struct grub_pxenv * EXPORT_FUNC(grub_pxe_scan) (void); +int EXPORT_FUNC(grub_pxe_call) (int func, void * data); + +extern struct grub_pxenv *grub_pxe_pxenv; +extern grub_uint32_t grub_pxe_your_ip; +extern grub_uint32_t grub_pxe_server_ip; +extern grub_uint32_t grub_pxe_gateway_ip; +extern int grub_pxe_blksize; + +void grub_pxe_unload (void); + +#endif + +#endif /* GRUB_CPU_PXE_H */ diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index aa582ac49..197c447e3 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -2054,3 +2054,102 @@ FUNCTION(grub_vbe_bios_set_palette_data) popl %ebx popl %ebp ret + + +pxe_rm_entry: + .long 0 + +/* + * struct grub_pxenv *grub_pxe_scan (void); + */ +FUNCTION(grub_pxe_scan) + pushl %ebp + pushl %ebx + + xorl %ebx, %ebx + xorl %ecx, %ecx + + call prot_to_real + .code16 + + pushw %es + + movw $0x5650, %ax + int $0x1A + cmpw $0x564E, %ax + jnz 1f + cmpl $0x4E455850, %es:(%bx) /* PXEN(V+) */ + jnz 1f + cmpw $0x201, %es:6(%bx) /* API version */ + jb 1f + lesw %es:0x28(%bx), %bx /* !PXE structure */ + cmpl $0x45585021, %es:(%bx) /* !PXE */ + jnz 1f + movw %es, %cx + jmp 2f +1: + xorw %bx, %bx + xorw %cx, %cx +2: + + popw %es + + DATA32 call real_to_prot + .code32 + + xorl %eax, %eax + leal (%eax, %ecx, 4), %ecx + leal (%ebx, %ecx, 4), %eax /* eax = ecx * 16 + ebx */ + + orl %eax, %eax + jz 1f + + movl 0x10(%eax), %ecx + movl %ecx, pxe_rm_entry + +1: + + popl %ebx + popl %ebp + ret + +/* + * int grub_pxe_call (int func, void* data); + */ +FUNCTION(grub_pxe_call) + pushl %ebp + movl %esp, %ebp + pushl %esi + pushl %edi + pushl %ebx + + movl %eax, %ecx + movl %edx, %eax + andl $0xF, %eax + shrl $4, %edx + shll $16, %edx + addl %eax, %edx + movl pxe_rm_entry, %ebx + + call prot_to_real + .code16 + + pushl %ebx + pushl %edx + pushw %cx + movw %sp, %bx + lcall *%ss:6(%bx) + cld + addw $10, %sp + movw %ax, %cx + + DATA32 call real_to_prot + .code32 + + movzwl %cx, %eax + + popl %ebx + popl %edi + popl %esi + popl %ebp + ret