1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-25 11:37:56 +00:00

Obtained from: Whistle Communications

Add code to the boot blocks to allow the user to place default boot strings
on block 1 of the disk (2nd block), should the correct magic numbers be present.

If the correct options are used it will 'delete' the name used from block1,
thereby assuring that if the boot fails it won't be stuck in an infinite loop.

the boot strings are set by the utility "nextboot"
(not yet checked in, but being tested.)
By default these changes should have no effect on existing installations
and if compiled without the NAMEBLOCK option should be essentially identical
to the old ones.
This commit is contained in:
Julian Elischer 1996-07-05 19:55:05 +00:00
parent 86ff3944a1
commit 9ed24653f7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=16983
6 changed files with 240 additions and 63 deletions

View File

@ -1,3 +1,6 @@
Note: all my origianl references to 386BSD also refer to freeBSD and NetBSD
which in some ways derived from 386BSD. --julian@freebsd.org
This Boot code is different from the original boot code that came with
386BSD in that it uses the BIOS to load the kernel and to provide all i/o
services. The advantage ofthis is that the same boot code exactly, can run
@ -25,31 +28,45 @@ if it has (the same) magic numbers, jumps into it. In 386bsd this is the
first stage boot, (or boot1) it is represented in /usr/mdec by
wdboot, asboot and sdboot. If the disk has been set up without DOS partitioning
then this block will be at block zero, and will have been loaded directly by
the BIOS.
the BIOS. This is the usual case with floppies.
4/ Boot1 will look at block0 (which might be itself if there are no DOS
partitions) and will find the 386bsd partition, and using the information
regarding the start position of that partition, will load the next 13 sectors
or so, to around 90000 (640k - 64k). and will jump into it at the appropriate
entry point. Since boot1 and boot2 were compiled together as one file
and then split later, boot1 knows the exact position within boot2 of the
entry point.
partitions) and will find the 386bsd partition,
Boot 1 also contains a compiled in DOS partition table
(in case it is at block 0), which contains a 386bsd partition starting
at 0. This ensures that the same code can work whether or not
boot1 is at block 0.
4A/ IF the NAMEBLOCK option is compiled into the bootcode, then the
boot1 code will load and examine block1 (Usually unused) and
look for a default boot string to use later.. (if the corrct magic number
is present). If the option NAMEBLOCKWRITEBACK is also defined, then
it will zero out that name after finding it, and write the block back,
having "used up" that name. The block may contain multiple different
boot strings which will be "used up" one after the other.. (one per boot)
They are set using the "nextboot" utility.
4B/ Using the information found in step 4, regarding the start position
of the BSD partition, boot1 will load the first 16 sectors of that partition,
to around 0x10000 (64k). and will jump into it at the appropriate entry point.
Since boot1 and boot2 were compiled together as one file and then split
later, boot1 knows the exact position within boot2 of the entry point.
5/ Boot2 asks the user for a boot device, partition and filename, and then
loads the MBR of the selected device. This may or may not be the device
which was originally used to boot the first MBR. The partition table
of the new MBR is searched for a 386bsd partition, and if one is found,
that is then in turn searched for the disklabel. This could all be on the
second disk at this point, if the user selected it.
second disk at this point, if the user selected it. If the user makes no
actions then a default string will be used.
6/On finding the disklabel, boot2 can find the correct unix partition
within the 386bsd partition, and using cutdown filesystem code,
look for the file to boot (e.g. 386bsd).
If the NAMEBLOCK option is used, then the default string may have been
loaded from block2. If none was found then a compiled in default will be used.
6/On finding the disklabel, on the disk th euser spacified, boot2 can find
the correct unix partition within the 386bsd partition, and using cutdown
filesystem code, look for the file to boot (e.g. 386bsd).
7/ Boot2 loads this file starting at the location specified by the a.out header,
(see later) and leaps into it at the location specified in he header.
@ -82,6 +99,8 @@ If you want to do it by hand remember that BIOS counts sectors starting at 1.
2/ you cannot overwrite the bottom 4k of ram until you have finished ALL
bios calls, as BIOS uses this area as scratch memory.
This is no longer really a probelm as we no-longer support loading the kernel
at location 0.
3/ Since BIOS runs in REAL mode, and Boot2 runs in protected mode,
Boot 2 switches back to real mode just before each BIOS call and then
@ -92,6 +111,8 @@ In answering the prompt from Boot2:
you can,
1/ leave it alone.. it will boot the indicated file from the first
partition of the first drive seen by the BIOS (C:)
If the NAMEBLOCK option is in use, the default name might be taken from block1
(2nd block) on that drive. (the drive on which boot 1 was loaded).
2/ enter only "-s" to boot the default to single user mode
@ -148,4 +169,4 @@ Before you do this ensure you have a booting floppy with correct
disktab and bootblock files on it so that if it doesn't work, you can
re-disklabel from the floppy.
$Id: README.386BSD,v 1.3 1995/02/16 12:02:08 jkh Exp $
$Id: README.386BSD,v 1.4 1996/04/07 14:27:57 bde Exp $

View File

@ -24,7 +24,7 @@
* the rights to redistribute these changes.
*
* from: Mach, Revision 2.7 92/02/29 15:33:41 rpd
* $Id: asm.h,v 1.3 1993/10/16 19:11:29 rgrimes Exp $
* $Id: asm.h,v 1.4 1995/05/30 07:58:25 rgrimes Exp $
*/
#define S_ARG0 4(%esp)
@ -142,3 +142,10 @@
#define Entry(x) .globl EXT(x); .align ALIGN; LEXT(x)
#define DATA(x) .globl EXT(x); .align ALIGN; LEXT(x)
/* note, this calls the 'message' in boot1 */
#define DEBUGMSG(msg) \
data32 ;\
mov $(msg), %esi ;\
data32 ;\
call EXT(message)

View File

@ -24,7 +24,7 @@
* the rights to redistribute these changes.
*
* from: Mach, [92/04/03 16:51:14 rvb]
* $Id: boot.c,v 1.49 1996/05/02 10:43:01 phk Exp $
* $Id: boot.c,v 1.50 1996/05/11 04:27:24 bde Exp $
*/
@ -62,6 +62,7 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define NAMEBUF_LEN (8*1024)
char namebuf[NAMEBUF_LEN];
extern char *dflt_name;
struct exec head;
struct bootinfo bootinfo;
int loadflags;
@ -126,8 +127,19 @@ boot(int drive)
}
#endif
}
/*
* XXX
* DAMN! I don't understand why this is not being set
* by the code in boot2.S
*/
dflt_name= (char *)0x0000ffb0;
loadstart:
if( (dflt_name[0] == 'D') && (dflt_name[1] == 'N') && dflt_name[2] ) {
name = dflt_name+2;
dflt_name[0] = 0;
} else {
name = dflname; /* re-initialize in case of loop */
}
/* print this all each time.. (saves space to do so) */
/* If we have looped, use the previous entries as defaults */
printf("\n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory\n"
@ -137,7 +149,6 @@ boot(int drive)
ouraddr, bootinfo.bi_basemem, bootinfo.bi_extmem,
dosdev & 0x7f, devs[maj], unit, name);
name = dflname; /* re-initialize in case of loop */
loadflags &= RB_SERIAL; /* clear all, but leave serial console */
getbootdev(namebuf, &loadflags);
ret = openrd();

View File

@ -24,7 +24,7 @@
* the rights to redistribute these changes.
*
* from: Mach, Revision 2.2 92/04/04 11:35:26 rpd
* $Id: boot2.S,v 1.5 1994/08/30 01:38:03 bde Exp $
* $Id: boot2.S,v 1.6 1995/01/25 21:37:40 bde Exp $
*/
#include "asm.h"
@ -47,6 +47,7 @@
/*
* boot2() -- second stage boot
* SP points to default string if found
*/
ENTRY(boot2)
@ -57,6 +58,9 @@ ENTRY(boot2)
mov %ax, %es
data32
shll $4, %eax
addr32
data32
movl %esp, EXT(dflt_name)
/* fix up GDT entries for bootstrap */
#define FIXUP(gdt_index) \

View File

@ -24,7 +24,7 @@
* the rights to redistribute these changes.
*
* from: Mach, Revision 2.2 92/04/04 11:36:29 rpd
* $Id: start.S,v 1.5 1994/10/06 09:41:05 rgrimes Exp $
* $Id: start.S,v 1.6 1995/09/16 13:51:20 bde Exp $
*/
/*
@ -60,6 +60,9 @@ NUMPART= 4 /* number of partitions in partition table */
PARTSZ= 16 /* each partition table entry is 16 bytes */
BSDPART= 0xA5 /* value of boot_ind, means bootable partition */
BOOTABLE= 0x80 /* value of boot_ind, means bootable partition */
NAMEBLOCKMAGIC= 0xfadefeed /* value of magicnumebr for block2 */
/* to debug this, Use the DEBUGMSG(msg) macro defined in asm.S */
.text
@ -80,18 +83,17 @@ start:
data32
mov $BOOTSEG, %eax
mov %ax, %ss
/*
* make a little room on the stack for
* us to save the default bootstring we might find..
* effectively, we push the bootstring.
*/
data32
mov $BOOTSTACK, %esp
mov $(BOOTSTACK - 64), %esp
/* set up %es, (where we will load boot2 to) */
mov %ax, %es
#ifdef DEBUG
data32
mov $one, %esi
data32
call message
#endif
/* bootstrap passes us drive number in %dl */
cmpb $0x80, %dl
@ -108,44 +110,20 @@ fd:
mov $0x0, %dl
/* reset the disk system */
#ifdef DEBUG
data32
mov $two, %esi
data32
call message
#endif
movb $0x0, %ah
int $0x13
data32
mov $0x0001, %ecx /* cyl 0, sector 1 */
movb $0, %dh /* head */
#ifdef DEBUG
data32
mov $three, %esi
data32
call message
#endif
data32
jmp load
hd: /**** load sector 0 into the BOOTSEG ****/
#ifdef DEBUG
data32
mov $four, %esi
data32
call message
#endif
data32
mov $0x0201, %eax
xor %ebx, %ebx /* %bx = 0 */
data32
mov $0x0001, %ecx
#ifdef DEBUG
data32
mov $five, %esi
data32
call message
#endif
data32
andl $0xff, %edx
/*mov $0x0080, %edx*/
@ -194,6 +172,164 @@ found:
movl %es:2(%ebx), %ecx /*sect, cyl (+ 2 bytes junk in top word) */
load:
#ifdef NAMEBLOCK
/*
* Load the second sector and see if it is a boot instruction block.
* If it is then scan the contents for the first valid string and copy it to
* the location of the default boot string.. then zero it out.
* Finally write the block back to disk with the zero'd out entry..
* I hate writing at this stage but we need this to be persistant.
* If the boot fails, then the next boot will get the next string.
* /etc/rc will regenerate a complete block2 iff teh boot succeeds.
*
* Format of block 2 is:
* [NAMEBLOCKMAGIC] <--0xdeafc0de
* [nulls]
* [bootstring]NULL <---e.g. 0:wd(0,a)/kernel.experimental
* [bootstring]NULL <---e.g. 0:wd(0,a)/kernel.old
* ....
* [bootstring]NULL <---e.g. 0:wd(0,f)/kernel
* FF FF FF
*/
where:
/*
* save things we might smash
* (that are not smashed immedatly after us anyway.)
*/
data32
push %ecx /* preserve 'cyl,sector ' */
data32
push %edx
/*
* Load the second sector
* BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
* Call with %ah = 0x2
* %al = number of sectors
* %ch = cylinder
* %cl = sector
* %dh = head
* %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
* %es:%bx = segment:offset of buffer
* Return:
* %al = 0x0 on success; err code on failure
*/
data32
movl $0x0201, %eax /function 2 (read) 1 sector */
xor %ebx, %ebx /* %bx = 0 */ /* buffer address (ES:0) */
data32
movl $0x0002, %ecx /* sector 2, cylinder 0 */
data32
andl $0x00ff, %edx /* head 0, drive N */
int $0x13
data32
jb read_error
/*
* confirm that it is one for us
*/
data32
xorl %ebx, %ebx /* magic number at start of buffer */
data32
addr32
movl %es:(%ebx), %eax
data32
cmpl $NAMEBLOCKMAGIC, %eax
data32
jne notours /* not ours so return to caller */
/*
* scan for a bootstring
* Skip the magic number, and scan till we find a non-null,
* or a -1
*/
incl %ebx /* quicker and smaller */
incl %ebx
incl %ebx
scan:
incl %ebx
addr32
movb %es:(%ebx), %al /* load the next byte */
testb %al, %al /* and if it is null */
data32 /* keep scanning (past deleted entries) */
jz scan
incb %al /* now look for -1 */
data32
jz notours /* if we reach the 0xFF then we have finished */
/*
* save our settings.. we need them twice..
*/
data32
push %ebx
/*
* copy it to the default string location
* which is just above the stack for 64 bytes.
*/
data32
movl $(BOOTSTACK-64), %ecx /* 64 bytes at the top of the stack */
nxtbyte:
addr32
movb %es:(%ebx), %al /* get the next byte in */
addr32
movb %al, %es:(%ecx) /* and transfer it to the name buffer */
incl %ebx /* get on with the next byte */
incl %ecx /* get on with the next byte */
testb %al, %al /* if it was 0 then quit this */
data32
jnz nxtbyte /* and looop if more to do */
/*
* restore the saved settings and
* zero it out so next time we don't try it again
*/
data32
pop %ebx /* get back our starting location */
#ifdef NAMEBLOCK_WRITEBACK
nxtbyte2:
addr32
movb %es:(%ebx), %al /* get the byte */
addr32
movb $0, %es:(%ebx) /* zero it out */
data32
incl %ebx /* point to the next byte */
testb %al, %al /* check if we have finished.. */
data32
jne nxtbyte2
/*
* Write the second sector back
* Load the second sector
* BIOS call "INT 0x13 Function 0x3" to write sectors from memory to disk
* Call with %ah = 0x3
* %al = number of sectors
* %ch = cylinder
* %cl = sector
* %dh = head
* %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
* %es:%bx = segment:offset of buffer
* Return:
* %al = 0x0 on success; err code on failure
*/
data32
movl $0x0301, %eax /* write 1 sector */
xor %ebx, %ebx /* buffer is at offset 0 */
data32
movl $0x0002, %ecx /* block 2 */
data32
andl $0xff, %edx /* head 0 */
int $0x13
data32
jnb notours
data32
mov $eread, %esi
jmp err_stop
#endif /* NAMEBLOCK_WRITEBACK */
/*
* return to the main-line
*/
notours:
data32
pop %edx
data32
pop %ecx
#endif
movb $0x2, %ah /* function 2 */
movb $LOADSZ, %al /* number of blocks */
xor %ebx, %ebx /* %bx = 0, put it at 0 in the BOOTSEG */
@ -207,12 +343,6 @@ load:
* as an internal buffer "intbuf".
*/
#ifdef DEBUG
data32
mov $six, %esi
data32
call message
#endif
data32
ljmp $BOOTSEG, $ EXT(boot2)
@ -231,6 +361,7 @@ err_stop:
/*
* message: write the error message in %ds:%esi to console
*/
ENTRY(message)
message:
/*
* Use BIOS "int 10H Function 0Eh" to write character in teletype mode
@ -269,15 +400,16 @@ stop: hlt
/* error messages */
#ifdef DEBUG
one: String "1\r\n\0"
two: String "2\r\n\0"
three: String "3\r\n\0"
four: String "4\r\n\0"
five: String "5\r\n\0"
six: String "6\r\n\0"
seven: String "7\r\n\0"
one: String "1-\0"
two: String "2-\0"
three: String "3-\0"
four: String "4-\0"
#endif DEBUG
#ifdef NAMEBLOCK_WRITEBACK
ewrite: String "Write error\r\n\0"
#endif /* NAMEBLOCK_WRITEBACK */
eread: String "Read error\r\n\0"
enoboot: String "No bootable partition\r\n\0"
endofcode:
@ -291,6 +423,7 @@ endofcode:
*/
/* flag, head, sec, cyl, typ, ehead, esect, ecyl, start, len */
. = EXT(boot1) + PARTSTART
strttbl:
.byte 0x0,0,0,0,0,0,0,0
.long 0,0
.byte 0x0,0,0,0,0,0,0,0

View File

@ -24,7 +24,7 @@
* the rights to redistribute these changes.
*
* from: Mach, Revision 2.2 92/04/04 11:36:43 rpd
* $Id: table.c,v 1.9 1996/03/08 05:15:54 bde Exp $
* $Id: table.c,v 1.10 1996/04/07 14:28:05 bde Exp $
*/
/*
@ -140,3 +140,4 @@ char *devs[] = { "wd", "dk", "fd", "wt", "sd", 0 };
char dflname[] = "/kernel";
char *name = dflname;
unsigned long tw_chars = 0x5C2D2F7C; /* "\-/|" */
char *dflt_name;