I don't know if any grub users have been forced to use Intel's "PXE"
(preboot execution environment) for netbooting. It's not that it's
badly designed. But Intel can't seem to do it right. *sigh*
Anyway, PXE is happy to load and run any binary, so I figured it would
be great if I could load grub with PXE and let grub do all the complex
stuff. And it was actually pretty easy to get grub to work with PXE.
All I had to do was arrange for stage2 to expect to be loaded at PXE's
load address, namely, 7C00.
But ... Once I got into the #ifdef complexities, I figured that
instead of just adding another #ifdef, I might as well clean things up
and parameterize all of the various origins where grub's stages expect
to be loaded. Thus, the below patch.
Please consider this patch as my small way of thanking all of you for
this really cool utility. Network booting is important for the
project I'm working on, and PXE just isn't reliable. It's cost me a
lot of time and trouble. But from now on, I can just load grub and
let it do all the complex work. And if it breaks, I can fix it!
Thank you!
2000-05-19 Chip Salzenberg <[EMAIL PROTECTED]>
Parameterize load addresses.
Create binary "pxegrub" for use with PXE network boot.
* stage2/Makefile.am (pxegrub): New binary.
(PXEGRUB): New macro for building pxegrub.
(START_ADDR, PRE_STAGE2_ADDR, PXEGRUB_ADDR, STAGE1_5_ADDR):
Define possible origins.
(ADDR_FLAGS): Add them to preprocessor flags.
(ORIGIN): Define as actual origin of current binary.
* stage2/start.S (ABS): Use ORIGIN.
* stage2/asm.S (ABS): Likewise.
(boot_drive): Set to NETWORK_DRIVE if building PXEGRUB.
(offset): Use asterisk on indirect ljmp.
* stage2/builtins.c (install_func): Use origin macros.
* stage2/stage1_5.c (cmain): Likewise.
Index: stage2/Makefile.am
diff -u -2 -r1.23 Makefile.am
--- stage2/Makefile.am 2000/04/15 13:39:38 1.23
+++ stage2/Makefile.am 2000/05/20 05:05:42
@@ -3,4 +3,14 @@
noinst_SCRIPTS = $(TESTS)
+START_ADDR = 8000
+PRE_STAGE2_ADDR = 8200
+PXEGRUB_ADDR = 7C00
+STAGE1_5_ADDR = 2000
+
+ADDR_FLAGS = -DSTART_ADDR=0x$(START_ADDR) \
+ -DPRE_STAGE2_ADDR=0x$(PRE_STAGE2_ADDR) \
+ -DPXEGRUB_ADDR=0x$(PXEGRUB_ADDR) \
+ -DSTAGE1_5_ADDR=0x$(STAGE1_5_ADDR)
+
# For dist target.
noinst_HEADERS = apic.h defs.h dir.h disk_inode.h disk_inode_ffs.h \
@@ -17,5 +27,5 @@
disk_io.c gunzip.c fsys_ffs.c fsys_ext2fs.c fsys_fat.c \
fsys_minix.c fsys_reiserfs.c stage2.c
-libgrub_a_CFLAGS = $(GRUB_CFLAGS) -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 \
+libgrub_a_CFLAGS = $(GRUB_CFLAGS) $(ADDR_FLAGS) -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 \
-DFSYS_FAT=1 -DFSYS_FFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
-fwritable-strings
@@ -23,24 +33,32 @@
# Stage 2 and Stage 1.5's.
pkgdatadir = $(datadir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
-pkgdata_DATA = stage2 e2fs_stage1_5 fat_stage1_5 ffs_stage1_5 \
+pkgdata_DATA = stage2 pxegrub e2fs_stage1_5 fat_stage1_5 ffs_stage1_5 \
minix_stage1_5 reiserfs_stage1_5
noinst_DATA = pre_stage2 start
-noinst_PROGRAMS = pre_stage2.exec start.exec e2fs_stage1_5.exec \
+noinst_PROGRAMS = pre_stage2.exec pxegrub.exec start.exec e2fs_stage1_5.exec \
fat_stage1_5.exec ffs_stage1_5.exec minix_stage1_5.exec \
reiserfs_stage1_5.exec
MOSTLYCLEANFILES = $(noinst_PROGRAMS)
-PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200
-START_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8000
if NETBOOT_SUPPORT
-STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
+STAGE2_COMPILE = $(STAGE2_CFLAGS) $(ADDR_FLAGS) -fno-builtin -nostdinc \
-I$(top_srcdir)/netboot -DSUPPORT_NETBOOT=1
else
-STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc
+STAGE2_COMPILE = $(STAGE2_CFLAGS) $(ADDR_FLAGS) -fno-builtin -nostdinc
endif
+
+START_COMPILE = $(STAGE2_COMPILE) -DORIGIN=START_ADDR
+START_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(START_ADDR)
+
+PRE_STAGE2_COMPILE = $(STAGE2_COMPILE) -DORIGIN=PRE_STAGE2_ADDR
+PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(PRE_STAGE2_ADDR)
-STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
-STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
+PXEGRUB_COMPILE = $(STAGE2_COMPILE) -DORIGIN=PXEGRUB_ADDR -DPXEGRUB=1
+PXEGRUB_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(PXEGRUB_ADDR)
+STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DORIGIN=STAGE1_5_ADDR -DSTAGE1_5=1 \
+ -DNO_DECOMPRESSION=1
+STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(STAGE1_5_ADDR)
+
# For stage2 target.
pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c common.c \
@@ -48,7 +66,6 @@
fsys_fat.c fsys_ffs.c fsys_minix.c fsys_reiserfs.c smp-imps.c \
stage2.c
-pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
+pre_stage2_exec_CFLAGS = $(PRE_STAGE2_COMPILE) $(FSYS_CFLAGS)
pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
-
if NETBOOT_SUPPORT
pre_stage2_exec_LDADD = ../netboot/libdrivers.a
@@ -64,5 +81,5 @@
start_exec_SOURCES = start.S
-start_exec_CFLAGS = $(STAGE2_COMPILE)
+start_exec_CFLAGS = $(START_COMPILE)
start_exec_LDFLAGS = $(START_LINK)
@@ -76,4 +93,13 @@
-rm -f stage2
cat start pre_stage2 > stage2
+
+# For pxegrub target.
+pxegrub_exec_SOURCES = asm.S bios.c boot.c builtins.c common.c \
+ char_io.c cmdline.c disk_io.c gunzip.c fsys_ext2fs.c \
+ fsys_fat.c fsys_ffs.c fsys_minix.c fsys_reiserfs.c smp-imps.c \
+ stage2.c
+pxegrub_exec_CFLAGS = $(PXEGRUB_COMPILE) $(FSYS_CFLAGS)
+pxegrub_exec_LDFLAGS = $(PXEGRUB_LINK)
+pxegrub_exec_LDADD = ../netboot/libdrivers.a
# For e2fs_stage1_5 target.
Index: stage2/start.S
diff -u -2 -r1.2 start.S
--- stage2/start.S 1999/10/21 17:38:49 1.2
+++ stage2/start.S 2000/05/20 05:05:47
@@ -33,9 +33,5 @@
This makes the assembler generate the address without support
from the linker. (ELF can't relocate 16-bit addresses!) */
-#ifdef STAGE1_5
-# define ABS(x) (x-_start+0x2000)
-#else
-# define ABS(x) (x-_start+0x8000)
-#endif /* STAGE1_5 */
+#define ABS(x) ((x) - _start + ORIGIN)
/* Print message string */
@@ -54,6 +50,6 @@
_start:
/*
- * _start is loaded at 0x8000 and is jumped to with
- * CS:IP 0:0x8000 in stage2.
+ * _start is loaded at START_ADDR and is jumped to with
+ * CS:IP 0:START_ADDR in stage2.
*/
@@ -314,9 +310,5 @@
bootit:
popw %dx /* this makes sure %dl is our "boot" drive */
-#ifdef STAGE1_5
- ljmp $0, $0x2200
-#else /* ! STAGE1_5 */
- ljmp $0, $0x8200
-#endif /* ! STAGE1_5 */
+ ljmp $0, $(ORIGIN + 0x200)
Index: stage2/asm.S
diff -u -2 -r1.27 asm.S
--- stage2/asm.S 2000/04/18 11:22:07 1.27
+++ stage2/asm.S 2000/05/20 05:05:42
@@ -23,9 +23,8 @@
#include "shared.h"
-#ifdef STAGE1_5
-#define ABS(x) ((x) - EXT_C(main) + 0x2200)
-#else
-#define ABS(x) ((x) - EXT_C(main) + 0x8200)
-#endif
+ /* 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) - EXT_C(main) + ORIGIN)
.file "asm.S"
@@ -50,6 +49,5 @@
ENTRY(main)
/*
- * Guarantee that "main" is loaded at 0x0:0x8200 in stage2 and
- * at 0x0:0x2200 in stage1.5.
+ * Guarantee that "main" is loaded at 0x0:(ORIGIN+0x200)
*/
ljmp $0, $ABS(codestart)
@@ -108,4 +106,6 @@
sti /* we're safe again */
+#if !defined(PXEGRUB)
+
/* save boot drive reference */
ADDR32 movb %dl, EXT_C(boot_drive)
@@ -114,4 +114,6 @@
int $0x13
+#endif /* !PXEGRUB */
+
/* transition to protected mode */
DATA32 call EXT_C(real_to_prot)
@@ -697,5 +699,5 @@
.code16
- DATA32 ADDR32 ljmp (offset)
+ DATA32 ADDR32 ljmp *(offset)
.code32
#endif /* STAGE1_5 */
@@ -737,5 +739,5 @@
.code16
- DATA32 ADDR32 ljmp (offset)
+ DATA32 ADDR32 ljmp *(offset)
.code32
@@ -1654,5 +1656,5 @@
/* jump to start */
- DATA32 ADDR32 ljmp (offset)
+ DATA32 ADDR32 ljmp *(offset)
.code32
@@ -2073,10 +2075,14 @@
VARIABLE(boot_drive)
+#if defined(PXEGRUB)
+ .long NETWORK_DRIVE
+#else
.long 0
+#endif
/* an address can only be long-jumped to if it is in memory, this
is used by multiple routines */
offset:
- .long 0x8000
+ .long START_ADDR
segment:
.word 0
Index: stage2/builtins.c
diff -u -2 -r1.59 builtins.c
--- stage2/builtins.c 2000/04/29 16:30:13 1.59
+++ stage2/builtins.c 2000/05/20 05:05:46
@@ -1605,9 +1605,7 @@
{
if (! is_stage1_5)
- /* Stage 2. */
- installaddr = 0x8000;
+ installaddr = START_ADDR;
else
- /* Stage 1.5. */
- installaddr = 0x2000;
+ installaddr = STAGE1_5_ADDR;
}
Index: stage2/stage1_5.c
diff -u -2 -r1.4 stage1_5.c
--- stage2/stage1_5.c 1999/11/11 20:43:16 1.4
+++ stage2/stage1_5.c 2000/05/20 05:05:46
@@ -31,10 +31,10 @@
if (grub_open (config_file))
{
- int ret = grub_read ((char *) 0x8000, -1);
+ int ret = grub_read ((char *) START_ADDR, -1);
grub_close ();
if (ret)
- chain_stage2 (0, 0x8200);
+ chain_stage2 (0, PRE_STAGE2_ADDR);
}
--
Chip Salzenberg - a.k.a. - <[EMAIL PROTECTED]>
"I wanted to play hopscotch with the impenetrable mystery of existence,
but he stepped in a wormhole and had to go in early." // MST3K