⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bootsect.s

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 S
字号:
/* *	bootsect.S		Copyright (C) 1991, 1992 Linus Torvalds * *	modified by Drew Eckhardt *	modified by Bruce Evans (bde) *	modified by Chris Noe (May 1999) (as86 -> gas) * * bootsect is loaded at 0x7c00 by the bios-startup routines, and moves * itself out of the way to address 0x90000, and jumps there. * * bde - should not jump blindly, there may be systems with only 512K low * memory.  Use int 0x12 to get the top of memory, etc. * * It then loads 'setup' directly after itself (0x90200), and the system * at 0x10000, using BIOS interrupts.  * * NOTE! currently system is at most (8*65536-4096) bytes long. This should  * be no problem, even in the future. I want to keep it simple. This 508 kB * kernel size should be enough, especially as this doesn't contain the * buffer cache as in minix (and especially now that the kernel is  * compressed :-) * * The loader has been made as simple as possible, and continuous * read errors will result in a unbreakable loop. Reboot by hand. It * loads pretty fast by getting whole tracks at a time whenever possible. */#include <linux/config.h>		/* for CONFIG_ROOT_RDONLY */#include <asm/boot.h>SETUPSECS	= 4			/* default nr of setup-sectors */BOOTSEG		= 0x07C0		/* original address of boot-sector */INITSEG		= DEF_INITSEG		/* we move boot here - out of the way */SETUPSEG	= DEF_SETUPSEG		/* setup starts here */SYSSEG		= DEF_SYSSEG		/* system loaded at 0x10000 (65536) */SYSSIZE		= DEF_SYSSIZE		/* system size: # of 16-byte clicks */					/* to be loaded */ROOT_DEV	= 0 			/* ROOT_DEV is now written by "build" */SWAP_DEV	= 0			/* SWAP_DEV is now written by "build" */#ifndef SVGA_MODE#define SVGA_MODE ASK_VGA#endif#ifndef RAMDISK#define RAMDISK 0#endif #ifndef CONFIG_ROOT_RDONLY#define CONFIG_ROOT_RDONLY 1#endif.code16.text.global _start_start:#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */	int	$0x3#endif	movw	$BOOTSEG, %ax	movw	%ax, %ds	movw	$INITSEG, %ax	movw	%ax, %es	movw	$256, %cx	subw	%si, %si	subw	%di, %di	cld	rep	movsw	ljmp	$INITSEG, $go# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde).  We# wouldn't have to worry about this if we checked the top of memory.  Also# my BIOS can be configured to put the wini drive tables in high memory# instead of in the vector table.  The old stack might have clobbered the# drive table.go:	movw	$0x4000-12, %di		# 0x4000 is an arbitrary value >=					# length of bootsect + length of					# setup + room for stack;					# 12 is disk parm size.	movw	%ax, %ds		# ax and es already contain INITSEG	movw	%ax, %ss	movw	%di, %sp		# put stack at INITSEG:0x4000-12.# Many BIOS's default disk parameter tables will not recognize# multi-sector reads beyond the maximum sector number specified# in the default diskette parameter tables - this may mean 7# sectors in some cases.## Since single sector reads are slow and out of the question,# we must take care of this by creating new parameter tables# (for the first disk) in RAM.  We will set the maximum sector# count to 36 - the most we will encounter on an ED 2.88.  ## High doesn't hurt.  Low does.## Segments are as follows: ds = es = ss = cs - INITSEG, fs = 0,# and gs is unused.	movw	%cx, %fs		# set fs to 0	movw	$0x78, %bx		# fs:bx is parameter table address	pushw	%ds	ldsw	%fs:(%bx), %si		# ds:si is source	movb	$6, %cl			# copy 12 bytes	pushw	%di			# di = 0x4000-12.	rep				# don't need cld -> done on line 66	movsw	popw	%di	popw	%ds	movb	$36, 0x4(%di)		# patch sector count	movw	%di, %fs:(%bx)	movw	%es, %fs:2(%bx)# Load the setup-sectors directly after the bootblock.# Note that 'es' is already set up.# Also, cx = 0 from rep movsw above.load_setup:	xorb	%ah, %ah		# reset FDC 	xorb	%dl, %dl	int 	$0x13		xorw	%dx, %dx		# drive 0, head 0	movb	$0x02, %cl		# sector 2, track 0	movw	$0x0200, %bx		# address = 512, in INITSEG	movb	$0x02, %ah		# service 2, "read sector(s)"	movb	setup_sects, %al	# (assume all on head 0, track 0)	int	$0x13			# read it	jnc	ok_load_setup		# ok - continue	pushw	%ax			# dump error code	call	print_nl	movw	%sp, %bp	call	print_hex	popw	%ax		jmp	load_setupok_load_setup:# Get disk drive parameters, specifically number of sectors/track.# It seems that there is no BIOS call to get the number of sectors.# Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18# can be read, 15 if sector 15 can be read.  Otherwise guess 9.	movw	$disksizes, %si		# table of sizes to tryprobe_loop:	lodsb	cbtw				# extend to word	movw	%ax, sectors	cmpw	$disksizes+4, %si	jae	got_sectors		# If all else fails, try 9		xchgw	%cx, %ax		# cx = track and sector	xorw	%dx, %dx		# drive 0, head 0	xorb	%bl, %bl	movb	setup_sects, %bh	incb	%bh	shlb	%bh			# address after setup (es = cs) 	movw	$0x0201, %ax		# service 2, 1 sector	int	$0x13	jc	probe_loop		# try next valuegot_sectors:	movw	$INITSEG, %ax	movw	%ax, %es		# set up es	movb	$0x03, %ah		# read cursor pos	xorb	%bh, %bh	int	$0x10	movw	$9, %cx	movw	$0x0007, %bx		# page 0, attribute 7 (normal)	movw    $msg1, %bp	movw    $0x1301, %ax		# write string, move cursor	int	$0x10			# tell the user we're loading..	movw	$SYSSEG, %ax		# ok, we've written the message, now	movw	%ax, %es		# we want to load system (at 0x10000)	call	read_it	call	kill_motor	call	print_nl# 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, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8)# depending on the number of sectors we pretend to know we have.	movw	root_dev, %ax	orw	%ax, %ax	jne	root_defined		movw	sectors, %bx	movw	$0x0208, %ax		# /dev/ps0 - 1.2Mb	cmpw	$15, %bx	je	root_defined		movb	$0x1c, %al		# /dev/PS0 - 1.44Mb	cmpw	$18, %bx	je	root_defined		movb	$0x20, %al		# /dev/fd0H2880 - 2.88Mb	cmpw	$36, %bx	je	root_defined		movb	$0, %al			# /dev/fd0 - autodetectroot_defined:	movw	%ax, root_dev# After that (everything loaded), we jump to the setup-routine# loaded directly after the bootblock:	ljmp	$SETUPSEG, $0# 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.# es = starting address segment (normally 0x1000)sread:	.word 0				# sectors read of current trackhead:	.word 0				# current headtrack:	.word 0				# current trackread_it:	movb	setup_sects, %al	incb	%al	movb	%al, sread	movw	%es, %ax	testw	$0x0fff, %axdie:	jne	die			# es must be at 64kB boundary	xorw	%bx, %bx		# bx is starting address within segmentrp_read:#ifdef __BIG_KERNEL__	bootsect_kludge = 0x220		# 0x200 (size of bootsector) + 0x20 (offset	lcall	bootsect_kludge		# of bootsect_kludge in setup.S)#else	movw	%es, %ax	subw	$SYSSEG, %ax#endif	cmpw	syssize, %ax		# have we loaded all yet?	jbe	ok1_read	retok1_read:	movw	sectors, %ax	subw	sread, %ax	movw	%ax, %cx	shlw	$9, %cx	addw	%bx, %cx	jnc	ok2_read		je	ok2_read	xorw	%ax, %ax	subw	%bx, %ax	shrw	$9, %axok2_read:	call	read_track	movw	%ax, %cx	addw	sread, %ax	cmpw	sectors, %ax	jne	ok3_read		movw	$1, %ax	subw	head, %ax	jne	ok4_read		incw	trackok4_read:	movw	%ax, head	xorw	%ax, %axok3_read:	movw	%ax, sread	shlw	$9, %cx	addw	%cx, %bx	jnc	rp_read		movw	%es, %ax	addb	$0x10, %ah	movw	%ax, %es	xorw	%bx, %bx	jmp	rp_readread_track:	pusha	pusha		movw	$0xe2e, %ax 			# loading... message 2e = .	movw	$7, %bx 	int	$0x10	popa			movw	track, %dx	movw	sread, %cx	incw	%cx	movb	%dl, %ch	movw	head, %dx	movb	%dl, %dh	andw	$0x0100, %dx	movb	$2, %ah	pushw	%dx				# save for error dump	pushw	%cx	pushw	%bx	pushw	%ax	int	$0x13	jc	bad_rt		addw	$8, %sp	popa	retbad_rt:	pushw	%ax				# save error code	call	print_all			# ah = error, al = read	xorb	%ah, %ah	xorb	%dl, %dl	int	$0x13	addw	$10, %sp	popa	jmp read_track# print_all is for debugging purposes.  ## it will print out all of the registers.  The assumption is that this is# called from a routine, with a stack frame like##	%dx #	%cx#	%bx#	%ax#	(error)#	ret <- %sp print_all:	movw	$5, %cx				# error code + 4 registers	movw	%sp, %bpprint_loop:	pushw	%cx				# save count left	call	print_nl			# nl for readability	cmpb	$5, %cl	jae	no_reg				# see if register name is needed		movw	$0xe05 + 'A' - 1, %ax	subb	%cl, %al	int	$0x10	movb	$'X', %al	int	$0x10	movb	$':', %al	int	$0x10no_reg:	addw	$2, %bp				# next register	call	print_hex			# print it	popw	%cx	loop	print_loop	retprint_nl:	movw	$0xe0d, %ax			# CR	int	$0x10	movb	$0xa, %al			# LF	int 	$0x10	ret# print_hex is for debugging purposes, and prints the word# pointed to by ss:bp in hexadecimal.print_hex:	movw	$4, %cx				# 4 hex digits	movw	(%bp), %dx			# load word into dxprint_digit:	rolw	$4, %dx				# rotate to use low 4 bits	movw	$0xe0f, %ax			# ah = request	andb	%dl, %al			# al = mask for nybble	addb	$0x90, %al			# convert al to ascii hex	daa					# in only four instructions!	adc	$0x40, %al	daa	int	$0x10	loop	print_digit	ret# 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:	movw	$0x3f2, %dx	xorb	%al, %al	outb	%al, %dx	retsectors:	.word 0disksizes:	.byte 36, 18, 15, 9msg1:		.byte 13, 10		.ascii "Loading"# XXX: This is a *very* snug fit..org 497setup_sects:	.byte SETUPSECSroot_flags:	.word CONFIG_ROOT_RDONLYsyssize:	.word SYSSIZEswap_dev:	.word SWAP_DEVram_size:	.word RAMDISKvid_mode:	.word SVGA_MODEroot_dev:	.word ROOT_DEVboot_flag:	.word 0xAA55

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -