[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] PXE support for grub2
From: |
Marco Gerards |
Subject: |
Re: [PATCH] PXE support for grub2 |
Date: |
Mon, 04 Aug 2008 23:08:46 +0200 |
User-agent: |
Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux) |
Hi,
Bean <address@hidden> 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 <address@hidden>
>
> * 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
> address@hidden
> http://lists.gnu.org/mailman/listinfo/grub-devel