Date: Mon, 13 May 1996 11:46:36 -0400 (EDT) From: Bill Paul <wpaul@skynet.ctr.columbia.edu> To: freebsd-hackers@freebsd.org Cc: wpaul@skynet.ctr.columbia.edu (Bill Paul) Subject: Making a three-stage boot Message-ID: <199605131546.LAA01112@skynet.ctr.columbia.edu>
next in thread | raw e-mail | index | archive | help
Lately I've been experimenting with creating a three-sgate bootstrap
program. (No, I don't know why. It isn't as if I don't have enough to
do already.) Unfortunately, much as I expected, I've hit a wall.
And I can't get up.
The idea I had was to create a bootstrap similar to the one used by
SunOS, which works as follows:
- There is a standalong program called /boot. This program should run
in protected mode, but have the same ability to perform real mode
BIOS operations as the existing second-stage bootstrap. I believe it
has to be limited to having at most 64K of text and data, though I
may be mistaken about this. This is the program which will ultimately
read the kernel image from the filesystem and run it.
- 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. In essence, this second stage
is very much like the one we have now, except that it can only load
one program: it doesn't need to know how the filesystem is structured
since it knows exactly what blocks to look for, which means it doesn't
need any code to grok a UFS filesystem; it doesn't need any keyboard or
serial port I/O code since it doesn't have to interact with the user.
All it needs to do is read a list of pre-defined sectors and jump to
the new program.
- The second stage bootstrap is read in by the first stage, which is
a boot block exactly like the one we have now.
Now, here's how this is used: when the operating system is installed,
the first and second stages are written to disk using a special installboot
program (which may be merged with disklabel to simplify things). The
installboot program actually scans the standalone /boot program and
determines what physical blocks it occupies on disk, as well as the
underlying filesystem blocksize. This information is then patched directly
into the second stage bootstrap image and the patched image is then
slapped onto the disk.
I started by writing a simple installboot program, which at this point
only scans the /boot program and patches a second stage image -- I'm
still using disklabel to write the patched images to disk. The patching
is done by compiling the initial bootstrap images with the disk block
arrays populated with magic numbers. The installboot program reads in
the second stage image and stops when it reaches the magic numbers, then
overwrites them with the proper disk block values. (This is ugly, but
it's the only way I could find to do it without a symbol table.)
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,
or anything else that it would be useful to save. The one restriction
here is that /boot must remain where it is. If it is moved, the installboot
program must be run again in order to install a new second stage boot
with a new set of physical block numbers.
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:
- 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
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.)
- 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?
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?
o For that matter, where in memory should it be loaded?
o Should it have an a.out header or not?
o Should it be stripped?
- How do I hand off control to the standalone image from the second
stage bootstrap? Can I use the same startprog() routine that the
existing bootstrap uses to kick off the kernel? If not, what do I
use instead?
After hunting around a bit, I discovered a bootstrap program from
OSF Mach version 3 which seems to be similar to what I need, but it
appears to be incomplete: there is a mach_kboot program which is meant
to be loaded in place of the kernel that starts in protected mode and
then copies itself over the existing bootstrap. I was even able to
compile and link the mach_kboot program in FreeBSD. Unfortunately,
this is only the 'third' stage and the first and second stages appear to
be incomplete or missing (meaning that I can't find the code that loads
and runs this part of the bootstrap, which is what I really need). The
README with he code gives some clues but doesn't tell me everything I
need to put all the pieces together.
Basically, this is deep magic, and I'm not yet a clever enough magician
to make it all work. I _want_ to learn how to do this, but I'm not making
much progress. If anyone can shed some light on this subject, either
by pointing me at some in-depth documentation (that preferably doesn't
need to be viewed with a stinking web browser) or answering some of the
above questions, I'd greatly appreciate it.
-Bill
--
=============================================================================
-Bill Paul (212) 854-6020 | System Manager
Work: wpaul@ctr.columbia.edu | Center for Telecommunications Research
Home: wpaul@skynet.ctr.columbia.edu | Columbia University, New York City
=============================================================================
License error: The license for this .sig file has expired. You must obtain
a new license key before any more witty phrases will appear in this space.
=============================================================================
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199605131546.LAA01112>
