Hallo GRUB hackers !

Here is the 'cvs diff -u' from my worktree and a fresh checked out
(utc: 2000-04-04, about 17:00).

Following features are supported:

        Grub can be downloaded diskless from a boot server
        (boopt and tftp). I used the neboot-0.9.0 package as boot ROM
        on a NE2000 (Relatek 8019), the boot ROM is the only thing I
        used from this package. I think etherboot works as well, but
        I have to check, if it is allowed to load to address 0x8000 !

        Grub detects, that is was netbooted and runs a bootp by itself.
        Further it sets up the root to the network, to be prepared
        to run a menu.lst from the server.

        While the bootp process, the tag T99 of the bootptab is
        evaluated. The string T99 tells GRUB which 'menu.lst' it should
        use. Example:

                machine1:\
                        :ip=196.1.1.71:\
                        :ha=004F4C08AE7E:\
                        :bf=indy1/nbGrub:\
                        :T99="/tftpboot/indy1/root/boot/grub/menu.lst":\
                        :tc=.default:

        If the menu is found, it is displayed.

Building up a netbootable GRUB

        At the moment, ther are problems with the automake setup,
        so I have tested my patch by editing the Makefile directly.
        After CVS handlings and rerunning of the ./configure script
        I lost my patched Makefile.

        Please give me a hint, how can I use the automake,etc,
        environment.

        All C-files use the new GRUB_DISKLESS macro to setup for
        netbootable diskless GRUB.

        I added to the makefile the 

                make nbGrub

        rule, to build up a ready netbootable image of grub. For this
        the 'mknbi-grub' script is called with following parameters:

                mknbi-grub nbloader stage2 nbGrub

        This has to be executed under stage2 subdir. 'nbloader' is
        the netboot boot sector, stage2 is the normal stage2 binary
        and nbGrub is the output of the script.

        The 'nbloder.S' includes the netboot header and has to be
        compiled in the same way as the 'start' module.

        The ./configure script should get something like
        
                --enable-diskless

        and set the -DGRUB_DISKLESS (not implemented yet, I added
        -DGRUB_DISKLESS to the 'NET_CONFIG' to test in the 
        'stage2/Makefile' and 'netboot/Makefile'.

What I send in this mail:

        I will attach the 'cvs diff -u' output of the source tree
        (all build related files are not included, as mentioned above),
        and the 3 new files:


                grub-diff-20000405.log  - cvs diff file
                
                stage2/nbloader.S       - the netboot header
                stage2/netbooted.h      - header needed by some
                                          stage2, netboot and mknbi-grub
                stage2/mknbi-grub       - a script to generate nbGrub


*** By the way, I patched a fix in builtin.c, where 'grub_memcmp'
*** used instead of 'grub_strcmp'. !!!

Cheers, and I hope I could help !!!

        Christoph Plattner


----------------------------------------------------------------------
priavate:                               office:
Christoph Plattner              
Murraygasse 40/1/9              
A-1220 Wien                     
[EMAIL PROTECTED]               [EMAIL PROTECTED]
/* -*-Asm-*- */
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 1996   Erich Boleyn  <[EMAIL PROTECTED]>
 *  Copyright (C) 1999,2000   Free Software Foundation, Inc.
 *
 *  This program 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 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stage1.h>
#include <netbooted.h>
                
/*
 *  defines for the code go here
 */

        /* Absolute addresses
           This makes the assembler generate the address without support
           from the linker. (ELF can't relocate 16-bit addresses!) */
#define ABS(x) (x-_start+0x7c00)

        .file   "stage1_nb.S"

        .text

        /* Tell GAS to generate 16-bit instructions so that this code works
           in real mode. */
        .code16

.globl _start; _start:
        /*
         * _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00
         */

        /*
         * netboot image header
         */

        .long NETBOOT_MAGIC
        .long 0x00000004
        .word NETBOOT_DEST_ADDR
                                /* load address of the first block  */
        .word 0x0000  
        .word NETBOOT_DEST_ADDR + 0x0200
                                /* start addr of the code (stage 2) */
        .word 0x0000

        .long 0x04000004
        .long NETBOOT_DEST_ADDR + 0x0200
        .long (MAX_STAGE2_BLOCKS * 512)
        .long (MAX_STAGE2_BLOCKS * 512)
        
        . = _start + STAGE1_PARTEND

/* the last 2 bytes in the sector 0 contain the signature */
        .word   STAGE1_SIGNATURE






/*  -*-c-*-
 * $Id$
 *  
 * Abstract:
 *     File for diskless grub support
 * 
 * Modifications:
 * $Log$
 *
 */

#ifndef __netbooted_h__
#define __netbooted_h__

#define NETBOOT_MAGIC          0x1B031336
#define NETBOOT_DEST_ADDR      0x8000
#define BOOTP_GRUBMENU_TAG     99
#define MAX_STAGE2_BLOCKS      200

#ifdef GRUB_DISKLESS
int grub_netbooted(void);
#endif

#endif /* __netbooted_h__ */
? stage2/nbloader.S
? stage2/mknbi-grub
? stage2/netbooted.h
Index: grub/asmstub.c
===================================================================
RCS file: /cvs/grub/grub/asmstub.c,v
retrieving revision 1.45
diff -u -r1.45 asmstub.c
--- grub/asmstub.c      2000/04/02 17:22:53     1.45
+++ grub/asmstub.c      2000/04/04 22:35:36
@@ -86,6 +86,10 @@
 char version_string[] = VERSION;
 char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */
 
+#ifdef GRUB_DISKLESS
+char config_file_nb[128] = "/tftpboot/grub/menu.lst"; /* FIXME: arbitrary */
+#endif
+
 /* Emulation requirements. */
 char *grub_scratch_mem = 0;
 
Index: netboot/main.c
===================================================================
RCS file: /cvs/grub/netboot/main.c,v
retrieving revision 1.5
diff -u -r1.5 main.c
--- netboot/main.c      2000/02/12 07:00:47     1.5
+++ netboot/main.c      2000/04/04 22:35:43
@@ -34,6 +34,11 @@
 
 #include <netboot_config.h>
 
+#ifdef GRUB_DISKLESS
+#include "netbooted.h"
+extern char config_file_nb[];
+#endif
+
 struct arptable_t arptable[MAX_ARP];
 
 /* Set if the user pushes Control-C.  */
@@ -866,6 +871,19 @@
              p++;
              continue;
            }
+#ifdef GRUB_DISKLESS
+         else if (c == BOOTP_GRUBMENU_TAG)  /* special code */
+           {
+             int l;
+               
+              p++;
+             l = (int)(*(char *)p);
+             p++;
+             grub_memmove((void *)config_file_nb,p,l);
+             p += l;
+             continue;
+           }
+#endif /* GRUB_DISKLESS */
          else if (c == RFC1533_END)
            {
              end_of_rfc1533 = end = p;
Index: stage2/asm.S
===================================================================
RCS file: /cvs/grub/stage2/asm.S,v
retrieving revision 1.26
diff -u -r1.26 asm.S
--- stage2/asm.S        2000/02/07 05:14:46     1.26
+++ stage2/asm.S        2000/04/04 22:35:47
@@ -82,7 +82,18 @@
        .long   0xffffffff
        .string "/boot/grub/stage2"
 #endif  /* STAGE1_5 */
-
+       
+       /*
+        * for diskless grub operation, this string will be patched by
+        * by the bootp tag !
+        */
+       
+#ifdef GRUB_DISKLESS
+VARIABLE(config_file_nb)
+       .string "/tftpboot/grub/menu.lst"
+       .string "** some more place **"
+#endif
+       
        /*
         *  Leave some breathing room for the config file name.
         */
Index: stage2/builtins.c
===================================================================
RCS file: /cvs/grub/stage2/builtins.c,v
retrieving revision 1.53
diff -u -r1.53 builtins.c
--- stage2/builtins.c   2000/04/03 12:22:20     1.53
+++ stage2/builtins.c   2000/04/04 22:35:57
@@ -1832,23 +1832,23 @@
 
   /* If the option `--type=TYPE' is specified, convert the string to
      a kernel type.  */
-  if (grub_memcmp (arg, "--type=") == 0)
+  if (grub_strcmp (arg, "--type=") == 0)
     {
       arg += 7;
       
-      if (grub_memcmp (arg, "netbsd") == 0)
+      if (grub_strcmp (arg, "netbsd") == 0)
        suggested_type = KERNEL_TYPE_NETBSD;
-      else if (grub_memcmp (arg, "freebsd") == 0)
+      else if (grub_strcmp (arg, "freebsd") == 0)
        suggested_type = KERNEL_TYPE_FREEBSD;
-      else if (grub_memcmp (arg, "openbsd") == 0)
+      else if (grub_strcmp (arg, "openbsd") == 0)
        /* XXX: For now, OpenBSD is identical to NetBSD, from GRUB's
           point of view.  */
        suggested_type = KERNEL_TYPE_NETBSD;
-      else if (grub_memcmp (arg, "linux") == 0)
+      else if (grub_strcmp (arg, "linux") == 0)
        suggested_type = KERNEL_TYPE_LINUX;
-      else if (grub_memcmp (arg, "biglinux") == 0)
+      else if (grub_strcmp (arg, "biglinux") == 0)
        suggested_type = KERNEL_TYPE_BIG_LINUX;
-      else if (grub_memcmp (arg, "multiboot") == 0)
+      else if (grub_strcmp (arg, "multiboot") == 0)
        suggested_type = KERNEL_TYPE_MULTIBOOT;
       else
        {
@@ -2937,6 +2937,28 @@
   " installed.  Any system address range maps are discarded."
 };
 
+/*
+ * support for diskless grub operations
+ */
+#ifdef GRUB_DISKLESS
+
+int grub_setup_nd(void)
+{
+    if (bootp_func((char *)NULL, 0))
+    {
+       grub_printf("\n%s: error return of bootp_func\n",__FUNCTION__);
+       return(-1);
+    }
+    if (root_func("(nd)",0)) 
+    {
+       grub_printf("\n%s: error return of root_func\n",__FUNCTION__);
+       return(-1);
+    }
+    print_root_device ();
+    return(0);
+}
+
+#endif /* GRUB_DISKLESS */
 
 /* The table of builtin commands. Sorted in dictionary order.  */
 struct builtin *builtin_table[] =
Index: stage2/shared.h
===================================================================
RCS file: /cvs/grub/stage2/shared.h,v
retrieving revision 1.40
diff -u -r1.40 shared.h
--- stage2/shared.h     2000/04/03 12:22:20     1.40
+++ stage2/shared.h     2000/04/04 22:36:04
@@ -421,6 +421,9 @@
 extern unsigned long boot_part_offset;
 extern char version_string[];
 extern char config_file[];
+#ifdef GRUB_DISKLESS
+extern char config_file_nb[];
+#endif
 
 #ifdef GRUB_UTIL
 /* If not using config file, this variable is set to zero,
Index: stage2/stage2.c
===================================================================
RCS file: /cvs/grub/stage2/stage2.c,v
retrieving revision 1.12
diff -u -r1.12 stage2.c
--- stage2/stage2.c     2000/04/02 17:22:53     1.12
+++ stage2/stage2.c     2000/04/04 22:36:06
@@ -19,6 +19,10 @@
 
 #include "shared.h"
 
+#ifdef GRUB_DISKLESS
+#include "netbooted.h"
+#endif
+
 grub_jmp_buf restart_env;
 
 static char *
@@ -571,7 +575,27 @@
   return pos;
 }
 
+/*
+ * query if grub was diskless netbooted
+ */
+
+#ifdef GRUB_DISKLESS
+
+int grub_netbooted(void)
+{
+    /*
+     * check for netboot header magic
+     */
+    if (*((unsigned *) RAW_ADDR ( NETBOOT_DEST_ADDR )) == NETBOOT_MAGIC)
+    {
+       grub_printf ("\nGrub was netbooted\n");
+       return(1);
+    }
+    return(0);
+}
 
+#endif /* GRUB_DISKLESS */
+
 /* This is the starting function in C.  */
 void
 cmain (void)
@@ -579,6 +603,7 @@
   int config_len, menu_len, num_entries;
   char *config_entries, *menu_entries;
   char *kill = (char *) KILL_BUF;
+  char *cfg_file;
 
   /* Initialize the environment for restarting Stage 2.  */
   grub_setjmp (restart_env);
@@ -596,12 +621,38 @@
       menu_entries = (char *) MENU_BUF;
       init_config ();
 
+#ifdef GRUB_DISKLESS
+
+#ifdef GRUB_UTIL
+      if (use_config_file)
+        {
+#endif
+          if (grub_netbooted())
+            {
+              int r;
+              extern int grub_setup_nd(void);
+
+              (void) grub_setup_nd();
+              cfg_file = config_file_nb;
+            }
+          else
+            {
+              cfg_file = config_file;
+            }
+#ifdef GRUB_UTIL
+       }
+#endif   
+
+#else  /* ! GRUB_DISKLESS */
+      cfg_file = config_file;
+#endif /* GRUB_DISKLESS */
+
       /* Here load the configuration file.  */
 
 #ifdef GRUB_UTIL
-      if (use_config_file && grub_open (config_file))
+      if (use_config_file && grub_open (cfg_file))
 #else
-      if (grub_open (config_file))
+      if (grub_open (cfg_file))
 #endif
        {
          /* STATE 0:  Before any title command.
#!/bin/bash
#++
#
#   $Id$
#
#   mknbi-xxxx creates a netboot image of grub
#
#   usage:
#         mknbi-grub stage1_nb stage2 nb-imagename
#   $Log$
#
#--

# set -x

INC_CONF_H=./netbooted.h

if [ ! -f $CFG_INC ] ; then
        echo $0: cannot find $CFG_INC, abort.
        exit 1
fi

if [ $# -lt 3 ] ; then
        echo $0: invalid numbers of arguments "($#)", abort.
        exit 1
fi

NBIMAGE=$3
BOOTPATH=`dirname $1`

if [ ! -f $1 ] ; then
        echo $0: cannont find boot sector $1, abort.
        exit 1
fi

if [ ! -f $2 ] ; then
        echo $0: cannont find input image $2, abort.
        exit 1
fi

cp $1 $NBIMAGE
dd if=$2 of=$BOOTPATH/tmpImage bs=512 skip=1
cat $BOOTPATH/tmpImage >> $NBIMAGE

MAXBLKS=`grep "MAX_STAGE2_BLOCKS" $INC_CONF_H | \
         sed 's/^.*\( [0-9abcdefABCDEF]\)/\1/' |\
         sed 's/ //'`

echo Configured block size is $MAXBLKS

set dummy `ls -l $BOOTPATH/tmpImage`
echo $6
PADZERO=$(($MAXBLKS * 512 - $6))

dd if=/dev/zero of=$BOOTPATH/zeropad bs=1 count=$PADZERO
cat $BOOTPATH/zeropad >> $NBIMAGE

rm -f $BOOTPATH/tmpImage $BOOTPATH/zeropad
echo $NBIMAGE is written
sync


Reply via email to