Hi, Bean <[EMAIL PROTECTED]> writes:
> This patch add the (pxe) device that can be used to load files using > the pxe service. It also add a user land command pxe that can be used > to show pxe information as well as set some parameter. Great! :-) > To create a pxe boot image: > > ./grub-mkimage -d . -o core.img pxe > cat pxeboot.img core.img > g2pxe > > g2pxe is the pxe boot file, copy it to tftp server, you also need to > copy *.mod, fs.lst, command.lst, moddep.lst and grub.cfg to /boot/grub > directory in the tftp server. > > To test it in qemu, copy the files to directory such as /tftp, then: > > qemu -boot n -tftp /tftp -bootp /g2pxe > > usage for pxe command: > > pxe info > Show information about pxe, like block size, client ip, etc. > > pxe blksize size > Set block size. tftp transfer in trunks of bytes, the size can be > configured. The minimum size is 512, which is also the default. The > maximum size is 1432. Normally, you can increase download speed by > setting larger block size, but some old tftp server may not support > it. Also, qemu doesn't support size other than 512. > > pxe unload > Unload the pxe runtime environment. Actually, I would prefer: pxe --info pxe --blksize=size pxe --unload You kinda reimplemented an argument parser. The advantage of the build in argument parser is that it supports generation of --help documentation and it supports tab completion. > Please note that this patch depends on my other patch bufio, you need > to apply that first. > > 2008-07-30 Bean <[EMAIL PROTECTED]> > > * boot/i386/pc/pxeboot.S: Use drive number 0x7F for pxe. Isn't it in _start? * 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. > > * kern/i386/pc/init.c (make_install_device): Set root to (pxe) for pxe > boot. > > * 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. > > -- > Bean > > diff --git a/boot/i386/pc/pxeboot.S b/boot/i386/pc/pxeboot.S > index 7f2a143..62a4fb2 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 Please update the copyright year of files you change. IIRC this file is not from this year. I often forget to mention this, but it applies in general. > > /* 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 100755 > index 0000000..6bf3045 > --- /dev/null > +++ b/commands/i386/pc/pxecmd.c > @@ -0,0 +1,92 @@ > +/* 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 <http://www.gnu.org/licenses/>. > + */ > + > +#include <grub/normal.h> > +#include <grub/dl.h> > +#include <grub/arg.h> > +#include <grub/err.h> > +#include <grub/misc.h> > +#include <grub/machine/pxe.h> > + > +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 __attribute__ ((unused)), > + int argc, char **args) > +{ > + if (! grub_pxe_pxenv) > + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment"); > + > + if ((argc == 0) || (! grub_strcmp (args[0], "info"))) > + { > + 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"); > + } > + else if (! grub_strcmp (args[0], "blksize")) > + { > + int size; > + > + if (argc < 2) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no blksize specified"); > + > + size = grub_strtoul (args[1], 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; > + } > + else if (! grub_strcmp (args[0], "unload")) > + { > + 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 info | blksize size | unload", > + "Show information about PXE.", 0); > +} > + > +GRUB_MOD_FINI(pxecmd) > +{ > + grub_unregister_command ("pxe"); > +} > diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk > index 8617a92..59fc6a3 100644 > --- a/conf/i386-pc.rmk > +++ b/conf/i386-pc.rmk > @@ -50,7 +50,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) > @@ -158,7 +159,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 > @@ -325,4 +326,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 = disk/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/disk/i386/pc/pxe.c b/disk/i386/pc/pxe.c > new file mode 100644 > index 0000000..ced1088 > --- /dev/null > +++ b/disk/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 <http://www.gnu.org/licenses/>. > + */ > + > +#include <grub/dl.h> > +#include <grub/fs.h> > +#include <grub/mm.h> > +#include <grub/disk.h> > +#include <grub/file.h> > +#include <grub/misc.h> > +#include <grub/bufio.h> > + > +#include <grub/machine/pxe.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_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); Is it save to use this memory? > + 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); filesystems belong in fs/ > + } > +} > + > +GRUB_MOD_FINI(pxe) > +{ > + grub_pxe_unload (); > +} > diff --git a/include/grub/disk.h b/include/grub/disk.h > index 0e27892..16765d0 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 100755 > index 0000000..43fec80 > --- /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 <http://www.gnu.org/licenses/>. > + */ > + > +#ifndef GRUB_CPU_PXE_H > +#define GRUB_CPU_PXE_H > + > +#include <grub/types.h> > + > +#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)); Can you GRUB-ify the comments here and below a bit? > +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]; Please don't use a tab here. > +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/init.c b/kern/i386/pc/init.c > index e47cbfd..646545e 100644 > --- a/kern/i386/pc/init.c > +++ b/kern/i386/pc/init.c > @@ -71,14 +71,19 @@ make_install_device (void) > if (grub_root_drive == 0xFF) > grub_root_drive = grub_boot_drive; > > - grub_sprintf (dev, "(%cd%u", (grub_root_drive & 0x80) ? 'h' : 'f', > - grub_root_drive & 0x7f); > + if (grub_root_drive == 0x7F) > + grub_strcpy (dev, "(pxe"); > + else > + { > + grub_sprintf (dev, "(%cd%u", (grub_root_drive & 0x80) ? 'h' : 'f', > + grub_root_drive & 0x7f); > > - if (grub_install_dos_part >= 0) > - grub_sprintf (dev + grub_strlen (dev), ",%u", grub_install_dos_part + > 1); > + if (grub_install_dos_part >= 0) > + grub_sprintf (dev + grub_strlen (dev), ",%u", grub_install_dos_part > + 1); > > - if (grub_install_bsd_part >= 0) > - grub_sprintf (dev + grub_strlen (dev), ",%c", grub_install_bsd_part + > 'a'); > + if (grub_install_bsd_part >= 0) > + grub_sprintf (dev + grub_strlen (dev), ",%c", grub_install_bsd_part > + 'a'); > + } > > grub_sprintf (dev + grub_strlen (dev), ")%s", grub_prefix); > grub_strcpy (grub_prefix, dev); > diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S > index 75c46ad..679ad1f 100644 > --- a/kern/i386/pc/startup.S > +++ b/kern/i386/pc/startup.S > @@ -2053,3 +2053,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 > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel