Subject: RFC: start.S
To: None <current-users@NetBSD.ORG>
From: VaX#n8 <vax@linkdead.paranoia.com>
List: current-users
Date: 06/16/1996 20:43:30
Below I've included a new start.S that only does a stage1 boot (so far).
I have included an objdump so that you can see the discrepancy between
the opcodes and what the new gas creates.
It seems gas needs a bit of work on 16-bit code. :(
I'd appreciate comments, improvements, etc. Be nice, it's my first
x86 assembler project.
I don't think it will run in it's current state.
I tried it a few edit-compile cycles ago and it crashed, probably
because of the irregular treatment of 16-bit regs.
/* $NetBSD: start.S,v 1.12 1995/01/18 17:34:18 mycroft Exp $ */
/* heavily edited by VaX#n8 (vax@linkdead.paranoia.com) 16 Jun 1996 */
/*
* Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*
* Mach Operating System
* Copyright (c) 1992, 1991 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
Copyright 1988, 1989, 1990, 1991, 1992
by Intel Corporation, Santa Clara, California.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appears in all
copies and that both the copyright notice and this permission notice
appear in supporting documentation, and that the name of Intel
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <machine/asm.h>
BOOTSEG = 0x0100 /* boot2 will be loaded here (below 640K) */
BOOTSTACK = 0xfffc /* boot stack */
SIGNATURE = 0xaa55 /* magic num at end of partition table */
LOADSZ = 15 /* size of unix boot */
PARTSTART = 0x1be /* starting address of partition table */
NUMPART = 4 /* number of partitions in partition table */
PARTSZ = 16 /* each partition table entry is 16 bytes */
BSDPART = 0xA5 /* value of boot_ind, means bsd partition */
BOOTABLE = 0x80 /* value of boot_ind, means bootable part'n */
BOOT2 = 0x200 /* offset to boot2 from $BOOTSEG */
CHAR_S = 'S'
CHAR_F = 'F'
CHAR_H = 'H'
CHAR_D = 'D'
CHAR_L = 'L'
.file "start.S"
.code16
/* boot1 is automatically located at 0x0:7c00 by your BIOS int 0x19 */
ENTRY(boot1)
/* set up %ss and %sp */
movw $BOOTSEG, %ax
movw %ax, %ss
movw $BOOTSTACK, %sp
/* set up %es, (where we will load boot2 and possibly MBR to) */
movw %ax, %es
#ifdef SERIAL
/* BIOS int 0x14 service 0x00 : initialize serial port */
pushw %dx
movw $0x00e3, %ax /* init port, to 9600/N/1/8 */
xorw %dx, %dx /* port (%dx=0) */
int $0x14
popw %dx
#endif
#ifdef DEBUG
movb $CHAR_S, %al
call message
#endif
/* bootstrap passes us drive number in %dl */
pushw %dx
/* BIOS int 0x13 service 0x08 : get drive parameters */
movb $8, %ah
int $0x13
jnc worked
/* call failed due to funky BIOS, assume CHS of 80:2:15 */
movw $0x500f, %cx
/* max_head_num <- 1 */
movb $1, %dh
worked:
/* get number of heads */
xorb %ah, %ah /* %ah <- 0 */
movb %dh, %al /* %al <- (max_head_num) */
incw %ax /* %ax <- (number_of_heads) */
movw %ax, heads
/* get number of cylinders */
xorb %ah, %ah /* %ah <- 0 */
movb %cl, %al
shlw $2, %ax /* %ah <- (max_cyl_num:8-9) */
movb %ch, %al /* %al <- (max_cyl_num:0-7) */
incw %ax /* %ax <- (number_of_cyls) */
movw %ax, cylinders
/* get number of sectors */
movb %cl, %al
andb $0x3F, %al
movb %al, sectors
/* test drive type (fd or hd) */
popw %dx
cmpb $0x80, %dl
jae hd
fd: /* start reading at 0:0:1 */
#ifdef DEBUG
movb $CHAR_F, %al
call message
#endif
movw $0x0001, %cx /* cyl 0, sector 1 */
xorb %dh, %dh /* head (%dh=0) */
jmp load
hd: /* look at the partition table */
#ifdef DEBUG
movb $CHAR_H, %al
call message
#endif
/* see if the partition table entry is pointed to by %ds:%si */
/* for compatibility with OS-BS and many other bootloaders */
/* this enables us to boot from extended partitions or 2nd disk */
/* a partition table entry: */
/* byte meaning */
/* 0 active */
/* 1-3 starting CHS */
/* 4 system type id */
/* prepare for a successful comparison: */
/* TODO: shouldn't have to use 32-bit reg here */
movb 1(%esi), %dh /* starting head */
movw 2(%esi), %cx /* starting cyl/sector */
movb 4(%esi), %al /* system id / partition type */
cmpb $BSDPART, %al
/* jump if we know where our partition is */
je load
/* no; time to search the disk */
#ifdef DEBUG
movb $CHAR_D, %al
call message
#endif
/* BIOS int 0x13 service 0x02 : read from disk (see comment later) */
movw $0x0201, %ax /* will read (%al=1) sector */
xorw %bx, %bx /* to %es:%bx (where %bx=0) */
movw $0x0001, %cx /* cyl=0, sector=1 */
movb %dh, %dh /* head (%dh=0) */
int $0x13
jc read_error
/* find the first BSD partition */
movw $PARTSTART, %bx
movw $NUMPART, %cx
again:
movb %es:4(%ebx), %al
cmpb $BSDPART, %al
je found
addw $PARTSZ, %bx
loop again
/* could not find partition */
/* TODO - search in extended partitions */
movw $enoboot, %si
jmp err_stop
found:
/* TODO: fix this, should not need 32-bit reg */
movb %es:1(%ebx), %dh /* head */
movw %es:2(%ebx), %cx /* sect, cyl */
load:
#ifdef DEBUG
movb $CHAR_L, %al
call message
#endif
/* TODO: add one to the sector number (with carry) to */
/* avoid loading "boot sector" (usually this program) */
/* over again */
/* BIOS int 0x13 service 0x02 : read sectors from disk */
/* Call with %ah = 0x2 */
/* %al = number of sectors */
/* %ch = cylinder */
/* %cl = sector (bits 6-7 are high bits of cyl on hd) */
/* %dh = head */
/* %dl = drive (0x80 for hard disk, 0x0 for floppy disk) */
/* %es:%bx = segment:offset of buffer */
/* Return carry flag = clear if ok/set if error */
/* %al = num sectors transferred */
/* %ah = status */
movw $0x200 | LOADSZ, %ax /* read $LOADSZ blocks */
xorw %bx, %bx /* put it at BOOTSEG:0x00 */
int $0x13
jc read_error
/* ljmp to the second stage boot loader (boot2). */
/* After ljmp, %cs is BOOTSEG */
ljmp $BOOTSEG, $BOOT2
print_char: /* write char in %al to console */
/* %al = char to print */
/* %ah = scratch (serial printchar retval) */
#ifndef SERIAL
/* BIOS int 0x10 service 0x0e : video - teletype output */
movb $0x0e, %ah
pushw %bx
movw $0x001, %bx /* page=%bh=0x00, forecolor=%bl=0x01 */
int $0x10
popw %bx
#else /* SERIAL */
/* BIOS int 0x14 service 0x01 : serial - write char to port */
movb $0x01, %ah
pushw %dx
movw $0x00, %dx /* port=%dx=0x00 */
int $0x14
popw %dx
#endif /* SERIAL */
ret
read_error: /* create "read error" message and stop */
movw $eread, %si
/* fall through: */
err_stop: /* print a message in %ds:%si and stop */
call message
jmp stop
message: /* write the error message in %ds:%si to console */
/* %ds:%si = string to print */
/* %al = scratch */
/* %ah = scratch (serial char retval) */
cld
#ifndef SERIAL
pushw %bx /* save %bx */
#else /* SERIAL */
pushw %dx
#endif /* SERIAL */
nextb:
lodsb /* load a byte into %al */
testb %al, %al /* test for null terminator byte */
jz done /* if null, we're done */
#ifndef SERIAL
/* BIOS int 0x10 service 0x0e : video - teletype output */
movb $0x0e, %ah
movw $0x001, %bx /* page=%bh=0x00, forecolor=%bl=0x01 */
int $0x10
#else /* SERIAL */
/* BIOS int 0x14 service 0x01 : serial - write char to port */
movb $0x01, %ah
movw $0x00, %dx /* port=%dx=0x00 */
int $0x14
#endif /* SERIAL */
jmp nextb
done:
#ifndef SERIAL
popw %bx /* restore %bx */
#else /* SERIAL */
popw %dx /* restore %dx */
#endif /* SERIAL */
ret
stop: /* halt the machine */
cli
hlt
eread: ASMSTR "Read error\r\n"
enoboot: ASMSTR "No bootable partition\r\n"
/* scratch space */
sectors: .byte 0
heads: .word 0
cylinders: .word 0
endofcode:
/* throw in a partition in case we are block0 as well */
/* flag, head, sec, cyl, typ, ehead, esect, ecyl, start, len */
. = _C_LABEL(boot1) + PARTSTART
.byte 0x0,0,0,0,0,0,0,0
.long 0,0
.byte 0x0,0,0,0,0,0,0,0
.long 0,0
.byte 0x0,0,0,0,0,0,0,0
.long 0,0
.byte BOOTABLE,0,1,0,BSDPART,255,255,255
.long 0,50000
/* the last 2 bytes in the sector 0 contain the signature */
. = _C_LABEL(boot1) + 0x1fe
.short SIGNATURE
. = _C_LABEL(boot1) + BOOT2
(compiled with -DDEBUG)
boot.sym: file format a.out-mach3
Disassembly of section .text:
00000000 <_boot1-7c00> movl $0xd08e0100,%eax
00000005 <_boot1-7bfb> movl $0xc08efffc,%esp
0000000a <_boot1-7bf6> movb $0x53,%al
0000000c <_boot1-7bf4> call 000000e2 <BSDPART+3d>
00000012 <_boot1-7bee> pushl %edx
00000013 <_boot1-7bed> movb $0x8,%ah
00000015 <_boot1-7beb> int $0x13
00000017 <_boot1-7be9> jae 0000001f <PARTSZ+f>
0000001a <_boot1-7be6> movl $0x1b6500f,%ecx
0000001f <_boot1-7be1> xorb %ah,%ah
00000021 <_boot1-7bdf> movb %dh,%al
00000023 <_boot1-7bdd> incl %eax
00000024 <_boot1-7bdc> addr16 movl %eax,0x7d1f
00000028 <_boot1-7bd8> addb %al,(%eax)
0000002a <_boot1-7bd6> xorb %ah,%ah
0000002c <_boot1-7bd4> movb %cl,%al
0000002e <_boot1-7bd2> shll $0x2,%eax
00000031 <_boot1-7bcf> movb %ch,%al
00000033 <_boot1-7bcd> incl %eax
00000034 <_boot1-7bcc> addr16 movl %eax,0x7d21
00000038 <_boot1-7bc8> addb %al,(%eax)
0000003a <_boot1-7bc6> movb %cl,%al
0000003c <_boot1-7bc4> andb $0x3f,%al
0000003e <_boot1-7bc2> addr16 movb %al,0x7d1e
00000045 <_boot1-7bbb> popl %edx
00000046 <_boot1-7bba> cmpb $0x80,%dl
00000049 <_boot1-7bb7> jae 0000005c <CHAR_S+9>
0000004c <_boot1-7bb4> movb $0x46,%al
0000004e <_boot1-7bb2> call 000000e2 <BSDPART+3d>
00000054 <_boot1-7bac> movl $0xf6300001,%ecx
00000059 <_boot1-7ba7> jmp 000000b1 <BSDPART+c>
0000005c <_boot1-7ba4> movb $0x48,%al
0000005e <_boot1-7ba2> call 000000e2 <BSDPART+3d>
00000064 <_boot1-7b9c> addr16 movb 0x1(%esi),%dh
00000068 <_boot1-7b98> addr16 movl 0x2(%esi),%ecx
0000006c <_boot1-7b94> addr16 movb 0x4(%esi),%al
00000070 <_boot1-7b90> cmpb $0xa5,%al
00000072 <_boot1-7b8e> je 000000b1 <BSDPART+c>
00000075 <_boot1-7b8b> movb $0x44,%al
00000077 <_boot1-7b89> call 000000e2 <BSDPART+3d>
0000007d <_boot1-7b83> movl $0xdb310201,%eax
00000082 <_boot1-7b7e> movl $0xf6880001,%ecx
00000087 <_boot1-7b79> int $0x13
00000089 <_boot1-7b77> jb 000000d6 <BSDPART+31>
0000008c <_boot1-7b74> movl $0x4b901be,%ebx
00000091 <_boot1-7b6f> addb %ah,0x26(%edi)
00000094 <_boot1-7b6c> movb 0x4(%ebx),%al
00000097 <_boot1-7b69> cmpb $0xa5,%al
00000099 <_boot1-7b67> je 000000a7 <BSDPART+2>
0000009c <_boot1-7b64> addl $0x10,%ebx
0000009f <_boot1-7b61> loop 00000092 <BOOTABLE+12>
000000a1 <_boot1-7b5f> movl $0xeb667d06,%esi
000000a6 <_boot1-7b5a> xorb 0x26(%edi),%ah
000000a9 <_boot1-7b57> movb 0x1(%ebx),%dh
000000ac <_boot1-7b54> addr16 movl %es:0x2(%ebx),%ecx
000000b1 <_boot1-7b4f> movb $0x4c,%al
000000b3 <_boot1-7b4d> call 000000e2 <BSDPART+3d>
000000b9 <_boot1-7b47> movl $0xdb31020f,%eax
000000be <_boot1-7b42> int $0x13
000000c0 <_boot1-7b40> jb 000000d6 <BSDPART+31>
000000c3 <_boot1-7b3d> ljmp 0x100,0x200
000000cb <_boot1-7b35> movb $0xe,%ah
000000cd <_boot1-7b33> pushl %ebx
000000ce <_boot1-7b32> movl $0x10cd0001,%ebx
000000d3 <_boot1-7b2d> popl %ebx
000000d4 <_boot1-7b2c> ret
000000d6 <_boot1-7b2a> movl $0xe8667cf9,%esi
000000db <_boot1-7b25> addl (%eax),%eax
000000dd <_boot1-7b23> addb %al,(%eax)
000000df <_boot1-7b21> jmp 000000f7 <BSDPART+52>
000000e2 <_boot1-7b1e> cld
000000e3 <_boot1-7b1d> pushl %ebx
000000e4 <_boot1-7b1c> lodsb %ds:(%esi),%al
000000e5 <_boot1-7b1b> testb %al,%al
000000e7 <_boot1-7b19> je 000000f4 <BSDPART+4f>
000000ea <_boot1-7b16> movb $0xe,%ah
000000ec <_boot1-7b14> movl $0x10cd0001,%ebx
000000f1 <_boot1-7b0f> jmp 000000e4 <BSDPART+3f>
000000f4 <_boot1-7b0c> popl %ebx
000000f5 <_boot1-7b0b> ret
000000f7 <_boot1-7b09> cli
000000f8 <_boot1-7b08> hlt
000000f9 <_boot1-7b07> pushl %edx
000000fa <_boot1-7b06> popa
000000fc <_boot1-7b04> andb %ah,%fs:0x72(%ebp)
00000100 <_boot1-7b00> jb 00000171 <BOOTSEG+71>
00000102 <_boot1-7afe> jb 00000111 <BOOTSEG+11>
00000104 <_boot1-7afc> orb (%eax),%al
00000106 <_boot1-7afa> decl %esi
00000107 <_boot1-7af9> outsl %ds:(%esi),(%dx)
00000108 <_boot1-7af8> andb %ah,0x6f(%edx)
0000010b <_boot1-7af5> outsl %ds:(%esi),(%dx)
0000010c <_boot1-7af4> je 0000016f <BOOTSEG+6f>
0000010e <_boot1-7af2> boundl 0x20(%ebp,2),%ebp
00000112 <_boot1-7aee> jo 00000175 <BOOTSEG+75>
00000114 <_boot1-7aec> jb 0000018a <BOOTSEG+8a>
00000116 <_boot1-7aea> imull $0xa0d6e,0x6f(%ecx,%ebp,2),%esi
...
000001ee <_boot1-7a12> addb $0x1,(%eax)
000001f1 <_boot1-7a0f> addb %ah,0xffffff(%ebp)
000001f7 <_boot1-7a09> addb %al,(%eax)
000001f9 <_boot1-7a07> addb %dl,0xffffffc3(%eax)
000001fc <_boot1-7a04> addb %al,(%eax)
000001fe <_boot1-7a02> pushl %ebp
000001ff <_boot1-7a01> Address 0x200 is out of bounds.