grub-devel
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]