Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 May 1996 03:38:03 +1000
From:      Bruce Evans <bde@zeta.org.au>
To:        freebsd-hackers@FreeBSD.ORG, wpaul@skynet.ctr.columbia.edu
Subject:   Re: Making a three-stage boot
Message-ID:  <199605141738.DAA12954@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>...
>The idea I had was to create a bootstrap similar to the one used by
>SunOS, which works as follows:
>...
>- The /boot program is loaded by a second stage bootstrap, which is
>  by design very dumb and limited in function. It has a compiled-in
>  array of disk blocks which tell it where the the /boot program resides
>  on disk. It also has a compiled-in value for the filesystem blocksize,
>  and possibly some other magic values.

This is similar to the Linux LILO bootstrap except for the third stage.
It is more general and less convenient than what we have now.  Don't
implement it.  Linux sort of needs it because the original Linux file
system (minixfs) only leaves 1K for the first stage bootstrap.  It's
difficult to fit a loader for /kernel in 1K.  We already have the loader
for /kernel fitted in 7.5K and would only have to worry about squeezing
it to boot from misdesigned file systems.  We won't be able to avoid
much work implementing loaders for several file systems since we (I)
want the loader in the next stage.  Anyway, `installboot' doesn't need
to be implemented yet.

>What I'm really trying to do here is effectivaly split the existing
>second stage into two pieces: rather than giving the second stage all
>the brains, which takes up too much space, I want to move most of the
>work into third stage and make the second stage just smart enough
>to load it. Also, by patching values into the bootstrap, we can save
>other information, such as the proper disk geometry of the boot drive,

The second stage should load a third stage which is just like the
current second stage only larger.  Values should be saved in a file and
patched using $EDITOR.

>Now all I have to do is turn the existing second stage bootstrap into
>a standalone program. Unfortunately, I don't know how to do it. There
>are several questions I can't answer:

Practice using the current second stage to load itself as a third stage.
Why wouldn't that work?  Answer: it would load it at 0x100000 where it
would at best (if you link it to run there) get in in the way of loading
the kernel at 0x100000.  Essentially all that is necessary is to keep
the stages out of each other's way and set up the stack pointer before
starting main().  The current stage 2 clears the bss for the next stage
although it probably shouldn't.

>- The standalone image obviously needs some sort of assembly language
>  startup routine, only I'm not adept enough at 386 protected-mode
>  assembly language to write it myself. (What would really help is if

	movl $stack,%esp; jmp _main	# :-)

See also locore.s.  Notice how little setup it does before calling a
function.  The second stage has already set up a similar environment
with less complications (all registers except %esp are already suitable,
and there are no relocations to high memory).

>  we had some sort of 'libsa' standalone library. 4.4BSD-Lite had one
>  for the i386 architecture, but it relied on special protected-mode
>  drivers. It would be terrific if we had one that used the BIOS
>  instead.)

You can use `.PATH: ../stage2' for now.

>- Assuming I had a startup routine (and the right code to do the real-mode
>  BIOS operations), how exactly do I link the image?

>	o Should it be a ZMAGIC binary like the kernel? Or should it
>          be OMAGIC like the existing bootstrap?

Same as the current stage 2.  Oops.  Stage 3 can't be as much like stage
2 as I thought it could when I wrote some of the above.  Stage 2 uses
descriptors based at BOOT_SEG*16 to avoid relocations.  It's probably
best to use the same method and limit the program to 64K to avoid
complications in the real mode interface (code from the current stage 2
probably wouldn't be reusable if the stage 3 segments are flat).  This
requires more setup.  An easy way to implement this is to use more of
the stage 2 assembler code: load stage 3 at BOOT_3_SEG*16, switch to
real mode, and jump to _boot2 in segment BOOT_3_SEG.  Stage 3 should
then start up just like stage 2.

>	o What start address should it be linked for? Should it be
>	  linked at address 0 like the bootstrap or should it be
>	  linked for the address at which it will be loaded, like
>	  the kernel?

0 if you make it like stage 2 or its load address if you make it like the
kernel.  (The kernel is actually linked at 0xf0000000 higher than its
load address but that requires paging and complications to address things
before paging is set up.)

>	o For that matter, where in memory should it be loaded?

Above stage 2, at 0x20000.

>	o Should it have an a.out header or not?

It has to for the current stage 2 to work.  OTOH, stage 2 should simply
load a whole file and jump to it, so that it doesn't depend on the file's
format.

>	o Should it be stripped?

No, it's easy to strip it at load time if necessary and impossible to
unstrip it at load time if desired.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199605141738.DAA12954>