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

📄 setup.s

📁 linux-2.6.15.6
💻 S
📖 第 1 页 / 共 2 页
字号:
/* *	setup.S		Copyright (C) 1991, 1992 Linus Torvalds * * setup.s is responsible for getting the system data from the BIOS, * and putting them into the appropriate places in system memory. * both setup.s and system has been loaded by the bootblock. * * This code asks the bios for memory/disk/other parameters, and * puts them in a "safe" place: 0x90000-0x901FF, ie where the * boot-block used to be. It is then up to the protected mode * system to read them from there before the area is overwritten * for buffer-blocks. * * Move PS/2 aux init code to psaux.c * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 * * some changes and additional features by Christoph Niemann, * March 1993/June 1994 (Christoph.Niemann@linux.org) * * add APM BIOS checking by Stephen Rothwell, May 1994 * (sfr@canb.auug.org.au) * * High load stuff, initrd support and position independency * by Hans Lermen & Werner Almesberger, February 1996 * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch> * * Video handling moved to video.S by Martin Mares, March 1996 * <mj@k332.feld.cvut.cz> * * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david * parsons) to avoid loadlin confusion, July 1997 * * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. * <stiker@northlink.com> * * Fix to work around buggy BIOSes which don't use carry bit correctly * and/or report extended memory in CX/DX for e801h memory size detection  * call.  As a result the kernel got wrong figures.  The int15/e801h docs * from Ralf Brown interrupt list seem to indicate AX/BX should be used * anyway.  So to avoid breaking many machines (presumably there was a reason * to orginally use CX/DX instead of AX/BX), we do a kludge to see * if CX/DX have been changed in the e801 call and if so use AX/BX . * Michael Miller, April 2001 <michaelm@mjmm.org> * * Added long mode checking and SSE force. March 2003, Andi Kleen.		 */#include <linux/config.h>#include <asm/segment.h>#include <linux/version.h>#include <linux/compile.h>#include <asm/boot.h>#include <asm/e820.h>#include <asm/page.h>/* Signature words to ensure LILO loaded us right */#define SIG1	0xAA55#define SIG2	0x5A5AINITSEG  = DEF_INITSEG		# 0x9000, we move boot here, out of the waySYSSEG   = DEF_SYSSEG		# 0x1000, system loaded at 0x10000 (65536).SETUPSEG = DEF_SETUPSEG		# 0x9020, this is the current segment				# ... and the former contents of CSDELTA_INITSEG = SETUPSEG - INITSEG	# 0x0020.code16.globl begtext, begdata, begbss, endtext, enddata, endbss.textbegtext:.databegdata:.bssbegbss:.textstart:	jmp	trampoline# This is the setup header, and it must start at %cs:2 (old 0x9020:2)		.ascii	"HdrS"		# header signature		.word	0x0204		# header version number (>= 0x0105)					# or else old loadlin-1.5 will fail)realmode_swtch:	.word	0, 0		# default_switch, SETUPSEGstart_sys_seg:	.word	SYSSEG		.word	kernel_version	# pointing to kernel version string					# above section of header is compatible					# with loadlin-1.5 (header v1.5). Don't					# change it.type_of_loader:	.byte	0		# = 0, old one (LILO, Loadlin,					#      Bootlin, SYSLX, bootsect...)					# See Documentation/i386/boot.txt for					# assigned ids	# flags, unused bits must be zero (RFU) bit within loadflagsloadflags:LOADED_HIGH	= 1			# If set, the kernel is loaded highCAN_USE_HEAP	= 0x80			# If set, the loader also has set					# heap_end_ptr to tell how much					# space behind setup.S can be used for					# heap purposes.					# Only the loader knows what is free#ifndef __BIG_KERNEL__		.byte	0#else		.byte	LOADED_HIGH#endifsetup_move_size: .word  0x8000		# size to move, when setup is not					# loaded at 0x90000. We will move setup 					# to 0x90000 then just before jumping					# into the kernel. However, only the					# loader knows how much data behind					# us also needs to be loaded.code32_start:				# here loaders can put a different					# start address for 32-bit code.#ifndef __BIG_KERNEL__		.long	0x1000		#   0x1000 = default for zImage#else		.long	0x100000	# 0x100000 = default for big kernel#endiframdisk_image:	.long	0		# address of loaded ramdisk image					# Here the loader puts the 32-bit					# address where it loaded the image.					# This only will be read by the kernel.ramdisk_size:	.long	0		# its size in bytesbootsect_kludge:		.long	0		# obsoleteheap_end_ptr:	.word	modelist+1024	# (Header version 0x0201 or later)					# space from here (exclusive) down to					# end of setup code can be used by setup					# for local heap purposes.pad1:		.word	0cmd_line_ptr:	.long 0			# (Header version 0x0202 or later)					# If nonzero, a 32-bit pointer					# to the kernel command line.					# The command line should be					# located between the start of					# setup and the end of low					# memory (0xa0000), or it may					# get overwritten before it					# gets read.  If this field is					# used, there is no longer					# anything magical about the					# 0x90000 segment; the setup					# can be located anywhere in					# low memory 0x10000 or higher.ramdisk_max:	.long 0xffffffff	trampoline:	call	start_of_setup		.align 16					# The offset at this point is 0x240		.space  (0xeff-0x240+1)	# E820 & EDD space (ending at 0xeff)# End of setup header #####################################################start_of_setup:# Bootlin depends on this being done early	movw	$0x01500, %ax	movb	$0x81, %dl	int	$0x13#ifdef SAFE_RESET_DISK_CONTROLLER# Reset the disk controller.	movw	$0x0000, %ax	movb	$0x80, %dl	int	$0x13#endif# Set %ds = %cs, we know that SETUPSEG = %cs at this point	movw	%cs, %ax		# aka SETUPSEG	movw	%ax, %ds# Check signature at end of setup	cmpw	$SIG1, setup_sig1	jne	bad_sig	cmpw	$SIG2, setup_sig2	jne	bad_sig	jmp	good_sig1# Routine to print asciiz string at ds:siprtstr:	lodsb	andb	%al, %al	jz	fin	call	prtchr	jmp	prtstrfin:	ret# Space printingprtsp2:	call	prtspc		# Print double spaceprtspc:	movb	$0x20, %al	# Print single space (note: fall-thru)prtchr:		pushw	%ax	pushw	%cx	movw	$0007,%bx	movw	$0x01, %cx	movb	$0x0e, %ah	int	$0x10	popw	%cx	popw	%ax	retbeep:	movb	$0x07, %al	jmp	prtchr	no_sig_mess: .string	"No setup signature found ..."good_sig1:	jmp	good_sig# We now have to find the rest of the setup code/databad_sig:	movw	%cs, %ax			# SETUPSEG	subw	$DELTA_INITSEG, %ax		# INITSEG	movw	%ax, %ds	xorb	%bh, %bh	movb	(497), %bl			# get setup sect from bootsect	subw	$4, %bx				# LILO loads 4 sectors of setup	shlw	$8, %bx				# convert to words (1sect=2^8 words)	movw	%bx, %cx	shrw	$3, %bx				# convert to segment	addw	$SYSSEG, %bx	movw	%bx, %cs:start_sys_seg# Move rest of setup code/data to here	movw	$2048, %di			# four sectors loaded by LILO	subw	%si, %si	movw	%cs, %ax			# aka SETUPSEG	movw	%ax, %es	movw	$SYSSEG, %ax	movw	%ax, %ds	rep	movsw	movw	%cs, %ax			# aka SETUPSEG	movw	%ax, %ds	cmpw	$SIG1, setup_sig1	jne	no_sig	cmpw	$SIG2, setup_sig2	jne	no_sig	jmp	good_signo_sig:	lea	no_sig_mess, %si	call	prtstrno_sig_loop:	jmp	no_sig_loopgood_sig:	movw	%cs, %ax			# aka SETUPSEG	subw	$DELTA_INITSEG, %ax 		# aka INITSEG	movw	%ax, %ds# Check if an old loader tries to load a big-kernel	testb	$LOADED_HIGH, %cs:loadflags	# Do we have a big kernel?	jz	loader_ok			# No, no danger for old loaders.	cmpb	$0, %cs:type_of_loader 		# Do we have a loader that						# can deal with us?	jnz	loader_ok			# Yes, continue.	pushw	%cs				# No, we have an old loader,	popw	%ds				# die. 	lea	loader_panic_mess, %si	call	prtstr	jmp	no_sig_looploader_panic_mess: .string "Wrong loader, giving up..."loader_ok:	/* check for long mode. */	/* we have to do this before the VESA setup, otherwise the user	   can't see the error message. */		pushw	%ds	movw	%cs,%ax	movw	%ax,%ds		/* minimum CPUID flags for x86-64 */	/* see http://www.x86-64.org/lists/discuss/msg02971.html */		#define SSE_MASK ((1<<25)|(1<<26))#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|\					   (1<<13)|(1<<15)|(1<<24))#define REQUIRED_MASK2 (1<<29)	pushfl				/* standard way to check for cpuid */	popl	%eax	movl	%eax,%ebx	xorl	$0x200000,%eax	pushl	%eax	popfl	pushfl	popl	%eax	cmpl	%eax,%ebx	jz	no_longmode		/* cpu has no cpuid */	movl	$0x0,%eax	cpuid	cmpl	$0x1,%eax	jb	no_longmode		/* no cpuid 1 */	xor	%di,%di	cmpl	$0x68747541,%ebx	/* AuthenticAMD */	jnz	noamd	cmpl	$0x69746e65,%edx	jnz	noamd	cmpl	$0x444d4163,%ecx	jnz	noamd	mov	$1,%di			/* cpu is from AMD */noamd:			movl    $0x1,%eax	cpuid	andl	$REQUIRED_MASK1,%edx	xorl	$REQUIRED_MASK1,%edx	jnz	no_longmode	movl    $0x80000000,%eax	cpuid	cmpl    $0x80000001,%eax	jb      no_longmode             /* no extended cpuid */	movl    $0x80000001,%eax	cpuid	andl    $REQUIRED_MASK2,%edx	xorl    $REQUIRED_MASK2,%edx	jnz     no_longmodesse_test:			movl	$1,%eax	cpuid	andl	$SSE_MASK,%edx	cmpl	$SSE_MASK,%edx	je	sse_ok	test	%di,%di	jz	no_longmode	/* only try to force SSE on AMD */ 	movl	$0xc0010015,%ecx	/* HWCR */	rdmsr	btr	$15,%eax	/* enable SSE */	wrmsr	xor	%di,%di		/* don't loop */	jmp	sse_test	/* try again */	no_longmode:	call	beep	lea	long_mode_panic,%si	call	prtstrno_longmode_loop:			jmp	no_longmode_looplong_mode_panic:	.string "Your CPU does not support long mode. Use a 32bit distribution."	.byte 0	sse_ok:	popw	%ds	# tell BIOS we want to go to long mode	movl  $0xec00,%eax	# declare target operating mode	movl  $2,%ebx		# long mode	int $0x15				# Get memory size (extended mem, kB)	xorl	%eax, %eax	movl	%eax, (0x1e0)#ifndef STANDARD_MEMORY_BIOS_CALL	movb	%al, (E820NR)# Try three different memory detection schemes.  First, try# e820h, which lets us assemble a memory map, then try e801h,# which returns a 32-bit memory size, and finally 88h, which# returns 0-64m# method E820H:# the memory map from hell.  e820h returns memory classified into# a whole bunch of different types, and allows memory holes and# everything.  We scan through this memory map and build a list# of the first 32 memory areas, which we return at [E820MAP].# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.#define SMAP  0x534d4150meme820:	xorl	%ebx, %ebx			# continuation counter	movw	$E820MAP, %di			# point into the whitelist						# so we can have the bios						# directly write into it.jmpe820:	movl	$0x0000e820, %eax		# e820, upper word zeroed	movl	$SMAP, %edx			# ascii 'SMAP'	movl	$20, %ecx			# size of the e820rec	pushw	%ds				# data record.	popw	%es	int	$0x15				# make the call	jc	bail820				# fall to e801 if it fails	cmpl	$SMAP, %eax			# check the return is `SMAP'	jne	bail820				# fall to e801 if it fails#	cmpl	$1, 16(%di)			# is this usable memory?#	jne	again820	# If this is usable memory, we save it by simply advancing %di by	# sizeof(e820rec).	#good820:	movb	(E820NR), %al			# up to 128 entries	cmpb	$E820MAX, %al	jae	bail820	incb	(E820NR)	movw	%di, %ax	addw	$20, %ax	movw	%ax, %diagain820:	cmpl	$0, %ebx			# check to see if	jne	jmpe820				# %ebx is set to EOFbail820:# method E801H:# memory size is in 1k chunksizes, to avoid confusing loadlin.# we store the 0xe801 memory size in a completely different place,# because it will most likely be longer than 16 bits.# (use 1e0 because that's what Larry Augustine uses in his# alternative new memory detection scheme, and it's sensible

⌨️ 快捷键说明

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