File:  [Early Linux] / linux / boot / bootsect.sg
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:01:31 2018 UTC (8 years, 3 months ago) by root
Branches: linus, MAIN
CVS tags: linux010, HEAD
linux 0.10

/* 
 *
 *	bootsect.s		(C) 1991 Linus Torvalds
 *
 * bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
 * iself out of the way to address 0x90000, and jumps there.
 *
 * It then loads 'setup' directly after itself (0x90200), and the system
 * at 0x10000, using BIOS interrupts. 
 *
 * NOTE! currently system is at most 8*65536 bytes long. This should be no
 * problem, even in the future. I want to keep it simple. This 512 kB
 * kernel size should be enough, especially as this doesn't contain the
 * buffer cache as in minix
 *
 * The loader has been made as simple as possible, and continuos
 * read errors will result in a unbreakable loop. Reboot by hand. It
 * loads pretty fast by getting whole sectors at a time whenever possible.
 */

.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text

SETUPLEN = 4				# nr of setup-sectors
BOOTSEG  = 0x07c0			# original address of boot-sector
INITSEG  = 0x9000			# we move boot here - out of the way
SETUPSEG = 0x9020			# setup starts here
SYSSEG   = 0x1000			# system loaded at 0x10000 (65536).
ENDSEG   = SYSSEG + SYSSIZE		# where to stop loading

/* 
 * ROOT_DEV:	0x000 - same type of floppy as boot.
 *		0x301 - first partition on first drive etc
 */
ROOT_DEV = 0 # 0x306

entry start
start:
	mov	$BOOTSEG,%ax
	mov	%ax,%ds
	mov	$INITSEG,%ax
	mov	%ax,%es
	mov	$256,%cx
	sub	%si,%si
	sub	%di,%di
	rep
	movw
	jmpi	go,INITSEG
go:	mov	%cs,%ax
	mov	%ax,%ds
	mov	%ax,%es
/* 
 * put stack at 0x9ff00.
 */
	mov	%ax,%ss
	mov	$0xFF00,%sp		# arbitrary value >>512

/* 
 * load the setup-sectors directly after the bootblock.
 * Note that 'es' is already set up.
 */

load_setup:
	mov	$0x0000,%dx		# drive 0, head 0
	mov	$0x0002,%cx		# sector 2, track 0
	mov	$0x0200,%bx		# address = 512, in INITSEG
	mov	$0x0200,%ax+SETUPLEN	# service 2, nr of sectors
	int	0x13			# read it
	jnc	ok_load_setup		# ok - continue
	mov	$0x0000,%dx
	mov	$0x0000,%ax		# reset the diskette
	int	0x13
	j	load_setup

ok_load_setup:

/* 
 * Get disk drive parameters, specifically nr of sectors/track
 */

	mov	$0x00,%dl
	mov	$0x0800,%ax		# AH=8 is get drive parameters
	int	0x13
	mov	$0x00,%ch
	seg %cs
	mov	%cx,sectors
	mov	$INITSEG,%ax
	mov	%ax,%es

/* 
 * Print some inane message
 */

	mov	$0x03,%ah		# read cursor pos
	xor	%bh,%bh
	int	0x10
	
	mov	$24,%cx
	mov	$0x0007,%bx		# page 0, attribute 7 (normal)
	mov	$msg1,%bp
	mov	$0x1301,%ax		# write string, move cursor
	int	0x10

/* 
 * ok, we've written the message, now
 * we want to load the system (at 0x10000)
 */

	mov	$SYSSEG,%ax
	mov	%ax,%es		# segment of 0x010000
	call	read_it
	call	kill_motor

/* 
 * After that we check which root-device to use. If the device is
 * defined (!= 0), nothing is done and the given device is used.
 * Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
 * on the number of sectors that the BIOS reports currently.
 */

	seg %cs
	mov	root,%ax_dev
	cmp	%ax,$0
	jne	root_defined
	seg %cs
	mov	sectors,%bx
	mov	$0x0208,%ax		# /dev/ps0 - 1.2Mb
	cmp	%bx,$15
	je	root_defined
	mov	$0x021c,%ax		# /dev/PS0 - 1.44Mb
	cmp	%bx,$18
	je	root_defined
undef_root:
	jmp undef_root
root_defined:
	seg %cs
	mov	root_%ax,dev

/* 
 * after that (everyting loaded), we jump to
 * the setup-routine loaded directly after
 * the bootblock:
 */

	jmpi	0,SETUPSEG

/* 
 * This routine loads the system at address 0x10000, making sure
 * no 64kB boundaries are crossed. We try to load it as fast as
 * possible, loading whole tracks whenever we can.
 *
 * in:	es - starting address segment (normally 0x1000)
 *
 */
sread:	.word 1+SETUPLEN	# sectors read of current track
head:	.word 0			# current head
track:	.word 0			# current track

read_it:
	mov %es,%ax
	test %ax,$0x0fff
die:	jne die			# %es must be at 64kB boundary
	xor %bx,%bx		# %bx is starting address within segment
rp_read:
	mov %es,%ax
	cmp %ax,$ENDSEG		# have we loaded all yet?
	jb ok1_read
	ret
ok1_read:
	seg %cs
	mov sectors,%ax
	sub sread,%ax
	mov %ax,%cx
	shl $9,%cx
	add %bx,%cx
	jnc ok2_read
	je ok2_read
	xor %ax,%ax
	sub %bx,%ax
	shr $9,%ax
ok2_read:
	call read_track
	mov %ax,%cx
	add sread,%ax
	seg %cs
	cmp %ax,sectors
	jne ok3_read
	mov $1,%ax
	sub head,%ax
	jne ok4_read
	inc track
ok4_read:
	mov %ax,head
	xor %ax,%ax
ok3_read:
	mov %ax,sread
	shl $9,%cx
	add %cx,%bx
	jnc rp_read
	mov %es,%ax
	add $0x1000,%ax
	mov %ax,%es
	xor %bx,%bx
	jmp rp_read

read_track:
	push %ax
	push %bx
	push %cx
	push %dx
	mov track,%dx
	mov sread,%cx
	inc %cx
	mov %dl,%ch
	mov head,%dx
	mov %dl,%dh
	mov $0,%dl
	and $0x0100,%dx
	mov $2,%ah
	int 0x13
	jc bad_rt
	pop %dx
	pop %cx
	pop %bx
	pop %ax
	ret
bad_rt:	mov %ax,$0
	mov $0,%dx
	int 0x13
	pop %dx
	pop %cx
	pop %bx
	pop %ax
	jmp read_track

/*
 * This procedure turns off the floppy drive motor, so
 * that we enter the kernel in a known state, and
 * don't have to worry about it later.
 */
kill_motor:
	push %dx
	mov $0x3f2,%dx
	mov $0,%al
	outb
	pop %dx
	ret

sectors:
	.word 0

msg1:
	.byte 13,10
	.ascii "Loading system ..."
	.byte 13,10,13,10

.org 508
root_dev:
	.word ROOT_DEV
boot_flag:
	.word 0xAA55

.text
endtext:
.data
enddata:
.bss
endbss:

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.