Subject: NetBSD/VAX netboot problem SOLVED
To: None <port-vax@netbsd.org>
From: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
List: port-vax
Date: 03/05/2006 22:47:13
--9jxsPFA5p3P2qPhR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Moin,

while on CLT2006 I did some research into that strange netboot problem
that we had since at least 1.6.

The problem was that the boot program did not work when loaded over the
network. There was a suggested workaround to modify
/usr/src/usr.sbin/mopd/common/file.c to explicitly set the entry point
to zero, which doesn't seem to be The Right Thing(TM) to do.

The standalone startup code used by boot will relocate the program to
whatever address the program was linked to. When boot was still a.out,
the a_entry field in the a.out header was explicitly set to nisse (which
equals location 0) while the program itself was linked to have the .text
segment at address 0x2f0000. Since this address of .text is not stored
in the a.out header, the primary boot program bootxx just loaded boot at
its entry point (location 0), which just works because of said
relocation code.

When boot was changed to ELF the entry point was explicitly set to the
start symbol (which equals the base address of the .text segment), and
the primary bootstrap loaded boot at just this address which it reads
from the ELF program header. The boot program is then started at its
entry point, which is normally the same. No relocation was even needed
here, so this worked too.

As far as I can tell the MOP boot code of the VMB just loads the boot
program at location 0, at least I was not able to change this to
0x2f000. If I understand this correctly, VMB loads the program at
location 0 but starts it at location 0x2f000, which of course fails.

Simply changing the entry point of boot back to nisse will not help
either, since the primary bootstrap will then load boot at location
0x2f000 and start it at 0, so that disk bootstraps will fail.

I attached a diff to sys/arch/vax/boot/boot/Makefile and
sys/arch/vax/boot/xxboot/bootxx.c which correct this problem. The boot
program will now be linked to 0x2f0000 and have its entry point set to
nisse (0) just like it was before it was changed to ELF, and the primary
boot code in bootxx.c will just ignore ph.p_paddr and load the file at
its entry point, just like it did (and still does) for a.out programs.

Please test and review these patches, I hope that these will be
committed and possibly even pulled up for 3.0.1 or whatever the
next release will be called.

- Hans Rosenfeld


-- 
%SYSTEM-F-ANARCHISM, The operating system has been overthrown

--9jxsPFA5p3P2qPhR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

Index: boot/Makefile
===================================================================
RCS file: /cvsroot/src/sys/arch/vax/boot/boot/Makefile,v
retrieving revision 1.35
diff -u -r1.35 Makefile
--- boot/Makefile	21 Apr 2004 22:01:44 -0000	1.35
+++ boot/Makefile	5 Mar 2006 21:21:36 -0000
@@ -31,19 +31,13 @@
 .include "${S}/lib/libkern/Makefile.inc"
 LIBKERN=${KERNLIB}
 
-.if ${OBJECT_FMT} == "ELF"
-START=start
-.else
-START=nisse
-.endif
-
 .PHONY: vers.c
 vers.c: ${.CURDIR}/version
 	${HOST_SH} ${S}/conf/newvers_stand.sh -NM ${.CURDIR}/version "${MACHINE}"
 
 ${PROG}: machine-links ${OBJS} ${LIBSA} ${LIBZ} ${LIBKERN}
 	${_MKTARGET_LINK}
-	${LD} -N -Ttext ${RELOC} -e ${START} -o ${PROG}.sym ${OBJS} \
+	${LD} -N -Ttext ${RELOC} -e nisse -o ${PROG}.sym ${OBJS} \
 	    ${LIBSA} ${LIBZ} ${LIBSA} ${LIBKERN}
 	${STRIP} -o ${PROG} ${PROG}.sym
 
Index: xxboot/bootxx.c
===================================================================
RCS file: /cvsroot/src/sys/arch/vax/boot/xxboot/bootxx.c,v
retrieving revision 1.18
diff -u -r1.18 bootxx.c
--- xxboot/bootxx.c	6 Jan 2004 17:01:48 -0000	1.18
+++ xxboot/bootxx.c	5 Mar 2006 21:21:36 -0000
@@ -165,8 +165,8 @@
 			read(io, &tmp, sizeof(tmp));
 			off += sizeof(tmp);
 		}
-		read(io, (void *) ph.p_paddr, ph.p_filesz);
-		memset((void *) (ph.p_paddr + ph.p_filesz), 0,
+		read(io, (void *) hdr.elf.e_entry, ph.p_filesz);
+		memset((void *) (hdr.elf.e_entry + ph.p_filesz), 0,
 		       ph.p_memsz - ph.p_filesz);
 	} else {
 		goto die;

--9jxsPFA5p3P2qPhR--