From owner-freebsd-hackers Tue May 14 10:41:51 1996 Return-Path: owner-hackers Received: (from root@localhost) by freefall.freebsd.org (8.7.3/8.7.3) id KAA26841 for hackers-outgoing; Tue, 14 May 1996 10:41:51 -0700 (PDT) Received: from godzilla.zeta.org.au (godzilla.zeta.org.au [203.2.228.19]) by freefall.freebsd.org (8.7.3/8.7.3) with SMTP id KAA26830 for ; Tue, 14 May 1996 10:41:48 -0700 (PDT) Received: (from bde@localhost) by godzilla.zeta.org.au (8.6.12/8.6.9) id DAA12954; Wed, 15 May 1996 03:38:03 +1000 Date: Wed, 15 May 1996 03:38:03 +1000 From: Bruce Evans Message-Id: <199605141738.DAA12954@godzilla.zeta.org.au> To: freebsd-hackers@FreeBSD.ORG, wpaul@skynet.ctr.columbia.edu Subject: Re: Making a three-stage boot Sender: owner-hackers@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk >... >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