aboutsummaryrefslogtreecommitdiff
path: root/sys/i386/boot
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i386/boot')
-rw-r--r--sys/i386/boot/biosboot/README.386BSD45
-rw-r--r--sys/i386/boot/biosboot/asm.h9
-rw-r--r--sys/i386/boot/biosboot/boot.c17
-rw-r--r--sys/i386/boot/biosboot/boot2.S6
-rw-r--r--sys/i386/boot/biosboot/start.S223
-rw-r--r--sys/i386/boot/biosboot/table.c3
6 files changed, 240 insertions, 63 deletions
diff --git a/sys/i386/boot/biosboot/README.386BSD b/sys/i386/boot/biosboot/README.386BSD
index ebcdb65fab2c..f4be27ed6e96 100644
--- a/sys/i386/boot/biosboot/README.386BSD
+++ b/sys/i386/boot/biosboot/README.386BSD
@@ -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.
+
+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, 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).
+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 $
diff --git a/sys/i386/boot/biosboot/asm.h b/sys/i386/boot/biosboot/asm.h
index 5d2c380b9fd3..8abb23a3bec7 100644
--- a/sys/i386/boot/biosboot/asm.h
+++ b/sys/i386/boot/biosboot/asm.h
@@ -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)
diff --git a/sys/i386/boot/biosboot/boot.c b/sys/i386/boot/biosboot/boot.c
index 1c4c1c903de4..54469d7401a5 100644
--- a/sys/i386/boot/biosboot/boot.c
+++ b/sys/i386/boot/biosboot/boot.c
@@ -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 @@ loadstart:
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();
diff --git a/sys/i386/boot/biosboot/boot2.S b/sys/i386/boot/biosboot/boot2.S
index 26a5442dc706..ecb6b81e13b2 100644
--- a/sys/i386/boot/biosboot/boot2.S
+++ b/sys/i386/boot/biosboot/boot2.S
@@ -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) \
diff --git a/sys/i386/boot/biosboot/start.S b/sys/i386/boot/biosboot/start.S
index a30ab6804f2e..3d351c08612f 100644
--- a/sys/i386/boot/biosboot/start.S
+++ b/sys/i386/boot/biosboot/start.S
@@ -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
diff --git a/sys/i386/boot/biosboot/table.c b/sys/i386/boot/biosboot/table.c
index ba304a873315..9f3959a3ba7b 100644
--- a/sys/i386/boot/biosboot/table.c
+++ b/sys/i386/boot/biosboot/table.c
@@ -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;