ウォンツテック

そでやまのーと

OS

FDの読み込みを汎用的にして64KB以上に対応。
addw $0x1000, %ax
とやらなければならない所を
addw 0x1000, %ax
とやってて気づくのに2時間くらい掛かったorz..

/*
 *  @File	 bootacient.S
 *  @Brief	 The initial boot section of Sodex
 *  
 *  @Author	 Sodex
 *  @Revision	 0.1
 *  @License	 suspension
 *  @Date	 create: 2007/04/05  update: 2007/04/26
 *		
 *  Copyright (C) 2007 Sodex
 */

BOOTSEG			= 0x07C0
INITSEG			= 0x9000
KERNEL_SEG		= 0x0100		
KERNEL_STACK_SEG        = 0x8000

# We won't have to increase the BOOT_SECTS to more 18
ACIENT_SECTS	= 1
MIDDLE_SECTS	= 7
KERNEL_SECTS	= 280
BOOT_SECTS	= ACIENT_SECTS + MIDDLE_SECTS
KERNEL_FIRST	= SECTORS - BOOT_SECTS		

# This is the default size of general FD formatted at 1.44MB.		
SECTORS		= 18		

.code16
.text
	
.global _start, printstr
_start:	
	
		jmpl	$BOOTSEG, $start2
		
start2:
		xorw	%si, %si
		xorw	%di, %di
		movw	$BOOTSEG, %ax
		movw	%ax, %ds
		movw	$INITSEG, %ax
		movw	%ax, %es
		movw	$0x100, %cx
		cld
		rep	movsw
		jmpl	$INITSEG, $next

next:
		movw	%ax, %ds
		movw	$KERNEL_STACK_SEG, %ax
		movw	%ax, %ss
		xorw	%sp, %sp

		
# Clear the display and the message is printed
# before we load the boot_middle and kernel
		
		movb	$0x3, %al		# Clear the display
		movb	$0, %ah
		int	$0x10
		movw	$loader_mes, %si
		call	printstr

# Reset FD		
		call	reset_fd
		jmp	read_middleboot

/* Read next boot section from floppy drive.
 * The data is read from fd and It is set at ES:BX of the memory point.
 * The reserved memory at first is the parameter of FD.
 *  "secotr:" is sectors of current track ( 1 <= sector <= 18 )
 *  "head:" is current head ( 0 <= head <= 1 )
 *  "track:" is current track ( 0 <= track <= 79 )		
 */
		sector: .byte 1
		track:	.byte 0
		head:	.byte 0
		nread:	.byte 0
		over64k:.byte 0
		ecount:	.byte 5

read_middleboot:						
		movw	$0x200, %bx		# "es" is already set at 0x9000
		movb	$2, (sector)

		movb	$0x2, %ah	# AH is BIOS COMMAND, The no.2 indicates
					# reading disk sectors

		movb	$MIDDLE_SECTS, %al	# AL is Num of sectors to read
		movb	(sector), %cl		# CL is the sector
		movb	(track), %ch		# CH is the track
		movb	(head), %dh			# DH is the head
		movb	$0, %dl				# DL is the drive(always 0)
		int	$0x13

		jnc	_read0
		call	read_error
		jmp	halt

_read0:
		addb	%al, (sector)
		
/* Read the kernel section from FD.
 * The data is read from fd and It is set at ES:BX.
 */
read0:			
		xorw	%bx, %bx
		movw	$KERNEL_SEG, %ax
		movw	%ax, %es			# ES:BX = 0x0100:0x0000(0x1000)
		movw	$KERNEL_SECTS, %di	# set the num of kernel sects to di

		call	read_kernel

		call	reset_fd		
		jmp	middle_start		


/* Read FD's kernel data
 * Before using this function, we must set the following parameter
 *  ES:BX  -  sent address
 *  DI     -  Num of read sectors
 *  sector, track, head, nread -  FD parameters				
 */		
read_kernel:
/* decide nread */		
		movb	(sector), %al		# get sector num
		subb	$1, %al
		movb	$18, %dl
		subb	%al, %dl		    # dl = 18 - al (= 18 - (sector-1))
		xorb	%dh, %dh
		cmpw	%dx, %di		    # if ( di >= dx )		
		jae	read_itr1
		movw	%di, %dx
		
read_itr1:
		movw	%es, %cx
		shl	$4, %cx				# es = es<<4
		movw	%bx, %ax
		addw	%ax, %cx		    # es = es + bx
		movw	%cx, %si
		movw	%dx, %ax
		shl	$9, %ax				# ax = bx * 0x200
		addw	%ax, %cx		    # es = es + bx + (nread)*0x200
		pushf
		call	print_all_registers
		popf
		jc	read_itr1_over64k
		movw	%dx, (nread)		
		jmp	read_itr2		
		
read_itr1_over64k:
		movw	$1, (over64k)
		movw	$0xffff, %ax
		subw	%si, %ax		    # si = es + bx
		addw	$1, %ax				# ax = 0x10000 - (es + bx)
		shr	$9, %ax				# ax = ax/0x200
		movb	%al, (nread)
		call	print_all_registers
		movw	$fd_over64k_error_mes, %si
		call	printstr

/* end deciding nread */		

/* just read from fd */				
read_itr2:
		movb	(nread), %al
		movb	(sector), %cl
		movb	(track), %ch
		movb	(head), %dh
		movb	$0x02, %ah
		movb	$0, %dl
		call	print_all_registers
		int	$0x13
		jnc	read_itr3
		
		# error occur
		call	print_all_registers
		decb	(ecount)
		jz	halt
		call	read_error
		pusha
		call	reset_fd
		popa
		jmp	read_itr2
/* end reading from fd */
		
/* post-processing */				
read_itr3:
		movb	%al, (nread)
		movb	(over64k), %cl				
		cmp	$1, %cl
		jz	read_itr3_over64k
		addb	%al, %bh
		addb	%al, %bh			# bx += al * 512
		jmp	read_itr4
		
read_itr3_over64k:						
		movw	%es, %ax
		andw	$0xf000, %ax
		addw	$0x1000, %ax
		
		movw	%ax, %es		    # es = es&0xf000+0x1000
		xorw	%bx, %bx
		movb	$0, (over64k)

read_itr4:			
		movb	(nread), %al
		movb	(sector), %cl
		addb	%cl, %al
		cmp	$SECTORS, %al
		ja	read_itr4_over1track
		movb	%al, (sector)
		jmp	read_itr5

read_itr4_over1track:
		movb	$1, (sector)
		movb	(head), %al
		cmp	$0, %al
		jz	read_itr4_over1track_head0
		movb	$0, (head)			# head == 1
		addb	$1, (track)
		jmp	read_itr5
		
read_itr4_over1track_head0:		
		movb	$1, (head)

read_itr5:				
		movb	(nread), %al
		xorb	%ah, %ah
		subw	%ax, %di
/* end of post-processing */		
		
		cmpw	$0, %di
		ja	read_kernel			
		ret		



/* Reset floppy drive
 * Set AH = 0, which indicate to reset drive
 * Set AL = 0, which indicate first floppy drive.
 * INT 0x13: BIOS Disk services
 */
reset_fd:
		xorw	%ax, %ax		
		xorb	%dl, %dl		# dl is num of drive
		int	$0x13
		jnc	fd_reset_ok
		movw	$fd_reset_error_mes, %si
		call	printstr
		jmp	reset_fd
fd_reset_ok:					
		ret		

read_error:		
		movw	$fd_read_error_mes, %si
		call	printstr
		ret
		
printstr:
		pusha
printstr_start:
                lodsb
		cmpb	$0, %al
		jz	printstr_end
		movb	$0x0e, %ah
		movb	$0, %bh
		int	$0x10
		jmp	printstr_start
printstr_end:
		popa
		ret

halt:			
#		hlt
		jmp	halt

loader_mes:	
		.ascii	"Loading...\r\n\0"
fd_reset_error_mes:		
		.ascii	"The floppy drive failed reset..\r\n\0"
fd_read_error_mes:		
		.ascii	"read error from FD..\r\n\0"
fd_over64k_error_mes:		
		.ascii	"over 64k..\r\n\0"		

		.org 510
	        .word 0xAA55